Appearance
Withdrawal
Start a Coinbase withdrawal, confirm 2FA when required, and inspect the pending state.
When to use
After amount / network selection. Session must be active. Pair with cooldown so the Start button cannot double-submit.
Methods
| Method | Purpose |
|---|---|
startWithdrawal(request, options?) | Start withdraw; often returns { status: 'requires2fa' } |
confirmWithdrawal(code) | Submit 2FA code for the pending withdrawal (6–7 characters; SMS, email, or authenticator) |
cancelWithdrawal() | Clear local pending 2FA state (does not cancel Coinbase-side) |
getActiveWithdrawal() | Pending withdrawal awaiting 2FA, or null |
Request
ts
type StartCoinbaseWithdrawalRequest = {
amount: string
currency: TokenSymbol
name: string // CoinbaseBalance.name
network?: Network
fundingTokens?: TokenSymbol[]
}Options
ts
type StartCoinbaseWithdrawalOptions = {
/**
* Called when the requested amount is above the fee-reserve max and the SDK
* auto-adjusts to maxAmount. May be async. Return `false` to cancel.
*/
onAmountAdjusted?: (
adjustment: CoinbaseWithdrawalAmountAdjustment,
) => boolean | void | Promise<boolean | void>
}When the amount is above the fee-reserve max and the capped max is still viable (> 0 and >= minAmount), startWithdrawal adjusts the amount automatically and awaits onAmountAdjusted if provided. Return false to cancel — the call resolves { status: 'idle' } and does not start cooldown. Omit the callback (or return undefined / true) to proceed with the adjusted amount.
Amounts that cannot be auto-adjusted (below_min, invalid_amount, or a max that would fall below min) still throw COINBASE_INVALID_WITHDRAWAL_AMOUNT.
Statuses
| Status | Meaning |
|---|---|
idle | Cancelled via onAmountAdjusted returning false, or never started |
requires2fa | Show 2FA input, then confirmWithdrawal(code) |
completed | Done — read summary |
error | Surface error; retry when allowed |
Wrong 2FA usually returns { status: 'requires2fa' } again — not a thrown hard error. Confirm is not blocked by cooldown.
The 2FA code can come from SMS, email, or an authenticator app and is typically 6–7 characters. Do not hardcode a 6-digit-only input in your UI.
Passkeys are not supported → COINBASE_PASSKEY_NOT_SUPPORTED.
Example
ts
import { TokenSymbol } from '@swapped/connect-sdk';
const { isInCooldown } = client.coinbase.getCooldown();
if (isInCooldown) {
// disable Start — see Cooldown docs
}
const startResult = await client.coinbase.startWithdrawal(
{
amount: '10',
currency: TokenSymbol.USDC,
name: usdc.name,
network: network?.id,
fundingTokens: [TokenSymbol.ETH],
},
{
// Fire-and-forget: toast, then continue.
onAmountAdjusted: ({ formatted }) => {
toast(`Reduced to ${formatted.adjustedAmount} for the network fee reserve.`)
},
},
);
// Or block on a confirmation dialog:
await client.coinbase.startWithdrawal(request, {
onAmountAdjusted: async ({ formatted }) =>
await confirmDialog(`Withdraw ${formatted.adjustedAmount} instead?`),
});
if (startResult.status === 'requires2fa') {
const confirmResult = await client.coinbase.confirmWithdrawal(userCode);
if (confirmResult.status === 'requires2fa') {
// Wrong code — keep 2FA UI and show feedback
}
}
// User abandons 2FA
client.coinbase.cancelWithdrawal();Errors
| Code | When | What to do |
|---|---|---|
SESSION_NOT_ACTIVE | Swapped session cannot pay again | restartSession() |
COINBASE_NOT_CONNECTED | Not connected | connect() |
COINBASE_SESSION_EXPIRED | Token invalid | Reconnect |
COINBASE_COOLDOWN_ACTIVE | Start during cooldown | Wait; use cooldown UI |
COINBASE_INVALID_WITHDRAWAL_AMOUNT | Amount below min, invalid, or above spendable with no viable cap | Validate in limits first |
COINBASE_PASSKEY_NOT_SUPPORTED | Passkey-only confirm | Ask for SMS / authenticator |
COINBASE_NO_ACTIVE_WITHDRAWAL | Confirm with nothing pending | Start again |
See Errors.