@secondlayer/cli 1.6.0 → 1.6.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/dist/cli.js +151 -141
- package/dist/cli.js.map +21 -21
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2229,8 +2229,8 @@ function migrateConfig(raw) {
|
|
|
2229
2229
|
if (typeof old.dataDir === "string") {
|
|
2230
2230
|
migrated.dataDir = old.dataDir;
|
|
2231
2231
|
}
|
|
2232
|
-
if (typeof old.
|
|
2233
|
-
migrated.
|
|
2232
|
+
if (typeof old.defaultEndpointUrl === "string") {
|
|
2233
|
+
migrated.defaultEndpointUrl = old.defaultEndpointUrl;
|
|
2234
2234
|
}
|
|
2235
2235
|
if (typeof old.nodeInstallPath === "string" || typeof old.nodeNetwork === "string") {
|
|
2236
2236
|
migrated.node = {
|
|
@@ -2270,8 +2270,8 @@ async function loadConfig() {
|
|
|
2270
2270
|
}
|
|
2271
2271
|
}
|
|
2272
2272
|
config = applyEnvOverrides(config);
|
|
2273
|
-
if (!config.
|
|
2274
|
-
config.
|
|
2273
|
+
if (!config.defaultEndpointUrl && config.network === "local") {
|
|
2274
|
+
config.defaultEndpointUrl = LOCAL_ENDPOINT_URL;
|
|
2275
2275
|
}
|
|
2276
2276
|
return config;
|
|
2277
2277
|
}
|
|
@@ -2301,12 +2301,15 @@ function applyEnvOverrides(config) {
|
|
|
2301
2301
|
result.ports = { ...result.ports, indexer: port };
|
|
2302
2302
|
}
|
|
2303
2303
|
}
|
|
2304
|
-
if (process.env.
|
|
2305
|
-
const port = parseInt(process.env.
|
|
2304
|
+
if (process.env.SL_RECEIVER_PORT) {
|
|
2305
|
+
const port = parseInt(process.env.SL_RECEIVER_PORT, 10);
|
|
2306
2306
|
if (!isNaN(port) && port > 0 && port <= 65535) {
|
|
2307
|
-
result.ports = { ...result.ports,
|
|
2307
|
+
result.ports = { ...result.ports, receiver: port };
|
|
2308
2308
|
}
|
|
2309
2309
|
}
|
|
2310
|
+
if (process.env.STACKS_NODE_RPC_URL) {
|
|
2311
|
+
result.nodeRpcUrl = process.env.STACKS_NODE_RPC_URL;
|
|
2312
|
+
}
|
|
2310
2313
|
if (process.env.DATABASE_URL) {
|
|
2311
2314
|
result.database = { type: "external", url: process.env.DATABASE_URL };
|
|
2312
2315
|
}
|
|
@@ -2395,13 +2398,13 @@ function isDefaultValue(config, key) {
|
|
|
2395
2398
|
const defaultValue = getConfigValue(DEFAULT_CONFIG, key);
|
|
2396
2399
|
return JSON.stringify(currentValue) === JSON.stringify(defaultValue);
|
|
2397
2400
|
}
|
|
2398
|
-
var PortsSchema, NodeSchema, DatabaseSchema, NetworkSchema, API_URLS, ConfigSchema, CONFIG_DIR, CONFIG_PATH,
|
|
2401
|
+
var PortsSchema, NodeSchema, DatabaseSchema, NetworkSchema, API_URLS, ConfigSchema, CONFIG_DIR, CONFIG_PATH, LOCAL_ENDPOINT_URL = "http://localhost:3900/receiver", DEFAULT_CONFIG;
|
|
2399
2402
|
var init_config = __esm(() => {
|
|
2400
2403
|
init_fs();
|
|
2401
2404
|
PortsSchema = z.object({
|
|
2402
2405
|
api: z.number().int().min(1).max(65535).default(3800),
|
|
2403
2406
|
indexer: z.number().int().min(1).max(65535).default(3700),
|
|
2404
|
-
|
|
2407
|
+
receiver: z.number().int().min(1).max(65535).default(3900)
|
|
2405
2408
|
});
|
|
2406
2409
|
NodeSchema = z.object({
|
|
2407
2410
|
installPath: z.string().min(1),
|
|
@@ -2421,8 +2424,9 @@ var init_config = __esm(() => {
|
|
|
2421
2424
|
network: NetworkSchema.default("mainnet"),
|
|
2422
2425
|
apiUrl: z.string().url().optional(),
|
|
2423
2426
|
apiKey: z.string().optional(),
|
|
2427
|
+
nodeRpcUrl: z.string().url().optional(),
|
|
2424
2428
|
dataDir: z.string().default("~/.secondlayer/data"),
|
|
2425
|
-
|
|
2429
|
+
defaultEndpointUrl: z.string().url().optional(),
|
|
2426
2430
|
node: NodeSchema.optional(),
|
|
2427
2431
|
ports: PortsSchema.default({}),
|
|
2428
2432
|
database: DatabaseSchema.default({})
|
|
@@ -2432,7 +2436,7 @@ var init_config = __esm(() => {
|
|
|
2432
2436
|
DEFAULT_CONFIG = {
|
|
2433
2437
|
network: "mainnet",
|
|
2434
2438
|
dataDir: "~/.secondlayer/data",
|
|
2435
|
-
ports: { api: 3800, indexer: 3700,
|
|
2439
|
+
ports: { api: 3800, indexer: 3700, receiver: 3900 },
|
|
2436
2440
|
database: { type: "docker" }
|
|
2437
2441
|
};
|
|
2438
2442
|
});
|
|
@@ -12432,13 +12436,16 @@ class StacksApiClient {
|
|
|
12432
12436
|
static hasWarnedAboutApiKey = false;
|
|
12433
12437
|
baseUrl;
|
|
12434
12438
|
headers;
|
|
12439
|
+
usingHiro;
|
|
12435
12440
|
constructor(network = "mainnet", apiKey, apiUrl) {
|
|
12436
|
-
|
|
12441
|
+
const nodeRpcUrl = process.env.STACKS_NODE_RPC_URL;
|
|
12442
|
+
this.baseUrl = apiUrl || nodeRpcUrl || HIRO_URLS[network];
|
|
12443
|
+
this.usingHiro = !apiUrl && !nodeRpcUrl;
|
|
12437
12444
|
this.headers = apiKey ? { "x-api-key": apiKey } : {};
|
|
12438
|
-
if (!apiKey && !StacksApiClient.hasWarnedAboutApiKey) {
|
|
12439
|
-
console.warn(`⚠️
|
|
12440
|
-
` + ` Set
|
|
12441
|
-
` + " Get a free key at: https://platform.hiro.so/");
|
|
12445
|
+
if (this.usingHiro && !apiKey && !StacksApiClient.hasWarnedAboutApiKey) {
|
|
12446
|
+
console.warn(`⚠️ Using Hiro public API (no STACKS_NODE_RPC_URL set). You may be rate-limited.
|
|
12447
|
+
` + ` Set STACKS_NODE_RPC_URL to use your own node, or set HIRO_API_KEY for Hiro.
|
|
12448
|
+
` + " Get a free Hiro key at: https://platform.hiro.so/");
|
|
12442
12449
|
StacksApiClient.hasWarnedAboutApiKey = true;
|
|
12443
12450
|
}
|
|
12444
12451
|
}
|
|
@@ -12471,7 +12478,7 @@ class StacksApiClient {
|
|
|
12471
12478
|
return data.source;
|
|
12472
12479
|
}
|
|
12473
12480
|
}
|
|
12474
|
-
var gotWithRetry,
|
|
12481
|
+
var gotWithRetry, HIRO_URLS;
|
|
12475
12482
|
var init_api = __esm(() => {
|
|
12476
12483
|
init_source3();
|
|
12477
12484
|
gotWithRetry = source_default2.extend({
|
|
@@ -12483,7 +12490,7 @@ var init_api = __esm(() => {
|
|
|
12483
12490
|
calculateDelay: ({ attemptCount }) => attemptCount * 1000
|
|
12484
12491
|
}
|
|
12485
12492
|
});
|
|
12486
|
-
|
|
12493
|
+
HIRO_URLS = {
|
|
12487
12494
|
mainnet: "https://api.hiro.so",
|
|
12488
12495
|
testnet: "https://api.testnet.hiro.so",
|
|
12489
12496
|
devnet: "http://localhost:3999"
|
|
@@ -13189,9 +13196,9 @@ var init_api2 = __esm(() => {
|
|
|
13189
13196
|
init_manager();
|
|
13190
13197
|
});
|
|
13191
13198
|
|
|
13192
|
-
// src/services/
|
|
13199
|
+
// src/services/receiver-server.ts
|
|
13193
13200
|
import { verifySignatureHeader } from "@secondlayer/shared/crypto";
|
|
13194
|
-
function
|
|
13201
|
+
function startReceiverServer(options2 = {}) {
|
|
13195
13202
|
const port = options2.port ?? 3900;
|
|
13196
13203
|
const responseCode = options2.responseCode ?? 200;
|
|
13197
13204
|
server = Bun.serve({
|
|
@@ -13230,27 +13237,27 @@ function startWebhookServer(options2 = {}) {
|
|
|
13230
13237
|
body,
|
|
13231
13238
|
signatureValid
|
|
13232
13239
|
};
|
|
13233
|
-
if (options2.
|
|
13234
|
-
options2.
|
|
13240
|
+
if (options2.onDelivery) {
|
|
13241
|
+
options2.onDelivery(event);
|
|
13235
13242
|
} else {
|
|
13236
|
-
|
|
13243
|
+
logDelivery(event);
|
|
13237
13244
|
}
|
|
13238
13245
|
return new Response("OK", { status: responseCode });
|
|
13239
13246
|
}
|
|
13240
13247
|
});
|
|
13241
13248
|
return port;
|
|
13242
13249
|
}
|
|
13243
|
-
function
|
|
13250
|
+
function stopReceiverServer() {
|
|
13244
13251
|
if (server) {
|
|
13245
13252
|
server.stop();
|
|
13246
13253
|
server = null;
|
|
13247
13254
|
}
|
|
13248
13255
|
}
|
|
13249
|
-
function
|
|
13256
|
+
function logDelivery(event) {
|
|
13250
13257
|
const time = event.timestamp.toISOString();
|
|
13251
13258
|
console.log("");
|
|
13252
13259
|
console.log(blue("━".repeat(60)));
|
|
13253
|
-
console.log(green("⚡
|
|
13260
|
+
console.log(green("⚡ Delivery received"));
|
|
13254
13261
|
console.log(dim(` ${time}`));
|
|
13255
13262
|
console.log(dim(` ${event.method} ${event.path}`));
|
|
13256
13263
|
if (event.signatureValid === true) {
|
|
@@ -13272,7 +13279,7 @@ function logWebhook(event) {
|
|
|
13272
13279
|
console.log(blue("━".repeat(60)));
|
|
13273
13280
|
}
|
|
13274
13281
|
var server = null;
|
|
13275
|
-
var
|
|
13282
|
+
var init_receiver_server = __esm(() => {
|
|
13276
13283
|
init_output();
|
|
13277
13284
|
});
|
|
13278
13285
|
|
|
@@ -13300,7 +13307,7 @@ var init_services = __esm(() => {
|
|
|
13300
13307
|
init_indexer();
|
|
13301
13308
|
init_worker();
|
|
13302
13309
|
init_api2();
|
|
13303
|
-
|
|
13310
|
+
init_receiver_server();
|
|
13304
13311
|
init_subgraph_processor();
|
|
13305
13312
|
});
|
|
13306
13313
|
|
|
@@ -13344,7 +13351,7 @@ async function runBackground(options2) {
|
|
|
13344
13351
|
const dataDir = getDataDir(config);
|
|
13345
13352
|
const indexerPort = options2.stacksNode ? 3701 : parseInt(options2.indexerPort) || config.ports.indexer;
|
|
13346
13353
|
const apiPort = parseInt(options2.apiPort) || config.ports.api;
|
|
13347
|
-
const
|
|
13354
|
+
const receiverPort = parseInt(options2.receiverPort) || config.ports.receiver;
|
|
13348
13355
|
if (options2.stacksNode && config.node) {
|
|
13349
13356
|
const validation = await validateNetworkConsistency(config);
|
|
13350
13357
|
if (!validation.valid) {
|
|
@@ -13454,24 +13461,24 @@ async function runBackground(options2) {
|
|
|
13454
13461
|
};
|
|
13455
13462
|
console.log(green(" ✓ Subgraph processor"), dim("processing subgraphs"));
|
|
13456
13463
|
}
|
|
13457
|
-
if (options2.
|
|
13458
|
-
const
|
|
13459
|
-
const
|
|
13460
|
-
const
|
|
13464
|
+
if (options2.receiver) {
|
|
13465
|
+
const receiverLogFile = getLogFile("receiver");
|
|
13466
|
+
const receiverArgs = ["bun", "run", resolve6(packagesDir, "packages/cli/src/services/receiver-standalone.ts")];
|
|
13467
|
+
const receiverEnv = { ...process.env, PORT: String(receiverPort) };
|
|
13461
13468
|
if (options2.secret)
|
|
13462
|
-
|
|
13463
|
-
const
|
|
13464
|
-
env:
|
|
13465
|
-
stdout: Bun.file(
|
|
13466
|
-
stderr: Bun.file(
|
|
13469
|
+
receiverEnv.SIGNING_SECRET = options2.secret;
|
|
13470
|
+
const receiverProc = Bun.spawn(receiverArgs, {
|
|
13471
|
+
env: receiverEnv,
|
|
13472
|
+
stdout: Bun.file(receiverLogFile),
|
|
13473
|
+
stderr: Bun.file(receiverLogFile)
|
|
13467
13474
|
});
|
|
13468
|
-
state.services.
|
|
13469
|
-
pid:
|
|
13470
|
-
port:
|
|
13475
|
+
state.services.receiver = {
|
|
13476
|
+
pid: receiverProc.pid,
|
|
13477
|
+
port: receiverPort,
|
|
13471
13478
|
startedAt: new Date().toISOString(),
|
|
13472
|
-
logFile:
|
|
13479
|
+
logFile: receiverLogFile
|
|
13473
13480
|
};
|
|
13474
|
-
console.log(green(" ✓
|
|
13481
|
+
console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
|
|
13475
13482
|
}
|
|
13476
13483
|
await Bun.sleep(500);
|
|
13477
13484
|
for (const [name, service] of Object.entries(state.services)) {
|
|
@@ -13481,7 +13488,7 @@ async function runBackground(options2) {
|
|
|
13481
13488
|
}
|
|
13482
13489
|
await saveDevState(state);
|
|
13483
13490
|
console.log("");
|
|
13484
|
-
printUrls(indexerPort, apiPort,
|
|
13491
|
+
printUrls(indexerPort, apiPort, receiverPort, options2.receiver);
|
|
13485
13492
|
console.log("");
|
|
13486
13493
|
success("Dev environment started in background");
|
|
13487
13494
|
console.log("");
|
|
@@ -13519,14 +13526,14 @@ async function runForeground(options2) {
|
|
|
13519
13526
|
const dataDir = getDataDir(config);
|
|
13520
13527
|
const indexerPort = options2.stacksNode ? 3701 : parseInt(options2.indexerPort) || config.ports.indexer;
|
|
13521
13528
|
const apiPort = parseInt(options2.apiPort) || config.ports.api;
|
|
13522
|
-
const
|
|
13529
|
+
const receiverPort = parseInt(options2.receiverPort) || config.ports.receiver;
|
|
13523
13530
|
let devPostgresStarted = false;
|
|
13524
13531
|
const shutdown = async () => {
|
|
13525
13532
|
console.log(`
|
|
13526
13533
|
`);
|
|
13527
13534
|
info("Shutting down services...");
|
|
13528
|
-
if (options2.
|
|
13529
|
-
|
|
13535
|
+
if (options2.receiver) {
|
|
13536
|
+
stopReceiverServer();
|
|
13530
13537
|
}
|
|
13531
13538
|
await serviceManager.stopAll();
|
|
13532
13539
|
if (devPostgresStarted) {
|
|
@@ -13573,9 +13580,9 @@ async function runForeground(options2) {
|
|
|
13573
13580
|
console.log("");
|
|
13574
13581
|
}
|
|
13575
13582
|
process.env.DEV_MODE = "true";
|
|
13576
|
-
if (options2.
|
|
13577
|
-
|
|
13578
|
-
console.log(green(" ✓
|
|
13583
|
+
if (options2.receiver) {
|
|
13584
|
+
startReceiverServer({ port: receiverPort, secret: options2.secret });
|
|
13585
|
+
console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
|
|
13579
13586
|
}
|
|
13580
13587
|
await startApi({ port: apiPort, onLog: (line) => logService("api", line) });
|
|
13581
13588
|
console.log(green(" ✓ API"), dim(`http://localhost:${apiPort}`));
|
|
@@ -13588,7 +13595,7 @@ async function runForeground(options2) {
|
|
|
13588
13595
|
await startSubgraphProcessor({ onLog: (line) => logService("subgraphs", line) });
|
|
13589
13596
|
console.log(green(" ✓ Subgraph processor"), dim("processing subgraphs"));
|
|
13590
13597
|
console.log("");
|
|
13591
|
-
printUrls(indexerPort, apiPort,
|
|
13598
|
+
printUrls(indexerPort, apiPort, receiverPort, options2.receiver);
|
|
13592
13599
|
console.log("");
|
|
13593
13600
|
info("Press Ctrl+C to stop all services");
|
|
13594
13601
|
console.log("");
|
|
@@ -13596,8 +13603,8 @@ async function runForeground(options2) {
|
|
|
13596
13603
|
} catch (err) {
|
|
13597
13604
|
error(`Failed to start services: ${err}`);
|
|
13598
13605
|
await serviceManager.stopAll();
|
|
13599
|
-
if (options2.
|
|
13600
|
-
|
|
13606
|
+
if (options2.receiver) {
|
|
13607
|
+
stopReceiverServer();
|
|
13601
13608
|
}
|
|
13602
13609
|
process.exit(1);
|
|
13603
13610
|
}
|
|
@@ -13628,10 +13635,10 @@ async function showLogs(options2) {
|
|
|
13628
13635
|
await showStaticLogs(serviceEntries, lines, verbose);
|
|
13629
13636
|
}
|
|
13630
13637
|
}
|
|
13631
|
-
function
|
|
13638
|
+
function formatDeliverySummary(jsonStr) {
|
|
13632
13639
|
try {
|
|
13633
13640
|
const data = JSON.parse(jsonStr);
|
|
13634
|
-
if (data.type !== "
|
|
13641
|
+
if (data.type !== "delivery" || !data.body)
|
|
13635
13642
|
return null;
|
|
13636
13643
|
const { body, method, path, timestamp } = data;
|
|
13637
13644
|
const streamName = body.streamName ?? body.streamId?.slice(0, 8) ?? "unknown";
|
|
@@ -13661,8 +13668,8 @@ function formatLogLine2(service, line, verbose) {
|
|
|
13661
13668
|
return `${prefix} ${dimTimestamp} ${dim(level + ":")} ${dim(message)}`;
|
|
13662
13669
|
}
|
|
13663
13670
|
}
|
|
13664
|
-
if (service === "
|
|
13665
|
-
const summary =
|
|
13671
|
+
if (service === "receiver" && !verbose) {
|
|
13672
|
+
const summary = formatDeliverySummary(line);
|
|
13666
13673
|
if (summary)
|
|
13667
13674
|
return `${prefix} ${summary}`;
|
|
13668
13675
|
}
|
|
@@ -13838,21 +13845,21 @@ async function restartDev() {
|
|
|
13838
13845
|
};
|
|
13839
13846
|
console.log(green(" ✓ Worker"), dim("processing jobs"));
|
|
13840
13847
|
}
|
|
13841
|
-
if (state.services.
|
|
13842
|
-
const
|
|
13843
|
-
const
|
|
13844
|
-
const
|
|
13845
|
-
env: { ...process.env, PORT: String(
|
|
13846
|
-
stdout: Bun.file(
|
|
13847
|
-
stderr: Bun.file(
|
|
13848
|
+
if (state.services.receiver) {
|
|
13849
|
+
const receiverPort = config.ports.receiver;
|
|
13850
|
+
const receiverLogFile = getLogFile("receiver");
|
|
13851
|
+
const receiverProc = Bun.spawn(["bun", "run", resolve6(packagesDir, "packages/cli/src/services/receiver-standalone.ts")], {
|
|
13852
|
+
env: { ...process.env, PORT: String(receiverPort) },
|
|
13853
|
+
stdout: Bun.file(receiverLogFile),
|
|
13854
|
+
stderr: Bun.file(receiverLogFile)
|
|
13848
13855
|
});
|
|
13849
|
-
newState.services.
|
|
13850
|
-
pid:
|
|
13851
|
-
port:
|
|
13856
|
+
newState.services.receiver = {
|
|
13857
|
+
pid: receiverProc.pid,
|
|
13858
|
+
port: receiverPort,
|
|
13852
13859
|
startedAt: new Date().toISOString(),
|
|
13853
|
-
logFile:
|
|
13860
|
+
logFile: receiverLogFile
|
|
13854
13861
|
};
|
|
13855
|
-
console.log(green(" ✓
|
|
13862
|
+
console.log(green(" ✓ Receiver server"), dim(`http://localhost:${receiverPort}`));
|
|
13856
13863
|
}
|
|
13857
13864
|
if (state.services.subgraphs) {
|
|
13858
13865
|
const subgraphsLogFile = getLogFile("subgraphs");
|
|
@@ -13928,7 +13935,7 @@ function printBanner2() {
|
|
|
13928
13935
|
console.log(dim(" Starting services..."));
|
|
13929
13936
|
console.log("");
|
|
13930
13937
|
}
|
|
13931
|
-
function printUrls(indexerPort, apiPort,
|
|
13938
|
+
function printUrls(indexerPort, apiPort, receiverPort, receiverEnabled) {
|
|
13932
13939
|
console.log(dim(" ─────────────────────────────────────────"));
|
|
13933
13940
|
console.log("");
|
|
13934
13941
|
console.log(" " + blue("API:"));
|
|
@@ -13939,9 +13946,9 @@ function printUrls(indexerPort, apiPort, webhookPort, webhookEnabled) {
|
|
|
13939
13946
|
console.log(` Health check: curl http://localhost:${indexerPort}/health`);
|
|
13940
13947
|
console.log(` Send block: curl -X POST http://localhost:${indexerPort}/new_block -d @block.json`);
|
|
13941
13948
|
console.log("");
|
|
13942
|
-
if (
|
|
13943
|
-
console.log(" " + blue("Test
|
|
13944
|
-
console.log(` Receives
|
|
13949
|
+
if (receiverEnabled) {
|
|
13950
|
+
console.log(" " + blue("Test Receiver:"));
|
|
13951
|
+
console.log(` Receives deliveries at http://localhost:${receiverPort}/`);
|
|
13945
13952
|
console.log(` Use this URL when creating streams for testing`);
|
|
13946
13953
|
console.log("");
|
|
13947
13954
|
}
|
|
@@ -14018,7 +14025,7 @@ var init_dev_impl = __esm(() => {
|
|
|
14018
14025
|
indexer: cyan,
|
|
14019
14026
|
worker: yellow,
|
|
14020
14027
|
subgraphs: magenta,
|
|
14021
|
-
|
|
14028
|
+
receiver: green
|
|
14022
14029
|
};
|
|
14023
14030
|
});
|
|
14024
14031
|
|
|
@@ -32268,7 +32275,7 @@ function deriveContractName(filePath) {
|
|
|
32268
32275
|
const basename = path10.basename(filePath, ".clar");
|
|
32269
32276
|
return basename.replace(/[-_](.)/g, (_2, char) => char.toUpperCase()).replace(/^(.)/, (_2, char) => char.toLowerCase()).replace(/^\d/, "_$&");
|
|
32270
32277
|
}
|
|
32271
|
-
async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddress) {
|
|
32278
|
+
async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddress, nodeRpcUrl) {
|
|
32272
32279
|
const contracts = [];
|
|
32273
32280
|
const deployer = defaultAddress || DEFAULT_DEVNET_ADDRESS;
|
|
32274
32281
|
if (parsedInputs.files.length > 0 && !defaultAddress) {
|
|
@@ -32290,7 +32297,7 @@ async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddre
|
|
|
32290
32297
|
const { address, contractName } = parseContractId(contractId);
|
|
32291
32298
|
const network = inferNetwork(address) ?? "mainnet";
|
|
32292
32299
|
try {
|
|
32293
|
-
const apiClient = new StacksApiClient(network, apiKey);
|
|
32300
|
+
const apiClient = new StacksApiClient(network, apiKey, nodeRpcUrl);
|
|
32294
32301
|
const contractInfo = await apiClient.getContractInfo(contractId);
|
|
32295
32302
|
const abi = parseApiResponse(contractInfo);
|
|
32296
32303
|
const name = toCamelCase7(contractName);
|
|
@@ -32333,7 +32340,8 @@ No .clar files or contract addresses matched the provided inputs`));
|
|
|
32333
32340
|
process.exit(1);
|
|
32334
32341
|
}
|
|
32335
32342
|
const apiKey = options3.apiKey || process.env.HIRO_API_KEY;
|
|
32336
|
-
|
|
32343
|
+
const cliConfig = await loadConfig();
|
|
32344
|
+
config = await buildConfigFromInputs(parsedInputs, options3.out, apiKey, undefined, cliConfig.nodeRpcUrl);
|
|
32337
32345
|
} else {
|
|
32338
32346
|
config = await loadConfig2(options3.config);
|
|
32339
32347
|
}
|
|
@@ -32462,6 +32470,7 @@ var import_fast_glob, DEFAULT_DEVNET_ADDRESS = "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZ
|
|
|
32462
32470
|
var init_generate = __esm(() => {
|
|
32463
32471
|
init_source4();
|
|
32464
32472
|
init_config2();
|
|
32473
|
+
init_config();
|
|
32465
32474
|
init_api();
|
|
32466
32475
|
init_clarity();
|
|
32467
32476
|
init_contract();
|
|
@@ -32538,7 +32547,7 @@ var {
|
|
|
32538
32547
|
// package.json
|
|
32539
32548
|
var package_default = {
|
|
32540
32549
|
name: "@secondlayer/cli",
|
|
32541
|
-
version: "1.6.
|
|
32550
|
+
version: "1.6.1",
|
|
32542
32551
|
description: "CLI for streams, subgraphs, and real-time blockchain indexing on Stacks",
|
|
32543
32552
|
type: "module",
|
|
32544
32553
|
bin: {
|
|
@@ -32930,7 +32939,7 @@ async function printConfigTree(cfg) {
|
|
|
32930
32939
|
console.log(blue("ports:"));
|
|
32931
32940
|
printValue(" api", cfg.ports.api, cfg.ports.api === defaults.ports.api, 2);
|
|
32932
32941
|
printValue(" indexer", cfg.ports.indexer, cfg.ports.indexer === defaults.ports.indexer, 2);
|
|
32933
|
-
printValue("
|
|
32942
|
+
printValue(" receiver", cfg.ports.receiver, cfg.ports.receiver === defaults.ports.receiver, 2);
|
|
32934
32943
|
console.log("");
|
|
32935
32944
|
console.log(blue("database:"));
|
|
32936
32945
|
printValue(" type", cfg.database.type, cfg.database.type === "docker", 2);
|
|
@@ -32976,13 +32985,13 @@ import { select as select2, input, confirm } from "@inquirer/prompts";
|
|
|
32976
32985
|
init_config();
|
|
32977
32986
|
var STREAMS_DIR = "streams";
|
|
32978
32987
|
function registerSetupCommand(program2) {
|
|
32979
|
-
program2.command("setup").description("Set up a streams project and configure settings").option("--detect-only", "Only detect existing Stacks nodes, don't initialize").option("-y, --yes", "Use defaults without prompts").option("--data-dir <path>", "Data directory path").option("--node-path <path>", "Path to Stacks node").option("--network <network>", "Network (local, testnet, or mainnet)").option("--
|
|
32988
|
+
program2.command("setup").description("Set up a streams project and configure settings").option("--detect-only", "Only detect existing Stacks nodes, don't initialize").option("-y, --yes", "Use defaults without prompts").option("--data-dir <path>", "Data directory path").option("--node-path <path>", "Path to Stacks node").option("--network <network>", "Network (local, testnet, or mainnet)").option("--endpoint-url <url>", "Default endpoint URL for new streams").action(async (options) => {
|
|
32980
32989
|
try {
|
|
32981
32990
|
if (options.detectOnly) {
|
|
32982
32991
|
await runDetection();
|
|
32983
32992
|
return;
|
|
32984
32993
|
}
|
|
32985
|
-
const hasFlags = options.yes || options.dataDir || options.nodePath || options.network || options.
|
|
32994
|
+
const hasFlags = options.yes || options.dataDir || options.nodePath || options.network || options.endpointUrl;
|
|
32986
32995
|
if (hasFlags) {
|
|
32987
32996
|
await runNonInteractive(options);
|
|
32988
32997
|
return;
|
|
@@ -33011,7 +33020,7 @@ async function runNonInteractive(options) {
|
|
|
33011
33020
|
return;
|
|
33012
33021
|
}
|
|
33013
33022
|
config.dataDir = options.dataDir || config.dataDir || "~/.secondlayer/data";
|
|
33014
|
-
config.
|
|
33023
|
+
config.defaultEndpointUrl = options.endpointUrl || config.defaultEndpointUrl;
|
|
33015
33024
|
if (options.nodePath) {
|
|
33016
33025
|
config.node = {
|
|
33017
33026
|
installPath: options.nodePath,
|
|
@@ -33055,8 +33064,8 @@ async function runWizard() {
|
|
|
33055
33064
|
if (nodeConfig) {
|
|
33056
33065
|
config.node = nodeConfig;
|
|
33057
33066
|
}
|
|
33058
|
-
const
|
|
33059
|
-
config.
|
|
33067
|
+
const endpointUrl = await promptEndpointUrl(config);
|
|
33068
|
+
config.defaultEndpointUrl = endpointUrl;
|
|
33060
33069
|
await saveConfig(config);
|
|
33061
33070
|
await Bun.$`mkdir -p ${STREAMS_DIR}`.quiet();
|
|
33062
33071
|
await Bun.write(`${STREAMS_DIR}/.gitkeep`, "");
|
|
@@ -33183,10 +33192,10 @@ async function promptNetwork() {
|
|
|
33183
33192
|
});
|
|
33184
33193
|
return network;
|
|
33185
33194
|
}
|
|
33186
|
-
async function
|
|
33187
|
-
const internalUrl = "http://localhost:3900/
|
|
33195
|
+
async function promptEndpointUrl(config) {
|
|
33196
|
+
const internalUrl = "http://localhost:3900/receiver";
|
|
33188
33197
|
const choice = await select2({
|
|
33189
|
-
message: "Default
|
|
33198
|
+
message: "Default endpoint URL for new streams?",
|
|
33190
33199
|
choices: [
|
|
33191
33200
|
{ name: `Internal test server (${internalUrl})`, value: "internal" },
|
|
33192
33201
|
{ name: "Custom URL...", value: "custom" }
|
|
@@ -33196,8 +33205,8 @@ async function promptWebhookUrl(config) {
|
|
|
33196
33205
|
return internalUrl;
|
|
33197
33206
|
}
|
|
33198
33207
|
const customUrl = await input({
|
|
33199
|
-
message: "Enter
|
|
33200
|
-
default: config.
|
|
33208
|
+
message: "Enter endpoint URL:",
|
|
33209
|
+
default: config.defaultEndpointUrl !== internalUrl ? config.defaultEndpointUrl : undefined,
|
|
33201
33210
|
validate: (value) => {
|
|
33202
33211
|
if (!value.trim())
|
|
33203
33212
|
return "URL cannot be empty";
|
|
@@ -33295,8 +33304,8 @@ function printSummary(config) {
|
|
|
33295
33304
|
console.log();
|
|
33296
33305
|
console.log(" Settings:");
|
|
33297
33306
|
console.log(` Data directory: ${config.dataDir}`);
|
|
33298
|
-
if (config.
|
|
33299
|
-
console.log(`
|
|
33307
|
+
if (config.defaultEndpointUrl) {
|
|
33308
|
+
console.log(` Endpoint URL: ${config.defaultEndpointUrl}`);
|
|
33300
33309
|
}
|
|
33301
33310
|
if (config.node) {
|
|
33302
33311
|
console.log(` Node path: ${config.node.installPath}`);
|
|
@@ -33345,10 +33354,10 @@ function printNodeInfo(node) {
|
|
|
33345
33354
|
import { join as join3 } from "node:path";
|
|
33346
33355
|
|
|
33347
33356
|
// src/templates/stream.ts
|
|
33348
|
-
function generateStreamTemplate(name,
|
|
33357
|
+
function generateStreamTemplate(name, endpointUrl) {
|
|
33349
33358
|
return {
|
|
33350
33359
|
name,
|
|
33351
|
-
|
|
33360
|
+
endpointUrl: endpointUrl || "https://example.com/endpoint",
|
|
33352
33361
|
filters: [
|
|
33353
33362
|
{
|
|
33354
33363
|
type: "contract_call",
|
|
@@ -33384,12 +33393,12 @@ function registerNewCommand(program2) {
|
|
|
33384
33393
|
if (dir) {
|
|
33385
33394
|
await ensureDir(dir);
|
|
33386
33395
|
}
|
|
33387
|
-
const template = generateStreamTemplate(name, config.
|
|
33396
|
+
const template = generateStreamTemplate(name, config.defaultEndpointUrl);
|
|
33388
33397
|
await writeTextFile(outputPath, JSON.stringify(template, null, 2) + `
|
|
33389
33398
|
`);
|
|
33390
33399
|
success(`Created ${outputPath}`);
|
|
33391
|
-
if (!config.
|
|
33392
|
-
warn("Edit the
|
|
33400
|
+
if (!config.defaultEndpointUrl) {
|
|
33401
|
+
warn("Edit the endpointUrl before registering — it must be a reachable HTTPS endpoint");
|
|
33393
33402
|
}
|
|
33394
33403
|
console.log(`
|
|
33395
33404
|
Edit the file to configure your stream, then run:`);
|
|
@@ -33452,7 +33461,7 @@ function registerGetCommand(program2) {
|
|
|
33452
33461
|
["ID", stream.id],
|
|
33453
33462
|
["Name", stream.name],
|
|
33454
33463
|
["Status", statusColor(stream.status)],
|
|
33455
|
-
["
|
|
33464
|
+
["Endpoint URL", stream.endpointUrl],
|
|
33456
33465
|
["Total Deliveries", stream.totalDeliveries.toString()],
|
|
33457
33466
|
["Failed Deliveries", stream.failedDeliveries.toString()],
|
|
33458
33467
|
["Last Triggered", stream.lastTriggeredAt || dim("never")],
|
|
@@ -33520,10 +33529,10 @@ function registerRegisterCommand(program2) {
|
|
|
33520
33529
|
console.log(formatKeyValue([
|
|
33521
33530
|
["ID", result.stream.id],
|
|
33522
33531
|
["Name", result.stream.name],
|
|
33523
|
-
["
|
|
33532
|
+
["Signing Secret", result.signingSecret]
|
|
33524
33533
|
]));
|
|
33525
33534
|
console.log(dim(`
|
|
33526
|
-
Save the
|
|
33535
|
+
Save the signing secret - it won't be shown again!`));
|
|
33527
33536
|
} catch (err) {
|
|
33528
33537
|
handleApiError(err, "register stream");
|
|
33529
33538
|
}
|
|
@@ -34019,12 +34028,12 @@ init_api_client();
|
|
|
34019
34028
|
init_output();
|
|
34020
34029
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
34021
34030
|
function registerRotateSecretCommand(program2) {
|
|
34022
|
-
program2.command("rotate-secret <id>").description("Generate a new
|
|
34031
|
+
program2.command("rotate-secret <id>").description("Generate a new signing secret for a stream").option("-y, --yes", "Skip confirmation prompt").action(async (id, options) => {
|
|
34023
34032
|
try {
|
|
34024
34033
|
const stream = await getStream(id);
|
|
34025
34034
|
if (!options.yes) {
|
|
34026
34035
|
const confirmed = await confirm3({
|
|
34027
|
-
message: `Rotate
|
|
34036
|
+
message: `Rotate signing secret for "${stream.name}"? The current secret will be invalidated.`,
|
|
34028
34037
|
default: false
|
|
34029
34038
|
});
|
|
34030
34039
|
if (!confirmed) {
|
|
@@ -34033,13 +34042,13 @@ function registerRotateSecretCommand(program2) {
|
|
|
34033
34042
|
}
|
|
34034
34043
|
}
|
|
34035
34044
|
const result = await rotateSecret(stream.id);
|
|
34036
|
-
success(`Rotated
|
|
34045
|
+
success(`Rotated signing secret for: ${stream.name}`);
|
|
34037
34046
|
console.log(formatKeyValue([
|
|
34038
34047
|
["Stream", stream.name],
|
|
34039
|
-
["
|
|
34048
|
+
["Signing Secret", result.secret]
|
|
34040
34049
|
]));
|
|
34041
34050
|
console.log(dim(`
|
|
34042
|
-
Save the
|
|
34051
|
+
Save the signing secret - it won't be shown again!`));
|
|
34043
34052
|
} catch (err) {
|
|
34044
34053
|
handleApiError(err, "rotate secret");
|
|
34045
34054
|
}
|
|
@@ -34722,15 +34731,15 @@ async function resyncDatabase(skipConfirm, backfill) {
|
|
|
34722
34731
|
process.exit(1);
|
|
34723
34732
|
}
|
|
34724
34733
|
}
|
|
34725
|
-
// src/commands/
|
|
34734
|
+
// src/commands/receiver.ts
|
|
34726
34735
|
init_output();
|
|
34727
34736
|
init_config();
|
|
34728
34737
|
import { join as join5 } from "node:path";
|
|
34729
|
-
function
|
|
34730
|
-
const
|
|
34738
|
+
function registerReceiverCommand(program2) {
|
|
34739
|
+
const receiver = program2.command("receiver").description("Receiver development tools").hook("preAction", async () => {
|
|
34731
34740
|
await requireLocalNetwork();
|
|
34732
34741
|
});
|
|
34733
|
-
|
|
34742
|
+
receiver.command("init <directory>").description("Scaffold a receiver handler with types and signature verification").option("-n, --name <name>", "Stream name", "my-stream").option("--network <network>", "Network (mainnet/testnet)", "mainnet").option("-p, --port <port>", "Server port", "4000").action(async (directory, options) => {
|
|
34734
34743
|
try {
|
|
34735
34744
|
const config = await loadConfig();
|
|
34736
34745
|
const port = parseInt(options.port);
|
|
@@ -34744,13 +34753,13 @@ function registerWebhookCommand(program2) {
|
|
|
34744
34753
|
await Bun.$`mkdir -p ${dir}`.quiet();
|
|
34745
34754
|
await generateServerFile(dir, port);
|
|
34746
34755
|
await generateTypesFile(dir);
|
|
34747
|
-
await generateStreamJson(dir, options.name, network, port, config.
|
|
34756
|
+
await generateStreamJson(dir, options.name, network, port, config.defaultEndpointUrl);
|
|
34748
34757
|
await generateEnvFile(dir);
|
|
34749
34758
|
await generatePackageJson(dir, options.name);
|
|
34750
|
-
success(`Created
|
|
34759
|
+
success(`Created receiver handler in ${directory}/`);
|
|
34751
34760
|
console.log("");
|
|
34752
34761
|
console.log(" Files created:");
|
|
34753
|
-
console.log(` ${dim("server.ts")}
|
|
34762
|
+
console.log(` ${dim("server.ts")} Receiver server with HMAC verification`);
|
|
34754
34763
|
console.log(` ${dim("types.ts")} Payload type definitions`);
|
|
34755
34764
|
console.log(` ${dim("stream.json")} Stream configuration`);
|
|
34756
34765
|
console.log(` ${dim(".env")} Environment variables`);
|
|
@@ -34765,26 +34774,26 @@ function registerWebhookCommand(program2) {
|
|
|
34765
34774
|
console.log(` sl streams register ${directory}/stream.json`);
|
|
34766
34775
|
console.log("");
|
|
34767
34776
|
} catch (err) {
|
|
34768
|
-
error(`Failed to scaffold
|
|
34777
|
+
error(`Failed to scaffold receiver: ${err}`);
|
|
34769
34778
|
process.exit(1);
|
|
34770
34779
|
}
|
|
34771
34780
|
});
|
|
34772
34781
|
}
|
|
34773
34782
|
async function generateServerFile(dir, port) {
|
|
34774
|
-
const content = `import type {
|
|
34783
|
+
const content = `import type { DeliveryPayload } from "./types.ts";
|
|
34775
34784
|
|
|
34776
|
-
const
|
|
34785
|
+
const SIGNING_SECRET = process.env.STREAMS_SIGNING_SECRET;
|
|
34777
34786
|
|
|
34778
34787
|
/**
|
|
34779
34788
|
* Verify HMAC signature from Stacks Streams
|
|
34780
34789
|
*/
|
|
34781
34790
|
async function verifySignature(body: string, signature: string | null): Promise<boolean> {
|
|
34782
|
-
if (!
|
|
34791
|
+
if (!SIGNING_SECRET || !signature) return false;
|
|
34783
34792
|
|
|
34784
34793
|
const encoder = new TextEncoder();
|
|
34785
34794
|
const key = await crypto.subtle.importKey(
|
|
34786
34795
|
"raw",
|
|
34787
|
-
encoder.encode(
|
|
34796
|
+
encoder.encode(SIGNING_SECRET),
|
|
34788
34797
|
{ name: "HMAC", hash: "SHA-256" },
|
|
34789
34798
|
false,
|
|
34790
34799
|
["sign"]
|
|
@@ -34797,9 +34806,9 @@ async function verifySignature(body: string, signature: string | null): Promise<
|
|
|
34797
34806
|
}
|
|
34798
34807
|
|
|
34799
34808
|
/**
|
|
34800
|
-
* Handle incoming
|
|
34809
|
+
* Handle incoming delivery payload
|
|
34801
34810
|
*/
|
|
34802
|
-
async function handlePayload(payload:
|
|
34811
|
+
async function handlePayload(payload: DeliveryPayload): Promise<void> {
|
|
34803
34812
|
console.log(\`Block \${payload.block.height}: \${payload.matches.events.length} events\`);
|
|
34804
34813
|
|
|
34805
34814
|
for (const event of payload.matches.events) {
|
|
@@ -34838,13 +34847,13 @@ Bun.serve({
|
|
|
34838
34847
|
return new Response("ok");
|
|
34839
34848
|
}
|
|
34840
34849
|
|
|
34841
|
-
//
|
|
34850
|
+
// Receiver endpoint
|
|
34842
34851
|
if (req.method === "POST" && url.pathname === "/payload") {
|
|
34843
34852
|
const body = await req.text();
|
|
34844
34853
|
const signature = req.headers.get("x-streams-signature");
|
|
34845
34854
|
|
|
34846
34855
|
// Verify signature
|
|
34847
|
-
if (
|
|
34856
|
+
if (SIGNING_SECRET) {
|
|
34848
34857
|
const valid = await verifySignature(body, signature);
|
|
34849
34858
|
if (!valid) {
|
|
34850
34859
|
console.error("Invalid signature");
|
|
@@ -34853,7 +34862,7 @@ Bun.serve({
|
|
|
34853
34862
|
}
|
|
34854
34863
|
|
|
34855
34864
|
try {
|
|
34856
|
-
const payload:
|
|
34865
|
+
const payload: DeliveryPayload = JSON.parse(body);
|
|
34857
34866
|
await handlePayload(payload);
|
|
34858
34867
|
return new Response("ok");
|
|
34859
34868
|
} catch (err) {
|
|
@@ -34866,18 +34875,18 @@ Bun.serve({
|
|
|
34866
34875
|
},
|
|
34867
34876
|
});
|
|
34868
34877
|
|
|
34869
|
-
console.log(\`
|
|
34878
|
+
console.log(\`Receiver server listening on http://localhost:${port}/payload\`);
|
|
34870
34879
|
`;
|
|
34871
34880
|
await Bun.write(join5(dir, "server.ts"), content);
|
|
34872
34881
|
}
|
|
34873
34882
|
async function generateTypesFile(dir) {
|
|
34874
34883
|
const content = `/**
|
|
34875
|
-
* Stacks Streams
|
|
34884
|
+
* Stacks Streams Delivery Payload Types
|
|
34876
34885
|
*
|
|
34877
34886
|
* These types match the payload structure sent by Stacks Streams.
|
|
34878
34887
|
*/
|
|
34879
34888
|
|
|
34880
|
-
export interface
|
|
34889
|
+
export interface DeliveryPayload {
|
|
34881
34890
|
streamId: string;
|
|
34882
34891
|
streamName: string;
|
|
34883
34892
|
network: "mainnet" | "testnet";
|
|
@@ -34999,11 +35008,11 @@ export function isPrintEvent(event: EventMatch): event is PrintEvent {
|
|
|
34999
35008
|
`;
|
|
35000
35009
|
await Bun.write(join5(dir, "types.ts"), content);
|
|
35001
35010
|
}
|
|
35002
|
-
async function generateStreamJson(dir, name, network, port,
|
|
35011
|
+
async function generateStreamJson(dir, name, network, port, _defaultEndpointUrl) {
|
|
35003
35012
|
const content = {
|
|
35004
35013
|
name,
|
|
35005
35014
|
network,
|
|
35006
|
-
|
|
35015
|
+
endpointUrl: `http://localhost:${port}/payload`,
|
|
35007
35016
|
filters: [
|
|
35008
35017
|
{
|
|
35009
35018
|
type: "stx_transfer",
|
|
@@ -35023,9 +35032,9 @@ async function generateStreamJson(dir, name, network, port, _defaultWebhookUrl)
|
|
|
35023
35032
|
`);
|
|
35024
35033
|
}
|
|
35025
35034
|
async function generateEnvFile(dir) {
|
|
35026
|
-
const content = `# Stacks Streams
|
|
35035
|
+
const content = `# Stacks Streams Signing Secret
|
|
35027
35036
|
# Get this from: sl streams register stream.json
|
|
35028
|
-
|
|
35037
|
+
STREAMS_SIGNING_SECRET=
|
|
35029
35038
|
|
|
35030
35039
|
# Add your database connection, etc.
|
|
35031
35040
|
# DATABASE_URL=postgres://...
|
|
@@ -35034,7 +35043,7 @@ STREAMS_WEBHOOK_SECRET=
|
|
|
35034
35043
|
}
|
|
35035
35044
|
async function generatePackageJson(dir, name) {
|
|
35036
35045
|
const content = {
|
|
35037
|
-
name: `${name}-
|
|
35046
|
+
name: `${name}-receiver`,
|
|
35038
35047
|
version: "0.1.0",
|
|
35039
35048
|
type: "module",
|
|
35040
35049
|
scripts: {
|
|
@@ -35587,9 +35596,10 @@ ${rows.length} row(s)`));
|
|
|
35587
35596
|
}
|
|
35588
35597
|
const outPath = resolve(options2.output);
|
|
35589
35598
|
const network = inferNetwork(contractAddress) ?? "mainnet";
|
|
35599
|
+
const config = await loadConfig();
|
|
35590
35600
|
const apiKey = options2.apiKey ?? process.env.HIRO_API_KEY;
|
|
35591
35601
|
info(`Fetching ABI for ${contractAddress}...`);
|
|
35592
|
-
const client = new StacksApiClient(network, apiKey);
|
|
35602
|
+
const client = new StacksApiClient(network, apiKey, config.nodeRpcUrl);
|
|
35593
35603
|
const contractInfo = await client.getContractInfo(contractAddress);
|
|
35594
35604
|
const abi = parseApiResponse(contractInfo);
|
|
35595
35605
|
info(`Generating scaffold...`);
|
|
@@ -35941,7 +35951,7 @@ async function checkHealth() {
|
|
|
35941
35951
|
const portsToCheck = [
|
|
35942
35952
|
{ port: config.ports.api, name: "API" },
|
|
35943
35953
|
{ port: config.ports.indexer, name: "Indexer" },
|
|
35944
|
-
{ port: config.ports.
|
|
35954
|
+
{ port: config.ports.receiver, name: "Receiver" },
|
|
35945
35955
|
{ port: 20443, name: "Node RPC" }
|
|
35946
35956
|
];
|
|
35947
35957
|
for (const { port, name } of portsToCheck) {
|
|
@@ -36413,14 +36423,14 @@ init_config();
|
|
|
36413
36423
|
init_dev_state();
|
|
36414
36424
|
init_node_manager();
|
|
36415
36425
|
init_output();
|
|
36416
|
-
var DEV_SERVICES = ["api", "indexer", "worker", "
|
|
36426
|
+
var DEV_SERVICES = ["api", "indexer", "worker", "receiver", "subgraphs"];
|
|
36417
36427
|
function registerLocalCommand(program2) {
|
|
36418
36428
|
const local = program2.command("local").description("Manage local development environment and Stacks node").hook("preAction", async (_thisCommand, actionCommand) => {
|
|
36419
36429
|
if (actionCommand.name() === "help")
|
|
36420
36430
|
return;
|
|
36421
36431
|
await requireLocalNetwork();
|
|
36422
36432
|
});
|
|
36423
|
-
local.command("start").description("Start all local dev services (API, indexer, worker,
|
|
36433
|
+
local.command("start").description("Start all local dev services (API, indexer, worker, receiver)").option("--indexer-port <port>", "Indexer port", "3700").option("--api-port <port>", "API port", "3800").option("--receiver-port <port>", "Test receiver server port", "3900").option("--no-receiver", "Skip test receiver server").option("--no-worker", "Skip worker service").option("--secret <secret>", "Signing secret for signature verification").option("--stacks-node", "Use port 3701 for indexer (avoids conflict with stacks-blockchain-api)").option("-f, --foreground", "Run in foreground (blocking)").action(async (options2) => {
|
|
36424
36434
|
const { runBackground: runBackground2, runForeground: runForeground2, isDevAlreadyRunning: isDevAlreadyRunning2 } = await Promise.resolve().then(() => (init_dev_impl(), exports_dev_impl));
|
|
36425
36435
|
if (await isDevAlreadyRunning2()) {
|
|
36426
36436
|
return;
|
|
@@ -36442,7 +36452,7 @@ function registerLocalCommand(program2) {
|
|
|
36442
36452
|
local.command("status").description("Show local environment status").action(async () => {
|
|
36443
36453
|
await showLocalStatus();
|
|
36444
36454
|
});
|
|
36445
|
-
local.command("logs").description("View local service logs (dev + node)").option("-s, --service <name>", "Filter by service (api, indexer, worker,
|
|
36455
|
+
local.command("logs").description("View local service logs (dev + node)").option("-s, --service <name>", "Filter by service (api, indexer, worker, receiver, subgraphs, node)").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Number of lines to show", "50").option("-q, --quiet", "Filter out common noise").option("-v, --verbose", "Show full payloads").action(async (options2) => {
|
|
36446
36456
|
await showLocalLogs(options2);
|
|
36447
36457
|
});
|
|
36448
36458
|
const node = local.command("node").description("Manage local Stacks node");
|
|
@@ -36519,7 +36529,7 @@ var serviceColors2 = {
|
|
|
36519
36529
|
indexer: cyan,
|
|
36520
36530
|
worker: yellow,
|
|
36521
36531
|
subgraphs: magenta,
|
|
36522
|
-
|
|
36532
|
+
receiver: green,
|
|
36523
36533
|
node: red
|
|
36524
36534
|
};
|
|
36525
36535
|
async function showLocalLogs(options2) {
|
|
@@ -36671,17 +36681,17 @@ function formatLogLine3(service, line, verbose) {
|
|
|
36671
36681
|
return `${prefix} ${dimTimestamp} ${dim(level + ":")} ${dim(message)}`;
|
|
36672
36682
|
}
|
|
36673
36683
|
}
|
|
36674
|
-
if (service === "
|
|
36675
|
-
const summary =
|
|
36684
|
+
if (service === "receiver" && !verbose) {
|
|
36685
|
+
const summary = formatDeliverySummary2(line);
|
|
36676
36686
|
if (summary)
|
|
36677
36687
|
return `${prefix} ${summary}`;
|
|
36678
36688
|
}
|
|
36679
36689
|
return `${prefix} ${line}`;
|
|
36680
36690
|
}
|
|
36681
|
-
function
|
|
36691
|
+
function formatDeliverySummary2(jsonStr) {
|
|
36682
36692
|
try {
|
|
36683
36693
|
const data = JSON.parse(jsonStr);
|
|
36684
|
-
if (data.type !== "
|
|
36694
|
+
if (data.type !== "delivery" || !data.body)
|
|
36685
36695
|
return null;
|
|
36686
36696
|
const { body, method, path, timestamp } = data;
|
|
36687
36697
|
const streamName = body.streamName ?? body.streamId?.slice(0, 8) ?? "unknown";
|
|
@@ -36765,8 +36775,8 @@ registerSetupCommand(program);
|
|
|
36765
36775
|
registerConfigCommand(program);
|
|
36766
36776
|
registerAuthCommand(program);
|
|
36767
36777
|
registerWhoamiCommand(program);
|
|
36768
|
-
|
|
36778
|
+
registerReceiverCommand(program);
|
|
36769
36779
|
program.parse();
|
|
36770
36780
|
|
|
36771
|
-
//# debugId=
|
|
36781
|
+
//# debugId=9817C710C5B4B19A64756E2164756E21
|
|
36772
36782
|
//# sourceMappingURL=cli.js.map
|