@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 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
- return { functions };
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
- ${methods}
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.2.5",
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.2.2",
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=C236EDEA54ABBFA664756E2164756E21
16622
+ //# debugId=C23BA423D3B8E0DF64756E2164756E21
16441
16623
  //# sourceMappingURL=cli.js.map