@secondlayer/cli 8.6.2 → 8.6.4
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 +21 -564
- package/dist/cli.js.map +8 -11
- package/dist/plugins/index.js +62 -597
- package/dist/plugins/index.js.map +6 -7
- package/package.json +4 -3
package/dist/cli.js
CHANGED
|
@@ -12870,8 +12870,12 @@ class StacksApiClient {
|
|
|
12870
12870
|
async getContractInfo(contractId) {
|
|
12871
12871
|
await this.ensureProxy();
|
|
12872
12872
|
if (this.useProxy) {
|
|
12873
|
-
const url2 = `${this.baseUrl}/
|
|
12874
|
-
|
|
12873
|
+
const url2 = `${this.baseUrl}/v1/contracts/${encodeURIComponent(contractId)}?include=abi`;
|
|
12874
|
+
const { contract } = await this.fetchWithErrorHandling(url2, "Contract", contractId);
|
|
12875
|
+
if (!contract?.abi) {
|
|
12876
|
+
throw new Error(`ABI not available for ${contractId} (status: ${contract?.abi_status ?? "unknown"})`);
|
|
12877
|
+
}
|
|
12878
|
+
return contract.abi;
|
|
12875
12879
|
}
|
|
12876
12880
|
const { address, contractName } = parseContractId(contractId);
|
|
12877
12881
|
const url = `${this.baseUrl}/v2/contracts/interface/${address}/${contractName}`;
|
|
@@ -20296,562 +20300,15 @@ var require_out4 = __commonJS((exports, module) => {
|
|
|
20296
20300
|
module.exports = FastGlob;
|
|
20297
20301
|
});
|
|
20298
20302
|
|
|
20299
|
-
// src/utils/clarity-conversion.ts
|
|
20300
|
-
import {
|
|
20301
|
-
isAbiBuffer as isAbiBuffer2,
|
|
20302
|
-
isAbiList,
|
|
20303
|
-
isAbiOptional as isAbiOptional2,
|
|
20304
|
-
isAbiResponse,
|
|
20305
|
-
isAbiStringAscii as isAbiStringAscii2,
|
|
20306
|
-
isAbiStringUtf8 as isAbiStringUtf82,
|
|
20307
|
-
isAbiTuple,
|
|
20308
|
-
toCamelCase as toCamelCase4
|
|
20309
|
-
} from "@secondlayer/stacks/clarity";
|
|
20310
|
-
function generateClarityConversion(argName, argType) {
|
|
20311
|
-
const type = argType.type;
|
|
20312
|
-
if (typeof type === "string") {
|
|
20313
|
-
switch (type) {
|
|
20314
|
-
case "uint128":
|
|
20315
|
-
return `Cl.uint(${argName})`;
|
|
20316
|
-
case "int128":
|
|
20317
|
-
return `Cl.int(${argName})`;
|
|
20318
|
-
case "bool":
|
|
20319
|
-
return `Cl.bool(${argName})`;
|
|
20320
|
-
case "principal":
|
|
20321
|
-
case "trait_reference":
|
|
20322
|
-
return `(() => {
|
|
20323
|
-
const [address, contractName] = ${argName}.split(".") as [string, string | undefined];
|
|
20324
|
-
if (!validateStacksAddress(address)) {
|
|
20325
|
-
throw new Error("Invalid Stacks address format");
|
|
20326
|
-
}
|
|
20327
|
-
if (contractName !== undefined) {
|
|
20328
|
-
if (!CONTRACT_NAME_REGEX.test(contractName)) {
|
|
20329
|
-
throw new Error("Invalid contract name format: must start with letter and contain only letters, numbers, and hyphens");
|
|
20330
|
-
}
|
|
20331
|
-
return Cl.contractPrincipal(address, contractName);
|
|
20332
|
-
}
|
|
20333
|
-
return Cl.standardPrincipal(${argName});
|
|
20334
|
-
})()`;
|
|
20335
|
-
default:
|
|
20336
|
-
return `${argName}`;
|
|
20337
|
-
}
|
|
20338
|
-
}
|
|
20339
|
-
if (isAbiStringAscii2(type)) {
|
|
20340
|
-
return `Cl.stringAscii(${argName})`;
|
|
20341
|
-
}
|
|
20342
|
-
if (isAbiStringUtf82(type)) {
|
|
20343
|
-
return `Cl.stringUtf8(${argName})`;
|
|
20344
|
-
}
|
|
20345
|
-
if (isAbiBuffer2(type)) {
|
|
20346
|
-
return `(() => {
|
|
20347
|
-
const value = ${argName};
|
|
20348
|
-
if (value instanceof Uint8Array) {
|
|
20349
|
-
return Cl.buffer(value);
|
|
20350
|
-
}
|
|
20351
|
-
if (typeof value === 'object' && value !== null && value.type && value.value) {
|
|
20352
|
-
switch (value.type) {
|
|
20353
|
-
case 'ascii':
|
|
20354
|
-
return Cl.bufferFromAscii(value.value);
|
|
20355
|
-
case 'utf8':
|
|
20356
|
-
return Cl.bufferFromUtf8(value.value);
|
|
20357
|
-
case 'hex':
|
|
20358
|
-
return Cl.bufferFromHex(value.value);
|
|
20359
|
-
default:
|
|
20360
|
-
throw new Error(\`Unsupported buffer type: \${value.type}\`);
|
|
20361
|
-
}
|
|
20362
|
-
}
|
|
20363
|
-
if (typeof value === 'string') {
|
|
20364
|
-
if (value.startsWith('0x') || /^[0-9a-fA-F]+$/.test(value)) {
|
|
20365
|
-
return Cl.bufferFromHex(value);
|
|
20366
|
-
}
|
|
20367
|
-
const hasNonAscii = value.split('').some(char => char.charCodeAt(0) > 127);
|
|
20368
|
-
if (hasNonAscii) {
|
|
20369
|
-
return Cl.bufferFromUtf8(value);
|
|
20370
|
-
}
|
|
20371
|
-
return Cl.bufferFromAscii(value);
|
|
20372
|
-
}
|
|
20373
|
-
throw new Error(\`Invalid buffer value: \${value}\`);
|
|
20374
|
-
})()`;
|
|
20375
|
-
}
|
|
20376
|
-
if (isAbiOptional2(type)) {
|
|
20377
|
-
const innerConversion = generateClarityConversion(argName, {
|
|
20378
|
-
type: type.optional
|
|
20379
|
-
});
|
|
20380
|
-
return `${argName} !== null ? Cl.some(${innerConversion.replace(argName, `${argName}`)}) : Cl.none()`;
|
|
20381
|
-
}
|
|
20382
|
-
if (isAbiList(type)) {
|
|
20383
|
-
const innerConversion = generateClarityConversion("item", {
|
|
20384
|
-
type: type.list.type
|
|
20385
|
-
});
|
|
20386
|
-
const maxLength = type.list.length || 100;
|
|
20387
|
-
return `(() => {
|
|
20388
|
-
const listValue = ${argName};
|
|
20389
|
-
if (listValue.length > ${maxLength}) {
|
|
20390
|
-
throw new Error(\`List length \${listValue.length} exceeds max ${maxLength}\`);
|
|
20391
|
-
}
|
|
20392
|
-
return Cl.list(listValue.map(item => ${innerConversion}));
|
|
20393
|
-
})()`;
|
|
20394
|
-
}
|
|
20395
|
-
if (isAbiTuple(type)) {
|
|
20396
|
-
const requiredFields = type.tuple.map((f) => f.name);
|
|
20397
|
-
const fieldNames = JSON.stringify(requiredFields);
|
|
20398
|
-
const fields = type.tuple.map((field) => {
|
|
20399
|
-
const camelFieldName = toCamelCase4(field.name);
|
|
20400
|
-
const fieldConversion = generateClarityConversion(`tupleValue.${camelFieldName}`, { type: field.type });
|
|
20401
|
-
return `"${field.name}": ${fieldConversion}`;
|
|
20402
|
-
}).join(", ");
|
|
20403
|
-
return `(() => {
|
|
20404
|
-
const tupleValue = ${argName};
|
|
20405
|
-
const requiredFields = ${fieldNames};
|
|
20406
|
-
for (const fieldName of requiredFields) {
|
|
20407
|
-
const camelName = fieldName.replace(/-([a-z])/g, (_: string, l: string) => l.toUpperCase());
|
|
20408
|
-
if (!(fieldName in tupleValue) && !(camelName in tupleValue)) {
|
|
20409
|
-
throw new Error(\`Missing tuple field: \${fieldName}\`);
|
|
20410
|
-
}
|
|
20411
|
-
}
|
|
20412
|
-
return Cl.tuple({ ${fields} });
|
|
20413
|
-
})()`;
|
|
20414
|
-
}
|
|
20415
|
-
if (isAbiResponse(type)) {
|
|
20416
|
-
const okConversion = generateClarityConversion("responseValue.ok", {
|
|
20417
|
-
type: type.response.ok
|
|
20418
|
-
});
|
|
20419
|
-
const errConversion = generateClarityConversion("responseValue.err", {
|
|
20420
|
-
type: type.response.error
|
|
20421
|
-
});
|
|
20422
|
-
return `(() => {
|
|
20423
|
-
const responseValue = ${argName};
|
|
20424
|
-
const hasOk = 'ok' in responseValue;
|
|
20425
|
-
const hasErr = 'err' in responseValue;
|
|
20426
|
-
if (hasOk && !hasErr) {
|
|
20427
|
-
return Cl.ok(${okConversion});
|
|
20428
|
-
}
|
|
20429
|
-
if (hasErr && !hasOk) {
|
|
20430
|
-
return Cl.error(${errConversion});
|
|
20431
|
-
}
|
|
20432
|
-
throw new Error("Response must have exactly 'ok' or 'err' property");
|
|
20433
|
-
})()`;
|
|
20434
|
-
}
|
|
20435
|
-
return `${argName}`;
|
|
20436
|
-
}
|
|
20437
|
-
var init_clarity_conversion = () => {};
|
|
20438
|
-
|
|
20439
|
-
// src/utils/type-mapping.ts
|
|
20440
|
-
import {
|
|
20441
|
-
isAbiBuffer as isAbiBuffer3,
|
|
20442
|
-
isAbiList as isAbiList2,
|
|
20443
|
-
isAbiOptional as isAbiOptional3,
|
|
20444
|
-
isAbiResponse as isAbiResponse2,
|
|
20445
|
-
isAbiStringAscii as isAbiStringAscii3,
|
|
20446
|
-
isAbiStringUtf8 as isAbiStringUtf83,
|
|
20447
|
-
isAbiTuple as isAbiTuple2,
|
|
20448
|
-
toCamelCase as toCamelCase5
|
|
20449
|
-
} from "@secondlayer/stacks/clarity";
|
|
20450
|
-
function clarityTypeToTS(type) {
|
|
20451
|
-
if (typeof type === "string") {
|
|
20452
|
-
switch (type) {
|
|
20453
|
-
case "uint128":
|
|
20454
|
-
case "int128":
|
|
20455
|
-
return "bigint";
|
|
20456
|
-
case "bool":
|
|
20457
|
-
return "boolean";
|
|
20458
|
-
case "principal":
|
|
20459
|
-
case "trait_reference":
|
|
20460
|
-
return "string";
|
|
20461
|
-
default: {
|
|
20462
|
-
const typeStr = type;
|
|
20463
|
-
if (typeStr === "none") {
|
|
20464
|
-
return "null";
|
|
20465
|
-
}
|
|
20466
|
-
if (typeStr.includes("string") || typeStr.includes("ascii") || typeStr.includes("utf8")) {
|
|
20467
|
-
return "string";
|
|
20468
|
-
}
|
|
20469
|
-
if (typeStr.includes("buff")) {
|
|
20470
|
-
return "Uint8Array | string | { type: 'ascii' | 'utf8' | 'hex'; value: string }";
|
|
20471
|
-
}
|
|
20472
|
-
if (typeStr.includes("uint") || typeStr.includes("int")) {
|
|
20473
|
-
return "bigint";
|
|
20474
|
-
}
|
|
20475
|
-
return "any";
|
|
20476
|
-
}
|
|
20477
|
-
}
|
|
20478
|
-
}
|
|
20479
|
-
if (isAbiBuffer3(type)) {
|
|
20480
|
-
return "Uint8Array | string | { type: 'ascii' | 'utf8' | 'hex'; value: string }";
|
|
20481
|
-
}
|
|
20482
|
-
if (isAbiStringAscii3(type) || isAbiStringUtf83(type)) {
|
|
20483
|
-
return "string";
|
|
20484
|
-
}
|
|
20485
|
-
if (isAbiOptional3(type)) {
|
|
20486
|
-
const innerType = clarityTypeToTS(type.optional);
|
|
20487
|
-
if (innerType.includes(" | ") && !innerType.startsWith("(")) {
|
|
20488
|
-
return `(${innerType}) | null`;
|
|
20489
|
-
}
|
|
20490
|
-
return `${innerType} | null`;
|
|
20491
|
-
}
|
|
20492
|
-
if (isAbiList2(type)) {
|
|
20493
|
-
const innerType = clarityTypeToTS(type.list.type);
|
|
20494
|
-
if (innerType.includes(" | ") && !innerType.startsWith("(")) {
|
|
20495
|
-
return `(${innerType})[]`;
|
|
20496
|
-
}
|
|
20497
|
-
return `${innerType}[]`;
|
|
20498
|
-
}
|
|
20499
|
-
if (isAbiTuple2(type)) {
|
|
20500
|
-
const fields = type.tuple.map((field) => `${toCamelCase5(field.name)}: ${clarityTypeToTS(field.type)}`).join("; ");
|
|
20501
|
-
return `{ ${fields} }`;
|
|
20502
|
-
}
|
|
20503
|
-
if (isAbiResponse2(type)) {
|
|
20504
|
-
const okType = clarityTypeToTS(type.response.ok);
|
|
20505
|
-
const errType = clarityTypeToTS(type.response.error);
|
|
20506
|
-
return `{ ok: ${okType} } | { err: ${errType} }`;
|
|
20507
|
-
}
|
|
20508
|
-
return "any";
|
|
20509
|
-
}
|
|
20510
|
-
function getTypeForArg(arg) {
|
|
20511
|
-
return clarityTypeToTS(arg.type);
|
|
20512
|
-
}
|
|
20513
|
-
var init_type_mapping = () => {};
|
|
20514
|
-
|
|
20515
|
-
// src/utils/generator-helpers.ts
|
|
20516
|
-
import {
|
|
20517
|
-
isAbiTuple as isAbiTuple3,
|
|
20518
|
-
toCamelCase as toCamelCase6
|
|
20519
|
-
} from "@secondlayer/stacks/clarity";
|
|
20520
|
-
function generateArgsSignature(args) {
|
|
20521
|
-
if (args.length === 0)
|
|
20522
|
-
return "";
|
|
20523
|
-
const argsTypes = args.map((arg) => {
|
|
20524
|
-
const camelName = toCamelCase6(arg.name);
|
|
20525
|
-
return `${camelName}: ${getTypeForArg(arg)}`;
|
|
20526
|
-
}).join("; ");
|
|
20527
|
-
return `args: { ${argsTypes} }, `;
|
|
20528
|
-
}
|
|
20529
|
-
function generateClarityArgs(args) {
|
|
20530
|
-
if (args.length === 0)
|
|
20531
|
-
return "";
|
|
20532
|
-
return args.map((arg) => {
|
|
20533
|
-
const argName = `args.${toCamelCase6(arg.name)}`;
|
|
20534
|
-
return generateClarityConversion(argName, arg);
|
|
20535
|
-
}).join(", ");
|
|
20536
|
-
}
|
|
20537
|
-
function generateMapKeyConversion(keyType) {
|
|
20538
|
-
if (isAbiTuple3(keyType)) {
|
|
20539
|
-
const fields = keyType.tuple.map((field) => {
|
|
20540
|
-
const camelFieldName = toCamelCase6(field.name);
|
|
20541
|
-
const fieldConversion = generateClarityConversion(`key.${camelFieldName}`, { type: field.type });
|
|
20542
|
-
return `"${field.name}": ${fieldConversion}`;
|
|
20543
|
-
}).join(", ");
|
|
20544
|
-
return `Cl.tuple({ ${fields} })`;
|
|
20545
|
-
}
|
|
20546
|
-
return generateClarityConversion("key", { type: keyType });
|
|
20547
|
-
}
|
|
20548
|
-
var init_generator_helpers = __esm(() => {
|
|
20549
|
-
init_clarity_conversion();
|
|
20550
|
-
init_type_mapping();
|
|
20551
|
-
});
|
|
20552
|
-
|
|
20553
20303
|
// src/generators/contract.ts
|
|
20554
20304
|
import {
|
|
20555
|
-
|
|
20556
|
-
} from "@secondlayer/
|
|
20557
|
-
function generateNetworkUtils() {
|
|
20558
|
-
return `/**
|
|
20559
|
-
* API URLs for different networks
|
|
20560
|
-
*/
|
|
20561
|
-
const API_URLS: Record<'mainnet' | 'testnet' | 'devnet', string> = {
|
|
20562
|
-
mainnet: 'https://api.hiro.so',
|
|
20563
|
-
testnet: 'https://api.testnet.hiro.so',
|
|
20564
|
-
devnet: 'http://localhost:3999'
|
|
20565
|
-
};
|
|
20566
|
-
|
|
20567
|
-
/**
|
|
20568
|
-
* Infer network from Stacks address prefix
|
|
20569
|
-
* SP/SM = mainnet, ST/SN = testnet
|
|
20570
|
-
*/
|
|
20571
|
-
function inferNetworkFromAddress(address: string): 'mainnet' | 'testnet' | undefined {
|
|
20572
|
-
if (address.startsWith('SP') || address.startsWith('SM')) return 'mainnet';
|
|
20573
|
-
if (address.startsWith('ST') || address.startsWith('SN')) return 'testnet';
|
|
20574
|
-
return undefined;
|
|
20575
|
-
}
|
|
20576
|
-
|
|
20577
|
-
/**
|
|
20578
|
-
* Get API URL, inferring network from contract address if not specified
|
|
20579
|
-
*/
|
|
20580
|
-
function getApiUrl(
|
|
20581
|
-
contractAddress: string,
|
|
20582
|
-
explicitNetwork?: 'mainnet' | 'testnet' | 'devnet'
|
|
20583
|
-
): string {
|
|
20584
|
-
const network = explicitNetwork ?? inferNetworkFromAddress(contractAddress) ?? 'mainnet';
|
|
20585
|
-
return API_URLS[network];
|
|
20586
|
-
}`;
|
|
20587
|
-
}
|
|
20588
|
-
function generateValidationUtils() {
|
|
20589
|
-
return `/**
|
|
20590
|
-
* Contract name validation regex
|
|
20591
|
-
* Must start with letter, contain only letters, numbers, and hyphens, max 128 chars
|
|
20592
|
-
*/
|
|
20593
|
-
const CONTRACT_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9\\-]{0,127}$/;`;
|
|
20594
|
-
}
|
|
20305
|
+
generateContractInterface as buildContractInterface
|
|
20306
|
+
} from "@secondlayer/scaffold";
|
|
20595
20307
|
async function generateContractInterface(contracts) {
|
|
20596
|
-
|
|
20597
|
-
const header = `/**
|
|
20598
|
-
* Generated by @secondlayer/cli
|
|
20599
|
-
* DO NOT EDIT MANUALLY
|
|
20600
|
-
*
|
|
20601
|
-
* @requires @secondlayer/stacks - Install with: npm install @secondlayer/stacks
|
|
20602
|
-
*/`;
|
|
20603
|
-
const validationUtils = generateValidationUtils();
|
|
20604
|
-
const networkUtils = generateNetworkUtils();
|
|
20605
|
-
const contractsCode = contracts.map((contract) => generateContract(contract)).join(`
|
|
20606
|
-
|
|
20607
|
-
`);
|
|
20608
|
-
const code = `${imports}
|
|
20609
|
-
|
|
20610
|
-
${header}
|
|
20611
|
-
|
|
20612
|
-
${validationUtils}
|
|
20613
|
-
|
|
20614
|
-
${networkUtils}
|
|
20615
|
-
|
|
20616
|
-
${contractsCode}`;
|
|
20617
|
-
return formatCode(code);
|
|
20618
|
-
}
|
|
20619
|
-
function generateContract(contract) {
|
|
20620
|
-
const { name, address, contractName, abi } = contract;
|
|
20621
|
-
const abiCode = generateAbiConstant(name, abi);
|
|
20622
|
-
const methods = abi.functions.filter((func) => func.access !== "private").map((func) => generateMethod(func, address, contractName)).join(`,
|
|
20623
|
-
|
|
20624
|
-
`);
|
|
20625
|
-
const mapsObject = generateMapsObject(abi.maps || [], address, contractName);
|
|
20626
|
-
const varsObject = generateVarsObject(abi.variables || [], address, contractName);
|
|
20627
|
-
const constantsObject = generateConstantsObject(abi.variables || [], address, contractName);
|
|
20628
|
-
const allMembers = [methods, mapsObject, varsObject, constantsObject].filter(Boolean);
|
|
20629
|
-
const contractCode = `export const ${name} = {
|
|
20630
|
-
address: '${address}',
|
|
20631
|
-
contractAddress: '${address}',
|
|
20632
|
-
contractName: '${contractName}',
|
|
20633
|
-
|
|
20634
|
-
${allMembers.join(`,
|
|
20635
|
-
|
|
20636
|
-
`)}
|
|
20637
|
-
} as const`;
|
|
20638
|
-
return `${abiCode}
|
|
20639
|
-
|
|
20640
|
-
${contractCode}`;
|
|
20641
|
-
}
|
|
20642
|
-
function generateAbiConstant(name, abi) {
|
|
20643
|
-
const abiJson = JSON.stringify(abi, null, 2).replace(/"([a-zA-Z_$][a-zA-Z0-9_$]*)":/g, "$1:").replace(/"/g, "'");
|
|
20644
|
-
return `export const ${name}Abi = ${abiJson} as const`;
|
|
20645
|
-
}
|
|
20646
|
-
function generateMethod(func, address, contractName) {
|
|
20647
|
-
const methodName = toCamelCase7(func.name);
|
|
20648
|
-
if (func.args.length === 0) {
|
|
20649
|
-
return `${methodName}() {
|
|
20650
|
-
return {
|
|
20651
|
-
contractAddress: '${address}',
|
|
20652
|
-
contractName: '${contractName}',
|
|
20653
|
-
functionName: '${func.name}',
|
|
20654
|
-
functionArgs: []
|
|
20655
|
-
}
|
|
20656
|
-
}`;
|
|
20657
|
-
}
|
|
20658
|
-
if (func.args.length === 1) {
|
|
20659
|
-
const originalArgName = func.args[0].name;
|
|
20660
|
-
const argName = toCamelCase7(originalArgName);
|
|
20661
|
-
const argType = getTypeForArg(func.args[0]);
|
|
20662
|
-
const clarityConversion = generateClarityConversion(argName, func.args[0]);
|
|
20663
|
-
return `${methodName}(...args: [{ ${argName}: ${argType} }] | [${argType}]) {
|
|
20664
|
-
const ${argName} = args.length === 1 && typeof args[0] === 'object' && args[0] !== null && '${argName}' in args[0]
|
|
20665
|
-
? args[0].${argName}
|
|
20666
|
-
: args[0] as ${argType}
|
|
20667
|
-
|
|
20668
|
-
return {
|
|
20669
|
-
contractAddress: '${address}',
|
|
20670
|
-
contractName: '${contractName}',
|
|
20671
|
-
functionName: '${func.name}',
|
|
20672
|
-
functionArgs: [${clarityConversion}]
|
|
20673
|
-
}
|
|
20674
|
-
}`;
|
|
20675
|
-
}
|
|
20676
|
-
const argsList = func.args.map((arg) => toCamelCase7(arg.name)).join(", ");
|
|
20677
|
-
const argsTypes = func.args.map((arg) => {
|
|
20678
|
-
const camelName = toCamelCase7(arg.name);
|
|
20679
|
-
return `${camelName}: ${getTypeForArg(arg)}`;
|
|
20680
|
-
}).join("; ");
|
|
20681
|
-
const argsArray = func.args.map((arg) => {
|
|
20682
|
-
const argName = toCamelCase7(arg.name);
|
|
20683
|
-
return generateClarityConversion(argName, arg);
|
|
20684
|
-
}).join(", ");
|
|
20685
|
-
const objectAccess = func.args.map((arg) => {
|
|
20686
|
-
const camelName = toCamelCase7(arg.name);
|
|
20687
|
-
return `args[0].${camelName}`;
|
|
20688
|
-
}).join(", ");
|
|
20689
|
-
const positionTypes = func.args.map((arg) => getTypeForArg(arg)).join(", ");
|
|
20690
|
-
return `${methodName}(...args: [{ ${argsTypes} }] | [${positionTypes}]) {
|
|
20691
|
-
const [${argsList}] = args.length === 1 && typeof args[0] === 'object' && args[0] !== null
|
|
20692
|
-
? [${objectAccess}]
|
|
20693
|
-
: args as [${positionTypes}]
|
|
20694
|
-
|
|
20695
|
-
return {
|
|
20696
|
-
contractAddress: '${address}',
|
|
20697
|
-
contractName: '${contractName}',
|
|
20698
|
-
functionName: '${func.name}',
|
|
20699
|
-
functionArgs: [${argsArray}]
|
|
20700
|
-
}
|
|
20701
|
-
}`;
|
|
20702
|
-
}
|
|
20703
|
-
function generateMapsObject(maps, address, contractName) {
|
|
20704
|
-
if (!maps || maps.length === 0) {
|
|
20705
|
-
return "";
|
|
20706
|
-
}
|
|
20707
|
-
const mapMethods = maps.map((map) => {
|
|
20708
|
-
const methodName = toCamelCase7(map.name);
|
|
20709
|
-
const keyType = getTypeForArg({ type: map.key });
|
|
20710
|
-
const valueType = getTypeForArg({ type: map.value });
|
|
20711
|
-
const keyConversion = generateMapKeyConversion(map.key);
|
|
20712
|
-
return `${methodName}: {
|
|
20713
|
-
async get(key: ${keyType}, options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType} | null> {
|
|
20714
|
-
try {
|
|
20715
|
-
const { cvToJSON, serializeCV } = await import('@secondlayer/stacks/clarity');
|
|
20716
|
-
const baseUrl = getApiUrl('${address}', options?.network);
|
|
20717
|
-
const mapKey = ${keyConversion};
|
|
20718
|
-
const keyHex = serializeCV(mapKey).toString('hex');
|
|
20719
|
-
|
|
20720
|
-
const response = await fetch(
|
|
20721
|
-
\`\${baseUrl}/v2/map_entry/${address}/${contractName}/${map.name}\`,
|
|
20722
|
-
{
|
|
20723
|
-
method: 'POST',
|
|
20724
|
-
headers: { 'Content-Type': 'application/json' },
|
|
20725
|
-
body: JSON.stringify(keyHex)
|
|
20726
|
-
}
|
|
20727
|
-
);
|
|
20728
|
-
|
|
20729
|
-
if (!response.ok) {
|
|
20730
|
-
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
20731
|
-
}
|
|
20732
|
-
|
|
20733
|
-
const result = await response.json();
|
|
20734
|
-
if (!result.data || result.data === '0x09') {
|
|
20735
|
-
return null; // none value
|
|
20736
|
-
}
|
|
20737
|
-
|
|
20738
|
-
const { deserializeCV } = await import('@secondlayer/stacks/clarity');
|
|
20739
|
-
const cv = deserializeCV(result.data);
|
|
20740
|
-
const parsed = cvToJSON(cv);
|
|
20741
|
-
// Unwrap the (some ...) wrapper
|
|
20742
|
-
return parsed.value?.value ?? parsed.value ?? null;
|
|
20743
|
-
} catch (error) {
|
|
20744
|
-
if (error instanceof Error) {
|
|
20745
|
-
throw new Error(\`Map access failed for '${map.name}': \${error.message}\`);
|
|
20746
|
-
}
|
|
20747
|
-
throw error;
|
|
20748
|
-
}
|
|
20749
|
-
},
|
|
20750
|
-
keyType: ${JSON.stringify(map.key)} as const,
|
|
20751
|
-
valueType: ${JSON.stringify(map.value)} as const
|
|
20752
|
-
}`;
|
|
20753
|
-
});
|
|
20754
|
-
return `maps: {
|
|
20755
|
-
${mapMethods.join(`,
|
|
20756
|
-
|
|
20757
|
-
`)}
|
|
20758
|
-
}`;
|
|
20759
|
-
}
|
|
20760
|
-
function generateVarsObject(variables, address, contractName) {
|
|
20761
|
-
if (!variables || variables.length === 0) {
|
|
20762
|
-
return "";
|
|
20763
|
-
}
|
|
20764
|
-
const dataVars = variables.filter((v) => v.access === "variable");
|
|
20765
|
-
if (dataVars.length === 0) {
|
|
20766
|
-
return "";
|
|
20767
|
-
}
|
|
20768
|
-
const varMethods = dataVars.map((variable) => {
|
|
20769
|
-
const methodName = toCamelCase7(variable.name);
|
|
20770
|
-
const valueType = getTypeForArg({ type: variable.type });
|
|
20771
|
-
return `${methodName}: {
|
|
20772
|
-
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
20773
|
-
try {
|
|
20774
|
-
const { cvToJSON, deserializeCV } = await import('@secondlayer/stacks/clarity');
|
|
20775
|
-
const baseUrl = getApiUrl('${address}', options?.network);
|
|
20776
|
-
|
|
20777
|
-
const response = await fetch(
|
|
20778
|
-
\`\${baseUrl}/v2/data_var/${address}/${contractName}/${variable.name}?proof=0\`
|
|
20779
|
-
);
|
|
20780
|
-
|
|
20781
|
-
if (!response.ok) {
|
|
20782
|
-
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
20783
|
-
}
|
|
20784
|
-
|
|
20785
|
-
const result = await response.json();
|
|
20786
|
-
const cv = deserializeCV(result.data);
|
|
20787
|
-
const parsed = cvToJSON(cv);
|
|
20788
|
-
return parsed.value ?? parsed;
|
|
20789
|
-
} catch (error) {
|
|
20790
|
-
if (error instanceof Error) {
|
|
20791
|
-
throw new Error(\`Variable access failed for '${variable.name}': \${error.message}\`);
|
|
20792
|
-
}
|
|
20793
|
-
throw error;
|
|
20794
|
-
}
|
|
20795
|
-
},
|
|
20796
|
-
type: ${JSON.stringify(variable.type)} as const
|
|
20797
|
-
}`;
|
|
20798
|
-
});
|
|
20799
|
-
return `vars: {
|
|
20800
|
-
${varMethods.join(`,
|
|
20801
|
-
|
|
20802
|
-
`)}
|
|
20803
|
-
}`;
|
|
20804
|
-
}
|
|
20805
|
-
function generateConstantsObject(variables, address, contractName) {
|
|
20806
|
-
if (!variables || variables.length === 0) {
|
|
20807
|
-
return "";
|
|
20808
|
-
}
|
|
20809
|
-
const constants = variables.filter((v) => v.access === "constant");
|
|
20810
|
-
if (constants.length === 0) {
|
|
20811
|
-
return "";
|
|
20812
|
-
}
|
|
20813
|
-
const constMethods = constants.map((constant) => {
|
|
20814
|
-
const methodName = toCamelCase7(constant.name);
|
|
20815
|
-
const valueType = getTypeForArg({ type: constant.type });
|
|
20816
|
-
return `${methodName}: {
|
|
20817
|
-
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
20818
|
-
try {
|
|
20819
|
-
const { cvToJSON, deserializeCV } = await import('@secondlayer/stacks/clarity');
|
|
20820
|
-
const baseUrl = getApiUrl('${address}', options?.network);
|
|
20821
|
-
|
|
20822
|
-
const response = await fetch(
|
|
20823
|
-
\`\${baseUrl}/v2/constant_val/${address}/${contractName}/${constant.name}?proof=0\`
|
|
20824
|
-
);
|
|
20825
|
-
|
|
20826
|
-
if (!response.ok) {
|
|
20827
|
-
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
20828
|
-
}
|
|
20829
|
-
|
|
20830
|
-
const result = await response.json();
|
|
20831
|
-
const cv = deserializeCV(result.data);
|
|
20832
|
-
const parsed = cvToJSON(cv);
|
|
20833
|
-
return parsed.value ?? parsed;
|
|
20834
|
-
} catch (error) {
|
|
20835
|
-
if (error instanceof Error) {
|
|
20836
|
-
throw new Error(\`Constant access failed for '${constant.name}': \${error.message}\`);
|
|
20837
|
-
}
|
|
20838
|
-
throw error;
|
|
20839
|
-
}
|
|
20840
|
-
},
|
|
20841
|
-
type: ${JSON.stringify(constant.type)} as const
|
|
20842
|
-
}`;
|
|
20843
|
-
});
|
|
20844
|
-
return `constants: {
|
|
20845
|
-
${constMethods.join(`,
|
|
20846
|
-
|
|
20847
|
-
`)}
|
|
20848
|
-
}`;
|
|
20308
|
+
return formatCode(buildContractInterface(contracts));
|
|
20849
20309
|
}
|
|
20850
20310
|
var init_contract = __esm(() => {
|
|
20851
|
-
init_clarity_conversion();
|
|
20852
20311
|
init_format();
|
|
20853
|
-
init_generator_helpers();
|
|
20854
|
-
init_type_mapping();
|
|
20855
20312
|
});
|
|
20856
20313
|
|
|
20857
20314
|
// src/utils/config.ts
|
|
@@ -32098,7 +31555,7 @@ __export(exports_generate, {
|
|
|
32098
31555
|
});
|
|
32099
31556
|
import path11 from "node:path";
|
|
32100
31557
|
import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
|
|
32101
|
-
import { toCamelCase as
|
|
31558
|
+
import { toCamelCase as toCamelCase4 } from "@secondlayer/stacks/clarity";
|
|
32102
31559
|
function isContractAddress(input5) {
|
|
32103
31560
|
const contractIdPattern = /^(SP|ST|SM|SN)[A-Z0-9]{38,}\.[a-zA-Z][a-zA-Z0-9-]*$/;
|
|
32104
31561
|
return contractIdPattern.test(input5);
|
|
@@ -32159,7 +31616,7 @@ async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddre
|
|
|
32159
31616
|
const apiClient = new StacksApiClient(network, apiKey);
|
|
32160
31617
|
const contractInfo = await apiClient.getContractInfo(contractId);
|
|
32161
31618
|
const abi = parseApiResponse(contractInfo);
|
|
32162
|
-
const name =
|
|
31619
|
+
const name = toCamelCase4(contractName);
|
|
32163
31620
|
contracts.push({
|
|
32164
31621
|
name,
|
|
32165
31622
|
address: contractId,
|
|
@@ -32198,7 +31655,7 @@ Examples:`));
|
|
|
32198
31655
|
No .clar files or contract addresses matched the provided inputs`));
|
|
32199
31656
|
process.exit(1);
|
|
32200
31657
|
}
|
|
32201
|
-
const apiKey = options3.apiKey || process.env.STACKS_NODE_API_KEY
|
|
31658
|
+
const apiKey = options3.apiKey || process.env.STACKS_NODE_API_KEY;
|
|
32202
31659
|
config = await buildConfigFromInputs(parsedInputs, options3.out, apiKey);
|
|
32203
31660
|
} else {
|
|
32204
31661
|
config = await loadConfig2(options3.config);
|
|
@@ -32354,7 +31811,7 @@ var {
|
|
|
32354
31811
|
// package.json
|
|
32355
31812
|
var package_default = {
|
|
32356
31813
|
name: "@secondlayer/cli",
|
|
32357
|
-
version: "8.6.
|
|
31814
|
+
version: "8.6.4",
|
|
32358
31815
|
repository: {
|
|
32359
31816
|
type: "git",
|
|
32360
31817
|
url: "git+https://github.com/ryanwaits/secondlayer.git",
|
|
@@ -32403,8 +31860,9 @@ var package_default = {
|
|
|
32403
31860
|
dependencies: {
|
|
32404
31861
|
"@inquirer/prompts": "^8.2.0",
|
|
32405
31862
|
"@secondlayer/bundler": "^0.3.7",
|
|
32406
|
-
"@secondlayer/
|
|
32407
|
-
"@secondlayer/
|
|
31863
|
+
"@secondlayer/scaffold": "^1.2.0",
|
|
31864
|
+
"@secondlayer/sdk": "^6.19.0",
|
|
31865
|
+
"@secondlayer/shared": "^6.28.1",
|
|
32408
31866
|
"@secondlayer/stacks": "^2.4.0",
|
|
32409
31867
|
"@secondlayer/subgraphs": "^3.10.0",
|
|
32410
31868
|
"@biomejs/js-api": "^0.7.0",
|
|
@@ -34635,6 +34093,7 @@ import { TRAIT_STANDARDS } from "@secondlayer/stacks/clarity";
|
|
|
34635
34093
|
|
|
34636
34094
|
// src/generators/subgraph-scaffold.ts
|
|
34637
34095
|
init_format();
|
|
34096
|
+
import { generateTraitSubgraph } from "@secondlayer/scaffold";
|
|
34638
34097
|
import { classifyContract } from "@secondlayer/stacks/clarity";
|
|
34639
34098
|
|
|
34640
34099
|
// src/generators/clarity-to-subgraph.ts
|
|
@@ -34711,7 +34170,7 @@ ${handlers}
|
|
|
34711
34170
|
}
|
|
34712
34171
|
function tokenScaffold(name, source) {
|
|
34713
34172
|
const isFt = source.type === "ft_transfer";
|
|
34714
|
-
const scope =
|
|
34173
|
+
const scope = `assetIdentifier: '${source.assetIdentifier}'`;
|
|
34715
34174
|
const cols = isFt ? ` sender: { type: 'principal' },
|
|
34716
34175
|
recipient: { type: 'principal' },
|
|
34717
34176
|
amount: { type: 'uint' },
|
|
@@ -34775,9 +34234,7 @@ ${cols || " sender: { type: 'principal' }"}
|
|
|
34775
34234
|
}
|
|
34776
34235
|
async function generateSubgraphScaffold(input2) {
|
|
34777
34236
|
if (input2.trait) {
|
|
34778
|
-
|
|
34779
|
-
const type = input2.trait === "sip-009" ? "nft_transfer" : "ft_transfer";
|
|
34780
|
-
return formatCode(tokenScaffold(name2, { type, trait: input2.trait }));
|
|
34237
|
+
return formatCode(generateTraitSubgraph({ trait: input2.trait, name: input2.subgraphName }));
|
|
34781
34238
|
}
|
|
34782
34239
|
const { contractId, abi } = input2;
|
|
34783
34240
|
if (!contractId || !abi) {
|
|
@@ -36365,7 +35822,7 @@ Examples:
|
|
|
36365
35822
|
} else {
|
|
36366
35823
|
const address = contractAddress;
|
|
36367
35824
|
const network = inferNetwork(address) ?? "mainnet";
|
|
36368
|
-
const apiKey = options2.apiKey ?? process.env.STACKS_NODE_API_KEY
|
|
35825
|
+
const apiKey = options2.apiKey ?? process.env.STACKS_NODE_API_KEY;
|
|
36369
35826
|
const client = new StacksApiClient(network, apiKey);
|
|
36370
35827
|
info(`Fetching ABI for ${address} via ${client.describeContractInfoSource()}...`);
|
|
36371
35828
|
const contractInfo = await client.getContractInfo(address);
|
|
@@ -38459,5 +37916,5 @@ registerAccountCommand(program);
|
|
|
38459
37916
|
registerKeysCommand(program);
|
|
38460
37917
|
program.parse();
|
|
38461
37918
|
|
|
38462
|
-
//# debugId=
|
|
37919
|
+
//# debugId=D852EB907B2A586864756E2164756E21
|
|
38463
37920
|
//# sourceMappingURL=cli.js.map
|