@varla/polymarket 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md ADDED
@@ -0,0 +1,243 @@
1
+ # AGENTS.md - AI Coding Assistant Instructions
2
+
3
+ This file provides context for AI coding assistants (Cursor, Cline, Copilot, etc.) working on `@varla/polymarket`.
4
+
5
+ ## Package Overview
6
+
7
+ `@varla/polymarket` is a high-performance Polymarket SDK that's **139% faster** than the official `@polymarket/clob-client`. It provides full trading support for Polymarket's CLOB and Gamma APIs.
8
+
9
+ ## Tech Stack
10
+
11
+ | Technology | Purpose |
12
+ |------------|---------|
13
+ | **Bun** | Runtime & package manager (not Node.js) |
14
+ | **viem** | Ethereum wallet/signing (not ethers.js) |
15
+ | **Web Crypto API** | HMAC/SHA256 (not node:crypto) |
16
+ | **fetch** | HTTP (not axios) |
17
+ | **SQLite** | Order persistence (via @varla/db) |
18
+ | **Biome** | Linting & formatting |
19
+
20
+ ## Critical Rules
21
+
22
+ ### ❌ DO NOT USE
23
+ ```typescript
24
+ // Node.js APIs - will fail in Bun/edge
25
+ import crypto from "node:crypto";
26
+ import fs from "node:fs";
27
+ import { Buffer } from "node:buffer";
28
+
29
+ // ethers.js - we use viem
30
+ import { ethers } from "ethers";
31
+
32
+ // axios - we use fetch
33
+ import axios from "axios";
34
+ ```
35
+
36
+ ### ✅ DO USE
37
+ ```typescript
38
+ // Web Crypto API
39
+ const key = await crypto.subtle.importKey(...);
40
+ const sig = await crypto.subtle.sign("HMAC", key, data);
41
+
42
+ // viem for wallets
43
+ import { createWalletClient, http } from "viem";
44
+ import { privateKeyToAccount } from "viem/accounts";
45
+
46
+ // Native fetch
47
+ const res = await fetch(url, { headers });
48
+
49
+ // Bun file APIs
50
+ const file = Bun.file("path");
51
+ await Bun.write("path", content);
52
+ ```
53
+
54
+ ## Project Structure
55
+
56
+ ```
57
+ packages/polymarket/
58
+ ├── src/
59
+ │ ├── index.ts # Public exports
60
+ │ ├── clob-client.ts # Public CLOB API (read-only)
61
+ │ ├── clob-trading-client.ts # Authenticated trading
62
+ │ ├── clob-auth.ts # API key management, EIP712 auth
63
+ │ ├── clob-orders.ts # Order building & signing
64
+ │ ├── clob-persistence.ts # SQLite order tracking
65
+ │ ├── clob-ws.ts # WebSocket client
66
+ │ ├── gamma-client.ts # Gamma API (markets, metadata)
67
+ │ ├── signing/ # HMAC & EIP712 signatures
68
+ │ ├── config/ # Contract addresses, endpoints
69
+ │ └── abi/ # Contract ABIs
70
+ ├── test/
71
+ │ ├── unit/ # Deterministic unit tests
72
+ │ ├── integration/ # Network mocking tests
73
+ │ ├── sdk/ # Parity tests vs official SDK
74
+ │ ├── live/ # Real API tests (optional)
75
+ │ └── bench/ # Performance benchmarks
76
+ └── docs/
77
+ └── SDK_COMPARISON.md # Official SDK comparison
78
+ ```
79
+
80
+ ## Key Patterns
81
+
82
+ ### EIP712 Signing (Orders & Auth)
83
+
84
+ ```typescript
85
+ // Use viem's signTypedData
86
+ const signature = await walletClient.signTypedData({
87
+ account,
88
+ domain: { name: "...", chainId: 137 },
89
+ types: { ... },
90
+ primaryType: "...",
91
+ message: { ... },
92
+ });
93
+ ```
94
+
95
+ ### HMAC Signing (API Requests)
96
+
97
+ ```typescript
98
+ // Use Web Crypto API
99
+ export async function buildPolyHmacSignature(params: {
100
+ secret: string;
101
+ timestamp: number;
102
+ method: string;
103
+ path: string;
104
+ body?: string;
105
+ }): Promise<string> {
106
+ const message = `${params.timestamp}${params.method}${params.path}${params.body ?? ""}`;
107
+ const key = await crypto.subtle.importKey(
108
+ "raw",
109
+ base64ToUint8Array(params.secret),
110
+ { name: "HMAC", hash: "SHA-256" },
111
+ false,
112
+ ["sign"]
113
+ );
114
+ const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(message));
115
+ return btoa(String.fromCharCode(...new Uint8Array(sig)));
116
+ }
117
+ ```
118
+
119
+ ### HTTP Requests
120
+
121
+ ```typescript
122
+ // Always use native fetch with proper error handling
123
+ const response = await fetch(url, {
124
+ method: "POST",
125
+ headers: {
126
+ "Content-Type": "application/json",
127
+ ...this.buildAuthHeaders(timestamp, method, path, body),
128
+ },
129
+ body: JSON.stringify(payload),
130
+ });
131
+
132
+ if (!response.ok) {
133
+ throw new ClobHttpError(response.status, await response.text());
134
+ }
135
+ ```
136
+
137
+ ## Testing
138
+
139
+ ### Run Tests
140
+
141
+ ```bash
142
+ # All unit tests
143
+ bun test packages/polymarket/test/unit
144
+
145
+ # All tests (including integration)
146
+ bun test packages/polymarket
147
+
148
+ # With coverage
149
+ bun test packages/polymarket --coverage
150
+
151
+ # Run benchmarks
152
+ POLYMARKET_BENCH=true bun test packages/polymarket/test/sdk
153
+
154
+ # Live tests (requires API keys)
155
+ POLYMARKET_LIVE_TESTS=1 bun test packages/polymarket/test/live
156
+ ```
157
+
158
+ ### Test Patterns
159
+
160
+ ```typescript
161
+ import { describe, test, expect, beforeEach, mock } from "bun:test";
162
+
163
+ describe("Feature", () => {
164
+ test("does X", async () => {
165
+ // Arrange
166
+ const input = ...;
167
+
168
+ // Act
169
+ const result = await fn(input);
170
+
171
+ // Assert
172
+ expect(result).toEqual(...);
173
+ });
174
+ });
175
+ ```
176
+
177
+ ## Common Tasks
178
+
179
+ ### Add New API Method
180
+
181
+ 1. Add type to `src/clob-trading-types.ts`
182
+ 2. Add method to `src/clob-trading-client.ts`
183
+ 3. Add test to `test/unit/clob-trading-client.test.ts`
184
+ 4. Update `src/index.ts` exports if needed
185
+
186
+ ### Add New Config
187
+
188
+ 1. Add to `src/config/*.ts`
189
+ 2. Export from `src/config/index.ts`
190
+ 3. Re-export from `src/index.ts`
191
+
192
+ ### Debug Signature Issues
193
+
194
+ 1. Run SDK comparison test: `bun test test/sdk/reference-examples.test.ts -t "signing"`
195
+ 2. Compare with `.reference/clob-client-repo/tests/` fixtures
196
+ 3. Check EIP712 domain/types match exactly
197
+
198
+ ## Performance
199
+
200
+ Our SDK is significantly faster than the official SDK:
201
+
202
+ | Metric | Value |
203
+ |--------|-------|
204
+ | Average speedup | **139%** |
205
+ | Functions faster | 81/88 (92%) |
206
+ | Best case | 1233% faster (RFQ cancel) |
207
+
208
+ Key optimizations:
209
+ - Native fetch vs axios
210
+ - Web Crypto vs node:crypto polyfills
211
+ - viem vs ethers.js
212
+ - Zero unnecessary serialization
213
+
214
+ ## Environment Variables
215
+
216
+ ```bash
217
+ # Required for trading
218
+ POLYMARKET_API_KEY=...
219
+ POLYMARKET_SECRET=...
220
+ POLYMARKET_PASSPHRASE=...
221
+
222
+ # Required for signing orders
223
+ PRIVATE_KEY=0x...
224
+
225
+ # Optional
226
+ POLYMARKET_BASE_URL=https://clob.polymarket.com # default
227
+ ```
228
+
229
+ ## Useful Commands
230
+
231
+ ```bash
232
+ # Format code
233
+ bun x biome format --write packages/polymarket
234
+
235
+ # Lint
236
+ bun x biome check packages/polymarket
237
+
238
+ # Type check
239
+ bun run typecheck
240
+
241
+ # Check no Node imports
242
+ bun run check:no-node-imports
243
+ ```
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Varla
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,354 @@
1
+ # @varla/polymarket
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@varla/polymarket.svg)](https://www.npmjs.com/package/@varla/polymarket)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![CI](https://github.com/Varla-xyz/varla-api/actions/workflows/ci.yml/badge.svg)](https://github.com/Varla-xyz/varla-api/actions/workflows/ci.yml)
6
+
7
+ **High-performance Polymarket SDK** — 139% faster than the official SDK.
8
+
9
+ A modern, lightweight TypeScript client for Polymarket's CLOB and Gamma APIs with full trading support.
10
+
11
+ ## Why @varla/polymarket?
12
+
13
+ | Metric | @varla/polymarket | @polymarket/clob-client |
14
+ |--------|-------------------|-------------------------|
15
+ | **Average Speed** | **139% faster** | baseline |
16
+ | **Bundle Size** | ~50KB | ~500KB (ethers.js) |
17
+ | **Runtime** | Bun/Node/Edge | Node.js only |
18
+ | **Signing** | viem (native) | ethers.js |
19
+ | **HTTP** | fetch | axios |
20
+
21
+ ### Benchmark Highlights
22
+
23
+ | Function | Speedup |
24
+ |----------|---------|
25
+ | `getLastTradePrice` | 261% faster |
26
+ | `getMidpoints` | 176% faster |
27
+ | `deleteApiKey` | 144% faster |
28
+ | `cancelOrder` | 73% faster |
29
+ | `getOpenOrders` | 56% faster |
30
+
31
+ <details>
32
+ <summary>Full benchmark results (88 functions)</summary>
33
+
34
+ - **81 functions faster** (92%)
35
+ - **7 functions slower** (8%)
36
+ - Best case: 1233% faster (RFQ operations)
37
+
38
+ Run benchmarks yourself:
39
+ ```bash
40
+ POLYMARKET_BENCH=true bun test packages/polymarket/test/sdk
41
+ ```
42
+ </details>
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ bun add @varla/polymarket
48
+ # or
49
+ npm install @varla/polymarket
50
+ # or
51
+ pnpm add @varla/polymarket
52
+ ```
53
+
54
+ **Peer dependencies:**
55
+ - `viem` ^2.0.0
56
+
57
+ ## Quick Start
58
+
59
+ ### Read-Only (No Auth Required)
60
+
61
+ ```typescript
62
+ import { GammaClient, ClobClient } from "@varla/polymarket";
63
+
64
+ // Fetch markets from Gamma API
65
+ const gamma = new GammaClient();
66
+ const markets = await gamma.getMarkets({ limit: 10 });
67
+
68
+ // Get orderbook from CLOB
69
+ const clob = new ClobClient();
70
+ const book = await clob.getBook(markets[0].clobTokenIds[0]);
71
+ console.log("Best bid:", book.bids[0]);
72
+ console.log("Best ask:", book.asks[0]);
73
+
74
+ // Get prices
75
+ const midpoint = await clob.getMidpoint(markets[0].clobTokenIds[0]);
76
+ const spread = await clob.getSpread(markets[0].clobTokenIds[0]);
77
+ ```
78
+
79
+ ### Authenticated Trading
80
+
81
+ ```typescript
82
+ import { createWalletClient, http } from "viem";
83
+ import { privateKeyToAccount } from "viem/accounts";
84
+ import { polygon } from "viem/chains";
85
+ import { ClobTradingClient } from "@varla/polymarket";
86
+
87
+ // Create wallet
88
+ const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
89
+ const walletClient = createWalletClient({
90
+ account,
91
+ chain: polygon,
92
+ transport: http(),
93
+ });
94
+
95
+ // Create trading client
96
+ const client = new ClobTradingClient(walletClient);
97
+ await client.init(); // Derives API key from wallet
98
+
99
+ // Place a limit order
100
+ const response = await client.createAndPostOrder(
101
+ {
102
+ tokenId: "123456...", // From Gamma API
103
+ price: 0.50, // $0.50 per share
104
+ size: 100, // 100 shares
105
+ side: "BUY",
106
+ },
107
+ {
108
+ tickSize: "0.01", // From Gamma API
109
+ negRisk: false, // From Gamma API
110
+ },
111
+ "GTC" // Good-Til-Cancelled
112
+ );
113
+
114
+ console.log("Order ID:", response.orderID);
115
+
116
+ // Cancel order
117
+ await client.cancelOrder(response.orderID);
118
+
119
+ // Get open orders
120
+ const orders = await client.getOpenOrders();
121
+ ```
122
+
123
+ ### WebSocket (Real-time Updates)
124
+
125
+ ```typescript
126
+ import { ClobWsClient } from "@varla/polymarket";
127
+
128
+ const ws = new ClobWsClient({
129
+ onBookUpdate: (update) => {
130
+ console.log("Market:", update.market);
131
+ console.log("Best bid:", update.bids[0]);
132
+ console.log("Best ask:", update.asks[0]);
133
+ },
134
+ onConnect: () => console.log("Connected"),
135
+ onDisconnect: (reason) => console.log("Disconnected:", reason),
136
+ });
137
+
138
+ ws.connect();
139
+ ws.subscribeMarket("0x5f65177b394277fd294cd75650044e32ba009a95...");
140
+
141
+ // Cleanup
142
+ ws.close();
143
+ ```
144
+
145
+ ### Order Persistence (SQLite)
146
+
147
+ Track orders locally for fast queries and restart recovery:
148
+
149
+ ```typescript
150
+ import {
151
+ ClobTradingClient,
152
+ createSqliteOrderPersistence,
153
+ createTrackedOrder,
154
+ } from "@varla/polymarket";
155
+
156
+ const persistence = createSqliteOrderPersistence("./orders.db");
157
+
158
+ // Track placed orders
159
+ const order = createTrackedOrder({
160
+ orderId: response.orderID,
161
+ market: "0x...",
162
+ tokenId: "123456...",
163
+ side: "BUY",
164
+ price: 0.5,
165
+ size: 100,
166
+ orderType: "GTC",
167
+ status: "OPEN",
168
+ });
169
+ await persistence.save(order);
170
+
171
+ // Query orders
172
+ const openOrders = await persistence.getOpen();
173
+ const marketOrders = await persistence.getByMarket("0x...");
174
+
175
+ // Cleanup old orders
176
+ await persistence.prune(24 * 60 * 60 * 1000); // 24h
177
+
178
+ persistence.close();
179
+ ```
180
+
181
+ ## API Reference
182
+
183
+ ### Clients
184
+
185
+ | Client | Purpose |
186
+ |--------|---------|
187
+ | `GammaClient` | Market discovery, metadata, token IDs |
188
+ | `ClobClient` | Public orderbook, prices, trades (read-only) |
189
+ | `ClobTradingClient` | Authenticated trading operations |
190
+ | `ClobWsClient` | Real-time WebSocket updates |
191
+
192
+ ### ClobTradingClient Methods
193
+
194
+ ```typescript
195
+ // Initialization
196
+ client.init() // Derive/create API key
197
+ client.setCredentials(creds) // Set API key manually
198
+
199
+ // Orders
200
+ client.createOrder(params, options) // Create signed order
201
+ client.postOrder(order, type) // Post to CLOB
202
+ client.createAndPostOrder(params, options, type) // Combined
203
+ client.getOrder(orderId) // Get order details
204
+ client.getOpenOrders(filter?) // List open orders
205
+
206
+ // Cancellation
207
+ client.cancelOrder(orderId) // Cancel one order
208
+ client.cancelOrders(orderIds) // Cancel multiple
209
+ client.cancelMarketOrders({ market }) // Cancel by market
210
+ client.cancelAll() // Cancel all orders
211
+
212
+ // Account
213
+ client.getClosedOnlyMode() // Check if account is restricted
214
+ ```
215
+
216
+ ### Order Types
217
+
218
+ ```typescript
219
+ type Side = "BUY" | "SELL";
220
+ type OrderType = "GTC" | "GTD" | "FOK"; // Good-Til-Cancel, Good-Til-Date, Fill-Or-Kill
221
+ type OrderStatus = "OPEN" | "MATCHED" | "FILLED" | "CANCELLED" | "EXPIRED";
222
+ ```
223
+
224
+ ## Configuration
225
+
226
+ ### Environment Variables
227
+
228
+ ```bash
229
+ # For authenticated trading
230
+ POLYMARKET_API_KEY=...
231
+ POLYMARKET_SECRET=...
232
+ POLYMARKET_PASSPHRASE=...
233
+
234
+ # For signing orders
235
+ PRIVATE_KEY=0x...
236
+ ```
237
+
238
+ ### Custom Endpoints
239
+
240
+ ```typescript
241
+ const client = new ClobTradingClient(walletClient, {
242
+ baseUrl: "https://clob.polymarket.com", // default
243
+ requestTimeoutMs: 15000,
244
+ maxRetries: 3,
245
+ });
246
+ ```
247
+
248
+ ### Signature Types
249
+
250
+ | Type | Value | Use Case |
251
+ |------|-------|----------|
252
+ | EOA | 0 | Direct wallet (Metamask, Rabby, hardware) |
253
+ | POLY_PROXY | 1 | Polymarket Magic/Email login |
254
+
255
+ ```typescript
256
+ // For Magic/Email wallets
257
+ const client = new ClobTradingClient(walletClient, {
258
+ signatureType: 1, // POLY_PROXY
259
+ funderAddress: "0x...", // Your Polymarket profile address
260
+ });
261
+ ```
262
+
263
+ ## Error Handling
264
+
265
+ ```typescript
266
+ import { OrderValidationError, ClobHttpError } from "@varla/polymarket";
267
+
268
+ try {
269
+ await client.createAndPostOrder(params, options, "GTC");
270
+ } catch (error) {
271
+ if (error instanceof OrderValidationError) {
272
+ console.error("Invalid order:", error.message);
273
+ } else if (error instanceof ClobHttpError) {
274
+ if (error.status === 401) {
275
+ // API key expired, reinitialize
276
+ await client.init();
277
+ }
278
+ }
279
+ }
280
+ ```
281
+
282
+ ## Validation Utilities
283
+
284
+ ```typescript
285
+ import {
286
+ validateOrderParams,
287
+ roundToTickSize,
288
+ isValidPrice,
289
+ getMinimumOrderSize,
290
+ } from "@varla/polymarket";
291
+
292
+ // Validate before creating
293
+ validateOrderParams(params, options); // throws OrderValidationError
294
+
295
+ // Round to valid tick
296
+ const price = roundToTickSize(0.505, "0.01"); // 0.51
297
+
298
+ // Check price validity
299
+ isValidPrice(0.505, "0.01"); // false
300
+
301
+ // Get minimum shares for $1 order
302
+ getMinimumOrderSize(0.5); // 2 shares
303
+ ```
304
+
305
+ ## Testing
306
+
307
+ ```bash
308
+ # Unit tests
309
+ bun test packages/polymarket/test/unit
310
+
311
+ # All tests
312
+ bun test packages/polymarket
313
+
314
+ # With coverage
315
+ bun test packages/polymarket --coverage
316
+
317
+ # Benchmarks (compare with official SDK)
318
+ POLYMARKET_BENCH=true bun test packages/polymarket/test/sdk
319
+
320
+ # Live tests (requires API keys)
321
+ POLYMARKET_LIVE_TESTS=1 bun test packages/polymarket/test/live
322
+ ```
323
+
324
+ ## Architecture
325
+
326
+ ```
327
+ ┌─────────────────────────────────────────────────────────────┐
328
+ │ ClobTradingClient │
329
+ │ - init(), createAndPostOrder(), cancelOrder(), etc. │
330
+ ├─────────────────────┬───────────────────┬───────────────────┤
331
+ │ ClobAuthManager │ ClobOrderBuilder │ HTTP + Auth │
332
+ │ - L1/L2 auth │ - EIP712 signing │ - HMAC headers │
333
+ │ - API key mgmt │ - Validation │ │
334
+ ├─────────────────────┴───────────────────┴───────────────────┤
335
+ │ viem WalletClient │
336
+ │ (signTypedData, etc.) │
337
+ └─────────────────────────────────────────────────────────────┘
338
+
339
+ ┌──────────────────┐ ┌─────────────────┐ ┌────────────────┐
340
+ │ OrderPersistence │ │ ClobWsClient │ │ GammaClient │
341
+ │ - SQLite/Memory │ │ - WebSocket │ │ - Markets │
342
+ │ - Order tracking │ │ - Book updates │ │ - Metadata │
343
+ └──────────────────┘ └─────────────────┘ └────────────────┘
344
+ ```
345
+
346
+ ## Related Packages
347
+
348
+ - [`@varla/db`](../db) - SQLite persistence layer
349
+ - [`@varla/rpc`](../rpc) - Resilient RPC client
350
+ - [`@varla/runtime`](../runtime) - Service runtime utilities
351
+
352
+ ## License
353
+
354
+ MIT © [Varla](https://varla.xyz)