@secondlayer/cli 0.3.7 → 0.3.9
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 +161 -86
- package/dist/cli.js.map +13 -11
- package/dist/index.d.ts +5 -0
- package/dist/index.js +155 -100
- package/dist/index.js.map +12 -10
- package/dist/plugin-manager.d.ts +5 -0
- package/dist/plugin-manager.js +44 -26
- package/dist/plugin-manager.js.map +6 -4
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,11 @@ interface StacksConfig {
|
|
|
41
41
|
* Base URL for Stacks API (optional override)
|
|
42
42
|
*/
|
|
43
43
|
apiUrl?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Default deployer address for local contracts without explicit addresses
|
|
46
|
+
* Defaults to ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM (devnet default)
|
|
47
|
+
*/
|
|
48
|
+
defaultAddress?: string;
|
|
44
49
|
}
|
|
45
50
|
interface ResolvedContract {
|
|
46
51
|
name: string;
|
package/dist/index.js
CHANGED
|
@@ -15,13 +15,53 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
15
15
|
});
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
|
+
var __export = (target, all) => {
|
|
19
|
+
for (var name in all)
|
|
20
|
+
__defProp(target, name, {
|
|
21
|
+
get: all[name],
|
|
22
|
+
enumerable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
set: (newValue) => all[name] = () => newValue
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
18
28
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
29
|
|
|
30
|
+
// src/utils/format.ts
|
|
31
|
+
var exports_format = {};
|
|
32
|
+
__export(exports_format, {
|
|
33
|
+
formatCode: () => formatCode,
|
|
34
|
+
PRETTIER_OPTIONS: () => PRETTIER_OPTIONS
|
|
35
|
+
});
|
|
36
|
+
import { format } from "prettier";
|
|
37
|
+
async function formatCode(code) {
|
|
38
|
+
return format(code, PRETTIER_OPTIONS);
|
|
39
|
+
}
|
|
40
|
+
var PRETTIER_OPTIONS;
|
|
41
|
+
var init_format = __esm(() => {
|
|
42
|
+
PRETTIER_OPTIONS = {
|
|
43
|
+
parser: "typescript",
|
|
44
|
+
singleQuote: true,
|
|
45
|
+
semi: true,
|
|
46
|
+
printWidth: 100,
|
|
47
|
+
trailingComma: "es5"
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
|
|
20
51
|
// src/core/plugin-manager.ts
|
|
21
52
|
import { promises as fs } from "fs";
|
|
22
53
|
import path from "path";
|
|
23
54
|
import { validateStacksAddress } from "@stacks/transactions";
|
|
24
55
|
|
|
56
|
+
// src/types/plugin.ts
|
|
57
|
+
function isClarinetContract(c) {
|
|
58
|
+
return "_clarinetSource" in c && c._clarinetSource === true;
|
|
59
|
+
}
|
|
60
|
+
function isDirectFileContract(c) {
|
|
61
|
+
return "_directFile" in c && c._directFile === true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/core/plugin-manager.ts
|
|
25
65
|
class PluginManager {
|
|
26
66
|
plugins = [];
|
|
27
67
|
logger;
|
|
@@ -81,7 +121,7 @@ class PluginManager {
|
|
|
81
121
|
async transformContracts(contracts, _config) {
|
|
82
122
|
const processedContracts = [];
|
|
83
123
|
for (let contract of contracts) {
|
|
84
|
-
if (contract
|
|
124
|
+
if (isClarinetContract(contract) && contract.abi) {
|
|
85
125
|
const address = typeof contract.address === "string" ? contract.address : "";
|
|
86
126
|
const [contractAddress, contractName] = address.split(".");
|
|
87
127
|
const processed = {
|
|
@@ -95,7 +135,7 @@ class PluginManager {
|
|
|
95
135
|
processedContracts.push(processed);
|
|
96
136
|
continue;
|
|
97
137
|
}
|
|
98
|
-
if (contract
|
|
138
|
+
if (isDirectFileContract(contract) && contract.abi) {
|
|
99
139
|
const address = typeof contract.address === "string" ? contract.address : "";
|
|
100
140
|
const [contractAddress, contractName] = address.split(".");
|
|
101
141
|
const processed = {
|
|
@@ -281,14 +321,8 @@ ${JSON.stringify(content, null, 2)}`;
|
|
|
281
321
|
return { address, contractName };
|
|
282
322
|
},
|
|
283
323
|
formatCode: async (code) => {
|
|
284
|
-
const {
|
|
285
|
-
return
|
|
286
|
-
parser: "typescript",
|
|
287
|
-
singleQuote: true,
|
|
288
|
-
semi: true,
|
|
289
|
-
printWidth: 100,
|
|
290
|
-
trailingComma: "es5"
|
|
291
|
-
});
|
|
324
|
+
const { formatCode: formatCode2 } = await Promise.resolve().then(() => (init_format(), exports_format));
|
|
325
|
+
return formatCode2(code);
|
|
292
326
|
},
|
|
293
327
|
resolvePath: (relativePath) => {
|
|
294
328
|
return path.resolve(process.cwd(), relativePath);
|
|
@@ -315,9 +349,10 @@ ${JSON.stringify(content, null, 2)}`;
|
|
|
315
349
|
}
|
|
316
350
|
// src/plugins/clarinet/index.ts
|
|
317
351
|
import { initSimnet } from "@hirosystems/clarinet-sdk";
|
|
352
|
+
import { toCamelCase as toCamelCase3 } from "@secondlayer/clarity-types";
|
|
318
353
|
|
|
319
354
|
// src/generators/contract.ts
|
|
320
|
-
|
|
355
|
+
init_format();
|
|
321
356
|
import {
|
|
322
357
|
toCamelCase as toCamelCase2
|
|
323
358
|
} from "@secondlayer/clarity-types";
|
|
@@ -346,6 +381,9 @@ function clarityTypeToTS(type) {
|
|
|
346
381
|
return "string";
|
|
347
382
|
default: {
|
|
348
383
|
const typeStr = type;
|
|
384
|
+
if (typeStr === "none") {
|
|
385
|
+
return "null";
|
|
386
|
+
}
|
|
349
387
|
if (typeStr.includes("string") || typeStr.includes("ascii") || typeStr.includes("utf8")) {
|
|
350
388
|
return "string";
|
|
351
389
|
}
|
|
@@ -455,14 +493,7 @@ ${validationUtils}
|
|
|
455
493
|
${networkUtils}
|
|
456
494
|
|
|
457
495
|
${contractsCode}`;
|
|
458
|
-
|
|
459
|
-
parser: "typescript",
|
|
460
|
-
singleQuote: true,
|
|
461
|
-
semi: true,
|
|
462
|
-
printWidth: 100,
|
|
463
|
-
trailingComma: "es5"
|
|
464
|
-
});
|
|
465
|
-
return formatted;
|
|
496
|
+
return formatCode(code);
|
|
466
497
|
}
|
|
467
498
|
function generateContract(contract) {
|
|
468
499
|
const { name, address, contractName, abi } = contract;
|
|
@@ -692,34 +723,41 @@ function generateMapsObject(maps, address, contractName) {
|
|
|
692
723
|
const keyConversion = generateMapKeyConversion(map.key);
|
|
693
724
|
return `${methodName}: {
|
|
694
725
|
async get(key: ${keyType}, options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType} | null> {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
726
|
+
try {
|
|
727
|
+
const { cvToJSON, serializeCV } = await import('@stacks/transactions');
|
|
728
|
+
const baseUrl = getApiUrl('${address}', options?.network);
|
|
729
|
+
const mapKey = ${keyConversion};
|
|
730
|
+
const keyHex = serializeCV(mapKey).toString('hex');
|
|
731
|
+
|
|
732
|
+
const response = await fetch(
|
|
733
|
+
\`\${baseUrl}/v2/map_entry/${address}/${contractName}/${map.name}\`,
|
|
734
|
+
{
|
|
735
|
+
method: 'POST',
|
|
736
|
+
headers: { 'Content-Type': 'application/json' },
|
|
737
|
+
body: JSON.stringify(keyHex)
|
|
738
|
+
}
|
|
739
|
+
);
|
|
740
|
+
|
|
741
|
+
if (!response.ok) {
|
|
742
|
+
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
706
743
|
}
|
|
707
|
-
);
|
|
708
744
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
745
|
+
const result = await response.json();
|
|
746
|
+
if (!result.data || result.data === '0x09') {
|
|
747
|
+
return null; // none value
|
|
748
|
+
}
|
|
712
749
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
750
|
+
const { deserializeCV } = await import('@stacks/transactions');
|
|
751
|
+
const cv = deserializeCV(result.data);
|
|
752
|
+
const parsed = cvToJSON(cv);
|
|
753
|
+
// Unwrap the (some ...) wrapper
|
|
754
|
+
return parsed.value?.value ?? parsed.value ?? null;
|
|
755
|
+
} catch (error) {
|
|
756
|
+
if (error instanceof Error) {
|
|
757
|
+
throw new Error(\`Map access failed for '${map.name}': \${error.message}\`);
|
|
758
|
+
}
|
|
759
|
+
throw error;
|
|
716
760
|
}
|
|
717
|
-
|
|
718
|
-
const { deserializeCV } = await import('@stacks/transactions');
|
|
719
|
-
const cv = deserializeCV(result.data);
|
|
720
|
-
const parsed = cvToJSON(cv);
|
|
721
|
-
// Unwrap the (some ...) wrapper
|
|
722
|
-
return parsed.value?.value ?? parsed.value ?? null;
|
|
723
761
|
},
|
|
724
762
|
keyType: ${JSON.stringify(map.key)} as const,
|
|
725
763
|
valueType: ${JSON.stringify(map.value)} as const
|
|
@@ -744,21 +782,28 @@ function generateVarsObject(variables, address, contractName) {
|
|
|
744
782
|
const valueType = getTypeForArg({ type: variable.type });
|
|
745
783
|
return `${methodName}: {
|
|
746
784
|
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
747
|
-
|
|
748
|
-
|
|
785
|
+
try {
|
|
786
|
+
const { cvToJSON, deserializeCV } = await import('@stacks/transactions');
|
|
787
|
+
const baseUrl = getApiUrl('${address}', options?.network);
|
|
749
788
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
789
|
+
const response = await fetch(
|
|
790
|
+
\`\${baseUrl}/v2/data_var/${address}/${contractName}/${variable.name}?proof=0\`
|
|
791
|
+
);
|
|
753
792
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
793
|
+
if (!response.ok) {
|
|
794
|
+
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
795
|
+
}
|
|
757
796
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
797
|
+
const result = await response.json();
|
|
798
|
+
const cv = deserializeCV(result.data);
|
|
799
|
+
const parsed = cvToJSON(cv);
|
|
800
|
+
return parsed.value ?? parsed;
|
|
801
|
+
} catch (error) {
|
|
802
|
+
if (error instanceof Error) {
|
|
803
|
+
throw new Error(\`Variable access failed for '${variable.name}': \${error.message}\`);
|
|
804
|
+
}
|
|
805
|
+
throw error;
|
|
806
|
+
}
|
|
762
807
|
},
|
|
763
808
|
type: ${JSON.stringify(variable.type)} as const
|
|
764
809
|
}`;
|
|
@@ -782,21 +827,28 @@ function generateConstantsObject(variables, address, contractName) {
|
|
|
782
827
|
const valueType = getTypeForArg({ type: constant.type });
|
|
783
828
|
return `${methodName}: {
|
|
784
829
|
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
785
|
-
|
|
786
|
-
|
|
830
|
+
try {
|
|
831
|
+
const { cvToJSON, deserializeCV } = await import('@stacks/transactions');
|
|
832
|
+
const baseUrl = getApiUrl('${address}', options?.network);
|
|
787
833
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
834
|
+
const response = await fetch(
|
|
835
|
+
\`\${baseUrl}/v2/constant_val/${address}/${contractName}/${constant.name}?proof=0\`
|
|
836
|
+
);
|
|
791
837
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
838
|
+
if (!response.ok) {
|
|
839
|
+
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
840
|
+
}
|
|
795
841
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
842
|
+
const result = await response.json();
|
|
843
|
+
const cv = deserializeCV(result.data);
|
|
844
|
+
const parsed = cvToJSON(cv);
|
|
845
|
+
return parsed.value ?? parsed;
|
|
846
|
+
} catch (error) {
|
|
847
|
+
if (error instanceof Error) {
|
|
848
|
+
throw new Error(\`Constant access failed for '${constant.name}': \${error.message}\`);
|
|
849
|
+
}
|
|
850
|
+
throw error;
|
|
851
|
+
}
|
|
800
852
|
},
|
|
801
853
|
type: ${JSON.stringify(constant.type)} as const
|
|
802
854
|
}`;
|
|
@@ -820,9 +872,6 @@ function generateMapKeyConversion(keyType) {
|
|
|
820
872
|
}
|
|
821
873
|
|
|
822
874
|
// src/plugins/clarinet/index.ts
|
|
823
|
-
function toCamelCase3(str) {
|
|
824
|
-
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/-([A-Z])/g, (_, letter) => letter).replace(/-(\d)/g, (_, digit) => digit).replace(/-/g, "").replace(/^\d/, "_$&");
|
|
825
|
-
}
|
|
826
875
|
function sanitizeContractName(name) {
|
|
827
876
|
return toCamelCase3(name);
|
|
828
877
|
}
|
|
@@ -1279,7 +1328,7 @@ ${indentedHelpersCode}
|
|
|
1279
1328
|
});
|
|
1280
1329
|
}
|
|
1281
1330
|
// src/plugins/react/provider/index.ts
|
|
1282
|
-
|
|
1331
|
+
init_format();
|
|
1283
1332
|
async function generateProvider() {
|
|
1284
1333
|
const code = `/**
|
|
1285
1334
|
* Generated Stacks React Provider
|
|
@@ -1367,18 +1416,11 @@ export function useStacksConfig(): StacksReactConfig {
|
|
|
1367
1416
|
|
|
1368
1417
|
return context
|
|
1369
1418
|
}`;
|
|
1370
|
-
|
|
1371
|
-
parser: "typescript",
|
|
1372
|
-
singleQuote: true,
|
|
1373
|
-
semi: false,
|
|
1374
|
-
printWidth: 100,
|
|
1375
|
-
trailingComma: "es5"
|
|
1376
|
-
});
|
|
1377
|
-
return formatted;
|
|
1419
|
+
return formatCode(code);
|
|
1378
1420
|
}
|
|
1379
1421
|
|
|
1380
1422
|
// src/plugins/react/generators/generic.ts
|
|
1381
|
-
|
|
1423
|
+
init_format();
|
|
1382
1424
|
var GENERIC_HOOKS = [
|
|
1383
1425
|
"useAccount",
|
|
1384
1426
|
"useConnect",
|
|
@@ -1399,10 +1441,37 @@ async function generateGenericHooks(excludeList = []) {
|
|
|
1399
1441
|
const imports = `import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
1400
1442
|
import { useState, useCallback } from 'react'
|
|
1401
1443
|
import { useStacksConfig } from './provider'
|
|
1402
|
-
import { connect, disconnect, isConnected, request, openContractCall as stacksOpenContractCall } from '@stacks/connect'
|
|
1444
|
+
import { connect, disconnect, isConnected, request, openContractCall as stacksOpenContractCall, openSTXTransfer, openSignatureRequestPopup, openContractDeploy } from '@stacks/connect'
|
|
1403
1445
|
import { Cl, validateStacksAddress } from '@stacks/transactions'
|
|
1404
1446
|
import type { PostCondition } from '@stacks/transactions'
|
|
1405
|
-
import type { ExtractFunctionArgs, ExtractFunctionNames, ClarityContract } from '@secondlayer/clarity-types'
|
|
1447
|
+
import type { ExtractFunctionArgs, ExtractFunctionNames, ClarityContract } from '@secondlayer/clarity-types'
|
|
1448
|
+
|
|
1449
|
+
const API_URLS: Record<string, string> = {
|
|
1450
|
+
mainnet: 'https://api.hiro.so',
|
|
1451
|
+
testnet: 'https://api.testnet.hiro.so',
|
|
1452
|
+
devnet: 'http://localhost:3999'
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
async function fetchTransaction({ txId, network, apiUrl }: { txId: string; network?: string; apiUrl?: string }): Promise<any> {
|
|
1456
|
+
const baseUrl = apiUrl || API_URLS[network || 'mainnet']
|
|
1457
|
+
const response = await fetch(\`\${baseUrl}/extended/v1/tx/\${txId}\`)
|
|
1458
|
+
if (!response.ok) throw new Error(\`Failed to fetch transaction: \${response.statusText}\`)
|
|
1459
|
+
return response.json()
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
async function fetchBlock({ height, network, apiUrl }: { height: number; network?: string; apiUrl?: string }): Promise<any> {
|
|
1463
|
+
const baseUrl = apiUrl || API_URLS[network || 'mainnet']
|
|
1464
|
+
const response = await fetch(\`\${baseUrl}/extended/v1/block/by_height/\${height}\`)
|
|
1465
|
+
if (!response.ok) throw new Error(\`Failed to fetch block: \${response.statusText}\`)
|
|
1466
|
+
return response.json()
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
async function fetchAccountTransactions({ address, network, apiUrl }: { address: string; network?: string; apiUrl?: string }): Promise<any> {
|
|
1470
|
+
const baseUrl = apiUrl || API_URLS[network || 'mainnet']
|
|
1471
|
+
const response = await fetch(\`\${baseUrl}/extended/v1/address/\${address}/transactions\`)
|
|
1472
|
+
if (!response.ok) throw new Error(\`Failed to fetch transactions: \${response.statusText}\`)
|
|
1473
|
+
return response.json()
|
|
1474
|
+
}`;
|
|
1406
1475
|
const header = `/**
|
|
1407
1476
|
* Generated generic Stacks React hooks
|
|
1408
1477
|
* DO NOT EDIT MANUALLY
|
|
@@ -1415,14 +1484,7 @@ import type { ExtractFunctionArgs, ExtractFunctionNames, ClarityContract } from
|
|
|
1415
1484
|
${header}
|
|
1416
1485
|
|
|
1417
1486
|
${hooksCode}`;
|
|
1418
|
-
|
|
1419
|
-
parser: "typescript",
|
|
1420
|
-
singleQuote: true,
|
|
1421
|
-
semi: false,
|
|
1422
|
-
printWidth: 100,
|
|
1423
|
-
trailingComma: "es5"
|
|
1424
|
-
});
|
|
1425
|
-
return formatted;
|
|
1487
|
+
return formatCode(code);
|
|
1426
1488
|
}
|
|
1427
1489
|
function generateGenericHook(hookName) {
|
|
1428
1490
|
switch (hookName) {
|
|
@@ -2187,7 +2249,7 @@ function generateGenericHook(hookName) {
|
|
|
2187
2249
|
}
|
|
2188
2250
|
|
|
2189
2251
|
// src/plugins/react/generators/contract.ts
|
|
2190
|
-
|
|
2252
|
+
init_format();
|
|
2191
2253
|
|
|
2192
2254
|
// src/plugins/react/generators/utils.ts
|
|
2193
2255
|
import { toCamelCase as toCamelCase5 } from "@secondlayer/clarity-types";
|
|
@@ -2253,14 +2315,7 @@ import { ${contracts.map((c) => c.name).join(", ")} } from './contracts'`;
|
|
|
2253
2315
|
${header}
|
|
2254
2316
|
|
|
2255
2317
|
${hooksCode}`;
|
|
2256
|
-
|
|
2257
|
-
parser: "typescript",
|
|
2258
|
-
singleQuote: true,
|
|
2259
|
-
semi: false,
|
|
2260
|
-
printWidth: 100,
|
|
2261
|
-
trailingComma: "es5"
|
|
2262
|
-
});
|
|
2263
|
-
return formatted;
|
|
2318
|
+
return formatCode(code);
|
|
2264
2319
|
}
|
|
2265
2320
|
function generateContractHookMethods(contract, excludeList) {
|
|
2266
2321
|
const { abi, name, address, contractName } = contract;
|
|
@@ -2924,5 +2979,5 @@ export {
|
|
|
2924
2979
|
PluginManager
|
|
2925
2980
|
};
|
|
2926
2981
|
|
|
2927
|
-
//# debugId=
|
|
2982
|
+
//# debugId=FE7B5594AE67250064756E2164756E21
|
|
2928
2983
|
//# sourceMappingURL=index.js.map
|