@secondlayer/cli 8.14.2 → 9.0.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/README.md +12 -8
- package/dist/cli.js +103 -7
- package/dist/cli.js.map +3 -3
- package/dist/plugins/index.d.ts +6 -19
- package/dist/plugins/index.js +97 -269
- package/dist/plugins/index.js.map +12 -12
- package/package.json +5 -5
package/dist/plugins/index.d.ts
CHANGED
|
@@ -287,6 +287,11 @@ interface ClarinetPluginOptions {
|
|
|
287
287
|
include?: string[];
|
|
288
288
|
/** Exclude specific contracts */
|
|
289
289
|
exclude?: string[];
|
|
290
|
+
/**
|
|
291
|
+
* Also generate interfaces for dependency contracts declared under
|
|
292
|
+
* `[project.requirements]` in Clarinet.toml (default: true).
|
|
293
|
+
*/
|
|
294
|
+
includeRequirements?: boolean;
|
|
290
295
|
/** Enable debug output */
|
|
291
296
|
debug?: boolean;
|
|
292
297
|
}
|
|
@@ -298,24 +303,6 @@ declare const clarinet: PluginFactory<ClarinetPluginOptions>;
|
|
|
298
303
|
* Utility function to check if a Clarinet project exists
|
|
299
304
|
*/
|
|
300
305
|
declare function hasClarinetProject(path?: string): Promise<boolean>;
|
|
301
|
-
interface ActionsPluginOptions {
|
|
302
|
-
/** Include only specific contracts */
|
|
303
|
-
include?: string[];
|
|
304
|
-
/** Exclude specific contracts */
|
|
305
|
-
exclude?: string[];
|
|
306
|
-
/** Include only specific functions */
|
|
307
|
-
includeFunctions?: string[];
|
|
308
|
-
/** Exclude specific functions */
|
|
309
|
-
excludeFunctions?: string[];
|
|
310
|
-
/** Enable debug output */
|
|
311
|
-
debug?: boolean;
|
|
312
|
-
/** Environment variable name for default sender key (default: "STX_SENDER_KEY") */
|
|
313
|
-
senderKeyEnv?: string;
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Actions plugin factory
|
|
317
|
-
*/
|
|
318
|
-
declare const actions: PluginFactory<ActionsPluginOptions>;
|
|
319
306
|
/**
|
|
320
307
|
* React plugin configuration options
|
|
321
308
|
*/
|
|
@@ -361,4 +348,4 @@ declare function filterByOptions<T extends {
|
|
|
361
348
|
* Utility function to create a simple plugin
|
|
362
349
|
*/
|
|
363
350
|
declare function createPlugin(name: string, version: string, implementation: Partial<SecondLayerPlugin>): SecondLayerPlugin;
|
|
364
|
-
export { testing, react, hasClarinetProject, filterByOptions, createPlugin, clarinet,
|
|
351
|
+
export { testing, react, hasClarinetProject, filterByOptions, createPlugin, clarinet, TestingPluginOptions, SecondLayerPlugin, ReactPluginOptions, PluginUtils, PluginOptions, PluginManager, PluginFactory, PluginContext, Logger, GenerateContext, ClarinetPluginOptions, BasePluginOptions };
|
package/dist/plugins/index.js
CHANGED
|
@@ -558,25 +558,56 @@ init_plugin_manager();
|
|
|
558
558
|
init_contract();
|
|
559
559
|
import { initSimnet } from "@hirosystems/clarinet-sdk";
|
|
560
560
|
import { toCamelCase as toCamelCase2 } from "@secondlayer/stacks/clarity";
|
|
561
|
+
|
|
562
|
+
// src/utils/constants.ts
|
|
563
|
+
var DEFAULT_SENDER_ADDRESS = "SP000000000000000000002Q6VF78";
|
|
564
|
+
// src/plugins/shared.ts
|
|
565
|
+
function matchesContractFilters(name, options) {
|
|
566
|
+
if (options.include && !options.include.includes(name)) {
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
if (options.exclude?.includes(name)) {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/plugins/clarinet/index.ts
|
|
561
576
|
function sanitizeContractName(name) {
|
|
562
577
|
return toCamelCase2(name);
|
|
563
578
|
}
|
|
564
|
-
async function
|
|
565
|
-
const { address, contractName } = parseContractId(contractId);
|
|
579
|
+
async function readManifestInfo(manifestPath) {
|
|
566
580
|
try {
|
|
567
581
|
const { promises: fs2 } = await import("node:fs");
|
|
568
582
|
const tomlContent = await fs2.readFile(manifestPath, "utf-8");
|
|
583
|
+
const projectContracts = new Set;
|
|
569
584
|
const contractSectionRegex = /^\[contracts\.([^\]]+)\]/gm;
|
|
570
|
-
const userContracts = new Set;
|
|
571
585
|
let match = contractSectionRegex.exec(tomlContent);
|
|
572
586
|
while (match !== null) {
|
|
573
|
-
|
|
587
|
+
projectContracts.add(match[1]);
|
|
574
588
|
match = contractSectionRegex.exec(tomlContent);
|
|
575
589
|
}
|
|
576
|
-
|
|
577
|
-
|
|
590
|
+
const requirementIds = new Set;
|
|
591
|
+
const requirementRegex = /contract_id\s*=\s*["']([^"']+)["']/g;
|
|
592
|
+
match = requirementRegex.exec(tomlContent);
|
|
593
|
+
while (match !== null) {
|
|
594
|
+
requirementIds.add(match[1]);
|
|
595
|
+
match = requirementRegex.exec(tomlContent);
|
|
578
596
|
}
|
|
579
|
-
|
|
597
|
+
return { projectContracts, requirementIds };
|
|
598
|
+
} catch {
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
function classifyContract(contractId, manifest) {
|
|
603
|
+
const { address, contractName } = parseContractId(contractId);
|
|
604
|
+
if (manifest) {
|
|
605
|
+
if (manifest.projectContracts.has(contractName))
|
|
606
|
+
return "project";
|
|
607
|
+
if (manifest.requirementIds.has(contractId))
|
|
608
|
+
return "requirement";
|
|
609
|
+
return "system";
|
|
610
|
+
}
|
|
580
611
|
const systemContractPatterns = [
|
|
581
612
|
/^pox-\d+$/,
|
|
582
613
|
/^bns$/,
|
|
@@ -584,16 +615,16 @@ async function isUserDefinedContract(contractId, manifestPath) {
|
|
|
584
615
|
/^lockup$/
|
|
585
616
|
];
|
|
586
617
|
if (systemContractPatterns.some((pattern) => pattern.test(contractName))) {
|
|
587
|
-
return
|
|
618
|
+
return "system";
|
|
588
619
|
}
|
|
589
620
|
const systemAddresses = [
|
|
590
|
-
|
|
621
|
+
DEFAULT_SENDER_ADDRESS,
|
|
591
622
|
"ST000000000000000000002AMW42H"
|
|
592
623
|
];
|
|
593
624
|
if (systemAddresses.includes(address)) {
|
|
594
|
-
return
|
|
625
|
+
return "system";
|
|
595
626
|
}
|
|
596
|
-
return
|
|
627
|
+
return "project";
|
|
597
628
|
}
|
|
598
629
|
var clarinet = (options = {}) => {
|
|
599
630
|
const manifestPath = options.path || "./Clarinet.toml";
|
|
@@ -606,18 +637,18 @@ var clarinet = (options = {}) => {
|
|
|
606
637
|
simnet = await initSimnet(manifestPath);
|
|
607
638
|
const contractInterfaces = simnet.getContractsInterfaces();
|
|
608
639
|
const contracts = [];
|
|
640
|
+
const manifest = await readManifestInfo(manifestPath);
|
|
641
|
+
const includeRequirements = options.includeRequirements ?? true;
|
|
609
642
|
for (const [contractId, abi] of contractInterfaces) {
|
|
610
643
|
const { contractName } = parseContractId(contractId);
|
|
611
|
-
|
|
644
|
+
const kind = classifyContract(contractId, manifest);
|
|
645
|
+
if (kind === "system" || kind === "requirement" && !includeRequirements) {
|
|
612
646
|
if (options.debug) {
|
|
613
|
-
console.log(`\uD83D\uDEAB Skipping
|
|
647
|
+
console.log(`\uD83D\uDEAB Skipping ${kind} contract: ${contractId}`);
|
|
614
648
|
}
|
|
615
649
|
continue;
|
|
616
650
|
}
|
|
617
|
-
if (
|
|
618
|
-
continue;
|
|
619
|
-
}
|
|
620
|
-
if (options.exclude?.includes(contractName)) {
|
|
651
|
+
if (!matchesContractFilters(contractName, options)) {
|
|
621
652
|
continue;
|
|
622
653
|
}
|
|
623
654
|
const sanitizedName = sanitizeContractName(contractName);
|
|
@@ -637,8 +668,10 @@ var clarinet = (options = {}) => {
|
|
|
637
668
|
};
|
|
638
669
|
} catch (error) {
|
|
639
670
|
const err = error;
|
|
640
|
-
if (
|
|
641
|
-
console.warn(`⚠️ Clarinet plugin failed to load contracts: ${err.message}`);
|
|
671
|
+
if (await hasClarinetProject(manifestPath)) {
|
|
672
|
+
console.warn(`⚠️ Clarinet plugin: found ${manifestPath} but failed to load contracts: ${err.message}`);
|
|
673
|
+
} else if (options.debug) {
|
|
674
|
+
console.warn(`⚠️ Clarinet plugin: no manifest at ${manifestPath}, skipping`);
|
|
642
675
|
}
|
|
643
676
|
return config;
|
|
644
677
|
}
|
|
@@ -669,221 +702,16 @@ async function hasClarinetProject(path2 = "./Clarinet.toml") {
|
|
|
669
702
|
return false;
|
|
670
703
|
}
|
|
671
704
|
}
|
|
672
|
-
// src/plugins/actions/generators.ts
|
|
673
|
-
import { toCamelCase as toCamelCase3 } from "@secondlayer/stacks/clarity";
|
|
674
|
-
|
|
675
|
-
// src/utils/generator-helpers.ts
|
|
676
|
-
import {
|
|
677
|
-
generateArgsSignature,
|
|
678
|
-
generateClarityArgs,
|
|
679
|
-
generateMapKeyConversion
|
|
680
|
-
} from "@secondlayer/scaffold";
|
|
681
|
-
|
|
682
|
-
// src/plugins/actions/generators.ts
|
|
683
|
-
function generateReadHelpers(contract, options) {
|
|
684
|
-
const { abi } = contract;
|
|
685
|
-
const functions = abi.functions || [];
|
|
686
|
-
const readOnlyFunctions = functions.filter((f) => f.access === "read-only");
|
|
687
|
-
if (readOnlyFunctions.length === 0) {
|
|
688
|
-
return "";
|
|
689
|
-
}
|
|
690
|
-
const filteredFunctions = readOnlyFunctions.filter((func) => {
|
|
691
|
-
if (options.includeFunctions && !options.includeFunctions.includes(func.name)) {
|
|
692
|
-
return false;
|
|
693
|
-
}
|
|
694
|
-
if (options.excludeFunctions?.includes(func.name)) {
|
|
695
|
-
return false;
|
|
696
|
-
}
|
|
697
|
-
return true;
|
|
698
|
-
});
|
|
699
|
-
if (filteredFunctions.length === 0) {
|
|
700
|
-
return "";
|
|
701
|
-
}
|
|
702
|
-
const helpers = filteredFunctions.map((func) => {
|
|
703
|
-
const methodName = toCamelCase3(func.name);
|
|
704
|
-
const argsSignature = generateArgsSignature(func.args);
|
|
705
|
-
const clarityArgs = generateClarityArgs(func.args);
|
|
706
|
-
return `async ${methodName}(${argsSignature}options?: {
|
|
707
|
-
network?: 'mainnet' | 'testnet' | 'devnet';
|
|
708
|
-
senderAddress?: string;
|
|
709
|
-
}) {
|
|
710
|
-
return await fetchCallReadOnlyFunction({
|
|
711
|
-
contractAddress: '${contract.address}',
|
|
712
|
-
contractName: '${contract.contractName}',
|
|
713
|
-
functionName: '${func.name}',
|
|
714
|
-
functionArgs: [${clarityArgs}],
|
|
715
|
-
network: options?.network ?? inferNetworkFromAddress('${contract.address}') ?? 'mainnet',
|
|
716
|
-
senderAddress: options?.senderAddress || 'SP000000000000000000002Q6VF78'
|
|
717
|
-
});
|
|
718
|
-
}`;
|
|
719
|
-
});
|
|
720
|
-
return `read: {
|
|
721
|
-
${helpers.join(`,
|
|
722
|
-
|
|
723
|
-
`)}
|
|
724
|
-
}`;
|
|
725
|
-
}
|
|
726
|
-
function generateWriteHelpers(contract, options) {
|
|
727
|
-
const { abi } = contract;
|
|
728
|
-
const functions = abi.functions || [];
|
|
729
|
-
const envVarName = options.senderKeyEnv ?? "STX_SENDER_KEY";
|
|
730
|
-
const publicFunctions = functions.filter((f) => f.access === "public");
|
|
731
|
-
if (publicFunctions.length === 0) {
|
|
732
|
-
return "";
|
|
733
|
-
}
|
|
734
|
-
const filteredFunctions = publicFunctions.filter((func) => {
|
|
735
|
-
if (options.includeFunctions && !options.includeFunctions.includes(func.name)) {
|
|
736
|
-
return false;
|
|
737
|
-
}
|
|
738
|
-
if (options.excludeFunctions?.includes(func.name)) {
|
|
739
|
-
return false;
|
|
740
|
-
}
|
|
741
|
-
return true;
|
|
742
|
-
});
|
|
743
|
-
if (filteredFunctions.length === 0) {
|
|
744
|
-
return "";
|
|
745
|
-
}
|
|
746
|
-
const helpers = filteredFunctions.map((func) => {
|
|
747
|
-
const methodName = toCamelCase3(func.name);
|
|
748
|
-
const argsSignature = generateArgsSignature(func.args);
|
|
749
|
-
const clarityArgs = generateClarityArgs(func.args);
|
|
750
|
-
return `async ${methodName}(${argsSignature}senderKey?: string, options?: {
|
|
751
|
-
network?: 'mainnet' | 'testnet' | 'devnet';
|
|
752
|
-
fee?: string | number | undefined;
|
|
753
|
-
nonce?: bigint;
|
|
754
|
-
anchorMode?: 1 | 2 | 3; // AnchorMode: OnChainOnly = 1, OffChainOnly = 2, Any = 3
|
|
755
|
-
postConditions?: PostCondition[];
|
|
756
|
-
validateWithAbi?: boolean;
|
|
757
|
-
}) {
|
|
758
|
-
const resolvedSenderKey = senderKey ?? process.env.${envVarName};
|
|
759
|
-
if (!resolvedSenderKey) {
|
|
760
|
-
throw new Error('senderKey required: pass as argument or set ${envVarName} env var');
|
|
761
|
-
}
|
|
762
|
-
const { network = 'mainnet', ...txOptions } = options ?? {};
|
|
763
|
-
|
|
764
|
-
return await makeContractCall({
|
|
765
|
-
contractAddress: '${contract.address}',
|
|
766
|
-
contractName: '${contract.contractName}',
|
|
767
|
-
functionName: '${func.name}',
|
|
768
|
-
functionArgs: [${clarityArgs}],
|
|
769
|
-
senderKey: resolvedSenderKey,
|
|
770
|
-
network,
|
|
771
|
-
validateWithAbi: true,
|
|
772
|
-
...txOptions
|
|
773
|
-
});
|
|
774
|
-
}`;
|
|
775
|
-
});
|
|
776
|
-
return `write: {
|
|
777
|
-
${helpers.join(`,
|
|
778
|
-
|
|
779
|
-
`)}
|
|
780
|
-
}`;
|
|
781
|
-
}
|
|
782
|
-
async function generateActionHelpers(contract, options) {
|
|
783
|
-
const readHelpers = generateReadHelpers(contract, options);
|
|
784
|
-
const writeHelpers = generateWriteHelpers(contract, options);
|
|
785
|
-
if (!readHelpers && !writeHelpers) {
|
|
786
|
-
return "";
|
|
787
|
-
}
|
|
788
|
-
const helpers = [readHelpers, writeHelpers].filter(Boolean);
|
|
789
|
-
return helpers.join(`,
|
|
790
|
-
|
|
791
|
-
`);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
// src/plugins/actions/index.ts
|
|
795
|
-
var actions = (options = {}) => {
|
|
796
|
-
return {
|
|
797
|
-
name: "@secondlayer/cli/plugin-actions",
|
|
798
|
-
version: "1.0.0",
|
|
799
|
-
async generate(context) {
|
|
800
|
-
const { contracts } = context;
|
|
801
|
-
const filteredContracts = contracts.filter((contract) => {
|
|
802
|
-
if (options.include && !options.include.includes(contract.name)) {
|
|
803
|
-
return false;
|
|
804
|
-
}
|
|
805
|
-
if (options.exclude?.includes(contract.name)) {
|
|
806
|
-
return false;
|
|
807
|
-
}
|
|
808
|
-
return true;
|
|
809
|
-
});
|
|
810
|
-
if (filteredContracts.length === 0) {
|
|
811
|
-
if (options.debug) {
|
|
812
|
-
context.logger.debug("Actions plugin: No contracts to process");
|
|
813
|
-
}
|
|
814
|
-
return;
|
|
815
|
-
}
|
|
816
|
-
if (options.debug) {
|
|
817
|
-
context.logger.debug(`Actions plugin: Generating read/write helpers for ${filteredContracts.length} contracts`);
|
|
818
|
-
}
|
|
819
|
-
const contractHelpers = new Map;
|
|
820
|
-
for (const contract of filteredContracts) {
|
|
821
|
-
const actionsCode = await generateActionHelpers(contract, options);
|
|
822
|
-
if (actionsCode) {
|
|
823
|
-
contractHelpers.set(contract.name, actionsCode);
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
if (contractHelpers.size > 0) {
|
|
827
|
-
const existingOutput = context.outputs.get("contracts");
|
|
828
|
-
if (existingOutput) {
|
|
829
|
-
let modifiedContent = addRequiredImports(existingOutput.content);
|
|
830
|
-
for (const [contractName, helpersCode] of contractHelpers) {
|
|
831
|
-
modifiedContent = injectHelpersIntoContract(modifiedContent, contractName, helpersCode);
|
|
832
|
-
}
|
|
833
|
-
context.outputs.set("contracts", {
|
|
834
|
-
...existingOutput,
|
|
835
|
-
content: modifiedContent
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
};
|
|
841
|
-
};
|
|
842
|
-
function addRequiredImports(content) {
|
|
843
|
-
const stacksImportRegex = /import\s+\{([^}]+)\}\s+from\s+['"]@secondlayer\/stacks['"];/;
|
|
844
|
-
const match = content.match(stacksImportRegex);
|
|
845
|
-
if (match) {
|
|
846
|
-
let updatedContent = content;
|
|
847
|
-
if (!updatedContent.includes("fetchCallReadOnlyFunction")) {
|
|
848
|
-
updatedContent = updatedContent.replace(stacksImportRegex, `${match[0]}
|
|
849
|
-
import { fetchCallReadOnlyFunction, makeContractCall } from '@secondlayer/stacks/clarity';`);
|
|
850
|
-
}
|
|
851
|
-
if (!updatedContent.includes("type PostCondition")) {
|
|
852
|
-
updatedContent = updatedContent.replace(stacksImportRegex, `${match[0]}
|
|
853
|
-
import type { PostCondition } from '@secondlayer/stacks';`);
|
|
854
|
-
}
|
|
855
|
-
return updatedContent;
|
|
856
|
-
}
|
|
857
|
-
return content;
|
|
858
|
-
}
|
|
859
|
-
function injectHelpersIntoContract(content, contractName, helpersCode) {
|
|
860
|
-
const contractPattern = new RegExp(`(export const ${contractName} = \\{[\\s\\S]*?)\\n\\} as const;`, "g");
|
|
861
|
-
return content.replace(contractPattern, (_, contractBody) => {
|
|
862
|
-
const cleanBody = contractBody.replace(/,\s*$/, "");
|
|
863
|
-
const indentedHelpersCode = helpersCode.split(`
|
|
864
|
-
`).map((line) => {
|
|
865
|
-
if (line.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*\s*:/)) {
|
|
866
|
-
return ` ${line}`;
|
|
867
|
-
}
|
|
868
|
-
return line;
|
|
869
|
-
}).join(`
|
|
870
|
-
`);
|
|
871
|
-
return `${cleanBody},
|
|
872
|
-
|
|
873
|
-
${indentedHelpersCode}
|
|
874
|
-
} as const;`;
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
705
|
// src/plugins/react/generators/contract.ts
|
|
878
706
|
init_format();
|
|
879
707
|
|
|
880
708
|
// src/utils/case-conversion.ts
|
|
881
|
-
import { toCamelCase as
|
|
709
|
+
import { toCamelCase as toCamelCase3 } from "@secondlayer/stacks/clarity";
|
|
882
710
|
function capitalize(str) {
|
|
883
711
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
884
712
|
}
|
|
885
713
|
function toPascalCase(str) {
|
|
886
|
-
return capitalize(
|
|
714
|
+
return capitalize(toCamelCase3(str));
|
|
887
715
|
}
|
|
888
716
|
|
|
889
717
|
// src/utils/type-mapping.ts
|
|
@@ -897,23 +725,23 @@ import {
|
|
|
897
725
|
function generateHookArgsSignature(args) {
|
|
898
726
|
if (args.length === 0)
|
|
899
727
|
return "";
|
|
900
|
-
const argsList = args.map((arg) => `${
|
|
728
|
+
const argsList = args.map((arg) => `${toCamelCase3(arg.name)}: ${clarityTypeToTS(arg.type)}`).join(", ");
|
|
901
729
|
return `${argsList}`;
|
|
902
730
|
}
|
|
903
731
|
function generateArgsType(args) {
|
|
904
732
|
if (args.length === 0)
|
|
905
733
|
return "void";
|
|
906
|
-
const argsList = args.map((arg) => `${
|
|
734
|
+
const argsList = args.map((arg) => `${toCamelCase3(arg.name)}: ${clarityTypeToTS(arg.type)}`).join("; ");
|
|
907
735
|
return `{ ${argsList} }`;
|
|
908
736
|
}
|
|
909
737
|
function generateArgNames(args) {
|
|
910
738
|
if (args.length === 0)
|
|
911
739
|
return "";
|
|
912
|
-
return args.map((arg) =>
|
|
740
|
+
return args.map((arg) => toCamelCase3(arg.name)).join(", ");
|
|
913
741
|
}
|
|
914
742
|
function generateEnabledCondition(args) {
|
|
915
743
|
return args.map((arg) => {
|
|
916
|
-
const camelName =
|
|
744
|
+
const camelName = toCamelCase3(arg.name);
|
|
917
745
|
const type = clarityTypeToTS(arg.type);
|
|
918
746
|
if (type === "string")
|
|
919
747
|
return `!!${camelName}`;
|
|
@@ -925,7 +753,7 @@ function generateEnabledCondition(args) {
|
|
|
925
753
|
function generateObjectArgs(args) {
|
|
926
754
|
if (args.length === 0)
|
|
927
755
|
return "";
|
|
928
|
-
return args.map((arg) => `${arg.name}: ${
|
|
756
|
+
return args.map((arg) => `${arg.name}: ${toCamelCase3(arg.name)}`).join(", ");
|
|
929
757
|
}
|
|
930
758
|
|
|
931
759
|
// src/plugins/react/generators/contract.ts
|
|
@@ -958,21 +786,21 @@ function generateContractHookMethods(contract, excludeList) {
|
|
|
958
786
|
const readOnlyFunctions = functions.filter((f) => f.access === "read-only");
|
|
959
787
|
const publicFunctions = functions.filter((f) => f.access === "public");
|
|
960
788
|
const readHooks = readOnlyFunctions.map((func) => {
|
|
961
|
-
const hookName = `use${capitalize(name)}${capitalize(
|
|
789
|
+
const hookName = `use${capitalize(name)}${capitalize(toCamelCase3(func.name))}`;
|
|
962
790
|
if (excludeList.includes(hookName)) {
|
|
963
791
|
return null;
|
|
964
792
|
}
|
|
965
793
|
return generateReadHook(func, name);
|
|
966
794
|
}).filter(Boolean);
|
|
967
795
|
const writeHooks = publicFunctions.map((func) => {
|
|
968
|
-
const hookName = `use${capitalize(name)}${capitalize(
|
|
796
|
+
const hookName = `use${capitalize(name)}${capitalize(toCamelCase3(func.name))}`;
|
|
969
797
|
if (excludeList.includes(hookName)) {
|
|
970
798
|
return null;
|
|
971
799
|
}
|
|
972
800
|
return generateWriteHook(func, name);
|
|
973
801
|
}).filter(Boolean);
|
|
974
802
|
const mapHooks = maps.map((map) => {
|
|
975
|
-
const hookName = `use${capitalize(name)}${capitalize(
|
|
803
|
+
const hookName = `use${capitalize(name)}${capitalize(toCamelCase3(map.name))}`;
|
|
976
804
|
if (excludeList.includes(hookName)) {
|
|
977
805
|
return null;
|
|
978
806
|
}
|
|
@@ -980,7 +808,7 @@ function generateContractHookMethods(contract, excludeList) {
|
|
|
980
808
|
}).filter(Boolean);
|
|
981
809
|
const dataVars = variables.filter((v) => v.access === "variable");
|
|
982
810
|
const varHooks = dataVars.map((variable) => {
|
|
983
|
-
const hookName = `use${capitalize(name)}${capitalize(
|
|
811
|
+
const hookName = `use${capitalize(name)}${capitalize(toCamelCase3(variable.name))}`;
|
|
984
812
|
if (excludeList.includes(hookName)) {
|
|
985
813
|
return null;
|
|
986
814
|
}
|
|
@@ -988,7 +816,7 @@ function generateContractHookMethods(contract, excludeList) {
|
|
|
988
816
|
}).filter(Boolean);
|
|
989
817
|
const constants = variables.filter((v) => v.access === "constant");
|
|
990
818
|
const constantHooks = constants.map((constant) => {
|
|
991
|
-
const hookName = `use${capitalize(name)}${capitalize(
|
|
819
|
+
const hookName = `use${capitalize(name)}${capitalize(toCamelCase3(constant.name))}`;
|
|
992
820
|
if (excludeList.includes(hookName)) {
|
|
993
821
|
return null;
|
|
994
822
|
}
|
|
@@ -1009,7 +837,7 @@ function generateContractHookMethods(contract, excludeList) {
|
|
|
1009
837
|
`);
|
|
1010
838
|
}
|
|
1011
839
|
function generateReadHook(func, contractName) {
|
|
1012
|
-
const hookName = `use${capitalize(contractName)}${capitalize(
|
|
840
|
+
const hookName = `use${capitalize(contractName)}${capitalize(toCamelCase3(func.name))}`;
|
|
1013
841
|
const argsSignature = generateHookArgsSignature(func.args);
|
|
1014
842
|
const enabledParam = func.args.length > 0 ? ", options?: { enabled?: boolean }" : "options?: { enabled?: boolean }";
|
|
1015
843
|
const returnType = clarityTypeToTS(func.outputs);
|
|
@@ -1018,9 +846,9 @@ function generateReadHook(func, contractName) {
|
|
|
1018
846
|
|
|
1019
847
|
return useQuery<${returnType}>({
|
|
1020
848
|
queryKey: ['${func.name}', ${contractName}.address, ${generateArgNames(func.args)}],
|
|
1021
|
-
queryFn: () => ${contractName}.read.${
|
|
849
|
+
queryFn: () => ${contractName}.read.${toCamelCase3(func.name)}(${generateArgNames(func.args) ? `{ ${generateObjectArgs(func.args)} }, ` : ""}{
|
|
1022
850
|
network: config.network,
|
|
1023
|
-
senderAddress: config.senderAddress || '
|
|
851
|
+
senderAddress: config.senderAddress || '${DEFAULT_SENDER_ADDRESS}'
|
|
1024
852
|
}),
|
|
1025
853
|
${func.args.length > 0 ? `enabled: ${generateEnabledCondition(func.args)} && (options?.enabled ?? true),` : ""}
|
|
1026
854
|
...options
|
|
@@ -1028,7 +856,7 @@ function generateReadHook(func, contractName) {
|
|
|
1028
856
|
}`;
|
|
1029
857
|
}
|
|
1030
858
|
function generateWriteHook(func, contractName) {
|
|
1031
|
-
const hookName = `use${capitalize(contractName)}${capitalize(
|
|
859
|
+
const hookName = `use${capitalize(contractName)}${capitalize(toCamelCase3(func.name))}`;
|
|
1032
860
|
const argsType = generateArgsType(func.args);
|
|
1033
861
|
return `export function ${hookName}() {
|
|
1034
862
|
const config = useSecondLayerConfig()
|
|
@@ -1045,7 +873,7 @@ function generateWriteHook(func, contractName) {
|
|
|
1045
873
|
};
|
|
1046
874
|
}) => {
|
|
1047
875
|
const { args, options = {} } = params
|
|
1048
|
-
const contractCallData = ${contractName}.${
|
|
876
|
+
const contractCallData = ${contractName}.${toCamelCase3(func.name)}(args)
|
|
1049
877
|
const { contractAddress, contractName: name, functionName, functionArgs } = contractCallData
|
|
1050
878
|
const network = config.network || 'mainnet'
|
|
1051
879
|
const contract = \`\${contractAddress}.\${name}\`
|
|
@@ -1070,7 +898,7 @@ function generateWriteHook(func, contractName) {
|
|
|
1070
898
|
}
|
|
1071
899
|
})
|
|
1072
900
|
|
|
1073
|
-
const ${
|
|
901
|
+
const ${toCamelCase3(func.name)} = useCallback(async (
|
|
1074
902
|
args: ${argsType},
|
|
1075
903
|
options?: {
|
|
1076
904
|
postConditions?: PostCondition[];
|
|
@@ -1083,7 +911,7 @@ function generateWriteHook(func, contractName) {
|
|
|
1083
911
|
}, [mutation])
|
|
1084
912
|
|
|
1085
913
|
return {
|
|
1086
|
-
${
|
|
914
|
+
${toCamelCase3(func.name)},
|
|
1087
915
|
// Expose mutation state
|
|
1088
916
|
isPending: mutation.isPending,
|
|
1089
917
|
isError: mutation.isError,
|
|
@@ -1095,7 +923,7 @@ function generateWriteHook(func, contractName) {
|
|
|
1095
923
|
}`;
|
|
1096
924
|
}
|
|
1097
925
|
function generateMapHook(map, contractVarName, _address, _contractName) {
|
|
1098
|
-
const hookName = `use${capitalize(contractVarName)}${capitalize(
|
|
926
|
+
const hookName = `use${capitalize(contractVarName)}${capitalize(toCamelCase3(map.name))}`;
|
|
1099
927
|
const keyType = clarityTypeToTS(map.key);
|
|
1100
928
|
const valueType = clarityTypeToTS(map.value);
|
|
1101
929
|
return `export function ${hookName}(key: ${keyType}, options?: { enabled?: boolean }) {
|
|
@@ -1104,14 +932,14 @@ function generateMapHook(map, contractVarName, _address, _contractName) {
|
|
|
1104
932
|
return useQuery<${valueType} | null>({
|
|
1105
933
|
queryKey: ['${contractVarName}', '${map.name}', 'map', key, config.network],
|
|
1106
934
|
queryFn: async () => {
|
|
1107
|
-
return ${contractVarName}.maps.${
|
|
935
|
+
return ${contractVarName}.maps.${toCamelCase3(map.name)}.get(key, { network: config.network })
|
|
1108
936
|
},
|
|
1109
937
|
enabled: options?.enabled ?? true
|
|
1110
938
|
})
|
|
1111
939
|
}`;
|
|
1112
940
|
}
|
|
1113
941
|
function generateVarHook(variable, contractVarName, _address, _contractName) {
|
|
1114
|
-
const hookName = `use${capitalize(contractVarName)}${capitalize(
|
|
942
|
+
const hookName = `use${capitalize(contractVarName)}${capitalize(toCamelCase3(variable.name))}`;
|
|
1115
943
|
const valueType = clarityTypeToTS(variable.type);
|
|
1116
944
|
return `export function ${hookName}(options?: { enabled?: boolean }) {
|
|
1117
945
|
const config = useSecondLayerConfig()
|
|
@@ -1119,14 +947,14 @@ function generateVarHook(variable, contractVarName, _address, _contractName) {
|
|
|
1119
947
|
return useQuery<${valueType}>({
|
|
1120
948
|
queryKey: ['${contractVarName}', '${variable.name}', 'var', config.network],
|
|
1121
949
|
queryFn: async () => {
|
|
1122
|
-
return ${contractVarName}.vars.${
|
|
950
|
+
return ${contractVarName}.vars.${toCamelCase3(variable.name)}.get({ network: config.network })
|
|
1123
951
|
},
|
|
1124
952
|
enabled: options?.enabled ?? true
|
|
1125
953
|
})
|
|
1126
954
|
}`;
|
|
1127
955
|
}
|
|
1128
956
|
function generateConstantHook(constant, contractVarName, _address, _contractName) {
|
|
1129
|
-
const hookName = `use${capitalize(contractVarName)}${capitalize(
|
|
957
|
+
const hookName = `use${capitalize(contractVarName)}${capitalize(toCamelCase3(constant.name))}`;
|
|
1130
958
|
const valueType = clarityTypeToTS(constant.type);
|
|
1131
959
|
return `export function ${hookName}(options?: { enabled?: boolean }) {
|
|
1132
960
|
const config = useSecondLayerConfig()
|
|
@@ -1134,7 +962,7 @@ function generateConstantHook(constant, contractVarName, _address, _contractName
|
|
|
1134
962
|
return useQuery<${valueType}>({
|
|
1135
963
|
queryKey: ['${contractVarName}', '${constant.name}', 'constant', config.network],
|
|
1136
964
|
queryFn: async () => {
|
|
1137
|
-
return ${contractVarName}.constants.${
|
|
965
|
+
return ${contractVarName}.constants.${toCamelCase3(constant.name)}.get({ network: config.network })
|
|
1138
966
|
},
|
|
1139
967
|
enabled: options?.enabled ?? true,
|
|
1140
968
|
staleTime: Infinity // Constants never change
|
|
@@ -1642,7 +1470,7 @@ function generateGenericHook(hookName) {
|
|
|
1642
1470
|
functionName: params.functionName,
|
|
1643
1471
|
functionArgs,
|
|
1644
1472
|
network: params.network || config.network || 'mainnet',
|
|
1645
|
-
senderAddress: config.senderAddress || '
|
|
1473
|
+
senderAddress: config.senderAddress || '${DEFAULT_SENDER_ADDRESS}'
|
|
1646
1474
|
}) as TResult
|
|
1647
1475
|
},
|
|
1648
1476
|
enabled: params.enabled ?? true
|
|
@@ -1910,7 +1738,7 @@ export function createSecondLayerConfig(config: SecondLayerReactConfig): SecondL
|
|
|
1910
1738
|
network: config.network,
|
|
1911
1739
|
apiKey: config.apiKey,
|
|
1912
1740
|
apiUrl: config.apiUrl,
|
|
1913
|
-
senderAddress: config.senderAddress || '
|
|
1741
|
+
senderAddress: config.senderAddress || '${DEFAULT_SENDER_ADDRESS}'
|
|
1914
1742
|
}
|
|
1915
1743
|
}
|
|
1916
1744
|
|
|
@@ -1987,8 +1815,17 @@ var react = (options = {}) => {
|
|
|
1987
1815
|
import {
|
|
1988
1816
|
isAbiTuple
|
|
1989
1817
|
} from "@secondlayer/stacks/clarity";
|
|
1818
|
+
|
|
1819
|
+
// src/utils/generator-helpers.ts
|
|
1820
|
+
import {
|
|
1821
|
+
generateArgsSignature,
|
|
1822
|
+
generateClarityArgs,
|
|
1823
|
+
generateMapKeyConversion
|
|
1824
|
+
} from "@secondlayer/scaffold";
|
|
1825
|
+
|
|
1826
|
+
// src/plugins/testing/generators.ts
|
|
1990
1827
|
function generatePublicFunction(func, contractId) {
|
|
1991
|
-
const methodName =
|
|
1828
|
+
const methodName = toCamelCase3(func.name);
|
|
1992
1829
|
const argsSignature = generateArgsSignature(func.args);
|
|
1993
1830
|
const clarityArgs = generateClarityArgs(func.args);
|
|
1994
1831
|
return `${methodName}: (${argsSignature}caller: string) => {
|
|
@@ -2002,7 +1839,7 @@ function generatePublicFunction(func, contractId) {
|
|
|
2002
1839
|
}`;
|
|
2003
1840
|
}
|
|
2004
1841
|
function generateReadOnlyFunction(func, contractId) {
|
|
2005
|
-
const methodName =
|
|
1842
|
+
const methodName = toCamelCase3(func.name);
|
|
2006
1843
|
const argsSignature = generateArgsSignature(func.args);
|
|
2007
1844
|
const clarityArgs = generateClarityArgs(func.args);
|
|
2008
1845
|
const hasArgs = func.args.length > 0;
|
|
@@ -2017,7 +1854,7 @@ function generateReadOnlyFunction(func, contractId) {
|
|
|
2017
1854
|
}`;
|
|
2018
1855
|
}
|
|
2019
1856
|
function generatePrivateFunction(func, contractId) {
|
|
2020
|
-
const methodName =
|
|
1857
|
+
const methodName = toCamelCase3(func.name);
|
|
2021
1858
|
const argsSignature = generateArgsSignature(func.args);
|
|
2022
1859
|
const clarityArgs = generateClarityArgs(func.args);
|
|
2023
1860
|
return `${methodName}: (${argsSignature}caller: string) => {
|
|
@@ -2031,20 +1868,20 @@ function generatePrivateFunction(func, contractId) {
|
|
|
2031
1868
|
}`;
|
|
2032
1869
|
}
|
|
2033
1870
|
function generateDataVarHelper(variable, contractId) {
|
|
2034
|
-
const methodName =
|
|
1871
|
+
const methodName = toCamelCase3(variable.name);
|
|
2035
1872
|
return `${methodName}: () => {
|
|
2036
1873
|
return simnet.getDataVar('${contractId}', '${variable.name}');
|
|
2037
1874
|
}`;
|
|
2038
1875
|
}
|
|
2039
1876
|
function getMapKeyType(keyType) {
|
|
2040
1877
|
if (isAbiTuple(keyType)) {
|
|
2041
|
-
const fields = keyType.tuple.map((field) => `${
|
|
1878
|
+
const fields = keyType.tuple.map((field) => `${toCamelCase3(field.name)}: ${getTypeForArg({ type: field.type })}`).join("; ");
|
|
2042
1879
|
return `{ ${fields} }`;
|
|
2043
1880
|
}
|
|
2044
1881
|
return getTypeForArg({ type: keyType });
|
|
2045
1882
|
}
|
|
2046
1883
|
function generateMapEntryHelper(map, contractId) {
|
|
2047
|
-
const methodName =
|
|
1884
|
+
const methodName = toCamelCase3(map.name);
|
|
2048
1885
|
const keyType = getMapKeyType(map.key);
|
|
2049
1886
|
const keyConversion = generateMapKeyConversion(map.key);
|
|
2050
1887
|
return `${methodName}: (key: ${keyType}) => {
|
|
@@ -2114,7 +1951,7 @@ function generateContractHelper(contract, options) {
|
|
|
2114
1951
|
}
|
|
2115
1952
|
function generateGetContracts(contracts) {
|
|
2116
1953
|
const contractEntries = contracts.map((contract) => {
|
|
2117
|
-
const camelName =
|
|
1954
|
+
const camelName = toCamelCase3(contract.name);
|
|
2118
1955
|
const pascalName = toPascalCase(contract.name);
|
|
2119
1956
|
return `${camelName}: get${pascalName}(simnet)`;
|
|
2120
1957
|
}).join(`,
|
|
@@ -2181,15 +2018,7 @@ var testing = (options = {}) => {
|
|
|
2181
2018
|
version: "1.0.0",
|
|
2182
2019
|
async generate(context) {
|
|
2183
2020
|
const { contracts } = context;
|
|
2184
|
-
const filteredContracts = contracts.filter((contract) =>
|
|
2185
|
-
if (options.include && !options.include.includes(contract.name)) {
|
|
2186
|
-
return false;
|
|
2187
|
-
}
|
|
2188
|
-
if (options.exclude?.includes(contract.name)) {
|
|
2189
|
-
return false;
|
|
2190
|
-
}
|
|
2191
|
-
return true;
|
|
2192
|
-
});
|
|
2021
|
+
const filteredContracts = contracts.filter((contract) => matchesContractFilters(contract.name, options));
|
|
2193
2022
|
if (filteredContracts.length === 0) {
|
|
2194
2023
|
if (options.debug) {
|
|
2195
2024
|
context.logger.debug("Testing plugin: No contracts to process");
|
|
@@ -2238,9 +2067,8 @@ export {
|
|
|
2238
2067
|
filterByOptions,
|
|
2239
2068
|
createPlugin,
|
|
2240
2069
|
clarinet,
|
|
2241
|
-
actions,
|
|
2242
2070
|
PluginManager
|
|
2243
2071
|
};
|
|
2244
2072
|
|
|
2245
|
-
//# debugId=
|
|
2073
|
+
//# debugId=E6E6E78DF371674C64756E2164756E21
|
|
2246
2074
|
//# sourceMappingURL=index.js.map
|