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

# Withdraw from an embedded wallet

> Build and send a withdrawal route from an embedded wallet with the headless core: getBalances, buildRoute, useWallet, sendRouteTransaction, and submitReceipt.

There is no prebuilt widget for withdrawals. To move funds out of an embedded wallet, call the [headless core](/integration/headless-core) directly with the embedded wallet as the source. The flow is the same five calls every time:

1. `Trustware.getBalances()` to load what the wallet can send
2. `Trustware.buildRoute()` to get a signable route
3. `Trustware.useWallet()` to attach the embedded wallet
4. `Trustware.sendRouteTransaction()` to sign and broadcast
5. `Trustware.submitReceipt()` to confirm the transaction and enable status tracking

The embedded wallet signs the withdrawal, and funds move through the routing provider's contracts to the destination the user chooses. Trustware builds the route and tracks settlement; it never holds the funds.

<Note>
  This guide covers users withdrawing funds held in an embedded wallet your app provisioned. It is unrelated to paymaster fund management in the Client Dashboard.
</Note>

## When to use this pattern

Choose this pattern when:

* your app provisions embedded wallets and users hold balances in them
* users need to move those funds to an external wallet or another chain
* you want to build the withdrawal UI in your own design system

## Prerequisites

* An adapted embedded wallet. Follow [use Trustware with embedded wallets](/guides/embedded-wallets) to wrap the wallet's EIP-1193 provider with `useEIP1193`.
* An initialized SDK. Either mount `TrustwareProvider` with your config, or call `Trustware.init(config)` before the calls below.

```ts theme={null}
import { Trustware, type TrustwareConfigOptions } from "@trustware/sdk";

const config = {
  apiKey: process.env.NEXT_PUBLIC_TRUSTWARE_API_KEY!,
} satisfies TrustwareConfigOptions;

await Trustware.init(config);
```

## 1. Load embedded wallet balances

`getBalances` returns the token balances for an address on one chain. Filter to funded rows to drive your source-token picker:

```ts theme={null}
const rows = await Trustware.getBalances(fromChain, embeddedAddress, {
  forceRefresh: true,
});

const funded = rows.filter((row) => BigInt(row.balance || "0") > 0n);
```

The SDK caches `getBalances` results per chain and address. Pass `forceRefresh: true` to force a fresh on-chain scan, for example right after a deposit lands; omit it to reuse the cache when the user is only switching between chains.

Each row is a `BalanceRow`:

```ts theme={null}
type BalanceRow = {
  chain_key: string;
  category: "native" | "erc20" | "spl" | "btc";
  contract?: string;
  address?: string;
  symbol?: string;
  decimals: number;
  balance: string; // base units
  name?: string;
  logoURI?: string;
  usdPrice?: number;
};
```

## 2. Build the withdrawal route

Build a route with the embedded wallet as `fromAddress` and the user's chosen destination as `toAddress`:

```ts theme={null}
const route = await Trustware.buildRoute({
  fromChain,
  toChain,
  fromToken,
  toToken,
  fromAmount, // base units, e.g. "1500000" for 1.5 USDC
  fromAddress: embeddedAddress,
  toAddress: destinationAddress,
  slippageBps: 100, // 1% slippage tolerance
});
```

`fromAmount` is in the token's smallest unit. Convert human-readable input with the token's `decimals` before calling the SDK, for example with viem's `parseUnits`. See [headless core](/integration/headless-core) for the full `BuildRouteBody` and `BuildRouteResult` shapes.

## 3. Attach the embedded wallet and send

Attach the adapted wallet, then sign and broadcast the route. `sendRouteTransaction` switches the wallet to the route's chain if needed and returns the transaction hash:

```ts theme={null}
Trustware.useWallet(wallet);

const txHash = await Trustware.sendRouteTransaction(route, fromChain);
```

## 4. Submit the receipt and track status

Submit the transaction hash so Trustware can track settlement, then poll until the route resolves:

```ts theme={null}
await Trustware.submitReceipt(route.intentId, txHash);

const result = await Trustware.pollStatus(route.intentId);

if (result.status === "success") {
  console.log("Withdrawal settled:", result.destTxHash);
}
```

`pollStatus` resolves when the route reaches `success` or `failed`. Use `Trustware.getStatus(route.intentId)` instead if you want to poll on your own schedule.

## Gas reserve for native withdrawals

When the user withdraws the chain's native token, the wallet still needs gas to send the transaction. A "Use max" control should fill the balance minus a small reserve rather than the full balance. Size the reserve for the chain you target: a tiny flat reserve covers a transfer on an L2 like Base, while L1 mainnet needs a larger one for its higher and more volatile gas costs.

## Complete example

A complete Next.js implementation of this flow, including balance display, amount entry with max handling, and route sending, is available in the Trustware examples repo alongside the deposit flow from the [embedded wallets guide](/guides/embedded-wallets).
