@clarigen/core 4.1.3 → 4.1.5
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/deployment-BoAUH7JK.mjs +58 -0
- package/dist/deployment-BoAUH7JK.mjs.map +1 -0
- package/dist/deployment-Bv57LEA2.d.cts +2 -1
- package/dist/deployment-DRgKqqdY.cjs +94 -0
- package/dist/deployment-DRgKqqdY.cjs.map +1 -0
- package/dist/deployment-hBXji8Xz.d.mts +2 -1
- package/dist/deployment.cjs +8 -1
- package/dist/deployment.mjs +3 -1
- package/dist/index.cjs +901 -2
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -27
- package/dist/index.d.mts +4 -27
- package/dist/index.mjs +831 -2
- package/dist/index.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/deployment-CGEqh8yH.mjs +0 -1
- package/dist/deployment-DN-sbX_m.cjs +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,831 @@
|
|
|
1
|
-
import
|
|
2
|
-
`)}\n${i}}`}case r.StringASCII:return`"${e.value}"`;case r.StringUTF8:return`u"${e.value}"`}}function F(e,t=!1){switch(e.type){case r.BoolTrue:return!0;case r.BoolFalse:return!1;case r.Int:case r.UInt:return`${e.value}`;case r.Buffer:return e.value;case r.OptionalNone:return null;case r.OptionalSome:return F(e.value);case r.ResponseErr:return t?x(F(e.value)):F(e.value);case r.ResponseOk:return t?b(F(e.value)):F(e.value);case r.PrincipalStandard:case r.PrincipalContract:return S(e);case r.List:return e.value.map(e=>F(e));case r.Tuple:return Object.entries(e.value).reduce((e,[t,n])=>{let r=h(t);return{...e,[r]:F(n)}},{});case r.StringASCII:return e.value;case r.StringUTF8:return e.value}}function I(e,t){return e.args.map(e=>{let n=t[z(e.name,t)];return N(n,e.type)})}function L(e,t){return t.map((t,n)=>N(t,e.args[n].type))}function R(e,t){if(t.length===0)return[];let[n]=t;if(t.length===1&&e.args.length!==1)return I(e,n);if(typeof n==`object`&&!Array.isArray(n)&&n!==null)try{let t=!0;if(e.args.forEach(e=>{try{z(e.name,n)}catch{t=!1}}),t)return I(e,n)}catch{}return L(e,t)}function z(e,t){let n=Object.keys(t).find(t=>{let n=e===t,r=e===g(t);return n||r});if(!n)throw Error(`Error encoding JS tuple: ${e} not found in input.`);return n}function B(e){if(e.isOk)return e.value;throw Error(`Expected OK, received error: ${String(e.value)}`)}function V(e){if(!e.isOk)return e.value;throw Error(`Expected Err, received ok: ${String(e.value)}`)}function H(e){if(T(e))return e===`int128`?`int`:e===`uint128`?`uint`:e;if(E(e))return`(buff ${e.buffer.length})`;if(D(e))return`(string-ascii ${e[`string-ascii`].length})`;if(O(e))return`(string-utf8 ${e[`string-utf8`].length})`;if(k(e))return`(response ${H(e.response.ok)} ${H(e.response.error)})`;if(A(e))return`(optional ${H(e.optional)})`;if(j(e))return`{ ${e.tuple.map(e=>`${e.name}: ${H(e.type)}`).join(`, `)} }`;if(M(e))return`(list ${e.list.length} ${H(e.list.type)})`;throw Error(`Type string unsupported for Clarity type: ${JSON.stringify(e)}`)}function De(e,t){let n=e.abi.functions.find(e=>h(e.name)===t);if(n)return(...t)=>({functionArgs:R(n,t),contractAddress:e.contractAddress,contractName:e.contractName,function:n,functionName:n.name,nativeArgs:t});let r=e.abi.maps.find(e=>h(e.name)===t);if(r)return t=>{let n=N(t,r.key);return{contractAddress:e.contractAddress,contractName:e.contractName,map:r,nativeKey:t,key:n}};throw Error(`Invalid function call: no function exists for ${String(t)}`)}const Oe={get:De},ke=e=>new Proxy(e,Oe),Ae=[`devnet`,`simnet`,`testnet`,`mainnet`];function je(e,t){let n=[];return Object.entries(e.contracts).forEach(([r,i])=>{let a=e.deployments[r][t];return a&&n.push([r,W(i,a)]),!1}),Object.fromEntries(n)}function Me(e,t){return Object.fromEntries(Object.entries(e).map(([e,n])=>[e,W(n,`${t}.${n.contractName}`)]))}function U(e,t){return Object.fromEntries(Object.entries(e).map(([e,n])=>[e,Object.assign((...e)=>{let r=R(n,e),[i,a]=t.split(`.`);return{functionArgs:r,contractAddress:i,contractName:a,function:n,functionName:n.name,nativeArgs:e}},{abi:n})]))}function W(e,t){let n={...e};return{...U(e.functions,t),...n,identifier:t}}function Ne(r,i){let a={};return n(i.plan.batches).forEach(n=>{let i=e(n),[o,s]=i.split(`.`),c=h(s),l=r[c],u=r[c];if(u===void 0)throw Error(`Clarigen error: mismatch for contract '${c}'`);a[c]=u,u.contractFile=t(n),u.identifier=i,Object.keys(r[c].functions).forEach(e=>{let t=e;u[t]=((...e)=>{let n=l.functions[t];return{functionArgs:R(n,e),contractAddress:o,contractName:u.contractName,function:n,nativeArgs:e}})})}),a}function G(e,t){return{key:t,keyCV:N(t,e.key),map:e}}function K(e,t={}){let n={...t};return e&&(n[`x-api-key`]=e),n}function Pe(e,t,n){return new de(new ue({basePath:e,headers:K(t,n)}))}function Fe(e){return`${e}/v2`}const Ie=(e,t)=>{try{let n=new URL(e);return Object.keys(t).forEach(e=>{let r=t[e];if(r){if(Array.isArray(r))return r.length===0?void 0:n.searchParams.set(`${e}[]`,Le(e,r));if(typeof r==`boolean`||ye(r))return n.searchParams.set(e,String(r));n.searchParams.set(e,r)}}),n.toString()}catch(t){return console.error(`generateUrl`),console.error(t),e}},Le=(e,t)=>t!=null&&t.length?`${t.map((t,n)=>`${n>0?encodeURIComponent(`${e}[]`):``}=${encodeURIComponent(t)}`).join(`&`)}`:``;function Re(e){if(e.okay)return u(e.result);throw Error(e.cause)}async function ze(e){let{contractAddress:t,functionArgs:n,senderAddress:r=t,url:i}=e;return Re(await Pe(i,e.apiKey,e.headers).callReadOnlyFunction({...e,readOnlyFunctionArgs:{sender:r,arguments:n.map(e=>typeof e==`string`?e:c(e))}}))}function Be(e){return typeof e==`object`&&!!e&&`isNone`in e&&typeof e.isNone==`boolean`}function Ve(e){return typeof e==`object`&&!!e&&`isOk`in e&&typeof e.isOk==`boolean`}function q(e,t){if(A(t))return Be(e)?e.isNone?null:q(e.value,t.optional):e;if(E(t))return typeof e==`string`?v(e.startsWith(`0x`)?e.slice(2):e):e;if(j(t)){if(typeof e!=`object`||!e)return e;let n={};for(let r of t.tuple){let t=e[r.name];n[r.name]=q(t,r.type)}return n}return M(t)&&Array.isArray(e)?e.map(e=>q(e,t.list.type)):e}function J(e,t){if(k(t)){if(!Ve(e))throw Error(`Response type requires { isOk: boolean, value: unknown } form value`);let n=e.isOk?t.response.ok:t.response.error,r=J(e.isOk?e.ok??e.value:e.err??e.value,n);return e.isOk?ie(r):re(r)}return N(q(e,t),t)}function He(e,t){if(e===void 0||e===``)return A(t)?{isNone:!0,value:null}:M(t)?[]:j(t)?{}:T(t)&&t===`bool`?!1:``;if(t===`principal`&&e.startsWith(`'`))return e.slice(1);if(A(t)||M(t)||j(t)||k(t))try{return JSON.parse(e)}catch{return e}return T(t)&&t===`bool`?e===`true`:e}function Ue(e,t){return t.map(t=>{let n=e[t.name];return J(He(Array.isArray(n)?n[0]:n,t.type),t.type)})}function We(e){if(e.latest!==!1)return e.latest||e.tip===void 0?`latest`:e.tip}async function Y(e,t){let n=We(t),r=await ze({contractAddress:e.contractAddress,contractName:e.contractName,functionName:e.functionName,functionArgs:e.functionArgs,tip:n,url:X(t),apiKey:t.apiKey,headers:t.headers});return t.json?F(r):C(r,!0)}async function Ge(e,t){return B(await Y(e,t))}async function Ke(e,t){return V(await Y(e,t))}function X(e){return fe(e.network).client.baseUrl}async function qe(e,t,n,r){let i=G(t,n),a=JSON.stringify(s(i.keyCV)),[o,c]=e.split(`.`),u=Ie(`${Fe(X(r))}/map_entry/${o}/${c}/${i.map.name}`,{proof:0,tip:We(r)});return C(l((await(await fetch(u,{method:`POST`,body:a,headers:{"Content-Type":`application/json`,Accept:`application/json`,...K(r.apiKey,r.headers)}})).json()).data),!0)}async function Je(e,t){let n=t.network,r=await i({transaction:e,network:n});if(`error`in r)throw Error(`Error broadcasting tx: ${r.error} - ${r.reason} - ${JSON.stringify(`reason_data`in r?r.reason_data:void 0)}`);return{txId:r.txid,stacksTransaction:e}}var Ye=class{network;constructor(e,t,n){this.apiKey=t,this.headers=n,this.network=e}roOptions(e){return{network:this.network,apiKey:this.apiKey,headers:this.headers,...e}}ro(e,t){return Y(e,this.roOptions(t||{}))}roOk(e,t){return Ge(e,this.roOptions(t||{}))}roErr(e,t){return Ke(e,this.roOptions(t||{}))}};function Z(e,t){let[n,r]=e.identifier.split(`.`);if(!(`identifier`in e))throw Error(`Invalid contract`);for(let i of e.non_fungible_tokens)if(i.name===t)return`${n}.${r}::${i.name}`;for(let i of e.fungible_tokens)if(i.name===t)return`${n}.${r}::${i.name}`;throw Error(`Invalid asset: "${t}" is not an asset in contract.`)}function Xe(e,t,n,r){let[i]=e.non_fungible_tokens,a=Z(e,i.name),o=i.type;return{type:`nft-postcondition`,address:t,condition:n,asset:a,assetId:N(r,o)}}function Ze(e,t,n,r){let[i,a]=t.split(`.`),[o]=e.fungible_tokens;return{type:`ft-postcondition`,address:t,condition:n,asset:Z(e,o.name),amount:r}}function Q(e,t=``){return e.slice(t.length+2,-1)}function $(e,t){if(j(t)){let n=et(e),r={},i=Object.entries(n).reduce((e,[t,n])=>{let r=t.trim();return{...e,[r]:n.trim()}},{});return t.tuple.forEach(({name:e,type:t})=>{let n=h(e);r[n]=$(i[e],t)}),r}if(M(t))return $e(e).map(e=>$(e,t.list.type));if(A(t))return e===`none`?null:$(Q(e,`some`),t.optional);if(D(t))return e.slice(1,-1);if(O(t))return e.slice(2,-1);if(t===`bool`)return e===`true`;if(t===`uint128`)return BigInt(e.slice(1));if(t===`int128`)return BigInt(e);if(t===`trait_reference`||t===`principal`)return e.replace(/^'/,``);if(t===`none`)return null;if(E(t))return v(e.slice(2));if(k(t))return e.startsWith(`(ok`)?b($(Q(e,`ok`),t.response.ok)):x($(Q(e,`err`),t.response.error));throw Error(`Unable to parse cv string to value: ${e} ${JSON.stringify(t,null,2)}`)}const Qe=Array(255);for(let e=0;e<=255;++e)Qe[e]=e.toString(16).padStart(2,`0`);function $e(e){if(e.charAt(0)!==`[`||e.at(-1)!==`]`)throw Error(`Expected (list ..), got ${e.toString()}`);let t=[],n=[],r=1;for(let i=0;i<e.length;i++)e.charAt(i)===`,`&&t.length===1&&(n.push(e.substring(r,i)),r=i+2),[`(`,`[`,`{`].includes(e.charAt(i))&&t.push(e.charAt(i)),e.charAt(i)===`)`&&t.at(-1)===`(`&&t.pop(),e.charAt(i)===`}`&&t.at(-1)===`{`&&t.pop(),e.charAt(i)===`]`&&t.at(-1)===`[`&&t.pop();let i=e.substring(r,e.length-1);return i.length>0&&n.push(i),n}function et(e){if(e.charAt(0)!==`{`||e.at(-1)!==`}`)throw Error(`Expected '(tuple ..)', got ${e.toString()}`);let t=1,n=[],r=[];for(let i=0;i<e.length;i++)e.charAt(i)===`,`&&n.length===1&&(r.push(e.substring(t,i)),t=i+2),[`(`,`[`,`{`].includes(e.charAt(i))&&n.push(e.charAt(i)),e.charAt(i)===`)`&&n.at(-1)===`(`&&n.pop(),e.charAt(i)===`}`&&n.at(-1)===`{`&&n.pop(),e.charAt(i)===`]`&&n.at(-1)===`[`&&n.pop();let i=e.substring(t,e.length-1);i.length>0&&r.push(i);let a={};for(let e of r)for(let t=0;t<e.length;t++)if(e.charAt(t)===`:`){let n=e.substring(0,t);a[n]=e.substring(t+2,e.length);break}return a}export{Ye as ClarigenClient,xe as CoreNodeEventType,Ae as DEPLOYMENT_NETWORKS,m as MAINNET_BURN_ADDRESS,p as TESTNET_BURN_ADDRESS,ge as bootContractIdentifier,Je as broadcast,ve as bytesToAscii,_e as bytesToHex,ze as callReadOnlyFunction,W as contractFactory,Me as contractsFactory,Z as createAssetInfo,s as cvToHex,F as cvToJSON,P as cvToString,C as cvToValue,Ne as deploymentFactory,x as err,V as expectErr,B as expectOk,y as extractErrors,qe as fetchMapGet,Se as filterEvents,z as findJsTupleKey,J as formValueToCV,q as formValueToParseable,U as functionsFactory,X as getApiUrl,me as getContractIdentifier,pe as getContractName,_ as getContractNameFromPath,he as getContractPrincipalCV,H as getTypeString,v as hexToBytes,l as hexToCV,Te as hexToCvValue,E as isClarityAbiBuffer,M as isClarityAbiList,A as isClarityAbiOptional,T as isClarityAbiPrimitive,k as isClarityAbiResponse,D as isClarityAbiStringAscii,O as isClarityAbiStringUtf8,Ee as isClarityAbiTraitReference,j as isClarityAbiTuple,ye as isNumber,Be as isOptionalFormValue,we as isResponse,Ve as isResponseFormValue,Ce as makeContracts,Ze as makeFungiblePostCondition,Xe as makeNonFungiblePostCondition,G as mapFactory,b as ok,He as parseQueryValue,Re as parseReadOnlyResponse,N as parseToCV,S as principalToString,be as projectErrors,je as projectFactory,ke as pureProxy,Ue as queryToFunctionArgs,$ as rawClarityToValue,Y as ro,Ke as roErr,Ge as roOk,h as toCamelCase,g as toKebabCase,L as transformArgsArray,R as transformArgsToCV,I as transformObjectArgs};
|
|
1
|
+
import { a as getIdentifierForDeploymentTx, i as getDeploymentTxPath, n as getContractTxs } from "./deployment-BoAUH7JK.mjs";
|
|
2
|
+
import { ClarityType, broadcastTransaction, bufferCV, contractPrincipalCV, cvToHex, cvToHex as cvToHex$1, hexToCV, hexToCV as hexToCV$1, intCV, listCV, noneCV, parseToCV as parseToCV$1, responseErrorCV, responseOkCV, someCV, stringAsciiCV, stringUtf8CV, tupleCV, uintCV } from "@stacks/transactions";
|
|
3
|
+
import { hex } from "@scure/base";
|
|
4
|
+
import { Configuration, SmartContractsApi } from "@stacks/blockchain-api-client";
|
|
5
|
+
import { networkFrom } from "@stacks/network";
|
|
6
|
+
|
|
7
|
+
//#region src/utils.ts
|
|
8
|
+
/** biome-ignore-all lint/style/useTrimStartEnd: suppressed */
|
|
9
|
+
const TESTNET_BURN_ADDRESS = "ST000000000000000000002AMW42H";
|
|
10
|
+
const MAINNET_BURN_ADDRESS = "SP000000000000000000002Q6VF78";
|
|
11
|
+
const toCamelCase = (input, titleCase) => {
|
|
12
|
+
const inputStr = typeof input === "string" ? input : String(input);
|
|
13
|
+
if (/^[A-Z_]+$/.test(inputStr)) return inputStr;
|
|
14
|
+
const [first, ...parts] = inputStr.replace("!", "_x").replace("?", "_q").split("-");
|
|
15
|
+
let result = `${titleCase ? first[0].toUpperCase() : first[0].toLowerCase()}${first.slice(1)}`;
|
|
16
|
+
parts.forEach((part) => {
|
|
17
|
+
const capitalized = part[0].toUpperCase() + part.slice(1);
|
|
18
|
+
result += capitalized;
|
|
19
|
+
});
|
|
20
|
+
return result;
|
|
21
|
+
};
|
|
22
|
+
function toKebabCase(input) {
|
|
23
|
+
const matches = input.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g);
|
|
24
|
+
if (!matches) return input;
|
|
25
|
+
return matches.join("-").toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
function getContractName(identifier, camelCase = true) {
|
|
28
|
+
const name = identifier.split(".")[1];
|
|
29
|
+
return camelCase ? toCamelCase(name) : name;
|
|
30
|
+
}
|
|
31
|
+
const getContractNameFromPath = (path) => {
|
|
32
|
+
const filename = path.split("/").at(-1);
|
|
33
|
+
const [contractName] = (filename === null || filename === void 0 ? void 0 : filename.split(".")) ?? [];
|
|
34
|
+
return contractName;
|
|
35
|
+
};
|
|
36
|
+
const getContractIdentifier = (contract) => `${contract.address}.${contract.name}`;
|
|
37
|
+
const getContractPrincipalCV = (contract) => {
|
|
38
|
+
const contractName = getContractNameFromPath(contract.contractFile);
|
|
39
|
+
return contractPrincipalCV(contract.address, contractName);
|
|
40
|
+
};
|
|
41
|
+
function bootContractIdentifier(name, mainnet) {
|
|
42
|
+
return `${mainnet ? MAINNET_BURN_ADDRESS : TESTNET_BURN_ADDRESS}.${name}`;
|
|
43
|
+
}
|
|
44
|
+
function bytesToHex(bytes) {
|
|
45
|
+
return hex.encode(bytes);
|
|
46
|
+
}
|
|
47
|
+
function hexToBytes(hexString) {
|
|
48
|
+
return hex.decode(hexString);
|
|
49
|
+
}
|
|
50
|
+
function bytesToAscii(bytes) {
|
|
51
|
+
const bytesArray = Array.from(bytes);
|
|
52
|
+
return String.fromCharCode.apply(null, bytesArray);
|
|
53
|
+
}
|
|
54
|
+
const isNumber = (value) => typeof value === "number";
|
|
55
|
+
function extractErrors(contract) {
|
|
56
|
+
const { constants } = contract;
|
|
57
|
+
const result = {};
|
|
58
|
+
for (const key in constants) if (key.toLowerCase().startsWith("err")) {
|
|
59
|
+
const value = constants[key];
|
|
60
|
+
if (typeof value === "object" && value && "isOk" in value && !value.isOk && "value" in value) result[key] = value.value;
|
|
61
|
+
else result[key] = value;
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
function projectErrors(project) {
|
|
66
|
+
const { contracts } = project;
|
|
67
|
+
const result = {};
|
|
68
|
+
for (const key in contracts) result[key] = extractErrors(contracts[key]);
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/events.ts
|
|
74
|
+
let CoreNodeEventType = /* @__PURE__ */ function(CoreNodeEventType$1) {
|
|
75
|
+
CoreNodeEventType$1["ContractEvent"] = "contract_event";
|
|
76
|
+
CoreNodeEventType$1["StxTransferEvent"] = "stx_transfer_event";
|
|
77
|
+
CoreNodeEventType$1["StxMintEvent"] = "stx_mint_event";
|
|
78
|
+
CoreNodeEventType$1["StxBurnEvent"] = "stx_burn_event";
|
|
79
|
+
CoreNodeEventType$1["StxLockEvent"] = "stx_lock_event";
|
|
80
|
+
CoreNodeEventType$1["NftTransferEvent"] = "nft_transfer_event";
|
|
81
|
+
CoreNodeEventType$1["NftMintEvent"] = "nft_mint_event";
|
|
82
|
+
CoreNodeEventType$1["NftBurnEvent"] = "nft_burn_event";
|
|
83
|
+
CoreNodeEventType$1["FtTransferEvent"] = "ft_transfer_event";
|
|
84
|
+
CoreNodeEventType$1["FtMintEvent"] = "ft_mint_event";
|
|
85
|
+
CoreNodeEventType$1["FtBurnEvent"] = "ft_burn_event";
|
|
86
|
+
return CoreNodeEventType$1;
|
|
87
|
+
}({});
|
|
88
|
+
function filterEvents(events, type) {
|
|
89
|
+
return events.filter((event) => event.type === type);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/contracts.ts
|
|
94
|
+
function makeContracts(contracts, options = {}) {
|
|
95
|
+
const instances = {};
|
|
96
|
+
for (const k in contracts) {
|
|
97
|
+
const contract = contracts[k];
|
|
98
|
+
const address = options.deployerAddress || contract.address;
|
|
99
|
+
instances[k] = {
|
|
100
|
+
identifier: `${address}.${contract.name}`,
|
|
101
|
+
contract: contract.contract(address, contract.name)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return instances;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/clarity-types.ts
|
|
109
|
+
/** biome-ignore-all lint/style/useTrimStartEnd: suppressed */
|
|
110
|
+
function ok(value) {
|
|
111
|
+
return {
|
|
112
|
+
isOk: true,
|
|
113
|
+
value
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function err(value) {
|
|
117
|
+
return {
|
|
118
|
+
isOk: false,
|
|
119
|
+
value
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function isResponse(value) {
|
|
123
|
+
return typeof value === "object" && value !== null && "isOk" in value;
|
|
124
|
+
}
|
|
125
|
+
function principalToString(principal) {
|
|
126
|
+
return principal.value;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @param val - ClarityValue
|
|
130
|
+
* @param returnResponse - if true, this will return a "response" object.
|
|
131
|
+
* Otherwise, it returns the inner value of the response (whether ok or err)
|
|
132
|
+
*/
|
|
133
|
+
function cvToValue(val, returnResponse = false) {
|
|
134
|
+
switch (val.type) {
|
|
135
|
+
case ClarityType.BoolTrue: return true;
|
|
136
|
+
case ClarityType.BoolFalse: return false;
|
|
137
|
+
case ClarityType.Int:
|
|
138
|
+
case ClarityType.UInt: return val.value;
|
|
139
|
+
case ClarityType.Buffer: return hexToBytes(val.value);
|
|
140
|
+
case ClarityType.OptionalNone: return null;
|
|
141
|
+
case ClarityType.OptionalSome: return cvToValue(val.value, true);
|
|
142
|
+
case ClarityType.ResponseErr:
|
|
143
|
+
if (returnResponse) return err(cvToValue(val.value, true));
|
|
144
|
+
return cvToValue(val.value, true);
|
|
145
|
+
case ClarityType.ResponseOk:
|
|
146
|
+
if (returnResponse) return ok(cvToValue(val.value, true));
|
|
147
|
+
return cvToValue(val.value, true);
|
|
148
|
+
case ClarityType.PrincipalStandard:
|
|
149
|
+
case ClarityType.PrincipalContract: return principalToString(val);
|
|
150
|
+
case ClarityType.List: return val.value.map((v) => cvToValue(v, true));
|
|
151
|
+
case ClarityType.Tuple: return Object.entries(val.value).reduce((acc, [key, val$1]) => {
|
|
152
|
+
const keyFixed = toCamelCase(key);
|
|
153
|
+
return {
|
|
154
|
+
...acc,
|
|
155
|
+
[keyFixed]: cvToValue(val$1, true)
|
|
156
|
+
};
|
|
157
|
+
}, {});
|
|
158
|
+
case ClarityType.StringASCII: return val.value;
|
|
159
|
+
case ClarityType.StringUTF8: return val.value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Converts a hex encoded string to the javascript clarity value object {type: string; value: any}
|
|
164
|
+
* @param hex - the hex encoded string with or without `0x` prefix
|
|
165
|
+
* @param jsonCompat - enable to serialize bigints to strings
|
|
166
|
+
*/
|
|
167
|
+
function hexToCvValue(hex$1, jsonCompat = false) {
|
|
168
|
+
return cvToValue(hexToCV$1(hex$1), jsonCompat);
|
|
169
|
+
}
|
|
170
|
+
function inputToBigInt(input) {
|
|
171
|
+
if (!(typeof input === "bigint" || typeof input === "number" || typeof input === "string")) throw new Error("Invalid input type for integer");
|
|
172
|
+
return BigInt(input);
|
|
173
|
+
}
|
|
174
|
+
const isClarityAbiPrimitive = (val) => typeof val === "string";
|
|
175
|
+
const isClarityAbiBuffer = (val) => val.buffer !== void 0;
|
|
176
|
+
const isClarityAbiStringAscii = (val) => val["string-ascii"] !== void 0;
|
|
177
|
+
const isClarityAbiStringUtf8 = (val) => val["string-utf8"] !== void 0;
|
|
178
|
+
const isClarityAbiResponse = (val) => val.response !== void 0;
|
|
179
|
+
const isClarityAbiOptional = (val) => val.optional !== void 0;
|
|
180
|
+
const isClarityAbiTuple = (val) => val.tuple !== void 0;
|
|
181
|
+
const isClarityAbiList = (val) => val.list !== void 0;
|
|
182
|
+
const isClarityAbiTraitReference = (val) => val === "trait_reference";
|
|
183
|
+
function parseToCV(input, type) {
|
|
184
|
+
if (isClarityAbiTuple(type)) {
|
|
185
|
+
if (typeof input !== "object") throw new Error("Invalid tuple input");
|
|
186
|
+
const tuple = {};
|
|
187
|
+
type.tuple.forEach((key) => {
|
|
188
|
+
const val = input[findJsTupleKey(key.name, input)];
|
|
189
|
+
tuple[key.name] = parseToCV(val, key.type);
|
|
190
|
+
});
|
|
191
|
+
return tupleCV(tuple);
|
|
192
|
+
}
|
|
193
|
+
if (isClarityAbiList(type)) return listCV(input.map((input$1) => parseToCV(input$1, type.list.type)));
|
|
194
|
+
if (isClarityAbiOptional(type)) {
|
|
195
|
+
if (input === null) return noneCV();
|
|
196
|
+
return someCV(parseToCV(input, type.optional));
|
|
197
|
+
}
|
|
198
|
+
if (isClarityAbiStringAscii(type)) {
|
|
199
|
+
if (typeof input !== "string") throw new Error("Invalid string-ascii input");
|
|
200
|
+
return stringAsciiCV(input);
|
|
201
|
+
}
|
|
202
|
+
if (isClarityAbiStringUtf8(type)) {
|
|
203
|
+
if (typeof input !== "string") throw new Error("Invalid string-ascii input");
|
|
204
|
+
return stringUtf8CV(input);
|
|
205
|
+
}
|
|
206
|
+
if (isClarityAbiResponse(type)) {
|
|
207
|
+
if (!isResponse(input)) throw new Error("Invalid response input");
|
|
208
|
+
if (input.isOk) return responseOkCV(parseToCV(input.value, type.response.ok));
|
|
209
|
+
return responseErrorCV(parseToCV(input.value, type.response.error));
|
|
210
|
+
}
|
|
211
|
+
if (type === "bool") return parseToCV$1(typeof input === "boolean" ? input.toString() : input, type);
|
|
212
|
+
if (type === "uint128") return uintCV(inputToBigInt(input).toString());
|
|
213
|
+
if (type === "int128") return intCV(inputToBigInt(input).toString());
|
|
214
|
+
if (type === "trait_reference") {
|
|
215
|
+
if (typeof input !== "string") throw new Error("Invalid input for trait_reference");
|
|
216
|
+
const [addr, name] = input.split(".");
|
|
217
|
+
return contractPrincipalCV(addr, name);
|
|
218
|
+
}
|
|
219
|
+
if (isClarityAbiBuffer(type)) return bufferCV(input);
|
|
220
|
+
return parseToCV$1(input, type);
|
|
221
|
+
}
|
|
222
|
+
function cvToString(val, optionsOrEncoding) {
|
|
223
|
+
const options = typeof optionsOrEncoding === "object" ? optionsOrEncoding : {
|
|
224
|
+
encoding: optionsOrEncoding,
|
|
225
|
+
indent: void 0,
|
|
226
|
+
depth: void 0
|
|
227
|
+
};
|
|
228
|
+
const encoding = options.encoding ?? "hex";
|
|
229
|
+
const indent = options.indent;
|
|
230
|
+
const depth = options.depth ?? 0;
|
|
231
|
+
switch (val.type) {
|
|
232
|
+
case ClarityType.BoolTrue: return "true";
|
|
233
|
+
case ClarityType.BoolFalse: return "false";
|
|
234
|
+
case ClarityType.Int: return val.value.toString();
|
|
235
|
+
case ClarityType.UInt: return `u${val.value.toString()}`;
|
|
236
|
+
case ClarityType.Buffer:
|
|
237
|
+
if (encoding === "tryAscii") {
|
|
238
|
+
const str = bytesToAscii(hexToBytes(val.value));
|
|
239
|
+
if (/[ -~]/.test(str)) return JSON.stringify(str);
|
|
240
|
+
}
|
|
241
|
+
return `0x${val.value}`;
|
|
242
|
+
case ClarityType.OptionalNone: return "none";
|
|
243
|
+
case ClarityType.OptionalSome: return `(some ${cvToString(val.value, options)})`;
|
|
244
|
+
case ClarityType.ResponseErr: return `(err ${cvToString(val.value, options)})`;
|
|
245
|
+
case ClarityType.ResponseOk: return `(ok ${cvToString(val.value, options)})`;
|
|
246
|
+
case ClarityType.PrincipalStandard:
|
|
247
|
+
case ClarityType.PrincipalContract: return `'${principalToString(val)}`;
|
|
248
|
+
case ClarityType.List: return `(list ${val.value.map((v) => cvToString(v, options)).join(" ")})`;
|
|
249
|
+
case ClarityType.Tuple: {
|
|
250
|
+
const keys = Object.keys(val.value);
|
|
251
|
+
if (indent === void 0 || keys.length === 0) return `{ ${keys.map((key) => `${key}: ${cvToString(val.value[key], options)}`).join(", ")} }`;
|
|
252
|
+
const padding = " ".repeat((depth + 1) * indent);
|
|
253
|
+
const outerPadding = " ".repeat(depth * indent);
|
|
254
|
+
return `{\n${keys.map((key) => `${padding}${key}: ${cvToString(val.value[key], {
|
|
255
|
+
...options,
|
|
256
|
+
depth: depth + 1
|
|
257
|
+
})}`).join(",\n")}\n${outerPadding}}`;
|
|
258
|
+
}
|
|
259
|
+
case ClarityType.StringASCII: return `"${val.value}"`;
|
|
260
|
+
case ClarityType.StringUTF8: return `u"${val.value}"`;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Convert a Clarity value to valid JSON. This does this same thing as
|
|
265
|
+
* `cvToValue`, except that integers are returned as strings, and buffers
|
|
266
|
+
* are returned as hex-encoded strings.
|
|
267
|
+
*
|
|
268
|
+
* @param val - ClarityValue
|
|
269
|
+
*/
|
|
270
|
+
function cvToJSON(val, returnResponse = false) {
|
|
271
|
+
switch (val.type) {
|
|
272
|
+
case ClarityType.BoolTrue: return true;
|
|
273
|
+
case ClarityType.BoolFalse: return false;
|
|
274
|
+
case ClarityType.Int:
|
|
275
|
+
case ClarityType.UInt: return `${val.value}`;
|
|
276
|
+
case ClarityType.Buffer: return val.value;
|
|
277
|
+
case ClarityType.OptionalNone: return null;
|
|
278
|
+
case ClarityType.OptionalSome: return cvToJSON(val.value);
|
|
279
|
+
case ClarityType.ResponseErr:
|
|
280
|
+
if (returnResponse) return err(cvToJSON(val.value));
|
|
281
|
+
return cvToJSON(val.value);
|
|
282
|
+
case ClarityType.ResponseOk:
|
|
283
|
+
if (returnResponse) return ok(cvToJSON(val.value));
|
|
284
|
+
return cvToJSON(val.value);
|
|
285
|
+
case ClarityType.PrincipalStandard:
|
|
286
|
+
case ClarityType.PrincipalContract: return principalToString(val);
|
|
287
|
+
case ClarityType.List: return val.value.map((v) => cvToJSON(v));
|
|
288
|
+
case ClarityType.Tuple: return Object.entries(val.value).reduce((acc, [key, val$1]) => {
|
|
289
|
+
const keyFixed = toCamelCase(key);
|
|
290
|
+
return {
|
|
291
|
+
...acc,
|
|
292
|
+
[keyFixed]: cvToJSON(val$1)
|
|
293
|
+
};
|
|
294
|
+
}, {});
|
|
295
|
+
case ClarityType.StringASCII: return val.value;
|
|
296
|
+
case ClarityType.StringUTF8: return val.value;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
function transformObjectArgs(func, args) {
|
|
300
|
+
return func.args.map((abiArg) => {
|
|
301
|
+
const val = args[findJsTupleKey(abiArg.name, args)];
|
|
302
|
+
return parseToCV(val, abiArg.type);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
function transformArgsArray(func, args) {
|
|
306
|
+
return args.map((arg, index) => parseToCV(arg, func.args[index].type));
|
|
307
|
+
}
|
|
308
|
+
function transformArgsToCV(func, args) {
|
|
309
|
+
if (args.length === 0) return [];
|
|
310
|
+
const [firstArg] = args;
|
|
311
|
+
if (args.length === 1 && func.args.length !== 1) return transformObjectArgs(func, firstArg);
|
|
312
|
+
if (typeof firstArg === "object" && !Array.isArray(firstArg) && firstArg !== null) try {
|
|
313
|
+
let hasAllArgs = true;
|
|
314
|
+
func.args.forEach((a) => {
|
|
315
|
+
try {
|
|
316
|
+
findJsTupleKey(a.name, firstArg);
|
|
317
|
+
} catch (_error) {
|
|
318
|
+
hasAllArgs = false;
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
if (hasAllArgs) return transformObjectArgs(func, firstArg);
|
|
322
|
+
} catch (_error) {}
|
|
323
|
+
return transformArgsArray(func, args);
|
|
324
|
+
}
|
|
325
|
+
function findJsTupleKey(key, input) {
|
|
326
|
+
const found = Object.keys(input).find((k) => {
|
|
327
|
+
const camelEq = key === k;
|
|
328
|
+
const kebabEq = key === toKebabCase(k);
|
|
329
|
+
return camelEq || kebabEq;
|
|
330
|
+
});
|
|
331
|
+
if (!found) throw new Error(`Error encoding JS tuple: ${key} not found in input.`);
|
|
332
|
+
return found;
|
|
333
|
+
}
|
|
334
|
+
function expectOk(response) {
|
|
335
|
+
if (response.isOk) return response.value;
|
|
336
|
+
throw new Error(`Expected OK, received error: ${String(response.value)}`);
|
|
337
|
+
}
|
|
338
|
+
function expectErr(response) {
|
|
339
|
+
if (!response.isOk) return response.value;
|
|
340
|
+
throw new Error(`Expected Err, received ok: ${String(response.value)}`);
|
|
341
|
+
}
|
|
342
|
+
function getTypeString(val) {
|
|
343
|
+
if (isClarityAbiPrimitive(val)) {
|
|
344
|
+
if (val === "int128") return "int";
|
|
345
|
+
if (val === "uint128") return "uint";
|
|
346
|
+
return val;
|
|
347
|
+
}
|
|
348
|
+
if (isClarityAbiBuffer(val)) return `(buff ${val.buffer.length})`;
|
|
349
|
+
if (isClarityAbiStringAscii(val)) return `(string-ascii ${val["string-ascii"].length})`;
|
|
350
|
+
if (isClarityAbiStringUtf8(val)) return `(string-utf8 ${val["string-utf8"].length})`;
|
|
351
|
+
if (isClarityAbiResponse(val)) return `(response ${getTypeString(val.response.ok)} ${getTypeString(val.response.error)})`;
|
|
352
|
+
if (isClarityAbiOptional(val)) return `(optional ${getTypeString(val.optional)})`;
|
|
353
|
+
if (isClarityAbiTuple(val)) return `{ ${val.tuple.map((t) => `${t.name}: ${getTypeString(t.type)}`).join(", ")} }`;
|
|
354
|
+
if (isClarityAbiList(val)) return `(list ${val.list.length} ${getTypeString(val.list.type)})`;
|
|
355
|
+
throw new Error(`Type string unsupported for Clarity type: ${JSON.stringify(val)}`);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region src/factory.ts
|
|
360
|
+
const DEPLOYMENT_NETWORKS = [
|
|
361
|
+
"devnet",
|
|
362
|
+
"simnet",
|
|
363
|
+
"testnet",
|
|
364
|
+
"mainnet"
|
|
365
|
+
];
|
|
366
|
+
function projectFactory(project, network) {
|
|
367
|
+
const e = [];
|
|
368
|
+
Object.entries(project.contracts).forEach(([contractName, contract]) => {
|
|
369
|
+
const id = project.deployments[contractName][network];
|
|
370
|
+
if (id) e.push([contractName, contractFactory(contract, id)]);
|
|
371
|
+
return false;
|
|
372
|
+
});
|
|
373
|
+
return Object.fromEntries(e);
|
|
374
|
+
}
|
|
375
|
+
function contractsFactory(contracts, deployer) {
|
|
376
|
+
return Object.fromEntries(Object.entries(contracts).map(([contractName, contract]) => {
|
|
377
|
+
return [contractName, contractFactory(contract, `${deployer}.${contract.contractName}`)];
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
function functionsFactory(abi, identifier) {
|
|
381
|
+
return Object.fromEntries(Object.entries(abi.functions).map(([fnName, foundFunction]) => {
|
|
382
|
+
return [fnName, Object.assign((...args) => {
|
|
383
|
+
const functionArgs = transformArgsToCV(foundFunction, args);
|
|
384
|
+
const [contractAddress, contractName] = identifier.split(".");
|
|
385
|
+
return {
|
|
386
|
+
functionArgs,
|
|
387
|
+
contractAddress,
|
|
388
|
+
contractName,
|
|
389
|
+
function: foundFunction,
|
|
390
|
+
functionName: foundFunction.name,
|
|
391
|
+
nativeArgs: args,
|
|
392
|
+
contractAbi: abi
|
|
393
|
+
};
|
|
394
|
+
}, { abi: foundFunction })];
|
|
395
|
+
}));
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Provide a contract's types and it's contract identifier to generate
|
|
399
|
+
* a full contract object with all functions available.
|
|
400
|
+
*
|
|
401
|
+
* @param abi - The Clarigen-generated contract types
|
|
402
|
+
* @param identifier - The contract's identifier, like `SP000000000000000000002Q6VF78.bns`
|
|
403
|
+
* @returns
|
|
404
|
+
*/
|
|
405
|
+
function contractFactory(abi, identifier) {
|
|
406
|
+
const full = { ...abi };
|
|
407
|
+
return {
|
|
408
|
+
...functionsFactory(abi, identifier),
|
|
409
|
+
...full,
|
|
410
|
+
identifier
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function deploymentFactory(contracts, deployer) {
|
|
414
|
+
const result = {};
|
|
415
|
+
getContractTxs(deployer.plan.batches).forEach((tx) => {
|
|
416
|
+
const id = getIdentifierForDeploymentTx(tx);
|
|
417
|
+
const [contractAddress, contractFileName] = id.split(".");
|
|
418
|
+
const contractName = toCamelCase(contractFileName);
|
|
419
|
+
const def = contracts[contractName];
|
|
420
|
+
const final = contracts[contractName];
|
|
421
|
+
if (typeof final === "undefined") throw new Error(`Clarigen error: mismatch for contract '${contractName}'`);
|
|
422
|
+
result[contractName] = final;
|
|
423
|
+
final.contractFile = getDeploymentTxPath(tx);
|
|
424
|
+
final.identifier = id;
|
|
425
|
+
Object.keys(contracts[contractName].functions).forEach((_fnName) => {
|
|
426
|
+
const fnName = _fnName;
|
|
427
|
+
const fn = ((...args) => {
|
|
428
|
+
const foundFunction = def.functions[fnName];
|
|
429
|
+
return {
|
|
430
|
+
functionArgs: transformArgsToCV(foundFunction, args),
|
|
431
|
+
contractAddress,
|
|
432
|
+
contractName: final.contractName,
|
|
433
|
+
function: foundFunction,
|
|
434
|
+
nativeArgs: args
|
|
435
|
+
};
|
|
436
|
+
});
|
|
437
|
+
final[fnName] = fn;
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
function mapFactory(map, key) {
|
|
443
|
+
return {
|
|
444
|
+
key,
|
|
445
|
+
keyCV: parseToCV(key, map.key),
|
|
446
|
+
map
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
//#endregion
|
|
451
|
+
//#region src/api/api-helpers.ts
|
|
452
|
+
/** biome-ignore-all lint/style/useTrimStartEnd: suppressed */
|
|
453
|
+
function getHeaders(apiKey, headersOverride = {}) {
|
|
454
|
+
const headers = { ...headersOverride };
|
|
455
|
+
if (apiKey) headers["x-api-key"] = apiKey;
|
|
456
|
+
return headers;
|
|
457
|
+
}
|
|
458
|
+
function smartContractsApi(url, apiKey, headersOverride) {
|
|
459
|
+
return new SmartContractsApi(new Configuration({
|
|
460
|
+
basePath: url,
|
|
461
|
+
headers: getHeaders(apiKey, headersOverride)
|
|
462
|
+
}));
|
|
463
|
+
}
|
|
464
|
+
function v2Endpoint(url) {
|
|
465
|
+
return `${url}/v2`;
|
|
466
|
+
}
|
|
467
|
+
const generateUrl = (baseUrl, params) => {
|
|
468
|
+
try {
|
|
469
|
+
const url = new URL(baseUrl);
|
|
470
|
+
Object.keys(params).forEach((key) => {
|
|
471
|
+
const value = params[key];
|
|
472
|
+
if (!value) return;
|
|
473
|
+
if (Array.isArray(value)) {
|
|
474
|
+
if (value.length === 0) return;
|
|
475
|
+
return url.searchParams.set(`${key}[]`, generateQueryStringFromArray(key, value));
|
|
476
|
+
}
|
|
477
|
+
if (typeof value === "boolean" || isNumber(value)) return url.searchParams.set(key, String(value));
|
|
478
|
+
url.searchParams.set(key, value);
|
|
479
|
+
});
|
|
480
|
+
return url.toString();
|
|
481
|
+
} catch (e) {
|
|
482
|
+
console.error("generateUrl");
|
|
483
|
+
console.error(e);
|
|
484
|
+
return baseUrl;
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
const generateQueryStringFromArray = (key, values) => {
|
|
488
|
+
if (values === null || values === void 0 ? void 0 : values.length) return `${values.map((value, index) => `${index > 0 ? encodeURIComponent(`${key}[]`) : ""}=${encodeURIComponent(value)}`).join("&")}`;
|
|
489
|
+
return "";
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/api/call-read-only.ts
|
|
494
|
+
/**
|
|
495
|
+
* Converts the response of a read-only function call into its Clarity Value
|
|
496
|
+
* @param response - {@link ReadOnlyFunctionResponse}
|
|
497
|
+
*/
|
|
498
|
+
function parseReadOnlyResponse(response) {
|
|
499
|
+
if (response.okay) return hexToCV$1(response.result);
|
|
500
|
+
throw new Error(response.cause);
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Calls a read only function from a contract interface
|
|
504
|
+
*
|
|
505
|
+
* @param options - the options object
|
|
506
|
+
*
|
|
507
|
+
* Returns an ClarityValue
|
|
508
|
+
*
|
|
509
|
+
*/
|
|
510
|
+
async function callReadOnlyFunction(options) {
|
|
511
|
+
const { contractAddress, functionArgs, senderAddress = contractAddress, url } = options;
|
|
512
|
+
return parseReadOnlyResponse(await smartContractsApi(url, options.apiKey, options.headers).callReadOnlyFunction({
|
|
513
|
+
...options,
|
|
514
|
+
readOnlyFunctionArgs: {
|
|
515
|
+
sender: senderAddress,
|
|
516
|
+
arguments: functionArgs.map((arg) => typeof arg === "string" ? arg : cvToHex$1(arg))
|
|
517
|
+
}
|
|
518
|
+
}));
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
//#endregion
|
|
522
|
+
//#region src/api/url-parsing.ts
|
|
523
|
+
function isOptionalFormValue(value) {
|
|
524
|
+
return typeof value === "object" && value !== null && "isNone" in value && typeof value.isNone === "boolean";
|
|
525
|
+
}
|
|
526
|
+
function isResponseFormValue(value) {
|
|
527
|
+
return typeof value === "object" && value !== null && "isOk" in value && typeof value.isOk === "boolean";
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Converts a form value to the format expected by parseToCV.
|
|
531
|
+
* Handles differences between form representation and parseToCV expectations:
|
|
532
|
+
* - Optionals use { isNone, value } in forms but null for none in parseToCV
|
|
533
|
+
* - Buffers are hex strings in forms but Uint8Array in parseToCV
|
|
534
|
+
*/
|
|
535
|
+
function formValueToParseable(value, type) {
|
|
536
|
+
if (isClarityAbiOptional(type)) {
|
|
537
|
+
if (isOptionalFormValue(value)) {
|
|
538
|
+
if (value.isNone) return null;
|
|
539
|
+
return formValueToParseable(value.value, type.optional);
|
|
540
|
+
}
|
|
541
|
+
return value;
|
|
542
|
+
}
|
|
543
|
+
if (isClarityAbiBuffer(type)) {
|
|
544
|
+
if (typeof value === "string") return hexToBytes(value.startsWith("0x") ? value.slice(2) : value);
|
|
545
|
+
return value;
|
|
546
|
+
}
|
|
547
|
+
if (isClarityAbiTuple(type)) {
|
|
548
|
+
if (typeof value !== "object" || value === null) return value;
|
|
549
|
+
const result = {};
|
|
550
|
+
for (const member of type.tuple) {
|
|
551
|
+
const memberValue = value[member.name];
|
|
552
|
+
result[member.name] = formValueToParseable(memberValue, member.type);
|
|
553
|
+
}
|
|
554
|
+
return result;
|
|
555
|
+
}
|
|
556
|
+
if (isClarityAbiList(type)) {
|
|
557
|
+
if (!Array.isArray(value)) return value;
|
|
558
|
+
return value.map((item) => formValueToParseable(item, type.list.type));
|
|
559
|
+
}
|
|
560
|
+
return value;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Converts a single form value to a ClarityValue using the ABI type.
|
|
564
|
+
*/
|
|
565
|
+
function formValueToCV(value, type) {
|
|
566
|
+
if (isClarityAbiResponse(type)) {
|
|
567
|
+
if (!isResponseFormValue(value)) throw new Error("Response type requires { isOk: boolean, value: unknown } form value");
|
|
568
|
+
const innerType = value.isOk ? type.response.ok : type.response.error;
|
|
569
|
+
const innerCV = formValueToCV(value.isOk ? value.ok ?? value.value : value.err ?? value.value, innerType);
|
|
570
|
+
return value.isOk ? responseOkCV(innerCV) : responseErrorCV(innerCV);
|
|
571
|
+
}
|
|
572
|
+
return parseToCV(formValueToParseable(value, type), type);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Parses a raw string value from a URL query parameter into a "form value"
|
|
576
|
+
* based on the Clarity ABI type. This intermediate form value can then
|
|
577
|
+
* be converted to a ClarityValue using `formValueToCV`.
|
|
578
|
+
*/
|
|
579
|
+
function parseQueryValue(value, type) {
|
|
580
|
+
if (value === void 0 || value === "") {
|
|
581
|
+
if (isClarityAbiOptional(type)) return {
|
|
582
|
+
isNone: true,
|
|
583
|
+
value: null
|
|
584
|
+
};
|
|
585
|
+
if (isClarityAbiList(type)) return [];
|
|
586
|
+
if (isClarityAbiTuple(type)) return {};
|
|
587
|
+
if (isClarityAbiPrimitive(type) && type === "bool") return false;
|
|
588
|
+
return "";
|
|
589
|
+
}
|
|
590
|
+
if (type === "principal" && value.startsWith("'")) return value.slice(1);
|
|
591
|
+
if (isClarityAbiOptional(type) || isClarityAbiList(type) || isClarityAbiTuple(type) || isClarityAbiResponse(type)) try {
|
|
592
|
+
return JSON.parse(value);
|
|
593
|
+
} catch {
|
|
594
|
+
return value;
|
|
595
|
+
}
|
|
596
|
+
if (isClarityAbiPrimitive(type) && type === "bool") return value === "true";
|
|
597
|
+
return value;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Converts all query parameters to an array of ClarityValues based on the function's ABI args.
|
|
601
|
+
*/
|
|
602
|
+
function queryToFunctionArgs(query, args) {
|
|
603
|
+
return args.map((arg) => {
|
|
604
|
+
const rawValue = query[arg.name];
|
|
605
|
+
return formValueToCV(parseQueryValue(Array.isArray(rawValue) ? rawValue[0] : rawValue, arg.type), arg.type);
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
//#endregion
|
|
610
|
+
//#region src/api/index.ts
|
|
611
|
+
/** biome-ignore-all lint/style/useTrimStartEnd: suppressed */
|
|
612
|
+
function getTip(options) {
|
|
613
|
+
if (options.latest === false) return;
|
|
614
|
+
if (options.latest) return "latest";
|
|
615
|
+
if (typeof options.tip === "undefined") return "latest";
|
|
616
|
+
return options.tip;
|
|
617
|
+
}
|
|
618
|
+
async function ro(tx, options) {
|
|
619
|
+
const tip = getTip(options);
|
|
620
|
+
const cv = await callReadOnlyFunction({
|
|
621
|
+
contractAddress: tx.contractAddress,
|
|
622
|
+
contractName: tx.contractName,
|
|
623
|
+
functionName: tx.functionName,
|
|
624
|
+
functionArgs: tx.functionArgs,
|
|
625
|
+
tip,
|
|
626
|
+
url: getApiUrl(options),
|
|
627
|
+
apiKey: options.apiKey,
|
|
628
|
+
headers: options.headers
|
|
629
|
+
});
|
|
630
|
+
if (options.json) return cvToJSON(cv);
|
|
631
|
+
return cvToValue(cv, true);
|
|
632
|
+
}
|
|
633
|
+
async function roOk(tx, options) {
|
|
634
|
+
return expectOk(await ro(tx, options));
|
|
635
|
+
}
|
|
636
|
+
async function roErr(tx, options) {
|
|
637
|
+
return expectErr(await ro(tx, options));
|
|
638
|
+
}
|
|
639
|
+
function getApiUrl(opts) {
|
|
640
|
+
return networkFrom(opts.network).client.baseUrl;
|
|
641
|
+
}
|
|
642
|
+
async function fetchMapGet(contractId, map, key, options) {
|
|
643
|
+
const payload = mapFactory(map, key);
|
|
644
|
+
const lookupKey = JSON.stringify(cvToHex(payload.keyCV));
|
|
645
|
+
const [addr, id] = contractId.split(".");
|
|
646
|
+
const path = generateUrl(`${v2Endpoint(getApiUrl(options))}/map_entry/${addr}/${id}/${payload.map.name}`, {
|
|
647
|
+
proof: 0,
|
|
648
|
+
tip: getTip(options)
|
|
649
|
+
});
|
|
650
|
+
return cvToValue(hexToCV((await (await fetch(path, {
|
|
651
|
+
method: "POST",
|
|
652
|
+
body: lookupKey,
|
|
653
|
+
headers: {
|
|
654
|
+
"Content-Type": "application/json",
|
|
655
|
+
Accept: "application/json",
|
|
656
|
+
...getHeaders(options.apiKey, options.headers)
|
|
657
|
+
}
|
|
658
|
+
})).json()).data), true);
|
|
659
|
+
}
|
|
660
|
+
async function broadcast(transaction, options) {
|
|
661
|
+
const network = options.network;
|
|
662
|
+
const result = await broadcastTransaction({
|
|
663
|
+
transaction,
|
|
664
|
+
network
|
|
665
|
+
});
|
|
666
|
+
if ("error" in result) throw new Error(`Error broadcasting tx: ${result.error} - ${result.reason} - ${JSON.stringify("reason_data" in result ? result.reason_data : void 0)}`);
|
|
667
|
+
return {
|
|
668
|
+
txId: result.txid,
|
|
669
|
+
stacksTransaction: transaction
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
var ClarigenClient = class {
|
|
673
|
+
network;
|
|
674
|
+
constructor(networkOrUrl, apiKey, headers) {
|
|
675
|
+
this.apiKey = apiKey;
|
|
676
|
+
this.headers = headers;
|
|
677
|
+
this.network = networkOrUrl;
|
|
678
|
+
}
|
|
679
|
+
roOptions(options) {
|
|
680
|
+
return {
|
|
681
|
+
network: this.network,
|
|
682
|
+
apiKey: this.apiKey,
|
|
683
|
+
headers: this.headers,
|
|
684
|
+
...options
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
ro(tx, options) {
|
|
688
|
+
return ro(tx, this.roOptions(options || {}));
|
|
689
|
+
}
|
|
690
|
+
roOk(tx, options) {
|
|
691
|
+
return roOk(tx, this.roOptions(options || {}));
|
|
692
|
+
}
|
|
693
|
+
roErr(tx, options) {
|
|
694
|
+
return roErr(tx, this.roOptions(options || {}));
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
//#endregion
|
|
699
|
+
//#region src/post-conditions.ts
|
|
700
|
+
function createAssetInfo(contract, asset) {
|
|
701
|
+
const [addr, name] = contract.identifier.split(".");
|
|
702
|
+
if (!("identifier" in contract)) throw new Error("Invalid contract");
|
|
703
|
+
for (const nft of contract.non_fungible_tokens) if (nft.name === asset) return `${addr}.${name}::${nft.name}`;
|
|
704
|
+
for (const ft of contract.fungible_tokens) if (ft.name === asset) return `${addr}.${name}::${ft.name}`;
|
|
705
|
+
throw new Error(`Invalid asset: "${asset}" is not an asset in contract.`);
|
|
706
|
+
}
|
|
707
|
+
function makeNonFungiblePostCondition(contract, sender, condition, value) {
|
|
708
|
+
const [nftType] = contract.non_fungible_tokens;
|
|
709
|
+
const asset = createAssetInfo(contract, nftType.name);
|
|
710
|
+
const abiType = nftType.type;
|
|
711
|
+
return {
|
|
712
|
+
type: "nft-postcondition",
|
|
713
|
+
address: sender,
|
|
714
|
+
condition,
|
|
715
|
+
asset,
|
|
716
|
+
assetId: parseToCV(value, abiType)
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function makeFungiblePostCondition(contract, sender, condition, amount) {
|
|
720
|
+
const [_addr, _name] = sender.split(".");
|
|
721
|
+
const [ftType] = contract.fungible_tokens;
|
|
722
|
+
return {
|
|
723
|
+
type: "ft-postcondition",
|
|
724
|
+
address: sender,
|
|
725
|
+
condition,
|
|
726
|
+
asset: createAssetInfo(contract, ftType.name),
|
|
727
|
+
amount
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
//#endregion
|
|
732
|
+
//#region src/raw-clarity.ts
|
|
733
|
+
/** biome-ignore-all lint/style/useTrimStartEnd: suppressed */
|
|
734
|
+
function unwrap(input, prefix = "") {
|
|
735
|
+
return input.slice(prefix.length + 2, -1);
|
|
736
|
+
}
|
|
737
|
+
function rawClarityToValue(input, type) {
|
|
738
|
+
if (isClarityAbiTuple(type)) {
|
|
739
|
+
const decoded = expectTuple(input);
|
|
740
|
+
const tuple = {};
|
|
741
|
+
const tupleReduced = Object.entries(decoded).reduce((acc, [key, val]) => {
|
|
742
|
+
const keyFixed = key.trim();
|
|
743
|
+
return {
|
|
744
|
+
...acc,
|
|
745
|
+
[keyFixed]: val.trim()
|
|
746
|
+
};
|
|
747
|
+
}, {});
|
|
748
|
+
type.tuple.forEach(({ name, type: _type }) => {
|
|
749
|
+
const camelName = toCamelCase(name);
|
|
750
|
+
tuple[camelName] = rawClarityToValue(tupleReduced[name], _type);
|
|
751
|
+
});
|
|
752
|
+
return tuple;
|
|
753
|
+
}
|
|
754
|
+
if (isClarityAbiList(type)) return expectList(input).map((e) => rawClarityToValue(e, type.list.type));
|
|
755
|
+
if (isClarityAbiOptional(type)) {
|
|
756
|
+
if (input === "none") return null;
|
|
757
|
+
return rawClarityToValue(unwrap(input, "some"), type.optional);
|
|
758
|
+
}
|
|
759
|
+
if (isClarityAbiStringAscii(type)) return input.slice(1, -1);
|
|
760
|
+
if (isClarityAbiStringUtf8(type)) return input.slice(2, -1);
|
|
761
|
+
if (type === "bool") return input === "true";
|
|
762
|
+
if (type === "uint128") return BigInt(input.slice(1));
|
|
763
|
+
if (type === "int128") return BigInt(input);
|
|
764
|
+
if (type === "trait_reference") return input.replace(/^'/, "");
|
|
765
|
+
if (type === "principal") return input.replace(/^'/, "");
|
|
766
|
+
if (type === "none") return null;
|
|
767
|
+
if (isClarityAbiBuffer(type)) return hexToBytes(input.slice(2));
|
|
768
|
+
if (isClarityAbiResponse(type)) {
|
|
769
|
+
if (input.startsWith("(ok")) return ok(rawClarityToValue(unwrap(input, "ok"), type.response.ok));
|
|
770
|
+
return err(rawClarityToValue(unwrap(input, "err"), type.response.error));
|
|
771
|
+
}
|
|
772
|
+
throw new Error(`Unable to parse cv string to value: ${input} ${JSON.stringify(type, null, 2)}`);
|
|
773
|
+
}
|
|
774
|
+
const byteToHexCache = new Array(255);
|
|
775
|
+
for (let n = 0; n <= 255; ++n) byteToHexCache[n] = n.toString(16).padStart(2, "0");
|
|
776
|
+
function expectList(input) {
|
|
777
|
+
if (input.charAt(0) !== "[" || input.at(-1) !== "]") throw new Error(`Expected (list ..), got ${input.toString()}`);
|
|
778
|
+
const stack = [];
|
|
779
|
+
const elements = [];
|
|
780
|
+
let start = 1;
|
|
781
|
+
for (let i = 0; i < input.length; i++) {
|
|
782
|
+
if (input.charAt(i) === "," && stack.length === 1) {
|
|
783
|
+
elements.push(input.substring(start, i));
|
|
784
|
+
start = i + 2;
|
|
785
|
+
}
|
|
786
|
+
if ([
|
|
787
|
+
"(",
|
|
788
|
+
"[",
|
|
789
|
+
"{"
|
|
790
|
+
].includes(input.charAt(i))) stack.push(input.charAt(i));
|
|
791
|
+
if (input.charAt(i) === ")" && stack.at(-1) === "(") stack.pop();
|
|
792
|
+
if (input.charAt(i) === "}" && stack.at(-1) === "{") stack.pop();
|
|
793
|
+
if (input.charAt(i) === "]" && stack.at(-1) === "[") stack.pop();
|
|
794
|
+
}
|
|
795
|
+
const remainder = input.substring(start, input.length - 1);
|
|
796
|
+
if (remainder.length > 0) elements.push(remainder);
|
|
797
|
+
return elements;
|
|
798
|
+
}
|
|
799
|
+
function expectTuple(input) {
|
|
800
|
+
if (input.charAt(0) !== "{" || input.at(-1) !== "}") throw new Error(`Expected '(tuple ..)', got ${input.toString()}`);
|
|
801
|
+
let start = 1;
|
|
802
|
+
const stack = [];
|
|
803
|
+
const elements = [];
|
|
804
|
+
for (let i = 0; i < input.length; i++) {
|
|
805
|
+
if (input.charAt(i) === "," && stack.length === 1) {
|
|
806
|
+
elements.push(input.substring(start, i));
|
|
807
|
+
start = i + 2;
|
|
808
|
+
}
|
|
809
|
+
if ([
|
|
810
|
+
"(",
|
|
811
|
+
"[",
|
|
812
|
+
"{"
|
|
813
|
+
].includes(input.charAt(i))) stack.push(input.charAt(i));
|
|
814
|
+
if (input.charAt(i) === ")" && stack.at(-1) === "(") stack.pop();
|
|
815
|
+
if (input.charAt(i) === "}" && stack.at(-1) === "{") stack.pop();
|
|
816
|
+
if (input.charAt(i) === "]" && stack.at(-1) === "[") stack.pop();
|
|
817
|
+
}
|
|
818
|
+
const remainder = input.substring(start, input.length - 1);
|
|
819
|
+
if (remainder.length > 0) elements.push(remainder);
|
|
820
|
+
const tuple = {};
|
|
821
|
+
for (const element of elements) for (let i = 0; i < element.length; i++) if (element.charAt(i) === ":") {
|
|
822
|
+
const key = element.substring(0, i);
|
|
823
|
+
tuple[key] = element.substring(i + 2, element.length);
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
return tuple;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
//#endregion
|
|
830
|
+
export { ClarigenClient, CoreNodeEventType, DEPLOYMENT_NETWORKS, MAINNET_BURN_ADDRESS, TESTNET_BURN_ADDRESS, bootContractIdentifier, broadcast, bytesToAscii, bytesToHex, callReadOnlyFunction, contractFactory, contractsFactory, createAssetInfo, cvToHex, cvToJSON, cvToString, cvToValue, deploymentFactory, err, expectErr, expectOk, extractErrors, fetchMapGet, filterEvents, findJsTupleKey, formValueToCV, formValueToParseable, functionsFactory, getApiUrl, getContractIdentifier, getContractName, getContractNameFromPath, getContractPrincipalCV, getTypeString, hexToBytes, hexToCV, hexToCvValue, isClarityAbiBuffer, isClarityAbiList, isClarityAbiOptional, isClarityAbiPrimitive, isClarityAbiResponse, isClarityAbiStringAscii, isClarityAbiStringUtf8, isClarityAbiTraitReference, isClarityAbiTuple, isNumber, isOptionalFormValue, isResponse, isResponseFormValue, makeContracts, makeFungiblePostCondition, makeNonFungiblePostCondition, mapFactory, ok, parseQueryValue, parseReadOnlyResponse, parseToCV, principalToString, projectErrors, projectFactory, queryToFunctionArgs, rawClarityToValue, ro, roErr, roOk, toCamelCase, toKebabCase, transformArgsArray, transformArgsToCV, transformObjectArgs };
|
|
831
|
+
//# sourceMappingURL=index.mjs.map
|