Skip to main content
This guide covers how to implement deposit and withdrawal flows in your integration using the Blend SDKs.

Prerequisites

Install the Blend SDKs:
pnpm add @blend-money/sdk-core @blend-money/sdk-actions
Initialize the client:
import { BlendClientWithActions } from "@blend-money/sdk-actions";

const client = new BlendClientWithActions({
  baseUrl: "https://api.blend.money",
  userAddress: userWalletAddress,
  integratorId: "your-neobank-v1.0",
}, {
  gardenAppId: "YOUR_GARDEN_APP_ID", // Optional: for Botanix routes
  lifiIntegratorId: "YOUR_LIFI_ID",  // Optional: for LiFi routes
});

Deposits

Same-chain deposit

When the user’s source token is on the same chain as the target strategy:
import { Integrations } from "@blend-money/sdk-types";

// Get available strategies
const strategies = await client.strategy.getAvailableStrategies(Integrations.USX);

// Create deposit plan (same chain)
const plan = await client.actions.deposit(
  { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", symbol: "USDC", decimals: 6, chainId: 8453 },
  strategies[0],
  1_000_000n, // 1 USDC (6 decimals)
  50, // 0.5% slippage
);

// plan.requiredApprovals: ERC-20 approvals to execute first
// plan.requiredTxns: deposit transactions to execute

Cross-chain deposit

When the user’s funds are on a different chain, the SDK automatically selects the right bridge:
// User has USDC on Ethereum, strategy is on Base
const plan = await client.actions.deposit(
  { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", symbol: "USDC", decimals: 6, chainId: 1 },
  strategies[0], // Base strategy
  1_000_000n,
  100, // 1% slippage for cross-chain
);
// SDK uses LiFi for EVM-to-EVM routes, Garden for Botanix routes

Executing the deposit

import { TransactionHandler } from "@blend-money/sdk-actions";

const handler = new TransactionHandler("YOUR_PIMLICO_API_KEY");

const { receipts } = await handler.submitActionPlan(
  walletClient,
  publicClient,
  safeAddress,
  [plan],
);

Withdrawals

Partial withdrawal

import { createPublicClient, http } from 'viem';
import { base } from 'viem/chains';

const publicClient = createPublicClient({
  chain: base,
  transport: http('https://mainnet.base.org'),
});

const [withdrawPlan] = await client.actions.withdraw(
  publicClient,
  strategy,
  1_000_000n, // 1 USDC
  { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", symbol: "USDC", decimals: 6, chainId: 8453 },
  false, // not max withdrawal
  50,
);

Max withdrawal (full exit)

const [withdrawPlan, swapPlanBuilder] = await client.actions.withdraw(
  publicClient,
  strategy,
  0n, // ignored when isMaxWithdraw = true
  outputToken,
  true, // max withdrawal
  100,
);

// If cross-chain swap is needed, build the follow-up plan
if (swapPlanBuilder) {
  const swapPlan = await swapPlanBuilder();
  // Execute swapPlan after the withdrawal completes
}

Querying Balances

// Get user's current balance for a specific strategy
const balance = await client.strategy.getCurrentBalance(strategy);

console.log("Safe:", balance.safeAddress);
console.log("Balance:", balance.formattedBalance);

// Get TVL for your integration
const tvl = await client.strategy.getIntegrationTvl(Integrations.USX);
console.log("Total TVL:", tvl.formattedValue);

Error Handling

Always handle SDK errors gracefully:
import { SdkError } from "@blend-money/sdk-core";

try {
  const plan = await client.actions.deposit(inputToken, strategy, amount, slippage);
} catch (error) {
  if (error instanceof SdkError) {
    // Show user-friendly message
    console.error("Deposit failed:", error.getUserMessage());
    console.error("Error code:", error.code);
  } else {
    console.error("Unexpected error:", error);
  }
}
For production integrations, always use Decimal.js for financial calculations and validate all amounts before submitting transactions. See the SDK best practices for details.

Next Steps

Last modified on February 6, 2026