Skip to main content

Manage Positions

Reading Dual Investment Position

After a user makes a dual investment, their position is stored as a structure called Note on the blockchain.

We can retrieve their Note count from the previous section; the data is included in the result of getDysonPairInfos. It's important to mention that claimed positions will not disappear, but the data within the Note structure will be cleared,

warning

To manage this purely on-chain, we utilize an inefficient method in the SDK function by filtering all notes with data. However, we recommend using a backend server or subgraph to track active notes.

Example:

import { IDysonPairNotes } from '@dyson-finance/dyson-interface-sdk/entities'
import { getAccountNotes } from '@dyson-finance/dyson-interface-sdk/reads'

// ...
const client = await getWalletClient({ chainId })
const countPairTupleList = dysonPairInfoList.map((dysonPair) => {
const { noteCount, pairAddress } = dysonPair
return [noteCount, pairAddress]
})

const dysonPairNotes: = await getAccountNotes(client, {
account: (account as Address) || zeroAddress,
noteCounts: countPairTupleList.map((tuple) => tuple[0] as number),
pairAddresses: countPairTupleList.map((tuple) => tuple[1] as Address),
})
// ...

Claiming a Position

We provide a code example for claiming a dual investment position.
Please note that when a user attempts to claim a note related to a wrapped native token, it is necessary to sign a message to enable the router to assist in converting the wrapped native token to a native token.

If the user is only claiming a note not related to a wrapped native token or does not want to convert wrapped tokens, they can directly call the Dyson pair address for the action.

We offer an example to manage both wrapped native token pairs and common pairs.

tip

For a deeper understanding, please consult the following document.

Claim Note example:

import {
prepareNoteWithdraw,
prepareSetApprovalForAll,
prepareSetApprovalForAllWithSig,
} from '@dyson-finance/dyson-interface-sdk/actions'
import { ABIDysonSwapRouter } from '@dyson-finance/dyson-interface-sdk/constants/abis'
import {
getPairOperatorApprovals,
getPairsNonces,
} from '@dyson-finance/dyson-interface-sdk/reads'
import {
encodeFunctionData,
Hex,
publicActions,
} from 'viem'
import {
prepareWriteContract,
writeContract,
} from 'wagmi/actions'

// ...
const client = await getWalletClient({ chainId })
const completeClient = client.extend(publicActions) // make wallet client extend to public client

const publicClient =
const prepareResult = prepareNoteWithdraw(client, {
isNativePool,
noteIndex,
pairAddress,
addressTo,
})

if (isNativePool) {
// withdraw native token should check approval
const [isInOperator, nonces] = await completeClient.multicall({
contracts: [
{
...getPairOperatorApprovals(completeClient.account.address, routerAddress),
address: pairAddress,
},
{
...getPairsNonces(completeClient.account.address),
address: pairAddress,
},
],
})
const multicallData = [] as Hex[]
if (!isInOperator.result) {
if (!isContractWallet) {
const approvalWithSigConfig = await prepareSetApprovalForAllWithSig(
completeClient,
{
owner: completeClient.account.address,
approved: true,
deadline: BigInt(Math.floor(Date.now() / 1000) + 4 * TimeUnits.Day),
nonce: nonces.result ?? 0n,
pairAddress,
operator: routerAddress,
},
)

multicallData.push(encodeFunctionData({ ...approvalWithSigConfig }))
} else {
const approvalWithSigConfig = {
...(await prepareSetApprovalForAll(routerAddress, true)),
address: pairAddress,
} as const

multicallData.push(encodeFunctionData({ ...approvalWithSigConfig }))
}
}
multicallData.push(encodeFunctionData({ ...prepareResult }))

const { request } = await prepareWriteContract({
abi: ABIDysonSwapRouter,
functionName: 'multicall',
args: [multicallData],
address: routerAddress,
})
return await writeContract(request)
} else {
const { request } = await prepareWriteContract({
...prepareResult,
address: pairAddress,
})
return await writeContract(request)
}
// ...