@secondlayer/cli 8.4.2 → 8.5.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/README.md CHANGED
@@ -119,6 +119,14 @@ Read/action commands support `--json`. Destructive commands prompt unless
119
119
  `-y` / `--yes`. Filters are schema-aware: unknown tables/columns, bad operators,
120
120
  and non-scalar columns are rejected before the API call.
121
121
 
122
+ Subscriptions are polymorphic — **subgraph** (fires on a subgraph table's rows)
123
+ or **chain** (fires on raw chain events with no subgraph). `sl subscriptions
124
+ create` makes subgraph subscriptions only (via the `--subgraph`/`--table`
125
+ flags). Create chain subscriptions — a webhook on a contract / event / function /
126
+ trait — via the SDK, REST, or MCP with a `triggers` array. Every other
127
+ `sl subscriptions` command (list/get/update/pause/resume/delete/doctor/test/
128
+ deliveries/...) operates on both kinds.
129
+
122
130
  ### Local dev & OSS
123
131
 
124
132
  | Command | What it does |
package/dist/cli.js CHANGED
@@ -32354,7 +32354,7 @@ var {
32354
32354
  // package.json
32355
32355
  var package_default = {
32356
32356
  name: "@secondlayer/cli",
32357
- version: "8.4.2",
32357
+ version: "8.5.0",
32358
32358
  repository: {
32359
32359
  type: "git",
32360
32360
  url: "git+https://github.com/ryanwaits/secondlayer.git",
@@ -32403,8 +32403,8 @@ var package_default = {
32403
32403
  dependencies: {
32404
32404
  "@inquirer/prompts": "^8.2.0",
32405
32405
  "@secondlayer/bundler": "^0.3.7",
32406
- "@secondlayer/sdk": "^6.2.1",
32407
- "@secondlayer/shared": "^6.12.0",
32406
+ "@secondlayer/sdk": "^6.9.0",
32407
+ "@secondlayer/shared": "^6.18.0",
32408
32408
  "@secondlayer/stacks": "^2.3.0",
32409
32409
  "@secondlayer/subgraphs": "^3.5.0",
32410
32410
  "@biomejs/js-api": "^0.7.0",
@@ -33095,6 +33095,30 @@ async function validateDatabaseConnection(url) {
33095
33095
  console.log(dim("The URL was saved but connection failed. Check your database settings."));
33096
33096
  }
33097
33097
  }
33098
+ // src/commands/context.ts
33099
+ init_output();
33100
+ init_resolve_auth();
33101
+ import { SecondLayer as SecondLayer2 } from "@secondlayer/sdk";
33102
+ var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
33103
+ function registerContextCommand(program2) {
33104
+ program2.command("context").description("Print an agent orientation snapshot: account, live Streams/Index tips, your subgraphs/subscriptions, and in-flight reindex operations").option("--json", "Print as JSON (default)").action(async (o) => {
33105
+ try {
33106
+ const sl = new SecondLayer2({
33107
+ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL,
33108
+ apiKey: resolveEnvKey()
33109
+ });
33110
+ const snapshot = await sl.context();
33111
+ output({
33112
+ json: o.json,
33113
+ data: snapshot,
33114
+ human: () => writeData(JSON.stringify(snapshot, null, 2))
33115
+ });
33116
+ } catch (err) {
33117
+ error(err instanceof Error ? err.message : String(err));
33118
+ process.exit(1);
33119
+ }
33120
+ });
33121
+ }
33098
33122
  // src/commands/status.ts
33099
33123
  init_config();
33100
33124
  init_output();
@@ -33287,7 +33311,7 @@ import {
33287
33311
  import { dirname as dirname2, join as join4, relative, resolve } from "node:path";
33288
33312
  import { fileURLToPath } from "node:url";
33289
33313
  import { input, select as select2 } from "@inquirer/prompts";
33290
- import { SecondLayer as SecondLayer2 } from "@secondlayer/sdk";
33314
+ import { SecondLayer as SecondLayer3 } from "@secondlayer/sdk";
33291
33315
  init_output();
33292
33316
  init_resolve_auth();
33293
33317
 
@@ -33492,7 +33516,7 @@ SIGNING_SECRET=${signingSecret}
33492
33516
  }
33493
33517
  async function getSubscriptionClient() {
33494
33518
  const { apiUrl, ephemeralKey } = await resolveAuth();
33495
- return new SecondLayer2({ baseUrl: apiUrl, apiKey: ephemeralKey });
33519
+ return new SecondLayer3({ baseUrl: apiUrl, apiKey: ephemeralKey });
33496
33520
  }
33497
33521
  function addSubscriptionScaffold(parent, commandSpec, opts) {
33498
33522
  parent.command(commandSpec).description(opts.description).option("-r, --runtime <runtime>", "inngest | trigger | cloudflare | node").option("-s, --subgraph <name>", "Subgraph to subscribe to").option("-t, --table <name>", "Table to subscribe to").option("-u, --url <url>", "Webhook URL").option("--auth-token <token>", "Bearer token for receiver API auth").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--skip-api", "Copy template only, don't call the API").option("--no-scaffold", "Skip the local runtime template directory (webhook-only setups)").addHelpText("after", `
@@ -36358,7 +36382,7 @@ init_resolve_auth();
36358
36382
  import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
36359
36383
  import { dirname as dirname6, join as join8 } from "node:path";
36360
36384
  import { createStreamsClient } from "@secondlayer/sdk";
36361
- var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
36385
+ var DEFAULT_BASE_URL2 = "https://api.secondlayer.tools";
36362
36386
  var VALID_TYPES = [
36363
36387
  "stx_transfer",
36364
36388
  "stx_mint",
@@ -36382,7 +36406,7 @@ function readApiKey() {
36382
36406
  }
36383
36407
  function client() {
36384
36408
  return createStreamsClient({
36385
- baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL,
36409
+ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL2,
36386
36410
  apiKey: readApiKey()
36387
36411
  });
36388
36412
  }
@@ -36393,7 +36417,7 @@ function dumpsClient(dumpsUrl) {
36393
36417
  process.exit(1);
36394
36418
  }
36395
36419
  return createStreamsClient({
36396
- baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL,
36420
+ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL2,
36397
36421
  apiKey: resolveEnvKey() ?? "",
36398
36422
  dumpsBaseUrl
36399
36423
  });
@@ -36446,7 +36470,7 @@ function registerStreamsCommand(program2) {
36446
36470
  process.exit(1);
36447
36471
  }
36448
36472
  });
36449
- streams.command("events").description("List events (cursor-paginated; one page per call)").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--not-types <types>", "comma-separated event types to exclude").option("--contract-id <ids>", "comma-separated contract identifier(s)").option("--sender <addrs>", "comma-separated sender principal(s)").option("--recipient <addrs>", "comma-separated recipient principal(s)").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--from-block <n>", "filter to blocks >= n").option("--to-block <n>", "filter to blocks <= n").option("--limit <n>", "page size (1-1000, default 100)", "100").option("--json", "Output as JSON (streams always emits JSON)").addHelpText("after", `
36473
+ const events = streams.command("events").description("List events (cursor-paginated; one page per call)").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--not-types <types>", "comma-separated event types to exclude").option("--contract-id <ids>", "comma-separated contract identifier(s)").option("--sender <addrs>", "comma-separated sender principal(s)").option("--recipient <addrs>", "comma-separated recipient principal(s)").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--from-block <n>", "filter to blocks >= n").option("--to-block <n>", "filter to blocks <= n").option("--limit <n>", "page size (1-1000, default 100)", "100").option("--json", "Output as JSON (streams always emits JSON)").addHelpText("after", `
36450
36474
  Examples:
36451
36475
  $ sl streams events --types stx_transfer,print --limit 50
36452
36476
  $ sl streams events --not-types print --contract-id SP00....token,SP01....token
@@ -36470,6 +36494,15 @@ Examples:
36470
36494
  process.exit(1);
36471
36495
  }
36472
36496
  });
36497
+ events.command("by-tx <txId>").description("List all events emitted by a single transaction").option("--json", "Output as JSON (streams always emits JSON)").action(async (txId) => {
36498
+ try {
36499
+ const envelope = await client().events.byTxId(txId);
36500
+ writeData(JSON.stringify(envelope, null, 2));
36501
+ } catch (err) {
36502
+ error(err instanceof Error ? err.message : String(err));
36503
+ process.exit(1);
36504
+ }
36505
+ });
36473
36506
  streams.command("consume").description("Long-running pull from a cursor; emits one event per line (jsonl) until SIGINT or --max-pages").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--not-types <types>", "comma-separated event types to exclude").option("--contract-id <ids>", "comma-separated contract identifier(s)").option("--sender <addrs>", "comma-separated sender principal(s)").option("--recipient <addrs>", "comma-separated recipient principal(s)").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--batch-size <n>", "events per batch (1-1000, default 100)", "100").option("--max-pages <n>", "stop after N pages (default: run until SIGINT)").addHelpText("after", `
36474
36507
  Examples:
36475
36508
  $ sl streams consume --types print --cursor 150000:0
@@ -36488,8 +36521,8 @@ Examples:
36488
36521
  batchSize,
36489
36522
  mode: "tail",
36490
36523
  maxPages,
36491
- onBatch: (events, envelope) => {
36492
- for (const e of events) {
36524
+ onBatch: (events2, envelope) => {
36525
+ for (const e of events2) {
36493
36526
  process.stdout.write(`${JSON.stringify(e)}
36494
36527
  `);
36495
36528
  }
@@ -36562,13 +36595,23 @@ Examples:
36562
36595
  process.exit(1);
36563
36596
  }
36564
36597
  });
36598
+ streams.command("block-events <heightOrHash>").description("List all events in a single block (by height or block hash)").option("--json", "Output as JSON (streams always emits JSON)").action(async (heightOrHash) => {
36599
+ try {
36600
+ const ref = /^\d+$/.test(heightOrHash) ? Number.parseInt(heightOrHash, 10) : heightOrHash;
36601
+ const envelope = await client().blocks.events(ref);
36602
+ writeData(JSON.stringify(envelope, null, 2));
36603
+ } catch (err) {
36604
+ error(err instanceof Error ? err.message : String(err));
36605
+ process.exit(1);
36606
+ }
36607
+ });
36565
36608
  }
36566
36609
  // src/commands/datasets.ts
36567
36610
  init_output();
36568
36611
  import { CURSOR_SLUGS, Datasets } from "@secondlayer/sdk";
36569
- var DEFAULT_BASE_URL2 = "https://api.secondlayer.tools";
36612
+ var DEFAULT_BASE_URL3 = "https://api.secondlayer.tools";
36570
36613
  function client2() {
36571
- return new Datasets({ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL2 });
36614
+ return new Datasets({ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL3 });
36572
36615
  }
36573
36616
  function parseFilters(pairs) {
36574
36617
  const out = {};
@@ -36623,10 +36666,10 @@ Examples:
36623
36666
  init_output();
36624
36667
  init_resolve_auth();
36625
36668
  import { Index } from "@secondlayer/sdk";
36626
- var DEFAULT_BASE_URL3 = "https://api.secondlayer.tools";
36669
+ var DEFAULT_BASE_URL4 = "https://api.secondlayer.tools";
36627
36670
  function client3() {
36628
36671
  return new Index({
36629
- baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL3,
36672
+ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL4,
36630
36673
  apiKey: resolveEnvKey()
36631
36674
  });
36632
36675
  }
@@ -36638,15 +36681,17 @@ function fail(action, err) {
36638
36681
  }
36639
36682
  process.exit(1);
36640
36683
  }
36641
- function rangeParams(o) {
36684
+ function heightParams(o) {
36642
36685
  return {
36643
- contractId: o.contractId,
36644
36686
  fromHeight: o.fromHeight ? Number.parseInt(o.fromHeight, 10) : undefined,
36645
36687
  toHeight: o.toHeight ? Number.parseInt(o.toHeight, 10) : undefined,
36646
36688
  cursor: o.cursor,
36647
36689
  limit: o.limit ? Number.parseInt(o.limit, 10) : undefined
36648
36690
  };
36649
36691
  }
36692
+ function rangeParams(o) {
36693
+ return { contractId: o.contractId, ...heightParams(o) };
36694
+ }
36650
36695
  function emit(env, json) {
36651
36696
  output({
36652
36697
  json,
@@ -36658,9 +36703,21 @@ function emit(env, json) {
36658
36703
  }
36659
36704
  });
36660
36705
  }
36706
+ function emitOne(doc, label, json) {
36707
+ if (doc == null) {
36708
+ error(`Not found: ${label}`);
36709
+ process.exit(1);
36710
+ }
36711
+ output({
36712
+ json,
36713
+ data: doc,
36714
+ human: () => writeData(JSON.stringify(doc, null, 2))
36715
+ });
36716
+ }
36661
36717
  function registerIndexCommand(program2) {
36662
36718
  const index = program2.command("index").description("Query the decoded Index layer (L2 events + contract calls)");
36663
36719
  const rangeFlags = (cmd) => cmd.option("--contract-id <id>", "Filter by contract id").option("--from-height <n>", "Start block height (inclusive)").option("--to-height <n>", "End block height (inclusive)").option("--cursor <cursor>", "Resume token from a previous next_cursor").option("--limit <n>", "Rows per page").option("--json", "Print the full envelope as JSON");
36720
+ const heightFlags = (cmd) => cmd.option("--from-height <n>", "Start block height (inclusive)").option("--to-height <n>", "End block height (inclusive)").option("--cursor <cursor>", "Resume token from a previous next_cursor").option("--limit <n>", "Rows per page").option("--json", "Print the full envelope as JSON");
36664
36721
  rangeFlags(index.command("ft-transfers")).description("List decoded SIP-010 fungible-token transfers").option("--sender <principal>", "Filter by sender").option("--recipient <principal>", "Filter by recipient").action(async (o) => {
36665
36722
  try {
36666
36723
  emit(await client3().ftTransfers.list({
@@ -36708,6 +36765,119 @@ function registerIndexCommand(program2) {
36708
36765
  fail("list contract calls", err);
36709
36766
  }
36710
36767
  });
36768
+ heightFlags(index.command("canonical")).description("List the canonical Stacks block sequence (height + hash)").action(async (o) => {
36769
+ try {
36770
+ emit(await client3().canonical.list(heightParams(o)), o.json);
36771
+ } catch (err) {
36772
+ fail("list canonical blocks", err);
36773
+ }
36774
+ });
36775
+ const blocks = heightFlags(index.command("blocks")).description("List decoded blocks (run `blocks get <ref>` for one block)").action(async (o) => {
36776
+ try {
36777
+ emit(await client3().blocks.list(heightParams(o)), o.json);
36778
+ } catch (err) {
36779
+ fail("list blocks", err);
36780
+ }
36781
+ });
36782
+ blocks.command("get <ref>").description("Get a single block by height or block hash").option("--json", "Print as JSON").action(async (ref, o) => {
36783
+ try {
36784
+ const block = await client3().blocks.get(/^\d+$/.test(ref) ? Number.parseInt(ref, 10) : ref);
36785
+ emitOne(block, `block ${ref}`, o.json);
36786
+ } catch (err) {
36787
+ fail("get block", err);
36788
+ }
36789
+ });
36790
+ const transactions = rangeFlags(index.command("transactions")).description("List decoded transactions (run `transactions get <txId>` for one)").option("--type <type>", "Filter by transaction type").option("--sender <principal>", "Filter by sender").action(async (o) => {
36791
+ try {
36792
+ emit(await client3().transactions.list({
36793
+ ...rangeParams(o),
36794
+ type: o.type,
36795
+ sender: o.sender
36796
+ }), o.json);
36797
+ } catch (err) {
36798
+ fail("list transactions", err);
36799
+ }
36800
+ });
36801
+ transactions.command("get <txId>").description("Get a single transaction by tx_id").option("--json", "Print as JSON").action(async (txId, o) => {
36802
+ try {
36803
+ emitOne(await client3().transactions.get(txId), `tx ${txId}`, o.json);
36804
+ } catch (err) {
36805
+ fail("get transaction", err);
36806
+ }
36807
+ });
36808
+ heightFlags(index.command("stacking")).description("List decoded PoX-4 stacking actions").option("--function-name <name>", "Filter by PoX function name").option("--stacker <principal>", "Filter by stacker").option("--caller <principal>", "Filter by caller").action(async (o) => {
36809
+ try {
36810
+ emit(await client3().stacking.list({
36811
+ ...heightParams(o),
36812
+ functionName: o.functionName,
36813
+ stacker: o.stacker,
36814
+ caller: o.caller
36815
+ }), o.json);
36816
+ } catch (err) {
36817
+ fail("list stacking actions", err);
36818
+ }
36819
+ });
36820
+ const mempool = index.command("mempool").description("List pending mempool transactions (run `mempool get <txId>` for one)").option("--contract-id <id>", "Filter to pending calls to a contract").option("--sender <principal>", "Filter by sender").option("--type <type>", "Filter by transaction type").option("--cursor <cursor>", "Resume token from a previous next_cursor").option("--limit <n>", "Rows per page").option("--json", "Print the full envelope as JSON").action(async (o) => {
36821
+ try {
36822
+ emit(await client3().mempool.list({
36823
+ contractId: o.contractId,
36824
+ sender: o.sender,
36825
+ type: o.type,
36826
+ cursor: o.cursor,
36827
+ limit: o.limit ? Number.parseInt(o.limit, 10) : undefined
36828
+ }), o.json);
36829
+ } catch (err) {
36830
+ fail("list mempool", err);
36831
+ }
36832
+ });
36833
+ mempool.command("get <txId>").description("Get a single pending transaction by tx_id (404 once mined)").option("--json", "Print as JSON").action(async (txId, o) => {
36834
+ try {
36835
+ emitOne(await client3().mempool.get(txId), `pending tx ${txId}`, o.json);
36836
+ } catch (err) {
36837
+ fail("get mempool tx", err);
36838
+ }
36839
+ });
36840
+ }
36841
+ // src/commands/keys.ts
36842
+ init_output();
36843
+ init_resolve_auth();
36844
+ import { SecondLayer as SecondLayer4 } from "@secondlayer/sdk";
36845
+ var DEFAULT_BASE_URL5 = "https://api.secondlayer.tools";
36846
+ function registerKeysCommand(program2) {
36847
+ const keys = program2.command("keys").description("Manage API keys");
36848
+ keys.command("create").description("Mint a scoped streams/index read key (requires an account-level key)").option("--product <product>", "Key scope: streams or index", "streams").option("--name <name>", "Optional label for the key").option("--json", "Print the full response as JSON").action(async (o) => {
36849
+ if (o.product && o.product !== "streams" && o.product !== "index") {
36850
+ error("--product must be 'streams' or 'index'");
36851
+ process.exit(1);
36852
+ }
36853
+ const apiKey = resolveEnvKey();
36854
+ if (!apiKey) {
36855
+ error("No API key set. Export SL_API_KEY with an account-level key (issue one at https://www.secondlayer.tools/platform/api-keys).");
36856
+ process.exit(1);
36857
+ }
36858
+ try {
36859
+ const sl = new SecondLayer4({
36860
+ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL5,
36861
+ apiKey
36862
+ });
36863
+ const minted = await sl.apiKeys.create({
36864
+ product: o.product === "index" ? "index" : "streams",
36865
+ name: o.name
36866
+ });
36867
+ output({
36868
+ json: o.json,
36869
+ data: minted,
36870
+ human: () => {
36871
+ success(`Created ${minted.product} key (${minted.prefix}…)`);
36872
+ note("This key is shown once — store it now:");
36873
+ writeData(minted.key);
36874
+ }
36875
+ });
36876
+ } catch (err) {
36877
+ error(err instanceof Error ? err.message : String(err));
36878
+ process.exit(1);
36879
+ }
36880
+ });
36711
36881
  }
36712
36882
  // src/commands/doctor.ts
36713
36883
  init_config();
@@ -38221,9 +38391,11 @@ program.commandsGroup("Diagnostics:");
38221
38391
  registerStatusCommand(program);
38222
38392
  registerDoctorCommand(program);
38223
38393
  registerConfigCommand(program);
38394
+ registerContextCommand(program);
38224
38395
  program.commandsGroup("Account:");
38225
38396
  registerAccountCommand(program);
38397
+ registerKeysCommand(program);
38226
38398
  program.parse();
38227
38399
 
38228
- //# debugId=1CE2C8D6E9B70EC764756E2164756E21
38400
+ //# debugId=09F28BAC8C0CF0E864756E2164756E21
38229
38401
  //# sourceMappingURL=cli.js.map