> ## Documentation Index
> Fetch the complete documentation index at: https://staging-docs.orderly.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Deposit/Withdrawal

> Implement secure cross-chain deposits and withdrawals with step-by-step smart contract and API integration guides.

> \[!TIP]
> **Deposit Method Selection**:
> This page explains **Standard Vault Deposit**, where the user connects their wallet and invokes the smart contract `deposit` function.
> If your users are depositing from a Centralized Exchange (CEX) or using a custodial wallet that does not support DApps, refer to the [Deposit by Transfer](/build-on-omnichain/user-flows/deposit-by-transfer) guide.

## Deposit

Token deposits can be made on any supported chains (list [here](/introduction/trade-on-orderly/supported-chains))

To create a deposit request:

<Steps>
  <Step title="Approve spending of the token by the Vault smart contract">
    Get Vault & USDC contract addresses from the [Smart Contract Addresses](/build-on-omnichain/addresses) page.
    All our smart contracts are verified, meaning you can retrieve the Vault & Token ABIs from the block explorers of any supported mainnets or testnets.

    > \[!IMPORTANT]
    > *The addresses and RPC nodes used in the following examples are for **Arbitrum Sepolia** testnet. Since Orderly is an omnichain protocol, when deploying to production, replace these with the correct contract addresses and RPC endpoints for your target chain.*

    <Accordion title="Example code">
      <CodeGroup>
        ```Java Java theme={null}
        String usdcAddress = "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d";
        String vaultAddress = "0x0EaC556c0C2321BA25b9DC01e4e3c95aD5CDCd2f";

        Dotenv dotenv = Dotenv.load();
        String pk = dotenv.get("PRIVATE_KEY");
        Credentials credentials = Credentials.create(ECKeyPair.create(Hex.decodeHex(pk)));

        Web3j web3j = Web3j.build(new HttpService("https://arbitrum-sepolia.publicnode.com"));
        DefaultGasProvider gasProvider = new DefaultGasProvider();

        NativeUSDC USDC = new NativeUSDC(usdcAddress, web3j, credentials, gasProvider);

        BigInteger depositAmount = new BigInteger("10000000");

        // approve USDC ERC-20 to be transferred to Vault contract
        USDC.approve(vaultAddress, depositAmount).send();
        ```

        ```py Python theme={null}
        usdc_address = Web3.to_checksum_address("0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d")
        vault_address = Web3.to_checksum_address("0x0EaC556c0C2321BA25b9DC01e4e3c95aD5CDCd2f")

        private_key = os.environ.get("PRIVATE_KEY")
        account: Account = Account.from_key(private_key)

        w3 = Web3(Web3.HTTPProvider("https://arbitrum-sepolia.publicnode.com"))

        with open("./src/abi/NativeUSDC.json") as f:
            abi = json.load(f)
        usdc = w3.eth.contract(
            address=usdc_address,
            abi=abi,
        )

        deposit_amount = 10000000

        # Build transaction to approve USDC ERC-20 to be transferred to Vault contract
        approve_tx = usdc.functions.approve(vault_address, deposit_amount).build_transaction({
            "from": account.address,
            "nonce": w3.eth.get_transaction_count(account.address),
            "gasPrice": w3.eth.gas_price
        })

        # Sign and send the raw transaction directly (no middleware required)
        signed_tx = w3.eth.account.sign_transaction(approve_tx, private_key=private_key)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        w3.eth.wait_for_transaction_receipt(tx_hash)
        ```

        ```ts TypeScript theme={null}
        const usdcAddress = "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d";
        const vaultAddress = "0x0EaC556c0C2321BA25b9DC01e4e3c95aD5CDCd2f";

        const provider = new ethers.JsonRpcProvider("https://arbitrum-sepolia.publicnode.com");
        const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

        const usdcContract = NativeUSDC__factory.connect(usdcAddress, wallet);

        const depositAmount = 10_000_000n;
        await usdcContract.approve(vaultAddress, depositAmount);
        ```
      </CodeGroup>
    </Accordion>
  </Step>

  <Step title="Determine necessary deposit fee in WEI">
    <Accordion title="Example code">
      <CodeGroup>
        ```Java Java theme={null}
        String brokerId = "woofi_pro";
        String tokenId = "USDC";
        String orderlyAccountId = "0x...";

        Vault vault = new Vault(vaultAddress, web3j, credentials, gasProvider);

        Keccak.Digest256 brokerHash = new Keccak.Digest256();
        byte[] brokerIdBytes = brokerId.getBytes("UTF-8");
        brokerHash.update(brokerIdBytes, 0, brokerIdBytes.length);

        Keccak.Digest256 tokenHash = new Keccak.Digest256();
        byte[] usdcBytes = tokenId.getBytes("UTF-8");
        tokenHash.update(usdcBytes, 0, usdcBytes.length);

        Vault.VaultDepositFE depositInput = new Vault.VaultDepositFE(
        Hex.decodeHex(orderlyAccountId.substring(2)),
        brokerHash.digest(),
        tokenHash.digest(),
        depositAmount);

        // get wei deposit fee for `deposit` call
        BigInteger depositFee = vault.getDepositFee(credentials.getAddress(), depositInput).send();

        ```

        ```py Python theme={null}
        broker_id = "woofi_pro"
        token_id = "USDC"
        orderly_account_id = "0x..."

        with open("./src/abi/Vault.json") as f:
            abi = json.load(f)
        vault = w3.eth.contract(
            address=vault_address,
            abi=abi,
        )

        broker_hash = w3.keccak(text=broker_id)
        token_hash = w3.keccak(text=token_id)

        deposit_input = (
            bytes.fromhex(orderly_account_id[2:]),
            broker_hash,
            token_hash,
            deposit_amount,
        )

        # get wei deposit fee for `deposit` call
        deposit_fee = vault.functions.getDepositFee(
            Web3.to_checksum_address(account.address),
            deposit_input,
        ).call()
        ```

        ```ts TypeScript theme={null}
        const brokerId = "woofi_pro";
        const tokenId = "USDC";
        const orderlyAccountId = "0x...";

        const vaultContract = Vault__factory.connect(vaultAddress, wallet);

        const encoder = new TextEncoder();
        const depositInput = {
          accountId: orderlyAccountId,
          brokerHash: keccak256(encoder.encode(brokerId)),
          tokenHash: keccak256(encoder.encode(tokenId)),
          tokenAmount: depositAmount
        } satisfies VaultTypes.VaultDepositFEStruct;

        // get wei deposit fee for `deposit` call
        const depositFee = await vaultContract.getDepositFee(wallet.address, depositInput);
        ```
      </CodeGroup>
    </Accordion>
  </Step>

  <Step title="Call the `deposit` function of the smart contract">
    Contains the following structured data:

    ```json theme={null}
    struct DepositData {
      bytes32 accountId;
      bytes32 brokerHash;
      bytes32 tokenHash;
      uint128 tokenAmount;
    }
    ```

    where:

    | **Name**    | **Type** | **Required** | **Description**                                        |
    | ----------- | -------- | ------------ | ------------------------------------------------------ |
    | accountId   | bytes    | Y            | The account id of the user in bytes.                   |
    | brokerHash  | bytes    | Y            | The keccak256 hash of the builder id (eg "woofi\_dex") |
    | tokenHash   | bytes    | Y            | The keccak256 hash of the token string (eg "USDC")     |
    | tokenAmount | int      | Y            | Amount of tokens to be deposited                       |

    <Accordion title="Example code">
      <CodeGroup>
        ```Java Java theme={null}
        // deposit USDC into Vault contract
        vault.deposit(
              depositInput,
              depositFee).send();
        ```

        ```py Python theme={null}
        # deposit USDC into Vault contract
        vault.functions.deposit(deposit_input).transact(
            {"from": account.address, "value": deposit_fee}
        )
        ```

        ```ts TypeScript theme={null}
        // deposit USDC into Vault contract
        await vaultContract.deposit(depositInput, { value: depositFee });
        ```
      </CodeGroup>
    </Accordion>
  </Step>
</Steps>

<Note>
  Deposits will take some time to reflect depending on the origin chain, to allow for finalizing of
  the cross-chain transaction involved in the deposit. Once the deposit is credited, the balance
  will update and the transaction can be seen on the [Get asset history
  API](/build-on-omnichain/restful-api/private/get-asset-history).
</Note>

### Full example

<Accordion title="Code generation via ABI file" defaultOpen="true">
  <Tabs>
    <Tab title="Java">
      * install [Web3j CLI](https://docs.web3j.io/4.8.7/command_line_tools/)
      * `web3j generate solidity -a <./path/to/Vault.json> -o <./out-path/to/Vault.java> -p <package-name>`
    </Tab>

    <Tab title="TypeScript">
      * install [Typechain](https://github.com/dethcrypto/TypeChain)
      * `typechain --target=ethers-v6 <./path/to/Vault.json> --out-dir <out/path>`
    </Tab>
  </Tabs>
</Accordion>

<CodeGroup>
  ```Java Java theme={null}
  import java.math.BigInteger;

  import org.apache.commons.codec.binary.Hex;
  import org.bouncycastle.jcajce.provider.digest.Keccak;
  import org.web3j.crypto.Credentials;
  import org.web3j.crypto.ECKeyPair;
  import org.web3j.protocol.Web3j;
  import org.web3j.protocol.http.HttpService;
  import org.web3j.tx.gas.DefaultGasProvider;
  import io.github.cdimascio.dotenv.Dotenv;

  public class DepositExample {

        public static void main(String[] args) throws Exception {

              String brokerId = "woofi_pro";
              String tokenId = "USDC";
              String orderlyAccountId = "0x...";

              String usdcAddress = "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d";
              String vaultAddress = "0x0EaC556c0C2321BA25b9DC01e4e3c95aD5CDCd2f";

              Dotenv dotenv = Dotenv.load();
              String pk = dotenv.get("PRIVATE_KEY");
              Credentials credentials = Credentials.create(ECKeyPair.create(Hex.decodeHex(pk)));

              Web3j web3j = Web3j.build(new HttpService("https://arbitrum-sepolia.publicnode.com"));
              DefaultGasProvider gasProvider = new DefaultGasProvider();

              NativeUSDC USDC = new NativeUSDC(usdcAddress, web3j, credentials, gasProvider);

              BigInteger depositAmount = new BigInteger("10000000");

              // approve USDC ERC-20 to be transferred to Vault contract
              USDC.approve(vaultAddress, depositAmount).send();

              Vault vault = new Vault(vaultAddress, web3j, credentials, gasProvider);

              Keccak.Digest256 brokerHash = new Keccak.Digest256();
              byte[] brokerIdBytes = brokerId.getBytes("UTF-8");
              brokerHash.update(brokerIdBytes, 0, brokerIdBytes.length);

              Keccak.Digest256 tokenHash = new Keccak.Digest256();
              byte[] usdcBytes = tokenId.getBytes("UTF-8");
              tokenHash.update(usdcBytes, 0, usdcBytes.length);

              Vault.VaultDepositFE depositInput = new Vault.VaultDepositFE(
                          Hex.decodeHex(orderlyAccountId.substring(2)),
                          brokerHash.digest(),
                          tokenHash.digest(),
                          depositAmount);

              // get wei deposit fee for `deposit` call
              BigInteger depositFee = vault.getDepositFee(credentials.getAddress(), depositInput).send();

              // deposit USDC into Vault contract
              vault.deposit(
                          depositInput,
                          depositFee).send();
        }

  }

  ```

  ```py Python theme={null}
  import json
  import os

  from eth_account import Account
  from web3 import Web3

  broker_id = "woofi_pro"
  token_id = "USDC"
  orderly_account_id = "0x..."

  usdc_address = Web3.to_checksum_address("0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d")
  vault_address = Web3.to_checksum_address("0x0EaC556c0C2321BA25b9DC01e4e3c95aD5CDCd2f")

  private_key = os.environ.get("PRIVATE_KEY")
  account: Account = Account.from_key(private_key)

  w3 = Web3(Web3.HTTPProvider("https://arbitrum-sepolia.publicnode.com"))

  with open("./src/abi/NativeUSDC.json") as f:
      abi = json.load(f)
  usdc = w3.eth.contract(
      address=usdc_address,
      abi=abi,
  )

  deposit_amount = 10000000

  # 1. Build and sign approve transaction
  approve_tx = usdc.functions.approve(vault_address, deposit_amount).build_transaction({
      "from": account.address,
      "nonce": w3.eth.get_transaction_count(account.address),
      "gasPrice": w3.eth.gas_price
  })
  signed_approve_tx = w3.eth.account.sign_transaction(approve_tx, private_key=private_key)
  approve_hash = w3.eth.send_raw_transaction(signed_approve_tx.raw_transaction)
  w3.eth.wait_for_transaction_receipt(approve_hash)

  with open("./src/abi/Vault.json") as f:
      abi = json.load(f)
  vault = w3.eth.contract(
      address=vault_address,
      abi=abi,
  )

  broker_hash = w3.keccak(text=broker_id)
  token_hash = w3.keccak(text=token_id)

  deposit_input = (
      bytes.fromhex(orderly_account_id[2:]),
      bytes.fromhex(broker_hash.hex()[2:]),
      bytes.fromhex(token_hash.hex()[2:]),
      deposit_amount,
  )

  # get wei deposit fee for `deposit` call
  deposit_fee = vault.functions.getDepositFee(
      Web3.to_checksum_address(account.address),
      deposit_input,
  ).call()

  # 2. Build and sign deposit transaction
  deposit_tx = vault.functions.deposit(deposit_input).build_transaction({
      "from": account.address,
      "value": deposit_fee,
      "nonce": w3.eth.get_transaction_count(account.address),
      "gasPrice": w3.eth.gas_price
  })
  signed_deposit_tx = w3.eth.account.sign_transaction(deposit_tx, private_key=private_key)
  deposit_hash = w3.eth.send_raw_transaction(signed_deposit_tx.raw_transaction)
  w3.eth.wait_for_transaction_receipt(deposit_hash)
  ```

  ```ts TypeScript theme={null}
  import { config } from "dotenv";
  import { AbiCoder, ethers, keccak256, solidityPackedKeccak256 } from "ethers";

  import { Vault__factory, NativeUSDC__factory } from "./abi";
  import type { VaultTypes } from "./abi/Vault";

  const brokerId = "woofi_pro";
  const tokenId = "USDC";

  const usdcAddress = "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d";
  const vaultAddress = "0x0EaC556c0C2321BA25b9DC01e4e3c95aD5CDCd2f";

  config();

  async function deposit(): Promise<void> {
    const provider = new ethers.JsonRpcProvider("https://arbitrum-sepolia.publicnode.com");
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

    const usdcContract = NativeUSDC__factory.connect(usdcAddress, wallet);

    const depositAmount = 10_000_000n;
    await usdcContract.approve(vaultAddress, depositAmount);

    const vaultContract = Vault__factory.connect(vaultAddress, wallet);

    const orderlyAccountId = getAccountId(wallet.address, brokerId);

    const encoder = new TextEncoder();
    const depositInput = {
      accountId: orderlyAccountId,
      brokerHash: keccak256(encoder.encode(brokerId)),
      tokenHash: keccak256(encoder.encode(tokenId)),
      tokenAmount: depositAmount
    } satisfies VaultTypes.VaultDepositFEStruct;

    // get wei deposit fee for `deposit` call
    const depositFee = await vaultContract.getDepositFee(wallet.address, depositInput);

    // deposit USDC into Vault contract
    await vaultContract.deposit(depositInput, { value: depositFee });
  }

  export function getAccountId(address: string, brokerId: string) {
    const abicoder = new AbiCoder();
    return keccak256(
      abicoder.encode(
        ["address", "bytes32"],
        [address, solidityPackedKeccak256(["string"], [brokerId])]
      )
    );
  }

  deposit();
  ```
</CodeGroup>

## Withdrawal

> \[!WARNING]
> **PnL Settlement Requirement**: Any realized profit from open or recently closed positions must be settled via the **Settle PnL** flow before it can be added to your `withdrawable_balance`. If you attempt to withdraw without settling your PnL, the withdrawal amount may exceed your available balance and fail. See [Settle PnL](/build-on-omnichain/user-flows/settle-pnl) for details.

To withdraw tokens from Orderly:

<Steps>
  <Step title="Choose a valid chain to withdraw your funds to">
    A list of supported chains can be found on our [Smart Contract Addresses page](/build-on-omnichain/addresses).
  </Step>

  <Step title="Check if the chain has sufficient liquidity">
    Since Orderly is an omnichain trading infrastructure, the liquidity of withdrawn assets might need to move across chains. If there is not enough liquidity of the withdrawn asset on the target chain, then an
    additional cross-chain transaction fee will be deducted from the user's account.
  </Step>

  <Step title="Obtain a withdrawal nonce">
    Get a nonce from [Get Withdrawal Nonce API](/build-on-omnichain/restful-api/private/get-withdrawal-nonce).
  </Step>

  <Step title="Obtain a signature from EIP-712">
    Sign an EIP-712 message of [message type](/build-on-omnichain/user-flows/wallet-authentication#message-types) `Withdraw`:

    ```json theme={null}
    "Withdraw": [
        {"name": "brokerId", "type": "string"},
        {"name": "chainId", "type": "uint256"},
        {"name": "receiver", "type": "address"},
        {"name": "token", "type": "string"},
        {"name": "amount", "type": "uint256"},
        {"name": "withdrawNonce", "type": "uint64"},
        {"name": "timestamp", "type": "uint64"},
    ]
    ```

    Example:

    ```json theme={null}
    {
      "brokerId": "woofi_pro",
      "chainId": 421614,
      "receiver": "0x036Cb579025d3535a0ADcD929D05481a3189714b",
      "token": "USDC",
      "amount": 1000000,
      "withdrawNonce": 1,
      "timestamp": 1685973017064
    }
    ```

    where:

    | **Name**      | **Type**  | **Required** | **Description**                                                                                                                                                                                   |
    | ------------- | --------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | brokerId      | string    | Y            | The unique identifier of the Builder (also known as Broker ID). A list of valid IDs can be retrieved via the [Get list of builders API](/build-on-omnichain/restful-api/public/get-builder-list). |
    | chainId       | int       | Y            | Chain ID of the chain that the funds should be withdrawn to (within those that are supported by the Network)                                                                                      |
    | receiver      | string    | Y            | Address of the receiver, which should be equal to the address of the account.                                                                                                                     |
    | token         | string    | Y            | The string representation of the token that is being withdrawn (eg "USDC")                                                                                                                        |
    | amount        | string    | Y            | Amount of tokens to be withdrawn                                                                                                                                                                  |
    | withdrawNonce | int       | Y            | Valid withdrawal nonce from [Get Withdrawal Nonce API](/build-on-omnichain/restful-api/private/get-withdrawal-nonce)                                                                              |
    | timestamp     | timestamp | Y            | current timestamp in UNIX milliseconds                                                                                                                                                            |
  </Step>

  <Step title="Make a withdraw request">
    Call the [Create withdraw request API](/build-on-omnichain/restful-api/private/create-withdraw-request).
  </Step>
</Steps>

### Full Example

Unlike key registration which uses the off-chain domain, a withdrawal signature requires the **on-chain domain** targeting the Orderly Ledger contract.

Furthermore, note the type formatting difference:

* In the EIP-712 cryptography signature message, `amount` must be represented as a **numeric value** (`uint256`/`BigInt`).
* In the final REST API JSON payload, the `amount` field must be serialized as a **String**.

<CodeGroup>
  ```ts TypeScript theme={null}
  import { ethers } from "ethers";

  const types = {
    Withdraw: [
      { name: "brokerId", type: "string" },
      { name: "chainId", type: "uint256" },
      { name: "receiver", type: "address" },
      { name: "token", type: "string" },
      { name: "amount", type: "uint256" },
      { name: "withdrawNonce", type: "uint64" },
      { name: "timestamp", type: "uint64" }
    ]
  };

  // Target Ledger Contract Address (Arbitrum Sepolia L2 Ledger shown below)
  // Mainnet: 0x6F7a338F2aA472838dEFD3283eB360d4Dff5D203
  // Testnet: 0x1826B75e2ef249173FC735149AE4B8e9ea10abff
  const ON_CHAIN_DOMAIN = {
    name: "Orderly",
    version: "1",
    chainId: 421614,
    verifyingContract: "0x1826B75e2ef249173FC735149AE4B8e9ea10abff"
  };

  const BASE_URL = "https://testnet-api.orderly.org";

  async function requestWithdrawal() {
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!);

    // 1. Fetch withdrawal nonce from private API
    const timestamp = Date.now();
    const signatureKey = await wallet
      .signTypedData
      // ... Assume signature for API auth is already created
      ();
    // (Assuming you obtained withdrawNonce = 1 and orderlyAccountId)
    const withdrawNonce = 1;
    const orderlyAccountId = "0x...";

    // 2. Prepare EIP-712 message (amount as BigInt)
    const withdrawMessage = {
      brokerId: "woofi_dex",
      chainId: 421614,
      receiver: wallet.address,
      token: "USDC",
      amount: 1000000n, // 1 USDC (6 decimals)
      withdrawNonce,
      timestamp
    };

    // 3. Sign EIP-712 typed data
    const signature = await wallet.signTypedData(
      ON_CHAIN_DOMAIN,
      { Withdraw: types.Withdraw },
      withdrawMessage
    );

    // 4. Send request to REST API (amount as String)
    const response = await fetch(`${BASE_URL}/v1/withdraw_request`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "orderly-timestamp": String(timestamp),
        "orderly-account-id": orderlyAccountId,
        "orderly-key": "...",
        "orderly-signature": "..." // Ed25519 API signature
      },
      body: JSON.stringify({
        message: {
          brokerId: withdrawMessage.brokerId,
          chainId: withdrawMessage.chainId,
          receiver: withdrawMessage.receiver,
          token: withdrawMessage.token,
          amount: withdrawMessage.amount.toString(), // MUST be String
          withdrawNonce: withdrawMessage.withdrawNonce,
          timestamp: withdrawMessage.timestamp
        },
        signature,
        userAddress: wallet.address
      })
    });

    const result = await response.json();
    console.log(result);
  }
  ```

  ```py Python theme={null}
  import time
  import requests
  from eth_account import Account, messages

  MESSAGE_TYPES = {
      "Withdraw": [
          {"name": "brokerId", "type": "string"},
          {"name": "chainId", "type": "uint256"},
          {"name": "receiver", "type": "address"},
          {"name": "token", "type": "string"},
          {"name": "amount", "type": "uint256"},
          {"name": "withdrawNonce", "type": "uint64"},
          {"name": "timestamp", "type": "uint64"},
      ]
  }

  # Target Ledger Contract Address (Arbitrum Sepolia L2 Ledger shown below)
  # Mainnet: 0x6F7a338F2aA472838dEFD3283eB360d4Dff5D203
  # Testnet: 0x1826B75e2ef249173FC735149AE4B8e9ea10abff
  ON_CHAIN_DOMAIN = {
      "name": "Orderly",
      "version": "1",
      "chainId": 421614,
      "verifyingContract": "0x1826B75e2ef249173FC735149AE4B8e9ea10abff"
  }

  account = Account.from_key("your_private_key")
  timestamp = int(time.time() * 1000)
  withdraw_nonce = 1  # Fetched from /v1/withdraw_nonce

  # EIP-712 message: note amount is integer (numeric)
  withdraw_message = {
      "brokerId": "woofi_dex",
      "chainId": 421614,
      "receiver": account.address,
      "token": "USDC",
      "amount": 1000000, # 1 USDC (6 decimals)
      "withdrawNonce": withdraw_nonce,
      "timestamp": timestamp
  }

  encoded_data = messages.encode_typed_data(
      domain_data=ON_CHAIN_DOMAIN,
      message_types={"Withdraw": MESSAGE_TYPES["Withdraw"]},
      message_data=withdraw_message
  )
  signed_message = account.sign_message(encoded_data)

  # Send request to REST API (amount as String)
  payload = {
      "message": {
          "brokerId": withdraw_message["brokerId"],
          "chainId": withdraw_message["chainId"],
          "receiver": withdraw_message["receiver"],
          "token": withdraw_message["token"],
          "amount": str(withdraw_message["amount"]),  # Convert to String
          "withdrawNonce": withdraw_message["withdrawNonce"],
          "timestamp": withdraw_message["timestamp"]
      },
      "signature": signed_message.signature.hex(),
      "userAddress": account.address
  }

  res = requests.post(
      "https://testnet-api.orderly.org/v1/withdraw_request",
      headers={
          "Content-Type": "application/json",
          "orderly-timestamp": str(timestamp),
          "orderly-account-id": "...",
          "orderly-key": "...",
          "orderly-signature": "..."
      },
      json=payload
  )
  print(res.json())
  ```
</CodeGroup>
