@secondlayer/cli 0.3.8 → 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 +158 -86
- package/dist/cli.js.map +12 -10
- package/dist/index.d.ts +5 -0
- package/dist/index.js +152 -100
- package/dist/index.js.map +11 -9
- 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";
|
|
@@ -458,14 +493,7 @@ ${validationUtils}
|
|
|
458
493
|
${networkUtils}
|
|
459
494
|
|
|
460
495
|
${contractsCode}`;
|
|
461
|
-
|
|
462
|
-
parser: "typescript",
|
|
463
|
-
singleQuote: true,
|
|
464
|
-
semi: true,
|
|
465
|
-
printWidth: 100,
|
|
466
|
-
trailingComma: "es5"
|
|
467
|
-
});
|
|
468
|
-
return formatted;
|
|
496
|
+
return formatCode(code);
|
|
469
497
|
}
|
|
470
498
|
function generateContract(contract) {
|
|
471
499
|
const { name, address, contractName, abi } = contract;
|
|
@@ -695,34 +723,41 @@ function generateMapsObject(maps, address, contractName) {
|
|
|
695
723
|
const keyConversion = generateMapKeyConversion(map.key);
|
|
696
724
|
return `${methodName}: {
|
|
697
725
|
async get(key: ${keyType}, options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType} | null> {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
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}\`);
|
|
709
743
|
}
|
|
710
|
-
);
|
|
711
744
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
745
|
+
const result = await response.json();
|
|
746
|
+
if (!result.data || result.data === '0x09') {
|
|
747
|
+
return null; // none value
|
|
748
|
+
}
|
|
715
749
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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;
|
|
719
760
|
}
|
|
720
|
-
|
|
721
|
-
const { deserializeCV } = await import('@stacks/transactions');
|
|
722
|
-
const cv = deserializeCV(result.data);
|
|
723
|
-
const parsed = cvToJSON(cv);
|
|
724
|
-
// Unwrap the (some ...) wrapper
|
|
725
|
-
return parsed.value?.value ?? parsed.value ?? null;
|
|
726
761
|
},
|
|
727
762
|
keyType: ${JSON.stringify(map.key)} as const,
|
|
728
763
|
valueType: ${JSON.stringify(map.value)} as const
|
|
@@ -747,21 +782,28 @@ function generateVarsObject(variables, address, contractName) {
|
|
|
747
782
|
const valueType = getTypeForArg({ type: variable.type });
|
|
748
783
|
return `${methodName}: {
|
|
749
784
|
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
750
|
-
|
|
751
|
-
|
|
785
|
+
try {
|
|
786
|
+
const { cvToJSON, deserializeCV } = await import('@stacks/transactions');
|
|
787
|
+
const baseUrl = getApiUrl('${address}', options?.network);
|
|
752
788
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
789
|
+
const response = await fetch(
|
|
790
|
+
\`\${baseUrl}/v2/data_var/${address}/${contractName}/${variable.name}?proof=0\`
|
|
791
|
+
);
|
|
756
792
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
793
|
+
if (!response.ok) {
|
|
794
|
+
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
795
|
+
}
|
|
760
796
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
+
}
|
|
765
807
|
},
|
|
766
808
|
type: ${JSON.stringify(variable.type)} as const
|
|
767
809
|
}`;
|
|
@@ -785,21 +827,28 @@ function generateConstantsObject(variables, address, contractName) {
|
|
|
785
827
|
const valueType = getTypeForArg({ type: constant.type });
|
|
786
828
|
return `${methodName}: {
|
|
787
829
|
async get(options?: { network?: 'mainnet' | 'testnet' | 'devnet' }): Promise<${valueType}> {
|
|
788
|
-
|
|
789
|
-
|
|
830
|
+
try {
|
|
831
|
+
const { cvToJSON, deserializeCV } = await import('@stacks/transactions');
|
|
832
|
+
const baseUrl = getApiUrl('${address}', options?.network);
|
|
790
833
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
834
|
+
const response = await fetch(
|
|
835
|
+
\`\${baseUrl}/v2/constant_val/${address}/${contractName}/${constant.name}?proof=0\`
|
|
836
|
+
);
|
|
794
837
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
838
|
+
if (!response.ok) {
|
|
839
|
+
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
840
|
+
}
|
|
798
841
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
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
|
+
}
|
|
803
852
|
},
|
|
804
853
|
type: ${JSON.stringify(constant.type)} as const
|
|
805
854
|
}`;
|
|
@@ -823,9 +872,6 @@ function generateMapKeyConversion(keyType) {
|
|
|
823
872
|
}
|
|
824
873
|
|
|
825
874
|
// src/plugins/clarinet/index.ts
|
|
826
|
-
function toCamelCase3(str) {
|
|
827
|
-
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/-([A-Z])/g, (_, letter) => letter).replace(/-(\d)/g, (_, digit) => digit).replace(/-/g, "").replace(/^\d/, "_$&");
|
|
828
|
-
}
|
|
829
875
|
function sanitizeContractName(name) {
|
|
830
876
|
return toCamelCase3(name);
|
|
831
877
|
}
|
|
@@ -1282,7 +1328,7 @@ ${indentedHelpersCode}
|
|
|
1282
1328
|
});
|
|
1283
1329
|
}
|
|
1284
1330
|
// src/plugins/react/provider/index.ts
|
|
1285
|
-
|
|
1331
|
+
init_format();
|
|
1286
1332
|
async function generateProvider() {
|
|
1287
1333
|
const code = `/**
|
|
1288
1334
|
* Generated Stacks React Provider
|
|
@@ -1370,18 +1416,11 @@ export function useStacksConfig(): StacksReactConfig {
|
|
|
1370
1416
|
|
|
1371
1417
|
return context
|
|
1372
1418
|
}`;
|
|
1373
|
-
|
|
1374
|
-
parser: "typescript",
|
|
1375
|
-
singleQuote: true,
|
|
1376
|
-
semi: false,
|
|
1377
|
-
printWidth: 100,
|
|
1378
|
-
trailingComma: "es5"
|
|
1379
|
-
});
|
|
1380
|
-
return formatted;
|
|
1419
|
+
return formatCode(code);
|
|
1381
1420
|
}
|
|
1382
1421
|
|
|
1383
1422
|
// src/plugins/react/generators/generic.ts
|
|
1384
|
-
|
|
1423
|
+
init_format();
|
|
1385
1424
|
var GENERIC_HOOKS = [
|
|
1386
1425
|
"useAccount",
|
|
1387
1426
|
"useConnect",
|
|
@@ -1402,10 +1441,37 @@ async function generateGenericHooks(excludeList = []) {
|
|
|
1402
1441
|
const imports = `import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
1403
1442
|
import { useState, useCallback } from 'react'
|
|
1404
1443
|
import { useStacksConfig } from './provider'
|
|
1405
|
-
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'
|
|
1406
1445
|
import { Cl, validateStacksAddress } from '@stacks/transactions'
|
|
1407
1446
|
import type { PostCondition } from '@stacks/transactions'
|
|
1408
|
-
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
|
+
}`;
|
|
1409
1475
|
const header = `/**
|
|
1410
1476
|
* Generated generic Stacks React hooks
|
|
1411
1477
|
* DO NOT EDIT MANUALLY
|
|
@@ -1418,14 +1484,7 @@ import type { ExtractFunctionArgs, ExtractFunctionNames, ClarityContract } from
|
|
|
1418
1484
|
${header}
|
|
1419
1485
|
|
|
1420
1486
|
${hooksCode}`;
|
|
1421
|
-
|
|
1422
|
-
parser: "typescript",
|
|
1423
|
-
singleQuote: true,
|
|
1424
|
-
semi: false,
|
|
1425
|
-
printWidth: 100,
|
|
1426
|
-
trailingComma: "es5"
|
|
1427
|
-
});
|
|
1428
|
-
return formatted;
|
|
1487
|
+
return formatCode(code);
|
|
1429
1488
|
}
|
|
1430
1489
|
function generateGenericHook(hookName) {
|
|
1431
1490
|
switch (hookName) {
|
|
@@ -2190,7 +2249,7 @@ function generateGenericHook(hookName) {
|
|
|
2190
2249
|
}
|
|
2191
2250
|
|
|
2192
2251
|
// src/plugins/react/generators/contract.ts
|
|
2193
|
-
|
|
2252
|
+
init_format();
|
|
2194
2253
|
|
|
2195
2254
|
// src/plugins/react/generators/utils.ts
|
|
2196
2255
|
import { toCamelCase as toCamelCase5 } from "@secondlayer/clarity-types";
|
|
@@ -2256,14 +2315,7 @@ import { ${contracts.map((c) => c.name).join(", ")} } from './contracts'`;
|
|
|
2256
2315
|
${header}
|
|
2257
2316
|
|
|
2258
2317
|
${hooksCode}`;
|
|
2259
|
-
|
|
2260
|
-
parser: "typescript",
|
|
2261
|
-
singleQuote: true,
|
|
2262
|
-
semi: false,
|
|
2263
|
-
printWidth: 100,
|
|
2264
|
-
trailingComma: "es5"
|
|
2265
|
-
});
|
|
2266
|
-
return formatted;
|
|
2318
|
+
return formatCode(code);
|
|
2267
2319
|
}
|
|
2268
2320
|
function generateContractHookMethods(contract, excludeList) {
|
|
2269
2321
|
const { abi, name, address, contractName } = contract;
|
|
@@ -2927,5 +2979,5 @@ export {
|
|
|
2927
2979
|
PluginManager
|
|
2928
2980
|
};
|
|
2929
2981
|
|
|
2930
|
-
//# debugId=
|
|
2982
|
+
//# debugId=FE7B5594AE67250064756E2164756E21
|
|
2931
2983
|
//# sourceMappingURL=index.js.map
|