Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.blend.money/llms.txt

Use this file to discover all available pages before exploring further.

Quote and execute deposits and withdrawals. Cross-chain routing is handled automatically.

Deposits

Discover chains and tokens

Find which chains and tokens are available for deposits.
const chains = await sdk.discover.depositChains();
const tokens = await sdk.discover.depositTokens(8453);

const usdc = tokens.find((t) => t.symbol === "USDC")!;
depositTokens includes wallet balances when the user is signed in.

Quoting a deposit

import { parseAmount } from "@blend-money/fe";

const quote = await sdk.quoteDeposit({
  chainId: 8453,
  tokenAddress: usdc.address,
  amount: parseAmount("100", usdc.decimals),
  externalRef: "order-123",
});
The frontend SDK uses tokenAddress. It creates a session automatically.
The deposit quote tells you what the user sends and receives:
FieldTypeDescription
intentIdstringSession ID
inputobjectSymbol, amount, and USD value the user sends
outputobjectSymbol, amount, and USD value arriving in the vault
fees.totalUsdstringTotal fees in USD
estimatedSecondsnumberEstimated time to settlement
expiresAtstringWhen this quote expires

Executing a deposit

const result = await sdk.execute(quote, {
  signerAddress: walletClient.account.address,
  deriveSigner: async (chainId) => ({
    signer: getWalletClient({ chainId }),
    publicClient: getPublicClient({ chainId }),
  }),
  onStatusChange: (status) => console.log(status),
});

Re-quoting the same session

Call quoteDeposit() again on an open session to update prices. The session stays the same. Don’t create a new session for price refreshes.
// Same session, fresh prices
const freshQuote = await sdk.quoteDeposit({
  chainId: 8453,
  tokenAddress: usdc.address,
  amount: parseAmount("200", usdc.decimals),
});
To switch tokens or chains, pass forceReset: true. This cancels the existing session and creates a new one.

Withdrawals

Discover destinations

Find which chains accept withdrawals and which loan token the user will receive.
const destinations = await sdk.discover.withdrawDestinations();
// [{ chainId: 8453, name: "Base", loanTokenAddress: "0x..." }]

Quoting a withdrawal

const quote = await sdk.quoteWithdraw({
  destinationChainId: 8453,
  amount: parseAmount("50", 6),
});
For a full exit:
const quote = await sdk.quoteWithdraw({
  destinationChainId: 8453,
  amount: "0",
  isMaxWithdraw: true,
});
The withdrawal quote tells you where funds are pulled from:
FieldTypeDescription
intentIdstringSession ID
totalAmountstringTotal withdrawal in loan token smallest units
totalFeesUsdstringTotal fees in USD
estimatedSecondsnumberEstimated time to settlement
sourceChainIdsnumber[]Which chains Blend pulls funds from
sourceChainCountnumberNumber of source chains

Executing a withdrawal

Withdrawals may span multiple chains. The SDK handles multi-chain signing automatically.
const result = await sdk.execute(quote, {
  signerAddress: walletClient.account.address,
  deriveSigner: async (chainId) => ({
    signer: getWalletClient({ chainId }),
    publicClient: getPublicClient({ chainId }),
  }),
});
deriveSigner is called once per source chain. Handle wallet chain-switching inside the callback.

Flow plan conflicts

If a rebalance is in progress, withdrawal quoting returns a 409 with error code FLOWPLAN_CONFLICT. Show a “try again shortly” message to your user. Don’t auto-retry - wait for the rebalance to finish.

Cross-chain

Blend routes deposits and withdrawals across chains automatically using the Relay bridge.

Bridge adapters

AdapterProtocolWhen it’s used
AcrossAcross ProtocolPrimary bridge for cross-chain transfers. Fast finality.
CCTPCircle CCTPNative USDC bridging between supported chains. No wrapped tokens.
The SDK picks the best adapter based on the token and route. You don’t need to choose.

Safe address determinism

Safe addresses are deterministic. The same wallet address produces the same Safe address on every chain. This means cross-chain deposits route to the correct Safe automatically, even if the Safe hasn’t been deployed on the destination chain yet.

liquidityReset as delegateCall

During withdrawals, the liquidityReset step flushes vault positions back to the loan token. This step runs as a delegateCall through the Safe (the only step that does). The isDelegateCall: true flag in the action plan’s transaction marks it.

Testing

Test these scenarios before going to production:
ScenarioHow to testExpected result
Same-chain depositDeposit USDC on Base to a Base-native vaultSingle action plan, fast settlement
Cross-chain depositDeposit USDC on Ethereum to a Base vaultBridge routing, longer settlement
Partial withdrawalWithdraw 50% of balanceFunds pulled from fewest chains possible
Full withdrawalisMaxWithdraw: trueAll positions closed across all chains
Quote expirationWait past expiresAtRe-quote required, same session ID
Flow plan conflictWithdraw during an active rebalance409 with FLOWPLAN_CONFLICT

What to watch out for

Don’t use forceReset: true to update prices. Call quoteDeposit() or quoteWithdraw() on the existing session. forceReset cancels the session and starts fresh - use it only when switching tokens or chains. Don’t auto-retry on FLOWPLAN_CONFLICT. The rebalance needs to finish first. Show a message and let the user try again. Don’t assume single-chain for withdrawals. Funds may be spread across chains. Your deriveSigner (frontend) or submitActionPlan (server) callback must handle multiple chains. Don’t skip the amount field when using isMaxWithdraw: true. Pass "0" as the amount.

Frontend SDK

Frontend configuration, auth, and execution details.

Server SDK

Server configuration, account management, and session lifecycle.

SDK Reference

Error codes, types, and utility functions.

Best Practices

Production patterns for session management and error recovery.
Last modified on May 7, 2026