@secondlayer/cli 23.2.1 → 23.4.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 +96 -179
- package/dist/cli.js.map +8 -8
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -29357,6 +29357,12 @@ function inspectSourceGitState(absPath) {
|
|
|
29357
29357
|
}
|
|
29358
29358
|
return { kind: "clean" };
|
|
29359
29359
|
}
|
|
29360
|
+
function uncommittedSourceWarning(state, file) {
|
|
29361
|
+
if (state.kind !== "untracked" && state.kind !== "modified")
|
|
29362
|
+
return;
|
|
29363
|
+
const reason = state.kind === "untracked" ? "not tracked by git" : "modified with uncommitted changes";
|
|
29364
|
+
return `${file} is ${reason}, so this deploy's only copy is the database row. Commit it to keep a copy.`;
|
|
29365
|
+
}
|
|
29360
29366
|
var init_git_status = () => {};
|
|
29361
29367
|
|
|
29362
29368
|
// src/lib/merge-print-subgraph.ts
|
|
@@ -29990,7 +29996,6 @@ import {
|
|
|
29990
29996
|
} from "node:fs";
|
|
29991
29997
|
import { basename, dirname as dirname5, extname, join as join7, relative, resolve as resolve5 } from "node:path";
|
|
29992
29998
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
29993
|
-
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
29994
29999
|
import {
|
|
29995
30000
|
generatePrintPayloadTypes,
|
|
29996
30001
|
generatePrintSchemaSubgraph as generatePrintSchemaSubgraph2,
|
|
@@ -30004,31 +30009,11 @@ import {
|
|
|
30004
30009
|
deriveVerification as deriveVerification2,
|
|
30005
30010
|
isDeterminismViolation
|
|
30006
30011
|
} from "@secondlayer/subgraphs/verification";
|
|
30007
|
-
async function
|
|
30008
|
-
|
|
30009
|
-
|
|
30010
|
-
|
|
30011
|
-
|
|
30012
|
-
const code = err?.code;
|
|
30013
|
-
const missingSdk = (code === "ERR_MODULE_NOT_FOUND" || msg.includes("ERR_MODULE_NOT_FOUND")) && msg.includes("@secondlayer/subgraphs");
|
|
30014
|
-
if (!missingSdk)
|
|
30015
|
-
throw err;
|
|
30016
|
-
warn("Missing dependency: @secondlayer/subgraphs");
|
|
30017
|
-
const install = await confirm2({
|
|
30018
|
-
message: "Install with `bun add @secondlayer/subgraphs`?",
|
|
30019
|
-
default: true
|
|
30020
|
-
});
|
|
30021
|
-
if (!install)
|
|
30022
|
-
throw err;
|
|
30023
|
-
await new Promise((res, rej) => {
|
|
30024
|
-
const child = spawn2("bun", ["add", "@secondlayer/subgraphs"], {
|
|
30025
|
-
stdio: "inherit"
|
|
30026
|
-
});
|
|
30027
|
-
child.on("error", rej);
|
|
30028
|
-
child.on("exit", (c) => c === 0 ? res() : rej(new Error(`bun add exit ${c}`)));
|
|
30029
|
-
});
|
|
30030
|
-
return await import(absPath);
|
|
30031
|
-
}
|
|
30012
|
+
async function loadSubgraphDefinition(source, fileName) {
|
|
30013
|
+
const { bundleSubgraphCode } = await import("@secondlayer/bundler");
|
|
30014
|
+
const bundled = await bundleSubgraphCode(source, { fileName });
|
|
30015
|
+
const url = `data:text/javascript;base64,${Buffer.from(bundled.handlerCode, "utf8").toString("base64")}`;
|
|
30016
|
+
return { mod: await import(url), bundled };
|
|
30032
30017
|
}
|
|
30033
30018
|
async function typecheckHandler(absPath) {
|
|
30034
30019
|
await new Promise((res, rej) => {
|
|
@@ -30542,8 +30527,7 @@ Try --trait sip-010 or \`subgraphs scaffold ${opts.fromContract}\` for ABI calls
|
|
|
30542
30527
|
if (opts.fromContract) {
|
|
30543
30528
|
info(`Schema inferred from ${opts.fromContract} print events (${opts.tablePerTopic ? "table per topic" : "single wide table"})`);
|
|
30544
30529
|
}
|
|
30545
|
-
info(`Next:
|
|
30546
|
-
note(" deploy refuses an unstaged file unless you pass --allow-uncommitted: a staged copy is the one git can recover.");
|
|
30530
|
+
info(`Next: secondlayer subgraphs deploy subgraphs/${name}.ts`);
|
|
30547
30531
|
});
|
|
30548
30532
|
subgraphs.command("add <file>").description("Merge another contract's observed print sources into an existing subgraph file").requiredOption("--from-contract <contractId>", "Contract whose print schema to merge (requires network)").option("--table-per-topic", "One table per print topic instead of a single wide table for the added contract").addHelpText("after", `
|
|
30549
30533
|
Adds sources/schema/handlers for a second (or Nth) contract into an existing
|
|
@@ -30650,10 +30634,10 @@ Stopped watching.`);
|
|
|
30650
30634
|
});
|
|
30651
30635
|
await new Promise(() => {});
|
|
30652
30636
|
});
|
|
30653
|
-
subgraphs.command("deploy <file>").alias("update").description("Deploy a subgraph definition file (alias: update — deploy is create-or-update)").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--tip-first", "Go live at chain tip immediately; history backfills in the background (handlers may only insert, upsert and delete; update, increment and row reads are refused)").option("--dry-run", "Validate and preview deploy without writing changes").option("-y, --yes", "Skip the reindex confirmation prompt").option("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").option("--allow-uncommitted", "
|
|
30654
|
-
|
|
30655
|
-
|
|
30656
|
-
--allow-uncommitted to
|
|
30637
|
+
subgraphs.command("deploy <file>").alias("update").description("Deploy a subgraph definition file (alias: update — deploy is create-or-update)").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--tip-first", "Go live at chain tip immediately; history backfills in the background (handlers may only insert, upsert and delete; update, increment and row reads are refused)").option("--dry-run", "Validate and preview deploy without writing changes").option("-y, --yes", "Skip the reindex confirmation prompt").option("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").option("--allow-uncommitted", "Don't warn when the source file isn't committed in git").addHelpText("after", `
|
|
30638
|
+
If the source file isn't committed in git, deploy warns that the deployed
|
|
30639
|
+
definition's only copy is the row in the database. It never blocks; pass
|
|
30640
|
+
--allow-uncommitted to silence the warning.
|
|
30657
30641
|
|
|
30658
30642
|
Hosted: set SECONDLAYER_API_KEY and SECONDLAYER_API_URL=https://api.secondlayer.tools.
|
|
30659
30643
|
Hostable sources are event filters and contract_call/contract_deploy; anything else
|
|
@@ -30662,28 +30646,10 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
|
|
|
30662
30646
|
try {
|
|
30663
30647
|
const absPath = resolve5(file);
|
|
30664
30648
|
if (!options.dryRun) {
|
|
30665
|
-
if (options.allowUncommitted) {
|
|
30666
|
-
|
|
30667
|
-
|
|
30668
|
-
|
|
30669
|
-
if (gitState.kind === "untracked" || gitState.kind === "modified") {
|
|
30670
|
-
const reason = gitState.kind === "untracked" ? "not tracked by git" : "modified with uncommitted changes";
|
|
30671
|
-
const message = `${file} is ${reason}. Deploy it and the only copy of this definition is a row in the database.`;
|
|
30672
|
-
if (process.stdin.isTTY) {
|
|
30673
|
-
warn(message);
|
|
30674
|
-
const confirmed = await confirm2({
|
|
30675
|
-
message: "Deploy anyway?",
|
|
30676
|
-
default: false
|
|
30677
|
-
});
|
|
30678
|
-
if (!confirmed) {
|
|
30679
|
-
info("Nothing was deployed.");
|
|
30680
|
-
process.exit(0);
|
|
30681
|
-
}
|
|
30682
|
-
} else {
|
|
30683
|
-
error(`${message} Stage it with \`git add ${file}\`, or pass --allow-uncommitted.`);
|
|
30684
|
-
process.exit(1);
|
|
30685
|
-
}
|
|
30686
|
-
}
|
|
30649
|
+
if (!options.allowUncommitted) {
|
|
30650
|
+
const advice = uncommittedSourceWarning(inspectSourceGitState(absPath), file);
|
|
30651
|
+
if (advice)
|
|
30652
|
+
warn(advice);
|
|
30687
30653
|
}
|
|
30688
30654
|
}
|
|
30689
30655
|
const config = await loadConfig2();
|
|
@@ -30697,18 +30663,28 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
|
|
|
30697
30663
|
await typecheckHandler(absPath);
|
|
30698
30664
|
}
|
|
30699
30665
|
info(`Loading subgraph from ${absPath}`);
|
|
30700
|
-
const mod = await loadSubgraphWithDepCheck(absPath);
|
|
30701
|
-
const def = mod.default ?? mod;
|
|
30702
|
-
const effectiveDef = {
|
|
30703
|
-
...startBlock === undefined ? def : { ...def, startBlock },
|
|
30704
|
-
...options.tipFirst ? { backfillMode: "concurrent" } : {}
|
|
30705
|
-
};
|
|
30706
30666
|
const { validateSubgraphDefinition } = await import("@secondlayer/subgraphs/validate");
|
|
30707
30667
|
const { readFile } = await import("node:fs/promises");
|
|
30708
30668
|
const derived = config.network !== "local" ? await withDerivedAbis(await readFile(absPath, "utf8")) : undefined;
|
|
30709
30669
|
for (const name of Object.keys(derived?.abis ?? {})) {
|
|
30710
30670
|
info(`Using the deployed contract's abi for source "${name}"`);
|
|
30711
30671
|
}
|
|
30672
|
+
const source = derived?.source ?? await readFile(absPath, "utf8");
|
|
30673
|
+
const { mod, bundled } = await loadSubgraphDefinition(source, relative(process.cwd(), absPath));
|
|
30674
|
+
const def = mod.default ?? mod;
|
|
30675
|
+
const authored = {
|
|
30676
|
+
...def,
|
|
30677
|
+
sources: Object.fromEntries(Object.entries(def.sources ?? {}).map(([k, v]) => {
|
|
30678
|
+
if (!derived?.abis[k])
|
|
30679
|
+
return [k, v];
|
|
30680
|
+
const { abi: _abi, ...rest } = v;
|
|
30681
|
+
return [k, rest];
|
|
30682
|
+
}))
|
|
30683
|
+
};
|
|
30684
|
+
const effectiveDef = {
|
|
30685
|
+
...startBlock === undefined ? authored : { ...authored, startBlock },
|
|
30686
|
+
...options.tipFirst ? { backfillMode: "concurrent" } : {}
|
|
30687
|
+
};
|
|
30712
30688
|
const validated = validateSubgraphDefinition(derived && Object.keys(derived.abis).length > 0 ? {
|
|
30713
30689
|
...effectiveDef,
|
|
30714
30690
|
sources: Object.fromEntries(Object.entries(effectiveDef.sources).map(([k, v]) => [
|
|
@@ -30721,11 +30697,6 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
|
|
|
30721
30697
|
}
|
|
30722
30698
|
if (config.network !== "local") {
|
|
30723
30699
|
info(`${dryRun ? "Bundling for remote deploy dry run" : "Bundling for remote deploy"} (${config.network})...`);
|
|
30724
|
-
const source = derived?.source ?? await readFile(absPath, "utf8");
|
|
30725
|
-
const { bundleSubgraphCode } = await import("@secondlayer/bundler");
|
|
30726
|
-
const bundled = await bundleSubgraphCode(source, {
|
|
30727
|
-
fileName: relative(process.cwd(), absPath)
|
|
30728
|
-
});
|
|
30729
30700
|
const handlerCode = bundled.handlerCode;
|
|
30730
30701
|
const localVerification = checkDeterminism(effectiveDef, bundled.findings);
|
|
30731
30702
|
if (dryRun) {
|
|
@@ -30840,16 +30811,7 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
|
|
|
30840
30811
|
await printDeployFooter();
|
|
30841
30812
|
}
|
|
30842
30813
|
} else {
|
|
30843
|
-
|
|
30844
|
-
try {
|
|
30845
|
-
const { bundleSubgraphCode } = await import("@secondlayer/bundler");
|
|
30846
|
-
findings = (await bundleSubgraphCode(await readFile(absPath, "utf8"), {
|
|
30847
|
-
fileName: relative(process.cwd(), absPath)
|
|
30848
|
-
})).findings;
|
|
30849
|
-
} catch {
|
|
30850
|
-
findings = undefined;
|
|
30851
|
-
}
|
|
30852
|
-
const verification = findings ? checkDeterminism(effectiveDef, findings) : undefined;
|
|
30814
|
+
const verification = checkDeterminism(effectiveDef, bundled.findings);
|
|
30853
30815
|
if (dryRun) {
|
|
30854
30816
|
printSubgraphDeployPreview(createSubgraphDeployPreview(validated), {
|
|
30855
30817
|
network: config.network,
|
|
@@ -31892,7 +31854,7 @@ var {
|
|
|
31892
31854
|
// package.json
|
|
31893
31855
|
var package_default = {
|
|
31894
31856
|
name: "@secondlayer/cli",
|
|
31895
|
-
version: "23.
|
|
31857
|
+
version: "23.4.0",
|
|
31896
31858
|
description: "Run a Stacks index on your own hardware — set it up, restore verified history, and keep it current.",
|
|
31897
31859
|
repository: {
|
|
31898
31860
|
type: "git",
|
|
@@ -31918,7 +31880,7 @@ var package_default = {
|
|
|
31918
31880
|
build: "bunup",
|
|
31919
31881
|
dev: "bunup --watch",
|
|
31920
31882
|
test: "bun test",
|
|
31921
|
-
typecheck: "
|
|
31883
|
+
typecheck: "bun check",
|
|
31922
31884
|
prepublishOnly: "bun run build"
|
|
31923
31885
|
},
|
|
31924
31886
|
keywords: [
|
|
@@ -31942,8 +31904,8 @@ var package_default = {
|
|
|
31942
31904
|
"@secondlayer/bundler": "^0.7.3",
|
|
31943
31905
|
"@secondlayer/scaffold": "^1.6.3",
|
|
31944
31906
|
"@secondlayer/sdk": "^16.2.0",
|
|
31945
|
-
"@secondlayer/shared": "^15.0.
|
|
31946
|
-
"@secondlayer/stacks": "^6.
|
|
31907
|
+
"@secondlayer/shared": "^15.0.1",
|
|
31908
|
+
"@secondlayer/stacks": "^6.6.0",
|
|
31947
31909
|
"@secondlayer/subgraphs": "^8.0.1",
|
|
31948
31910
|
"@secondlayer/verify": "^0.6.1",
|
|
31949
31911
|
esbuild: "^0.28.2",
|
|
@@ -35611,14 +35573,14 @@ import { dirname as dirname7, join as join10 } from "node:path";
|
|
|
35611
35573
|
var DEFAULT_IMAGE_OWNER = "ryanwaits";
|
|
35612
35574
|
var DEFAULT_IMAGE_TAG = "latest";
|
|
35613
35575
|
var DEV_INSTANCE_TOKEN = "dev-instance-token";
|
|
35576
|
+
var DEV_WEBHOOK_SIGNING_KEY = "-----BEGIN PRIVATE KEY-----\\nMC4CAQAwBQYDK2VwBCIEIIczaKV9CBblFKXjqGwrA3A1FOJxY2HiST7++XGea/jX\\n-----END PRIVATE KEY-----";
|
|
35614
35577
|
function buildDevnetCompose(opts = {}) {
|
|
35615
35578
|
const owner = opts.owner ?? DEFAULT_IMAGE_OWNER;
|
|
35616
35579
|
const tag = opts.imageTag ?? DEFAULT_IMAGE_TAG;
|
|
35617
35580
|
const apiPort = opts.apiPort ?? 3800;
|
|
35618
35581
|
const indexerPort = opts.indexerPort ?? 3700;
|
|
35619
35582
|
const apiPublish = `127.0.0.1:${apiPort}`;
|
|
35620
|
-
const
|
|
35621
|
-
const indexerImage = `ghcr.io/${owner}/secondlayer-indexer:${tag}`;
|
|
35583
|
+
const runtimeImage = `ghcr.io/${owner}/secondlayer-runtime:${tag}`;
|
|
35622
35584
|
const dbUrl = "postgres://secondlayer:secondlayer@postgres:5432/secondlayer";
|
|
35623
35585
|
const DEV_SECRETS_KEY = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
|
|
35624
35586
|
return `# Generated by \`secondlayer devnet connect\` — do not edit by hand.
|
|
@@ -35641,22 +35603,24 @@ services:
|
|
|
35641
35603
|
retries: 10
|
|
35642
35604
|
restart: unless-stopped
|
|
35643
35605
|
|
|
35644
|
-
|
|
35645
|
-
image: ${
|
|
35646
|
-
command: ["bun", "run", "packages/shared/src/db/migrate.ts"]
|
|
35647
|
-
environment:
|
|
35648
|
-
DATABASE_URL: ${dbUrl}
|
|
35649
|
-
depends_on:
|
|
35650
|
-
postgres:
|
|
35651
|
-
condition: service_healthy
|
|
35652
|
-
restart: "no"
|
|
35653
|
-
|
|
35654
|
-
api:
|
|
35655
|
-
image: ${apiImage}
|
|
35606
|
+
secondlayer:
|
|
35607
|
+
image: ${runtimeImage}
|
|
35656
35608
|
environment:
|
|
35657
35609
|
INSTANCE_MODE: oss
|
|
35610
|
+
# Keep every network key aligned: the indexer writes index_progress under
|
|
35611
|
+
# STACKS_NETWORK, the subgraph processor reads it under NETWORK. If they
|
|
35612
|
+
# differ, catch-up finds no progress row and subgraphs never advance.
|
|
35613
|
+
NETWORKS: testnet
|
|
35614
|
+
STACKS_NETWORK: testnet
|
|
35615
|
+
NETWORK: testnet
|
|
35616
|
+
NODE_MODE: external
|
|
35617
|
+
# A devnet index is tiny; the runtime's RAM/disk floors target real
|
|
35618
|
+
# networks and a laptop's Docker VM often has less than 80 GB free.
|
|
35619
|
+
SECONDLAYER_ALLOW_UNDERSIZED: "true"
|
|
35658
35620
|
DATABASE_URL: ${dbUrl}
|
|
35659
|
-
|
|
35621
|
+
DATA_DIR: /data
|
|
35622
|
+
API_PORT: "3800"
|
|
35623
|
+
INDEXER_PORT: "3700"
|
|
35660
35624
|
# 0.0.0.0 is forced: a container process that binds loopback is
|
|
35661
35625
|
# unreachable through a published port. The real reach is the publish
|
|
35662
35626
|
# spec below, handed over verbatim so /v1 reads stay keyless on devnet.
|
|
@@ -35665,93 +35629,48 @@ services:
|
|
|
35665
35629
|
# Boot guard reads LISTEN_HOST, so a token is required to start at all.
|
|
35666
35630
|
# It gates writes only — reads are open on this loopback publish.
|
|
35667
35631
|
INSTANCE_TOKEN: ${DEV_INSTANCE_TOKEN}
|
|
35668
|
-
|
|
35669
|
-
|
|
35670
|
-
# Shared across api + subgraph-processor so the secret the api encrypts
|
|
35671
|
-
# (e.g. a webhook's signing secret) can be decrypted by the emitter.
|
|
35672
|
-
# OSS auto-generates a per-process key when unset — that splits them.
|
|
35673
|
-
# Local-dev fixed value; not a production secret.
|
|
35632
|
+
# Fixed so the secret the api encrypts (e.g. a webhook's signing secret)
|
|
35633
|
+
# can be decrypted by the emitter across restarts. Not a production secret.
|
|
35674
35634
|
SECONDLAYER_SECRETS_KEY: ${DEV_SECRETS_KEY}
|
|
35675
|
-
|
|
35676
|
-
|
|
35677
|
-
|
|
35678
|
-
|
|
35679
|
-
|
|
35680
|
-
|
|
35681
|
-
|
|
35682
|
-
|
|
35683
|
-
condition: service_healthy
|
|
35684
|
-
healthcheck:
|
|
35685
|
-
test: ["CMD", "curl", "-f", "http://localhost:3800/health"]
|
|
35686
|
-
interval: 10s
|
|
35687
|
-
timeout: 3s
|
|
35688
|
-
start_period: 10s
|
|
35689
|
-
retries: 5
|
|
35690
|
-
restart: unless-stopped
|
|
35691
|
-
|
|
35692
|
-
indexer:
|
|
35693
|
-
image: ${indexerImage}
|
|
35694
|
-
environment:
|
|
35695
|
-
DATABASE_URL: ${dbUrl}
|
|
35696
|
-
PORT: 3700
|
|
35697
|
-
NODE_ENV: production
|
|
35698
|
-
# Keep every network key aligned: the indexer writes index_progress under
|
|
35699
|
-
# STACKS_NETWORK, the subgraph processor reads it under NETWORK. If they
|
|
35700
|
-
# differ, catch-up finds no progress row and subgraphs never advance.
|
|
35701
|
-
NETWORKS: testnet
|
|
35702
|
-
STACKS_NETWORK: testnet
|
|
35703
|
-
NETWORK: testnet
|
|
35635
|
+
# Signed deliveries, so receivers can test verification. Publicly known.
|
|
35636
|
+
SECONDLAYER_WEBHOOK_SIGNING_PRIVATE_KEY: "${DEV_WEBHOOK_SIGNING_KEY}"
|
|
35637
|
+
# The emitter blocks webhook delivery to private/loopback IPs by default.
|
|
35638
|
+
# On a local devnet you deliver to your own localhost receiver, so allow it.
|
|
35639
|
+
SECONDLAYER_ALLOW_PRIVATE_EGRESS: "true"
|
|
35640
|
+
# An OSS indexer with no index_progress spools observer blocks until an
|
|
35641
|
+
# archive import finishes. A devnet has no archive, so ingest live.
|
|
35642
|
+
INGEST_MODE: live
|
|
35704
35643
|
# Fed by the devnet node's event observer — never reach out to Hiro mainnet.
|
|
35705
35644
|
AUTO_BACKFILL_ENABLED: "false"
|
|
35706
35645
|
TIP_FOLLOWER_ENABLED: "false"
|
|
35707
|
-
|
|
35708
|
-
|
|
35709
|
-
|
|
35710
|
-
|
|
35646
|
+
# clarinet publishes the devnet node RPC on the host's 20443.
|
|
35647
|
+
STACKS_NODE_RPC_URL: http://host.docker.internal:20443
|
|
35648
|
+
STREAMS_API_URL: http://127.0.0.1:3800
|
|
35649
|
+
SUBGRAPH_SOURCE: streams-index
|
|
35650
|
+
SUBGRAPH_INDEX_API_URL: http://127.0.0.1:3800
|
|
35651
|
+
NODE_ENV: production
|
|
35652
|
+
# The api is loopback-only; the indexer is deliberately published on every
|
|
35653
|
+
# interface: the devnet's stacks-node runs in its own container and POSTs
|
|
35654
|
+
# events to host.docker.internal:3700, which resolves to the host gateway
|
|
35655
|
+
# address, not 127.0.0.1. A loopback publish would drop every block.
|
|
35711
35656
|
ports:
|
|
35657
|
+
- "${apiPublish}:3800"
|
|
35712
35658
|
- "${indexerPort}:3700"
|
|
35713
35659
|
extra_hosts:
|
|
35714
35660
|
- "host.docker.internal:host-gateway"
|
|
35661
|
+
volumes:
|
|
35662
|
+
- subgraphs_data:/data/subgraphs
|
|
35715
35663
|
depends_on:
|
|
35716
|
-
migrate:
|
|
35717
|
-
condition: service_completed_successfully
|
|
35718
35664
|
postgres:
|
|
35719
35665
|
condition: service_healthy
|
|
35720
35666
|
healthcheck:
|
|
35721
|
-
test: ["CMD", "curl", "-f", "http://localhost:
|
|
35667
|
+
test: ["CMD", "curl", "-f", "http://localhost:3800/health"]
|
|
35722
35668
|
interval: 10s
|
|
35723
35669
|
timeout: 3s
|
|
35724
|
-
start_period:
|
|
35670
|
+
start_period: 40s
|
|
35725
35671
|
retries: 5
|
|
35726
35672
|
restart: unless-stopped
|
|
35727
35673
|
|
|
35728
|
-
subgraph-processor:
|
|
35729
|
-
image: ${apiImage}
|
|
35730
|
-
command: ["bun", "run", "packages/subgraphs/src/service.ts"]
|
|
35731
|
-
environment:
|
|
35732
|
-
DATABASE_URL: ${dbUrl}
|
|
35733
|
-
NODE_ENV: production
|
|
35734
|
-
DATA_DIR: /data
|
|
35735
|
-
# Must match the indexer's network key (see indexer note) — catch-up reads
|
|
35736
|
-
# index_progress under NETWORK.
|
|
35737
|
-
NETWORK: testnet
|
|
35738
|
-
STACKS_NETWORK: testnet
|
|
35739
|
-
# The emitter blocks webhook delivery to private/loopback IPs by default.
|
|
35740
|
-
# On a local devnet you deliver to your own localhost receiver, so allow it.
|
|
35741
|
-
SECONDLAYER_ALLOW_PRIVATE_EGRESS: "true"
|
|
35742
|
-
# Must match the api's key so the emitter can decrypt signing secrets.
|
|
35743
|
-
SECONDLAYER_SECRETS_KEY: ${DEV_SECRETS_KEY}
|
|
35744
|
-
volumes:
|
|
35745
|
-
- subgraphs_data:/data/subgraphs
|
|
35746
|
-
depends_on:
|
|
35747
|
-
migrate:
|
|
35748
|
-
condition: service_completed_successfully
|
|
35749
|
-
postgres:
|
|
35750
|
-
condition: service_healthy
|
|
35751
|
-
healthcheck:
|
|
35752
|
-
disable: true
|
|
35753
|
-
restart: unless-stopped
|
|
35754
|
-
|
|
35755
35674
|
volumes:
|
|
35756
35675
|
postgres_data:
|
|
35757
35676
|
subgraphs_data:
|
|
@@ -35910,7 +35829,7 @@ is what makes minting possible without Bitcoin.`).action(async (opts) => {
|
|
|
35910
35829
|
const txid = await client.callContract({
|
|
35911
35830
|
contract,
|
|
35912
35831
|
functionName: "complete-deposit-wrapper",
|
|
35913
|
-
|
|
35832
|
+
args: [
|
|
35914
35833
|
Cl.bufferFromHex(depositTxid),
|
|
35915
35834
|
Cl.uint(0),
|
|
35916
35835
|
Cl.uint(amount),
|
|
@@ -35966,13 +35885,7 @@ function dockerCompose(composePath, args) {
|
|
|
35966
35885
|
}
|
|
35967
35886
|
var API_URL = (process.env.SECONDLAYER_API_URL || LOCAL_API_URL).replace(/\/+$/, "");
|
|
35968
35887
|
var INDEXER_URL = process.env.INDEXER_URL ?? "http://localhost:3700";
|
|
35969
|
-
var SERVICES = [
|
|
35970
|
-
"indexer",
|
|
35971
|
-
"api",
|
|
35972
|
-
"subgraph-processor",
|
|
35973
|
-
"postgres",
|
|
35974
|
-
"migrate"
|
|
35975
|
-
];
|
|
35888
|
+
var SERVICES = ["secondlayer", "postgres"];
|
|
35976
35889
|
function registerDevnetCommand(program) {
|
|
35977
35890
|
const devnet = program.command("devnet").description("Run Secondlayer services against a local Clarinet devnet");
|
|
35978
35891
|
registerFaucetCommand(devnet);
|
|
@@ -35985,7 +35898,7 @@ function registerDevnetCommand(program) {
|
|
|
35985
35898
|
devnet.command("status").description("Snapshot of the local stack: ingest, subgraphs, and recent activity").option("-w, --watch", "Refresh every 2s until Ctrl-C").option("--limit <n>", "Recent activity rows to show", "12").action(async (options) => {
|
|
35986
35899
|
await status(options);
|
|
35987
35900
|
});
|
|
35988
|
-
devnet.command("logs [service]").description("Tail stack logs — all services, or one of:
|
|
35901
|
+
devnet.command("logs [service]").description("Tail stack logs — all services, or one of: secondlayer, postgres").option("--project <dir>", "Clarinet project directory").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Lines to show from the end of each log").action(async (service, options) => {
|
|
35989
35902
|
await logs(service, options);
|
|
35990
35903
|
});
|
|
35991
35904
|
}
|
|
@@ -36029,6 +35942,11 @@ Skipped docker. Start it with:
|
|
|
36029
35942
|
}
|
|
36030
35943
|
ensureDocker();
|
|
36031
35944
|
console.log(dim(`
|
|
35945
|
+
Pulling latest images…`));
|
|
35946
|
+
if (dockerCompose(composePath, ["pull"]) !== 0) {
|
|
35947
|
+
console.log(yellow("couldn't pull the latest images — starting with what's cached"));
|
|
35948
|
+
}
|
|
35949
|
+
console.log(dim(`
|
|
36032
35950
|
Starting Secondlayer stack (docker compose up -d)…`));
|
|
36033
35951
|
if (dockerCompose(composePath, ["up", "-d"]) !== 0) {
|
|
36034
35952
|
error("docker compose up failed — see output above.");
|
|
@@ -36105,7 +36023,7 @@ var SYS_COLS = new Set([
|
|
|
36105
36023
|
"tx_id"
|
|
36106
36024
|
]);
|
|
36107
36025
|
function shortVal(v) {
|
|
36108
|
-
const s = String(v);
|
|
36026
|
+
const s = typeof v === "object" && v !== null ? JSON.stringify(v) : String(v);
|
|
36109
36027
|
return s.length > 18 ? `${s.slice(0, 6)}…${s.slice(-4)}` : s;
|
|
36110
36028
|
}
|
|
36111
36029
|
async function renderStatus(limit) {
|
|
@@ -36912,7 +36830,7 @@ init_api_url();
|
|
|
36912
36830
|
init_http();
|
|
36913
36831
|
import { hostname } from "node:os";
|
|
36914
36832
|
import { createInterface } from "node:readline";
|
|
36915
|
-
import { confirm as
|
|
36833
|
+
import { confirm as confirm2, input } from "@inquirer/prompts";
|
|
36916
36834
|
|
|
36917
36835
|
// src/lib/open-browser.ts
|
|
36918
36836
|
import { spawn as spawn3 } from "node:child_process";
|
|
@@ -36995,7 +36913,7 @@ async function shouldContinueLogin(target, options, deps = defaultLoginCheckDeps
|
|
|
36995
36913
|
return false;
|
|
36996
36914
|
}
|
|
36997
36915
|
try {
|
|
36998
|
-
const proceed = await
|
|
36916
|
+
const proceed = await confirm2({
|
|
36999
36917
|
message: "Log in as a different user?",
|
|
37000
36918
|
default: false
|
|
37001
36919
|
});
|
|
@@ -37742,8 +37660,7 @@ program.hook("preAction", (thisCommand) => {
|
|
|
37742
37660
|
program.addHelpText("after", `
|
|
37743
37661
|
Quickstart:
|
|
37744
37662
|
$ secondlayer subgraphs create my-watcher --from-contract SP....my-contract
|
|
37745
|
-
$
|
|
37746
|
-
$ secondlayer subgraphs deploy subgraphs/my-watcher.ts # or --allow-uncommitted
|
|
37663
|
+
$ secondlayer subgraphs deploy subgraphs/my-watcher.ts
|
|
37747
37664
|
|
|
37748
37665
|
Self-host, from docker/oss in a checkout:
|
|
37749
37666
|
$ secondlayer init --network mainnet
|
|
@@ -37781,5 +37698,5 @@ registerCreditsCommand(program);
|
|
|
37781
37698
|
registerArchiveCommand(program);
|
|
37782
37699
|
program.parse();
|
|
37783
37700
|
|
|
37784
|
-
//# debugId=
|
|
37701
|
+
//# debugId=C1922C0758B86D1064756E2164756E21
|
|
37785
37702
|
//# sourceMappingURL=cli.js.map
|