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.

The frontend SDK (@blend-money/fe) handles wallet authentication, deposit/withdrawal quoting, and on-chain execution in the browser.

Quick-start flow

  1. Install @blend-money/fe and viem
  2. Create a BlendSdk instance with your publishable key and paymaster
  3. Sign in with sdk.signIn()
  4. Quote with sdk.quoteDeposit() or sdk.quoteWithdraw()
  5. Execute with sdk.execute(quote, { deriveSigner })

Install

pnpm add @blend-money/fe viem

Configuration

import { BlendSdk, getPimlicoPaymasterUrl } from "@blend-money/fe";

const sdk = new BlendSdk({
  publishableKey: "pk_live_abc123...",
  signMessage: (msg) => walletClient.signMessage({ message: msg }),
  paymasterUrl: getPimlicoPaymasterUrl("pimlico_api_key_here"),
});
FieldTypeRequiredDescription
publishableKeystringYesClient-safe key (pk_live_). Identifies your organization and account type.
signMessage(message: string) => Promise<string>For authWallet signing function for SIWE. Not needed for read-only usage.
paymasterUrlPaymasterUrlResolverYes(chainId: number) => string. Returns the ERC-4337 paymaster RPC URL.
baseUrlstringNoBlend API base URL. Defaults to production.
fiatCurrencystringNoISO 4217 code (e.g. "EUR"). Adds this currency to monetary responses.
timeoutMsnumberNoRequest timeout in milliseconds. Default: 15000.
retriesnumberNoMax retries for 429 and 5xx. Default: 3.

Authentication

signIn

Signs the user in with SIWE. Creates the account and Safe if this is their first time.
const session = await sdk.signIn({
  address: "0x1234...abcd",
  chainId: 8453,
});
Returns an AuthSession:
FieldTypeDescription
addressstringAuthenticated wallet address
accountIdstringBlend account ID
safeAddressstringOn-chain Safe address
chainsDeployednumber[]Chains where the Safe is live
expiresAtstringISO 8601 expiry (1 hour)

signOut

Revokes the JWT server-side and clears local state.
await sdk.signOut();

isSignedIn

Read-only boolean. true if a session is active.
if (sdk.isSignedIn) {
  // authenticated
}

session

Returns the current AuthSession. Throws SdkError with code AUTH_NOT_SIGNED_IN if not authenticated.
const { accountId, safeAddress } = sdk.session;

exportSession / restoreSession

Persist and restore sessions across page reloads.
// Save before unload
const snapshot = sdk.exportSession();
sessionStorage.setItem("blend", JSON.stringify(snapshot));

// Restore on next load
const saved = JSON.parse(sessionStorage.getItem("blend")!);
sdk.restoreSession(saved);
Use sessionStorage, not localStorage. Clear the session when the wallet disconnects or the address changes.

Quoting

quoteDeposit

Quotes a deposit. Creates a session automatically if one doesn’t exist.
import { parseAmount } from "@blend-money/fe";

const quote = await sdk.quoteDeposit({
  chainId: 8453,
  tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  amount: parseAmount("100", 6),
  externalRef: "order-123",
});
ParameterTypeRequiredDescription
chainIdnumberYesOrigin chain ID
tokenAddressstringYesToken contract on the origin chain
amountstringYesSmallest unit, non-negative integer string
externalRefstringNoYour reconciliation reference
forceResetbooleanNoCancel existing session first. Default: false.
Returns a DepositQuote:
FieldTypeDescription
type"DEPOSIT"Quote type
intentIdstringSession ID
originChainIdnumberChain the user sends from
destinationChainIdnumberChain where funds arrive
inputobjectsymbol, amount, amountUsd the user sends
outputobjectsymbol, amount, amountUsd arriving in the vault
fees.totalUsdstringTotal fees in USD
estimatedSecondsnumberEstimated settlement time
expiresAtstringWhen this quote expires

quoteWithdraw

Quotes a withdrawal. Blend picks which chains to pull funds from.
const quote = await sdk.quoteWithdraw({
  destinationChainId: 8453,
  amount: parseAmount("50", 6),
});
For a full exit, set isMaxWithdraw: true and amount: "0":
const quote = await sdk.quoteWithdraw({
  destinationChainId: 8453,
  amount: "0",
  isMaxWithdraw: true,
});
Returns a WithdrawQuote:
FieldTypeDescription
type"WITHDRAW"Quote type
intentIdstringSession ID
destinationChainIdnumberChain where funds arrive
totalAmountstringTotal withdrawal in loan token smallest units
totalFeesUsdstringTotal fees in USD
estimatedSecondsnumberEstimated settlement time
sourceChainCountnumberNumber of source chains
sourceChainIdsnumber[]Which chains funds are pulled from
expiresAtstringWhen this quote expires

Execution

execute

Locks the quote, submits transactions through the user’s Safe, and polls until settlement.
const result = await sdk.execute(quote, {
  signerAddress: "0x1234...abcd",
  deriveSigner: async (chainId) => ({
    signer: getWalletClient({ chainId }),
    publicClient: getPublicClient({ chainId }),
  }),
  onStatusChange: (status) => console.log(status),
});
ParameterTypeRequiredDescription
signerAddressstringYesEOA hex address. Must match the deriveSigner output.
deriveSigner(chainId: number) => Promise<DeriveSignerResult>YesReturns a viem WalletClient and PublicClient for the target chain
isContractSignerbooleanNoSet true for smart wallets (e.g. Coinbase). Default: false.
onStatusChange(status: ExecuteStatus) => voidNoCalled on each status transition
pollIntervalMsnumberNoPolling interval. Default: 3000.
pollTimeoutMsnumberNoMax polling time. Default: 300000 (5 min).
deriveSigner is called once per action plan. For deposits, that means once. For withdrawals, once per source chain. DeriveSignerResult:
FieldTypeDescription
signerWalletClientviem WalletClient for the target chain
publicClientPublicClientviem PublicClient for the target chain
ExecuteResult:
FieldTypeDescription
status"settled" | "failed" | "cancelled"Terminal status
txHashesArray<{ hash: string; chainId: number }>Submitted transaction hashes
settledAtstring | nullISO 8601 settlement time
errorstring | nullError message if failed

Discovery

These methods are available on sdk.discover. Deposit chains work without auth. Deposit tokens include wallet balances when signed in.
const chains = await sdk.discover.depositChains();
const tokens = await sdk.discover.depositTokens(8453);
const destinations = await sdk.discover.withdrawDestinations();
const yieldData = await sdk.discover.yield();
See SDK Reference for response shapes.

Account data

These methods are available on sdk.account after sign-in.
const balance = await sdk.account.balance();
const history = await sdk.account.balanceHistory();
const positions = await sdk.account.positions();
const returns = await sdk.account.returns();
See SDK Reference for response shapes.

Error handling

Every SDK method can throw SdkError. Catch it to get structured error info.
import { SdkError } from "@blend-money/fe";

try {
  const quote = await sdk.quoteDeposit({ /* ... */ });
} catch (error) {
  if (error instanceof SdkError) {
    console.error(error.code);            // "INTENT_EXPIRED"
    console.error(error.status);          // 410
    console.error(error.getUserMessage()); // user-friendly text
    if (error.isRetryable()) { /* retry */ }
  }
}
See SDK Reference for the full error codes table.

What to watch out for

Don’t create a new session to update prices. Call quoteDeposit() again on the open session. It re-quotes with fresh prices. Use forceReset: true only when switching tokens or chains. Don’t store sessions in localStorage. Use sessionStorage and clear it when the wallet disconnects. Don’t skip the onStatusChange callback. Show status updates in your UI so users know what’s happening during execution. Don’t ignore isContractSigner. If your users connect smart wallets (Coinbase Wallet, Safe), set it to true or signing will fail.

Deposits & Withdrawals

Full deposit and withdrawal flows with cross-chain routing.

SDK Reference

Auth, accounts, balances, error codes, and types.
Last modified on May 7, 2026