Redemption#
Call this endpoint when a user wants to withdraw assets from a DeFi protocol (redeem) or repay a loan (repay). Key parameters: investmentId, address. Critical note: always pass redeemPercent when redeeming (e.g., "1" for 100%) — otherwise, for tokens with dynamic balances such as aTokens, the on-chain execution may revert due to balance changes between API response and transaction confirmation. For V3 Pool redemptions, tokenId is required.
URL: POST /api/v6/defi/transaction/exit
Request Parameters#
| Field | Type | Required | Default | Explanation |
|---|---|---|---|---|
| investmentId | String | Yes | — | Investment product ID |
| address | String | Yes | — | User wallet address |
| tokenId | String | No | — | V3 Pool NFT position token ID. Required for redemption when isV3Pool=true |
| redeemPercent | String | Recommended | — | Redemption ratio, e.g., "1"=100%, "0.5"=50%. When not provided, the Zap calldata's tokenIn amount uses the exact value from userInputList.coinAmount; when provided, MAX_UINT256 is used to represent the full balance |
| userInputList | Array | No | — | For Farm and V2 Pool, input LP Token information; for other cases, input the target receiving token information |
| > tokenAddress | String | No | — | Required when userInputList is provided; Token contract address |
| > chainIndex | String | No | — | Required when userInputList is provided; Chain ID |
| > coinAmount | String | No | — | Required when userInputList is provided; Amount (human-readable, e.g., "0.05") |
| > tokenSymbol | String | No | — | Token symbol |
| > tokenPrecision | Integer | No | — | Precision |
| > tokenId | String | No | — | NFT token ID (V3 Pool scenario) |
| slippage | String | No | "0.01" | Transaction slippage (effective for adapter/Zap routing). "0.01"=1%, "0.1"=10% |
Key Notes#
redeemPercent is required: When type="REDEEM", if
redeemPercentis not provided, the Zap calldata generated by the API will use an exact value fortokenIn.amount(e.g., 60009) instead of MAX_UINT256. For tokens like aToken whose interest grows dynamically, the balance may change between the API response and on-chain execution, causingSafeERC20: low-level call failed. WhenredeemPercent: "1"is provided, the amount is set to MAX_UINT256, and the contract dynamically retrieves the actual balance.
Request Examples#
Example 1: BSC V3 Pool pure redemption (50%, without userInputList)#
Investment product: PancakeSwapV3 USDT-RIVER (id=1589649169)
{
"investmentId": "1589649169",
"address": "0x1ae68a40b9f903a469aed01574f3a9ab6d45c563",
"tokenId": "6632738",
"redeemPercent": "0.5"
}
Example 2: Avalanche Aave V3 redemption (redeemPercent="1")#
Investment product: Aave V3 USDC (id=124, chainIndex=43114)
{
"investmentId": "124",
"address": "0x1ae68a40b9f903a469aed01574f3a9ab6d45c563",
"userInputList": [
{
"tokenAddress": "0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e",
"chainIndex": "43114",
"coinAmount": "0.05"
}
],
"redeemPercent": "1"
}
Example 3: Sui NAVI redemption#
Investment product: NAVI USDC (id=32202, chainIndex=784)
{
"investmentId": "32202",
"address": "0x2791c11545a2fef7d8b3188002c80343bf6dc64130a603914238d8660b3bddde",
"userInputList": [
{
"tokenAddress": "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
"chainIndex": "784",
"coinAmount": "0.3"
}
]
}
Example 4: Solana Kamino repayment#
Investment product: Kamino USDC Borrow (id=29130, chainIndex=501)
{
"investmentId": "29130",
"address": "4GK2VMnznuPpg8gG9vqD5MM6889pjJ8WS2HqzktaBfSo",
"userInputList": [
{
"tokenAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"chainIndex": "501",
"coinAmount": "0.05"
}
]
}
Response Parameters#
| Field | Type | Explanation |
|---|---|---|
| data.dataList | Array | Calldata result list (execute in order) |
| > callDataType | String | Operation type (approve, subscribe, redeem, claim) |
| > from | String | From address (user wallet address) |
| > to | String | To address (target contract address) |
| > value | String | Transfer amount (native token quantity). Empty string or "0x0" when no native token transfer is needed |
| > serializedData | String | Serialized transaction data. EVM: hex calldata (0x prefix); Solana: base58 encoded; Sui: base64 encoded BCS bytes |
| > originalData | String | Auxiliary metadata (JSON string) |
| > transactionPayload | String | Transaction template, only returned for Aptos chains |
| > signatureData | String | Signature data |
| > gas | String | Gas limit, only returned for non-EVM chains such as Aptos |
Common dataList combinations during redemption:
- Single step:
[WITHDRAW]— pure redemption/repayment - Two steps:
[APPROVE, WITHDRAW]— requires prior aToken authorization to Zap - Two steps:
[WITHDRAW, SWAP]— V3 withdraw then swap back to target token (actually combined into a single callDataType=WITHDRAW,SWAP)
Response Example#
EVM chain (Avalanche Aave V3 USDC redemption, APPROVE + WITHDRAW two steps)
{
"code": 0,
"msg": "",
"data": {
"dataList": [
{
"callDataType": "APPROVE",
"from": "0x1ae68a40b9f903a469aed01574f3a9ab6d45c563",
"to": "0x625e7708f30ca75bfd92586e17077590c60eb4cd",
"value": "0x0",
"serializedData": "0x095ea7b3000000000000000000000000...ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"originalData": "{\"callDataType\":\"APPROVE\",\"methodId\":\"0x095ea7b3\",\"methodDefine\":\"approve(address,uint256)\",...}",
"signatureData": ""
},
{
"callDataType": "WITHDRAW",
"from": "0x1ae68a40b9f903a469aed01574f3a9ab6d45c563",
"to": "0x794a61358d6845594f94dc1db02a252b5b4814ad",
"value": "0x0",
"serializedData": "0x69328dec000000000000000000000000...0000000000000000000000001ae68a40b9f903a469aed01574f3a9ab6d45c563",
"originalData": "{\"callDataType\":\"WITHDRAW\",\"methodId\":\"0x69328dec\",\"methodDefine\":\"withdraw(address,uint256,address)\",...}",
"signatureData": ""
}
]
}
}
Note: When
redeemPercent="1", the amount parameter inserializedDatais MAX_UINT256, and the contract dynamically retrieves the actual balance for redemption, avoiding insufficient balance issues caused by aToken interest growth.