Overview
The SDK provides executeDepositFlow and executeWithdrawFlow, and getDepositedUsdcBalance methods to deposit and withdraw USDC from the Bison vault
on a given chain. These methods handle all the necessary steps including asking for approvals and authorization signatures.
Depositing USDC
Deposit USDC into the vault to enable trading on Kalshi markets.
executeDepositFlow
async executeDepositFlow(params: {
walletClient: WalletClient;
publicClient: PublicClient;
userAddress: `0x${string}`;
chain: 'base';
amountUusdc: number;
}): Promise<`0x${string}`>
Parameters
Viem wallet client for signing transactions
Viem public client for reading contract state
Chain identifier (currently only "base" is supported). Vault and USDC addresses are automatically resolved from the /info endpoint.
Amount in µUSDC (e.g., 100_000_000 for 100 USDC)
Returns
Transaction hash of the deposit transaction.
Example
import { createBisonClient } from 'bison-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
const txHash = await client.executeDepositFlow({
walletClient,
publicClient,
userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
chain: 'base',
amountUusdc: 100_000_000, // 100 USDC
});
console.log('Deposited! Transaction:', txHash);
// Expected output: "Deposited! Transaction: 0xabc123..."
Withdrawing USDC
Withdraw USDC from your deposited balance in the vault.
executeWithdrawFlow
async executeWithdrawFlow(params: {
walletClient: WalletClient;
publicClient: PublicClient;
userAddress: `0x${string}`;
chain: 'base';
amountUusdc: number;
}): Promise<`0x${string}`>
Parameters
Viem wallet client for signing transactions
Viem public client for reading contract state
Chain identifier (currently only "base" is supported). Vault address is automatically resolved from the /info endpoint.
Amount in µUSDC (e.g., 50_000_000 for 50 USDC). Must not exceed your deposited balance.
Returns
Transaction hash of the withdrawal transaction.
Example
// Withdraw 50 USDC
const txHash = await client.executeWithdrawFlow({
walletClient,
publicClient,
userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
chain: 'base',
amountUusdc: 50_000_000, // 50 USDC
});
console.log('Withdrawn! Transaction:', txHash);
// Expected output: "Withdrawn! Transaction: 0xdef456..."
Checking Balance
Get the user’s deposited USDC balance:
getDepositedUsdcBalance
async getDepositedUsdcBalance(userAddress: string): Promise<{
depositedBalanceUusdc: number;
}>
Example
const balance = await client.getDepositedUsdcBalance(
'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
);
// Convert µUSDC to USDC (1 USDC = 1,000,000 µUSDC)
const usdcAmount = balance.depositedBalanceUusdc / 1_000_000;
console.log(`Balance: ${usdcAmount} USDC`);
// Expected output: "Balance: 100 USDC"
Low-Level Methods
For advanced use cases, you can use the low-level authorization methods:
getWithdrawAuthorization
Get a signed authorization for withdrawing USDC:
async getWithdrawAuthorization(options: {
chain: string;
userAddress: string;
}): Promise<{
uuid: string;
signature: string;
expiresAt: number;
maxWithdrawAmount: number;
}>
Example
import { parseUnits } from 'viem';
import { VAULT_ABI } from 'bison-sdk-ts';
const auth = await client.getWithdrawAuthorization({
chain: 'base',
userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
});
console.log('Max withdraw amount:', auth.maxWithdrawAmount / 1_000_000, 'USDC');
console.log('Expires at:', new Date(auth.expiresAt * 1000));
// Expected output:
// "Max withdraw amount: 100 USDC"
// "Expires at: 2024-12-31T12:34:56.000Z"
// Use the authorization with the vault contract
const txHash = await walletClient.writeContract({
address: '0x1234567890123456789012345678901234567890',
abi: VAULT_ABI,
functionName: 'withdrawUSDC',
args: [
auth.uuid,
parseUnits('50', 6), // Amount in wei (6 decimals for USDC)
BigInt(auth.expiresAt),
auth.signature,
],
account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
});
console.log('Withdrawal transaction:', txHash);
Error Handling
All deposit and withdrawal methods throw errors when operations fail. Here’s how to handle common errors:
try {
const txHash = await client.executeDepositFlow({
walletClient,
publicClient,
userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
chain: 'base',
amountUusdc: 1_000_000_000, // 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
try {
const txHash = await client.executeWithdrawFlow({
walletClient,
publicClient,
userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
chain: 'base',
amountUusdc: 50_000_000, // 50 USDC
});
console.log('Withdrawn:', txHash);
} catch (error) {
if (error instanceof Error) {
if (error.message.includes('exceeds maximum')) {
// Requested amount is more than available balance
console.error('Insufficient deposited balance');
// Get actual balance
const balance = await client.getDepositedUsdcBalance(userAddress);
const maxAmount = balance.depositedBalanceUusdc / 1_000_000;
console.log(`Maximum withdrawable: ${maxAmount} USDC`);
} else if (error.message.includes('expired')) {
console.error('Authorization expired, retrying...');
// Retry the withdrawal
} else {
console.error('Withdrawal failed:', error.message);
}
}
}
Important Notes
- Withdraw authorizations expire after 30 seconds
- Each authorization can only be used once (replay protection)
- You can only withdraw up to your deposited balance minus any active positions
- After deposits/withdrawals, balances update automatically via blockchain events
- The SDK handles USDC approval automatically for deposits
- All amounts are in µUSDC (6 decimal places: 1 USDC = 1_000_000 µUSDC)
- 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