APIWallet Operation

Wallet Operation

This guide covers wallet-related operations that involve both StandX Perps HTTP APIs and, where required, SVM/EVM on-chain transactions.

Use it together with:

  • Perps Auth for API authentication and body signatures.
  • Perps HTTP API for the complete HTTP endpoint reference.
  • Your SVM/EVM wallet provider for on-chain signing and transaction submission.

Integration Notes

  • Cash Wallet and Perps Wallet transfers are HTTP-only operations. They require API authentication and a signed request body, but they do not require an EVM contract transaction.
  • Withdraw is a two-step operation. First create a withdraw request through the Bridge API, then submit the returned authorization to the Highway contract with the connected EVM wallet.
  • The connected EVM wallet address should match the signature.caller value returned by the withdraw API.
  • Examples below use DUSD on BSC with viem. Replace chain config, RPC transport, ABI import path, and request helper according to your integration.

Deposit

Deposit is a pure on-chain operation. There is no Perps HTTP API request required for deposit. Users send DUSD directly to the StandX Highway Vault address on the target chain.

ChainStandX Highway Vault (⚠️ Verify before sending⚠️)
BSC0x11b660397382AE3A83c4Ad80e2F791189b39e433
Solana2pBsToyWZjp4Kpkb2LxbYNhHSvKcAwxXeJyHneNhnxmi

⚠️ Funds safety checklist before deposit ⚠️

  • Verify the vault address on-chain first: Before sending any funds, independently verify that the vault address is valid on the target chain and matches the latest official StandX on-chain deployment. This step is mandatory because documentation updates may lag behind future on-chain changes.
  • Test with a small amount first: The minimum deposit amount is 0.5 DUSD. Always send a small test deposit and confirm it arrives as expected before sending a larger amount.
  • Confirm chain and token: Make sure you are sending DUSD on the intended chain. Sending funds to the wrong chain, wrong token address, or wrong vault address may cause permanent loss of funds.

Transfer Cash Wallet to Perps Wallet

POST /api/transfer_to_perps

Transfers funds from the Cash Wallet to the Perps Wallet. Use this when funds have already arrived in the Cash Wallet and should be made available for perps trading.

Authentication RequiredBody Signature Required

Required Parameters

ParameterTypeDescription
amountdecimalAmount to transfer
tokenstringToken symbol. Defaults to DUSD

Request Example:

{
  "amount": "1000.0",
  "token": "DUSD"
}

Response Example:

{
  "code": 0,
  "message": "success",
  "request_id": "xxx-xxx-xxx"
}

Transfer Perps Wallet to Cash Wallet

POST /api/transfer_to_spot

Transfers funds from the Perps Wallet back to the Cash Wallet. Use this before withdrawing if the funds are currently in the Perps Wallet.

Authentication RequiredBody Signature Required

Required Parameters

ParameterTypeDescription
amountdecimalAmount to transfer
tokenstringToken symbol. Defaults to DUSD

Request Example:

{
  "amount": "1000.0",
  "token": "DUSD"
}

Response Example:

{
  "code": 0,
  "message": "success",
  "request_id": "xxx-xxx-xxx"
}

Withdraw from Cash Wallet to EVM Wallet

POST /api/withdraw

Initiates a withdrawal from the Cash Wallet through the Bridge API. If your funds are in the Perps Wallet, transfer them to the Cash Wallet first with Transfer Perps Wallet to Cash Wallet.

Authentication RequiredBody Signature Required

Required Parameters

ParameterTypeDescription
amountdecimalAmount to withdraw
chainstringTarget chain, such as BSC or Solana
tokenstringToken symbol. Defaults to DUSD

Request Example:

{
  "amount": "1000.0",
  "chain": "BSC",
  "token": "DUSD"
}

Response Example:

{
  "tx": {
    "id": "tx_xxx",
    "nonce": 157,
    "tx_type": "withdraw_req",
    "status": "Pending",
    "from_addr": "bsc_0xYourWallet",
    "from_account_type": "spot",
    "to_addr": "bsc_0xYourWallet",
    "to_account_type": "spot",
    "token": "DUSD",
    "token_addr": "0xTokenAddress",
    "token_amount": "2",
    "src_chain": "standx",
    "src_tx": "",
    "src_block": "0",
    "dst_chain": "bsc",
    "dst_tx": "",
    "dst_block": "0",
    "updated_at": "2026-05-13T10:53:43.642264613Z",
    "created_at": "2026-05-13T10:53:43.642264613Z"
  },
  "withdraw_fee": "0.5",
  "signature": {
    "expired_at": 1778671423,
    "chain_id": 56,
    "caller": "0xYourWallet",
    "contract_address": "0xHighwayContract",
    "signature": "0xBackendSignature"
  }
}

Withdraw Procedure

Withdraw is a two-step procedure:

  1. Create the withdraw request with POST /api/withdraw. This reserves the off-chain Cash Wallet amount and returns:
    • tx.nonce: the withdraw request nonce used by the Highway contract
    • tx.token_addr: the DUSD token address on the destination EVM chain
    • tx.token_amount: the total off-chain amount requested for withdrawal
    • withdraw_fee: the fee deducted from tx.token_amount
    • signature: the backend authorization required by the Highway contract
  2. Submit the on-chain withdraw transaction with the connected EVM wallet. The on-chain amount must be the net received amount:
onchainAmount = (tx.token_amount - withdraw_fee) * DUSD base unit

Do not submit tx.token_amount directly. The web SDK follows this flow in sdk/withdraw.tsx: it calls perpsBridgeApiClient.withdraw(...), computes tx.token_amount - withdraw_fee, then calls adapter.spotWithdrawRequest(...). The EVM adapter sends the transaction to the Highway contract through reqRemoteCall(message, signature).

EVM Withdraw Example

import {
  createPublicClient,
  createWalletClient,
  custom,
  http,
  parseUnits,
} from "viem";
import { bsc } from "viem/chains";
import highwayAbi from "./highway.json";
 
const publicClient = createPublicClient({
  chain: bsc,
  transport: http(),
});
 
const walletClient = createWalletClient({
  chain: bsc,
  transport: custom(window.ethereum),
});
 
const [account] = await walletClient.getAddresses();
 
const withdrawRequest = await signedBridgeRequest("/api/withdraw", {
  amount: "2",
  chain: "bsc",
  token: "DUSD",
});
 
const onchainAmount =
  parseUnits(withdrawRequest.tx.token_amount, 18) -
  parseUnits(withdrawRequest.withdraw_fee, 18);
 
const message = {
  token: withdrawRequest.tx.token_addr as `0x${string}`,
  amount: onchainAmount,
  nonce: BigInt(withdrawRequest.tx.nonce),
};
 
const signature = {
  expiredAt: BigInt(withdrawRequest.signature.expired_at),
  chainId: BigInt(withdrawRequest.signature.chain_id),
  caller: withdrawRequest.signature.caller as `0x${string}`,
  contractAddress: withdrawRequest.signature.contract_address as `0x${string}`,
  signature: withdrawRequest.signature.signature as `0x${string}`,
};
 
const { request } = await publicClient.simulateContract({
  address: signature.contractAddress,
  abi: highwayAbi,
  functionName: "reqRemoteCall",
  args: [message, signature],
  account,
});
 
const txHash = await walletClient.writeContract(request);

After the EVM transaction is confirmed on-chain and indexed, the system will release the withdrawal funds.