@secondlayer/cli 23.0.0 → 23.1.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/dist/cli.js CHANGED
@@ -31507,7 +31507,7 @@ function client() {
31507
31507
  apiKey: resolveDataPlaneKey()
31508
31508
  });
31509
31509
  }
31510
- function fail(action, err) {
31510
+ function fail2(action, err) {
31511
31511
  const message = err instanceof Error ? err.message : String(err);
31512
31512
  error(`Failed to ${action}: ${message}`);
31513
31513
  if (/\b403\b/.test(message) || /forbidden/i.test(message)) {
@@ -31598,7 +31598,7 @@ function registerIndexCommand(program) {
31598
31598
  recipient: o.recipient
31599
31599
  }), o.json);
31600
31600
  } catch (err) {
31601
- fail("list ft transfers", err);
31601
+ fail2("list ft transfers", err);
31602
31602
  }
31603
31603
  });
31604
31604
  orderFlag(rangeFlags(index.command("nft-transfers"))).description("List decoded SIP-009 non-fungible-token transfers").option("--sender <principal>", "Filter by sender").option("--recipient <principal>", "Filter by recipient").option("--asset-identifier <id>", "Filter by asset identifier").action(async (o) => {
@@ -31611,7 +31611,7 @@ function registerIndexCommand(program) {
31611
31611
  assetIdentifier: o.assetIdentifier
31612
31612
  }), o.json);
31613
31613
  } catch (err) {
31614
- fail("list nft transfers", err);
31614
+ fail2("list nft transfers", err);
31615
31615
  }
31616
31616
  });
31617
31617
  orderFlag(rangeFlags(index.command("events"))).description("List decoded events by type (stx_*, ft/nft mint/burn, print, …)").option("--event-type <type>", `decoded event type (${VALID_INDEX_TYPES.join(", ")})`).option("--types <type>", "alias for --event-type, ONE value (the Streams spelling)").option("--sender <principal>", "Filter by sender").option("--recipient <principal>", "Filter by recipient").option("--asset-identifier <id>", "Filter by asset identifier").action(async (o) => {
@@ -31625,7 +31625,7 @@ function registerIndexCommand(program) {
31625
31625
  assetIdentifier: o.assetIdentifier
31626
31626
  }), o.json);
31627
31627
  } catch (err) {
31628
- fail("list events", err);
31628
+ fail2("list events", err);
31629
31629
  }
31630
31630
  });
31631
31631
  rangeFlags(index.command("contract-calls")).description("List decoded contract calls (function, args, result)").option("--function-name <name>", "Filter by called function").option("--sender <principal>", "Filter by caller").action(async (o) => {
@@ -31636,21 +31636,21 @@ function registerIndexCommand(program) {
31636
31636
  sender: o.sender
31637
31637
  }), o.json);
31638
31638
  } catch (err) {
31639
- fail("list contract calls", err);
31639
+ fail2("list contract calls", err);
31640
31640
  }
31641
31641
  });
31642
31642
  heightFlags(index.command("canonical")).description("List the canonical Stacks block sequence (height + hash)").action(async (o) => {
31643
31643
  try {
31644
31644
  emit(await client().canonical.list(heightParams(o)), o.json);
31645
31645
  } catch (err) {
31646
- fail("list canonical blocks", err);
31646
+ fail2("list canonical blocks", err);
31647
31647
  }
31648
31648
  });
31649
31649
  const blocks = heightFlags(index.command("blocks")).description("List decoded blocks (run `blocks get <ref>` for one block)").action(async (o) => {
31650
31650
  try {
31651
31651
  emit(await client().blocks.list(heightParams(o)), o.json);
31652
31652
  } catch (err) {
31653
- fail("list blocks", err);
31653
+ fail2("list blocks", err);
31654
31654
  }
31655
31655
  });
31656
31656
  blocks.command("get <ref>").description("Get a single block by height or block hash").option("--json", "Print as JSON").action(async (ref, o) => {
@@ -31658,7 +31658,7 @@ function registerIndexCommand(program) {
31658
31658
  const block = await client().blocks.get(/^\d+$/.test(ref) ? Number.parseInt(ref, 10) : ref);
31659
31659
  emitOne(block, `block ${ref}`, o.json);
31660
31660
  } catch (err) {
31661
- fail("get block", err);
31661
+ fail2("get block", err);
31662
31662
  }
31663
31663
  });
31664
31664
  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) => {
@@ -31669,14 +31669,14 @@ function registerIndexCommand(program) {
31669
31669
  sender: o.sender
31670
31670
  }), o.json);
31671
31671
  } catch (err) {
31672
- fail("list transactions", err);
31672
+ fail2("list transactions", err);
31673
31673
  }
31674
31674
  });
31675
31675
  transactions.command("get <txId>").description("Get a single transaction by tx_id").option("--json", "Print as JSON").action(async (txId, o) => {
31676
31676
  try {
31677
31677
  emitOne(await client().transactions.get(txId), `tx ${txId}`, o.json);
31678
31678
  } catch (err) {
31679
- fail("get transaction", err);
31679
+ fail2("get transaction", err);
31680
31680
  }
31681
31681
  });
31682
31682
  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) => {
@@ -31688,7 +31688,7 @@ function registerIndexCommand(program) {
31688
31688
  caller: o.caller
31689
31689
  }), o.json);
31690
31690
  } catch (err) {
31691
- fail("list stacking actions", err);
31691
+ fail2("list stacking actions", err);
31692
31692
  }
31693
31693
  });
31694
31694
  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("--function-name <name>", "Filter to pending calls to a function").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) => {
@@ -31702,14 +31702,14 @@ function registerIndexCommand(program) {
31702
31702
  limit: o.limit ? Number.parseInt(o.limit, 10) : undefined
31703
31703
  }), o.json);
31704
31704
  } catch (err) {
31705
- fail("list mempool", err);
31705
+ fail2("list mempool", err);
31706
31706
  }
31707
31707
  });
31708
31708
  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) => {
31709
31709
  try {
31710
31710
  emitOne(await client().mempool.get(txId), `pending tx ${txId}`, o.json);
31711
31711
  } catch (err) {
31712
- fail("get mempool tx", err);
31712
+ fail2("get mempool tx", err);
31713
31713
  }
31714
31714
  });
31715
31715
  const runes = index.command("runes").description("List etched runes (Bitcoin; run `runes get <rune>` for one)").option("--search <prefix>", "Name prefix, spacers and case ignored").option("--sort <order>", "number (etch order) or mints (busiest first)").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) => {
@@ -31721,7 +31721,7 @@ function registerIndexCommand(program) {
31721
31721
  limit: o.limit ? Number.parseInt(o.limit, 10) : undefined
31722
31722
  }), o.json);
31723
31723
  } catch (err) {
31724
- fail("list runes", err);
31724
+ fail2("list runes", err);
31725
31725
  }
31726
31726
  });
31727
31727
  runes.command("get <rune>").description("Get one rune by id (840000:3) or name, any spacing or case").option("--json", "Print as JSON").action(async (rune, _o, cmd) => {
@@ -31729,7 +31729,7 @@ function registerIndexCommand(program) {
31729
31729
  try {
31730
31730
  emitOne(await client().runes.get(rune), `rune ${rune}`, o.json);
31731
31731
  } catch (err) {
31732
- fail("get rune", err);
31732
+ fail2("get rune", err);
31733
31733
  }
31734
31734
  });
31735
31735
  runes.command("balances").description("Current rune balances by address or outpoint (Bitcoin)").option("--address <address>", "Bitcoin address").option("--outpoint <txid:vout>", "Unspent output").option("--rune <ref>", "Narrow to one rune (id or name)").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, cmd) => {
@@ -31742,7 +31742,7 @@ function registerIndexCommand(program) {
31742
31742
  limit: o.limit ? Number.parseInt(o.limit, 10) : undefined
31743
31743
  }), o.json);
31744
31744
  } catch (err) {
31745
- fail("list rune balances", err);
31745
+ fail2("list rune balances", err);
31746
31746
  }
31747
31747
  });
31748
31748
  runes.command("activity").description("List rune etches, mints, transfers and burns (Bitcoin)").option("--rune <ref>", "Filter by rune (id or name)").option("--address <address>", "Filter by Bitcoin address").option("--kind <kinds>", `Comma list of ${RUNE_KINDS.join(", ")}`).option("--txid <txid>", "Filter by Bitcoin transaction id").option("--from-height <n>", "Start Bitcoin block height (inclusive)").option("--to-height <n>", "End Bitcoin 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").action(async (_o, cmd) => {
@@ -31756,7 +31756,7 @@ function registerIndexCommand(program) {
31756
31756
  txid: o.txid
31757
31757
  }), o.json);
31758
31758
  } catch (err) {
31759
- fail("list rune activity", err);
31759
+ fail2("list rune activity", err);
31760
31760
  }
31761
31761
  });
31762
31762
  }
@@ -31888,7 +31888,7 @@ var {
31888
31888
  // package.json
31889
31889
  var package_default = {
31890
31890
  name: "@secondlayer/cli",
31891
- version: "23.0.0",
31891
+ version: "23.1.0",
31892
31892
  description: "Run a Stacks index on your own hardware — set it up, restore verified history, and keep it current.",
31893
31893
  repository: {
31894
31894
  type: "git",
@@ -34546,6 +34546,144 @@ async function runRefill(opts) {
34546
34546
  }
34547
34547
  });
34548
34548
  }
34549
+ // src/commands/keys.ts
34550
+ init_http();
34551
+ init_output();
34552
+ init_session();
34553
+ import { resolveAccountKey as resolveAccountKey4 } from "@secondlayer/sdk";
34554
+ var MIN_ID_REF_LENGTH = 8;
34555
+ function rotatableKeys(keys) {
34556
+ return keys.filter((k) => k.status === "active" && k.product === "account");
34557
+ }
34558
+ function describeKey(key) {
34559
+ return `${key.id.slice(0, 8)} ${key.name ?? "(unnamed)"}`;
34560
+ }
34561
+ function resolveKeyRef(keys, ref) {
34562
+ const candidates = rotatableKeys(keys);
34563
+ const barePrefix = ref.replace(/…$/, "");
34564
+ const kinds = [
34565
+ (k) => k.id === ref || ref.length >= MIN_ID_REF_LENGTH && k.id.startsWith(ref),
34566
+ (k) => k.prefix === barePrefix,
34567
+ (k) => k.name === ref
34568
+ ];
34569
+ for (const matches of kinds) {
34570
+ const found = candidates.filter(matches);
34571
+ if (found.length === 1)
34572
+ return found[0];
34573
+ if (found.length > 1) {
34574
+ throw new Error(`"${ref}" matches ${found.length} keys: ${found.map(describeKey).join(", ")}. Use an id.`);
34575
+ }
34576
+ }
34577
+ throw new Error(`No active account key matches "${ref}". Run: secondlayer keys list`);
34578
+ }
34579
+ async function applyRotationToLogin(prefix, newKey, deps = {}) {
34580
+ const apiUrl = deps.apiUrl ?? resolveArchiveOpsUrl();
34581
+ const read = deps.readSession ?? readSession;
34582
+ const write = deps.writeSession ?? writeSession;
34583
+ const envKey = "envKey" in deps ? deps.envKey : resolveAccountKey4();
34584
+ if (!prefix)
34585
+ return { loginUpdated: false, envStale: false };
34586
+ let loginUpdated = false;
34587
+ const session = await read(apiUrl);
34588
+ if (session?.token.startsWith(prefix)) {
34589
+ await write({ ...session, token: newKey }, apiUrl);
34590
+ loginUpdated = true;
34591
+ }
34592
+ return { loginUpdated, envStale: envKey?.startsWith(prefix) ?? false };
34593
+ }
34594
+ async function saveRotatedLogin(prefix, newKey, deps = {}) {
34595
+ try {
34596
+ return await applyRotationToLogin(prefix, newKey, deps);
34597
+ } catch (err) {
34598
+ const envKey = "envKey" in deps ? deps.envKey : resolveAccountKey4();
34599
+ return {
34600
+ loginUpdated: false,
34601
+ envStale: Boolean(prefix) && (envKey?.startsWith(prefix) ?? false),
34602
+ loginError: err instanceof Error ? err.message : String(err)
34603
+ };
34604
+ }
34605
+ }
34606
+ function fail(err) {
34607
+ if (err instanceof Error) {
34608
+ error(err.message);
34609
+ process.exit(1);
34610
+ }
34611
+ throw err;
34612
+ }
34613
+ async function fetchKeys() {
34614
+ const res = await httpArchiveOps("/api/keys");
34615
+ return res.keys;
34616
+ }
34617
+ async function runList(opts) {
34618
+ let keys;
34619
+ try {
34620
+ keys = rotatableKeys(await fetchKeys());
34621
+ } catch (err) {
34622
+ fail(err);
34623
+ }
34624
+ output({
34625
+ json: opts.json,
34626
+ data: {
34627
+ keys: keys.map(({ rowsDaily: _rowsDaily, ...rest }) => rest)
34628
+ },
34629
+ human: () => {
34630
+ if (keys.length === 0) {
34631
+ note("No active account keys. Make one at https://www.secondlayer.tools/account/keys");
34632
+ return;
34633
+ }
34634
+ console.log(formatTable(["ID", "NAME", "KEY", "LAST READ", "ROWS 30D"], keys.map((k) => [
34635
+ k.id.slice(0, 8),
34636
+ k.name ?? "(unnamed)",
34637
+ `${k.prefix}…`,
34638
+ k.lastUsedAt ?? "never",
34639
+ k.rows30d.toLocaleString("en-US")
34640
+ ])));
34641
+ }
34642
+ });
34643
+ }
34644
+ async function runRotate(ref, opts) {
34645
+ let target;
34646
+ try {
34647
+ target = resolveKeyRef(await fetchKeys(), ref);
34648
+ } catch (err) {
34649
+ fail(err);
34650
+ }
34651
+ const label = target.name ?? "(unnamed)";
34652
+ const ok = await confirmDestructive({
34653
+ message: `Rotate "${label}" (${target.prefix}…)? Anything using it gets a 401 at once.`,
34654
+ yes: opts.yes
34655
+ });
34656
+ if (!ok) {
34657
+ info("Cancelled");
34658
+ return;
34659
+ }
34660
+ let rotated;
34661
+ try {
34662
+ rotated = await httpArchiveOps(`/api/keys/${target.id}/rotate`, { method: "POST", body: {} });
34663
+ } catch (err) {
34664
+ fail(err);
34665
+ }
34666
+ const { loginUpdated, envStale, loginError } = await saveRotatedLogin(target.prefix, rotated.key);
34667
+ if (opts.json) {
34668
+ writeData(JSON.stringify({ ...rotated, loginUpdated }, null, 2));
34669
+ } else {
34670
+ success(`Rotated ${blue(label)}. The old key has stopped working.`);
34671
+ writeData(rotated.key);
34672
+ note("Shown once. Copy it now.");
34673
+ }
34674
+ if (loginError) {
34675
+ warn(`Couldn't update your CLI login: ${loginError}. Run: secondlayer login --with-token`);
34676
+ }
34677
+ if (loginUpdated)
34678
+ info("Updated your CLI login to the new key.");
34679
+ if (envStale)
34680
+ warn("SECONDLAYER_API_KEY still holds the old key. Update it.");
34681
+ }
34682
+ function registerKeysCommand(program) {
34683
+ const keys = program.command("keys").description("Manage account keys");
34684
+ keys.command("list").alias("ls").description("List your active account keys").option("--json", "Output as JSON").action((opts) => runList(opts));
34685
+ keys.command("rotate <ref>").description("Replace a key's secret; the old one stops working at once").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON").action((ref, opts) => runRotate(ref, opts));
34686
+ }
34549
34687
  // src/commands/codegen.ts
34550
34688
  function registerCodegenCommand(program) {
34551
34689
  const codegen = program.command("codegen").description("Generate typed code: contracts, subgraphs, Index, clients");
@@ -37615,6 +37753,7 @@ registerObserverCommand(program);
37615
37753
  registerLoginCommand(program);
37616
37754
  registerLogoutCommand(program);
37617
37755
  registerWhoamiCommand(program);
37756
+ registerKeysCommand(program);
37618
37757
  program.commandsGroup("Your data:");
37619
37758
  registerSubgraphsCommand(program);
37620
37759
  registerWebhooksCommand(program);
@@ -37638,5 +37777,5 @@ registerCreditsCommand(program);
37638
37777
  registerArchiveCommand(program);
37639
37778
  program.parse();
37640
37779
 
37641
- //# debugId=4D42122E1253AE8B64756E2164756E21
37780
+ //# debugId=0DC9F45DD895F4A264756E2164756E21
37642
37781
  //# sourceMappingURL=cli.js.map