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,
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.
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)
}
// ...