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

@quantchat/sdk

v0.6.2

Published

TypeScript SDK for the QuantChat trading and social platform

Readme

@quantchat/sdk

The framework-neutral TypeScript SDK for QuantChat. It is the canonical client transport, protobuf contract, and domain API layer for web, React Native, Node, CLI, and third-party integrations.

The SDK lives in its own repository and is distributed as a package. Consumers must not copy generated contracts or maintain a parallel HTTP transport.

Installation

npm install @quantchat/sdk

The package is ESM, has no framework dependency, and uses the host runtime's standard fetch, URL, Headers, AbortSignal, and TextDecoder APIs.

Node, CLI, And Server Quick Start

import { createClient } from '@quantchat/sdk'

const qc = createClient({
  apiKey: 'qc_live_...',
  // baseUrl: 'http://localhost:4000', // local development
})

const health = await qc.app.health()
const me = await qc.users.me()
const accounts = await qc.accounts.myAccounts()

console.log(health.status, me.handle, accounts.length)

The root import is a convenience aggregate for server and command-line consumers. It exposes every domain module on one client.

Resource Semantics

Mutable resources use the predictable CRUD vocabulary create, getById, list, update, and delete whenever the backend supports those operations. Natural-key lookups name the key explicitly, such as getBySlug and getBySymbol.

Singular getters return one entity or throw QuantChatError with code: "NOT_FOUND" and status 404. Collection list() methods return an empty array or connection when no records match. The SDK does not call a paginated single-page request getAll; that name is reserved for operations that truly exhaust every page.

Optional exact decimals can be passed directly through decimal:

import { decimal } from '@quantchat/sdk'

const run = await qc.backtests.create({
  // ...required fields
  initialCapital: decimal(optionalInitialCapital),
})

The result is DecimalString | undefined; required money fields still reject possibly-undefined values at compile time.

Web And React Native

Browser and mobile applications should import the transport, only the domain modules they use, and protobuf contracts through granular subpaths. This keeps unused domains out of client bundles.

import { BotsModule } from '@quantchat/sdk/modules/bots'
import { createTransport } from '@quantchat/sdk/transport'
import { GetMyBotsResponse } from '@quantchat/sdk/proto/bot/bot'

const transport = createTransport({
  baseUrl: 'https://api.quantchat.com',
  getAccessToken: async () => auth.currentToken(),
})
const bots = new BotsModule(transport)

const page = await transport.getPb('/api/bots', GetMyBotsResponse)
const bot = await bots.getById(page.bots[0]!.id)

getAccessToken is evaluated for every request, so rotating session tokens do not require rebuilding clients. React Native needs no Node polyfills on runtimes that implement the standard web APIs above.

Next.js

Create SDK objects lazily at module scope and pass Next.js fetch options through init. Public and authenticated transports should be separate so public requests remain cacheable and do not accidentally include user credentials.

import { createTransport } from '@quantchat/sdk/transport'

const publicApi = createTransport({
  baseUrl: process.env.NEXT_PUBLIC_API_URL,
})

const markets = await publicApi.get('/public/markets', undefined, {
  init: { next: { revalidate: 60, tags: ['markets'] } },
})

Strategies

const page = await qc.strategies.list({ sort: 'recent', limit: 25 })
console.log(page.items, page.cursor)

const generated = await qc.strategies.generate({
  prompt: 'Create a mean reversion strategy for large-cap US equities.',
  idempotencyKey: crypto.randomUUID(),
})
if (generated.kind === 'clarification') console.log(generated.questions)
else console.log(generated.strategy)

const intentStrategy = await qc.strategies.createFromIntent({ intent })
const updated = await qc.strategies.updateIntent(intentStrategy.id, nextIntent)

Bots And Backtests

const bot = await qc.bots.create({
  accountId: 'account-id',
  strategyId: 'strategy-id',
  idempotencyKey: crypto.randomUUID(),
  instrumentDefId: 'instrument-id-or-symbol',
  parameters: { lookback: 20 },
  initialCapital: '10000',
})

const bots = await qc.bots.list({ sort: 'recent', limit: 20 })
await qc.bots.stop(bot.id)

const backtest = await qc.backtests.create({
  strategyId: 'strategy-id',
  instrumentDefId: 'AAPL',
  timeframe: '1h',
  startTime: '2026-01-01T00:00:00Z',
  endTime: '2026-02-01T00:00:00Z',
})

Agents

const config = await qc.agents.launchConfig()

const agent = await qc.agents.create({
  accountId: 'paper-account-id',
  systemPrompt: 'Trade a small liquid universe conservatively.',
  model: config.models.find((m) => m.defaultModel)?.model ?? config.models[0]!.model,
  initialCapital: config.capitalDefaults.defaultInitialCapital,
  allowedInstrumentDefIds: ['instrument-id'],
  startNow: false,
})

await qc.agents.start(agent.id)
await qc.agents.stop(agent.id)

Instruments And Market Data

const matches = await qc.marketData.searchInstruments('AAPL')
const instrument = await qc.instruments.getBySymbol('AAPL')
const bars = await qc.marketData.getBars({ symbol: 'AAPL', timeframe: '1h', limit: 100 })
const quotes = await qc.marketData.getQuotes(['AAPL', 'BTC-USD'])

qc.instruments.list() returns the backend's enabled instrument-def directory. Use qc.marketData.searchInstruments() for symbol/name lookup.

Social And Utilities

const communities = await qc.communities.list()
const watchlists = await qc.watchlists.list()
const notifications = await qc.notifications.list()
const tradeCheck = await qc.tools.shouldITrade('AAPL')

Protobuf Contracts

The aggregate namespace is convenient on the server:

import { proto } from '@quantchat/sdk'

const decoded = proto.bot.GetMyBotsResponse.fromBinary(bytes)

Client applications should use granular contract imports so bundlers include only what the application references:

import { GetMyBotsResponse } from '@quantchat/sdk/proto/bot/bot'

Configuration

const qc = createClient({
  apiKey: 'qc_live_...',
  bearerToken: 'user-jwt',
  getAccessToken: async () => session.getToken(),
  baseUrl: 'http://localhost:4000',
  fetch: customFetch,
  signal: abortController.signal,
})

getAccessToken takes precedence over static credentials. Request helpers also accept cancellation and arbitrary host-runtime fetch options:

await qc.get('/api/example', undefined, {
  signal: requestSignal,
  init: { cache: 'no-store' },
})

Types

All public types are exported:

import type { Account, Agent, BacktestRun, Bot, InstrumentDef, Strategy } from '@quantchat/sdk'

Money

Money-of-record fields (capital, balances, nominal P&L, credits) are typed and delivered as exact decimal strings (e.g. bot.currentCapital === "10245.51"), matching the wire (proto string). The SDK never converts these to floats — consumers choose their own decimal handling (e.g. Decimal.js, Number() for display only). Genuine ratios (profitPercent, dailyChangePercent) are proto double and stay JS number.

Breaking in 0.4.0: money-of-record fields on Bot, Agent, Account, and AgentLaunchConfig changed from number to string to match the actual wire type — code doing arithmetic directly on these fields (e.g. bot.profitNominal * 2) must convert explicitly first.

License

MIT