@secondlayer/cli 0.2.5 → 0.3.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 +188 -6
- package/dist/cli.js.map +4 -4
- package/dist/index.js +288 -39
- package/dist/index.js.map +8 -8
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -15702,6 +15702,8 @@ function inferReturnType(body) {
|
|
|
15702
15702
|
function parseApiResponse(apiResponse) {
|
|
15703
15703
|
try {
|
|
15704
15704
|
const functions = [];
|
|
15705
|
+
const maps = [];
|
|
15706
|
+
const variables = [];
|
|
15705
15707
|
if (apiResponse.functions) {
|
|
15706
15708
|
for (const func of apiResponse.functions) {
|
|
15707
15709
|
const access = func.access === "read_only" ? "read-only" : func.access;
|
|
@@ -15716,7 +15718,29 @@ function parseApiResponse(apiResponse) {
|
|
|
15716
15718
|
});
|
|
15717
15719
|
}
|
|
15718
15720
|
}
|
|
15719
|
-
|
|
15721
|
+
if (apiResponse.maps) {
|
|
15722
|
+
for (const map of apiResponse.maps) {
|
|
15723
|
+
maps.push({
|
|
15724
|
+
name: map.name,
|
|
15725
|
+
key: convertApiType(map.key),
|
|
15726
|
+
value: convertApiType(map.value)
|
|
15727
|
+
});
|
|
15728
|
+
}
|
|
15729
|
+
}
|
|
15730
|
+
if (apiResponse.variables) {
|
|
15731
|
+
for (const variable of apiResponse.variables) {
|
|
15732
|
+
variables.push({
|
|
15733
|
+
name: variable.name,
|
|
15734
|
+
type: convertApiType(variable.type),
|
|
15735
|
+
access: variable.access
|
|
15736
|
+
});
|
|
15737
|
+
}
|
|
15738
|
+
}
|
|
15739
|
+
return {
|
|
15740
|
+
functions,
|
|
15741
|
+
maps: maps.length > 0 ? maps : undefined,
|
|
15742
|
+
variables: variables.length > 0 ? variables : undefined
|
|
15743
|
+
};
|
|
15720
15744
|
} catch (error) {
|
|
15721
15745
|
throw new Error(`Failed to parse API response: ${error}`);
|
|
15722
15746
|
}
|
|
@@ -15816,12 +15840,18 @@ function generateContract(contract) {
|
|
|
15816
15840
|
const methods = abi.functions.filter((func) => func.access !== "private").map((func) => generateMethod(func, address, contractName)).join(`,
|
|
15817
15841
|
|
|
15818
15842
|
`);
|
|
15843
|
+
const mapsObject = generateMapsObject(abi.maps || [], address, contractName);
|
|
15844
|
+
const varsObject = generateVarsObject(abi.variables || [], address, contractName);
|
|
15845
|
+
const constantsObject = generateConstantsObject(abi.variables || [], address, contractName);
|
|
15846
|
+
const allMembers = [methods, mapsObject, varsObject, constantsObject].filter(Boolean);
|
|
15819
15847
|
const contractCode = `export const ${name} = {
|
|
15820
15848
|
address: '${address}',
|
|
15821
15849
|
contractAddress: '${address}',
|
|
15822
15850
|
contractName: '${contractName}',
|
|
15823
|
-
|
|
15824
|
-
${
|
|
15851
|
+
|
|
15852
|
+
${allMembers.join(`,
|
|
15853
|
+
|
|
15854
|
+
`)}
|
|
15825
15855
|
} as const`;
|
|
15826
15856
|
return `${abiCode}
|
|
15827
15857
|
|
|
@@ -16032,6 +16062,158 @@ function generateClarityConversion(argName, argType) {
|
|
|
16032
16062
|
}
|
|
16033
16063
|
return `${argName}`;
|
|
16034
16064
|
}
|
|
16065
|
+
function generateMapsObject(maps, address, contractName) {
|
|
16066
|
+
if (!maps || maps.length === 0) {
|
|
16067
|
+
return "";
|
|
16068
|
+
}
|
|
16069
|
+
const mapMethods = maps.map((map) => {
|
|
16070
|
+
const methodName = toCamelCase(map.name);
|
|
16071
|
+
const keyType = getTypeForArg({ type: map.key });
|
|
16072
|
+
const valueType = getTypeForArg({ type: map.value });
|
|
16073
|
+
const keyConversion = generateMapKeyConversion(map.key);
|
|
16074
|
+
return `${methodName}: {
|
|
16075
|
+
async get(key: ${keyType}, options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType} | null> {
|
|
16076
|
+
const { cvToJSON, serializeCV } = await import('@stacks/transactions');
|
|
16077
|
+
const apiUrls: Record<string, string> = {
|
|
16078
|
+
mainnet: 'https://api.hiro.so',
|
|
16079
|
+
testnet: 'https://api.testnet.hiro.so',
|
|
16080
|
+
devnet: 'http://localhost:3999'
|
|
16081
|
+
};
|
|
16082
|
+
const baseUrl = apiUrls[options?.network || 'mainnet'];
|
|
16083
|
+
const mapKey = ${keyConversion};
|
|
16084
|
+
const keyHex = serializeCV(mapKey).toString('hex');
|
|
16085
|
+
|
|
16086
|
+
const response = await fetch(
|
|
16087
|
+
\`\${baseUrl}/v2/map_entry/${address}/${contractName}/${map.name}\`,
|
|
16088
|
+
{
|
|
16089
|
+
method: 'POST',
|
|
16090
|
+
headers: { 'Content-Type': 'application/json' },
|
|
16091
|
+
body: JSON.stringify(keyHex)
|
|
16092
|
+
}
|
|
16093
|
+
);
|
|
16094
|
+
|
|
16095
|
+
if (!response.ok) {
|
|
16096
|
+
throw new Error(\`Failed to fetch map entry: \${response.statusText}\`);
|
|
16097
|
+
}
|
|
16098
|
+
|
|
16099
|
+
const result = await response.json();
|
|
16100
|
+
if (!result.data || result.data === '0x09') {
|
|
16101
|
+
return null; // none value
|
|
16102
|
+
}
|
|
16103
|
+
|
|
16104
|
+
const { deserializeCV } = await import('@stacks/transactions');
|
|
16105
|
+
const cv = deserializeCV(result.data);
|
|
16106
|
+
const parsed = cvToJSON(cv);
|
|
16107
|
+
// Unwrap the (some ...) wrapper
|
|
16108
|
+
return parsed.value?.value ?? parsed.value ?? null;
|
|
16109
|
+
},
|
|
16110
|
+
keyType: ${JSON.stringify(map.key)} as const,
|
|
16111
|
+
valueType: ${JSON.stringify(map.value)} as const
|
|
16112
|
+
}`;
|
|
16113
|
+
});
|
|
16114
|
+
return `maps: {
|
|
16115
|
+
${mapMethods.join(`,
|
|
16116
|
+
|
|
16117
|
+
`)}
|
|
16118
|
+
}`;
|
|
16119
|
+
}
|
|
16120
|
+
function generateVarsObject(variables, address, contractName) {
|
|
16121
|
+
if (!variables || variables.length === 0) {
|
|
16122
|
+
return "";
|
|
16123
|
+
}
|
|
16124
|
+
const dataVars = variables.filter((v) => v.access === "variable");
|
|
16125
|
+
if (dataVars.length === 0) {
|
|
16126
|
+
return "";
|
|
16127
|
+
}
|
|
16128
|
+
const varMethods = dataVars.map((variable) => {
|
|
16129
|
+
const methodName = toCamelCase(variable.name);
|
|
16130
|
+
const valueType = getTypeForArg({ type: variable.type });
|
|
16131
|
+
return `${methodName}: {
|
|
16132
|
+
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
16133
|
+
const { cvToJSON, deserializeCV } = await import('@stacks/transactions');
|
|
16134
|
+
const apiUrls: Record<string, string> = {
|
|
16135
|
+
mainnet: 'https://api.hiro.so',
|
|
16136
|
+
testnet: 'https://api.testnet.hiro.so',
|
|
16137
|
+
devnet: 'http://localhost:3999'
|
|
16138
|
+
};
|
|
16139
|
+
const baseUrl = apiUrls[options?.network || 'mainnet'];
|
|
16140
|
+
|
|
16141
|
+
const response = await fetch(
|
|
16142
|
+
\`\${baseUrl}/v2/data_var/${address}/${contractName}/${variable.name}?proof=0\`
|
|
16143
|
+
);
|
|
16144
|
+
|
|
16145
|
+
if (!response.ok) {
|
|
16146
|
+
throw new Error(\`Failed to fetch data var: \${response.statusText}\`);
|
|
16147
|
+
}
|
|
16148
|
+
|
|
16149
|
+
const result = await response.json();
|
|
16150
|
+
const cv = deserializeCV(result.data);
|
|
16151
|
+
const parsed = cvToJSON(cv);
|
|
16152
|
+
return parsed.value ?? parsed;
|
|
16153
|
+
},
|
|
16154
|
+
type: ${JSON.stringify(variable.type)} as const
|
|
16155
|
+
}`;
|
|
16156
|
+
});
|
|
16157
|
+
return `vars: {
|
|
16158
|
+
${varMethods.join(`,
|
|
16159
|
+
|
|
16160
|
+
`)}
|
|
16161
|
+
}`;
|
|
16162
|
+
}
|
|
16163
|
+
function generateConstantsObject(variables, address, contractName) {
|
|
16164
|
+
if (!variables || variables.length === 0) {
|
|
16165
|
+
return "";
|
|
16166
|
+
}
|
|
16167
|
+
const constants = variables.filter((v) => v.access === "constant");
|
|
16168
|
+
if (constants.length === 0) {
|
|
16169
|
+
return "";
|
|
16170
|
+
}
|
|
16171
|
+
const constMethods = constants.map((constant) => {
|
|
16172
|
+
const methodName = toCamelCase(constant.name);
|
|
16173
|
+
const valueType = getTypeForArg({ type: constant.type });
|
|
16174
|
+
return `${methodName}: {
|
|
16175
|
+
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
16176
|
+
const { cvToJSON, deserializeCV } = await import('@stacks/transactions');
|
|
16177
|
+
const apiUrls: Record<string, string> = {
|
|
16178
|
+
mainnet: 'https://api.hiro.so',
|
|
16179
|
+
testnet: 'https://api.testnet.hiro.so',
|
|
16180
|
+
devnet: 'http://localhost:3999'
|
|
16181
|
+
};
|
|
16182
|
+
const baseUrl = apiUrls[options?.network || 'mainnet'];
|
|
16183
|
+
|
|
16184
|
+
const response = await fetch(
|
|
16185
|
+
\`\${baseUrl}/v2/constant_val/${address}/${contractName}/${constant.name}?proof=0\`
|
|
16186
|
+
);
|
|
16187
|
+
|
|
16188
|
+
if (!response.ok) {
|
|
16189
|
+
throw new Error(\`Failed to fetch constant: \${response.statusText}\`);
|
|
16190
|
+
}
|
|
16191
|
+
|
|
16192
|
+
const result = await response.json();
|
|
16193
|
+
const cv = deserializeCV(result.data);
|
|
16194
|
+
const parsed = cvToJSON(cv);
|
|
16195
|
+
return parsed.value ?? parsed;
|
|
16196
|
+
},
|
|
16197
|
+
type: ${JSON.stringify(constant.type)} as const
|
|
16198
|
+
}`;
|
|
16199
|
+
});
|
|
16200
|
+
return `constants: {
|
|
16201
|
+
${constMethods.join(`,
|
|
16202
|
+
|
|
16203
|
+
`)}
|
|
16204
|
+
}`;
|
|
16205
|
+
}
|
|
16206
|
+
function generateMapKeyConversion(keyType) {
|
|
16207
|
+
if (keyType.tuple) {
|
|
16208
|
+
const fields = keyType.tuple.map((field) => {
|
|
16209
|
+
const camelFieldName = toCamelCase(field.name);
|
|
16210
|
+
const fieldConversion = generateClarityConversion(`key.${camelFieldName}`, { type: field.type });
|
|
16211
|
+
return `"${field.name}": ${fieldConversion}`;
|
|
16212
|
+
}).join(", ");
|
|
16213
|
+
return `Cl.tuple({ ${fields} })`;
|
|
16214
|
+
}
|
|
16215
|
+
return generateClarityConversion("key", { type: keyType });
|
|
16216
|
+
}
|
|
16035
16217
|
var init_contract = () => {};
|
|
16036
16218
|
|
|
16037
16219
|
// src/commands/generate.ts
|
|
@@ -16361,7 +16543,7 @@ var {
|
|
|
16361
16543
|
// package.json
|
|
16362
16544
|
var package_default = {
|
|
16363
16545
|
name: "@secondlayer/cli",
|
|
16364
|
-
version: "0.
|
|
16546
|
+
version: "0.3.0",
|
|
16365
16547
|
description: "CLI for generating type-safe contract interfaces for the Stacks blockchain",
|
|
16366
16548
|
type: "module",
|
|
16367
16549
|
bin: {
|
|
@@ -16400,7 +16582,7 @@ var package_default = {
|
|
|
16400
16582
|
author: "",
|
|
16401
16583
|
license: "MIT",
|
|
16402
16584
|
dependencies: {
|
|
16403
|
-
"@secondlayer/clarity-types": "^0.
|
|
16585
|
+
"@secondlayer/clarity-types": "^0.3.0",
|
|
16404
16586
|
"@stacks/transactions": "7.0.6",
|
|
16405
16587
|
esbuild: "^0.19.0",
|
|
16406
16588
|
prettier: "^3.1.0"
|
|
@@ -16437,5 +16619,5 @@ program.command("init").description("Initialize a new stacks.config.ts file").ac
|
|
|
16437
16619
|
});
|
|
16438
16620
|
program.parse();
|
|
16439
16621
|
|
|
16440
|
-
//# debugId=
|
|
16622
|
+
//# debugId=C23BA423D3B8E0DF64756E2164756E21
|
|
16441
16623
|
//# sourceMappingURL=cli.js.map
|