Skip to main content
Blend’s SDKs include first‑class cross‑chain support. You can request routes directly through the API without integrating bridge/DEX SDKs yourself. The core library ships with adapters for:
  • LiFi: EVM chains (swaps/bridges) - Ethereum, Base, Polygon, Arbitrum, etc.
  • Garden: Botanix and native BTC routes - Bitcoin pegin/pegout operations

How it works

  • Automatic routing: The Actions module selects the appropriate adapter based on origin/destination chain
  • Same-chain optimization: If tokens match and are on the same chain, a direct transfer plan is produced
  • Cross-chain routing: Otherwise, a cross‑chain ActionPlan is returned with approval + initiate calls
  • Multi-hop support: Complex routes are automatically handled (e.g., ETH → USDC → BTC)

Supported Chains

LiFi (EVM-to-EVM)

  • Ethereum (1)
  • Base (8453)
  • Polygon (137)
  • Arbitrum (42161)
  • Optimism (10)
  • And more EVM-compatible chains

Garden (Bitcoin/Botanix)

  • Botanix (3637)
  • Bitcoin (via pegin/pegout)
  • Cross-chain Bitcoin operations

Discover supported cross‑chain assets

You can list all supported chains/tokens from each adapter. Merge them if you want a unified catalog.
import { LiFiAdapter, GardenAdapter } from "@blend-money/sdk-core";

// Initialize adapters
const lifi = new LiFiAdapter({ 
  baseUrl: "https://li.quest", 
  chainTypesFilter: "EVM" 
});

const garden = new GardenAdapter({ 
  baseUrl: "https://api.garden.finance/v2", 
  gardenAppId: "YOUR_GARDEN_APP_ID" 
});

// Get supported assets
const lifiCatalog = await lifi.getTokenCatalog(); // { chains, tokens }
const gardenCatalog = await garden.getTokenCatalog(); // { chains, tokens }

console.log("LiFi chains:", lifiCatalog.chains.length);
console.log("LiFi tokens:", lifiCatalog.tokens.length);
console.log("Garden chains:", gardenCatalog.chains.length);
console.log("Garden tokens:", gardenCatalog.tokens.length);

// Optional: merge/dedupe by chainId+address
const key = (t: { chainId: number; address: `0x${string}` }) => `${t.chainId}:${t.address.toLowerCase()}`;
const tokenMap = new Map<string, any>();
[...lifiCatalog.tokens, ...gardenCatalog.tokens].forEach((t) => tokenMap.set(key(t), t));
const allTokens = [...tokenMap.values()];

console.log("Total unique tokens:", allTokens.length);

Adapter Configuration

LiFi Adapter

import { LiFiAdapter } from "@blend-money/sdk-core";

const lifi = new LiFiAdapter({
  baseUrl: "https://li.quest", // Optional: default LiFi API
  chainTypesFilter: "EVM",     // Optional: filter to EVM chains only
});

Garden Adapter

import { GardenAdapter } from "@blend-money/sdk-core";

const garden = new GardenAdapter({
  baseUrl: "https://api.garden.finance/v2", // Optional: default Garden API
  gardenAppId: "YOUR_GARDEN_APP_ID",        // Optional: for authenticated requests
});

Direct usage with adapters (advanced)

For advanced use cases, you can use the adapters directly to build cross-chain routes.

LiFi Example (EVM to EVM)

import { LiFiAdapter } from "@blend-money/sdk-core";

const lifi = new LiFiAdapter({ 
  baseUrl: "https://li.quest", 
  chainTypesFilter: "EVM" 
});

// Build cross-chain route from Ethereum to Polygon
const plan = await lifi.buildCrossChainRoute({
  fromToken: { 
    address: "0x0000000000000000000000000000000000000000", 
    symbol: "ETH", 
    decimals: 18, 
    chainId: 1 
  },
  toToken: { 
    address: "0x0000000000000000000000000000000000000000", 
    symbol: "ETH", 
    decimals: 18, 
    chainId: 137 
  },
  amount: 1_000_000_000_000_000_000n, // 1 ETH
  fromAddress: "0x1234567890abcdef1234567890abcdef12345678",
  toAddress: "0x1234567890abcdef1234567890abcdef12345678",
  slippageBps: 50, // 0.5% slippage
});

console.log("Required approvals:", plan.requiredApprovals.length);
console.log("Required transactions:", plan.requiredTxns.length);

Garden Example (Bitcoin/Botanix)

import { GardenAdapter } from "@blend-money/sdk-core";

const garden = new GardenAdapter({ 
  baseUrl: "https://api.garden.finance/v2", 
  gardenAppId: "YOUR_GARDEN_APP_ID" 
});

// Build cross-chain route to Botanix
const plan = await garden.buildCrossChainRoute({
  fromToken: { 
    address: "0x0000000000000000000000000000000000000000", 
    symbol: "ETH", 
    decimals: 18, 
    chainId: 1 
  },
  toToken: { 
    address: "0x0000000000000000000000000000000000000000", 
    symbol: "BTC", 
    decimals: 8, 
    chainId: 3637 
  },
  amount: 1_000_000_000_000_000_000n, // 1 ETH
  fromAddress: "0x1234567890abcdef1234567890abcdef12345678",
  toAddress: "0x1234567890abcdef1234567890abcdef12345678",
  slippageBps: 100, // 1% slippage for Bitcoin routes
});

console.log("Garden route plan:", plan);

Error Handling

import { LiFiAdapter, SdkError } from "@blend-money/sdk-core";

const lifi = new LiFiAdapter();

try {
  const plan = await lifi.buildCrossChainRoute({
    fromToken: { address: "0x...", symbol: "USDC", decimals: 6, chainId: 1 },
    toToken: { address: "0x...", symbol: "USDC", decimals: 6, chainId: 8453 },
    amount: 1_000_000n,
    fromAddress: "0x1234567890abcdef1234567890abcdef12345678",
    toAddress: "0x1234567890abcdef1234567890abcdef12345678",
    slippageBps: 50,
  });
} catch (error) {
  if (error instanceof SdkError) {
    console.error("Cross-chain error:", error.getUserMessage());
    console.error("Error code:", error.code);
  } else {
    console.error("Unexpected error:", error);
  }
}

Using Actions for deposits/withdrawals

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

const client = new BlendClientWithActions({
  baseUrl: "https://api.blend.money",
  userAddress: "0x1234567890abcdef1234567890abcdef12345678",
  integratorId: "example-app",
}, { gardenAppId: "YOUR_GARDEN_APP_ID" });

// Cross‑chain deposit: destination is implied by the StrategyConfig (vault chain/token)
const depositPlan = await client.actions.deposit(
  { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", symbol: "USDC", decimals: 6, chainId: 1 },
  { vaultId: "0x0000000000000000000000000000000000000001", chainId: 8453, token: { address: "0x4200000000000000000000000000000000000006", symbol: "USDC", decimals: 6, chainId: 8453 }, name: "USDC Vault", symbol: "vUSDC" },
  1_000_000n,
  50,
);

// Cross‑chain withdraw: origin is implied by the StrategyConfig (vault chain/token)
// outputToken defines the desired asset and its destination chain
const [withdrawPlan, maybeSwapPlan] = await client.actions.withdraw(
  publicClient, // viem client on the vault chain
  { vaultId: "0x0000000000000000000000000000000000000001", chainId: 8453, token: { address: "0x4200000000000000000000000000000000000006", symbol: "USDC", decimals: 6, chainId: 8453 }, name: "USDC Vault", symbol: "vUSDC" },
  1_000_000n,
  { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", symbol: "USDC", decimals: 6, chainId: 1 },
  false,
  50,
);
// If outputToken differs from vault underlying/chain, the second element is a function
// that builds the cross‑chain swap/bridge plan after onchain state is updated.

Execution

ActionPlan returns the approvals and transactions you need. For Safe multisend/UserOps you can use the TransactionHandler helper from @blend-money/sdk-actions or submit the transactions using your own wallet flow.

Notes

  • LiFi adapter filters to EVM chains; Garden is used automatically for Botanix/native BTC routes.
  • You can call getTokenCatalog() on adapters to discover supported chains/tokens.
  • All examples use a generic test address 0x1234567890abcdef1234567890abcdef12345678.