npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@solana/breeze-sdk

v2.1.0

Published

TypeScript SDK for Breeze API reads and Solana transaction construction, with an optional Solana Kit client plugin.

Readme

@solana/breeze-sdk

TypeScript SDK for the Breeze API — user yield tracking, balance queries, and deposit, withdraw, and close-account transaction building on Solana.

  • Dependency-free core SDK — uses the built-in fetch.
  • Optional trusted-backend Solana Kit plugin for planning, signing, sending, and confirming Breeze transactions.
  • Dual ESM + CommonJS builds with bundled type definitions.
  • Fully typed requests and responses.

Installation

npm install @solana/breeze-sdk

The root entry requires Node.js 18+ (for global fetch). It can be bundled for modern browsers, but authenticated Breeze API calls belong on a trusted backend so the API key is never shipped to users.

For the optional Solana Kit transaction integration:

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

The @solana/breeze-sdk/kit entry follows Kit 7's Node.js requirement (20.18+). The dependency-free root entry remains compatible with Node.js 18+.

Quick start

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,
  baseUrl: 'https://api.breeze.baby/', // optional (this is the default)
  timeout: 30000,                       // optional, milliseconds (default: 30000)
});

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

for (const entry of userYield.data) {
  console.log(`${entry.fund_name}: earned ${entry.yield_earned} (APY ${entry.apy})`);
}

Choose a transaction integration

Keep the Breeze API key on a trusted server. The two supported transaction patterns have different trust boundaries:

  • Trusted backend or custodial signer: install the Kit plugin and finish a client.breeze.instructions.<op>() builder with .planTransaction() or .sendTransaction(). The same process can access the Breeze API key and an HSM, custody adapter, or other backend signer.
  • Browser or mobile wallet: have your backend call the core SDK instruction methods, then return the unsigned instruction payload to the wallet application. The browser builds and presents the transaction for approval; neither the Breeze API key nor signing-key material belongs in browser code.

Trusted backend: Solana Kit

Install the Breeze plugin after the signer and RPC plugins. When one backend signer is both the transaction identity and fee payer, Kit's signer() plugin installs both capabilities:

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';

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');
}

// With solanaMainnetRpc, use a Kit TransactionPartialSigner or
// TransactionModifyingSigner supplied by trusted key management.
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: 100, // asset's smallest unit
  })
  .sendTransaction();

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

instructions.deposit(...).sendTransaction() derives userKey and payerKey, fetches and validates Breeze instructions, fetches the required lookup table, converts eligible account metas to lookup-table metas, lets the planner size and build a version-0 message, then delegates signing, submission, and confirmation to the installed executor. instructions.withdraw(...) follows the same flow; close-account planning does not require a lookup table.

With the official solanaMainnetRpc executor, identity and payer must implement either Kit's TransactionPartialSigner (signTransactions) or TransactionModifyingSigner (modifyAndSignTransactions). A sending-only TransactionSigner is insufficient because the executor signs the planned message with signTransactionMessageWithSigners. A legacy @solana/web3.js Keypair or wallet-adapter object is not accepted directly; adapt it to a compatible Kit signer first. The generic Breeze plugin can also compose with a custom planner/executor that supports its installed signer capabilities. When fee payer and transaction identity differ, install them explicitly:

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

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

The plugin matches required signer account metas by address against the installed identity and payer. It fails before submission when a required signer is unavailable.

Browser wallet: backend instruction handoff

The browser sends public addresses and the requested operation to your backend. The backend authenticates the request, calls Breeze with its server-side API key, and returns the unsigned instruction response:

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 });
const instructionResponse = await sdk.getDepositInstructions({
  strategyId,
  baseAsset,
  amount,
  userKey: walletAddress,
  payerKey: walletAddress,
});

// Return only the unsigned instruction response to the wallet application.
return instructionResponse;

The wallet application converts the byte-array instruction payload, resolves the returned address lookup table, builds a version-0 transaction, and asks the connected wallet to review and sign it. The prebuilt createDepositTransaction/createWithdrawTransaction methods are also available when a serialized unsigned transaction is a better handoff format.

Configuration

new BreezeSDK(config) accepts a BreezeSDKConfig:

| Field | Type | Required | Default | |---|---|---|---| | apiKey | string | ✅ | — | | baseUrl | string | | https://api.breeze.baby/ | | timeout | number (ms) | | 30000 |

breeze(config) accepts the same fields. API request timeouts use timeout; the optional { abortSignal } argument on Kit .planTransaction() and .sendTransaction() terminals is forwarded to lookup-table fetching, planning, sending, and confirmation.

client.breeze methods

| Method | Options | Result | |---|---|---| | getUserYield | { userId, fundId?, page?, limit? } | Paginated yield records | | getUserBalances | { userId, asset?, sortBy?, sortOrder?, page?, limit? } | Paginated wallet balances | | getBreezeBalances | { userId, strategyId, asset?, sortBy?, sortOrder?, page?, limit? } | Strategy-scoped balances | | getStrategyInfo | strategyId | Strategy assets and APY data | | getHealth | none | API health response | | updateApiKey | apiKey | Replaces the API key used by later requests | | instructions.deposit(options) | { strategyId, baseAsset, userTokenAccount?, amount } or { ..., all: true } | Pending plan → .planTransaction(config?) / .sendTransaction(config?) | | instructions.withdraw(options) | Deposit fields plus createWsolAta?, unwrapWsolAta?, detectWsolAta?, excludeFees? | Pending plan → .planTransaction(config?) / .sendTransaction(config?) | | instructions.closeUserAccount(options) | { userAccount, fundsRecipient?, userTokenAccount? } or { strategyId, mint, fundsRecipient?, userTokenAccount? } | Pending plan → .planTransaction(config?) / .sendTransaction(config?) |

Each instructions.<op>() builder resolves lazily on the terminal call: .planTransaction(config?) returns the planned Kit message and .sendTransaction(config?) returns Kit's confirmed transaction-plan result; read its signature from result.context.signature. Both terminals accept an optional { abortSignal }. amount is denominated in the asset's smallest unit and is mutually exclusive with all: true. Identity and payer addresses are always derived from the Kit client. For seed-based account closure, the identity address is also used as userPubkey. Deposit and withdrawal enforce a version-0 message because their address lookup-table compression is not compatible with legacy or version-1 messages; close-account uses the planner's selected version.

API reference

Reads

getUserYield(options) — paginated yield data.

const res = await sdk.getUserYield({
  userId: '7EcSQsLNbkorQr3igFzfEwFJoPEUgB3NfmDTAigEcoSY',
  fundId: '8pfa...',   // optional filter
  page: 1,             // optional
  limit: 10,           // optional
});
// res.data: UserYieldEntry[]   res.meta: PaginationMeta

getUserBalances(options) — token balances with optional filtering/sorting.

const res = await sdk.getUserBalances({
  userId: '7EcSQsLNbkorQr3igFzfEwFJoPEUgB3NfmDTAigEcoSY',
  asset: 'USDC',       // optional
  sortBy: 'balance',   // optional
  sortOrder: 'desc',   // optional
  page: 1,             // optional
  limit: 10,           // optional
});
// Each entry has `yield_balance: YieldBalance | null` (null when there is no yield position).

getBreezeBalances(options) — strategy-scoped balances (strategyId required).

const res = await sdk.getBreezeBalances({
  userId: 'your-user-id',
  strategyId: 'your-strategy-id', // required
  asset: 'USDC',                  // optional
  sortBy: 'balance',              // optional
  sortOrder: 'desc',              // optional
  page: 1,                        // optional
  limit: 10,                      // optional
});

getStrategyInfo(strategyId) — supported assets and APY data.

const info = await sdk.getStrategyInfo('your-strategy-id');
console.log(info.strategy_name, info.apy, info.apy_per_asset);

Transactions

createDepositTransaction and createWithdrawTransaction resolve to a base64-encoded serialized transaction string. Identify the position with strategyId + baseAsset (mint address). Failed requests throw BreezeApiError; fundId is retained in the TypeScript type for compatibility but is rejected by the current API. For new signing and sending integrations, prefer the Kit plugin only in a trusted signing service. These methods remain available for browser-wallet and other unsigned-transaction handoffs.

const depositTx = await sdk.createDepositTransaction({
  strategyId: 'your-strategy-id',
  baseAsset: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // token mint (e.g. USDC)
  amount: 100,
  userKey: '7EcSQsLNbkorQr3igFzfEwFJoPEUgB3NfmDTAigEcoSY',
  payerKey: '...', // optional
});

const withdrawTx = await sdk.createWithdrawTransaction({
  strategyId: 'your-strategy-id',
  baseAsset: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amount: 50,
  userKey: '7EcSQsLNbkorQr3igFzfEwFJoPEUgB3NfmDTAigEcoSY',
  // withdraw-only options: createWsolAta, unwrapWsolAta, detectWsolAta, excludeFees
});

Instructions

Prefer instructions when composing your own transaction.

const deposit = await sdk.getDepositInstructions({ /* same options as deposit tx */ });
// deposit.deposit_instructions: SerializedInstruction[]   deposit.lookup_table?: string

const withdraw = await sdk.getWithdrawInstructions({ /* same options as withdraw tx */ });
// withdraw.withdraw_instructions: SerializedInstruction[]  withdraw.lookup_table?: string

Close user account

Identify the account with userPubkey + strategyId + mint (or a resolved userAccount).

const closeTx = await sdk.createCloseUserAccountTransaction({
  userPubkey: 'your-user-pubkey',
  strategyId: 'your-strategy-id',
  mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  payer: '...',           // optional
  fundsRecipient: '...',  // optional
  userTokenAccount: '...',// optional
});

const closeIx = await sdk.getCloseUserAccountInstructions({
  userPubkey: 'your-user-pubkey',
  strategyId: 'your-strategy-id',
  mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
});
// closeIx.close_user_fund_instructions: SerializedInstruction[]

Misc

await sdk.getHealth();          // "OK"
sdk.updateApiKey(rotatedApiKey); // rotate to a value loaded from trusted config
sdk.getApiClient();             // underlying ApiClient (advanced use)

Planning before sending

Finish an instructions.deposit, instructions.withdraw, or instructions.closeUserAccount builder with .planTransaction() when an application needs to inspect or further compose the Kit transaction message:

const message = await client.breeze.instructions
  .deposit({
    strategyId: 'your-strategy-id',
    baseAsset: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
    amount: 100,
  })
  .planTransaction();

// The message contains live signer objects plus Breeze lookup-table references.
// Keep it in this trusted process and send through the same Kit client.
const result = await client.sendTransaction(message);
console.log('Confirmed signature:', result.context.signature);

Planned messages are not a browser-wallet serialization format: they retain the installed backend signer objects. Use the backend instruction handoff above for user-controlled wallets.

The RPC plugin controls compute estimation, priority fees, preflight, and confirmation. Configure those concerns in solanaMainnetRpc({ transactionConfig, ... }); the Breeze plugin does not add a competing transaction policy.

Error handling

Every failed request throws a BreezeApiError:

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

try {
  await sdk.getStrategyInfo('bad-id');
} catch (err) {
  if (err instanceof BreezeApiError) {
    console.error(err.message, err.status, err.code, err.response);
  }
}

| Field | Type | Notes | |---|---|---| | message | string | Human-readable message (from the API when available). | | status | number \| undefined | HTTP status code. | | code | string \| undefined | TIMEOUT, NETWORK_ERROR, PARSE_ERROR, or an API code. | | response | unknown | Parsed error body, or raw text when it was not JSON. |

Breeze-specific instruction and precondition failures throw BreezeKitError from @solana/breeze-sdk/kit with one of four codes:

| Code | Meaning | |---|---| | INVALID_SERIALIZED_INSTRUCTION | The API instruction did not contain valid byte arrays, account metadata, or an address. | | MISSING_ADDRESS_LOOKUP_TABLE | A deposit or withdrawal instruction response omitted its required lookup table. | | MISSING_TRANSACTION_SIGNER | An account meta requires a signer whose address does not match the installed identity or payer. | | UNSUPPORTED_TRANSACTION_VERSION | The configured planner produced a non-version-0 message for a deposit or withdrawal, which requires version 0 for lookup-table compression. |

API failures still surface as BreezeApiError. Errors raised by Kit's address parsing, lookup-table RPC, transaction planner, sender, or confirmation logic remain their native Kit/RPC errors; the Breeze plugin does not wrap them.

Low-level Kit exports

The @solana/breeze-sdk/kit entry also exposes the primitives behind the fluent client for custom Kit composition:

| Export | Purpose | |---|---| | breeze(config) | Installs the typed client.breeze namespace. | | getKitInstruction(serializedInstruction, signers) | Validates a Breeze byte-array instruction, converts it to a Kit instruction, and attaches matching TransactionSigner objects. | | BreezeKitError | Identifies 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 wire instruction is malformed or a required signer is absent. Prefer the fluent builders unless you are assembling a custom Kit instruction plan.

Named Kit types include BreezeKitErrorCode, BreezePluginConfig, BreezePluginRequirements, BreezeKitClient, BreezeInstructionBuilders, BreezeInstructionPlan, BreezeTransactionConfig, and the deposit, withdrawal, and close-account option types.

Low-level API

The ApiClient and each endpoint function are exported for advanced use. The client holds the API key and attaches the x-api-key header automatically; every endpoint function takes (client, options):

import { ApiClient, getUserYield, getTransactionForDeposit } from '@solana/breeze-sdk';

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

const client = new ApiClient({
  apiKey,
  baseUrl: 'https://api.breeze.baby/', // optional
});

const userYield = await getUserYield(client, { userId: 'user_id' });

const depositTx = await getTransactionForDeposit(client, {
  strategyId: 'strategy_id',
  baseAsset: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amount: 100,
  userKey: 'user_key',
});

Exported functions: getUserYield, getUserBalances, getBreezeBalances, getStrategyInfo, getTransactionForDeposit, getInstructionsForDeposit, getTransactionForWithdraw, getInstructionsForWithdraw, getTransactionForCloseUserAccount, getInstructionsForCloseUserAccount, getHealth.

Types

All request options and responses are exported as named types, e.g. UserYield, UserBalances, BreezeBalancesResponse, BreezeBalance, StrategyInfo, DepositOptions, WithdrawOptions, CloseUserAccountOptions, InstructionsForDeposit, InstructionsForWithdraw, SerializedTransaction, and SerializedInstruction. SerializedInstructionData documents the API's byte-array program_id, account metadata, and instruction data, while SerializedInstruction retains its legacy opaque-record contract; the Kit entry requires, validates, and converts the wire fields before planning.

CloseUserAccountOptions requires exactly one identity form: userAccount, or the complete userPubkey + strategyId + mint tuple used to derive it.

API endpoints

| Method | Endpoint | SDK method | |---|---|---| | GET | /user-yield/{user_id} | getUserYield | | GET | /user-balances/{user_id} | getUserBalances | | GET | /breeze-balances/{user_id} | getBreezeBalances | | GET | /strategy-info/{strategy_id} | getStrategyInfo | | POST | /deposit/tx | createDepositTransaction | | POST | /deposit/ix | getDepositInstructions | | POST | /withdraw/tx | createWithdrawTransaction | | POST | /withdraw/ix | getWithdrawInstructions | | POST | /close-user-account/tx | createCloseUserAccountTransaction | | POST | /close-user-account/ix | getCloseUserAccountInstructions | | GET | /health | getHealth |

Development

This package lives in an npm-workspaces monorepo; run commands from projects/sdk (the npm workspace root), from packages/sdk, or with --workspace @solana/breeze-sdk.

npm install          # install all workspaces
npm run build        # bundle ESM + CJS + type declarations (tsup)
npm run typecheck    # tsc --noEmit
npm run typecheck:examples # compile examples without running them
npm run typecheck:integration # compile live tests without calling the API
npm run test         # offline unit tests
npm run verify:publish   # all typechecks + unit tests + build (also runs before publish)
npm run test:integration  # live tests against a real API (see below)

Project structure

src/
├── index.ts        # public exports
├── client.ts       # ApiClient + BreezeApiError
├── sdk.ts          # BreezeSDK class
├── types.ts        # request/response types
├── kit/            # optional Kit plugin, adapter, errors, and tests
└── endpoints/      # one module per endpoint group

Tests

  • Unit tests (src/**/*.test.ts) run fully offline with a mocked fetch.
  • Integration tests (tests-integration/) hit a real API — configure the documented environment variables, target guard, and fixture data in tests-integration/README.md first. Run npm run typecheck:integration to compile them without making API calls.

Kit instruction conversion, signer matching, lookup-table planning, and sending are covered by offline tests. The suite does not submit a live mainnet Kit transaction; do not treat mocked executor coverage as end-to-end confirmation.

Migrating from @solana/breeze-sdk 1.x

Version 2.0.0 makes the close-account identity contract explicit at compile time. CloseUserAccountOptions now accepts exactly one of:

{ userAccount: 'resolved-user-fund-account' }

// or
{
  userPubkey: 'user-wallet',
  strategyId: 'strategy-id',
  mint: 'asset-mint',
}

Remove empty, partial, or mixed identity objects before upgrading. The optional payer, fundsRecipient, and userTokenAccount overrides remain available with either identity form.

Migrating from @breezebaby/breeze-sdk v2

The new @solana/breeze-sdk package starts at 1.0.0. The BreezeSDK class API is unchanged from the legacy package except for one rename; the remaining breaking changes are in the low-level API:

  • BreezeSDK.getWithdrawInstruction(...)getWithdrawInstructions(...) (plural, to match its array payload and the deposit/close siblings). The low-level getInstructionForWithdraw is likewise now getInstructionsForWithdraw.
  • new ApiClient(baseUrl, timeout)new ApiClient({ apiKey, baseUrl?, timeout? }). The client now stores the API key and sends the x-api-key header itself.
  • Endpoint functions take (client, options) instead of long positional argument lists — e.g. getUserYield(client, { userId }), getTransactionForDeposit(client, { strategyId, baseAsset, amount, userKey }).
  • The internal BodyFor* request types were removed; use the *Options types.
  • The root import remains dependency-free. Install @solana/kit and import @solana/breeze-sdk/kit for trusted-backend composable transaction execution; browser wallets use the backend handoff described above.