@secondlayer/cli 1.9.0 → 1.10.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 CHANGED
@@ -4551,6 +4551,7 @@ var exports_api_client = {};
4551
4551
  __export(exports_api_client, {
4552
4552
  updateStreamByName: () => updateStreamByName,
4553
4553
  updateStream: () => updateStream,
4554
+ stopSubgraphApi: () => stopSubgraphApi,
4554
4555
  rotateSecret: () => rotateSecret,
4555
4556
  resumeAllStreams: () => resumeAllStreams,
4556
4557
  resolveStreamId: () => resolveStreamId,
@@ -4659,6 +4660,9 @@ async function reindexSubgraphApi(name, options) {
4659
4660
  async function backfillSubgraphApi(name, options) {
4660
4661
  return (await getClient()).subgraphs.backfill(name, options);
4661
4662
  }
4663
+ async function stopSubgraphApi(name) {
4664
+ return (await getClient()).subgraphs.stop(name);
4665
+ }
4662
4666
  async function deleteSubgraphApi(name) {
4663
4667
  return (await getClient()).subgraphs.delete(name);
4664
4668
  }
@@ -20262,7 +20266,7 @@ import { promises as fs3 } from "fs";
20262
20266
  import path from "path";
20263
20267
  import { isValidAddress as _validateStacksAddress } from "@secondlayer/stacks";
20264
20268
  import { getErrorMessage } from "@secondlayer/shared";
20265
- import { toCamelCase as toCamelCase2 } from "@secondlayer/stacks/clarity";
20269
+ import { toCamelCase as toCamelCase3 } from "@secondlayer/stacks/clarity";
20266
20270
 
20267
20271
  class PluginManager {
20268
20272
  plugins = [];
@@ -20486,7 +20490,7 @@ ${JSON.stringify(content, null, 2)}`;
20486
20490
  }
20487
20491
  createUtils() {
20488
20492
  return {
20489
- toCamelCase: toCamelCase2,
20493
+ toCamelCase: toCamelCase3,
20490
20494
  toKebabCase: (str) => {
20491
20495
  return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
20492
20496
  },
@@ -20537,7 +20541,7 @@ import {
20537
20541
  isAbiStringAscii as isAbiStringAscii2,
20538
20542
  isAbiStringUtf8 as isAbiStringUtf82,
20539
20543
  isAbiTuple,
20540
- toCamelCase as toCamelCase3
20544
+ toCamelCase as toCamelCase4
20541
20545
  } from "@secondlayer/stacks/clarity";
20542
20546
  function generateClarityConversion(argName, argType) {
20543
20547
  const type = argType.type;
@@ -20628,7 +20632,7 @@ function generateClarityConversion(argName, argType) {
20628
20632
  const requiredFields = type.tuple.map((f) => f.name);
20629
20633
  const fieldNames = JSON.stringify(requiredFields);
20630
20634
  const fields = type.tuple.map((field) => {
20631
- const camelFieldName = toCamelCase3(field.name);
20635
+ const camelFieldName = toCamelCase4(field.name);
20632
20636
  const fieldConversion = generateClarityConversion(`tupleValue.${camelFieldName}`, { type: field.type });
20633
20637
  return `"${field.name}": ${fieldConversion}`;
20634
20638
  }).join(", ");
@@ -20677,7 +20681,7 @@ import {
20677
20681
  isAbiStringAscii as isAbiStringAscii3,
20678
20682
  isAbiStringUtf8 as isAbiStringUtf83,
20679
20683
  isAbiTuple as isAbiTuple2,
20680
- toCamelCase as toCamelCase4
20684
+ toCamelCase as toCamelCase5
20681
20685
  } from "@secondlayer/stacks/clarity";
20682
20686
  function clarityTypeToTS(type) {
20683
20687
  if (typeof type === "string") {
@@ -20729,7 +20733,7 @@ function clarityTypeToTS(type) {
20729
20733
  return `${innerType}[]`;
20730
20734
  }
20731
20735
  if (isAbiTuple2(type)) {
20732
- const fields = type.tuple.map((field) => `${toCamelCase4(field.name)}: ${clarityTypeToTS(field.type)}`).join("; ");
20736
+ const fields = type.tuple.map((field) => `${toCamelCase5(field.name)}: ${clarityTypeToTS(field.type)}`).join("; ");
20733
20737
  return `{ ${fields} }`;
20734
20738
  }
20735
20739
  if (isAbiResponse2(type)) {
@@ -20747,12 +20751,12 @@ var init_type_mapping = () => {};
20747
20751
  // src/utils/generator-helpers.ts
20748
20752
  import {
20749
20753
  isAbiTuple as isAbiTuple3,
20750
- toCamelCase as toCamelCase5
20754
+ toCamelCase as toCamelCase6
20751
20755
  } from "@secondlayer/stacks/clarity";
20752
20756
  function generateMapKeyConversion(keyType) {
20753
20757
  if (isAbiTuple3(keyType)) {
20754
20758
  const fields = keyType.tuple.map((field) => {
20755
- const camelFieldName = toCamelCase5(field.name);
20759
+ const camelFieldName = toCamelCase6(field.name);
20756
20760
  const fieldConversion = generateClarityConversion(`key.${camelFieldName}`, { type: field.type });
20757
20761
  return `"${field.name}": ${fieldConversion}`;
20758
20762
  }).join(", ");
@@ -20767,7 +20771,7 @@ var init_generator_helpers = __esm(() => {
20767
20771
 
20768
20772
  // src/generators/contract.ts
20769
20773
  import {
20770
- toCamelCase as toCamelCase6
20774
+ toCamelCase as toCamelCase7
20771
20775
  } from "@secondlayer/stacks/clarity";
20772
20776
  function generateNetworkUtils() {
20773
20777
  return `/**
@@ -20859,7 +20863,7 @@ function generateAbiConstant(name, abi) {
20859
20863
  return `export const ${name}Abi = ${abiJson} as const`;
20860
20864
  }
20861
20865
  function generateMethod(func, address, contractName) {
20862
- const methodName = toCamelCase6(func.name);
20866
+ const methodName = toCamelCase7(func.name);
20863
20867
  if (func.args.length === 0) {
20864
20868
  return `${methodName}() {
20865
20869
  return {
@@ -20872,7 +20876,7 @@ function generateMethod(func, address, contractName) {
20872
20876
  }
20873
20877
  if (func.args.length === 1) {
20874
20878
  const originalArgName = func.args[0].name;
20875
- const argName = toCamelCase6(originalArgName);
20879
+ const argName = toCamelCase7(originalArgName);
20876
20880
  const argType = getTypeForArg(func.args[0]);
20877
20881
  const clarityConversion = generateClarityConversion(argName, func.args[0]);
20878
20882
  return `${methodName}(...args: [{ ${argName}: ${argType} }] | [${argType}]) {
@@ -20888,17 +20892,17 @@ function generateMethod(func, address, contractName) {
20888
20892
  }
20889
20893
  }`;
20890
20894
  }
20891
- const argsList = func.args.map((arg) => toCamelCase6(arg.name)).join(", ");
20895
+ const argsList = func.args.map((arg) => toCamelCase7(arg.name)).join(", ");
20892
20896
  const argsTypes = func.args.map((arg) => {
20893
- const camelName = toCamelCase6(arg.name);
20897
+ const camelName = toCamelCase7(arg.name);
20894
20898
  return `${camelName}: ${getTypeForArg(arg)}`;
20895
20899
  }).join("; ");
20896
20900
  const argsArray = func.args.map((arg) => {
20897
- const argName = toCamelCase6(arg.name);
20901
+ const argName = toCamelCase7(arg.name);
20898
20902
  return generateClarityConversion(argName, arg);
20899
20903
  }).join(", ");
20900
20904
  const objectAccess = func.args.map((arg) => {
20901
- const camelName = toCamelCase6(arg.name);
20905
+ const camelName = toCamelCase7(arg.name);
20902
20906
  return `args[0].${camelName}`;
20903
20907
  }).join(", ");
20904
20908
  const positionTypes = func.args.map((arg) => getTypeForArg(arg)).join(", ");
@@ -20920,7 +20924,7 @@ function generateMapsObject(maps, address, contractName) {
20920
20924
  return "";
20921
20925
  }
20922
20926
  const mapMethods = maps.map((map) => {
20923
- const methodName = toCamelCase6(map.name);
20927
+ const methodName = toCamelCase7(map.name);
20924
20928
  const keyType = getTypeForArg({ type: map.key });
20925
20929
  const valueType = getTypeForArg({ type: map.value });
20926
20930
  const keyConversion = generateMapKeyConversion(map.key);
@@ -20981,7 +20985,7 @@ function generateVarsObject(variables, address, contractName) {
20981
20985
  return "";
20982
20986
  }
20983
20987
  const varMethods = dataVars.map((variable) => {
20984
- const methodName = toCamelCase6(variable.name);
20988
+ const methodName = toCamelCase7(variable.name);
20985
20989
  const valueType = getTypeForArg({ type: variable.type });
20986
20990
  return `${methodName}: {
20987
20991
  async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
@@ -21026,7 +21030,7 @@ function generateConstantsObject(variables, address, contractName) {
21026
21030
  return "";
21027
21031
  }
21028
21032
  const constMethods = constants.map((constant) => {
21029
- const methodName = toCamelCase6(constant.name);
21033
+ const methodName = toCamelCase7(constant.name);
21030
21034
  const valueType = getTypeForArg({ type: constant.type });
21031
21035
  return `${methodName}: {
21032
21036
  async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
@@ -32310,7 +32314,7 @@ __export(exports_generate, {
32310
32314
  });
32311
32315
  import path10 from "path";
32312
32316
  import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
32313
- import { toCamelCase as toCamelCase7 } from "@secondlayer/stacks/clarity";
32317
+ import { toCamelCase as toCamelCase8 } from "@secondlayer/stacks/clarity";
32314
32318
  function isContractAddress(input4) {
32315
32319
  const contractIdPattern = /^(SP|ST|SM|SN)[A-Z0-9]{38,}\.[a-zA-Z][a-zA-Z0-9-]*$/;
32316
32320
  return contractIdPattern.test(input4);
@@ -32371,7 +32375,7 @@ async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddre
32371
32375
  const apiClient = new StacksApiClient(network, apiKey);
32372
32376
  const contractInfo = await apiClient.getContractInfo(contractId);
32373
32377
  const abi = parseApiResponse(contractInfo);
32374
- const name = toCamelCase7(contractName);
32378
+ const name = toCamelCase8(contractName);
32375
32379
  contracts.push({
32376
32380
  name,
32377
32381
  address: contractId,
@@ -32616,7 +32620,7 @@ var {
32616
32620
  // package.json
32617
32621
  var package_default = {
32618
32622
  name: "@secondlayer/cli",
32619
- version: "1.9.0",
32623
+ version: "1.10.1",
32620
32624
  description: "CLI for streams, subgraphs, and real-time blockchain indexing on Stacks",
32621
32625
  type: "module",
32622
32626
  bin: {
@@ -32657,10 +32661,10 @@ var package_default = {
32657
32661
  license: "MIT",
32658
32662
  dependencies: {
32659
32663
  "@inquirer/prompts": "^8.2.0",
32660
- "@secondlayer/sdk": "^0.8.1",
32661
- "@secondlayer/shared": "^0.9.0",
32664
+ "@secondlayer/sdk": "^0.9.1",
32665
+ "@secondlayer/shared": "^0.10.1",
32662
32666
  "@secondlayer/stacks": "^0.2.2",
32663
- "@secondlayer/subgraphs": "^0.7.2",
32667
+ "@secondlayer/subgraphs": "^0.9.0",
32664
32668
  "@biomejs/js-api": "^0.7.0",
32665
32669
  "@biomejs/wasm-nodejs": "^1.9.0",
32666
32670
  esbuild: "^0.19.0",
@@ -35222,6 +35226,9 @@ function mapType(abiType, nullable) {
35222
35226
  }
35223
35227
 
35224
35228
  // src/generators/subgraph-scaffold.ts
35229
+ function toCamelCase(str) {
35230
+ return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
35231
+ }
35225
35232
  async function generateSubgraphScaffold(input2) {
35226
35233
  const { contractId, functions } = input2;
35227
35234
  const contractParts = contractId.split(".");
@@ -35231,6 +35238,12 @@ async function generateSubgraphScaffold(input2) {
35231
35238
  if (publicFunctions.length === 0) {
35232
35239
  throw new Error(`No public functions found in ${contractId}`);
35233
35240
  }
35241
+ const sourceEntries = publicFunctions.map((fn) => {
35242
+ const sourceName = toCamelCase(fn.name);
35243
+ return ` ${sourceName}: { type: 'contract_call', contractId: '${contractId}', functionName: '${fn.name}' }`;
35244
+ });
35245
+ const sourcesBlock = sourceEntries.join(`,
35246
+ `);
35234
35247
  const tables = publicFunctions.map((fn) => {
35235
35248
  const columns = fn.args.map((arg) => {
35236
35249
  const mapped = clarityTypeToSubgraphColumn(arg.type);
@@ -35247,14 +35260,15 @@ ${columns || " _placeholder: { type: 'text' }"}
35247
35260
  });
35248
35261
  const schemaBlock = tables.join(`,
35249
35262
  `);
35250
- const handlerKeys = publicFunctions.map((fn) => {
35251
- return ` '${contractId}::${fn.name}': async (event, ctx) => {
35263
+ const handlerEntries = publicFunctions.map((fn) => {
35264
+ const sourceName = toCamelCase(fn.name);
35265
+ return ` ${sourceName}: async (event, ctx) => {
35252
35266
  // TODO: implement ${fn.name} handler
35253
35267
  // event.args contains the function arguments
35254
35268
  // ctx.insert('${fn.name.replace(/-/g, "_")}', { ... })
35255
35269
  }`;
35256
35270
  });
35257
- const handlersBlock = handlerKeys.join(`,
35271
+ const handlersBlock = handlerEntries.join(`,
35258
35272
 
35259
35273
  `);
35260
35274
  const code = `
@@ -35262,7 +35276,9 @@ import { defineSubgraph } from '@secondlayer/subgraphs';
35262
35276
 
35263
35277
  export default defineSubgraph({
35264
35278
  name: '${subgraphName}',
35265
- sources: [{ contract: '${contractId}' }],
35279
+ sources: {
35280
+ ${sourcesBlock}
35281
+ },
35266
35282
  schema: {
35267
35283
  ${schemaBlock}
35268
35284
  },
@@ -35275,12 +35291,12 @@ ${handlersBlock}
35275
35291
  }
35276
35292
 
35277
35293
  // src/utils/case-conversion.ts
35278
- import { toCamelCase } from "@secondlayer/stacks/clarity";
35294
+ import { toCamelCase as toCamelCase2 } from "@secondlayer/stacks/clarity";
35279
35295
  function capitalize(str) {
35280
35296
  return str.charAt(0).toUpperCase() + str.slice(1);
35281
35297
  }
35282
35298
  function toPascalCase(str) {
35283
- return capitalize(toCamelCase(str));
35299
+ return capitalize(toCamelCase2(str));
35284
35300
  }
35285
35301
 
35286
35302
  // src/generators/subgraphs.ts
@@ -35374,15 +35390,19 @@ export default defineSubgraph({
35374
35390
  description: "TODO: describe what this subgraph tracks",
35375
35391
 
35376
35392
  // Sources define what blockchain data this subgraph processes.
35377
- // Each source filters transactions/events by contract, type, function, or event.
35378
- // Examples:
35379
- // { contract: "SP000...::my-contract" } — all txs to a contract
35380
- // { contract: "SP000...::my-contract", event: "transfer" } — specific event
35381
- // { type: "stx_transfer", minAmount: 1000000n } — STX transfers >= 1 STX
35382
- // { contract: "*.pox-*" } — wildcard contract match
35383
- sources: [
35384
- { contract: "SP000000000000000000002Q6VF78.pox-4" },
35385
- ],
35393
+ // Each source is named the name becomes the handler key.
35394
+ //
35395
+ // Filter types:
35396
+ // { type: "ft_transfer", assetIdentifier: "SP...token::token-name" }
35397
+ // { type: "ft_mint", assetIdentifier: "SP...token::token-name" }
35398
+ // { type: "contract_call", contractId: "SP...contract", functionName: "swap" }
35399
+ // { type: "contract_deploy" }
35400
+ // { type: "print_event", contractId: "SP...contract", topic: "my-event" }
35401
+ // { type: "stx_transfer", minAmount: 1000000n }
35402
+ // { type: "nft_transfer", assetIdentifier: "SP...nft::nft-name" }
35403
+ sources: {
35404
+ handler: { type: "contract_call", contractId: "SP000000000000000000002Q6VF78.pox-4" },
35405
+ },
35386
35406
 
35387
35407
  // Schema defines the tables this subgraph creates.
35388
35408
  // Each table gets auto-columns: _id, _block_height, _tx_id, _created_at.
@@ -35394,20 +35414,18 @@ export default defineSubgraph({
35394
35414
  amount: { type: "uint" },
35395
35415
  memo: { type: "text", nullable: true },
35396
35416
  },
35397
- // Optional composite indexes
35398
- // indexes: [["sender", "amount"]],
35399
35417
  },
35400
35418
  },
35401
35419
 
35402
- // Handlers process matched events and write to your tables via the context.
35403
- // Keys match source patterns (use sourceKey format), or "*" as catch-all.
35404
- // Context methods: ctx.insert(), ctx.update(), ctx.delete()
35420
+ // Handlers process matched events. Keys must match source names.
35421
+ // Context: ctx.insert(), ctx.update(), ctx.upsert(), ctx.patch(),
35422
+ // ctx.patchOrInsert(), ctx.findOne(), ctx.findMany()
35405
35423
  handlers: {
35406
- "*": async (event, ctx) => {
35407
- await ctx.insert("data", {
35408
- sender: event.sender ?? event.tx?.sender,
35424
+ handler: (event, ctx) => {
35425
+ ctx.insert("data", {
35426
+ sender: ctx.tx.sender,
35409
35427
  amount: event.amount ?? 0,
35410
- memo: event.memo ?? null,
35428
+ memo: null,
35411
35429
  });
35412
35430
  },
35413
35431
  },
@@ -35516,12 +35534,11 @@ Stopped watching.`);
35516
35534
  write: false
35517
35535
  });
35518
35536
  const handlerCode = new TextDecoder().decode(buildResult.outputFiles[0].contents);
35519
- const { sourceKey } = await import("@secondlayer/subgraphs");
35520
35537
  const result = await deploySubgraphApi({
35521
35538
  name: def.name,
35522
35539
  version: def.version,
35523
35540
  description: def.description,
35524
- sources: def.sources.map(sourceKey),
35541
+ sources: def.sources,
35525
35542
  schema: def.schema,
35526
35543
  handlerCode,
35527
35544
  reindex: options2.reindex
@@ -35666,6 +35683,15 @@ Table endpoints:`));
35666
35683
  handleApiError(err, "backfill subgraph");
35667
35684
  }
35668
35685
  });
35686
+ subgraphs.command("stop <name>").description("Stop a running reindex or backfill operation").action(async (name) => {
35687
+ try {
35688
+ info(`Stopping operation for subgraph "${name}"...`);
35689
+ const result = await stopSubgraphApi(name);
35690
+ success(result.message);
35691
+ } catch (err) {
35692
+ handleApiError(err, "stop subgraph operation");
35693
+ }
35694
+ });
35669
35695
  subgraphs.command("gaps <name>").description("Show block gaps for a subgraph").option("--resolved", "Include resolved gaps").option("--limit <n>", "Max gaps to return", "50").option("--json", "Output as JSON").action(async (name, options2) => {
35670
35696
  try {
35671
35697
  const result = await getSubgraphGaps(name, {
@@ -37012,5 +37038,5 @@ registerWhoamiCommand(program);
37012
37038
  registerReceiverCommand(program);
37013
37039
  program.parse();
37014
37040
 
37015
- //# debugId=D8ABBF7C05EEC0E764756E2164756E21
37041
+ //# debugId=7DCC96BC6E5808DA64756E2164756E21
37016
37042
  //# sourceMappingURL=cli.js.map