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

bulk-ts-sdk

v0.0.10

Published

Unofficial TypeScript SDK for Bulk Exchange, providing high-performance, type-safe access to market data and trading operations.

Readme


🔗 Links


🚀 Features

  • ⚡ High Performance: Built with zero-dependency core logic and optimized for speed.
  • 🛡️ Fully Type-Safe: Comprehensive TypeScript definitions for all API responses and requests.
  • 🔌 Unified Client: Simple interface for HTTP (Market/Account) and WebSocket (Real-time) interactions.
  • 🔑 Seamless Signing: Integrated KeychainSigner for easy order signing and multi-sig support.
  • 🌐 Dual Compatibility: Works perfectly in Deno, Bun, Node.js, and browser environments.

📦 Installation

Deno (via JSR)

deno add jsr:@posaune0423/bulk-ts-sdk

Node.js / Bun / pnpm

# Using bun
bun add bulk-ts-sdk

# Using npm
npm install bulk-ts-sdk

# Using pnpm
pnpm add bulk-ts-sdk

🏃 Quick Start

Initialize the Client

import { BulkClient } from "bulk-ts-sdk";
import process from "node:process";

const client = new BulkClient({
  privateKey: process.env.MAIN_WALLET_PRIVATE_KEY!,
});

The client can be used without a key for public market data. A privateKey is required only when you call signing methods such as client.trade.placeLimitOrder(), client.trade.cancelOrder(), or client.trade.manageAgentWallet().

| Option | Required | Purpose | | :----------------- | :------- | :------------------------------------------------------------------------------------------- | | httpUrl | No | HTTP API base URL. Defaults to Bulk production. | | wsUrl | No | WebSocket API URL. Defaults to Bulk production. | | privateKey | No | Wallet private key used for signing trade and agent-wallet actions. | | accountPublicKey | No | Target account public key. Only needed when signing with an agent wallet for a main account. | | timeoutMs | No | Request timeout in milliseconds. |

Use one of these environment variable sets:

  • Main wallet only: set MAIN_WALLET_PRIVATE_KEY.
  • Agent wallet for a main wallet: set both AGENT_WALLET_PRIVATE_KEY and MAIN_WALLET_PUBLIC_KEY.

For normal trading with the main wallet key, pass MAIN_WALLET_PRIVATE_KEY as privateKey. In that case client.accountPublicKey is derived from the signer and can be reused for account queries.

const client = new BulkClient({
  privateKey: process.env.MAIN_WALLET_PRIVATE_KEY!,
});

const accountPublicKey = client.accountPublicKey;
if (!accountPublicKey) throw new Error("privateKey is required for account-scoped examples");

When signing for a main wallet through its registered agent wallet, pass AGENT_WALLET_PRIVATE_KEY as privateKey and the target MAIN_WALLET_PUBLIC_KEY as accountPublicKey. Target-account order signing depends on native bulk-keychain support for signing that target account; unsupported native builds fail before submitting an invalid signature.

const client = new BulkClient({
  privateKey: process.env.AGENT_WALLET_PRIVATE_KEY!,
  accountPublicKey: process.env.MAIN_WALLET_PUBLIC_KEY!,
});

Fetch Market Data

const info = await client.market.exchangeInfo();
const ticker = await client.market.ticker("BTC-USD");
const candles = await client.market.klines({
  symbol: "BTC-USD",
  interval: "1m",
  limit: 100,
});
const book = await client.market.l2Book({
  symbol: "BTC-USD",
  nlevels: 20,
});
const stats = await client.market.stats({ symbol: "BTC-USD" });
const risk = await client.market.riskSurfaces("BTC-USD");

console.log(info.length, ticker.lastPrice, candles.length, book, stats, risk);

Read Account Data

Account history methods take the account public key you want to inspect. If the client was created with a main wallet privateKey, use client.accountPublicKey.

const accountPublicKey = client.accountPublicKey;
if (!accountPublicKey) throw new Error("privateKey is required");

const full = await client.account.fullAccount(accountPublicKey);
const openOrders = await client.account.openOrders(accountPublicKey);
const fills = await client.account.fills(accountPublicKey);
const positions = await client.account.positions(accountPublicKey);
const funding = await client.account.fundingHistory(accountPublicKey);
const orders = await client.account.orderHistory(accountPublicKey);
const feeTier = await client.account.feeTier(accountPublicKey);

// Global fee state does not require an account public key.
const feeState = await client.account.feeState();

console.log({ full, openOrders, fills, positions, funding, orders, feeTier, feeState });

Multisig proposal snapshots are available when you already have a multisig account public key:

const proposals = await client.account.multisigProposals("multisig-account-public-key");
console.log(proposals.proposals);

Trade

const order = await client.trade.placeLimitOrder({
  symbol: "BTC-USD",
  side: "buy",
  price: 50000,
  size: 0.1,
  tif: "GTC",
});

const firstStatus = order.response.data.statuses[0];
if (firstStatus && "resting" in firstStatus && firstStatus.resting) {
  console.log(`Order ID: ${firstStatus.resting.oid}`);
}

await client.trade.cancelAll({ symbols: ["BTC-USD"] });

Market orders, single-order cancel, and batch submission use the same signer:

await client.trade.placeMarketOrder({
  symbol: "BTC-USD",
  side: "sell",
  size: 0.05,
});

await client.trade.cancelOrder({
  symbol: "BTC-USD",
  orderId: "order-id",
});

import { toKeychainCancelOrder, toKeychainLimitOrder } from "bulk-ts-sdk";

await client.trade.batch([
  toKeychainLimitOrder({
    symbol: "BTC-USD",
    side: "buy",
    price: 49000,
    size: 0.001,
  }),
  toKeychainCancelOrder({
    symbol: "BTC-USD",
    orderId: "order-id",
  }),
]);

Agent Wallet Registration

Register an agent wallet with the main wallet signer:

const agentWalletClient = new BulkClient({
  privateKey: process.env.AGENT_WALLET_PRIVATE_KEY!,
});

const agentWalletPublicKey = agentWalletClient.accountPublicKey;
if (!agentWalletPublicKey) throw new Error("AGENT_WALLET_PRIVATE_KEY is required");

await client.trade.manageAgentWallet({
  agent: agentWalletPublicKey,
  remove: false,
});

Real-time Subscriptions (WebSocket)

await client.ws.connect();

const subscription = await client.ws.subscribe({ type: "ticker", symbol: "BTC-USD" }, (data) => {
  console.log("Real-time Update:", data);
});

await subscription.unsubscribe();
await client.ws.close();

You can also submit signed trades over WebSocket:

await client.ws.connect();

const order = await client.trade.placeLimitOrder(
  {
    symbol: "BTC-USD",
    side: "buy",
    price: 50000,
    size: 0.001,
  },
  { via: "ws" },
);

console.log(order.status);

🔧 API Structure

The BulkClient is organized into focused sub-clients:

| Sub-Client | Description | | :--------- | :----------------------------------------------------------- | | market | Public data like tickers, candles (klines), and order books. | | account | Private data like balances, open orders, and trade history. | | trade | Execution operations (limit/market orders, cancels, batch). | | ws | WebSocket management and real-time subscriptions. |


🧪 Testing

E2E tests read .env through Deno's --env-file=.env support.

cp .env.example .env

For normal account/trade E2E with the main wallet key, only this wallet variable is required:

MAIN_WALLET_PRIVATE_KEY=main-wallet-private-key

For agent-wallet tests or examples targeting the main wallet, set both values:

AGENT_WALLET_PRIVATE_KEY=agent-wallet-private-key
MAIN_WALLET_PUBLIC_KEY=main-wallet-public-key

Optional test/example variables:

MULTISIG_PUBKEY=multisig-account-public-key
# Run all tests
deno task test

# Run e2e tests
deno task test:e2e

🤖 For Agent

Read llm.txt

📄 License

Distributed under the MIT License. See LICENSE for more information.