> For the complete documentation index, see [llms.txt](https://sodex.com/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sodex.com/documentation/for-developers/developers/wealth/vault-lifecycle/signed-redemptions.md).

# Signed Redemptions

Authorize a redemption with an EIP-712 signature, then submit it from a separate gas-paying wallet. See [Vault Lifecycle](/documentation/for-developers/developers/wealth/vault-lifecycle.md) 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](/documentation/for-developers/api-reference/wealth-api/funds.md#get-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](/documentation/for-developers/developers/valuechain-evm/relayer.md).

Set `referral` from [Referrals](/documentation/for-developers/developers/wealth/referrals.md) before signing; the example `bytes32(0)` means no code.

```typescript
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

```typescript
async function exampleRequestRedeemOnBehalf() {
  const shares = parseUnits("50", 18); // >= minRedeemShares
  const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600);
  const referral = "0x0000000000000000000000000000000000000000000000000000000000000000" as Hex;

  const [vaultName, vaultNonce, chainId] = await Promise.all([
    publicClient.readContract({ address: vault, abi: VaultAbi, functionName: "name" }),
    publicClient.readContract({ address: vault, abi: VaultAbi, functionName: "nonces", args: [onBehalf.address] }),
    publicClient.getChainId(),
  ]);

  const signature = await userClient.signTypedData({
    domain: { name: vaultName, version: "1", chainId, verifyingContract: vault },
    types: {
      RequestRedeem: [
        { name: "owner", type: "address" },
        { name: "shares", type: "uint256" },
        { name: "nonce", type: "uint256" },
        { name: "deadline", type: "uint256" },
        { name: "referral", type: "bytes32" },
      ],
    },
    primaryType: "RequestRedeem",
    message: {
      owner: onBehalf.address,
      shares,
      nonce: vaultNonce,
      deadline,
      referral,
    },
  });

  const hash = await relayerClient.writeContract({
    address: vault,
    abi: VaultAbi,
    functionName: "requestRedeemOnBehalf",
    args: [onBehalf.address, shares, deadline, referral, signature],
  });

  return hash;
}
```

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:

```typescript
async function submitAndConfirm() {
  const hash = await exampleRequestRedeemOnBehalf();
  console.log("Submitted transaction:", hash);
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
  if (receipt.status !== "success") throw new Error("Vault request reverted");
  console.log("Request included in block:", receipt.blockNumber.toString());
}
submitAndConfirm().catch(console.error);
```

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:

```bash
curl -sS "https://mainnet-gw.sodex.dev/api/v1/wealth/users/$USER_ADDRESS/fund-details?fundId=CXMT" \
  -H "Accept: application/json"
```

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](/documentation/for-developers/api-reference/wealth-api/user-fund-history.md) 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](/documentation/for-developers/developers/wealth/vault-lifecycle/settlement-and-claims.md).
