@clarigen/cli 1.0.0-next.17 → 1.0.0-next.18
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/commands/index.js +54 -40
- package/dist/commands/index.mjs +57 -43
- package/dist/index.d.ts +2 -1
- package/dist/index.js +64 -37
- package/dist/index.mjs +59 -32
- package/package.json +8 -6
- package/src/clarinet-config.ts +6 -0
- package/src/generate/declaration.ts +1 -1
- package/src/generate/single.ts +128 -0
- package/src/generate/vars.ts +82 -0
- package/src/utils.ts +43 -7
- package/src/writer.ts +39 -0
package/dist/commands/index.js
CHANGED
|
@@ -1,35 +1,22 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,!0,{longer:!0})}async function
|
|
3
|
-
`,!0)}async function
|
|
4
|
-
${
|
|
1
|
+
var D=Object.defineProperty,jt=Object.defineProperties,Et=Object.getOwnPropertyDescriptor,It=Object.getOwnPropertyDescriptors,kt=Object.getOwnPropertyNames,S=Object.getOwnPropertySymbols;var H=Object.prototype.hasOwnProperty,rt=Object.prototype.propertyIsEnumerable;var et=(t,e,r)=>e in t?D(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,y=(t,e)=>{for(var r in e||(e={}))H.call(e,r)&&et(t,r,e[r]);if(S)for(var r of S(e))rt.call(e,r)&&et(t,r,e[r]);return t},x=(t,e)=>jt(t,It(e));var V=(t,e)=>{var r={};for(var n in t)H.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&S)for(var n of S(t))e.indexOf(n)<0&&rt.call(t,n)&&(r[n]=t[n]);return r};var St=(t,e)=>{for(var r in e)D(t,r,{get:e[r],enumerable:!0})},Dt=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of kt(e))!H.call(t,o)&&o!==r&&D(t,o,{get:()=>e[o],enumerable:!(n=Et(e,o))||n.enumerable});return t};var Vt=t=>Dt(D({},"__esModule",{value:!0}),t);var re={};St(re,{Generate:()=>w});module.exports=Vt(re);var E=require("@oclif/command");var Wt=require("@clarigen/native-bin"),F=require("@clarigen/core"),B=require("path");var Ut=require("@oclif/command");var h=require("path"),L=require("fs/promises"),ct=require("fs");var Q=require("@ltd/j-toml"),X=require("path"),Y=require("fs/promises"),O=require("micro-stacks/wallet-sdk"),nt=require("toposort"),ot=require("micro-stacks/crypto");async function Ot(t){let e=(0,X.resolve)(t,"settings","Devnet.toml"),r=await(0,Y.readFile)(e,{encoding:"utf-8"});return(0,Q.parse)(r,1,`
|
|
2
|
+
`,!0,{longer:!0})}async function Lt(t){let e=(0,X.resolve)(t,"Clarinet.toml"),r=await(0,Y.readFile)(e,{encoding:"utf-8"});return(0,Q.parse)(r,1,`
|
|
3
|
+
`,!0)}async function it(t,e){let r=await Lt(t),n=e.deployer.address;return Mt(r.contracts).map(a=>({file:r.contracts[a].path.replace(/^contracts\//,""),address:n,name:a}))}function Mt(t){let e=[],r=[];return Object.entries(t).forEach(([o,i])=>{r.push(o),i.depends_on.forEach(a=>e.push([o,a]))}),(0,nt.array)(r,e).reverse()}async function st(t){let e=await Ot(t),r=await Promise.all(Object.entries(e.accounts).map(async([o,i])=>{let a=await(0,O.generateWallet)(i.mnemonic,"password"),[s]=a.accounts,l=(0,O.getStxAddressFromAccount)(s,ot.StacksNetworkVersion.testnetP2PKH);return[o,x(y({},i),{address:l})]}));return Object.fromEntries(r)}var at={outputDir:"src/clarigen",clarinet:"."};function _t(t){return(0,h.resolve)(t,"clarigen.config.json")}async function Bt(t){try{return await(0,L.access)(t,ct.constants.R_OK),!0}catch{return!1}}async function Jt(t){let e=_t(t);if(await Bt(e)){let n=await(0,L.readFile)(e,{encoding:"utf-8"}),o=JSON.parse(n);return y(y({},at),o)}return at}async function M(t){let e=await Jt(t),r=(0,h.resolve)(t,e.clarinet||"."),n=await st(r),o=await it(r,n),i=(0,h.relative)(process.cwd(),(0,h.join)(e.clarinet,"contracts"));return x(y({},e),{contracts:o,contractsDir:i,accounts:n,clarinet:e.clarinet||"."})}var m=require("micro-stacks/transactions"),_=require("@clarigen/core"),lt=require("reserved-words"),p=(t,e=!1)=>{if((0,m.isClarityAbiPrimitive)(t)){if(t==="uint128")return e?"number | bigint":"bigint";if(t==="int128")return e?"number | bigint":"bigint";if(t==="bool")return"boolean";if(t==="principal")return"string";if(t==="none")return"null";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(t)}`)}else{if((0,m.isClarityAbiBuffer)(t))return"Uint8Array";if((0,m.isClarityAbiResponse)(t)){let r=p(t.response.ok),n=p(t.response.error);return`Response<${r}, ${n}>`}else{if((0,m.isClarityAbiOptional)(t))return`${p(t.optional)} | null`;if((0,m.isClarityAbiTuple)(t)){let r=[];return t.tuple.forEach(({name:n,type:o})=>{let i=p(o);r.push(`"${n}": ${i}`)}),`{
|
|
4
|
+
${r.join(`;
|
|
5
5
|
`)}
|
|
6
|
-
}`}else{if((0,
|
|
7
|
-
`} ${o}`}),t.maps.forEach(
|
|
8
|
-
${
|
|
9
|
-
${o.stderr}
|
|
10
|
-
`);let i=JSON.parse(o.stdout);if(i.error){let{initialization:s}=i.error;if(s!=null&&s.includes(`
|
|
11
|
-
Near:
|
|
12
|
-
`)){let[a,f]=s.split(`
|
|
13
|
-
Near:
|
|
14
|
-
`),u="",m=/start_line: (\d+),/.exec(f);throw m&&(u=m[1]),new Error(`Error on ${r}:
|
|
15
|
-
${a}
|
|
16
|
-
${u?`Near line ${u}`:""}
|
|
17
|
-
Raw trace:
|
|
18
|
-
${f}
|
|
19
|
-
`)}throw new Error(`Error on ${r}:
|
|
20
|
-
${JSON.stringify(i.error,null,2)}
|
|
21
|
-
`)}return i.analysis},rt=({contractName:t,abi:r})=>{let n=(0,$.toCamelCase)(t,!0),s=r,{clarity_version:e}=s,o=V(s,["clarity_version"]),i=JSON.stringify(o,null,2);return`import { ClarityAbi } from '@clarigen/core';
|
|
6
|
+
}`}else{if((0,m.isClarityAbiList)(t))return`${p(t.list.type)}[]`;if((0,m.isClarityAbiStringAscii)(t))return"string";if((0,m.isClarityAbiStringUtf8)(t))return"string";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(t)}`)}}}};function Z(t){let e=(0,_.toCamelCase)(t);return`${(0,lt.check)(e,6)?"_":""}${e}`}var Rt={public:"Public",read_only:"ReadOnly",private:"Private"};function ft(t){let e="";return t.functions.forEach((r,n)=>{let o=`${(0,_.toCamelCase)(r.name)}: `;if(o+=`(${r.args.map(s=>`${Z(s.name)}: ${p(s.type,!0)}`).join(", ")}) => `,o+=`ContractCalls.${Rt[r.access]}<`,r.access==="public"){let{type:s}=r.outputs;if(!(0,m.isClarityAbiResponse)(s))throw new Error("Expected response type for public function");let l=p(s.response.ok),f=p(s.response.error);o+=`${l}, ${f}>;`}else o+=`${p(r.outputs.type)}>;`;e+=`${n===0?"":`
|
|
7
|
+
`} ${o}`}),t.maps.forEach(r=>{let n=`${(0,_.toCamelCase)(r.name)}: `,o=p(r.key,!0),i=`key: ${o}`,a=p(r.value);n+=`(${i}) => ContractCalls.Map<${o}, ${a}>;`,e+=`
|
|
8
|
+
${n}`}),e}var pt=({contractName:t,abi:e})=>{let r=(0,F.toCamelCase)(t,!0),s=e,{clarity_version:n}=s,o=V(s,["clarity_version"]),i=JSON.stringify(o,null,2);return`import { ClarityAbi } from '@clarigen/core';
|
|
22
9
|
|
|
23
10
|
// prettier-ignore
|
|
24
|
-
export const ${
|
|
25
|
-
`},
|
|
11
|
+
export const ${r}Interface: ClarityAbi = ${i};
|
|
12
|
+
`},mt=({contractFile:t,contractAddress:e,contractName:r})=>{let n=(0,F.toCamelCase)(r,!0),o=(0,F.toCamelCase)(r),i=`${n}Contract`,a=`${n}Interface`;return`import { pureProxy, Contract } from '@clarigen/core';
|
|
26
13
|
import type { ${i} } from './types';
|
|
27
|
-
import { ${
|
|
14
|
+
import { ${a} } from './abi';
|
|
28
15
|
export type { ${i} } from './types';
|
|
29
16
|
|
|
30
17
|
export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
31
18
|
return pureProxy<${i}>({
|
|
32
|
-
abi: ${
|
|
19
|
+
abi: ${a},
|
|
33
20
|
contractAddress,
|
|
34
21
|
contractName,
|
|
35
22
|
});
|
|
@@ -37,42 +24,69 @@ export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
|
37
24
|
|
|
38
25
|
export const ${o}Info: Contract<${i}> = {
|
|
39
26
|
contract: ${o}Contract,
|
|
40
|
-
address: '${
|
|
27
|
+
address: '${e}',
|
|
41
28
|
contractFile: '${t}',
|
|
42
|
-
name: '${
|
|
43
|
-
abi: ${
|
|
29
|
+
name: '${r}',
|
|
30
|
+
abi: ${a},
|
|
44
31
|
};
|
|
45
|
-
`},
|
|
32
|
+
`},ut=(t,e)=>{let r=(0,F.toCamelCase)(e,!0),n=ft(t);return`import { Response, ContractCalls } from '@clarigen/core';
|
|
46
33
|
|
|
47
34
|
// prettier-ignore
|
|
48
|
-
export interface ${
|
|
49
|
-
${
|
|
35
|
+
export interface ${r}Contract {
|
|
36
|
+
${n}
|
|
50
37
|
}
|
|
51
|
-
`},
|
|
38
|
+
`},gt=t=>{let e=["import type { ContractInstances } from '@clarigen/core';"],r=[],n=[],o="";"accounts"in t&&(o=`
|
|
52
39
|
|
|
53
40
|
// prettier-ignore
|
|
54
41
|
export const accounts = {
|
|
55
|
-
${Object.keys(t.accounts).map(
|
|
42
|
+
${Object.keys(t.accounts).map(l=>{let f=t.accounts[l];return`"${l}": {
|
|
56
43
|
mnemonic: "${f.mnemonic}",
|
|
57
44
|
balance: ${f.balance.toString()}n,
|
|
58
45
|
address: "${f.address}",
|
|
59
46
|
},`}).join(`
|
|
60
47
|
`)}
|
|
61
|
-
};`),t.contracts.forEach(s=>{let
|
|
48
|
+
};`),t.contracts.forEach(s=>{let l=s.name,f=(0,F.toCamelCase)(l),b=`${f}Info`,A=`${(0,F.toCamelCase)(l,!0)}Contract`,C=(0,B.dirname)(s.file),$=`'./${(0,B.join)(C||".",l)}'`,c=`import { ${b} } from ${$};`;e.push(c);let u=`export type { ${A} } from ${$};`;r.push(u);let v=`${f}: ${b},`;n.push(v)});let i=`
|
|
62
49
|
export type Contracts = ContractInstances<typeof contracts>;
|
|
63
|
-
`;return`${
|
|
50
|
+
`;return`${e.join(`
|
|
64
51
|
`)}
|
|
65
|
-
${
|
|
52
|
+
${r.join(`
|
|
66
53
|
`)}
|
|
67
54
|
${i}
|
|
68
55
|
export const contracts = {
|
|
69
|
-
${
|
|
56
|
+
${n.join(`
|
|
70
57
|
`)}
|
|
71
58
|
};${o}
|
|
72
|
-
`};var
|
|
59
|
+
`};var K=require("@clarigen/native-bin"),g=require("path"),Tt=require("fs/promises");var J=require("@clarigen/claridocs"),T=require("fs/promises"),P=require("path");async function Ct({contractFile:t,contractName:e,docsPath:r,abi:n,dirName:o}){let i=await(0,T.readFile)(t,{encoding:"utf-8"}),a=(0,J.createContractDocInfo)({contractSrc:i,abi:n}),s=(0,P.resolve)(process.cwd(),r,o||"."),l=(0,P.resolve)(s,`${e}.md`),f=(0,J.generateMarkdown)({contract:a,contractFile:(0,P.relative)(s,t),contractName:e,abi:n});await(0,T.mkdir)(s,{recursive:!0}),await(0,T.writeFile)(l,f)}async function yt(t){if(!t.docs)return;let r=`# Contracts
|
|
73
60
|
|
|
74
61
|
${t.contracts.map(o=>{let i=o.file.replace(".clar",".md");return`- [\`${o.name}\`](${i})`}).join(`
|
|
75
62
|
`)}
|
|
76
|
-
`,
|
|
77
|
-
${
|
|
78
|
-
${
|
|
63
|
+
`,n=(0,P.resolve)(process.cwd(),t.docs,"README.md");await(0,T.writeFile)(n,r)}var N=require("@clarigen/core");var U=require("path"),dt=require("fs/promises"),W=require("util");function zt(t){let{abi:e}=t,r=[],$=e,{functions:n,variables:o,maps:i}=$,a=V($,["functions","variables","maps"]);n.forEach(c=>{let u=`${(0,N.toCamelCase)(c.name)}: `,k=`[${c.args.map(tt=>`${Z(tt.name)}: ${p(tt.type,!0)}`).join(", ")}]`;u+=JSON.stringify(c);let Nt=p(c.outputs.type);u+=` as TypedAbiFunction<${k}, ${Nt}>`,r.push(u)});let s=t.variables.map(c=>{let u=`${(0,N.toCamelCase)(c.name)}: `,v=p(c.type);return u+=`${(0,W.inspect)(c,!1,null,!1)} as TypedAbiVariable<${v}>`,u}),f=t.variables.filter(c=>c.access==="constant").map(c=>`"${(0,N.toCamelCase)(c.name)}": ${qt(c.defaultValue)}`),b=i.map(c=>{let u=`${(0,N.toCamelCase)(c.name)}: `,v=p(c.key),k=p(c.value);return u+=JSON.stringify(c),u+=` as TypedAbiMap<${v}, ${k}>`,u}),A=JSON.stringify(a),C=(0,U.relative)(process.cwd(),t.contractFile);return`{
|
|
64
|
+
${R("functions",r)}
|
|
65
|
+
${R("variables",s)}
|
|
66
|
+
${R("maps",b)}
|
|
67
|
+
${R("constants",f)}
|
|
68
|
+
${A.slice(1,-1)},
|
|
69
|
+
contractName: '${t.contractName}',
|
|
70
|
+
contractFile: '${C}',
|
|
71
|
+
}`}async function $t(t,e){let r=e.map(a=>{let s=zt(a);return`${(0,N.toCamelCase)(a.contractName)}: ${s}`}),n=await Ht(),o=Kt(t);return`
|
|
72
|
+
${n}
|
|
73
|
+
|
|
74
|
+
export const contracts: Record<string, TypedAbi> = {
|
|
75
|
+
${r.join(`,
|
|
76
|
+
`)}
|
|
77
|
+
} as const;
|
|
78
|
+
|
|
79
|
+
${o}
|
|
80
|
+
`}function Kt(t){let e="";return"accounts"in t&&(e=`export const accounts = {
|
|
81
|
+
${Object.keys(t.accounts).map(n=>{let o=t.accounts[n];return`"${n}": {
|
|
82
|
+
mnemonic: "${o.mnemonic}",
|
|
83
|
+
balance: ${o.balance.toString()}n,
|
|
84
|
+
address: "${o.address}",
|
|
85
|
+
},`}).join(`
|
|
86
|
+
`)}
|
|
87
|
+
} as const;`),e}Uint8Array.prototype[W.inspect.custom]=function(){return`Uint8Array.from([${this.join(",")}])`};function qt(t){return(0,W.inspect)(t,!1,null,!1)}function R(t,e){return`"${t}": {
|
|
88
|
+
${e.join(`,
|
|
89
|
+
`)}
|
|
90
|
+
},`}async function Ht(){let t=(0,U.resolve)(__dirname,"../../../core/src/abi-types.ts");return await(0,dt.readFile)(t,{encoding:"utf-8"})}var bt=require("fs/promises"),xt=require("path"),z=require("prettier"),Qt={printWidth:80,semi:!0,singleQuote:!0,trailingComma:"es5"};async function Xt(){try{let t=await(0,z.resolveConfig)(process.cwd());if(t)return t}catch{}return Qt}async function Yt(t,e){try{let r=(0,xt.basename)(e),n=await Xt();return(0,z.format)(t,x(y({},n),{filepath:r}))}catch{}return t}async function j(t,e){let r=await Yt(e,t);await(0,bt.writeFile)(t,r)}var wt=require("@clarigen/core"),At=require("@clarigen/native-bin"),ht=require("micro-stacks/clarity");async function Ft({abi:t,contractIdentifier:e,provider:r}){let n=t.variables.map(i=>Zt({variable:i,provider:r,contractIdentifier:e}));return await Promise.all(n)}async function Zt({contractIdentifier:t,variable:e,provider:r}){let n=Gt(e),o=await(0,At.evalRaw)({contractAddress:t,code:n,provider:r}),i=(0,ht.hexToCV)(o.output_serialized),a=(0,wt.cvToValue)(i,!0);return x(y({},e),{defaultValue:a})}function Gt(t){let{access:e}=t;return e==="variable"?`(var-get ${t.name})`:t.name}var te=async({contractFile:t,outputFolder:e,provider:r,contractAddress:n,dirName:o,contractName:i,docsPath:a})=>{let s=(0,g.resolve)(process.cwd(),t),l=`${n}.${i}`,f=await(0,K.deployContract)({contractIdentifier:l,contractFilePath:s,provider:r}),b=await Ft({abi:f,contractIdentifier:l,provider:r}),A=ut(f,i),C=mt({contractFile:(0,g.relative)(process.cwd(),s),contractAddress:n,contractName:i}),$=pt({contractName:i,abi:f});typeof a<"u"&&await Ct({contractFile:s,contractName:i,abi:f,docsPath:a,dirName:o});let c=(0,g.resolve)(e,o||".",i);return await(0,Tt.mkdir)(c,{recursive:!0}),await j((0,g.resolve)(c,"abi.ts"),$),await j((0,g.resolve)(c,"index.ts"),C),await j((0,g.resolve)(c,"types.ts"),A),{abi:f,contractFile:s,contractName:i,dirName:o,contractAddress:n,variables:b}},q=async t=>{let e=await M(t),{contractsDir:r,outputDir:n,contracts:o}=e,i=(0,g.resolve)(t,n),a=await(0,K.createClarityBin)(),s=[];for(let C of o){let $=(0,g.resolve)(t,r,C.file),c=(0,g.dirname)(C.file),u=await te({contractFile:$,outputFolder:i,provider:a,contractAddress:C.address,dirName:c,contractName:C.name,docsPath:e.docs});s.push(u)}let l=gt(e);await yt(e);let f=(0,g.resolve)(i,"index.ts");await j(f,l);let b=await $t(e,s),A=(0,g.resolve)(i,"single.ts");await j(A,b)};var vt=require("chokidar"),Pt=require("path"),I=require("chalk"),ee=require("ora"),G=class extends E.Command{async run(){let{flags:e}=this.parse(G),r=process.cwd();if(e.watch){let n=ee("Generating files").start(),{contractsDir:o}=await M(r),i=(0,vt.watch)([o],{cwd:r});try{await q(r),n.succeed("Finished generating files. Watching for changes.")}catch(a){n.fail(`Error generating files.
|
|
91
|
+
${a.message}`)}i.on("change",async a=>{let s=(0,Pt.basename)(a);n.clear(),n.start(`Change detected for ${(0,I.green)(s)}, generating.`);try{await q(r),n.succeed(`Finished generating files for ${(0,I.green)(s)}. Watching for changes.`)}catch(l){let f=l.message;n.fail(`Error after saving ${(0,I.red)(s)}.
|
|
92
|
+
${f}`)}}),process.on("SIGINT",async()=>{await i.close(),process.exit()})}else await q(r)}},w=G;w.description="Generate project files",w.strict=!0,w.hidden=!1,w.flags={help:E.flags.help({char:"h"}),watch:E.flags.boolean({char:"w",description:"Watch for changes to your contracts"})},w.args=[];0&&(module.exports={Generate});
|
package/dist/commands/index.mjs
CHANGED
|
@@ -1,35 +1,22 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,!0,{longer:!0})}async function
|
|
3
|
-
`,!0)}async function
|
|
4
|
-
${
|
|
1
|
+
var lt=Object.defineProperty,pt=Object.defineProperties;var ft=Object.getOwnPropertyDescriptors;var N=Object.getOwnPropertySymbols;var R=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var M=(t,r,e)=>r in t?lt(t,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[r]=e,C=(t,r)=>{for(var e in r||(r={}))R.call(r,e)&&M(t,e,r[e]);if(N)for(var e of N(r))B.call(r,e)&&M(t,e,r[e]);return t},x=(t,r)=>pt(t,ft(r));var mt=(t=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(t,{get:(r,e)=>(typeof require!="undefined"?require:r)[e]}):t)(function(t){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var j=(t,r)=>{var e={};for(var n in t)R.call(t,n)&&r.indexOf(n)<0&&(e[n]=t[n]);if(t!=null&&N)for(var n of N(t))r.indexOf(n)<0&&B.call(t,n)&&(e[n]=t[n]);return e};import{fileURLToPath as ut}from"url";import gt from"path";var Ct=()=>ut(import.meta.url),yt=()=>gt.dirname(Ct()),u=yt();import{Command as be,flags as st}from"@oclif/command";import{hasStdErr as rr}from"@clarigen/native-bin";import{toCamelCase as F}from"@clarigen/core";import{dirname as Bt,join as Jt}from"path";import{run as Qe}from"@oclif/command";import{resolve as H,join as Ft,relative as Tt}from"path";import{readFile as vt,access as Pt}from"fs/promises";import{constants as Nt}from"fs";import{parse as J}from"@ltd/j-toml";import{resolve as U}from"path";import{readFile as W}from"fs/promises";import{generateWallet as dt,getStxAddressFromAccount as $t}from"micro-stacks/wallet-sdk";import{array as bt}from"toposort";import{StacksNetworkVersion as xt}from"micro-stacks/crypto";async function wt(t){let r=U(t,"settings","Devnet.toml"),e=await W(r,{encoding:"utf-8"});return J(e,1,`
|
|
2
|
+
`,!0,{longer:!0})}async function At(t){let r=U(t,"Clarinet.toml"),e=await W(r,{encoding:"utf-8"});return J(e,1,`
|
|
3
|
+
`,!0)}async function z(t,r){let e=await At(t),n=r.deployer.address;return ht(e.contracts).map(a=>({file:e.contracts[a].path.replace(/^contracts\//,""),address:n,name:a}))}function ht(t){let r=[],e=[];return Object.entries(t).forEach(([o,i])=>{e.push(o),i.depends_on.forEach(a=>r.push([o,a]))}),bt(e,r).reverse()}async function K(t){let r=await wt(t),e=await Promise.all(Object.entries(r.accounts).map(async([o,i])=>{let a=await dt(i.mnemonic,"password"),[s]=a.accounts,l=$t(s,xt.testnetP2PKH);return[o,x(C({},i),{address:l})]}));return Object.fromEntries(e)}var q={outputDir:"src/clarigen",clarinet:"."};function jt(t){return H(t,"clarigen.config.json")}async function Et(t){try{return await Pt(t,Nt.R_OK),!0}catch{return!1}}async function It(t){let r=jt(t);if(await Et(r)){let n=await vt(r,{encoding:"utf-8"}),o=JSON.parse(n);return C(C({},q),o)}return q}async function E(t){let r=await It(t),e=H(t,r.clarinet||"."),n=await K(e),o=await z(e,n),i=Tt(process.cwd(),Ft(r.clarinet,"contracts"));return x(C({},r),{contracts:o,contractsDir:i,accounts:n,clarinet:r.clarinet||"."})}import{isClarityAbiBuffer as kt,isClarityAbiList as St,isClarityAbiOptional as Dt,isClarityAbiPrimitive as Vt,isClarityAbiResponse as Q,isClarityAbiStringAscii as Ot,isClarityAbiStringUtf8 as Lt,isClarityAbiTuple as _t}from"micro-stacks/transactions";import{toCamelCase as S}from"@clarigen/core";import{check as Mt}from"reserved-words";var f=(t,r=!1)=>{if(Vt(t)){if(t==="uint128")return r?"number | bigint":"bigint";if(t==="int128")return r?"number | bigint":"bigint";if(t==="bool")return"boolean";if(t==="principal")return"string";if(t==="none")return"null";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(t)}`)}else{if(kt(t))return"Uint8Array";if(Q(t)){let e=f(t.response.ok),n=f(t.response.error);return`Response<${e}, ${n}>`}else{if(Dt(t))return`${f(t.optional)} | null`;if(_t(t)){let e=[];return t.tuple.forEach(({name:n,type:o})=>{let i=f(o);e.push(`"${n}": ${i}`)}),`{
|
|
4
|
+
${e.join(`;
|
|
5
5
|
`)}
|
|
6
|
-
}`}else{if(
|
|
7
|
-
`} ${o}`}),t.maps.forEach(
|
|
8
|
-
${
|
|
9
|
-
${o.stderr}
|
|
10
|
-
`);let i=JSON.parse(o.stdout);if(i.error){let{initialization:s}=i.error;if(s!=null&&s.includes(`
|
|
11
|
-
Near:
|
|
12
|
-
`)){let[a,f]=s.split(`
|
|
13
|
-
Near:
|
|
14
|
-
`),p="",g=/start_line: (\d+),/.exec(f);throw g&&(p=g[1]),new Error(`Error on ${n}:
|
|
15
|
-
${a}
|
|
16
|
-
${p?`Near line ${p}`:""}
|
|
17
|
-
Raw trace:
|
|
18
|
-
${f}
|
|
19
|
-
`)}throw new Error(`Error on ${n}:
|
|
20
|
-
${JSON.stringify(i.error,null,2)}
|
|
21
|
-
`)}return i.analysis},W=({contractName:t,abi:n})=>{let r=x(t,!0),s=n,{clarity_version:e}=s,o=D(s,["clarity_version"]),i=JSON.stringify(o,null,2);return`import { ClarityAbi } from '@clarigen/core';
|
|
6
|
+
}`}else{if(St(t))return`${f(t.list.type)}[]`;if(Ot(t))return"string";if(Lt(t))return"string";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(t)}`)}}}};function D(t){let r=S(t);return`${Mt(r,6)?"_":""}${r}`}var Rt={public:"Public",read_only:"ReadOnly",private:"Private"};function X(t){let r="";return t.functions.forEach((e,n)=>{let o=`${S(e.name)}: `;if(o+=`(${e.args.map(s=>`${D(s.name)}: ${f(s.type,!0)}`).join(", ")}) => `,o+=`ContractCalls.${Rt[e.access]}<`,e.access==="public"){let{type:s}=e.outputs;if(!Q(s))throw new Error("Expected response type for public function");let l=f(s.response.ok),p=f(s.response.error);o+=`${l}, ${p}>;`}else o+=`${f(e.outputs.type)}>;`;r+=`${n===0?"":`
|
|
7
|
+
`} ${o}`}),t.maps.forEach(e=>{let n=`${S(e.name)}: `,o=f(e.key,!0),i=`key: ${o}`,a=f(e.value);n+=`(${i}) => ContractCalls.Map<${o}, ${a}>;`,r+=`
|
|
8
|
+
${n}`}),r}var Y=({contractName:t,abi:r})=>{let e=F(t,!0),s=r,{clarity_version:n}=s,o=j(s,["clarity_version"]),i=JSON.stringify(o,null,2);return`import { ClarityAbi } from '@clarigen/core';
|
|
22
9
|
|
|
23
10
|
// prettier-ignore
|
|
24
|
-
export const ${
|
|
25
|
-
`},
|
|
11
|
+
export const ${e}Interface: ClarityAbi = ${i};
|
|
12
|
+
`},Z=({contractFile:t,contractAddress:r,contractName:e})=>{let n=F(e,!0),o=F(e),i=`${n}Contract`,a=`${n}Interface`;return`import { pureProxy, Contract } from '@clarigen/core';
|
|
26
13
|
import type { ${i} } from './types';
|
|
27
|
-
import { ${
|
|
14
|
+
import { ${a} } from './abi';
|
|
28
15
|
export type { ${i} } from './types';
|
|
29
16
|
|
|
30
17
|
export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
31
18
|
return pureProxy<${i}>({
|
|
32
|
-
abi: ${
|
|
19
|
+
abi: ${a},
|
|
33
20
|
contractAddress,
|
|
34
21
|
contractName,
|
|
35
22
|
});
|
|
@@ -37,42 +24,69 @@ export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
|
37
24
|
|
|
38
25
|
export const ${o}Info: Contract<${i}> = {
|
|
39
26
|
contract: ${o}Contract,
|
|
40
|
-
address: '${
|
|
27
|
+
address: '${r}',
|
|
41
28
|
contractFile: '${t}',
|
|
42
|
-
name: '${
|
|
43
|
-
abi: ${
|
|
29
|
+
name: '${e}',
|
|
30
|
+
abi: ${a},
|
|
44
31
|
};
|
|
45
|
-
`},
|
|
32
|
+
`},G=(t,r)=>{let e=F(r,!0),n=X(t);return`import { Response, ContractCalls } from '@clarigen/core';
|
|
46
33
|
|
|
47
34
|
// prettier-ignore
|
|
48
|
-
export interface ${
|
|
49
|
-
${
|
|
35
|
+
export interface ${e}Contract {
|
|
36
|
+
${n}
|
|
50
37
|
}
|
|
51
|
-
`},
|
|
38
|
+
`},tt=t=>{let r=["import type { ContractInstances } from '@clarigen/core';"],e=[],n=[],o="";"accounts"in t&&(o=`
|
|
52
39
|
|
|
53
40
|
// prettier-ignore
|
|
54
41
|
export const accounts = {
|
|
55
|
-
${Object.keys(t.accounts).map(
|
|
56
|
-
mnemonic: "${
|
|
57
|
-
balance: ${
|
|
58
|
-
address: "${
|
|
42
|
+
${Object.keys(t.accounts).map(l=>{let p=t.accounts[l];return`"${l}": {
|
|
43
|
+
mnemonic: "${p.mnemonic}",
|
|
44
|
+
balance: ${p.balance.toString()}n,
|
|
45
|
+
address: "${p.address}",
|
|
59
46
|
},`}).join(`
|
|
60
47
|
`)}
|
|
61
|
-
};`),t.contracts.forEach(s=>{let
|
|
48
|
+
};`),t.contracts.forEach(s=>{let l=s.name,p=F(l),b=`${p}Info`,w=`${F(l,!0)}Contract`,g=Bt(s.file),d=`'./${Jt(g||".",l)}'`,c=`import { ${b} } from ${d};`;r.push(c);let m=`export type { ${w} } from ${d};`;e.push(m);let h=`${p}: ${b},`;n.push(h)});let i=`
|
|
62
49
|
export type Contracts = ContractInstances<typeof contracts>;
|
|
63
|
-
`;return`${
|
|
50
|
+
`;return`${r.join(`
|
|
64
51
|
`)}
|
|
65
|
-
${
|
|
52
|
+
${e.join(`
|
|
66
53
|
`)}
|
|
67
54
|
${i}
|
|
68
55
|
export const contracts = {
|
|
69
|
-
${
|
|
56
|
+
${n.join(`
|
|
70
57
|
`)}
|
|
71
58
|
};${o}
|
|
72
|
-
`};import{createClarityBin as
|
|
59
|
+
`};import{createClarityBin as ue,deployContract as ge}from"@clarigen/native-bin";import{resolve as $,relative as Ce,dirname as ye}from"path";import{mkdir as de}from"fs/promises";import{createContractDocInfo as Ut,generateMarkdown as Wt}from"@clarigen/claridocs";import{mkdir as zt,readFile as Kt,writeFile as et}from"fs/promises";import{relative as qt,resolve as V}from"path";async function rt({contractFile:t,contractName:r,docsPath:e,abi:n,dirName:o}){let i=await Kt(t,{encoding:"utf-8"}),a=Ut({contractSrc:i,abi:n}),s=V(process.cwd(),e,o||"."),l=V(s,`${r}.md`),p=Wt({contract:a,contractFile:qt(s,t),contractName:r,abi:n});await zt(s,{recursive:!0}),await et(l,p)}async function nt(t){if(!t.docs)return;let e=`# Contracts
|
|
73
60
|
|
|
74
61
|
${t.contracts.map(o=>{let i=o.file.replace(".clar",".md");return`- [\`${o.name}\`](${i})`}).join(`
|
|
75
62
|
`)}
|
|
76
|
-
`,
|
|
77
|
-
${
|
|
78
|
-
${
|
|
63
|
+
`,n=V(process.cwd(),t.docs,"README.md");await et(n,e)}import{toCamelCase as v}from"@clarigen/core";import{relative as Ht,resolve as Qt}from"path";import{readFile as Xt}from"fs/promises";import{inspect as O}from"util";function Yt(t){let{abi:r}=t,e=[],d=r,{functions:n,variables:o,maps:i}=d,a=j(d,["functions","variables","maps"]);n.forEach(c=>{let m=`${v(c.name)}: `,P=`[${c.args.map(_=>`${D(_.name)}: ${f(_.type,!0)}`).join(", ")}]`;m+=JSON.stringify(c);let ct=f(c.outputs.type);m+=` as TypedAbiFunction<${P}, ${ct}>`,e.push(m)});let s=t.variables.map(c=>{let m=`${v(c.name)}: `,h=f(c.type);return m+=`${O(c,!1,null,!1)} as TypedAbiVariable<${h}>`,m}),p=t.variables.filter(c=>c.access==="constant").map(c=>`"${v(c.name)}": ${Gt(c.defaultValue)}`),b=i.map(c=>{let m=`${v(c.name)}: `,h=f(c.key),P=f(c.value);return m+=JSON.stringify(c),m+=` as TypedAbiMap<${h}, ${P}>`,m}),w=JSON.stringify(a),g=Ht(process.cwd(),t.contractFile);return`{
|
|
64
|
+
${I("functions",e)}
|
|
65
|
+
${I("variables",s)}
|
|
66
|
+
${I("maps",b)}
|
|
67
|
+
${I("constants",p)}
|
|
68
|
+
${w.slice(1,-1)},
|
|
69
|
+
contractName: '${t.contractName}',
|
|
70
|
+
contractFile: '${g}',
|
|
71
|
+
}`}async function ot(t,r){let e=r.map(a=>{let s=Yt(a);return`${v(a.contractName)}: ${s}`}),n=await te(),o=Zt(t);return`
|
|
72
|
+
${n}
|
|
73
|
+
|
|
74
|
+
export const contracts: Record<string, TypedAbi> = {
|
|
75
|
+
${e.join(`,
|
|
76
|
+
`)}
|
|
77
|
+
} as const;
|
|
78
|
+
|
|
79
|
+
${o}
|
|
80
|
+
`}function Zt(t){let r="";return"accounts"in t&&(r=`export const accounts = {
|
|
81
|
+
${Object.keys(t.accounts).map(n=>{let o=t.accounts[n];return`"${n}": {
|
|
82
|
+
mnemonic: "${o.mnemonic}",
|
|
83
|
+
balance: ${o.balance.toString()}n,
|
|
84
|
+
address: "${o.address}",
|
|
85
|
+
},`}).join(`
|
|
86
|
+
`)}
|
|
87
|
+
} as const;`),r}Uint8Array.prototype[O.custom]=function(){return`Uint8Array.from([${this.join(",")}])`};function Gt(t){return O(t,!1,null,!1)}function I(t,r){return`"${t}": {
|
|
88
|
+
${r.join(`,
|
|
89
|
+
`)}
|
|
90
|
+
},`}async function te(){let t=Qt(u,"../../../core/src/abi-types.ts");return await Xt(t,{encoding:"utf-8"})}import{writeFile as ee}from"fs/promises";import{basename as re}from"path";import{resolveConfig as ne,format as oe}from"prettier";var ie={printWidth:80,semi:!0,singleQuote:!0,trailingComma:"es5"};async function se(){try{let t=await ne(process.cwd());if(t)return t}catch{}return ie}async function ae(t,r){try{let e=re(r),n=await se();return oe(t,x(C({},n),{filepath:e}))}catch{}return t}async function T(t,r){let e=await ae(r,t);await ee(t,e)}import{cvToValue as ce}from"@clarigen/core";import{evalRaw as le}from"@clarigen/native-bin";import{hexToCV as pe}from"micro-stacks/clarity";async function it({abi:t,contractIdentifier:r,provider:e}){let n=t.variables.map(i=>fe({variable:i,provider:e,contractIdentifier:r}));return await Promise.all(n)}async function fe({contractIdentifier:t,variable:r,provider:e}){let n=me(r),o=await le({contractAddress:t,code:n,provider:e}),i=pe(o.output_serialized),a=ce(i,!0);return x(C({},r),{defaultValue:a})}function me(t){let{access:r}=t;return r==="variable"?`(var-get ${t.name})`:t.name}var $e=async({contractFile:t,outputFolder:r,provider:e,contractAddress:n,dirName:o,contractName:i,docsPath:a})=>{let s=$(process.cwd(),t),l=`${n}.${i}`,p=await ge({contractIdentifier:l,contractFilePath:s,provider:e}),b=await it({abi:p,contractIdentifier:l,provider:e}),w=G(p,i),g=Z({contractFile:Ce(process.cwd(),s),contractAddress:n,contractName:i}),d=Y({contractName:i,abi:p});typeof a<"u"&&await rt({contractFile:s,contractName:i,abi:p,docsPath:a,dirName:o});let c=$(r,o||".",i);return await de(c,{recursive:!0}),await T($(c,"abi.ts"),d),await T($(c,"index.ts"),g),await T($(c,"types.ts"),w),{abi:p,contractFile:s,contractName:i,dirName:o,contractAddress:n,variables:b}},k=async t=>{let r=await E(t),{contractsDir:e,outputDir:n,contracts:o}=r,i=$(t,n),a=await ue(),s=[];for(let g of o){let d=$(t,e,g.file),c=ye(g.file),m=await $e({contractFile:d,outputFolder:i,provider:a,contractAddress:g.address,dirName:c,contractName:g.name,docsPath:r.docs});s.push(m)}let l=tt(r);await nt(r);let p=$(i,"index.ts");await T(p,l);let b=await ot(r,s),w=$(i,"single.ts");await T(w,b)};import{watch as xe}from"chokidar";import{basename as we}from"path";import{red as Ae,green as at}from"chalk";var he=mt("ora"),L=class extends be{async run(){let{flags:r}=this.parse(L),e=process.cwd();if(r.watch){let n=he("Generating files").start(),{contractsDir:o}=await E(e),i=xe([o],{cwd:e});try{await k(e),n.succeed("Finished generating files. Watching for changes.")}catch(a){n.fail(`Error generating files.
|
|
91
|
+
${a.message}`)}i.on("change",async a=>{let s=we(a);n.clear(),n.start(`Change detected for ${at(s)}, generating.`);try{await k(e),n.succeed(`Finished generating files for ${at(s)}. Watching for changes.`)}catch(l){let p=l.message;n.fail(`Error after saving ${Ae(s)}.
|
|
92
|
+
${p}`)}}),process.on("SIGINT",async()=>{await i.close(),process.exit()})}else await k(e)}},A=L;A.description="Generate project files",A.strict=!0,A.hidden=!1,A.flags={help:st.help({char:"h"}),watch:st.boolean({char:"w",description:"Watch for changes to your contracts"})},A.args=[];export{A as Generate};
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ declare function getConfigFile(rootPath: string): Promise<ConfigFileContents>;
|
|
|
40
40
|
declare function getProjectConfig(rootPath: string): Promise<ConfigFile>;
|
|
41
41
|
|
|
42
42
|
declare const jsTypeFromAbiType: (val: ClarityAbiType, isArgument?: boolean) => string;
|
|
43
|
+
declare function getArgName(name: string): string;
|
|
43
44
|
declare function makePureTypes(abi: ClarityAbi): string;
|
|
44
45
|
|
|
45
46
|
declare const generateInterface: ({ provider, contractFile, contractAddress, contractName, }: {
|
|
@@ -60,4 +61,4 @@ declare const generateIndexFile: ({ contractFile, contractAddress, contractName,
|
|
|
60
61
|
declare const generateTypesFile: (abi: ClarityAbi, contractName: string) => string;
|
|
61
62
|
declare const generateProjectIndexFile: (config: ConfigFile) => string;
|
|
62
63
|
|
|
63
|
-
export { ConfigContract, ConfigFile, ConfigFileContents, configFileExists, configFilePath, defaultConfigFile, generateIndexFile, generateInterface, generateInterfaceFile, generateProjectIndexFile, generateTypesFile, getConfigFile, getProjectConfig, jsTypeFromAbiType, makePureTypes };
|
|
64
|
+
export { ConfigContract, ConfigFile, ConfigFileContents, configFileExists, configFilePath, defaultConfigFile, generateIndexFile, generateInterface, generateInterfaceFile, generateProjectIndexFile, generateTypesFile, getArgName, getConfigFile, getProjectConfig, jsTypeFromAbiType, makePureTypes };
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,!0,{longer:!0})}async function
|
|
3
|
-
`,!0)}async function
|
|
4
|
-
${
|
|
1
|
+
var V=Object.defineProperty,Dt=Object.defineProperties,Vt=Object.getOwnPropertyDescriptor,Ot=Object.getOwnPropertyDescriptors,Lt=Object.getOwnPropertyNames,D=Object.getOwnPropertySymbols;var Q=Object.prototype.hasOwnProperty,ct=Object.prototype.propertyIsEnumerable;var at=(t,e,r)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e)=>{for(var r in e||(e={}))Q.call(e,r)&&at(t,r,e[r]);if(D)for(var r of D(e))ct.call(e,r)&&at(t,r,e[r]);return t},w=(t,e)=>Dt(t,Ot(e));var O=(t,e)=>{var r={};for(var n in t)Q.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&D)for(var n of D(t))e.indexOf(n)<0&&ct.call(t,n)&&(r[n]=t[n]);return r};var Mt=(t,e)=>{for(var r in e)V(t,r,{get:e[r],enumerable:!0})},_t=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Lt(e))!Q.call(t,o)&&o!==r&&V(t,o,{get:()=>e[o],enumerable:!(n=Vt(e,o))||n.enumerable});return t};var Bt=t=>_t(V({},"__esModule",{value:!0}),t);var ne={};Mt(ne,{Generate:()=>A,configFileExists:()=>Ct,configFilePath:()=>gt,defaultConfigFile:()=>G,generateIndexFile:()=>rt,generateInterface:()=>zt,generateInterfaceFile:()=>et,generateProjectIndexFile:()=>ot,generateTypesFile:()=>nt,getArgName:()=>B,getConfigFile:()=>yt,getProjectConfig:()=>E,jsTypeFromAbiType:()=>p,makePureTypes:()=>tt,run:()=>kt.run});module.exports=Bt(ne);var kt=require("@oclif/command");var h=require("path"),M=require("fs/promises"),ut=require("fs");var X=require("@ltd/j-toml"),Y=require("path"),Z=require("fs/promises"),L=require("micro-stacks/wallet-sdk"),lt=require("toposort"),ft=require("micro-stacks/crypto");async function Jt(t){let e=(0,Y.resolve)(t,"settings","Devnet.toml"),r=await(0,Z.readFile)(e,{encoding:"utf-8"});return(0,X.parse)(r,1,`
|
|
2
|
+
`,!0,{longer:!0})}async function Rt(t){let e=(0,Y.resolve)(t,"Clarinet.toml"),r=await(0,Z.readFile)(e,{encoding:"utf-8"});return(0,X.parse)(r,1,`
|
|
3
|
+
`,!0)}async function pt(t,e){let r=await Rt(t),n=e.deployer.address;return Ut(r.contracts).map(a=>({file:r.contracts[a].path.replace(/^contracts\//,""),address:n,name:a}))}function Ut(t){let e=[],r=[];return Object.entries(t).forEach(([o,i])=>{r.push(o),i.depends_on.forEach(a=>e.push([o,a]))}),(0,lt.array)(r,e).reverse()}async function mt(t){let e=await Jt(t),r=await Promise.all(Object.entries(e.accounts).map(async([o,i])=>{let a=await(0,L.generateWallet)(i.mnemonic,"password"),[s]=a.accounts,f=(0,L.getStxAddressFromAccount)(s,ft.StacksNetworkVersion.testnetP2PKH);return[o,w(d({},i),{address:f})]}));return Object.fromEntries(r)}var G={outputDir:"src/clarigen",clarinet:"."};function gt(t){return(0,h.resolve)(t,"clarigen.config.json")}async function Ct(t){try{return await(0,M.access)(t,ut.constants.R_OK),!0}catch{return!1}}async function yt(t){let e=gt(t);if(await Ct(e)){let n=await(0,M.readFile)(e,{encoding:"utf-8"}),o=JSON.parse(n);return d(d({},G),o)}return G}async function E(t){let e=await yt(t),r=(0,h.resolve)(t,e.clarinet||"."),n=await mt(r),o=await pt(r,n),i=(0,h.relative)(process.cwd(),(0,h.join)(e.clarinet,"contracts"));return w(d({},e),{contracts:o,contractsDir:i,accounts:n,clarinet:e.clarinet||"."})}var m=require("micro-stacks/transactions"),_=require("@clarigen/core"),dt=require("reserved-words"),p=(t,e=!1)=>{if((0,m.isClarityAbiPrimitive)(t)){if(t==="uint128")return e?"number | bigint":"bigint";if(t==="int128")return e?"number | bigint":"bigint";if(t==="bool")return"boolean";if(t==="principal")return"string";if(t==="none")return"null";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(t)}`)}else{if((0,m.isClarityAbiBuffer)(t))return"Uint8Array";if((0,m.isClarityAbiResponse)(t)){let r=p(t.response.ok),n=p(t.response.error);return`Response<${r}, ${n}>`}else{if((0,m.isClarityAbiOptional)(t))return`${p(t.optional)} | null`;if((0,m.isClarityAbiTuple)(t)){let r=[];return t.tuple.forEach(({name:n,type:o})=>{let i=p(o);r.push(`"${n}": ${i}`)}),`{
|
|
4
|
+
${r.join(`;
|
|
5
5
|
`)}
|
|
6
|
-
}`}else{if((0,
|
|
7
|
-
`} ${o}`}),t.maps.forEach(
|
|
8
|
-
${
|
|
6
|
+
}`}else{if((0,m.isClarityAbiList)(t))return`${p(t.list.type)}[]`;if((0,m.isClarityAbiStringAscii)(t))return"string";if((0,m.isClarityAbiStringUtf8)(t))return"string";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(t)}`)}}}};function B(t){let e=(0,_.toCamelCase)(t);return`${(0,dt.check)(e,6)?"_":""}${e}`}var Wt={public:"Public",read_only:"ReadOnly",private:"Private"};function tt(t){let e="";return t.functions.forEach((r,n)=>{let o=`${(0,_.toCamelCase)(r.name)}: `;if(o+=`(${r.args.map(s=>`${B(s.name)}: ${p(s.type,!0)}`).join(", ")}) => `,o+=`ContractCalls.${Wt[r.access]}<`,r.access==="public"){let{type:s}=r.outputs;if(!(0,m.isClarityAbiResponse)(s))throw new Error("Expected response type for public function");let f=p(s.response.ok),l=p(s.response.error);o+=`${f}, ${l}>;`}else o+=`${p(r.outputs.type)}>;`;e+=`${n===0?"":`
|
|
7
|
+
`} ${o}`}),t.maps.forEach(r=>{let n=`${(0,_.toCamelCase)(r.name)}: `,o=p(r.key,!0),i=`key: ${o}`,a=p(r.value);n+=`(${i}) => ContractCalls.Map<${o}, ${a}>;`,e+=`
|
|
8
|
+
${n}`}),e}var $t=require("@clarigen/native-bin"),F=require("@clarigen/core"),J=require("path");var zt=async({provider:t,contractFile:e,contractAddress:r,contractName:n})=>{let o=await t.runCommand(["launch",`${r}.${n}`,e,t.dbFilePath,"--output_analysis","--costs","--assets"]);if((0,$t.hasStdErr)(o.stderr))throw new Error(`Error on ${e}:
|
|
9
9
|
${o.stderr}
|
|
10
10
|
`);let i=JSON.parse(o.stdout);if(i.error){let{initialization:s}=i.error;if(s!=null&&s.includes(`
|
|
11
11
|
Near:
|
|
12
|
-
`)){let[
|
|
12
|
+
`)){let[f,l]=s.split(`
|
|
13
13
|
Near:
|
|
14
|
-
`),
|
|
15
|
-
${a}
|
|
16
|
-
${u?`Near line ${u}`:""}
|
|
17
|
-
Raw trace:
|
|
14
|
+
`),y="",C=/start_line: (\d+),/.exec(l);throw C&&(y=C[1]),new Error(`Error on ${e}:
|
|
18
15
|
${f}
|
|
19
|
-
|
|
16
|
+
${y?`Near line ${y}`:""}
|
|
17
|
+
Raw trace:
|
|
18
|
+
${l}
|
|
19
|
+
`)}throw new Error(`Error on ${e}:
|
|
20
20
|
${JSON.stringify(i.error,null,2)}
|
|
21
|
-
`)}return i.analysis},
|
|
21
|
+
`)}return i.analysis},et=({contractName:t,abi:e})=>{let r=(0,F.toCamelCase)(t,!0),s=e,{clarity_version:n}=s,o=O(s,["clarity_version"]),i=JSON.stringify(o,null,2);return`import { ClarityAbi } from '@clarigen/core';
|
|
22
22
|
|
|
23
23
|
// prettier-ignore
|
|
24
|
-
export const ${
|
|
25
|
-
`},
|
|
24
|
+
export const ${r}Interface: ClarityAbi = ${i};
|
|
25
|
+
`},rt=({contractFile:t,contractAddress:e,contractName:r})=>{let n=(0,F.toCamelCase)(r,!0),o=(0,F.toCamelCase)(r),i=`${n}Contract`,a=`${n}Interface`;return`import { pureProxy, Contract } from '@clarigen/core';
|
|
26
26
|
import type { ${i} } from './types';
|
|
27
|
-
import { ${
|
|
27
|
+
import { ${a} } from './abi';
|
|
28
28
|
export type { ${i} } from './types';
|
|
29
29
|
|
|
30
30
|
export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
31
31
|
return pureProxy<${i}>({
|
|
32
|
-
abi: ${
|
|
32
|
+
abi: ${a},
|
|
33
33
|
contractAddress,
|
|
34
34
|
contractName,
|
|
35
35
|
});
|
|
@@ -37,42 +37,69 @@ export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
|
37
37
|
|
|
38
38
|
export const ${o}Info: Contract<${i}> = {
|
|
39
39
|
contract: ${o}Contract,
|
|
40
|
-
address: '${
|
|
40
|
+
address: '${e}',
|
|
41
41
|
contractFile: '${t}',
|
|
42
|
-
name: '${
|
|
43
|
-
abi: ${
|
|
42
|
+
name: '${r}',
|
|
43
|
+
abi: ${a},
|
|
44
44
|
};
|
|
45
|
-
`},
|
|
45
|
+
`},nt=(t,e)=>{let r=(0,F.toCamelCase)(e,!0),n=tt(t);return`import { Response, ContractCalls } from '@clarigen/core';
|
|
46
46
|
|
|
47
47
|
// prettier-ignore
|
|
48
|
-
export interface ${
|
|
49
|
-
${
|
|
48
|
+
export interface ${r}Contract {
|
|
49
|
+
${n}
|
|
50
50
|
}
|
|
51
|
-
`},
|
|
51
|
+
`},ot=t=>{let e=["import type { ContractInstances } from '@clarigen/core';"],r=[],n=[],o="";"accounts"in t&&(o=`
|
|
52
52
|
|
|
53
53
|
// prettier-ignore
|
|
54
54
|
export const accounts = {
|
|
55
|
-
${Object.keys(t.accounts).map(
|
|
56
|
-
mnemonic: "${
|
|
57
|
-
balance: ${
|
|
58
|
-
address: "${
|
|
55
|
+
${Object.keys(t.accounts).map(f=>{let l=t.accounts[f];return`"${f}": {
|
|
56
|
+
mnemonic: "${l.mnemonic}",
|
|
57
|
+
balance: ${l.balance.toString()}n,
|
|
58
|
+
address: "${l.address}",
|
|
59
59
|
},`}).join(`
|
|
60
60
|
`)}
|
|
61
|
-
};`),t.contracts.forEach(s=>{let
|
|
61
|
+
};`),t.contracts.forEach(s=>{let f=s.name,l=(0,F.toCamelCase)(f),y=`${l}Info`,x=`${(0,F.toCamelCase)(f,!0)}Contract`,C=(0,J.dirname)(s.file),b=`'./${(0,J.join)(C||".",f)}'`,c=`import { ${y} } from ${b};`;e.push(c);let u=`export type { ${x} } from ${b};`;r.push(u);let v=`${l}: ${y},`;n.push(v)});let i=`
|
|
62
62
|
export type Contracts = ContractInstances<typeof contracts>;
|
|
63
|
-
`;return`${
|
|
63
|
+
`;return`${e.join(`
|
|
64
64
|
`)}
|
|
65
|
-
${
|
|
65
|
+
${r.join(`
|
|
66
66
|
`)}
|
|
67
67
|
${i}
|
|
68
68
|
export const contracts = {
|
|
69
|
-
${
|
|
69
|
+
${n.join(`
|
|
70
70
|
`)}
|
|
71
71
|
};${o}
|
|
72
|
-
`};var
|
|
72
|
+
`};var I=require("@oclif/command");var q=require("@clarigen/native-bin"),g=require("path"),jt=require("fs/promises");var R=require("@clarigen/claridocs"),T=require("fs/promises"),P=require("path");async function bt({contractFile:t,contractName:e,docsPath:r,abi:n,dirName:o}){let i=await(0,T.readFile)(t,{encoding:"utf-8"}),a=(0,R.createContractDocInfo)({contractSrc:i,abi:n}),s=(0,P.resolve)(process.cwd(),r,o||"."),f=(0,P.resolve)(s,`${e}.md`),l=(0,R.generateMarkdown)({contract:a,contractFile:(0,P.relative)(s,t),contractName:e,abi:n});await(0,T.mkdir)(s,{recursive:!0}),await(0,T.writeFile)(f,l)}async function xt(t){if(!t.docs)return;let r=`# Contracts
|
|
73
73
|
|
|
74
74
|
${t.contracts.map(o=>{let i=o.file.replace(".clar",".md");return`- [\`${o.name}\`](${i})`}).join(`
|
|
75
75
|
`)}
|
|
76
|
-
`,
|
|
77
|
-
${
|
|
78
|
-
${
|
|
76
|
+
`,n=(0,P.resolve)(process.cwd(),t.docs,"README.md");await(0,T.writeFile)(n,r)}var N=require("@clarigen/core");var W=require("path"),wt=require("fs/promises"),z=require("util");function Kt(t){let{abi:e}=t,r=[],b=e,{functions:n,variables:o,maps:i}=b,a=O(b,["functions","variables","maps"]);n.forEach(c=>{let u=`${(0,N.toCamelCase)(c.name)}: `,S=`[${c.args.map(st=>`${B(st.name)}: ${p(st.type,!0)}`).join(", ")}]`;u+=JSON.stringify(c);let St=p(c.outputs.type);u+=` as TypedAbiFunction<${S}, ${St}>`,r.push(u)});let s=t.variables.map(c=>{let u=`${(0,N.toCamelCase)(c.name)}: `,v=p(c.type);return u+=`${(0,z.inspect)(c,!1,null,!1)} as TypedAbiVariable<${v}>`,u}),l=t.variables.filter(c=>c.access==="constant").map(c=>`"${(0,N.toCamelCase)(c.name)}": ${Ht(c.defaultValue)}`),y=i.map(c=>{let u=`${(0,N.toCamelCase)(c.name)}: `,v=p(c.key),S=p(c.value);return u+=JSON.stringify(c),u+=` as TypedAbiMap<${v}, ${S}>`,u}),x=JSON.stringify(a),C=(0,W.relative)(process.cwd(),t.contractFile);return`{
|
|
77
|
+
${U("functions",r)}
|
|
78
|
+
${U("variables",s)}
|
|
79
|
+
${U("maps",y)}
|
|
80
|
+
${U("constants",l)}
|
|
81
|
+
${x.slice(1,-1)},
|
|
82
|
+
contractName: '${t.contractName}',
|
|
83
|
+
contractFile: '${C}',
|
|
84
|
+
}`}async function At(t,e){let r=e.map(a=>{let s=Kt(a);return`${(0,N.toCamelCase)(a.contractName)}: ${s}`}),n=await Qt(),o=qt(t);return`
|
|
85
|
+
${n}
|
|
86
|
+
|
|
87
|
+
export const contracts: Record<string, TypedAbi> = {
|
|
88
|
+
${r.join(`,
|
|
89
|
+
`)}
|
|
90
|
+
} as const;
|
|
91
|
+
|
|
92
|
+
${o}
|
|
93
|
+
`}function qt(t){let e="";return"accounts"in t&&(e=`export const accounts = {
|
|
94
|
+
${Object.keys(t.accounts).map(n=>{let o=t.accounts[n];return`"${n}": {
|
|
95
|
+
mnemonic: "${o.mnemonic}",
|
|
96
|
+
balance: ${o.balance.toString()}n,
|
|
97
|
+
address: "${o.address}",
|
|
98
|
+
},`}).join(`
|
|
99
|
+
`)}
|
|
100
|
+
} as const;`),e}Uint8Array.prototype[z.inspect.custom]=function(){return`Uint8Array.from([${this.join(",")}])`};function Ht(t){return(0,z.inspect)(t,!1,null,!1)}function U(t,e){return`"${t}": {
|
|
101
|
+
${e.join(`,
|
|
102
|
+
`)}
|
|
103
|
+
},`}async function Qt(){let t=(0,W.resolve)(__dirname,"../../../core/src/abi-types.ts");return await(0,wt.readFile)(t,{encoding:"utf-8"})}var ht=require("fs/promises"),Ft=require("path"),K=require("prettier"),Xt={printWidth:80,semi:!0,singleQuote:!0,trailingComma:"es5"};async function Yt(){try{let t=await(0,K.resolveConfig)(process.cwd());if(t)return t}catch{}return Xt}async function Zt(t,e){try{let r=(0,Ft.basename)(e),n=await Yt();return(0,K.format)(t,w(d({},n),{filepath:r}))}catch{}return t}async function j(t,e){let r=await Zt(e,t);await(0,ht.writeFile)(t,r)}var Tt=require("@clarigen/core"),vt=require("@clarigen/native-bin"),Pt=require("micro-stacks/clarity");async function Nt({abi:t,contractIdentifier:e,provider:r}){let n=t.variables.map(i=>Gt({variable:i,provider:r,contractIdentifier:e}));return await Promise.all(n)}async function Gt({contractIdentifier:t,variable:e,provider:r}){let n=te(e),o=await(0,vt.evalRaw)({contractAddress:t,code:n,provider:r}),i=(0,Pt.hexToCV)(o.output_serialized),a=(0,Tt.cvToValue)(i,!0);return w(d({},e),{defaultValue:a})}function te(t){let{access:e}=t;return e==="variable"?`(var-get ${t.name})`:t.name}var ee=async({contractFile:t,outputFolder:e,provider:r,contractAddress:n,dirName:o,contractName:i,docsPath:a})=>{let s=(0,g.resolve)(process.cwd(),t),f=`${n}.${i}`,l=await(0,q.deployContract)({contractIdentifier:f,contractFilePath:s,provider:r}),y=await Nt({abi:l,contractIdentifier:f,provider:r}),x=nt(l,i),C=rt({contractFile:(0,g.relative)(process.cwd(),s),contractAddress:n,contractName:i}),b=et({contractName:i,abi:l});typeof a<"u"&&await bt({contractFile:s,contractName:i,abi:l,docsPath:a,dirName:o});let c=(0,g.resolve)(e,o||".",i);return await(0,jt.mkdir)(c,{recursive:!0}),await j((0,g.resolve)(c,"abi.ts"),b),await j((0,g.resolve)(c,"index.ts"),C),await j((0,g.resolve)(c,"types.ts"),x),{abi:l,contractFile:s,contractName:i,dirName:o,contractAddress:n,variables:y}},H=async t=>{let e=await E(t),{contractsDir:r,outputDir:n,contracts:o}=e,i=(0,g.resolve)(t,n),a=await(0,q.createClarityBin)(),s=[];for(let C of o){let b=(0,g.resolve)(t,r,C.file),c=(0,g.dirname)(C.file),u=await ee({contractFile:b,outputFolder:i,provider:a,contractAddress:C.address,dirName:c,contractName:C.name,docsPath:e.docs});s.push(u)}let f=ot(e);await xt(e);let l=(0,g.resolve)(i,"index.ts");await j(l,f);let y=await At(e,s),x=(0,g.resolve)(i,"single.ts");await j(x,y)};var Et=require("chokidar"),It=require("path"),k=require("chalk"),re=require("ora"),it=class extends I.Command{async run(){let{flags:e}=this.parse(it),r=process.cwd();if(e.watch){let n=re("Generating files").start(),{contractsDir:o}=await E(r),i=(0,Et.watch)([o],{cwd:r});try{await H(r),n.succeed("Finished generating files. Watching for changes.")}catch(a){n.fail(`Error generating files.
|
|
104
|
+
${a.message}`)}i.on("change",async a=>{let s=(0,It.basename)(a);n.clear(),n.start(`Change detected for ${(0,k.green)(s)}, generating.`);try{await H(r),n.succeed(`Finished generating files for ${(0,k.green)(s)}. Watching for changes.`)}catch(f){let l=f.message;n.fail(`Error after saving ${(0,k.red)(s)}.
|
|
105
|
+
${l}`)}}),process.on("SIGINT",async()=>{await i.close(),process.exit()})}else await H(r)}},A=it;A.description="Generate project files",A.strict=!0,A.hidden=!1,A.flags={help:I.flags.help({char:"h"}),watch:I.flags.boolean({char:"w",description:"Watch for changes to your contracts"})},A.args=[];0&&(module.exports={Generate,configFileExists,configFilePath,defaultConfigFile,generateIndexFile,generateInterface,generateInterfaceFile,generateProjectIndexFile,generateTypesFile,getArgName,getConfigFile,getProjectConfig,jsTypeFromAbiType,makePureTypes,run});
|
package/dist/index.mjs
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,!0,{longer:!0})}async function
|
|
3
|
-
`,!0)}async function
|
|
1
|
+
var lt=Object.defineProperty,pt=Object.defineProperties;var ft=Object.getOwnPropertyDescriptors;var N=Object.getOwnPropertySymbols;var R=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var M=(t,e,r)=>e in t?lt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,y=(t,e)=>{for(var r in e||(e={}))R.call(e,r)&&M(t,r,e[r]);if(N)for(var r of N(e))B.call(e,r)&&M(t,r,e[r]);return t},w=(t,e)=>pt(t,ft(e));var mt=(t=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(t,{get:(e,r)=>(typeof require!="undefined"?require:e)[r]}):t)(function(t){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var j=(t,e)=>{var r={};for(var n in t)R.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&N)for(var n of N(t))e.indexOf(n)<0&&B.call(t,n)&&(r[n]=t[n]);return r};import{fileURLToPath as ut}from"url";import gt from"path";var Ct=()=>ut(import.meta.url),yt=()=>gt.dirname(Ct()),C=yt();import{run as Zr}from"@oclif/command";import{resolve as H,join as Ft,relative as Tt}from"path";import{readFile as vt,access as Pt}from"fs/promises";import{constants as Nt}from"fs";import{parse as J}from"@ltd/j-toml";import{resolve as U}from"path";import{readFile as W}from"fs/promises";import{generateWallet as dt,getStxAddressFromAccount as $t}from"micro-stacks/wallet-sdk";import{array as bt}from"toposort";import{StacksNetworkVersion as xt}from"micro-stacks/crypto";async function wt(t){let e=U(t,"settings","Devnet.toml"),r=await W(e,{encoding:"utf-8"});return J(r,1,`
|
|
2
|
+
`,!0,{longer:!0})}async function At(t){let e=U(t,"Clarinet.toml"),r=await W(e,{encoding:"utf-8"});return J(r,1,`
|
|
3
|
+
`,!0)}async function z(t,e){let r=await At(t),n=e.deployer.address;return ht(r.contracts).map(a=>({file:r.contracts[a].path.replace(/^contracts\//,""),address:n,name:a}))}function ht(t){let e=[],r=[];return Object.entries(t).forEach(([o,i])=>{r.push(o),i.depends_on.forEach(a=>e.push([o,a]))}),bt(r,e).reverse()}async function K(t){let e=await wt(t),r=await Promise.all(Object.entries(e.accounts).map(async([o,i])=>{let a=await dt(i.mnemonic,"password"),[s]=a.accounts,p=$t(s,xt.testnetP2PKH);return[o,w(y({},i),{address:p})]}));return Object.fromEntries(r)}var q={outputDir:"src/clarigen",clarinet:"."};function jt(t){return H(t,"clarigen.config.json")}async function Et(t){try{return await Pt(t,Nt.R_OK),!0}catch{return!1}}async function It(t){let e=jt(t);if(await Et(e)){let n=await vt(e,{encoding:"utf-8"}),o=JSON.parse(n);return y(y({},q),o)}return q}async function E(t){let e=await It(t),r=H(t,e.clarinet||"."),n=await K(r),o=await z(r,n),i=Tt(process.cwd(),Ft(e.clarinet,"contracts"));return w(y({},e),{contracts:o,contractsDir:i,accounts:n,clarinet:e.clarinet||"."})}import{isClarityAbiBuffer as kt,isClarityAbiList as St,isClarityAbiOptional as Dt,isClarityAbiPrimitive as Vt,isClarityAbiResponse as Q,isClarityAbiStringAscii as Ot,isClarityAbiStringUtf8 as Lt,isClarityAbiTuple as _t}from"micro-stacks/transactions";import{toCamelCase as S}from"@clarigen/core";import{check as Mt}from"reserved-words";var f=(t,e=!1)=>{if(Vt(t)){if(t==="uint128")return e?"number | bigint":"bigint";if(t==="int128")return e?"number | bigint":"bigint";if(t==="bool")return"boolean";if(t==="principal")return"string";if(t==="none")return"null";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(t)}`)}else{if(kt(t))return"Uint8Array";if(Q(t)){let r=f(t.response.ok),n=f(t.response.error);return`Response<${r}, ${n}>`}else{if(Dt(t))return`${f(t.optional)} | null`;if(_t(t)){let r=[];return t.tuple.forEach(({name:n,type:o})=>{let i=f(o);r.push(`"${n}": ${i}`)}),`{
|
|
4
4
|
${r.join(`;
|
|
5
5
|
`)}
|
|
6
|
-
}`}else{if(
|
|
7
|
-
`} ${o}`}),t.maps.forEach(r=>{let
|
|
8
|
-
${
|
|
6
|
+
}`}else{if(St(t))return`${f(t.list.type)}[]`;if(Ot(t))return"string";if(Lt(t))return"string";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(t)}`)}}}};function D(t){let e=S(t);return`${Mt(e,6)?"_":""}${e}`}var Rt={public:"Public",read_only:"ReadOnly",private:"Private"};function X(t){let e="";return t.functions.forEach((r,n)=>{let o=`${S(r.name)}: `;if(o+=`(${r.args.map(s=>`${D(s.name)}: ${f(s.type,!0)}`).join(", ")}) => `,o+=`ContractCalls.${Rt[r.access]}<`,r.access==="public"){let{type:s}=r.outputs;if(!Q(s))throw new Error("Expected response type for public function");let p=f(s.response.ok),l=f(s.response.error);o+=`${p}, ${l}>;`}else o+=`${f(r.outputs.type)}>;`;e+=`${n===0?"":`
|
|
7
|
+
`} ${o}`}),t.maps.forEach(r=>{let n=`${S(r.name)}: `,o=f(r.key,!0),i=`key: ${o}`,a=f(r.value);n+=`(${i}) => ContractCalls.Map<${o}, ${a}>;`,e+=`
|
|
8
|
+
${n}`}),e}import{hasStdErr as Bt}from"@clarigen/native-bin";import{toCamelCase as F}from"@clarigen/core";import{dirname as Jt,join as Ut}from"path";var er=async({provider:t,contractFile:e,contractAddress:r,contractName:n})=>{let o=await t.runCommand(["launch",`${r}.${n}`,e,t.dbFilePath,"--output_analysis","--costs","--assets"]);if(Bt(o.stderr))throw new Error(`Error on ${e}:
|
|
9
9
|
${o.stderr}
|
|
10
10
|
`);let i=JSON.parse(o.stdout);if(i.error){let{initialization:s}=i.error;if(s!=null&&s.includes(`
|
|
11
11
|
Near:
|
|
12
|
-
`)){let[
|
|
12
|
+
`)){let[p,l]=s.split(`
|
|
13
13
|
Near:
|
|
14
|
-
`),
|
|
15
|
-
${
|
|
16
|
-
${
|
|
14
|
+
`),g="",u=/start_line: (\d+),/.exec(l);throw u&&(g=u[1]),new Error(`Error on ${e}:
|
|
15
|
+
${p}
|
|
16
|
+
${g?`Near line ${g}`:""}
|
|
17
17
|
Raw trace:
|
|
18
|
-
${
|
|
19
|
-
`)}throw new Error(`Error on ${
|
|
18
|
+
${l}
|
|
19
|
+
`)}throw new Error(`Error on ${e}:
|
|
20
20
|
${JSON.stringify(i.error,null,2)}
|
|
21
|
-
`)}return i.analysis},
|
|
21
|
+
`)}return i.analysis},Y=({contractName:t,abi:e})=>{let r=F(t,!0),s=e,{clarity_version:n}=s,o=j(s,["clarity_version"]),i=JSON.stringify(o,null,2);return`import { ClarityAbi } from '@clarigen/core';
|
|
22
22
|
|
|
23
23
|
// prettier-ignore
|
|
24
24
|
export const ${r}Interface: ClarityAbi = ${i};
|
|
25
|
-
`},
|
|
25
|
+
`},Z=({contractFile:t,contractAddress:e,contractName:r})=>{let n=F(r,!0),o=F(r),i=`${n}Contract`,a=`${n}Interface`;return`import { pureProxy, Contract } from '@clarigen/core';
|
|
26
26
|
import type { ${i} } from './types';
|
|
27
|
-
import { ${
|
|
27
|
+
import { ${a} } from './abi';
|
|
28
28
|
export type { ${i} } from './types';
|
|
29
29
|
|
|
30
30
|
export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
31
31
|
return pureProxy<${i}>({
|
|
32
|
-
abi: ${
|
|
32
|
+
abi: ${a},
|
|
33
33
|
contractAddress,
|
|
34
34
|
contractName,
|
|
35
35
|
});
|
|
@@ -37,42 +37,69 @@ export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
|
37
37
|
|
|
38
38
|
export const ${o}Info: Contract<${i}> = {
|
|
39
39
|
contract: ${o}Contract,
|
|
40
|
-
address: '${
|
|
40
|
+
address: '${e}',
|
|
41
41
|
contractFile: '${t}',
|
|
42
42
|
name: '${r}',
|
|
43
|
-
abi: ${
|
|
43
|
+
abi: ${a},
|
|
44
44
|
};
|
|
45
|
-
`},
|
|
45
|
+
`},G=(t,e)=>{let r=F(e,!0),n=X(t);return`import { Response, ContractCalls } from '@clarigen/core';
|
|
46
46
|
|
|
47
47
|
// prettier-ignore
|
|
48
48
|
export interface ${r}Contract {
|
|
49
|
-
${
|
|
49
|
+
${n}
|
|
50
50
|
}
|
|
51
|
-
`},
|
|
51
|
+
`},tt=t=>{let e=["import type { ContractInstances } from '@clarigen/core';"],r=[],n=[],o="";"accounts"in t&&(o=`
|
|
52
52
|
|
|
53
53
|
// prettier-ignore
|
|
54
54
|
export const accounts = {
|
|
55
|
-
${Object.keys(t.accounts).map(
|
|
56
|
-
mnemonic: "${
|
|
57
|
-
balance: ${
|
|
58
|
-
address: "${
|
|
55
|
+
${Object.keys(t.accounts).map(p=>{let l=t.accounts[p];return`"${p}": {
|
|
56
|
+
mnemonic: "${l.mnemonic}",
|
|
57
|
+
balance: ${l.balance.toString()}n,
|
|
58
|
+
address: "${l.address}",
|
|
59
59
|
},`}).join(`
|
|
60
60
|
`)}
|
|
61
|
-
};`),t.contracts.forEach(s=>{let
|
|
61
|
+
};`),t.contracts.forEach(s=>{let p=s.name,l=F(p),g=`${l}Info`,x=`${F(p,!0)}Contract`,u=Jt(s.file),$=`'./${Ut(u||".",p)}'`,c=`import { ${g} } from ${$};`;e.push(c);let m=`export type { ${x} } from ${$};`;r.push(m);let h=`${l}: ${g},`;n.push(h)});let i=`
|
|
62
62
|
export type Contracts = ContractInstances<typeof contracts>;
|
|
63
|
-
`;return`${
|
|
63
|
+
`;return`${e.join(`
|
|
64
64
|
`)}
|
|
65
65
|
${r.join(`
|
|
66
66
|
`)}
|
|
67
67
|
${i}
|
|
68
68
|
export const contracts = {
|
|
69
|
-
${
|
|
69
|
+
${n.join(`
|
|
70
70
|
`)}
|
|
71
71
|
};${o}
|
|
72
|
-
`};import{Command as
|
|
72
|
+
`};import{Command as xe,flags as st}from"@oclif/command";import{createClarityBin as ge,deployContract as Ce}from"@clarigen/native-bin";import{resolve as b,relative as ye,dirname as de}from"path";import{mkdir as $e}from"fs/promises";import{createContractDocInfo as Wt,generateMarkdown as zt}from"@clarigen/claridocs";import{mkdir as Kt,readFile as qt,writeFile as et}from"fs/promises";import{relative as Ht,resolve as V}from"path";async function rt({contractFile:t,contractName:e,docsPath:r,abi:n,dirName:o}){let i=await qt(t,{encoding:"utf-8"}),a=Wt({contractSrc:i,abi:n}),s=V(process.cwd(),r,o||"."),p=V(s,`${e}.md`),l=zt({contract:a,contractFile:Ht(s,t),contractName:e,abi:n});await Kt(s,{recursive:!0}),await et(p,l)}async function nt(t){if(!t.docs)return;let r=`# Contracts
|
|
73
73
|
|
|
74
74
|
${t.contracts.map(o=>{let i=o.file.replace(".clar",".md");return`- [\`${o.name}\`](${i})`}).join(`
|
|
75
75
|
`)}
|
|
76
|
-
`,
|
|
77
|
-
${
|
|
78
|
-
${
|
|
76
|
+
`,n=V(process.cwd(),t.docs,"README.md");await et(n,r)}import{toCamelCase as v}from"@clarigen/core";import{relative as Qt,resolve as Xt}from"path";import{readFile as Yt}from"fs/promises";import{inspect as O}from"util";function Zt(t){let{abi:e}=t,r=[],$=e,{functions:n,variables:o,maps:i}=$,a=j($,["functions","variables","maps"]);n.forEach(c=>{let m=`${v(c.name)}: `,P=`[${c.args.map(_=>`${D(_.name)}: ${f(_.type,!0)}`).join(", ")}]`;m+=JSON.stringify(c);let ct=f(c.outputs.type);m+=` as TypedAbiFunction<${P}, ${ct}>`,r.push(m)});let s=t.variables.map(c=>{let m=`${v(c.name)}: `,h=f(c.type);return m+=`${O(c,!1,null,!1)} as TypedAbiVariable<${h}>`,m}),l=t.variables.filter(c=>c.access==="constant").map(c=>`"${v(c.name)}": ${te(c.defaultValue)}`),g=i.map(c=>{let m=`${v(c.name)}: `,h=f(c.key),P=f(c.value);return m+=JSON.stringify(c),m+=` as TypedAbiMap<${h}, ${P}>`,m}),x=JSON.stringify(a),u=Qt(process.cwd(),t.contractFile);return`{
|
|
77
|
+
${I("functions",r)}
|
|
78
|
+
${I("variables",s)}
|
|
79
|
+
${I("maps",g)}
|
|
80
|
+
${I("constants",l)}
|
|
81
|
+
${x.slice(1,-1)},
|
|
82
|
+
contractName: '${t.contractName}',
|
|
83
|
+
contractFile: '${u}',
|
|
84
|
+
}`}async function ot(t,e){let r=e.map(a=>{let s=Zt(a);return`${v(a.contractName)}: ${s}`}),n=await ee(),o=Gt(t);return`
|
|
85
|
+
${n}
|
|
86
|
+
|
|
87
|
+
export const contracts: Record<string, TypedAbi> = {
|
|
88
|
+
${r.join(`,
|
|
89
|
+
`)}
|
|
90
|
+
} as const;
|
|
91
|
+
|
|
92
|
+
${o}
|
|
93
|
+
`}function Gt(t){let e="";return"accounts"in t&&(e=`export const accounts = {
|
|
94
|
+
${Object.keys(t.accounts).map(n=>{let o=t.accounts[n];return`"${n}": {
|
|
95
|
+
mnemonic: "${o.mnemonic}",
|
|
96
|
+
balance: ${o.balance.toString()}n,
|
|
97
|
+
address: "${o.address}",
|
|
98
|
+
},`}).join(`
|
|
99
|
+
`)}
|
|
100
|
+
} as const;`),e}Uint8Array.prototype[O.custom]=function(){return`Uint8Array.from([${this.join(",")}])`};function te(t){return O(t,!1,null,!1)}function I(t,e){return`"${t}": {
|
|
101
|
+
${e.join(`,
|
|
102
|
+
`)}
|
|
103
|
+
},`}async function ee(){let t=Xt(C,"../../../core/src/abi-types.ts");return await Yt(t,{encoding:"utf-8"})}import{writeFile as re}from"fs/promises";import{basename as ne}from"path";import{resolveConfig as oe,format as ie}from"prettier";var se={printWidth:80,semi:!0,singleQuote:!0,trailingComma:"es5"};async function ae(){try{let t=await oe(process.cwd());if(t)return t}catch{}return se}async function ce(t,e){try{let r=ne(e),n=await ae();return ie(t,w(y({},n),{filepath:r}))}catch{}return t}async function T(t,e){let r=await ce(e,t);await re(t,r)}import{cvToValue as le}from"@clarigen/core";import{evalRaw as pe}from"@clarigen/native-bin";import{hexToCV as fe}from"micro-stacks/clarity";async function it({abi:t,contractIdentifier:e,provider:r}){let n=t.variables.map(i=>me({variable:i,provider:r,contractIdentifier:e}));return await Promise.all(n)}async function me({contractIdentifier:t,variable:e,provider:r}){let n=ue(e),o=await pe({contractAddress:t,code:n,provider:r}),i=fe(o.output_serialized),a=le(i,!0);return w(y({},e),{defaultValue:a})}function ue(t){let{access:e}=t;return e==="variable"?`(var-get ${t.name})`:t.name}var be=async({contractFile:t,outputFolder:e,provider:r,contractAddress:n,dirName:o,contractName:i,docsPath:a})=>{let s=b(process.cwd(),t),p=`${n}.${i}`,l=await Ce({contractIdentifier:p,contractFilePath:s,provider:r}),g=await it({abi:l,contractIdentifier:p,provider:r}),x=G(l,i),u=Z({contractFile:ye(process.cwd(),s),contractAddress:n,contractName:i}),$=Y({contractName:i,abi:l});typeof a<"u"&&await rt({contractFile:s,contractName:i,abi:l,docsPath:a,dirName:o});let c=b(e,o||".",i);return await $e(c,{recursive:!0}),await T(b(c,"abi.ts"),$),await T(b(c,"index.ts"),u),await T(b(c,"types.ts"),x),{abi:l,contractFile:s,contractName:i,dirName:o,contractAddress:n,variables:g}},k=async t=>{let e=await E(t),{contractsDir:r,outputDir:n,contracts:o}=e,i=b(t,n),a=await ge(),s=[];for(let u of o){let $=b(t,r,u.file),c=de(u.file),m=await be({contractFile:$,outputFolder:i,provider:a,contractAddress:u.address,dirName:c,contractName:u.name,docsPath:e.docs});s.push(m)}let p=tt(e);await nt(e);let l=b(i,"index.ts");await T(l,p);let g=await ot(e,s),x=b(i,"single.ts");await T(x,g)};import{watch as we}from"chokidar";import{basename as Ae}from"path";import{red as he,green as at}from"chalk";var Fe=mt("ora"),L=class extends xe{async run(){let{flags:e}=this.parse(L),r=process.cwd();if(e.watch){let n=Fe("Generating files").start(),{contractsDir:o}=await E(r),i=we([o],{cwd:r});try{await k(r),n.succeed("Finished generating files. Watching for changes.")}catch(a){n.fail(`Error generating files.
|
|
104
|
+
${a.message}`)}i.on("change",async a=>{let s=Ae(a);n.clear(),n.start(`Change detected for ${at(s)}, generating.`);try{await k(r),n.succeed(`Finished generating files for ${at(s)}. Watching for changes.`)}catch(p){let l=p.message;n.fail(`Error after saving ${he(s)}.
|
|
105
|
+
${l}`)}}),process.on("SIGINT",async()=>{await i.close(),process.exit()})}else await k(r)}},A=L;A.description="Generate project files",A.strict=!0,A.hidden=!1,A.flags={help:st.help({char:"h"}),watch:st.boolean({char:"w",description:"Watch for changes to your contracts"})},A.args=[];export{A as Generate,Et as configFileExists,jt as configFilePath,q as defaultConfigFile,Z as generateIndexFile,er as generateInterface,Y as generateInterfaceFile,tt as generateProjectIndexFile,G as generateTypesFile,D as getArgName,It as getConfigFile,E as getProjectConfig,f as jsTypeFromAbiType,X as makePureTypes,Zr as run};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@clarigen/cli",
|
|
3
3
|
"description": "A CLI for generating a Typescript interface for a Clarity contract.",
|
|
4
4
|
"author": "Hank Stoever",
|
|
5
|
-
"version": "1.0.0-next.
|
|
5
|
+
"version": "1.0.0-next.18",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"main": "./dist/index.js",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"lint": "eslint \"src/**/*.{ts,tsx}\" && prettier --check src/**/*.ts",
|
|
25
25
|
"typecheck": "tsc --noEmit -p tsconfig-test.json",
|
|
26
26
|
"prepublishOnly": "yarn build",
|
|
27
|
-
"demo": "yarn build && node bin/run"
|
|
27
|
+
"demo": "yarn build && node bin/run",
|
|
28
|
+
"publish:dev": "yalc publish --push"
|
|
28
29
|
},
|
|
29
30
|
"bin": {
|
|
30
31
|
"clarigen": "./bin/run"
|
|
@@ -49,9 +50,9 @@
|
|
|
49
50
|
"ts-node": "^9.1.1"
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {
|
|
52
|
-
"@clarigen/claridocs": "1.0.0-next.
|
|
53
|
-
"@clarigen/core": "1.0.0-next.
|
|
54
|
-
"@clarigen/native-bin": "1.0.0-next.
|
|
53
|
+
"@clarigen/claridocs": "1.0.0-next.18",
|
|
54
|
+
"@clarigen/core": "1.0.0-next.18",
|
|
55
|
+
"@clarigen/native-bin": "1.0.0-next.18",
|
|
55
56
|
"@ltd/j-toml": "1.12.2",
|
|
56
57
|
"@oclif/command": "^1.8.0",
|
|
57
58
|
"@oclif/config": "^1.17.0",
|
|
@@ -60,11 +61,12 @@
|
|
|
60
61
|
"chokidar": "3.5.1",
|
|
61
62
|
"micro-stacks": "^0.2.0",
|
|
62
63
|
"ora": "5.4.0",
|
|
64
|
+
"prettier": "2.6.2",
|
|
63
65
|
"reserved-words": "0.1.2",
|
|
64
66
|
"toposort": "2.0.2"
|
|
65
67
|
},
|
|
66
68
|
"publishConfig": {
|
|
67
69
|
"access": "public"
|
|
68
70
|
},
|
|
69
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "597b4b53e6c876336126bf40b4b8850d1385af8f"
|
|
70
72
|
}
|
package/src/clarinet-config.ts
CHANGED
|
@@ -48,6 +48,12 @@ export interface ClarinetConfig {
|
|
|
48
48
|
contracts: ClarinetContracts;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
export const CLARINET_SETTINGS = [
|
|
52
|
+
'Devnet.toml',
|
|
53
|
+
'Testnet.toml',
|
|
54
|
+
'Mainnet.toml',
|
|
55
|
+
];
|
|
56
|
+
|
|
51
57
|
export async function getClarinetConfig(folder: string) {
|
|
52
58
|
const baseConfigPath = resolve(folder, 'Clarinet.toml');
|
|
53
59
|
const configContents = await readFile(baseConfigPath, { encoding: 'utf-8' });
|
|
@@ -69,7 +69,7 @@ export const jsTypeFromAbiType = (
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
// Check if it's a reserved word, and then camelCase
|
|
72
|
-
function getArgName(name: string) {
|
|
72
|
+
export function getArgName(name: string) {
|
|
73
73
|
const camel = toCamelCase(name);
|
|
74
74
|
const prefix = check(camel, 6) ? '_' : '';
|
|
75
75
|
return `${prefix}${camel}`;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { toCamelCase } from '@clarigen/core';
|
|
2
|
+
import type { ConfigFile } from '../config';
|
|
3
|
+
import { getArgName, jsTypeFromAbiType } from './declaration';
|
|
4
|
+
import type { ContractMeta } from '../utils';
|
|
5
|
+
import { resolveConfig, format } from 'prettier';
|
|
6
|
+
import { relative, resolve } from 'path';
|
|
7
|
+
import { readFile } from 'fs/promises';
|
|
8
|
+
import { inspect } from 'util';
|
|
9
|
+
|
|
10
|
+
export function generateContractMeta(contract: ContractMeta) {
|
|
11
|
+
const { abi } = contract;
|
|
12
|
+
const functionLines: string[] = [];
|
|
13
|
+
const { functions, variables, maps, ...rest } = abi;
|
|
14
|
+
functions.forEach((func) => {
|
|
15
|
+
let functionLine = `${toCamelCase(func.name)}: `;
|
|
16
|
+
const args = func.args.map((arg) => {
|
|
17
|
+
return `${getArgName(arg.name)}: ${jsTypeFromAbiType(arg.type, true)}`;
|
|
18
|
+
});
|
|
19
|
+
const argsTuple = `[${args.join(', ')}]`;
|
|
20
|
+
const funcDef = JSON.stringify(func);
|
|
21
|
+
functionLine += funcDef;
|
|
22
|
+
const retType = jsTypeFromAbiType(func.outputs.type);
|
|
23
|
+
functionLine += ` as TypedAbiFunction<${argsTuple}, ${retType}>`;
|
|
24
|
+
functionLines.push(functionLine);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const variableLines = contract.variables.map((v) => {
|
|
28
|
+
let varLine = `${toCamelCase(v.name)}: `;
|
|
29
|
+
const type = jsTypeFromAbiType(v.type);
|
|
30
|
+
const varJSON = inspect(v, false, null, false);
|
|
31
|
+
varLine += `${varJSON} as TypedAbiVariable<${type}>`;
|
|
32
|
+
return varLine;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const constants = contract.variables.filter((v) => v.access === 'constant');
|
|
36
|
+
const constantLines = constants.map((constant) => {
|
|
37
|
+
return `"${toCamelCase(constant.name)}": ${serialize(
|
|
38
|
+
constant.defaultValue
|
|
39
|
+
)}`;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const mapLines = maps.map((map) => {
|
|
43
|
+
let mapLine = `${toCamelCase(map.name)}: `;
|
|
44
|
+
const keyType = jsTypeFromAbiType(map.key);
|
|
45
|
+
const valType = jsTypeFromAbiType(map.value);
|
|
46
|
+
mapLine += JSON.stringify(map);
|
|
47
|
+
mapLine += ` as TypedAbiMap<${keyType}, ${valType}>`;
|
|
48
|
+
return mapLine;
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const otherAbi = JSON.stringify(rest);
|
|
52
|
+
|
|
53
|
+
const contractFile = relative(process.cwd(), contract.contractFile);
|
|
54
|
+
|
|
55
|
+
return `{
|
|
56
|
+
${serializeLines('functions', functionLines)}
|
|
57
|
+
${serializeLines('variables', variableLines)}
|
|
58
|
+
${serializeLines('maps', mapLines)}
|
|
59
|
+
${serializeLines('constants', constantLines)}
|
|
60
|
+
${otherAbi.slice(1, -1)},
|
|
61
|
+
contractName: '${contract.contractName}',
|
|
62
|
+
contractFile: '${contractFile}',
|
|
63
|
+
}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function generateSingleFile(
|
|
67
|
+
config: ConfigFile,
|
|
68
|
+
contracts: ContractMeta[]
|
|
69
|
+
) {
|
|
70
|
+
const contractDefs = contracts.map((contract) => {
|
|
71
|
+
const meta = generateContractMeta(contract);
|
|
72
|
+
const keyName = toCamelCase(contract.contractName);
|
|
73
|
+
return `${keyName}: ${meta}`;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const types = await getSingleTypes();
|
|
77
|
+
const accounts = generateAccounts(config);
|
|
78
|
+
|
|
79
|
+
const file = `
|
|
80
|
+
${types}
|
|
81
|
+
|
|
82
|
+
export const contracts: Record<string, TypedAbi> = {
|
|
83
|
+
${contractDefs.join(',\n')}
|
|
84
|
+
} as const;
|
|
85
|
+
|
|
86
|
+
${accounts}
|
|
87
|
+
`;
|
|
88
|
+
return file;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function generateAccounts(config: ConfigFile) {
|
|
92
|
+
let accounts = '';
|
|
93
|
+
if ('accounts' in config) {
|
|
94
|
+
const accountLines = Object.keys(config.accounts).map((key) => {
|
|
95
|
+
const account = config.accounts[key];
|
|
96
|
+
return `"${key}": {
|
|
97
|
+
mnemonic: "${account.mnemonic}",
|
|
98
|
+
balance: ${account.balance.toString()}n,
|
|
99
|
+
address: "${account.address}",
|
|
100
|
+
},`;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
accounts = `export const accounts = {
|
|
104
|
+
${accountLines.join('\n ')}
|
|
105
|
+
} as const;`;
|
|
106
|
+
}
|
|
107
|
+
return accounts;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
Uint8Array.prototype[inspect.custom] = function (this: Uint8Array) {
|
|
111
|
+
return `Uint8Array.from([${this.join(',')}])`;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
function serialize(obj: any) {
|
|
115
|
+
return inspect(obj, false, null, false);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function serializeLines(key: string, lines: string[]) {
|
|
119
|
+
return `"${key}": {
|
|
120
|
+
${lines.join(',\n ')}
|
|
121
|
+
},`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function getSingleTypes() {
|
|
125
|
+
const typesPath = resolve(__dirname, '../../../core/src/abi-types.ts');
|
|
126
|
+
const typesFile = await readFile(typesPath, { encoding: 'utf-8' });
|
|
127
|
+
return typesFile;
|
|
128
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClarityAbiType,
|
|
3
|
+
cvToValue,
|
|
4
|
+
AbiTypeTo,
|
|
5
|
+
ClarityAbi,
|
|
6
|
+
} from '@clarigen/core';
|
|
7
|
+
import { evalRaw, NativeClarityBinProvider } from '@clarigen/native-bin';
|
|
8
|
+
import { ClarityAbiVariable, hexToCV } from 'micro-stacks/clarity';
|
|
9
|
+
import type { ContractMeta } from '../utils';
|
|
10
|
+
|
|
11
|
+
// export interface TypedAbiVariable<T extends ClarityAbiType>
|
|
12
|
+
// extends ClarityAbiVariable {
|
|
13
|
+
// type: T;
|
|
14
|
+
// defaultValue: AbiTypeTo<T>;
|
|
15
|
+
// }
|
|
16
|
+
export type TypedAbiVariable<T> = ClarityAbiVariable & {
|
|
17
|
+
defaultValue: T;
|
|
18
|
+
};
|
|
19
|
+
// export type TypedAbiVariable<T> = T extends ClarityAbiVariable ?
|
|
20
|
+
// T['type'] extends ClarityAbiType ?
|
|
21
|
+
export type VariableType<T> = T extends ClarityAbiVariable ? T['type'] : never;
|
|
22
|
+
|
|
23
|
+
export async function getVariables({
|
|
24
|
+
abi,
|
|
25
|
+
contractIdentifier,
|
|
26
|
+
provider,
|
|
27
|
+
}: {
|
|
28
|
+
abi: ClarityAbi;
|
|
29
|
+
contractIdentifier: string;
|
|
30
|
+
provider: NativeClarityBinProvider;
|
|
31
|
+
}) {
|
|
32
|
+
const variableTransforms = abi.variables.map((variable) => {
|
|
33
|
+
return evalVariable({
|
|
34
|
+
variable,
|
|
35
|
+
provider,
|
|
36
|
+
contractIdentifier,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
const variables = await Promise.all(variableTransforms);
|
|
40
|
+
return variables;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function evalVariable<T extends ClarityAbiVariable>({
|
|
44
|
+
contractIdentifier,
|
|
45
|
+
variable,
|
|
46
|
+
provider,
|
|
47
|
+
}: {
|
|
48
|
+
contractIdentifier: string;
|
|
49
|
+
variable: T;
|
|
50
|
+
provider: NativeClarityBinProvider;
|
|
51
|
+
}) {
|
|
52
|
+
const code = getEvalCode(variable);
|
|
53
|
+
const result = await evalRaw({
|
|
54
|
+
contractAddress: contractIdentifier,
|
|
55
|
+
code,
|
|
56
|
+
provider,
|
|
57
|
+
});
|
|
58
|
+
const resultCV = hexToCV(result.output_serialized);
|
|
59
|
+
const value = cvToValue(resultCV, true);
|
|
60
|
+
return {
|
|
61
|
+
...variable,
|
|
62
|
+
defaultValue: value,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// export async function
|
|
67
|
+
|
|
68
|
+
function getEvalCode(variable: ClarityAbiVariable) {
|
|
69
|
+
const { access } = variable;
|
|
70
|
+
if (access === 'variable') {
|
|
71
|
+
return `(var-get ${variable.name})`;
|
|
72
|
+
}
|
|
73
|
+
return variable.name;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// export function serializeVariable(variable: TypedAbiVariable<any>) {
|
|
77
|
+
// const { defaultValue, ...rest } = variable;
|
|
78
|
+
// const lines = Object.keys(rest).map((key) => {
|
|
79
|
+
// return `"${key}": ${JSON.stringify(rest[key])}`;
|
|
80
|
+
// });
|
|
81
|
+
// const valueLine = typeof defaultValue === 'bigint' ? `${defaultValue.toString()}n` : JSON.stringify()
|
|
82
|
+
// }
|
package/src/utils.ts
CHANGED
|
@@ -8,11 +8,26 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
NativeClarityBinProvider,
|
|
10
10
|
createClarityBin,
|
|
11
|
+
deployContract,
|
|
11
12
|
} from '@clarigen/native-bin';
|
|
12
13
|
import { resolve, relative, dirname } from 'path';
|
|
13
|
-
import { mkdir
|
|
14
|
+
import { mkdir } from 'fs/promises';
|
|
14
15
|
import { getProjectConfig } from './config';
|
|
15
16
|
import { generateDocsIndex, generateMarkdownDoc } from './docs';
|
|
17
|
+
import { ClarityAbi, Contract } from '@clarigen/core';
|
|
18
|
+
import { generateContractMeta, generateSingleFile } from './generate/single';
|
|
19
|
+
import { writeFile } from './writer';
|
|
20
|
+
import { getVariables, TypedAbiVariable } from './generate/vars';
|
|
21
|
+
import { ClarityAbiVariable } from 'micro-stacks/clarity';
|
|
22
|
+
|
|
23
|
+
export interface ContractMeta {
|
|
24
|
+
abi: ClarityAbi;
|
|
25
|
+
contractFile: string;
|
|
26
|
+
dirName: string;
|
|
27
|
+
contractName: string;
|
|
28
|
+
contractAddress: string;
|
|
29
|
+
variables: TypedAbiVariable<unknown>[];
|
|
30
|
+
}
|
|
16
31
|
|
|
17
32
|
export const generateFilesForContract = async ({
|
|
18
33
|
contractFile: _contractFile,
|
|
@@ -30,15 +45,21 @@ export const generateFilesForContract = async ({
|
|
|
30
45
|
dirName?: string;
|
|
31
46
|
contractName: string;
|
|
32
47
|
docsPath?: string;
|
|
33
|
-
}) => {
|
|
48
|
+
}): Promise<ContractMeta> => {
|
|
34
49
|
const contractFile = resolve(process.cwd(), _contractFile);
|
|
50
|
+
const contractIdentifier = `${contractAddress}.${contractName}`;
|
|
35
51
|
|
|
36
|
-
const abi = await
|
|
37
|
-
|
|
52
|
+
const abi = await deployContract({
|
|
53
|
+
contractIdentifier,
|
|
54
|
+
contractFilePath: contractFile,
|
|
38
55
|
provider,
|
|
39
|
-
contractAddress,
|
|
40
|
-
contractName,
|
|
41
56
|
});
|
|
57
|
+
const variables = await getVariables({
|
|
58
|
+
abi,
|
|
59
|
+
contractIdentifier,
|
|
60
|
+
provider,
|
|
61
|
+
});
|
|
62
|
+
|
|
42
63
|
const typesFile = generateTypesFile(abi, contractName);
|
|
43
64
|
const indexFile = generateIndexFile({
|
|
44
65
|
contractFile: relative(process.cwd(), contractFile),
|
|
@@ -63,6 +84,15 @@ export const generateFilesForContract = async ({
|
|
|
63
84
|
await writeFile(resolve(outputPath, 'abi.ts'), abiFile);
|
|
64
85
|
await writeFile(resolve(outputPath, 'index.ts'), indexFile);
|
|
65
86
|
await writeFile(resolve(outputPath, 'types.ts'), typesFile);
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
abi,
|
|
90
|
+
contractFile,
|
|
91
|
+
contractName,
|
|
92
|
+
dirName,
|
|
93
|
+
contractAddress,
|
|
94
|
+
variables,
|
|
95
|
+
};
|
|
66
96
|
};
|
|
67
97
|
|
|
68
98
|
export const generateProject = async (projectPath: string) => {
|
|
@@ -70,11 +100,12 @@ export const generateProject = async (projectPath: string) => {
|
|
|
70
100
|
const { contractsDir, outputDir, contracts } = configFile;
|
|
71
101
|
const outputFolder = resolve(projectPath, outputDir);
|
|
72
102
|
const provider = await createClarityBin();
|
|
103
|
+
const metas: ContractMeta[] = [];
|
|
73
104
|
// this needs to be serial
|
|
74
105
|
for (const contract of contracts) {
|
|
75
106
|
const contractFile = resolve(projectPath, contractsDir, contract.file);
|
|
76
107
|
const dirName = dirname(contract.file);
|
|
77
|
-
await generateFilesForContract({
|
|
108
|
+
const meta = await generateFilesForContract({
|
|
78
109
|
contractFile,
|
|
79
110
|
outputFolder: outputFolder,
|
|
80
111
|
provider,
|
|
@@ -83,6 +114,7 @@ export const generateProject = async (projectPath: string) => {
|
|
|
83
114
|
contractName: contract.name,
|
|
84
115
|
docsPath: configFile.docs,
|
|
85
116
|
});
|
|
117
|
+
metas.push(meta);
|
|
86
118
|
}
|
|
87
119
|
|
|
88
120
|
const indexFile = generateProjectIndexFile(configFile);
|
|
@@ -90,4 +122,8 @@ export const generateProject = async (projectPath: string) => {
|
|
|
90
122
|
|
|
91
123
|
const indexPath = resolve(outputFolder, 'index.ts');
|
|
92
124
|
await writeFile(indexPath, indexFile);
|
|
125
|
+
|
|
126
|
+
const singleFile = await generateSingleFile(configFile, metas);
|
|
127
|
+
const singlePath = resolve(outputFolder, 'single.ts');
|
|
128
|
+
await writeFile(singlePath, singleFile);
|
|
93
129
|
};
|
package/src/writer.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Utilities for writing and formatting files
|
|
2
|
+
import { writeFile as _writeFile } from 'fs/promises';
|
|
3
|
+
import { basename } from 'path';
|
|
4
|
+
import { resolveConfig, format, Options } from 'prettier';
|
|
5
|
+
|
|
6
|
+
const defaultPrettierConfig: Options = {
|
|
7
|
+
printWidth: 80,
|
|
8
|
+
semi: true,
|
|
9
|
+
singleQuote: true,
|
|
10
|
+
trailingComma: 'es5',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function resolvePrettierConfig(): Promise<Options> {
|
|
14
|
+
try {
|
|
15
|
+
const local = await resolveConfig(process.cwd());
|
|
16
|
+
if (local) return local;
|
|
17
|
+
} catch (error) {}
|
|
18
|
+
return defaultPrettierConfig;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function formatFile(contents: string, path: string) {
|
|
22
|
+
try {
|
|
23
|
+
const fileName = basename(path);
|
|
24
|
+
const config = await resolvePrettierConfig();
|
|
25
|
+
const formatted = format(contents, {
|
|
26
|
+
...config,
|
|
27
|
+
filepath: fileName,
|
|
28
|
+
});
|
|
29
|
+
return formatted;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
// handle formatting error
|
|
32
|
+
}
|
|
33
|
+
return contents;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function writeFile(path: string, contents: string) {
|
|
37
|
+
const formatted = await formatFile(contents, path);
|
|
38
|
+
await _writeFile(path, formatted);
|
|
39
|
+
}
|