Skip to content

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

MethodPurpose
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

StatusMeaning
idleCancelled via onAmountAdjusted returning false, or never started
requires2faShow 2FA input, then confirmWithdrawal(code)
completedDone — read summary
errorSurface 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

CodeWhenWhat to do
SESSION_NOT_ACTIVESwapped session cannot pay againrestartSession()
COINBASE_NOT_CONNECTEDNot connectedconnect()
COINBASE_SESSION_EXPIREDToken invalidReconnect
COINBASE_COOLDOWN_ACTIVEStart during cooldownWait; use cooldown UI
COINBASE_INVALID_WITHDRAWAL_AMOUNTAmount below min, invalid, or above spendable with no viable capValidate in limits first
COINBASE_PASSKEY_NOT_SUPPORTEDPasskey-only confirmAsk for SMS / authenticator
COINBASE_NO_ACTIVE_WITHDRAWALConfirm with nothing pendingStart again

See Errors.