@surf-ai/sdk 1.0.0-alpha.0 → 1.0.0-alpha.10

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.
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
- };
11
8
  var __export = (target, all) => {
12
9
  for (var name in all)
13
10
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -30,7 +27,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
27
  ));
31
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
29
 
30
+ // src/server/index.ts
31
+ var server_exports = {};
32
+ __export(server_exports, {
33
+ createServer: () => createServer,
34
+ dataApi: () => dataApi
35
+ });
36
+ module.exports = __toCommonJS(server_exports);
37
+
38
+ // src/server/runtime.ts
39
+ var import_express = __toESM(require("express"), 1);
40
+ var import_cors = __toESM(require("cors"), 1);
41
+ var import_fs2 = __toESM(require("fs"), 1);
42
+ var import_path = __toESM(require("path"), 1);
43
+ var import_croner = require("croner");
44
+
33
45
  // src/core/config.ts
46
+ var DEFAULT_API_BASE_URL = "https://api.asksurf.ai/gateway/v1";
34
47
  function trimTrailingSlashes(value) {
35
48
  return String(value || "").replace(/\/+$/, "");
36
49
  }
@@ -50,13 +63,9 @@ function requireSurfApiConfig() {
50
63
  function readAdminApiKey() {
51
64
  return process.env.SURF_API_KEY;
52
65
  }
53
- var DEFAULT_API_BASE_URL;
54
- var init_config = __esm({
55
- "src/core/config.ts"() {
56
- "use strict";
57
- DEFAULT_API_BASE_URL = "https://api.ask.surf/gateway/v1";
58
- }
59
- });
66
+
67
+ // src/db/schema-sync.ts
68
+ var import_fs = __toESM(require("fs"), 1);
60
69
 
61
70
  // src/core/transport.ts
62
71
  function sleep(ms) {
@@ -114,47 +123,154 @@ async function postJson(path2, body) {
114
123
  body: body ? JSON.stringify(body) : void 0
115
124
  });
116
125
  }
117
- var init_transport = __esm({
118
- "src/core/transport.ts"() {
119
- "use strict";
120
- init_config();
121
- }
122
- });
123
126
 
124
127
  // src/data/client.ts
125
- var client_exports = {};
126
- __export(client_exports, {
127
- get: () => get,
128
- post: () => post
129
- });
130
128
  async function get(path2, params) {
131
129
  return getJson(path2, params);
132
130
  }
133
131
  async function post(path2, body) {
134
132
  return postJson(path2, body);
135
133
  }
136
- var init_client = __esm({
137
- "src/data/client.ts"() {
138
- "use strict";
139
- init_transport();
140
- }
141
- });
142
134
 
143
- // src/server/index.ts
144
- var server_exports = {};
145
- __export(server_exports, {
146
- createServer: () => createServer,
147
- dataApi: () => dataApi
148
- });
149
- module.exports = __toCommonJS(server_exports);
135
+ // src/db/schema-sync.ts
136
+ var syncing = false;
137
+ async function syncSchema(options) {
138
+ const { schemaPath, retries = 3, retryDelay = 2e3 } = options;
139
+ for (let i = 0; i < retries; i++) {
140
+ try {
141
+ await doSyncSchema(schemaPath);
142
+ return;
143
+ } catch (err) {
144
+ console.error(`DB schema sync attempt ${i + 1}/${retries} failed: ${err.message}`);
145
+ if (i < retries - 1) await new Promise((r) => setTimeout(r, retryDelay * (i + 1)));
146
+ }
147
+ }
148
+ console.error("DB schema sync failed after all retries");
149
+ }
150
+ async function doSyncSchema(schemaPath) {
151
+ if (syncing) return;
152
+ syncing = true;
153
+ try {
154
+ if (!import_fs.default.existsSync(schemaPath)) return;
155
+ let schema;
156
+ if (schemaPath.endsWith(".ts")) {
157
+ try {
158
+ schema = await import(`${schemaPath}?t=${Date.now()}`);
159
+ } catch (err) {
160
+ if (err instanceof SyntaxError) {
161
+ console.log("DB: schema file has syntax error, waiting for next change...");
162
+ return;
163
+ }
164
+ if (err.message.includes("Cannot find module") || err.message.includes("is not a function")) {
165
+ return;
166
+ }
167
+ throw err;
168
+ }
169
+ } else {
170
+ try {
171
+ delete require.cache[require.resolve(schemaPath)];
172
+ } catch {
173
+ }
174
+ try {
175
+ schema = require(schemaPath);
176
+ } catch (err) {
177
+ if (err instanceof SyntaxError) {
178
+ console.log("DB: schema file has syntax error, waiting for next change...");
179
+ return;
180
+ }
181
+ if (err.message.includes("Cannot find module") || err.message.includes("is not a function")) {
182
+ return;
183
+ }
184
+ throw err;
185
+ }
186
+ }
187
+ let getTableConfig;
188
+ try {
189
+ getTableConfig = require("drizzle-orm/pg-core").getTableConfig;
190
+ } catch {
191
+ return;
192
+ }
193
+ const tables = Object.values(schema).filter(
194
+ (t) => t && typeof t === "object" && /* @__PURE__ */ Symbol.for("drizzle:Name") in t
195
+ );
196
+ if (tables.length === 0) return;
197
+ await post("db/provision", {});
198
+ const tablesResult = await get("db/tables");
199
+ const tablesList = Array.isArray(tablesResult) ? tablesResult : tablesResult.tables || [];
200
+ const existing = tablesList.map((t) => typeof t === "string" ? t : t.name);
201
+ const missing = tables.filter((t) => !existing.includes(getTableConfig(t).name));
202
+ if (missing.length > 0) {
203
+ const { generateDrizzleJson, generateMigration } = require("drizzle-kit/api");
204
+ const missingSchema = {};
205
+ for (const t of missing) missingSchema[getTableConfig(t).name] = t;
206
+ const sqls = await generateMigration(generateDrizzleJson({}), generateDrizzleJson(missingSchema));
207
+ for (const sql of sqls) {
208
+ for (let attempt = 0; attempt < 2; attempt++) {
209
+ try {
210
+ await post("db/query", { sql, params: [] });
211
+ console.log(`DB: Executed: ${sql.slice(0, 80)}...`);
212
+ break;
213
+ } catch (err) {
214
+ if (attempt === 0) {
215
+ console.warn(`DB: Retrying after: ${err.message}`);
216
+ await new Promise((r) => setTimeout(r, 1500));
217
+ } else {
218
+ console.error(`DB: Failed: ${sql.slice(0, 80)}... \u2014 ${err.message}`);
219
+ }
220
+ }
221
+ }
222
+ }
223
+ }
224
+ const existingTables = tables.filter((t) => existing.includes(getTableConfig(t).name));
225
+ for (const t of existingTables) {
226
+ const cfg = getTableConfig(t);
227
+ try {
228
+ const live = await get("db/table-schema", { table: cfg.name });
229
+ const liveCols = new Set((live.columns || []).map((c) => c.name));
230
+ for (const col of cfg.columns) {
231
+ if (!liveCols.has(col.name)) {
232
+ const colType = col.getSQLType();
233
+ const ddl = `ALTER TABLE "${cfg.name}" ADD COLUMN IF NOT EXISTS "${col.name}" ${colType}`;
234
+ try {
235
+ await post("db/query", { sql: ddl, params: [] });
236
+ console.log(`DB: Added column ${col.name} to ${cfg.name}`);
237
+ } catch (err) {
238
+ console.warn(`DB: Failed to add column ${col.name} to ${cfg.name}: ${err.message}`);
239
+ }
240
+ }
241
+ }
242
+ } catch (err) {
243
+ console.warn(`DB: Column check failed for ${cfg.name}: ${err.message}`);
244
+ }
245
+ }
246
+ } finally {
247
+ syncing = false;
248
+ }
249
+ }
250
+ function watchSchema(schemaPath, options) {
251
+ const { debounceMs = 1e3, retries = 2, retryDelay = 1500 } = options || {};
252
+ if (!import_fs.default.existsSync(schemaPath)) return () => {
253
+ };
254
+ let debounce = null;
255
+ import_fs.default.watchFile(schemaPath, { interval: 2e3 }, () => {
256
+ if (debounce) clearTimeout(debounce);
257
+ debounce = setTimeout(async () => {
258
+ console.log("DB: schema file changed, re-syncing tables...");
259
+ try {
260
+ await syncSchema({ schemaPath, retries, retryDelay });
261
+ console.log("DB: schema re-sync complete");
262
+ } catch (err) {
263
+ console.error(`DB: schema re-sync failed: ${err.message}`);
264
+ }
265
+ }, debounceMs);
266
+ });
267
+ return () => {
268
+ import_fs.default.unwatchFile(schemaPath);
269
+ if (debounce) clearTimeout(debounce);
270
+ };
271
+ }
150
272
 
151
273
  // src/server/runtime.ts
152
- var import_express = __toESM(require("express"), 1);
153
- var import_cors = __toESM(require("cors"), 1);
154
- var import_fs = __toESM(require("fs"), 1);
155
- var import_path = __toESM(require("path"), 1);
156
- var import_croner = require("croner");
157
- init_config();
158
274
  function requireBearerAuth(req, res, next) {
159
275
  const apiKey = readAdminApiKey();
160
276
  if (!apiKey) {
@@ -166,9 +282,10 @@ function requireBearerAuth(req, res, next) {
166
282
  next();
167
283
  }
168
284
  function createServer(options = {}) {
169
- const port = options.port ?? (process.env.PORT ? Number.parseInt(process.env.PORT, 10) : void 0);
285
+ const rawPort = process.env.BACKEND_PORT;
286
+ const port = options.port ?? (rawPort ? Number.parseInt(rawPort, 10) : void 0);
170
287
  if (!Number.isInteger(port)) {
171
- throw new Error("createServer requires a port via options.port or process.env.PORT");
288
+ throw new Error("createServer requires a port via options.port or BACKEND_PORT env var");
172
289
  }
173
290
  const routesDir = options.routesDir || import_path.default.join(process.cwd(), "routes");
174
291
  const cronDir = options.cronDir || process.cwd();
@@ -178,8 +295,8 @@ function createServer(options = {}) {
178
295
  app.get("/api/health", (_req, res) => {
179
296
  res.json({ status: "ok" });
180
297
  });
181
- if (import_fs.default.existsSync(routesDir)) {
182
- for (const file of import_fs.default.readdirSync(routesDir)) {
298
+ if (import_fs2.default.existsSync(routesDir)) {
299
+ for (const file of import_fs2.default.readdirSync(routesDir)) {
183
300
  if (!file.endsWith(".js") && !file.endsWith(".ts")) continue;
184
301
  const name = file.replace(/\.(js|ts)$/, "");
185
302
  try {
@@ -217,108 +334,11 @@ var schemaSync = { run: async () => {
217
334
  }, watch: () => {
218
335
  } };
219
336
  function setupSchemaSync(app, schemaDir) {
220
- let syncing = false;
221
337
  let schemaReady = false;
222
- async function doSyncSchema() {
223
- if (syncing) return;
224
- syncing = true;
225
- try {
226
- const schemaPath = import_path.default.join(schemaDir, "schema.js");
227
- if (!import_fs.default.existsSync(schemaPath)) return;
228
- try {
229
- delete require.cache[require.resolve(schemaPath)];
230
- } catch {
231
- }
232
- let schema;
233
- try {
234
- schema = require(schemaPath);
235
- } catch (err) {
236
- if (err instanceof SyntaxError) {
237
- console.log("DB: schema.js has syntax error, waiting for next change...");
238
- return;
239
- }
240
- if (err.message.includes("Cannot find module") || err.message.includes("is not a function")) {
241
- return;
242
- }
243
- throw err;
244
- }
245
- let getTableConfig;
246
- try {
247
- getTableConfig = require("drizzle-orm/pg-core").getTableConfig;
248
- } catch {
249
- return;
250
- }
251
- const tables = Object.values(schema).filter(
252
- (t) => t && typeof t === "object" && /* @__PURE__ */ Symbol.for("drizzle:Name") in t
253
- );
254
- if (tables.length === 0) return;
255
- const { get: dbGet, post: dbPost } = await Promise.resolve().then(() => (init_client(), client_exports));
256
- await dbPost("db/provision");
257
- const existing = (await dbGet("db/tables")).map((t) => t.name);
258
- const missing = tables.filter((t) => !existing.includes(getTableConfig(t).name));
259
- if (missing.length > 0) {
260
- const { generateDrizzleJson, generateMigration } = require("drizzle-kit/api");
261
- const missingSchema = {};
262
- for (const t of missing) missingSchema[getTableConfig(t).name] = t;
263
- const sqls = await generateMigration(generateDrizzleJson({}), generateDrizzleJson(missingSchema));
264
- for (const sql of sqls) {
265
- for (let attempt = 0; attempt < 2; attempt++) {
266
- try {
267
- await dbPost("db/query", { sql, params: [] });
268
- console.log(`DB: Executed: ${sql.slice(0, 80)}...`);
269
- break;
270
- } catch (err) {
271
- if (attempt === 0) {
272
- console.warn(`DB: Retrying after: ${err.message}`);
273
- await new Promise((r) => setTimeout(r, 1500));
274
- } else {
275
- console.error(`DB: Failed: ${sql.slice(0, 80)}... \u2014 ${err.message}`);
276
- }
277
- }
278
- }
279
- }
280
- }
281
- const existingTables = tables.filter((t) => existing.includes(getTableConfig(t).name));
282
- for (const t of existingTables) {
283
- const cfg = getTableConfig(t);
284
- try {
285
- const live = await dbGet("db/table-schema", { table: cfg.name });
286
- const liveCols = new Set((live.columns || []).map((c) => c.name));
287
- for (const col of cfg.columns) {
288
- if (!liveCols.has(col.name)) {
289
- const colType = col.getSQLType();
290
- const ddl = `ALTER TABLE "${cfg.name}" ADD COLUMN IF NOT EXISTS "${col.name}" ${colType}`;
291
- try {
292
- await dbPost("db/query", { sql: ddl, params: [] });
293
- console.log(`DB: Added column ${col.name} to ${cfg.name}`);
294
- } catch (err) {
295
- console.warn(`DB: Failed to add column ${col.name} to ${cfg.name}: ${err.message}`);
296
- }
297
- }
298
- }
299
- } catch (err) {
300
- console.warn(`DB: Column check failed for ${cfg.name}: ${err.message}`);
301
- }
302
- }
303
- } finally {
304
- syncing = false;
305
- }
306
- }
307
- async function syncWithRetry(retries = 3, delay = 2e3) {
308
- for (let i = 0; i < retries; i++) {
309
- try {
310
- await doSyncSchema();
311
- return;
312
- } catch (err) {
313
- console.error(`DB schema sync attempt ${i + 1}/${retries} failed: ${err.message}`);
314
- if (i < retries - 1) await new Promise((r) => setTimeout(r, delay * (i + 1)));
315
- }
316
- }
317
- console.error("DB schema sync failed after all retries");
318
- }
338
+ const schemaPath = import_path.default.join(schemaDir, "schema.js");
319
339
  app.post("/api/__sync-schema", requireBearerAuth, async (_req, res) => {
320
340
  try {
321
- await syncWithRetry(2, 1500);
341
+ await syncSchema({ schemaPath, retries: 2, retryDelay: 1500 });
322
342
  res.json({ ok: true });
323
343
  } catch (err) {
324
344
  res.status(500).json({ ok: false, error: err.message });
@@ -330,7 +350,7 @@ function setupSchemaSync(app, schemaDir) {
330
350
  });
331
351
  schemaSync.run = async () => {
332
352
  try {
333
- await syncWithRetry();
353
+ await syncSchema({ schemaPath });
334
354
  schemaReady = true;
335
355
  console.log("Schema sync complete, API ready");
336
356
  } catch {
@@ -339,21 +359,7 @@ function setupSchemaSync(app, schemaDir) {
339
359
  }
340
360
  };
341
361
  schemaSync.watch = () => {
342
- const schemaPath = import_path.default.join(schemaDir, "schema.js");
343
- if (!import_fs.default.existsSync(schemaPath)) return;
344
- let debounce = null;
345
- import_fs.default.watchFile(schemaPath, { interval: 2e3 }, () => {
346
- if (debounce) clearTimeout(debounce);
347
- debounce = setTimeout(async () => {
348
- console.log("DB: schema.js changed, re-syncing tables...");
349
- try {
350
- await syncWithRetry(2, 1500);
351
- console.log("DB: schema re-sync complete");
352
- } catch (err) {
353
- console.error(`DB: schema re-sync failed: ${err.message}`);
354
- }
355
- }, 1e3);
356
- });
362
+ watchSchema(schemaPath);
357
363
  };
358
364
  }
359
365
  function setupCron(app, cronDir) {
@@ -369,10 +375,10 @@ function setupCron(app, cronDir) {
369
375
  }
370
376
  cronJobs.clear();
371
377
  const cronPath = import_path.default.join(cronDir, "cron.json");
372
- if (!import_fs.default.existsSync(cronPath)) return;
378
+ if (!import_fs2.default.existsSync(cronPath)) return;
373
379
  let tasks;
374
380
  try {
375
- tasks = JSON.parse(import_fs.default.readFileSync(cronPath, "utf-8"));
381
+ tasks = JSON.parse(import_fs2.default.readFileSync(cronPath, "utf-8"));
376
382
  } catch (e) {
377
383
  console.error("Failed to parse cron.json:", e.message);
378
384
  return;
@@ -453,7 +459,7 @@ function setupCron(app, cronDir) {
453
459
  const cronPath = import_path.default.join(cronDir, "cron.json");
454
460
  let tasks = [];
455
461
  try {
456
- if (import_fs.default.existsSync(cronPath)) tasks = JSON.parse(import_fs.default.readFileSync(cronPath, "utf8"));
462
+ if (import_fs2.default.existsSync(cronPath)) tasks = JSON.parse(import_fs2.default.readFileSync(cronPath, "utf8"));
457
463
  } catch {
458
464
  tasks = [];
459
465
  }
@@ -462,7 +468,7 @@ function setupCron(app, cronDir) {
462
468
  }
463
469
  const newTask = { id, name, schedule, handler, enabled, timeout };
464
470
  tasks.push(newTask);
465
- import_fs.default.writeFileSync(cronPath, JSON.stringify(tasks, null, 2));
471
+ import_fs2.default.writeFileSync(cronPath, JSON.stringify(tasks, null, 2));
466
472
  loadCronJobs();
467
473
  res.status(201).json(newTask);
468
474
  });
@@ -470,7 +476,7 @@ function setupCron(app, cronDir) {
470
476
  const cronPath = import_path.default.join(cronDir, "cron.json");
471
477
  let tasks = [];
472
478
  try {
473
- if (import_fs.default.existsSync(cronPath)) tasks = JSON.parse(import_fs.default.readFileSync(cronPath, "utf8"));
479
+ if (import_fs2.default.existsSync(cronPath)) tasks = JSON.parse(import_fs2.default.readFileSync(cronPath, "utf8"));
474
480
  } catch {
475
481
  tasks = [];
476
482
  }
@@ -491,7 +497,7 @@ function setupCron(app, cronDir) {
491
497
  }
492
498
  }
493
499
  tasks[idx] = { ...tasks[idx], ...updates, id: req.params.id };
494
- import_fs.default.writeFileSync(cronPath, JSON.stringify(tasks, null, 2));
500
+ import_fs2.default.writeFileSync(cronPath, JSON.stringify(tasks, null, 2));
495
501
  loadCronJobs();
496
502
  res.json(tasks[idx]);
497
503
  });
@@ -499,14 +505,14 @@ function setupCron(app, cronDir) {
499
505
  const cronPath = import_path.default.join(cronDir, "cron.json");
500
506
  let tasks = [];
501
507
  try {
502
- if (import_fs.default.existsSync(cronPath)) tasks = JSON.parse(import_fs.default.readFileSync(cronPath, "utf8"));
508
+ if (import_fs2.default.existsSync(cronPath)) tasks = JSON.parse(import_fs2.default.readFileSync(cronPath, "utf8"));
503
509
  } catch {
504
510
  tasks = [];
505
511
  }
506
512
  const idx = tasks.findIndex((t) => t.id === req.params.id);
507
513
  if (idx === -1) return res.status(404).json({ error: "Task not found" });
508
514
  tasks.splice(idx, 1);
509
- import_fs.default.writeFileSync(cronPath, JSON.stringify(tasks, null, 2));
515
+ import_fs2.default.writeFileSync(cronPath, JSON.stringify(tasks, null, 2));
510
516
  cronState.delete(req.params.id);
511
517
  loadCronJobs();
512
518
  res.json({ ok: true });
@@ -524,11 +530,7 @@ function setupCron(app, cronDir) {
524
530
  loadCronJobs();
525
531
  }
526
532
 
527
- // src/data/data-api.ts
528
- init_client();
529
-
530
533
  // src/data/categories/exchange.ts
531
- init_client();
532
534
  var exchange = {
533
535
  /** Returns order book bid/ask levels with computed stats. **Included fields:** spread, spread percentage, mid-price, and total bid/ask depth. Use `limit` to control the number of price levels (1–100, default 20). Set `type=swap` to query perpetual contract order books instead of spot. */
534
536
  depth: (params) => get("exchange/depth", params),
@@ -547,7 +549,6 @@ var exchange = {
547
549
  };
548
550
 
549
551
  // src/data/categories/fund.ts
550
- init_client();
551
552
  var fund = {
552
553
  /** Returns a fund's **profile metadata**. **Included fields:** X accounts, team members, recent research, invested project count. This does NOT return the list of investments — use `/fund/portfolio` for that. **Lookup:** by UUID (`id`) or name (`q`). Returns 404 if not found. */
553
554
  detail: (params) => get("fund/detail", params),
@@ -558,7 +559,6 @@ var fund = {
558
559
  };
559
560
 
560
561
  // src/data/categories/kalshi.ts
561
- init_client();
562
562
  var kalshi = {
563
563
  /** Returns Kalshi events with nested markets, optionally filtered by `event_ticker`. Each event includes market count and a list of markets. **Data refresh:** ~30 minutes */
564
564
  events: (params) => get("prediction-market/kalshi/events", params),
@@ -577,7 +577,6 @@ var kalshi = {
577
577
  };
578
578
 
579
579
  // src/data/categories/market.ts
580
- init_client();
581
580
  var market = {
582
581
  /** Returns daily ETF flow history for US spot ETFs. **Included fields:** net flow (USD), token price, per-ticker breakdown. Sorted by date descending. `symbol`: `BTC` or `ETH`. */
583
582
  etf: (params) => get("market/etf", params),
@@ -604,7 +603,6 @@ var market = {
604
603
  };
605
604
 
606
605
  // src/data/categories/matching.ts
607
- init_client();
608
606
  var matching = {
609
607
  /** Returns daily volume and open interest comparison for a specific matched market pair. Both `polymarket_condition_id` and `kalshi_market_ticker` are required. **Volume units:** Polymarket = USD, Kalshi = contracts. */
610
608
  market_daily: (params) => get("prediction-market/matching/daily", params),
@@ -615,7 +613,6 @@ var matching = {
615
613
  };
616
614
 
617
615
  // src/data/categories/news.ts
618
- init_client();
619
616
  var news = {
620
617
  /** Returns the full content of a single news article by its ID (returned as `id` in feed and search results). */
621
618
  detail: (params) => get("news/detail", params),
@@ -624,7 +621,6 @@ var news = {
624
621
  };
625
622
 
626
623
  // src/data/categories/onchain.ts
627
- init_client();
628
624
  var onchain = {
629
625
  /** Returns bridge protocols ranked by total USD volume over a specified time range. */
630
626
  bridge_ranking: (params) => get("onchain/bridge/ranking", params),
@@ -643,7 +639,6 @@ var onchain = {
643
639
  };
644
640
 
645
641
  // src/data/categories/polymarket.ts
646
- init_client();
647
642
  var polymarket = {
648
643
  /** Returns trade and redemption activity for a Polymarket wallet. **Data refresh:** ~30 minutes */
649
644
  activity: (params) => get("prediction-market/polymarket/activity", params),
@@ -666,14 +661,12 @@ var polymarket = {
666
661
  };
667
662
 
668
663
  // src/data/categories/prediction_market.ts
669
- init_client();
670
664
  var prediction_market = {
671
665
  /** Returns daily notional volume and open interest aggregated by category across Kalshi and Polymarket. **Filters:** `source` or `category`. **Data refresh:** daily */
672
666
  category_metrics: (params) => get("prediction-market/category-metrics", params)
673
667
  };
674
668
 
675
669
  // src/data/categories/project.ts
676
- init_client();
677
670
  var project = {
678
671
  /** Returns time-series DeFi metrics for a project. **Available metrics:** `volume`, `fee`, `fees`, `revenue`, `tvl`, `users`. **Lookup:** by UUID (`id`) or name (`q`). Filter by `chain` and date range (`from`/`to`). Returns 404 if the project is not found. **Note:** this endpoint only returns data for DeFi protocol projects (e.g. `aave`, `uniswap`, `lido`, `makerdao`). Use `q` with a DeFi protocol name. */
679
672
  defi_metrics: (params) => get("project/defi/metrics", params),
@@ -684,7 +677,6 @@ var project = {
684
677
  };
685
678
 
686
679
  // src/data/categories/search.ts
687
- init_client();
688
680
  var search = {
689
681
  /** Searches and filters airdrop opportunities. **Filters:** keyword, status, reward type, task type. Returns paginated results with optional task details. */
690
682
  airdrop: (params) => get("search/airdrop", params),
@@ -711,7 +703,6 @@ var search = {
711
703
  };
712
704
 
713
705
  // src/data/categories/social.ts
714
- init_client();
715
706
  var social = {
716
707
  /** Returns a **point-in-time snapshot** of social analytics for a project. **Available fields** (via `fields`): `sentiment`, `follower_geo`, `smart_followers`. **Lookup:** by X account ID (`x_id`) or project name (`q`, e.g. `uniswap`, `solana`). The `q` parameter must be a crypto project name, not a personal Twitter handle. Returns 404 if the project has no linked Twitter account. For sentiment **trends over time**, use `/social/mindshare` instead. */
717
708
  detail: (params) => get("social/detail", params),
@@ -738,7 +729,6 @@ var social = {
738
729
  };
739
730
 
740
731
  // src/data/categories/token.ts
741
- init_client();
742
732
  var token = {
743
733
  /** Returns recent DEX swap events for a token contract address. **Covered DEXes:** `uniswap`, `sushiswap`, `curve`, `balancer`. **Included fields:** trading pair, amounts, USD value, taker address. **Data refresh:** ~24 hours · **Chains:** Ethereum, Base */
744
734
  dex_trades: (params) => get("token/dex-trades", params),
@@ -751,7 +741,6 @@ var token = {
751
741
  };
752
742
 
753
743
  // src/data/categories/v2.ts
754
- init_client();
755
744
  var v2 = {
756
745
  /** Historical orderbook snapshots for a Kalshi market. Returns yes-side bid/ask levels. Timestamps in milliseconds, prices in cents. Data refresh: ~5 minutes */
757
746
  kalshi_orderbooks: (params) => get("gateway/v2/kalshi/orderbooks", params),
@@ -766,7 +755,6 @@ var v2 = {
766
755
  };
767
756
 
768
757
  // src/data/categories/wallet.ts
769
- init_client();
770
758
  var wallet = {
771
759
  /** Returns multiple wallet sub-resources in a single request. **Available fields** (via `fields`): `balance`, `tokens`, `labels`, `nft`. **Lookup:** by `address`. Partial failures return available fields with per-field error info. Returns 422 if `fields` is invalid. */
772
760
  detail: (params) => get("wallet/detail", params),
@@ -783,7 +771,6 @@ var wallet = {
783
771
  };
784
772
 
785
773
  // src/data/categories/web.ts
786
- init_client();
787
774
  var web = {
788
775
  /** Fetches a web page and converts it to clean, LLM-friendly markdown. **Options:** - `target_selector` — extract specific page sections - `remove_selector` — strip unwanted elements Returns 400 if the URL is invalid or unreachable. */
789
776
  fetch: (params) => get("web/fetch", params)