Breeze

Quickstart

Install the TypeScript SDK, read yield data, and send a deposit with Solana Kit

Install

For typed API access:

npm install @solana/breeze-sdk

For the recommended trusted-backend Solana Kit transaction integration:

npm install @solana/breeze-sdk @solana/kit \
  @solana/kit-plugin-rpc @solana/kit-plugin-signer

The dependency-free root import supports Node.js 18 or newer. The optional @solana/breeze-sdk/kit entry follows Solana Kit 7's Node.js 20.18 or newer requirement.

Configure

Create an API key, then store it in your server environment.

Keep API keys in trusted server-side configuration. Never expose them in client-side code, browser bundles, mobile applications, logs, or public repositories.

import { BreezeSDK } from '@solana/breeze-sdk';

const apiKey = process.env.BREEZE_API_KEY;
if (!apiKey) throw new Error('BREEZE_API_KEY is required');

const sdk = new BreezeSDK({ apiKey });

The production API URL and a 30-second request timeout are the defaults.

Read yield data

const userYield = await sdk.getUserYield({
  userId: 'USER_WALLET_ADDRESS',
});

for (const position of userYield.data) {
  console.log(position.fund_name, position.yield_earned, position.apy);
}

The response includes a data array and pagination meta. Response fields preserve the API's snake_case names; position values and earned yield use the token's smallest units, while APY is expressed in percentage points.

Send from a trusted backend with Solana Kit

Configure a Kit client with a server-managed signer and mainnet RPC before installing the Breeze plugin. serverSigner can come from a custody provider, key-management service, or another signer that runs in your trusted environment. For the direct-send flow below, it must implement Kit's TransactionPartialSigner (signTransactions) or TransactionModifyingSigner (modifyAndSignTransactions) capability. A signer that can only send transactions is not sufficient.

import { createClient } from '@solana/kit';
import { solanaMainnetRpc } from '@solana/kit-plugin-rpc';
import { signer } from '@solana/kit-plugin-signer';
import { breeze } from '@solana/breeze-sdk/kit';
import { getBackendSigner } from './custody-signer';

const apiKey = process.env.BREEZE_API_KEY;
const rpcUrl = process.env.SOLANA_RPC_URL;
if (!apiKey || !rpcUrl) {
  throw new Error('BREEZE_API_KEY and SOLANA_RPC_URL are required');
}

const backendSigner = await getBackendSigner();
const client = createClient()
  .use(signer(backendSigner))
  .use(solanaMainnetRpc({ rpcUrl }))
  .use(breeze({ apiKey }));

const result = await client.breeze.instructions
  .deposit({
    strategyId: 'YOUR_STRATEGY_ID',
    baseAsset: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
    amount: 1_000_000,
  })
  .sendTransaction();

console.log('Confirmed transaction signature:', result.context.signature);

The plugin derives userKey and payerKey from the installed identity and fee payer, fetches and validates Breeze instructions, retrieves the required address lookup table, and converts eligible accounts to lookup-table references. The installed planner then sizes and builds a v0 transaction before the executor signs, submits, and confirms it. amount uses raw token units; 1_000_000 is one USDC.

Mainnet transaction

Breeze is mainnet-only. instructions.deposit(...).sendTransaction(), instructions.withdraw(...), and instructions.closeUserAccount(...) sign and submit real transactions that can move funds. Validate the strategy, mint, amount, signer addresses, and RPC configuration before calling them.

instructions.withdraw(...) uses the same lookup-table-backed version-0 flow. instructions.closeUserAccount(...) uses the same fluent terminals but skips lookup-table resolution and keeps the installed planner's transaction version. Finish any builder with .planTransaction() instead of .sendTransaction() when you need to inspect the transaction message before sending it.

When identity and fee payer use different signers, install both roles explicitly. Each signer required by the transaction must implement TransactionPartialSigner or TransactionModifyingSigner for direct sending:

import { identity, payer } from '@solana/kit-plugin-signer';

const client = createClient()
  .use(payer(feePayerSigner))
  .use(identity(identitySigner))
  .use(solanaMainnetRpc({ rpcUrl }))
  .use(breeze({ apiKey }));

Hand off to a browser wallet

Do not install the Breeze plugin or place a Breeze API key in browser code. When the user signs with a browser wallet, keep the root SDK on your backend and return only the base64-encoded unsigned transaction:

// Trusted backend
const depositTransaction = await sdk.createDepositTransaction({
  strategyId: 'YOUR_STRATEGY_ID',
  baseAsset: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amount: 1_000_000,
  userKey: 'USER_WALLET_ADDRESS',
  payerKey: 'USER_WALLET_ADDRESS',
});

if (typeof depositTransaction !== 'string') {
  throw new Error(depositTransaction.message);
}

Before creating it, validate the requested strategy, mint, amount, user address, and payer address against values your application permits. Return the serialized transaction—not the API key—to the browser. The connected wallet can then deserialize it, show it to the user for review, sign it, submit it through the application's Solana RPC, and wait for confirmation.

The direct REST POST /deposit/tx and POST /withdraw/tx endpoints support the same backend-to-browser handoff. Never send a seed phrase or private key to Breeze or place one in application code.

Kit plugin reference

Setup

Install identity, payer, RPC, transaction-planning, and transaction-sending capabilities before breeze(). Every required direct-send signer must implement TransactionPartialSigner or TransactionModifyingSigner; a sending-only signer is insufficient. For deposits and withdrawals, Breeze first fetches the required lookup table and converts eligible instruction accounts to lookup-table references; the transaction planner must then build a version-0 message. Close-account planning skips lookup-table resolution.

breeze(config) accepts:

FieldTypeRequiredDefault
apiKeystringYes
baseUrlstringNohttps://api.breeze.baby/
timeoutnumber in millisecondsNo30000

The installed client.breeze namespace provides these read methods:

MethodResult
getUserYield(options)Paginated yield records
getUserBalances(options)Paginated wallet balances
getBreezeBalances(options)Strategy-scoped Breeze balances
getStrategyInfo(strategyId)Supported assets and current APY
getHealth()API health response
updateApiKey(apiKey)Replaces the key used by later Breeze requests

Transaction methods

Each client.breeze.instructions.<op>(options) builder is finished with a terminal call: .planTransaction(config?) builds the message without submitting, while .sendTransaction(config?) plans, signs, submits, and confirms. Both terminals accept an optional { abortSignal }.

BuilderTerminal calls
instructions.deposit(options).planTransaction(config?) / .sendTransaction(config?)
instructions.withdraw(options).planTransaction(config?) / .sendTransaction(config?)
instructions.closeUserAccount(options).planTransaction(config?) / .sendTransaction(config?)

Deposit and withdrawal options require strategyId, the baseAsset mint, and exactly one amount selection: amount in the asset's smallest unit or all: true. Both accept an optional userTokenAccount. Withdrawal also accepts createWsolAta, unwrapWsolAta, detectWsolAta, and excludeFees.

Close-account options require either a resolved userAccount or the strategyId + mint pair used with the installed identity. They also accept optional fundsRecipient and userTokenAccount overrides.

Each terminal accepts an optional { abortSignal } argument. API requests continue to use the timeout configured in breeze(config); transaction planning, lookup-table fetching, and sending use the installed Kit capabilities and their configuration. Deposit and withdrawal require the planner to produce version 0 because their lookup-table compression cannot be represented by legacy or version-1 messages. Close-account uses the planner's selected transaction version.

Errors

API failures remain BreezeApiError. Only Breeze-specific instruction and precondition failures throw BreezeKitError from @solana/breeze-sdk/kit:

CodeMeaning
INVALID_SERIALIZED_INSTRUCTIONThe API instruction payload cannot be safely converted to Kit.
MISSING_ADDRESS_LOOKUP_TABLEDeposit or withdrawal instructions omitted the required lookup table.
MISSING_TRANSACTION_SIGNERNo installed identity or payer signer matches a required signing account.
UNSUPPORTED_TRANSACTION_VERSIONThe planner produced a non-version-0 deposit or withdrawal, which requires version 0 for lookup-table compression.

Invalid addresses, lookup-table RPC failures, and failures from transaction planning, signing, sending, or confirmation remain native Kit or RPC errors. Inspect and handle those errors using the installed Kit capabilities rather than matching them as BreezeKitError.

Low-level exports

The @solana/breeze-sdk/kit entry also exports these primitives for custom Kit composition:

ExportPurpose
breeze(config)Installs the typed client.breeze namespace.
getKitInstruction(serializedInstruction, signers)Validates a Breeze byte-array instruction, converts it to Kit, and attaches matching TransactionSigner objects.
BreezeKitErrorExposes Breeze-specific conversion and planning precondition failures through its typed code.

getKitInstruction does not fetch lookup tables, plan, sign, or submit a transaction. It throws BreezeKitError when the instruction is malformed or a required signer is absent. Prefer the fluent builders unless you are assembling a custom Kit instruction plan.

The subpath also exports its plugin, client, builder, terminal, configuration, error-code, and operation-option types as named TypeScript exports.

Go deeper

On this page