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

# Deposits & Withdrawals

> Managing USDC deposits and withdrawals with the Bison SDK

## Overview

The SDK provides deposit and withdrawal methods for managing USDC on Bison:

* **Deposits**: Use `executeDepositFlow` to deposit USDC instantly
* **Withdrawals**: Use a two-step process with `scheduleWithdraw` and `claimWithdraw` to request and claim withdrawals
* **Balance Checking**: Use `getDepositedUsdcBalance` to check your available balance

These methods handle all the necessary steps including approvals and authorization signatures.

<Info>
  To avoid ambiguity, we denote the smallest possible multiple of USDC (0.000001 USDC) as one `uusdc`,
  which stands for µUSDC (micro-USDC), and denote the smallest possible multiple of a contract (0.01 contract)
  as one `ccontract` (centicontract).

  User-facing USDC balances are specified as fixed-point strings (e.g. `"1.2625"` for USDC). Contract quantities
  in the API and SDK are specified as integer `ccontracts` strings (e.g. `"1050"` for 10.50 contracts at precision 2).
</Info>

<BigIntAmounts />

## Depositing USDC

Deposit USDC to enable trading on Kalshi markets.

### `executeDepositFlow`

```typescript theme={null}
async executeDepositFlow(params: {
  walletClient: WalletClient;
  publicClient: PublicClient;
  userAddress: `0x${string}`;
  chain: 'base' | 'bsc';
  amountUusdc: string;
}): Promise<`0x${string}`>
```

#### Parameters

<ParamField path="walletClient" type="WalletClient" required>
  Viem wallet client for signing transactions
</ParamField>

<ParamField path="publicClient" type="PublicClient" required>
  Viem public client for reading contract state
</ParamField>

<ParamField path="userAddress" type="string" required>
  User's Ethereum address
</ParamField>

<ParamField path="chain" type="string" required>
  Chain identifier (`"base"` or `"bsc"`). Vault and USDC addresses are automatically resolved from the `/info` endpoint.
</ParamField>

<ParamField path="amountUusdc" type="string" required>
  Amount in µUSDC as an integer string (e.g., `"100000000"` for 100 USDC). Use `usdcToUusdc()` helper for conversion.
</ParamField>

#### Returns

Transaction hash of the deposit transaction.

#### Example

```typescript theme={null}
import { createBisonClient, usdcToUusdc } from '@bison-markets/sdk-ts';
import { createWalletClient, createPublicClient, http, custom } from 'viem';
import { base } from 'viem/chains';

const client = createBisonClient({ 
  baseUrl: 'https://api.bison.markets' 
});

const walletClient = createWalletClient({
  chain: base,
  transport: custom(window.ethereum!),
});

const publicClient = createPublicClient({
  chain: base,
  transport: http(),
});

// Deposit 100 USDC using helper function
const txHash = await client.executeDepositFlow({
  walletClient,
  publicClient,
  userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  chain: 'base',
  amountUusdc: usdcToUusdc(100).toString(), // Helper converts 100 USDC to 100000000 µUSDC
});

console.log('Deposited! Transaction:', txHash);
// Expected output: "Deposited! Transaction: 0xabc123..."
```

## Withdrawing USDC

Withdrawals use a two-step process for security and efficiency:

1. **Schedule**: Request a withdrawal with `scheduleWithdraw` (no gas required, just a signature)
2. **Claim**: Execute the withdrawal on-chain with `claimWithdraw` (requires gas)

This approach allows the system to batch and optimize withdrawal processing.

### `scheduleWithdraw`

Schedules a withdrawal request. This method requires only a signature and does not consume gas.

```typescript theme={null}
async scheduleWithdraw(params: {
  walletClient: WalletClient;
  userAddress: `0x${string}`;
  chain: 'base' | 'bsc';
  amountUusdc: string;
}): Promise<{
  withdrawId: string;
  amountUusdc: string;
  status: 'pending' | 'fill-locked' | 'unclaimed' | 'claimed';
  scheduledAt: string;
}>
```

#### Parameters

<ParamField path="walletClient" type="WalletClient" required>
  Viem wallet client for signing the withdrawal request
</ParamField>

<ParamField path="userAddress" type="string" required>
  User's Ethereum address
</ParamField>

<ParamField path="chain" type="string" required>
  Chain identifier (`"base"` or `"bsc"`)
</ParamField>

<ParamField path="amountUusdc" type="string" required>
  Amount in µUSDC as an integer string (e.g., `"50000000"` for 50 USDC). Must not exceed your deposited balance. Use `usdcToUusdc()` helper for conversion.
</ParamField>

#### Returns

Withdrawal details including the unique `withdrawId` and current status. Note that `amountUusdc` is returned as a string.

#### Example

```typescript theme={null}
import { usdcToUusdc } from '@bison-markets/sdk-ts';

// Step 1: Schedule a withdrawal (no gas required)
const withdrawal = await client.scheduleWithdraw({
  walletClient,
  userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  chain: 'base',
  amountUusdc: usdcToUusdc(50).toString(), // 50 USDC
});

console.log('Withdrawal scheduled:', withdrawal.withdrawId);
console.log('Status:', withdrawal.status); // "pending"
// Expected output: 
// "Withdrawal scheduled: 550e8400-e29b-41d4-a716-446655440000"
// "Status: pending"
```

### `getPendingWithdraws`

Get all pending withdrawals for a user.

```typescript theme={null}
async getPendingWithdraws(params: {
  userAddress: `0x${string}`;
}): Promise<{
  withdraws: Array<{
    id: string;
    chain: 'base' | 'bsc';
    amountUusdc: string;
    claimedAmountUusdc: string;
    remainingUusdc: string;
    status: 'pending' | 'fill-locked' | 'unclaimed' | 'claimed';
    scheduledAt: string;
    lockedAt: string | null;
    unclaimedAt: string | null;
  }>;
  totalPending: string;
  totalFillLocked: string;
  totalUnclaimed: string;
  totalAvailableUnclaimed: string;
}>
```

#### Example

```typescript theme={null}
import { uusdcToUsdc } from '@bison-markets/sdk-ts';

const withdrawals = await client.getPendingWithdraws({
  userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
});

// All amounts are returned as strings - use uusdcToUsdc() to convert for display
console.log(`Total unclaimed: ${uusdcToUsdc(withdrawals.totalAvailableUnclaimed)} USDC`);
withdrawals.withdraws.forEach(w => {
  console.log(`${w.id}: ${w.status} - ${uusdcToUsdc(w.amountUusdc)} USDC`);
});
```

### `claimWithdraw`

Claim all available withdrawals on-chain. This method executes a blockchain transaction and requires gas.

```typescript theme={null}
async claimWithdraw(params: {
  walletClient: WalletClient;
  publicClient: PublicClient;
  userAddress: `0x${string}`;
  chain: 'base' | 'bsc';
}): Promise<`0x${string}`>
```

#### Parameters

<ParamField path="walletClient" type="WalletClient" required>
  Viem wallet client for signing transactions
</ParamField>

<ParamField path="publicClient" type="PublicClient" required>
  Viem public client for reading contract state
</ParamField>

<ParamField path="userAddress" type="string" required>
  User's Ethereum address
</ParamField>

<ParamField path="chain" type="string" required>
  Chain identifier (`"base"` or `"bsc"`)
</ParamField>

#### Returns

Transaction hash of the withdrawal claim transaction.

#### Example

```typescript theme={null}
// Step 2: Claim the withdrawal (requires gas)
const txHash = await client.claimWithdraw({
  walletClient,
  publicClient,
  userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  chain: 'base',
});

console.log('Withdrawal claimed! Transaction:', txHash);
// Expected output: "Withdrawal claimed! Transaction: 0xdef456..."
```

### Complete Withdrawal Example

```typescript theme={null}
import { usdcToUusdc } from '@bison-markets/sdk-ts';

// Schedule a withdrawal
const withdrawal = await client.scheduleWithdraw({
  walletClient,
  userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  chain: 'base',
  amountUusdc: usdcToUusdc(50).toString(), // 50 USDC
});

console.log('Withdrawal scheduled with ID:', withdrawal.withdrawId);

// Wait for the withdrawal to be processed (status changes to 'unclaimed')
// This typically happens when the system batches and processes withdrawals

// Check pending withdrawals
const pending = await client.getPendingWithdraws({
  userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
});

if (pending.totalAvailableUnclaimed !== '0') {
  // Claim all available withdrawals
  const txHash = await client.claimWithdraw({
    walletClient,
    publicClient,
    userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    chain: 'base',
  });
  
  console.log('Successfully claimed withdrawals:', txHash);
}
```

## Checking Balance

Get the user's deposited USDC balance:

### `getDepositedUsdcBalance`

```typescript theme={null}
async getDepositedUsdcBalance(userAddress: string): Promise<{
  depositedBalanceUusdc: string;
}>
```

#### Example

```typescript theme={null}
import { uusdcToUsdc } from '@bison-markets/sdk-ts';

const balance = await client.getDepositedUsdcBalance(
  '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
);

// Balance is returned as a string - convert for display
const usdcAmount = uusdcToUsdc(balance.depositedBalanceUusdc);
console.log(`Balance: ${usdcAmount} USDC`);
// Expected output: "Balance: 100.000000 USDC"
```

## Low-Level Methods

For advanced use cases, you can use the low-level authorization methods:

### `getWithdrawAuthorization`

Get a signed authorization for claiming withdrawals. This is used internally by `claimWithdraw`, but you can call it directly for custom implementations:

```typescript theme={null}
async getWithdrawAuthorization(options: {
  chain: string;
  userAddress: string;
}): Promise<{
  uuid: string;
  signature: string;
  expiresAt: number;
  maxWithdrawAmount: string;
}>
```

#### Example

```typescript theme={null}
import { VAULT_ABI, uusdcToUsdc, parseBigInt } from '@bison-markets/sdk-ts';

const userAddress = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';

const auth = await client.getWithdrawAuthorization({
  chain: 'base',
  userAddress,
});

// maxWithdrawAmount is returned as a string
console.log('Max claimable amount:', uusdcToUsdc(auth.maxWithdrawAmount), 'USDC');
console.log('Expires at:', new Date(auth.expiresAt * 1000));
// Expected output:
// "Max claimable amount: 50.000000 USDC"
// "Expires at: 2024-12-31T12:34:56.000Z"

// Use the authorization with the vault contract - convert string to bigint
const txHash = await walletClient.writeContract({
  address: vaultAddress,
  abi: VAULT_ABI,
  functionName: 'withdrawUSDC',
  args: [
    auth.uuid,
    parseBigInt(auth.maxWithdrawAmount), // Convert string to bigint
    userAddress,
    BigInt(auth.expiresAt),
    auth.signature as `0x${string}`,
  ],
  account: userAddress,
});

console.log('Withdrawal transaction:', txHash);
```

## Error Handling

All deposit and withdrawal methods throw errors when operations fail. Here's how to handle common errors:

```typescript theme={null}
import { usdcToUusdc } from '@bison-markets/sdk-ts';

try {
  const txHash = await client.executeDepositFlow({
    walletClient,
    publicClient,
    userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    chain: 'base',
    amountUusdc: usdcToUusdc(1000).toString(), // 1000 USDC
  });
  console.log('Success:', txHash);
} catch (error) {
  if (error instanceof Error) {
    if (error.message.includes('insufficient funds')) {
      console.error('Not enough USDC in wallet');
      // Show error to user: "Insufficient USDC balance"
    } else if (error.message.includes('User rejected')) {
      console.error('User cancelled transaction');
      // User declined wallet approval
    } else if (error.message.includes('network')) {
      console.error('Network error, please retry');
      // Show retry button
    } else {
      console.error('Deposit failed:', error.message);
      // Show generic error message
    }
  }
}
```

### Withdrawal Error Handling

```typescript theme={null}
import { usdcToUusdc, uusdcToUsdc } from '@bison-markets/sdk-ts';

// Scheduling errors
try {
  const withdrawal = await client.scheduleWithdraw({
    walletClient,
    userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    chain: 'base',
    amountUusdc: usdcToUusdc(50).toString(),
  });
  console.log('Scheduled:', withdrawal.withdrawId);
} catch (error) {
  if (error instanceof Error) {
    if (error.message.includes('Insufficient balance')) {
      // Requested amount is more than available balance
      const balance = await client.getDepositedUsdcBalance(userAddress);
      const maxAmount = uusdcToUsdc(balance.depositedBalanceUusdc);
      console.log(`Maximum withdrawable: ${maxAmount} USDC`);
    } else if (error.message.includes('Signature expired')) {
      console.error('Signature expired, please retry');
    } else if (error.message.includes('Invalid signature')) {
      console.error('Signature verification failed');
    } else {
      console.error('Schedule failed:', error.message);
    }
  }
}

// Claiming errors
try {
  const txHash = await client.claimWithdraw({
    walletClient,
    publicClient,
    userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    chain: 'base',
  });
  console.log('Claimed:', txHash);
} catch (error) {
  if (error instanceof Error) {
    if (error.message.includes('No unclaimed withdrawals')) {
      console.error('No withdrawals ready to claim yet');
      // Check status with getPendingWithdraws
    } else if (error.message.includes('User rejected')) {
      console.error('User cancelled transaction');
    } else {
      console.error('Claim failed:', error.message);
    }
  }
}
```

## Important Notes

### Withdrawals

* Withdrawals use a two-step process: schedule then claim
* `scheduleWithdraw` only requires a signature (no gas)
* `claimWithdraw` executes the on-chain transaction (requires gas)
* Withdrawal status transitions: `pending` → `fill-locked` → `unclaimed` → `claimed`
* You can only schedule withdrawals up to your available balance (deposited balance minus active positions)
* Multiple scheduled withdrawals are batched when claiming
* Withdrawal scheduling signatures expire after 10 minutes

<Tip>
  **Testnet**: Withdrawals are automatically confirmed every 5 minutes. See [Testnet Environment](/general/testnet) for details.
</Tip>

### Deposits

* The SDK handles USDC approval automatically for deposits
* After deposits, balances update automatically via blockchain events

### General

* All amounts in the API are in µUSDC (6 decimal places: 1 USDC = 1,000,000 µUSDC)
* API responses return amounts as strings for precision
* Use `usdcToUusdc()` to convert USDC to µUSDC, then call `.toString()` for API inputs
* Use `uusdcToUsdc()` to convert µUSDC to display format (returns string)
* Vault and USDC addresses are automatically fetched from the `/info` endpoint and cached per client instance
* Transaction confirmation can take 2-5 seconds on Base network
