Skip to content

Commit ec8cdfc

Browse files
committed
feat: revamp extension usage
1 parent 0e01142 commit ec8cdfc

File tree

2 files changed

+154
-117
lines changed

2 files changed

+154
-117
lines changed

examples/counter/scripts/abi-generator.ts

Lines changed: 0 additions & 117 deletions
This file was deleted.
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Clarinet extention #1
2+
//
3+
// This extension is introspecting the contracts of the project it's running from,
4+
// and produce a Typescript data structure autocomplete friendly, that developers
5+
// can use in their frontend code.
6+
//
7+
// When running:
8+
// $ clarinet run --allow-write scripts/stacksjs-helper-generator.rs
9+
//
10+
// This script will write a file at the path artifacts/contracts.ts:
11+
//
12+
// export namespace CounterContract {
13+
// export const address = "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM";
14+
// export const name = "counter";
15+
// export namespace Functions {
16+
// export namespace Increment {
17+
// export const name = "increment";
18+
// export interface IncrementArgs {
19+
// step: ClarityValue,
20+
// }
21+
// export function args(args: IncrementArgs): [ClarityValue] {
22+
// return [
23+
// args.step,
24+
// ];
25+
// }
26+
// }
27+
// // read-counter
28+
// export namespace ReadCounter {
29+
// export const name = "read-counter";
30+
//
31+
// }
32+
// }
33+
// }
34+
//
35+
// By importing this file in their frontend code, developers can use constants, instead
36+
// of hard coding principals and strings:
37+
//
38+
// await makeContractCall({
39+
// contractAddress: CounterContract.address,
40+
// contractName: CounterContract.name,
41+
// functionName: CounterContract.Functions.Increment.name,
42+
// functionArgs: CounterContract.Functions.Increment.args({ step: uintCV(10); }),
43+
// ...
44+
// }
45+
46+
import { Clarinet, Contract, Account, StacksNode } from 'https://deno.land/x/clarinet@v0.13.0/index.ts';
47+
48+
Clarinet.run({
49+
async fn(accounts: Map<string, Account>, contracts: Map<string, Contract>, node: StacksNode) {
50+
let code = [];
51+
code.push([
52+
`// Code generated with the stacksjs-helper-generator extension`,
53+
`// Manual edits will be overwritten`,
54+
``,
55+
`import { ClarityValue } from "@stacks/transactions"`,
56+
``,
57+
]);
58+
59+
for (let [contractId, contract] of contracts) {
60+
let [address, name] = contractId.split(".");
61+
code.push([
62+
`export namespace ${kebabToCamel(capitalize(name))}Contract {`,
63+
` export const address = "${address}";`,
64+
` export const name = "${name}";`,
65+
``,
66+
]);
67+
68+
let functions = [];
69+
70+
for (let func of contract.contract_interface.functions) {
71+
if (func.access === "public") {
72+
functions.push(func);
73+
} else if (func.access === "read_only") {
74+
functions.push(func)
75+
}
76+
}
77+
78+
if (functions.length > 0) {
79+
code.push([
80+
` // Functions`,
81+
` export namespace Functions {`,
82+
]);
83+
for (let f of functions) {
84+
85+
code.push([
86+
` // ${f.name}`,
87+
` export namespace ${kebabToCamel(capitalize(f.name))} {`,
88+
` export const name = "${f.name}";`,
89+
``
90+
]);
91+
92+
if (f.args.length > 0) {
93+
94+
// Generate code for interface
95+
code.push([
96+
` export interface ${kebabToCamel(capitalize(f.name))}Args {`,
97+
]);
98+
for (let arg of f.args) {
99+
code.push([
100+
` ${kebabToCamel(arg.name)}: ClarityValue,`,
101+
]);
102+
}
103+
code.push([
104+
` }`,
105+
``
106+
]);
107+
108+
// Generate code for helper function
109+
code.push([
110+
` export function args(args: ${kebabToCamel(capitalize(f.name))}Args): [ClarityValue] {`,
111+
` return [`
112+
]);
113+
for (let arg of f.args) {
114+
code.push([
115+
` args.${kebabToCamel(arg.name)},`,
116+
]);
117+
}
118+
code.push([
119+
` ];`,
120+
` }`,
121+
``
122+
]);
123+
}
124+
125+
code.push([
126+
` }`,
127+
``
128+
]);
129+
}
130+
131+
code.push([
132+
` }`,
133+
]);
134+
}
135+
136+
code.push([
137+
`}`,
138+
``
139+
]);
140+
}
141+
142+
const write = await Deno.writeTextFile("./artifacts/contracts.ts", code.flat().join("\n"));
143+
}
144+
});
145+
146+
function capitalize(source: string): string {
147+
return source[0].toUpperCase() + source.slice(1);
148+
}
149+
150+
function kebabToCamel(source: string): string {
151+
return source
152+
.replace(/[^\w\-\_]/g, "")
153+
.replace(/(-\w)/g, (x) => x[1].toUpperCase());
154+
}

0 commit comments

Comments
 (0)