TypeScript (web) SDK
ESM-only TypeScript SDK that speaks gRPC-Web directly to the upstream sweetspot-server (tonic + tonic_web). Works in any modern browser and in Node 18.14+. No build-time codegen required by consumers — the package ships pre-generated TypeScript.
Surfaces
| Surface | How |
|---|---|
Public (MarketDataService, StatsService, HistoricalService) | createClient, createServiceClient |
Authenticated (MakerService) | createMakerClient + AuthFlow (passwordless email) or apiKeyInterceptor(...) (org API key) |
TxService + wallet signing | Not exposed — drive a wallet adapter or use the Rust / Python SDK |
Install
npm install @superis-labs/sweetspot-client @bufbuild/protobufThe only runtime dependency is @bufbuild/protobuf for serialization. The gRPC-Web transport ships in-tree.
Quickstart
import {
GrpcWebTransport,
MarketDataService,
StatsService,
createServiceClient,
} from "@superis-labs/sweetspot-client";
import { FeedLevel } from "@superis-labs/sweetspot-client/gen/sweetspot/api/v1/common_pb.js";
const transport = new GrpcWebTransport({
baseUrl: "https://api.superis.exchange",
});
// Public RPC — no auth needed.
const market = createServiceClient(MarketDataService, transport);
const stats = createServiceClient(StatsService, transport);
const pairs = await market.listPairs({});
const summary = await stats.getSummary({});
console.log(pairs.pairs);
console.log(summary);
// Server-streaming RPC — `for await` works directly.
const pair = { base: { id: 1n }, quote: { id: 0n } };
for await (const event of market.subscribe({
pairs: [{ pair, level: FeedLevel.L2, snapshotOnly: false }],
})) {
console.log(event);
}Where to go from here
| You want | Page |
|---|---|
| Stream books and fills | Market data |
| Pull historical trades / candles | Historical queries |
Authenticate against MakerService | Auth flow |
MakerService (authenticated)
MakerService requires organization-scoped credentials. Build a maker client via createMakerClient, passing either an AuthFlow (passwordless email login) or apiKeyInterceptor(key) (organization API key).
import {
AuthFlow,
createMakerClient,
} from "@superis-labs/sweetspot-client";
// Persist the bearer across reloads. Any localStorage-shaped store works
// — pass a sessionStorage, an IndexedDB-backed shim, or your own.
const auth = new AuthFlow({
baseUrl: "https://auth.api.superis.exchange",
storage: globalThis.localStorage,
onExpired: () => router.push("/login"),
});
// Login form:
await auth.requestLoginCode("trader@example.com");
// …prompt user, then…
await auth.verifyLoginCode("trader@example.com", code);
// Bind credentials to a maker client.
const maker = createMakerClient({
baseUrl: "https://auth.api.superis.exchange",
auth,
});
const { balances } = await maker.getBalance({ spotIds: [] });See Auth flow → TypeScript for the full walk-through, including API key auth.
HistoricalService (public)
HistoricalService is exposed as a generated descriptor. Build a service client with the public transport:
import {
GrpcWebTransport,
HistoricalService,
createServiceClient,
} from "@superis-labs/sweetspot-client";
const historical = createServiceClient(
HistoricalService,
new GrpcWebTransport({
baseUrl: "https://api.superis.exchange",
}),
);
const { trades } = await historical.getTrades({ pair, limit: 100 });Decimal handling
Live book and fill price / size fields come back as Decimal { value: string }. Parse with bignumber.js or decimal.js:
import BigNumber from "bignumber.js";
const price = new BigNumber(trade.price.value);
const size = new BigNumber(trade.size.value);
const notional = price.multipliedBy(size);Historical Trade and Candle responses use the same Decimal { value: string } wrapper for price, size, and OHLCV fields.
Errors
import { GrpcError, GrpcCode } from "@superis-labs/sweetspot-client";
try {
await market.listPairs({});
} catch (err) {
if (err instanceof GrpcError) {
switch (err.code) {
case GrpcCode.ResourceExhausted: await sleep(backoff); break;
case GrpcCode.Unavailable: await sleep(backoff); break;
}
}
}See Errors for the full code map.
Wire format
The transport speaks application/grpc-web+proto over HTTP/1.1, terminating at the server's tonic_web::GrpcWebLayer. Server streaming is supported via AsyncIterable<Output> on every streaming RPC. There is no gRPC-streaming-bidi or client-streaming over gRPC-Web — those RPCs throw at call time.
Browser compatibility
Modern browsers (Chrome 90+, Firefox 90+, Safari 14+). Requires fetch and ReadableStream — both baseline in every release-channel browser since 2022.
Source
- Package:
typescript-web/ - Examples:
examples/typescript-web/
