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.callervalue 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.
| Chain | StandX Highway Vault (⚠️ Verify before sending⚠️) |
|---|---|
| BSC | 0x11b660397382AE3A83c4Ad80e2F791189b39e433 |
| Solana | 2pBsToyWZjp4Kpkb2LxbYNhHSvKcAwxXeJyHneNhnxmi |
⚠️ 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 Required • Body Signature Required
Required Parameters
| Parameter | Type | Description |
|---|---|---|
| amount | decimal | Amount to transfer |
| token | string | Token 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 Required • Body Signature Required
Required Parameters
| Parameter | Type | Description |
|---|---|---|
| amount | decimal | Amount to transfer |
| token | string | Token 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 Required • Body Signature Required
Required Parameters
| Parameter | Type | Description |
|---|---|---|
| amount | decimal | Amount to withdraw |
| chain | string | Target chain, such as BSC or Solana |
| token | string | Token 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:
- 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 contracttx.token_addr: the DUSD token address on the destination EVM chaintx.token_amount: the total off-chain amount requested for withdrawalwithdraw_fee: the fee deducted fromtx.token_amountsignature: the backend authorization required by the Highway contract
- 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 unitDo 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.