@secondlayer/cli 20.0.1 → 20.1.1

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
@@ -164,7 +164,8 @@ points at.
164
164
  | Command | What it does |
165
165
  |---|---|
166
166
  | `secondlayer index ft-transfers` / `nft-transfers` / `events --event-type <t>` / `contract-calls` | Decoded Index layer. Anonymous reads OK |
167
- | `secondlayer streams tip` / `events` / `consume` / `reorgs` / `canonical <h>` / `dumps` | Raw chain event firehose. `consume` emits one event per line; a reorg appears inline as `{"kind":"reorg","fork_point_height":…}` and the loop rewinds to re-deliver the canonical run, so a reader drops rows at or above the fork point when it sees one. `--max-pages` must be a positive integer. **Requires `INSTANCE_TOKEN` past loopback** |
167
+ | `secondlayer index runes` / `runes get <rune>` / `runes balances (--address <a> \| --outpoint <txid:vout>)` / `runes activity [--kind etch,mint,transfer,burn]` | Bitcoin Runes: catalog, one rune, balances, activity. Hosted answers a "not configured" note until Runes data lands there |
168
+ | `secondlayer streams tip` / `events` / `consume` / `reorgs` / `canonical <h>` / `dumps` | Raw chain event firehose. `consume` emits one event per line; a reorg appears inline as `{"kind":"reorg","fork_point_height":…}` and the loop rewinds to re-deliver the canonical run, so a reader drops rows at or above the fork point when it sees one. `--max-pages` must be a positive integer. `events`, `events by-tx`, `consume` and `reorgs` take `--chain bitcoin` for Runes events (`rune_*` types; Stacks-only filters are refused). **Requires `INSTANCE_TOKEN` past loopback** |
168
169
 
169
170
  Reads emit JSON to stdout (`--json` accepted across all read commands); `-o/--output` is a file path, not a format.
170
171
 
package/dist/cli.js CHANGED
@@ -200299,6 +200299,34 @@ function fail(action, err) {
200299
200299
  }
200300
200300
  process.exit(1);
200301
200301
  }
200302
+ function parseRuneSort(value) {
200303
+ if (value === undefined)
200304
+ return;
200305
+ if (!RUNE_SORTS.includes(value)) {
200306
+ throw new Error(`invalid --sort "${value}"; expected one of: ${RUNE_SORTS.join(", ")}`);
200307
+ }
200308
+ return value;
200309
+ }
200310
+ function parseRuneKinds(value) {
200311
+ if (value === undefined)
200312
+ return;
200313
+ return value.split(",").map((raw) => {
200314
+ const name = raw.trim();
200315
+ if (!RUNE_KINDS.includes(name)) {
200316
+ throw new Error(`invalid --kind "${name}"; expected one or more of: ${RUNE_KINDS.join(", ")}`);
200317
+ }
200318
+ return `rune_${name}`;
200319
+ });
200320
+ }
200321
+ function runeBalanceSubject(o) {
200322
+ if (o.address !== undefined && o.outpoint === undefined) {
200323
+ return { address: o.address };
200324
+ }
200325
+ if (o.outpoint !== undefined && o.address === undefined) {
200326
+ return { outpoint: o.outpoint };
200327
+ }
200328
+ throw new Error("pass --address or --outpoint (one of them)");
200329
+ }
200302
200330
  function heightParams(o) {
200303
200331
  return {
200304
200332
  fromHeight: o.fromHeight ? Number.parseInt(o.fromHeight, 10) : undefined,
@@ -200456,6 +200484,53 @@ function registerIndexCommand(program) {
200456
200484
  fail("get mempool tx", err);
200457
200485
  }
200458
200486
  });
200487
+ 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) => {
200488
+ try {
200489
+ emit(await client().runes.list({
200490
+ search: o.search,
200491
+ sort: parseRuneSort(o.sort),
200492
+ cursor: o.cursor,
200493
+ limit: o.limit ? Number.parseInt(o.limit, 10) : undefined
200494
+ }), o.json);
200495
+ } catch (err) {
200496
+ fail("list runes", err);
200497
+ }
200498
+ });
200499
+ 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) => {
200500
+ const o = cmd.optsWithGlobals();
200501
+ try {
200502
+ emitOne(await client().runes.get(rune), `rune ${rune}`, o.json);
200503
+ } catch (err) {
200504
+ fail("get rune", err);
200505
+ }
200506
+ });
200507
+ 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) => {
200508
+ const o = cmd.optsWithGlobals();
200509
+ try {
200510
+ emit(await client().runes.balances({
200511
+ ...runeBalanceSubject(o),
200512
+ rune: o.rune,
200513
+ cursor: o.cursor,
200514
+ limit: o.limit ? Number.parseInt(o.limit, 10) : undefined
200515
+ }), o.json);
200516
+ } catch (err) {
200517
+ fail("list rune balances", err);
200518
+ }
200519
+ });
200520
+ 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) => {
200521
+ const o = cmd.optsWithGlobals();
200522
+ try {
200523
+ emit(await client().runes.activity.list({
200524
+ ...heightParams(o),
200525
+ rune: o.rune,
200526
+ address: o.address,
200527
+ kind: parseRuneKinds(o.kind),
200528
+ txid: o.txid
200529
+ }), o.json);
200530
+ } catch (err) {
200531
+ fail("list rune activity", err);
200532
+ }
200533
+ });
200459
200534
  }
200460
200535
  async function runIndexCodegen(o) {
200461
200536
  try {
@@ -200482,12 +200557,14 @@ async function runIndexCodegen(o) {
200482
200557
  process.exit(1);
200483
200558
  }
200484
200559
  }
200485
- var VALID_INDEX_TYPES;
200560
+ var VALID_INDEX_TYPES, RUNE_SORTS, RUNE_KINDS;
200486
200561
  var init_index_api = __esm(() => {
200487
200562
  init_fs();
200488
200563
  init_output();
200489
200564
  init_resolve_auth();
200490
200565
  VALID_INDEX_TYPES = DECODED_EVENT_TYPES3;
200566
+ RUNE_SORTS = ["number", "mints"];
200567
+ RUNE_KINDS = ["etch", "mint", "transfer", "burn"];
200491
200568
  });
200492
200569
 
200493
200570
  // ../../node_modules/postgres/src/query.js
@@ -202569,7 +202646,7 @@ var {
202569
202646
  // package.json
202570
202647
  var package_default = {
202571
202648
  name: "@secondlayer/cli",
202572
- version: "20.0.1",
202649
+ version: "20.1.1",
202573
202650
  description: "Run a Stacks index on your own hardware — set it up, restore verified history, and keep it current.",
202574
202651
  repository: {
202575
202652
  type: "git",
@@ -202608,11 +202685,11 @@ var package_default = {
202608
202685
  "@inquirer/prompts": "^8.2.0",
202609
202686
  "@secondlayer/bundler": "^0.7.1",
202610
202687
  "@secondlayer/scaffold": "^1.6.2",
202611
- "@secondlayer/sdk": "^15.0.0",
202612
- "@secondlayer/shared": "^12.0.0",
202613
- "@secondlayer/stacks": "^6.2.0",
202614
- "@secondlayer/subgraphs": "^7.0.1",
202615
- "@secondlayer/verify": "^0.5.0",
202688
+ "@secondlayer/sdk": "^15.0.1",
202689
+ "@secondlayer/shared": "^12.1.1",
202690
+ "@secondlayer/stacks": "^6.2.1",
202691
+ "@secondlayer/subgraphs": "^7.0.2",
202692
+ "@secondlayer/verify": "^0.5.3",
202616
202693
  esbuild: "^0.28.2",
202617
202694
  "smol-toml": "^1.9.1",
202618
202695
  zod: "^4.3.6"
@@ -206729,7 +206806,7 @@ import { createHash as createHash5 } from "node:crypto";
206729
206806
  import { mkdir as mkdir3, open as open2, rename as rename2 } from "node:fs/promises";
206730
206807
  import { dirname as dirname8, isAbsolute, resolve as resolve7, sep as sep2 } from "node:path";
206731
206808
  import { createStreamsClient } from "@secondlayer/sdk";
206732
- import { STREAMS_EVENT_TYPES } from "@secondlayer/shared";
206809
+ import { RUNE_EVENT_TYPES, STREAMS_EVENT_TYPES } from "@secondlayer/shared";
206733
206810
  var VALID_TYPES = STREAMS_EVENT_TYPES;
206734
206811
  function client2() {
206735
206812
  return createStreamsClient({
@@ -206791,17 +206868,40 @@ async function downloadDumpTo(file, dest, fetchImpl, url) {
206791
206868
  await rename2(part, dest);
206792
206869
  return bytes;
206793
206870
  }
206794
- function parseTypes(value, flag = "--types") {
206871
+ function parseChain(value) {
206872
+ if (value === undefined || value === "stacks")
206873
+ return;
206874
+ if (value !== "bitcoin") {
206875
+ throw new Error(`invalid --chain "${value}"; expected stacks or bitcoin`);
206876
+ }
206877
+ return "bitcoin";
206878
+ }
206879
+ function parseTypes(value, flag = "--types", chain) {
206795
206880
  if (!value)
206796
206881
  return;
206882
+ const valid = chain === "bitcoin" ? RUNE_EVENT_TYPES : VALID_TYPES;
206797
206883
  const parts = value.split(",").map((s) => s.trim());
206798
206884
  for (const p of parts) {
206799
- if (!VALID_TYPES.includes(p)) {
206800
- throw new Error(`invalid ${flag} value "${p}"; expected one of: ${VALID_TYPES.join(", ")}`);
206885
+ if (!valid.includes(p)) {
206886
+ throw new Error(`invalid ${flag} value "${p}"; expected one of: ${valid.join(", ")}`);
206801
206887
  }
206802
206888
  }
206803
206889
  return parts;
206804
206890
  }
206891
+ function rejectStacksFilters(chain, o) {
206892
+ if (chain !== "bitcoin")
206893
+ return;
206894
+ for (const [flag, value] of [
206895
+ ["--contract-id", o.contractId],
206896
+ ["--sender", o.sender],
206897
+ ["--recipient", o.recipient]
206898
+ ]) {
206899
+ if (value !== undefined) {
206900
+ throw new Error(`${flag} is Stacks-only; drop it with --chain bitcoin`);
206901
+ }
206902
+ }
206903
+ }
206904
+ var CHAIN_HELP = "stacks (default) or bitcoin (Runes events, their own cursors)";
206805
206905
  function parseList(value) {
206806
206906
  if (value === undefined)
206807
206907
  return;
@@ -206862,16 +206962,20 @@ function registerStreamsCommand(program) {
206862
206962
  process.exit(1);
206863
206963
  }
206864
206964
  });
206865
- 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("--event-type <type>", "alias for a single-value --types (the Index spelling)").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", `
206965
+ const events = streams.command("events").description("List events (cursor-paginated; one page per call)").option("--chain <chain>", CHAIN_HELP).option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")}; ${RUNE_EVENT_TYPES.join(", ")} with --chain bitcoin)`).option("--event-type <type>", "alias for a single-value --types (the Index spelling)").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", `
206866
206966
  Examples:
206867
206967
  $ secondlayer streams events --types stx_transfer,print --limit 50
206868
206968
  $ secondlayer streams events --not-types print --contract-id SP00....token,SP01....token
206869
206969
  $ secondlayer streams events --sender SP1...,SP2... --from-block 150000 --to-block 160000
206870
- $ secondlayer streams events --cursor 150000:3`).action(async (options) => {
206970
+ $ secondlayer streams events --cursor 150000:3
206971
+ $ secondlayer streams events --chain bitcoin --types rune_mint --limit 50`).action(async (options) => {
206871
206972
  try {
206973
+ const chain = parseChain(options.chain);
206974
+ rejectStacksFilters(chain, options);
206872
206975
  const envelope = await client2().events.list({
206873
- types: parseTypes(options.types ?? options.eventType),
206874
- notTypes: parseTypes(options.notTypes, "--not-types"),
206976
+ chain,
206977
+ types: parseTypes(options.types ?? options.eventType, "--types", chain),
206978
+ notTypes: parseTypes(options.notTypes, "--not-types", chain),
206875
206979
  contractId: parseList(options.contractId),
206876
206980
  sender: parseList(options.sender),
206877
206981
  recipient: parseList(options.recipient),
@@ -206886,22 +206990,26 @@ Examples:
206886
206990
  process.exit(1);
206887
206991
  }
206888
206992
  });
206889
- 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) => {
206993
+ events.command("by-tx <txId>").description("List all events emitted by a single transaction").option("--chain <chain>", CHAIN_HELP).option("--json", "Output as JSON (streams always emits JSON)").action(async (txId, _o, cmd) => {
206994
+ const options = cmd.optsWithGlobals();
206890
206995
  try {
206891
- const envelope = await client2().events.byTxId(txId);
206996
+ const chain = parseChain(options.chain);
206997
+ const envelope = chain ? await client2().events.byTxId(txId, { chain }) : await client2().events.byTxId(txId);
206892
206998
  writeData(JSON.stringify(envelope, null, 2));
206893
206999
  } catch (err) {
206894
207000
  error(err instanceof Error ? err.message : String(err));
206895
207001
  process.exit(1);
206896
207002
  }
206897
207003
  });
206898
- 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", `
207004
+ streams.command("consume").description("Long-running pull from a cursor; emits one event per line (jsonl) until SIGINT or --max-pages").option("--chain <chain>", CHAIN_HELP).option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")}; ${RUNE_EVENT_TYPES.join(", ")} with --chain bitcoin)`).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", `
206899
207005
  Examples:
206900
207006
  $ secondlayer streams consume --types print --cursor 150000:0
206901
207007
  $ secondlayer streams consume --not-types print --sender SP1...,SP2... --batch-size 500 --max-pages 10`).action(async (options) => {
206902
207008
  try {
206903
207009
  const batchSize = parseLimit(options.batchSize) ?? 100;
206904
207010
  const maxPages = parseMaxPages(options.maxPages);
207011
+ const chain = parseChain(options.chain);
207012
+ rejectStacksFilters(chain, options);
206905
207013
  note('# streaming events to stdout (jsonl); reorgs appear inline as {"kind":"reorg"}; next_cursor printed to stderr');
206906
207014
  const handlers = consumeHandlers({
206907
207015
  stdout: (line) => process.stdout.write(`${line}
@@ -206910,9 +207018,10 @@ Examples:
206910
207018
  `)
206911
207019
  });
206912
207020
  await client2().events.consume({
207021
+ chain,
206913
207022
  fromCursor: options.cursor,
206914
- types: parseTypes(options.types),
206915
- notTypes: parseTypes(options.notTypes, "--not-types"),
207023
+ types: parseTypes(options.types, "--types", chain),
207024
+ notTypes: parseTypes(options.notTypes, "--not-types", chain),
206916
207025
  contractId: parseList(options.contractId),
206917
207026
  sender: parseList(options.sender),
206918
207027
  recipient: parseList(options.recipient),
@@ -206927,9 +207036,11 @@ Examples:
206927
207036
  process.exit(1);
206928
207037
  }
206929
207038
  });
206930
- streams.command("reorgs").description("List recent reorgs (cursor-paginated)").requiredOption("--since <cursor>", "start cursor (block_height:event_index)").option("--limit <n>", "page size (default 100)", "100").option("--json", "Output as JSON (streams always emits JSON)").action(async (options) => {
207039
+ streams.command("reorgs").description("List recent reorgs (cursor-paginated)").requiredOption("--since <cursor>", "start cursor (block_height:event_index)").option("--chain <chain>", CHAIN_HELP).option("--limit <n>", "page size (default 100)", "100").option("--json", "Output as JSON (streams always emits JSON)").action(async (options) => {
206931
207040
  try {
207041
+ const chain = parseChain(options.chain);
206932
207042
  const envelope = await client2().reorgs.list({
207043
+ ...chain && { chain },
206933
207044
  since: options.since,
206934
207045
  limit: parseLimit(options.limit)
206935
207046
  });
@@ -208493,8 +208604,8 @@ services:
208493
208604
  profiles: ["full-node"]
208494
208605
 
208495
208606
  stacks-node:
208496
- # Consensus-critical — digest-pinned to 4.0.1. See docker/oss/docker-compose.yml.
208497
- image: ghcr.io/stacks-network/stacks-core:4.0.1@sha256:ceb768f881ef52a1d2792a2b4a89d81e092b1df11293b04c31ce36613c3f9711
208607
+ # Consensus-critical — digest-pinned to 4.0.5. See docker/oss/docker-compose.yml.
208608
+ image: ghcr.io/stacks-network/stacks-core:4.0.5@sha256:51aa7bf6f990b99fa010ebb23abe78653cf1f1d129ab8e7d88b1fe11a403c97d
208498
208609
  volumes:
208499
208610
  - \${STACKS_DATA_DIR:-./data/stacks}:/stacks-blockchain/data
208500
208611
  - ./Config.toml:/stacks-blockchain/Config.toml:ro
@@ -209393,5 +209504,5 @@ registerCreditsCommand(program);
209393
209504
  registerArchiveCommand(program);
209394
209505
  program.parse();
209395
209506
 
209396
- //# debugId=255DFF8A4862FC7D64756E2164756E21
209507
+ //# debugId=E9EB99B555C4CFDB64756E2164756E21
209397
209508
  //# sourceMappingURL=cli.js.map