> ## Documentation Index
> Fetch the complete documentation index at: https://core.vanish.trade/llms.txt
> Use this file to discover all available pages before exploring further.

# Trade

> Get a private trade executing on Solana in under 30 minutes.

This picks up where [Setup](/guide/quickstart/setup) left off, and uses the `vanish`, `signMessage`, `broadcast`, and `commit` helpers defined there.

***

## Fund Your Account

Trading requires a Vanish balance: fetch a deposit address, send funds on-chain, then commit the transaction.

<Steps>
  <Step title="Get a deposit address">
    <CodeGroup>
      ```typescript TypeScript theme={null}
      // 11111111111111111111111111111111 is the SOL native mint
      const { address: depositAddress } = await vanish(
        `/deposit_address?token_address=11111111111111111111111111111111`
      );
      ```

      ```rust Rust theme={null}
      // 11111111111111111111111111111111 is the SOL native mint
      let res = vanish(
          client, api_key,
          "/deposit_address?token_address=11111111111111111111111111111111",
          None,
      ).await?;
      let deposit_address = res["address"].as_str().unwrap();
      ```
    </CodeGroup>

    Always fetch a fresh address before each deposit - addresses may rotate to ensure maximum privacy.
  </Step>

  <Step title="Send SOL on-chain">
    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { PublicKey, SystemProgram, Transaction, sendAndConfirmTransaction } from '@solana/web3.js';

      const tx = new Transaction().add(
        SystemProgram.transfer({
          fromPubkey: userKeypair.publicKey,
          toPubkey:   new PublicKey(depositAddress),
          lamports:   100_000_000, // 0.1 SOL
        })
      );

      const depositTxId = await sendAndConfirmTransaction(connection, tx, [userKeypair]);
      ```

      ```rust Rust theme={null}
      use solana_sdk::{pubkey::Pubkey, system_instruction, transaction::Transaction};

      let to        = deposit_address.parse::<Pubkey>().unwrap();
      let ix        = system_instruction::transfer(&user_keypair.pubkey(), &to, 100_000_000); // 0.1 SOL
      let blockhash = rpc.get_latest_blockhash()?;
      let tx = Transaction::new_signed_with_payer(
          &[ix], Some(&user_keypair.pubkey()), &[&user_keypair], blockhash,
      );

      let deposit_tx_id = rpc.send_and_confirm_transaction(&tx)?.to_string();
      ```
    </CodeGroup>
  </Step>

  <Step title="Commit the deposit">
    <CodeGroup>
      ```typescript TypeScript theme={null}
      const deposit = await commit('/commit', depositTxId);
      console.log('Deposit status:', deposit.status);
      // completed = balance updated, ready to trade
      // rejected  = failed screening, funds will be refunded automatically
      ```

      ```rust Rust theme={null}
      let deposit = commit(client, api_key, "/commit", &deposit_tx_id).await?;
      println!("Deposit status: {}", deposit["status"]);
      // completed = balance updated, ready to trade
      // rejected  = failed screening, funds will be refunded automatically
      ```
    </CodeGroup>
  </Step>
</Steps>

***

## Execute a Trade

Vanish wraps your swap instructions - it does not build the route itself. Fetch an unsigned transaction from your DEX aggregator of choice and pass it to [`POST /trade/create`](/api-reference/trade/create).

<Info>
  **Critical:** set the **one-time wallet** as the transaction signer - not the user's wallet. Pass it wherever your aggregator asks for the signing wallet or user public key.
</Info>

<Steps>
  <Step title="Get a one-time wallet and build the swap">
    <CodeGroup>
      ```typescript TypeScript theme={null}
      const SOL_MINT    = '11111111111111111111111111111111';
      const TARGET_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; // USDC
      const AMOUNT      = '100000000'; // 0.1 SOL in lamports

      // never reuse a one-time wallet — fetch a fresh one for every trade
      const { address: oneTimeWallet } = await vanish('/trade/one-time-wallet');

      const quote = await (await fetch(
        `https://quote-api.jup.ag/v6/quote?inputMint=${SOL_MINT}` +
        `&outputMint=${TARGET_MINT}&amount=${AMOUNT}&slippageBps=50`
      )).json();

      const { swapTransaction } = await (await fetch('https://quote-api.jup.ag/v6/swap', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          quoteResponse:    quote,
          userPublicKey:    oneTimeWallet,   // must be the one-time wallet
          wrapAndUnwrapSol: true,
          dynamicComputeUnitLimit: true,
        }),
      })).json();
      ```

      ```rust Rust theme={null}
      const SOL_MINT: &str    = "11111111111111111111111111111111";
      const TARGET_MINT: &str = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"; // USDC
      const AMOUNT: &str      = "100000000"; // 0.1 SOL in lamports

      // never reuse a one-time wallet — fetch a fresh one for every trade
      let otw = vanish(client, api_key, "/trade/one-time-wallet", None).await?;
      let one_time_wallet = otw["address"].as_str().unwrap();

      let quote: Value = reqwest::get(&format!(
          "https://quote-api.jup.ag/v6/quote?inputMint={SOL_MINT}\
           &outputMint={TARGET_MINT}&amount={AMOUNT}&slippageBps=50"
      )).await?.json().await?;

      let swap_res: Value = client
          .post("https://quote-api.jup.ag/v6/swap")
          .json(&serde_json::json!({
              "quoteResponse":           quote,
              "userPublicKey":           one_time_wallet,  // must be the one-time wallet
              "wrapAndUnwrapSol":        true,
              "dynamicComputeUnitLimit": true,
          }))
          .send().await?.json().await?;

      let swap_transaction = swap_res["swapTransaction"].as_str().unwrap();
      ```
    </CodeGroup>
  </Step>

  <Step title="Create the trade and commit">
    <CodeGroup>
      ```typescript TypeScript theme={null}
      const LOAN_SOL = '12000000'; // covers ATA creation — unused amount is refunded
      const JITO_TIP = '1000000';  // 0.001 SOL — minimum recommended tip

      const timestamp = Date.now().toString();

      const trade = await vanish('/trade/create', {
        method: 'POST',
        body: JSON.stringify({
          user_address:         userKeypair.publicKey.toBase58(),
          source_token_address: SOL_MINT,
          target_token_address: TARGET_MINT,
          amount:               AMOUNT,
          swap_transaction:     swapTransaction,  // base64-encoded unsigned tx
          one_time_wallet:      oneTimeWallet,
          loan_additional_sol:  LOAN_SOL,
          jito_tip_amount:      JITO_TIP,
          split_repay:          1,
          timestamp,
          user_signature: signMessage(
            `trade:${SOL_MINT}:${TARGET_MINT}:${AMOUNT}:${LOAN_SOL}:${timestamp}:${JITO_TIP}`,
            userKeypair
          ),
          // omit prefer_non_jito to route via Jito (default)
        }),
      });

      // on the Jito route trade.transaction is null and broadcast() is a no-op
      const txId = (await broadcast(trade)) ?? trade.tx_id;
      const result = await commit('/commit', txId);

      console.log('Status:', result.status, 'Changes:', result.balance_changes);
      ```

      ```rust Rust theme={null}
      const LOAN_SOL: &str = "12000000"; // covers ATA creation — unused amount is refunded
      const JITO_TIP: &str = "1000000";  // 0.001 SOL — minimum recommended tip

      let timestamp = chrono::Utc::now().timestamp_millis().to_string();

      let trade = vanish(client, api_key, "/trade/create", Some(&serde_json::json!({
          "user_address":         user_keypair.pubkey().to_string(),
          "source_token_address": SOL_MINT,
          "target_token_address": TARGET_MINT,
          "amount":               AMOUNT,
          "swap_transaction":     swap_transaction,  // base64-encoded unsigned tx
          "one_time_wallet":      one_time_wallet,
          "loan_additional_sol":  LOAN_SOL,
          "jito_tip_amount":      JITO_TIP,
          "split_repay":          1,
          "timestamp":            &timestamp,
          "user_signature": sign_message(
              &format!("trade:{SOL_MINT}:{TARGET_MINT}:{AMOUNT}:{LOAN_SOL}:{timestamp}:{JITO_TIP}"),
              &user_keypair,
          ),
          // omit prefer_non_jito to route via Jito (default)
      }))).await?;

      // on the Jito route trade["transaction"] is null and broadcast() is a no-op
      let tx_id = broadcast(&rpc, &trade).await?
          .unwrap_or_else(|| trade["tx_id"].as_str().unwrap().to_string());
      let result = commit(client, api_key, "/commit", &tx_id).await?;

      println!("Status: {} Changes: {}", result["status"], result["balance_changes"]);
      ```
    </CodeGroup>

    <Warning>
      `/commit` must be called for every transaction - success, failure, or expiry. Without it, the user's balance remains in a pending state indefinitely.
    </Warning>

    On the non-Jito route, add `prefer_non_jito` to the request and commit the **on-chain signature** returned by broadcasting, not `trade.tx_id`. See [Routing](/guide/integration/trading#routing).
  </Step>
</Steps>

***

## Check Balances

See [`POST /account/balances`](/api-reference/account/get_balances) for full reference.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const timestamp = Date.now().toString();

  const balances = await vanish('/account/balances', {
    method: 'POST',
    body: JSON.stringify({
      user_address: userKeypair.publicKey.toBase58(),
      timestamp,
      signature: signMessage(`read:${timestamp}`, userKeypair),
    }),
  });

  // [{ token_address, balance, program_id }, ...]
  // balance is in lamports for SOL, base units for SPL tokens
  console.log(balances);
  ```

  ```rust Rust theme={null}
  let timestamp = chrono::Utc::now().timestamp_millis().to_string();

  let balances = vanish(client, api_key, "/account/balances", Some(&serde_json::json!({
      "user_address": user_keypair.pubkey().to_string(),
      "timestamp":    &timestamp,
      "signature":    sign_message(&format!("read:{timestamp}"), &user_keypair),
  }))).await?;

  // [{ token_address, balance, program_id }, ...]
  println!("{}", balances);
  ```
</CodeGroup>

***

## Next Steps

* [Lend](/guide/quickstart/lend) - Open a position with funds advanced by Vanish, then settle it.
* [Trading](/guide/integration/trading) - The full reference for the trade flow, including routing guidance.
* [Error Handling](/guide/handling) - Commit statuses and recovering interrupted flows.
* [Before Going Live](/guide/quickstart/lend#before-going-live) - The pre-launch checklist, covering both flows.
