@agg-build/sdk
v1.2.11
Published
Vanilla TypeScript client for the AGG prediction market aggregator (auth, markets, orderbooks, charts, trading, managed execution, WebSockets). Works in browsers, Node.js, and React Native.
Readme
@agg-build/sdk
Vanilla TypeScript client for the AGG prediction market aggregator — one client, every surface (auth, markets, orderbooks, charts, trading, managed execution, WebSockets).
What it is
@agg-build/sdk is the lowest-level package partners install. It speaks to the AGG API over HTTPS and
WebSockets, manages auth/session state, and exposes typed wrappers for every product endpoint
(markets, orderbooks, charts, trade execution, deposits/withdrawals, managed wallets, admin and
more). It has no framework dependency and works in browsers, Node.js, and React Native.
For React apps, layer @agg-build/hooks, @agg-build/ui, and @agg-build/auth on top — they all use this client
under the hood.
When to use this package
- You are building a vanilla TS/JS app, React Native app, or server-side integration.
- You want a typed, batteries-included client for the AGG REST API and WebSocket gateway.
- You are authoring your own React layer and need the underlying auth/session/trade primitives.
- You need a server-only helper: SSR config fetching, webhook verification, external-ID signing,
or the admin API client (see
@agg-build/sdk/server).
If you are shipping a React app and want ready-made hooks or UI, install @agg-build/hooks,
@agg-build/ui, and @agg-build/auth
instead — those packages are built on top of @agg-build/sdk.
Install
npm install @agg-build/sdkQuick start
import { createAggClient } from "@agg-build/sdk";
const client = createAggClient({
baseUrl: "https://api.agg.market",
appId: "your-app-id",
});
// Health check
const hello = await client.getHello();
// Current auth state (persisted across reloads via localStorage)
console.log(client.isAuthenticated, client.user);Authenticate a user (SIWE)
// 1. Start the auth flow
const { nonce } = await client.authStart({ provider: "siwe" });
// 2. Build the EIP-4361 message
const message = client.buildSiweMessage({
address: "0x…",
chainId: 1,
nonce,
domain: window.location.host,
uri: window.location.origin,
});
// 3. Sign with the user's wallet (wagmi, viem, ethers, …)
const signature = await wallet.signMessage(message);
// 4. Verify → stores accessToken + user in the client
const { accessToken, user } = await client.verify({ message, signature });SIWS (Solana) uses the same flow with buildSiwsMessage and a base58-encoded Ed25519 signature.
Redirect flows (Google, Apple, Twitter, email magic-link) return a URL to navigate to:
const response = await client.authStart({
provider: "google",
redirectUrl: "https://yourapp.com/auth/callback",
});
if (response.type === "redirect") {
window.location.assign(response.url);
}
// …back on the callback page:
const code = new URLSearchParams(window.location.search).get("code");
if (code) {
await client.exchangeAuthCode(code);
window.history.replaceState(null, "", window.location.pathname);
}HttpOnly cookie-refresh mode
For browser apps that prefer an HttpOnly refresh cookie over storing the refresh token in JS,
construct the client with authDelivery: "cookie-refresh":
const client = createAggClient({
baseUrl: "https://api.agg.market",
appId: "your-app-id",
authDelivery: "cookie-refresh",
});In this mode, verify() and exchangeAuthCode() may omit refreshToken from the returned
object. The refresh cookie stays scoped to the AGG API host under /auth and is never exposed to
partner frontend domains.
Streaming data (WebSocket)
const ws = client.createWebSocket({
onSnapshot: (marketId, book) => console.log("snapshot", marketId, book),
onDelta: (marketId, book) => console.log("delta", marketId, book),
onTrade: (trade) => console.log("trade", trade.venue, trade.price, trade.size),
});
const unsubscribe = ws.subscribe("market-id");
// Optional: authenticate for user-scoped events (orders, balances)
ws.authenticate(accessToken);
// Cleanup
unsubscribe();
ws.destroy();createWebSocket requires wsUrl to be passed to createAggClient. The underlying
AggWebSocket can also be instantiated directly if you want finer control.
Server-side helpers
Import from the /server entrypoint for Node-only utilities:
import { AggAdminClient, signExternalId, verifyWebhook } from "@agg-build/sdk/server";
// Sign a partner external-ID assertion before sending to the browser
const assertion = signExternalId(process.env.AGG_APP_SECRET!, partnerUser.id);
// Verify an inbound webhook
verifyWebhook(rawBody, req.headers, process.env.AGG_WEBHOOK_SECRET!);
// Admin API client (uses x-app-api-key)
const admin = new AggAdminClient({
baseUrl: "https://api.agg.market",
apiKey: process.env.AGG_APP_API_KEY!,
});
const users = await admin.listUsers("your-app-id", { limit: 50 });Client options
| Option | Type | Required | Description |
| ---------------- | ---------------------------- | --------------------- | ----------------------------------------------------- |
| baseUrl | string | Yes | API base URL (e.g. https://api.agg.market) |
| appId | string | One of appId/adminKey | Partner app ID |
| adminKey | string | One of appId/adminKey | Admin API key for admin-tier routes |
| wsUrl | string | For WebSocket | WebSocket gateway URL (required by createWebSocket) |
| authDelivery | "body" \| "cookie-refresh" | No | Token delivery mode (default: "body") |
| persistSession | boolean | No | Persist auth hint to localStorage (default: true) |
| kalshiDemo | boolean | No | Use Kalshi demo environment |
Call client.destroy() when you no longer need the client to release internal resources
(BroadcastChannel used for cross-tab auth sync).
Main exports
AggClient methods
Auth & session
| Method | Description |
| --------------------------------------------------- | ----------------------------------------------------- |
| authStart(body) | Start any auth flow (SIWE nonce, OAuth redirect, etc) |
| buildSiweMessage(params) | Build an EIP-4361 message string |
| buildSiwsMessage(params) | Build a Solana sign-in message |
| verify({ message, signature }) | Verify SIWE/SIWS signature, store tokens |
| exchangeAuthCode(code) | Exchange redirect auth code for tokens |
| refreshAccessToken() | Refresh the JWT using the stored refresh token |
| setSession({ accessToken, refreshToken?, user? }) | Seed tokens from a redirect callback |
| setAccessToken(token) / clearAccessToken() | Manage the JWT directly |
| signOut() | Revoke tokens server-side and clear local session |
| onAuthStateChange(listener) | Subscribe to auth state changes |
| isAuthenticated / user / authStatus | Getters for current session state |
User profile & accounts
| Method | Description |
| ------------------------------------------------- | ------------------------------------------- |
| getCurrentUser() | Fetch current user profile from /users/me |
| updateUser(data) | Update username, avatar, etc. |
| createAvatarUploadUrl(contentType) | Get a presigned avatar upload URL |
| linkExternalId({ externalId, timestamp, hmac }) | Link a backend-signed partner user ID |
| disconnectAccount(provider) | Remove a linked auth provider |
Market data
| Method | Description |
| --------------------------- | --------------------------------------------------- |
| getVenueEvents(options?) | List prediction market events (cursor pagination) |
| getVenueEventById(id) | Get a single event by ID |
| getVenueMarkets(options?) | List venue markets with filters (cursor pagination) |
| getCategories(options?) | List market categories |
Correlated Markets
| Method | Description |
| ------------------------------------ | ------------------------------------------------ |
| resolveCorrelatedMarkets(params) | Resolve a market and return expand/hedge ideas |
| getCorrelatedMarketCascade(params) | Get expand/hedge ideas for a known venueMarketId |
| getMarketCorrelatedSignals(id) | Inspect generated signals for a market |
| queryCorrelatedMarkets(params) | Search markets by signal similarity |
Orderbooks & routing
| Method | Description |
| ----------------------- | -------------------------------------------------------- |
| getOrderbooks(params) | Get live per-venue orderbooks for given venueMarketIds |
| getSmartRoute(params) | MILP solver for optimal order routing across venues |
Chart data
| Method | Description |
| ----------------------------- | ---------------------------------------------- |
| getChartBars(params) | TradingView-style OHLCV candles for an outcome |
| getPricesHistory(params) | Price history for venue market outcomes |
| getOrderbookHistory(params) | Orderbook depth history for an outcome |
Trading
| Method | Description |
| --------------------- | ----------------------------------------------- |
| validateTrade(body) | Pre-flight trade validation |
| executeTrade(body) | Execute orders on Kalshi/Polymarket via backend |
| computeSplits(body) | Compute best order splits across venues via API |
Venue keys
| Method | Description |
| ------------------------ | ------------------------------------------------ |
| listVenueKeys(venues?) | List stored venue API keys (no secrets returned) |
| upsertVenueKey(body) | Create or update a venue API key |
| deleteVenueKey(venue) | Delete a venue API key |
Managed execution & balances
| Method | Description |
| ----------------------------- | ---------------------------------------------------- |
| validateManaged(params) | Check balances and bridge requirements |
| quoteManaged(params) | Request a 2-min TTL quote with execution steps |
| executeManaged(params) | Execute a previously quoted trade |
| withdrawManaged(params) | Withdraw from managed wallets to an external address |
| syncManagedBalances() | Trigger on-chain balance sync |
| cancelManagedOrder(orderId) | Cancel a pending managed execution order |
| getVenueBalances(venues) | Get balances across venues |
| getManagedBalances() | Get managed wallet balances per-chain + per-venue |
| getDepositAddresses() | Get managed wallet deposit addresses (EVM + Solana) |
Orders & positions
| Method | Description |
| -------------------------------- | -------------------------------------------- |
| getOrders(params?) | List trade-executor orders |
| getExecutionOrders(params?) | List execution orders (cursor pagination) |
| getExecutionPositions(params?) | List execution positions (cursor pagination) |
| getPositions(params?) | Get open positions grouped by matched market |
| getUserHoldings(params) | Get user positions per venue |
Utilities
| Method | Description |
| ----------------------------- | ---------------------------------------------- |
| getHello() | Health check |
| request(path, init?) | Generic HTTP with auto-retry on 401 |
| createWebSocket(callbacks?) | Create a WebSocket instance (requires wsUrl) |
| destroy() | Release resources (BroadcastChannel, etc.) |
Standalone utilities
| Export | Description |
| --------------------------- | --------------------------------------------------------------- |
| AggWebSocket | Low-level WebSocket client (used by client.createWebSocket()) |
| CandleBuilder | Chart-library-agnostic candle builder (trades → OHLC) |
| computeBestSplitsByAmount | Pure function: optimal split across venue orderbooks |
| applyOrderbookDelta | Apply WS delta to an in-memory orderbook |
| computeChecksum | CRC32 orderbook checksum (used to detect desync) |
| snapshotToOrderbook | Convert a WS snapshot to the in-memory shape |
| aggregateMidpoint | Aggregate outcome midpoints across venues |
| mergeCandles | Merge live + historical candles, live-wins on collision |
| mergeClosedCandles | Variant that merges only fully closed candles |
| TurnstileChallengeError | Thrown when an auth endpoint requires a Turnstile challenge |
@agg-build/sdk/server
| Export | Description |
| --------------------------------------------- | ------------------------------------------------------------- |
| AggAdminClient | Admin REST client using x-app-api-key (server-only) |
| signExternalId(secret, userId) | HMAC-sign a partner user ID before calling linkExternalId() |
| verifyWebhook(payload, headers, secret) | Verify an inbound webhook signature |
| parseWebhookEvent(payload, headers, secret) | Verify + parse a webhook into a typed event |
| WebhookVerificationError | Thrown on signature/timestamp failures |
WebSocket callbacks
| Callback | When it fires |
| ------------------------------------ | ---------------------------------------------- |
| onSnapshot(marketId, book) | Full orderbook snapshot received |
| onDelta(marketId, book) | Incremental orderbook update applied |
| onTrade(trade) | Trade execution |
| onHeartbeat(hb) | Server heartbeat (every 30s) |
| onSubscribed / onUnsubscribed | Subscription lifecycle |
| onConnected / onAuthenticated | Connection / auth lifecycle |
| onOrderSubmitted | Order placed via WebSocket |
| onBalanceUpdate | Balance change event |
| onMarketResolved | Market resolution |
| onDiagnostics(event) | Diagnostic events (seq gaps, stale connection) |
| onConnectionStateChange(connected) | Connection state changed |
| onError(msg) | Error message from server |
Key behaviors:
- Single persistent connection with refcounted per-market subscriptions.
- In-memory orderbook state per market (snapshot + delta with CRC32 verification).
- Sequence gap or checksum mismatch triggers automatic resnapshot.
- Auto-reconnect with exponential backoff (base 1s, max 30s).
- Liveness: no message for 45s triggers reconnect; server heartbeats every 30s.
- Bids always sorted descending, asks always sorted ascending.
Headers attached automatically
x-app-id— from theappIdoptionAuthorization: Bearer <jwt>— after sign-inx-admin-key— ifadminKeyis providedx-auth-delivery: cookie-refresh+credentials: "include"on auth-only requests whenauthDelivery: "cookie-refresh"is enabled
Entrypoints
| Entry | Purpose |
| ----------------------- | -------------------------------------------------------------- |
| @agg-build/sdk | AggClient, createAggClient, AggWebSocket, utilities |
| @agg-build/sdk/server | Node-only helpers: admin client, external-ID / webhook signing |
Peer dependencies
None. @agg-build/sdk is dependency-light and bundles its own clients for viem, ethers@5,
@polymarket/clob-client, and @polymarket/builder-signing-sdk.
Links
- Documentation — https://docs.agg.market/
- Demo app — https://agg.market/
- React hooks —
@agg-build/hooks - Trading UI —
@agg-build/ui - Connect / sign-in UX —
@agg-build/auth
License
MIT
