@secondlayer/cli 1.6.0 → 1.6.2

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.
Files changed (3) hide show
  1. package/dist/cli.js +163 -149
  2. package/dist/cli.js.map +20 -20
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2229,8 +2229,8 @@ function migrateConfig(raw) {
2229
2229
  if (typeof old.dataDir === "string") {
2230
2230
  migrated.dataDir = old.dataDir;
2231
2231
  }
2232
- if (typeof old.defaultWebhookUrl === "string") {
2233
- migrated.defaultWebhookUrl = old.defaultWebhookUrl;
2232
+ if (typeof old.defaultEndpointUrl === "string") {
2233
+ migrated.defaultEndpointUrl = old.defaultEndpointUrl;
2234
2234
  }
2235
2235
  if (typeof old.nodeInstallPath === "string" || typeof old.nodeNetwork === "string") {
2236
2236
  migrated.node = {
@@ -2270,8 +2270,8 @@ async function loadConfig() {
2270
2270
  }
2271
2271
  }
2272
2272
  config = applyEnvOverrides(config);
2273
- if (!config.defaultWebhookUrl && config.network === "local") {
2274
- config.defaultWebhookUrl = LOCAL_WEBHOOK_URL;
2273
+ if (!config.defaultEndpointUrl && config.network === "local") {
2274
+ config.defaultEndpointUrl = LOCAL_ENDPOINT_URL;
2275
2275
  }
2276
2276
  return config;
2277
2277
  }
@@ -2301,12 +2301,15 @@ function applyEnvOverrides(config) {
2301
2301
  result.ports = { ...result.ports, indexer: port };
2302
2302
  }
2303
2303
  }
2304
- if (process.env.SL_WEBHOOK_PORT) {
2305
- const port = parseInt(process.env.SL_WEBHOOK_PORT, 10);
2304
+ if (process.env.SL_RECEIVER_PORT) {
2305
+ const port = parseInt(process.env.SL_RECEIVER_PORT, 10);
2306
2306
  if (!isNaN(port) && port > 0 && port <= 65535) {
2307
- result.ports = { ...result.ports, webhook: port };
2307
+ result.ports = { ...result.ports, receiver: port };
2308
2308
  }
2309
2309
  }
2310
+ if (process.env.STACKS_NODE_RPC_URL) {
2311
+ result.nodeRpcUrl = process.env.STACKS_NODE_RPC_URL;
2312
+ }
2310
2313
  if (process.env.DATABASE_URL) {
2311
2314
  result.database = { type: "external", url: process.env.DATABASE_URL };
2312
2315
  }
@@ -2395,13 +2398,13 @@ function isDefaultValue(config, key) {
2395
2398
  const defaultValue = getConfigValue(DEFAULT_CONFIG, key);
2396
2399
  return JSON.stringify(currentValue) === JSON.stringify(defaultValue);
2397
2400
  }
2398
- var PortsSchema, NodeSchema, DatabaseSchema, NetworkSchema, API_URLS, ConfigSchema, CONFIG_DIR, CONFIG_PATH, LOCAL_WEBHOOK_URL = "http://localhost:3900/webhook", DEFAULT_CONFIG;
2401
+ var PortsSchema, NodeSchema, DatabaseSchema, NetworkSchema, API_URLS, ConfigSchema, CONFIG_DIR, CONFIG_PATH, LOCAL_ENDPOINT_URL = "http://localhost:3900/receiver", DEFAULT_CONFIG;
2399
2402
  var init_config = __esm(() => {
2400
2403
  init_fs();
2401
2404
  PortsSchema = z.object({
2402
2405
  api: z.number().int().min(1).max(65535).default(3800),
2403
2406
  indexer: z.number().int().min(1).max(65535).default(3700),
2404
- webhook: z.number().int().min(1).max(65535).default(3900)
2407
+ receiver: z.number().int().min(1).max(65535).default(3900)
2405
2408
  });
2406
2409
  NodeSchema = z.object({
2407
2410
  installPath: z.string().min(1),
@@ -2421,8 +2424,9 @@ var init_config = __esm(() => {
2421
2424
  network: NetworkSchema.default("mainnet"),
2422
2425
  apiUrl: z.string().url().optional(),
2423
2426
  apiKey: z.string().optional(),
2427
+ nodeRpcUrl: z.string().url().optional(),
2424
2428
  dataDir: z.string().default("~/.secondlayer/data"),
2425
- defaultWebhookUrl: z.string().url().optional(),
2429
+ defaultEndpointUrl: z.string().url().optional(),
2426
2430
  node: NodeSchema.optional(),
2427
2431
  ports: PortsSchema.default({}),
2428
2432
  database: DatabaseSchema.default({})
@@ -2432,7 +2436,7 @@ var init_config = __esm(() => {
2432
2436
  DEFAULT_CONFIG = {
2433
2437
  network: "mainnet",
2434
2438
  dataDir: "~/.secondlayer/data",
2435
- ports: { api: 3800, indexer: 3700, webhook: 3900 },
2439
+ ports: { api: 3800, indexer: 3700, receiver: 3900 },
2436
2440
  database: { type: "docker" }
2437
2441
  };
2438
2442
  });
@@ -12429,19 +12433,26 @@ function parseContractId(contractId) {
12429
12433
 
12430
12434
  // src/utils/api.ts
12431
12435
  class StacksApiClient {
12432
- static hasWarnedAboutApiKey = false;
12433
12436
  baseUrl;
12434
12437
  headers;
12435
- constructor(network = "mainnet", apiKey, apiUrl) {
12436
- this.baseUrl = apiUrl || API_URLS2[network];
12437
- this.headers = apiKey ? { "x-api-key": apiKey } : {};
12438
- if (!apiKey && !StacksApiClient.hasWarnedAboutApiKey) {
12439
- console.warn(`⚠️ No API key provided. You may be rate-limited.
12440
- ` + ` Set HIRO_API_KEY env var or use --api-key flag.
12441
- ` + " Get a free key at: https://platform.hiro.so/");
12442
- StacksApiClient.hasWarnedAboutApiKey = true;
12438
+ useProxy;
12439
+ constructor(network = "mainnet", apiKey, apiUrl, slApiUrl) {
12440
+ this.useProxy = !apiUrl && network !== "devnet";
12441
+ if (this.useProxy) {
12442
+ this.baseUrl = slApiUrl || "";
12443
+ this.headers = {};
12444
+ } else {
12445
+ this.baseUrl = apiUrl || process.env.STACKS_NODE_RPC_URL || "http://localhost:3999";
12446
+ this.headers = apiKey ? { "x-api-key": apiKey } : {};
12443
12447
  }
12444
12448
  }
12449
+ async ensureProxy() {
12450
+ if (!this.useProxy || this.baseUrl)
12451
+ return;
12452
+ const config = await loadConfig();
12453
+ this.baseUrl = resolveApiUrl(config);
12454
+ this.headers = authHeaders(config);
12455
+ }
12445
12456
  async fetchWithErrorHandling(url, resourceType, resourceId) {
12446
12457
  try {
12447
12458
  const response2 = await gotWithRetry(url, {
@@ -12450,30 +12461,38 @@ class StacksApiClient {
12450
12461
  });
12451
12462
  return response2.body;
12452
12463
  } catch (error2) {
12464
+ if (error2.response?.statusCode === 401) {
12465
+ throw new Error("Authentication required. Run: secondlayer auth login");
12466
+ }
12453
12467
  if (error2.response?.statusCode === 404) {
12454
12468
  throw new Error(`${resourceType} not found: ${resourceId}`);
12455
12469
  }
12456
- if (error2.response?.statusCode === 429) {
12457
- throw new Error("Rate limited. Please provide an API key in your config.");
12458
- }
12459
12470
  throw new Error(`Failed to fetch ${resourceType.toLowerCase()}: ${error2.message}`);
12460
12471
  }
12461
12472
  }
12462
12473
  async getContractInfo(contractId) {
12474
+ await this.ensureProxy();
12475
+ if (this.useProxy) {
12476
+ const url2 = `${this.baseUrl}/api/node/contracts/${contractId}/abi`;
12477
+ return this.fetchWithErrorHandling(url2, "Contract", contractId);
12478
+ }
12463
12479
  const { address, contractName } = parseContractId(contractId);
12464
12480
  const url = `${this.baseUrl}/v2/contracts/interface/${address}/${contractName}`;
12465
12481
  return this.fetchWithErrorHandling(url, "Contract", contractId);
12466
12482
  }
12467
12483
  async getContractSource(contractId) {
12468
12484
  const { address, contractName } = parseContractId(contractId);
12469
- const url = `${this.baseUrl}/v2/contracts/source/${address}/${contractName}`;
12485
+ const rpcUrl = process.env.STACKS_NODE_RPC_URL || this.baseUrl;
12486
+ const url = `${rpcUrl}/v2/contracts/source/${address}/${contractName}`;
12470
12487
  const data = await this.fetchWithErrorHandling(url, "Contract source", contractId);
12471
12488
  return data.source;
12472
12489
  }
12473
12490
  }
12474
- var gotWithRetry, API_URLS2;
12491
+ var gotWithRetry;
12475
12492
  var init_api = __esm(() => {
12476
12493
  init_source3();
12494
+ init_config();
12495
+ init_api_client();
12477
12496
  gotWithRetry = source_default2.extend({
12478
12497
  timeout: { request: 30000 },
12479
12498
  retry: {
@@ -12483,11 +12502,6 @@ var init_api = __esm(() => {
12483
12502
  calculateDelay: ({ attemptCount }) => attemptCount * 1000
12484
12503
  }
12485
12504
  });
12486
- API_URLS2 = {
12487
- mainnet: "https://api.hiro.so",
12488
- testnet: "https://api.testnet.hiro.so",
12489
- devnet: "http://localhost:3999"
12490
- };
12491
12505
  });
12492
12506
 
12493
12507
  // src/utils/network.ts
@@ -13189,9 +13203,9 @@ var init_api2 = __esm(() => {
13189
13203
  init_manager();
13190
13204
  });
13191
13205
 
13192
- // src/services/webhook-server.ts
13206
+ // src/services/receiver-server.ts
13193
13207
  import { verifySignatureHeader } from "@secondlayer/shared/crypto";
13194
- function startWebhookServer(options2 = {}) {
13208
+ function startReceiverServer(options2 = {}) {
13195
13209
  const port = options2.port ?? 3900;
13196
13210
  const responseCode = options2.responseCode ?? 200;
13197
13211
  server = Bun.serve({
@@ -13230,27 +13244,27 @@ function startWebhookServer(options2 = {}) {
13230
13244
  body,
13231
13245
  signatureValid
13232
13246
  };
13233
- if (options2.onWebhook) {
13234
- options2.onWebhook(event);
13247
+ if (options2.onDelivery) {
13248
+ options2.onDelivery(event);
13235
13249
  } else {
13236
- logWebhook(event);
13250
+ logDelivery(event);
13237
13251
  }
13238
13252
  return new Response("OK", { status: responseCode });
13239
13253
  }
13240
13254
  });
13241
13255
  return port;
13242
13256
  }
13243
- function stopWebhookServer() {
13257
+ function stopReceiverServer() {
13244
13258
  if (server) {
13245
13259
  server.stop();
13246
13260
  server = null;
13247
13261
  }
13248
13262
  }
13249
- function logWebhook(event) {
13263
+ function logDelivery(event) {
13250
13264
  const time = event.timestamp.toISOString();
13251
13265
  console.log("");
13252
13266
  console.log(blue("━".repeat(60)));
13253
- console.log(green("⚡ Webhook received"));
13267
+ console.log(green("⚡ Delivery received"));
13254
13268
  console.log(dim(` ${time}`));
13255
13269
  console.log(dim(` ${event.method} ${event.path}`));
13256
13270
  if (event.signatureValid === true) {
@@ -13272,7 +13286,7 @@ function logWebhook(event) {
13272
13286
  console.log(blue("━".repeat(60)));
13273
13287
  }
13274
13288
  var server = null;
13275
- var init_webhook_server = __esm(() => {
13289
+ var init_receiver_server = __esm(() => {
13276
13290
  init_output();
13277
13291
  });
13278
13292
 
@@ -13300,7 +13314,7 @@ var init_services = __esm(() => {
13300
13314
  init_indexer();
13301
13315
  init_worker();
13302
13316
  init_api2();
13303
- init_webhook_server();
13317
+ init_receiver_server();
13304
13318
  init_subgraph_processor();
13305
13319
  });
13306
13320
 
@@ -13344,7 +13358,7 @@ async function runBackground(options2) {
13344
13358
  const dataDir = getDataDir(config);
13345
13359
  const indexerPort = options2.stacksNode ? 3701 : parseInt(options2.indexerPort) || config.ports.indexer;
13346
13360
  const apiPort = parseInt(options2.apiPort) || config.ports.api;
13347
- const webhookPort = parseInt(options2.webhookPort) || config.ports.webhook;
13361
+ const receiverPort = parseInt(options2.receiverPort) || config.ports.receiver;
13348
13362
  if (options2.stacksNode && config.node) {
13349
13363
  const validation = await validateNetworkConsistency(config);
13350
13364
  if (!validation.valid) {
@@ -13454,24 +13468,24 @@ async function runBackground(options2) {
13454
13468
  };
13455
13469
  console.log(green(" ✓ Subgraph processor"), dim("processing subgraphs"));
13456
13470
  }
13457
- if (options2.webhook) {
13458
- const webhookLogFile = getLogFile("webhook");
13459
- const webhookArgs = ["bun", "run", resolve6(packagesDir, "packages/cli/src/services/webhook-standalone.ts")];
13460
- const webhookEnv = { ...process.env, PORT: String(webhookPort) };
13471
+ if (options2.receiver) {
13472
+ const receiverLogFile = getLogFile("receiver");
13473
+ const receiverArgs = ["bun", "run", resolve6(packagesDir, "packages/cli/src/services/receiver-standalone.ts")];
13474
+ const receiverEnv = { ...process.env, PORT: String(receiverPort) };
13461
13475
  if (options2.secret)
13462
- webhookEnv.WEBHOOK_SECRET = options2.secret;
13463
- const webhookProc = Bun.spawn(webhookArgs, {
13464
- env: webhookEnv,
13465
- stdout: Bun.file(webhookLogFile),
13466
- stderr: Bun.file(webhookLogFile)
13476
+ receiverEnv.SIGNING_SECRET = options2.secret;
13477
+ const receiverProc = Bun.spawn(receiverArgs, {
13478
+ env: receiverEnv,
13479
+ stdout: Bun.file(receiverLogFile),
13480
+ stderr: Bun.file(receiverLogFile)
13467
13481
  });
13468
- state.services.webhook = {
13469
- pid: webhookProc.pid,
13470
- port: webhookPort,
13482
+ state.services.receiver = {
13483
+ pid: receiverProc.pid,
13484
+ port: receiverPort,
13471
13485
  startedAt: new Date().toISOString(),
13472
- logFile: webhookLogFile
13486
+ logFile: receiverLogFile
13473
13487
  };
13474
- console.log(green(" ✓ Webhook server"), dim(`http://localhost:${webhookPort}`));
13488
+ console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
13475
13489
  }
13476
13490
  await Bun.sleep(500);
13477
13491
  for (const [name, service] of Object.entries(state.services)) {
@@ -13481,7 +13495,7 @@ async function runBackground(options2) {
13481
13495
  }
13482
13496
  await saveDevState(state);
13483
13497
  console.log("");
13484
- printUrls(indexerPort, apiPort, webhookPort, options2.webhook);
13498
+ printUrls(indexerPort, apiPort, receiverPort, options2.receiver);
13485
13499
  console.log("");
13486
13500
  success("Dev environment started in background");
13487
13501
  console.log("");
@@ -13519,14 +13533,14 @@ async function runForeground(options2) {
13519
13533
  const dataDir = getDataDir(config);
13520
13534
  const indexerPort = options2.stacksNode ? 3701 : parseInt(options2.indexerPort) || config.ports.indexer;
13521
13535
  const apiPort = parseInt(options2.apiPort) || config.ports.api;
13522
- const webhookPort = parseInt(options2.webhookPort) || config.ports.webhook;
13536
+ const receiverPort = parseInt(options2.receiverPort) || config.ports.receiver;
13523
13537
  let devPostgresStarted = false;
13524
13538
  const shutdown = async () => {
13525
13539
  console.log(`
13526
13540
  `);
13527
13541
  info("Shutting down services...");
13528
- if (options2.webhook) {
13529
- stopWebhookServer();
13542
+ if (options2.receiver) {
13543
+ stopReceiverServer();
13530
13544
  }
13531
13545
  await serviceManager.stopAll();
13532
13546
  if (devPostgresStarted) {
@@ -13573,9 +13587,9 @@ async function runForeground(options2) {
13573
13587
  console.log("");
13574
13588
  }
13575
13589
  process.env.DEV_MODE = "true";
13576
- if (options2.webhook) {
13577
- startWebhookServer({ port: webhookPort, secret: options2.secret });
13578
- console.log(green(" ✓ Webhook server"), dim(`http://localhost:${webhookPort}`));
13590
+ if (options2.receiver) {
13591
+ startReceiverServer({ port: receiverPort, secret: options2.secret });
13592
+ console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
13579
13593
  }
13580
13594
  await startApi({ port: apiPort, onLog: (line) => logService("api", line) });
13581
13595
  console.log(green(" ✓ API"), dim(`http://localhost:${apiPort}`));
@@ -13588,7 +13602,7 @@ async function runForeground(options2) {
13588
13602
  await startSubgraphProcessor({ onLog: (line) => logService("subgraphs", line) });
13589
13603
  console.log(green(" ✓ Subgraph processor"), dim("processing subgraphs"));
13590
13604
  console.log("");
13591
- printUrls(indexerPort, apiPort, webhookPort, options2.webhook);
13605
+ printUrls(indexerPort, apiPort, receiverPort, options2.receiver);
13592
13606
  console.log("");
13593
13607
  info("Press Ctrl+C to stop all services");
13594
13608
  console.log("");
@@ -13596,8 +13610,8 @@ async function runForeground(options2) {
13596
13610
  } catch (err) {
13597
13611
  error(`Failed to start services: ${err}`);
13598
13612
  await serviceManager.stopAll();
13599
- if (options2.webhook) {
13600
- stopWebhookServer();
13613
+ if (options2.receiver) {
13614
+ stopReceiverServer();
13601
13615
  }
13602
13616
  process.exit(1);
13603
13617
  }
@@ -13628,10 +13642,10 @@ async function showLogs(options2) {
13628
13642
  await showStaticLogs(serviceEntries, lines, verbose);
13629
13643
  }
13630
13644
  }
13631
- function formatWebhookSummary(jsonStr) {
13645
+ function formatDeliverySummary(jsonStr) {
13632
13646
  try {
13633
13647
  const data = JSON.parse(jsonStr);
13634
- if (data.type !== "webhook" || !data.body)
13648
+ if (data.type !== "delivery" || !data.body)
13635
13649
  return null;
13636
13650
  const { body, method, path, timestamp } = data;
13637
13651
  const streamName = body.streamName ?? body.streamId?.slice(0, 8) ?? "unknown";
@@ -13661,8 +13675,8 @@ function formatLogLine2(service, line, verbose) {
13661
13675
  return `${prefix} ${dimTimestamp} ${dim(level + ":")} ${dim(message)}`;
13662
13676
  }
13663
13677
  }
13664
- if (service === "webhook" && !verbose) {
13665
- const summary = formatWebhookSummary(line);
13678
+ if (service === "receiver" && !verbose) {
13679
+ const summary = formatDeliverySummary(line);
13666
13680
  if (summary)
13667
13681
  return `${prefix} ${summary}`;
13668
13682
  }
@@ -13838,21 +13852,21 @@ async function restartDev() {
13838
13852
  };
13839
13853
  console.log(green(" ✓ Worker"), dim("processing jobs"));
13840
13854
  }
13841
- if (state.services.webhook) {
13842
- const webhookPort = config.ports.webhook;
13843
- const webhookLogFile = getLogFile("webhook");
13844
- const webhookProc = Bun.spawn(["bun", "run", resolve6(packagesDir, "packages/cli/src/services/webhook-standalone.ts")], {
13845
- env: { ...process.env, PORT: String(webhookPort) },
13846
- stdout: Bun.file(webhookLogFile),
13847
- stderr: Bun.file(webhookLogFile)
13855
+ if (state.services.receiver) {
13856
+ const receiverPort = config.ports.receiver;
13857
+ const receiverLogFile = getLogFile("receiver");
13858
+ const receiverProc = Bun.spawn(["bun", "run", resolve6(packagesDir, "packages/cli/src/services/receiver-standalone.ts")], {
13859
+ env: { ...process.env, PORT: String(receiverPort) },
13860
+ stdout: Bun.file(receiverLogFile),
13861
+ stderr: Bun.file(receiverLogFile)
13848
13862
  });
13849
- newState.services.webhook = {
13850
- pid: webhookProc.pid,
13851
- port: webhookPort,
13863
+ newState.services.receiver = {
13864
+ pid: receiverProc.pid,
13865
+ port: receiverPort,
13852
13866
  startedAt: new Date().toISOString(),
13853
- logFile: webhookLogFile
13867
+ logFile: receiverLogFile
13854
13868
  };
13855
- console.log(green(" ✓ Webhook server"), dim(`http://localhost:${webhookPort}`));
13869
+ console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
13856
13870
  }
13857
13871
  if (state.services.subgraphs) {
13858
13872
  const subgraphsLogFile = getLogFile("subgraphs");
@@ -13928,7 +13942,7 @@ function printBanner2() {
13928
13942
  console.log(dim(" Starting services..."));
13929
13943
  console.log("");
13930
13944
  }
13931
- function printUrls(indexerPort, apiPort, webhookPort, webhookEnabled) {
13945
+ function printUrls(indexerPort, apiPort, receiverPort, receiverEnabled) {
13932
13946
  console.log(dim(" ─────────────────────────────────────────"));
13933
13947
  console.log("");
13934
13948
  console.log(" " + blue("API:"));
@@ -13939,9 +13953,9 @@ function printUrls(indexerPort, apiPort, webhookPort, webhookEnabled) {
13939
13953
  console.log(` Health check: curl http://localhost:${indexerPort}/health`);
13940
13954
  console.log(` Send block: curl -X POST http://localhost:${indexerPort}/new_block -d @block.json`);
13941
13955
  console.log("");
13942
- if (webhookEnabled) {
13943
- console.log(" " + blue("Test Webhook:"));
13944
- console.log(` Receives webhooks at http://localhost:${webhookPort}/`);
13956
+ if (receiverEnabled) {
13957
+ console.log(" " + blue("Test Receiver:"));
13958
+ console.log(` Receives deliveries at http://localhost:${receiverPort}/`);
13945
13959
  console.log(` Use this URL when creating streams for testing`);
13946
13960
  console.log("");
13947
13961
  }
@@ -14018,7 +14032,7 @@ var init_dev_impl = __esm(() => {
14018
14032
  indexer: cyan,
14019
14033
  worker: yellow,
14020
14034
  subgraphs: magenta,
14021
- webhook: green
14035
+ receiver: green
14022
14036
  };
14023
14037
  });
14024
14038
 
@@ -32538,7 +32552,7 @@ var {
32538
32552
  // package.json
32539
32553
  var package_default = {
32540
32554
  name: "@secondlayer/cli",
32541
- version: "1.6.0",
32555
+ version: "1.6.2",
32542
32556
  description: "CLI for streams, subgraphs, and real-time blockchain indexing on Stacks",
32543
32557
  type: "module",
32544
32558
  bin: {
@@ -32930,7 +32944,7 @@ async function printConfigTree(cfg) {
32930
32944
  console.log(blue("ports:"));
32931
32945
  printValue(" api", cfg.ports.api, cfg.ports.api === defaults.ports.api, 2);
32932
32946
  printValue(" indexer", cfg.ports.indexer, cfg.ports.indexer === defaults.ports.indexer, 2);
32933
- printValue(" webhook", cfg.ports.webhook, cfg.ports.webhook === defaults.ports.webhook, 2);
32947
+ printValue(" receiver", cfg.ports.receiver, cfg.ports.receiver === defaults.ports.receiver, 2);
32934
32948
  console.log("");
32935
32949
  console.log(blue("database:"));
32936
32950
  printValue(" type", cfg.database.type, cfg.database.type === "docker", 2);
@@ -32976,13 +32990,13 @@ import { select as select2, input, confirm } from "@inquirer/prompts";
32976
32990
  init_config();
32977
32991
  var STREAMS_DIR = "streams";
32978
32992
  function registerSetupCommand(program2) {
32979
- program2.command("setup").description("Set up a streams project and configure settings").option("--detect-only", "Only detect existing Stacks nodes, don't initialize").option("-y, --yes", "Use defaults without prompts").option("--data-dir <path>", "Data directory path").option("--node-path <path>", "Path to Stacks node").option("--network <network>", "Network (local, testnet, or mainnet)").option("--webhook-url <url>", "Default webhook URL for new streams").action(async (options) => {
32993
+ program2.command("setup").description("Set up a streams project and configure settings").option("--detect-only", "Only detect existing Stacks nodes, don't initialize").option("-y, --yes", "Use defaults without prompts").option("--data-dir <path>", "Data directory path").option("--node-path <path>", "Path to Stacks node").option("--network <network>", "Network (local, testnet, or mainnet)").option("--endpoint-url <url>", "Default endpoint URL for new streams").action(async (options) => {
32980
32994
  try {
32981
32995
  if (options.detectOnly) {
32982
32996
  await runDetection();
32983
32997
  return;
32984
32998
  }
32985
- const hasFlags = options.yes || options.dataDir || options.nodePath || options.network || options.webhookUrl;
32999
+ const hasFlags = options.yes || options.dataDir || options.nodePath || options.network || options.endpointUrl;
32986
33000
  if (hasFlags) {
32987
33001
  await runNonInteractive(options);
32988
33002
  return;
@@ -33011,7 +33025,7 @@ async function runNonInteractive(options) {
33011
33025
  return;
33012
33026
  }
33013
33027
  config.dataDir = options.dataDir || config.dataDir || "~/.secondlayer/data";
33014
- config.defaultWebhookUrl = options.webhookUrl || config.defaultWebhookUrl;
33028
+ config.defaultEndpointUrl = options.endpointUrl || config.defaultEndpointUrl;
33015
33029
  if (options.nodePath) {
33016
33030
  config.node = {
33017
33031
  installPath: options.nodePath,
@@ -33055,8 +33069,8 @@ async function runWizard() {
33055
33069
  if (nodeConfig) {
33056
33070
  config.node = nodeConfig;
33057
33071
  }
33058
- const webhookUrl = await promptWebhookUrl(config);
33059
- config.defaultWebhookUrl = webhookUrl;
33072
+ const endpointUrl = await promptEndpointUrl(config);
33073
+ config.defaultEndpointUrl = endpointUrl;
33060
33074
  await saveConfig(config);
33061
33075
  await Bun.$`mkdir -p ${STREAMS_DIR}`.quiet();
33062
33076
  await Bun.write(`${STREAMS_DIR}/.gitkeep`, "");
@@ -33183,10 +33197,10 @@ async function promptNetwork() {
33183
33197
  });
33184
33198
  return network;
33185
33199
  }
33186
- async function promptWebhookUrl(config) {
33187
- const internalUrl = "http://localhost:3900/webhook";
33200
+ async function promptEndpointUrl(config) {
33201
+ const internalUrl = "http://localhost:3900/receiver";
33188
33202
  const choice = await select2({
33189
- message: "Default webhook URL for new streams?",
33203
+ message: "Default endpoint URL for new streams?",
33190
33204
  choices: [
33191
33205
  { name: `Internal test server (${internalUrl})`, value: "internal" },
33192
33206
  { name: "Custom URL...", value: "custom" }
@@ -33196,8 +33210,8 @@ async function promptWebhookUrl(config) {
33196
33210
  return internalUrl;
33197
33211
  }
33198
33212
  const customUrl = await input({
33199
- message: "Enter webhook URL:",
33200
- default: config.defaultWebhookUrl !== internalUrl ? config.defaultWebhookUrl : undefined,
33213
+ message: "Enter endpoint URL:",
33214
+ default: config.defaultEndpointUrl !== internalUrl ? config.defaultEndpointUrl : undefined,
33201
33215
  validate: (value) => {
33202
33216
  if (!value.trim())
33203
33217
  return "URL cannot be empty";
@@ -33295,8 +33309,8 @@ function printSummary(config) {
33295
33309
  console.log();
33296
33310
  console.log(" Settings:");
33297
33311
  console.log(` Data directory: ${config.dataDir}`);
33298
- if (config.defaultWebhookUrl) {
33299
- console.log(` Webhook URL: ${config.defaultWebhookUrl}`);
33312
+ if (config.defaultEndpointUrl) {
33313
+ console.log(` Endpoint URL: ${config.defaultEndpointUrl}`);
33300
33314
  }
33301
33315
  if (config.node) {
33302
33316
  console.log(` Node path: ${config.node.installPath}`);
@@ -33345,10 +33359,10 @@ function printNodeInfo(node) {
33345
33359
  import { join as join3 } from "node:path";
33346
33360
 
33347
33361
  // src/templates/stream.ts
33348
- function generateStreamTemplate(name, webhookUrl) {
33362
+ function generateStreamTemplate(name, endpointUrl) {
33349
33363
  return {
33350
33364
  name,
33351
- webhookUrl: webhookUrl || "https://example.com/webhook",
33365
+ endpointUrl: endpointUrl || "https://example.com/endpoint",
33352
33366
  filters: [
33353
33367
  {
33354
33368
  type: "contract_call",
@@ -33384,12 +33398,12 @@ function registerNewCommand(program2) {
33384
33398
  if (dir) {
33385
33399
  await ensureDir(dir);
33386
33400
  }
33387
- const template = generateStreamTemplate(name, config.defaultWebhookUrl);
33401
+ const template = generateStreamTemplate(name, config.defaultEndpointUrl);
33388
33402
  await writeTextFile(outputPath, JSON.stringify(template, null, 2) + `
33389
33403
  `);
33390
33404
  success(`Created ${outputPath}`);
33391
- if (!config.defaultWebhookUrl) {
33392
- warn("Edit the webhookUrl before registering — it must be a reachable HTTPS endpoint");
33405
+ if (!config.defaultEndpointUrl) {
33406
+ warn("Edit the endpointUrl before registering — it must be a reachable HTTPS endpoint");
33393
33407
  }
33394
33408
  console.log(`
33395
33409
  Edit the file to configure your stream, then run:`);
@@ -33452,7 +33466,7 @@ function registerGetCommand(program2) {
33452
33466
  ["ID", stream.id],
33453
33467
  ["Name", stream.name],
33454
33468
  ["Status", statusColor(stream.status)],
33455
- ["Webhook URL", stream.webhookUrl],
33469
+ ["Endpoint URL", stream.endpointUrl],
33456
33470
  ["Total Deliveries", stream.totalDeliveries.toString()],
33457
33471
  ["Failed Deliveries", stream.failedDeliveries.toString()],
33458
33472
  ["Last Triggered", stream.lastTriggeredAt || dim("never")],
@@ -33520,10 +33534,10 @@ function registerRegisterCommand(program2) {
33520
33534
  console.log(formatKeyValue([
33521
33535
  ["ID", result.stream.id],
33522
33536
  ["Name", result.stream.name],
33523
- ["Webhook Secret", result.webhookSecret]
33537
+ ["Signing Secret", result.signingSecret]
33524
33538
  ]));
33525
33539
  console.log(dim(`
33526
- Save the webhook secret - it won't be shown again!`));
33540
+ Save the signing secret - it won't be shown again!`));
33527
33541
  } catch (err) {
33528
33542
  handleApiError(err, "register stream");
33529
33543
  }
@@ -34019,12 +34033,12 @@ init_api_client();
34019
34033
  init_output();
34020
34034
  import { confirm as confirm3 } from "@inquirer/prompts";
34021
34035
  function registerRotateSecretCommand(program2) {
34022
- program2.command("rotate-secret <id>").description("Generate a new webhook secret for a stream").option("-y, --yes", "Skip confirmation prompt").action(async (id, options) => {
34036
+ program2.command("rotate-secret <id>").description("Generate a new signing secret for a stream").option("-y, --yes", "Skip confirmation prompt").action(async (id, options) => {
34023
34037
  try {
34024
34038
  const stream = await getStream(id);
34025
34039
  if (!options.yes) {
34026
34040
  const confirmed = await confirm3({
34027
- message: `Rotate webhook secret for "${stream.name}"? The current secret will be invalidated.`,
34041
+ message: `Rotate signing secret for "${stream.name}"? The current secret will be invalidated.`,
34028
34042
  default: false
34029
34043
  });
34030
34044
  if (!confirmed) {
@@ -34033,13 +34047,13 @@ function registerRotateSecretCommand(program2) {
34033
34047
  }
34034
34048
  }
34035
34049
  const result = await rotateSecret(stream.id);
34036
- success(`Rotated webhook secret for: ${stream.name}`);
34050
+ success(`Rotated signing secret for: ${stream.name}`);
34037
34051
  console.log(formatKeyValue([
34038
34052
  ["Stream", stream.name],
34039
- ["Webhook Secret", result.secret]
34053
+ ["Signing Secret", result.secret]
34040
34054
  ]));
34041
34055
  console.log(dim(`
34042
- Save the webhook secret - it won't be shown again!`));
34056
+ Save the signing secret - it won't be shown again!`));
34043
34057
  } catch (err) {
34044
34058
  handleApiError(err, "rotate secret");
34045
34059
  }
@@ -34722,15 +34736,15 @@ async function resyncDatabase(skipConfirm, backfill) {
34722
34736
  process.exit(1);
34723
34737
  }
34724
34738
  }
34725
- // src/commands/webhook.ts
34739
+ // src/commands/receiver.ts
34726
34740
  init_output();
34727
34741
  init_config();
34728
34742
  import { join as join5 } from "node:path";
34729
- function registerWebhookCommand(program2) {
34730
- const webhook = program2.command("webhook").description("Webhook development tools").hook("preAction", async () => {
34743
+ function registerReceiverCommand(program2) {
34744
+ const receiver = program2.command("receiver").description("Receiver development tools").hook("preAction", async () => {
34731
34745
  await requireLocalNetwork();
34732
34746
  });
34733
- webhook.command("init <directory>").description("Scaffold a webhook handler with types and signature verification").option("-n, --name <name>", "Stream name", "my-stream").option("--network <network>", "Network (mainnet/testnet)", "mainnet").option("-p, --port <port>", "Server port", "4000").action(async (directory, options) => {
34747
+ receiver.command("init <directory>").description("Scaffold a receiver handler with types and signature verification").option("-n, --name <name>", "Stream name", "my-stream").option("--network <network>", "Network (mainnet/testnet)", "mainnet").option("-p, --port <port>", "Server port", "4000").action(async (directory, options) => {
34734
34748
  try {
34735
34749
  const config = await loadConfig();
34736
34750
  const port = parseInt(options.port);
@@ -34744,13 +34758,13 @@ function registerWebhookCommand(program2) {
34744
34758
  await Bun.$`mkdir -p ${dir}`.quiet();
34745
34759
  await generateServerFile(dir, port);
34746
34760
  await generateTypesFile(dir);
34747
- await generateStreamJson(dir, options.name, network, port, config.defaultWebhookUrl);
34761
+ await generateStreamJson(dir, options.name, network, port, config.defaultEndpointUrl);
34748
34762
  await generateEnvFile(dir);
34749
34763
  await generatePackageJson(dir, options.name);
34750
- success(`Created webhook handler in ${directory}/`);
34764
+ success(`Created receiver handler in ${directory}/`);
34751
34765
  console.log("");
34752
34766
  console.log(" Files created:");
34753
- console.log(` ${dim("server.ts")} Webhook server with HMAC verification`);
34767
+ console.log(` ${dim("server.ts")} Receiver server with HMAC verification`);
34754
34768
  console.log(` ${dim("types.ts")} Payload type definitions`);
34755
34769
  console.log(` ${dim("stream.json")} Stream configuration`);
34756
34770
  console.log(` ${dim(".env")} Environment variables`);
@@ -34765,26 +34779,26 @@ function registerWebhookCommand(program2) {
34765
34779
  console.log(` sl streams register ${directory}/stream.json`);
34766
34780
  console.log("");
34767
34781
  } catch (err) {
34768
- error(`Failed to scaffold webhook: ${err}`);
34782
+ error(`Failed to scaffold receiver: ${err}`);
34769
34783
  process.exit(1);
34770
34784
  }
34771
34785
  });
34772
34786
  }
34773
34787
  async function generateServerFile(dir, port) {
34774
- const content = `import type { WebhookPayload } from "./types.ts";
34788
+ const content = `import type { DeliveryPayload } from "./types.ts";
34775
34789
 
34776
- const WEBHOOK_SECRET = process.env.STREAMS_WEBHOOK_SECRET;
34790
+ const SIGNING_SECRET = process.env.STREAMS_SIGNING_SECRET;
34777
34791
 
34778
34792
  /**
34779
34793
  * Verify HMAC signature from Stacks Streams
34780
34794
  */
34781
34795
  async function verifySignature(body: string, signature: string | null): Promise<boolean> {
34782
- if (!WEBHOOK_SECRET || !signature) return false;
34796
+ if (!SIGNING_SECRET || !signature) return false;
34783
34797
 
34784
34798
  const encoder = new TextEncoder();
34785
34799
  const key = await crypto.subtle.importKey(
34786
34800
  "raw",
34787
- encoder.encode(WEBHOOK_SECRET),
34801
+ encoder.encode(SIGNING_SECRET),
34788
34802
  { name: "HMAC", hash: "SHA-256" },
34789
34803
  false,
34790
34804
  ["sign"]
@@ -34797,9 +34811,9 @@ async function verifySignature(body: string, signature: string | null): Promise<
34797
34811
  }
34798
34812
 
34799
34813
  /**
34800
- * Handle incoming webhook payload
34814
+ * Handle incoming delivery payload
34801
34815
  */
34802
- async function handlePayload(payload: WebhookPayload): Promise<void> {
34816
+ async function handlePayload(payload: DeliveryPayload): Promise<void> {
34803
34817
  console.log(\`Block \${payload.block.height}: \${payload.matches.events.length} events\`);
34804
34818
 
34805
34819
  for (const event of payload.matches.events) {
@@ -34838,13 +34852,13 @@ Bun.serve({
34838
34852
  return new Response("ok");
34839
34853
  }
34840
34854
 
34841
- // Webhook endpoint
34855
+ // Receiver endpoint
34842
34856
  if (req.method === "POST" && url.pathname === "/payload") {
34843
34857
  const body = await req.text();
34844
34858
  const signature = req.headers.get("x-streams-signature");
34845
34859
 
34846
34860
  // Verify signature
34847
- if (WEBHOOK_SECRET) {
34861
+ if (SIGNING_SECRET) {
34848
34862
  const valid = await verifySignature(body, signature);
34849
34863
  if (!valid) {
34850
34864
  console.error("Invalid signature");
@@ -34853,7 +34867,7 @@ Bun.serve({
34853
34867
  }
34854
34868
 
34855
34869
  try {
34856
- const payload: WebhookPayload = JSON.parse(body);
34870
+ const payload: DeliveryPayload = JSON.parse(body);
34857
34871
  await handlePayload(payload);
34858
34872
  return new Response("ok");
34859
34873
  } catch (err) {
@@ -34866,18 +34880,18 @@ Bun.serve({
34866
34880
  },
34867
34881
  });
34868
34882
 
34869
- console.log(\`Webhook server listening on http://localhost:${port}/payload\`);
34883
+ console.log(\`Receiver server listening on http://localhost:${port}/payload\`);
34870
34884
  `;
34871
34885
  await Bun.write(join5(dir, "server.ts"), content);
34872
34886
  }
34873
34887
  async function generateTypesFile(dir) {
34874
34888
  const content = `/**
34875
- * Stacks Streams Webhook Payload Types
34889
+ * Stacks Streams Delivery Payload Types
34876
34890
  *
34877
34891
  * These types match the payload structure sent by Stacks Streams.
34878
34892
  */
34879
34893
 
34880
- export interface WebhookPayload {
34894
+ export interface DeliveryPayload {
34881
34895
  streamId: string;
34882
34896
  streamName: string;
34883
34897
  network: "mainnet" | "testnet";
@@ -34999,11 +35013,11 @@ export function isPrintEvent(event: EventMatch): event is PrintEvent {
34999
35013
  `;
35000
35014
  await Bun.write(join5(dir, "types.ts"), content);
35001
35015
  }
35002
- async function generateStreamJson(dir, name, network, port, _defaultWebhookUrl) {
35016
+ async function generateStreamJson(dir, name, network, port, _defaultEndpointUrl) {
35003
35017
  const content = {
35004
35018
  name,
35005
35019
  network,
35006
- webhookUrl: `http://localhost:${port}/payload`,
35020
+ endpointUrl: `http://localhost:${port}/payload`,
35007
35021
  filters: [
35008
35022
  {
35009
35023
  type: "stx_transfer",
@@ -35023,9 +35037,9 @@ async function generateStreamJson(dir, name, network, port, _defaultWebhookUrl)
35023
35037
  `);
35024
35038
  }
35025
35039
  async function generateEnvFile(dir) {
35026
- const content = `# Stacks Streams Webhook Secret
35040
+ const content = `# Stacks Streams Signing Secret
35027
35041
  # Get this from: sl streams register stream.json
35028
- STREAMS_WEBHOOK_SECRET=
35042
+ STREAMS_SIGNING_SECRET=
35029
35043
 
35030
35044
  # Add your database connection, etc.
35031
35045
  # DATABASE_URL=postgres://...
@@ -35034,7 +35048,7 @@ STREAMS_WEBHOOK_SECRET=
35034
35048
  }
35035
35049
  async function generatePackageJson(dir, name) {
35036
35050
  const content = {
35037
- name: `${name}-webhook`,
35051
+ name: `${name}-receiver`,
35038
35052
  version: "0.1.0",
35039
35053
  type: "module",
35040
35054
  scripts: {
@@ -35941,7 +35955,7 @@ async function checkHealth() {
35941
35955
  const portsToCheck = [
35942
35956
  { port: config.ports.api, name: "API" },
35943
35957
  { port: config.ports.indexer, name: "Indexer" },
35944
- { port: config.ports.webhook, name: "Webhook" },
35958
+ { port: config.ports.receiver, name: "Receiver" },
35945
35959
  { port: 20443, name: "Node RPC" }
35946
35960
  ];
35947
35961
  for (const { port, name } of portsToCheck) {
@@ -36413,14 +36427,14 @@ init_config();
36413
36427
  init_dev_state();
36414
36428
  init_node_manager();
36415
36429
  init_output();
36416
- var DEV_SERVICES = ["api", "indexer", "worker", "webhook", "subgraphs"];
36430
+ var DEV_SERVICES = ["api", "indexer", "worker", "receiver", "subgraphs"];
36417
36431
  function registerLocalCommand(program2) {
36418
36432
  const local = program2.command("local").description("Manage local development environment and Stacks node").hook("preAction", async (_thisCommand, actionCommand) => {
36419
36433
  if (actionCommand.name() === "help")
36420
36434
  return;
36421
36435
  await requireLocalNetwork();
36422
36436
  });
36423
- local.command("start").description("Start all local dev services (API, indexer, worker, webhook)").option("--indexer-port <port>", "Indexer port", "3700").option("--api-port <port>", "API port", "3800").option("--webhook-port <port>", "Test webhook server port", "3900").option("--no-webhook", "Skip test webhook server").option("--no-worker", "Skip worker service").option("--secret <secret>", "Webhook secret for signature verification").option("--stacks-node", "Use port 3701 for indexer (avoids conflict with stacks-blockchain-api)").option("-f, --foreground", "Run in foreground (blocking)").action(async (options2) => {
36437
+ local.command("start").description("Start all local dev services (API, indexer, worker, receiver)").option("--indexer-port <port>", "Indexer port", "3700").option("--api-port <port>", "API port", "3800").option("--receiver-port <port>", "Test receiver server port", "3900").option("--no-receiver", "Skip test receiver server").option("--no-worker", "Skip worker service").option("--secret <secret>", "Signing secret for signature verification").option("--stacks-node", "Use port 3701 for indexer (avoids conflict with stacks-blockchain-api)").option("-f, --foreground", "Run in foreground (blocking)").action(async (options2) => {
36424
36438
  const { runBackground: runBackground2, runForeground: runForeground2, isDevAlreadyRunning: isDevAlreadyRunning2 } = await Promise.resolve().then(() => (init_dev_impl(), exports_dev_impl));
36425
36439
  if (await isDevAlreadyRunning2()) {
36426
36440
  return;
@@ -36442,7 +36456,7 @@ function registerLocalCommand(program2) {
36442
36456
  local.command("status").description("Show local environment status").action(async () => {
36443
36457
  await showLocalStatus();
36444
36458
  });
36445
- local.command("logs").description("View local service logs (dev + node)").option("-s, --service <name>", "Filter by service (api, indexer, worker, webhook, subgraphs, node)").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Number of lines to show", "50").option("-q, --quiet", "Filter out common noise").option("-v, --verbose", "Show full payloads").action(async (options2) => {
36459
+ local.command("logs").description("View local service logs (dev + node)").option("-s, --service <name>", "Filter by service (api, indexer, worker, receiver, subgraphs, node)").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Number of lines to show", "50").option("-q, --quiet", "Filter out common noise").option("-v, --verbose", "Show full payloads").action(async (options2) => {
36446
36460
  await showLocalLogs(options2);
36447
36461
  });
36448
36462
  const node = local.command("node").description("Manage local Stacks node");
@@ -36519,7 +36533,7 @@ var serviceColors2 = {
36519
36533
  indexer: cyan,
36520
36534
  worker: yellow,
36521
36535
  subgraphs: magenta,
36522
- webhook: green,
36536
+ receiver: green,
36523
36537
  node: red
36524
36538
  };
36525
36539
  async function showLocalLogs(options2) {
@@ -36671,17 +36685,17 @@ function formatLogLine3(service, line, verbose) {
36671
36685
  return `${prefix} ${dimTimestamp} ${dim(level + ":")} ${dim(message)}`;
36672
36686
  }
36673
36687
  }
36674
- if (service === "webhook" && !verbose) {
36675
- const summary = formatWebhookSummary2(line);
36688
+ if (service === "receiver" && !verbose) {
36689
+ const summary = formatDeliverySummary2(line);
36676
36690
  if (summary)
36677
36691
  return `${prefix} ${summary}`;
36678
36692
  }
36679
36693
  return `${prefix} ${line}`;
36680
36694
  }
36681
- function formatWebhookSummary2(jsonStr) {
36695
+ function formatDeliverySummary2(jsonStr) {
36682
36696
  try {
36683
36697
  const data = JSON.parse(jsonStr);
36684
- if (data.type !== "webhook" || !data.body)
36698
+ if (data.type !== "delivery" || !data.body)
36685
36699
  return null;
36686
36700
  const { body, method, path, timestamp } = data;
36687
36701
  const streamName = body.streamName ?? body.streamId?.slice(0, 8) ?? "unknown";
@@ -36765,8 +36779,8 @@ registerSetupCommand(program);
36765
36779
  registerConfigCommand(program);
36766
36780
  registerAuthCommand(program);
36767
36781
  registerWhoamiCommand(program);
36768
- registerWebhookCommand(program);
36782
+ registerReceiverCommand(program);
36769
36783
  program.parse();
36770
36784
 
36771
- //# debugId=2320C06E5C8D182A64756E2164756E21
36785
+ //# debugId=2EB552BA8CA7A84564756E2164756E21
36772
36786
  //# sourceMappingURL=cli.js.map