@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 +2 -1
- package/dist/cli.js +135 -24
- package/dist/cli.js.map +5 -5
- package/package.json +6 -6
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
|
|
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.
|
|
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.
|
|
202612
|
-
"@secondlayer/shared": "^12.
|
|
202613
|
-
"@secondlayer/stacks": "^6.2.
|
|
202614
|
-
"@secondlayer/subgraphs": "^7.0.
|
|
202615
|
-
"@secondlayer/verify": "^0.5.
|
|
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
|
|
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 (!
|
|
206800
|
-
throw new Error(`invalid ${flag} value "${p}"; expected one of: ${
|
|
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
|
|
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
|
-
|
|
206874
|
-
|
|
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
|
|
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.
|
|
208497
|
-
image: ghcr.io/stacks-network/stacks-core:4.0.
|
|
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=
|
|
209507
|
+
//# debugId=E9EB99B555C4CFDB64756E2164756E21
|
|
209397
209508
|
//# sourceMappingURL=cli.js.map
|