Signed Redemptions
Authorize a redemption with an EIP-712 signature, then submit it from a separate gas-paying wallet. See Vault Lifecycle for immediate and delayed settlement.
Only the vault's EIP-712 RequestRedeem signature is required. The vault transfers shares internally from onBehalf, so no share approval or permit is needed. The request uses vault.nonces(onBehalf).
1. Configure the client
Install dependencies with npm install viem tsx. Save the setup and the following function together in a .ts file. Configure USER_PK and RELAYER_PK locally; never send private keys to an API.
The addresses and amounts below are the CXMT/vUSDC example. Confirm current addresses with Fund Information, minimum amounts, balances, and the selected network before running. This example submits from a local gas-paying wallet (RELAYER_PK). To have SoDEX broadcast the signed OnBehalf call, use the Transaction Relayer.
Set referral from Referrals before signing; the example bytes32(0) means no code.
import {
type Address,
type Hex,
createWalletClient,
createPublicClient,
defineChain,
http,
parseAbi,
parseUnits,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
const valuechain = defineChain({
id: 286623,
name: "ValueChain",
nativeCurrency: { name: "SOSO", symbol: "SOSO", decimals: 18 },
rpcUrls: { default: { http: ["https://mainnet.valuechain.xyz"] } },
});
const VaultAbi = parseAbi([
"function name() view returns (string)",
"function nonces(address owner) view returns (uint256)",
"function requestDepositOnBehalf(address onBehalf, uint256 assets, uint256 deadline, bytes permitSignature, bytes requestSignature, bytes32 referral)",
"function requestRedeemOnBehalf(address onBehalf, uint256 shares, uint256 deadline, bytes32 referral, bytes signature)",
]);
const vault = "0x9876b381a94876eA8FeA56b625E15556fB450629" as Address; // CXMT Vault
const asset = "0xcb7F80Dff2727c791fA491722c428e6657f7e2c6" as Address; // vUSDC
const onBehalf = privateKeyToAccount(process.env.USER_PK as Hex);
const relayer = privateKeyToAccount(process.env.RELAYER_PK as Hex);
const publicClient = createPublicClient({ chain: valuechain, transport: http() });
const userClient = createWalletClient({ account: onBehalf, chain: valuechain, transport: http() });
const relayerClient = createWalletClient({ account: relayer, chain: valuechain, transport: http() });2. Submit a redemption request
To submit, append exampleRequestRedeemOnBehalf().then(console.log).catch(console.error); and run npx tsx redeem.ts.
3. Confirm submission and track settlement
Save the returned transaction hash before waiting. With the same client setup, append this after the selected function instead of the one-line invocation above:
A successful receipt confirms execution of the redemption request, not completion of settlement. Query the user's fund timeline with USER_ADDRESS set to the request owner:
Entries may be processing, completed, or cancelled. Inspect immediate and delayed redemption amounts independently; completion of the immediate portion does not settle the delayed portion. See User Fund History for fields.
SoDEX normally claims for the user. Call claimRedeem or claimDelayedRedeem only for a settled portion that was not auto-claimed.
Continue with Settlement and Claims.
Last updated