@secondlayer/stacks 4.3.2 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -11
- package/dist/shared/{stacks-bfan7ex7.js → stacks-4d7c3x27.js} +5 -5
- package/dist/shared/{stacks-bfan7ex7.js.map → stacks-4d7c3x27.js.map} +3 -3
- package/dist/shared/{stacks-709tra19.js → stacks-4hs8r4q2.js} +16 -2
- package/dist/shared/stacks-4hs8r4q2.js.map +10 -0
- package/dist/shared/{stacks-w23294am.js → stacks-51ybf135.js} +3 -3
- package/dist/shared/{stacks-0jk7vd8r.cjs → stacks-69nq48jp.js} +120 -17
- package/dist/shared/stacks-69nq48jp.js.map +15 -0
- package/dist/shared/{stacks-8pfdscq6.js → stacks-6gavarmy.js} +37 -9
- package/dist/shared/stacks-6gavarmy.js.map +12 -0
- package/dist/shared/{stacks-gxq2pbky.js → stacks-71k0vmct.js} +65 -8
- package/dist/shared/stacks-71k0vmct.js.map +13 -0
- package/dist/shared/{stacks-7wkf2rph.js → stacks-7bqkf3b0.js} +86 -71
- package/dist/shared/{stacks-7wkf2rph.js.map → stacks-7bqkf3b0.js.map} +9 -10
- package/dist/shared/{stacks-zcpvzbr0.js → stacks-8brgfvqx.js} +3 -3
- package/dist/shared/{stacks-4vzmhw3q.cjs → stacks-8vzxax5e.cjs} +13 -3
- package/dist/shared/stacks-8vzxax5e.cjs.map +10 -0
- package/dist/shared/{stacks-hnqt5rz4.js → stacks-9c1yam8b.js} +3 -3
- package/dist/shared/{stacks-bnbdqznq.cjs → stacks-bdgh9n83.cjs} +11 -10
- package/dist/shared/{stacks-bnbdqznq.cjs.map → stacks-bdgh9n83.cjs.map} +3 -3
- package/dist/shared/{stacks-fb75yew8.js → stacks-db3kwavg.cjs} +346 -138
- package/dist/shared/stacks-db3kwavg.cjs.map +23 -0
- package/dist/shared/{stacks-jpt52csy.js → stacks-e3nwm1dz.js} +14 -17
- package/dist/shared/stacks-e3nwm1dz.js.map +10 -0
- package/dist/shared/{stacks-ta1gar0b.cjs → stacks-ee53k9j2.cjs} +62 -6
- package/dist/shared/stacks-ee53k9j2.cjs.map +13 -0
- package/dist/shared/{stacks-27fmgajb.js → stacks-ga026yxz.js} +9 -9
- package/dist/shared/{stacks-27fmgajb.js.map → stacks-ga026yxz.js.map} +3 -3
- package/dist/shared/{stacks-nyaw1z2a.cjs → stacks-ggdz96r1.cjs} +4 -4
- package/dist/shared/{stacks-nyaw1z2a.cjs.map → stacks-ggdz96r1.cjs.map} +3 -3
- package/dist/shared/{stacks-08y0y0t7.js → stacks-gjz26k6b.js} +2 -2
- package/dist/shared/{stacks-x5386y2y.cjs → stacks-gza2n1zs.cjs} +5 -5
- package/dist/shared/{stacks-x5386y2y.cjs.map → stacks-gza2n1zs.cjs.map} +3 -3
- package/dist/shared/{stacks-ztzygy90.js → stacks-mftyrc60.js} +2 -2
- package/dist/shared/stacks-n4d8j8q3.js +801 -0
- package/dist/shared/stacks-n4d8j8q3.js.map +23 -0
- package/dist/shared/{stacks-ycbq8pf7.cjs → stacks-p337hp6m.cjs} +74 -59
- package/dist/shared/{stacks-ycbq8pf7.cjs.map → stacks-p337hp6m.cjs.map} +9 -10
- package/dist/shared/{stacks-ttdk2g2f.js → stacks-s5vej5z6.cjs} +92 -41
- package/dist/shared/stacks-s5vej5z6.cjs.map +15 -0
- package/dist/shared/stacks-sdqkapct.cjs +67 -0
- package/dist/shared/stacks-sdqkapct.cjs.map +12 -0
- package/dist/shared/{stacks-1arrcd11.js → stacks-v2rfr46a.js} +2 -2
- package/dist/shared/{stacks-9mqveyjv.cjs → stacks-w9t61fra.cjs} +7 -10
- package/dist/shared/stacks-w9t61fra.cjs.map +10 -0
- package/dist/shared/{stacks-tjjnkt3r.js → stacks-wxfd6r4b.js} +2 -2
- package/dist/shared/{stacks-4z72akdf.js → stacks-x0qqwrev.js} +3 -3
- package/dist/shared/{stacks-gck1sq7h.cjs → stacks-xjkn3en1.cjs} +16 -2
- package/dist/shared/stacks-xjkn3en1.cjs.map +10 -0
- package/dist/shared/stacks-xnrywjf1.cjs +131 -0
- package/dist/shared/stacks-xnrywjf1.cjs.map +11 -0
- package/dist/shared/stacks-yajyej2y.js +139 -0
- package/dist/shared/stacks-yajyej2y.js.map +11 -0
- package/dist/shared/{stacks-913a2rx7.js → stacks-yvb7rvwk.js} +13 -3
- package/dist/shared/stacks-yvb7rvwk.js.map +10 -0
- package/dist/shared/{stacks-0cdm20eh.js → stacks-z90xdr1x.js} +7 -11
- package/dist/shared/{stacks-0cdm20eh.js.map → stacks-z90xdr1x.js.map} +3 -3
- package/dist/src/accounts/index.js +2 -3
- package/dist/src/accounts/index.js.map +2 -2
- package/dist/src/actions/index.cjs +2 -1
- package/dist/src/actions/index.cjs.map +1 -1
- package/dist/src/actions/index.d.cts +108 -20
- package/dist/src/actions/index.d.ts +108 -20
- package/dist/src/actions/index.js +17 -15
- package/dist/src/actions/index.js.map +1 -1
- package/dist/src/bitcoin/index.d.cts +27 -0
- package/dist/src/bitcoin/index.d.ts +27 -0
- package/dist/src/bitcoin/index.js +10 -11
- package/dist/src/bitcoin/index.js.map +2 -2
- package/dist/src/bns/index.d.cts +27 -0
- package/dist/src/bns/index.d.ts +27 -0
- package/dist/src/bns/index.js +13 -13
- package/dist/src/bns/index.js.map +1 -1
- package/dist/src/clarity/index.js +7 -6
- package/dist/src/clarity/index.js.map +1 -1
- package/dist/src/connect/index.cjs +44 -30
- package/dist/src/connect/index.cjs.map +7 -7
- package/dist/src/connect/index.d.cts +16 -1
- package/dist/src/connect/index.d.ts +16 -1
- package/dist/src/connect/index.js +44 -30
- package/dist/src/connect/index.js.map +7 -7
- package/dist/src/connect/walletconnect/index.cjs +49 -413
- package/dist/src/connect/walletconnect/index.cjs.map +4 -4
- package/dist/src/connect/walletconnect/index.js +47 -411
- package/dist/src/connect/walletconnect/index.js.map +4 -4
- package/dist/src/filters/index.js +2 -2
- package/dist/src/index.cjs +49 -124
- package/dist/src/index.cjs.map +6 -8
- package/dist/src/index.d.cts +163 -54
- package/dist/src/index.d.ts +163 -54
- package/dist/src/index.js +79 -147
- package/dist/src/index.js.map +6 -8
- package/dist/src/postconditions/index.js +6 -5
- package/dist/src/postconditions/index.js.map +1 -1
- package/dist/src/pox/index.cjs +7 -83
- package/dist/src/pox/index.cjs.map +3 -3
- package/dist/src/pox/index.d.cts +32 -1
- package/dist/src/pox/index.d.ts +32 -1
- package/dist/src/pox/index.js +22 -102
- package/dist/src/pox/index.js.map +3 -3
- package/dist/src/pox5/index.cjs +4 -112
- package/dist/src/pox5/index.cjs.map +3 -4
- package/dist/src/pox5/index.d.cts +27 -0
- package/dist/src/pox5/index.d.ts +27 -0
- package/dist/src/pox5/index.js +20 -131
- package/dist/src/pox5/index.js.map +3 -4
- package/dist/src/sbtc/index.cjs +2 -27
- package/dist/src/sbtc/index.cjs.map +3 -3
- package/dist/src/sbtc/index.d.cts +30 -2
- package/dist/src/sbtc/index.d.ts +30 -2
- package/dist/src/sbtc/index.js +15 -45
- package/dist/src/sbtc/index.js.map +3 -3
- package/dist/src/stackingdao/index.d.cts +27 -0
- package/dist/src/stackingdao/index.d.ts +27 -0
- package/dist/src/stackingdao/index.js +11 -11
- package/dist/src/stackingdao/index.js.map +1 -1
- package/dist/src/subscriptions/index.d.cts +27 -0
- package/dist/src/subscriptions/index.d.ts +27 -0
- package/dist/src/subscriptions/index.js +2 -2
- package/dist/src/tools/btc/index.cjs.map +2 -2
- package/dist/src/tools/btc/index.js.map +2 -2
- package/dist/src/tools/index.cjs +629 -392
- package/dist/src/tools/index.cjs.map +30 -28
- package/dist/src/tools/index.d.cts +44 -0
- package/dist/src/tools/index.d.ts +44 -0
- package/dist/src/tools/index.js +628 -391
- package/dist/src/tools/index.js.map +30 -28
- package/dist/src/transactions/index.js +6 -5
- package/dist/src/transactions/index.js.map +1 -1
- package/dist/src/utils/index.d.cts +2 -5
- package/dist/src/utils/index.d.ts +2 -5
- package/dist/src/utils/index.js +2 -2
- package/package.json +18 -7
- package/dist/shared/stacks-0eatsx6d.cjs +0 -25
- package/dist/shared/stacks-0eatsx6d.cjs.map +0 -10
- package/dist/shared/stacks-0jk7vd8r.cjs.map +0 -14
- package/dist/shared/stacks-4vzmhw3q.cjs.map +0 -10
- package/dist/shared/stacks-5nmz5ad9.js +0 -409
- package/dist/shared/stacks-5nmz5ad9.js.map +0 -10
- package/dist/shared/stacks-709tra19.js.map +0 -10
- package/dist/shared/stacks-8pfdscq6.js.map +0 -12
- package/dist/shared/stacks-913a2rx7.js.map +0 -10
- package/dist/shared/stacks-9mqveyjv.cjs.map +0 -10
- package/dist/shared/stacks-e4xn4m7j.js +0 -27
- package/dist/shared/stacks-e4xn4m7j.js.map +0 -10
- package/dist/shared/stacks-fb75yew8.js.map +0 -21
- package/dist/shared/stacks-gck1sq7h.cjs.map +0 -10
- package/dist/shared/stacks-gxq2pbky.js.map +0 -13
- package/dist/shared/stacks-jpt52csy.js.map +0 -10
- package/dist/shared/stacks-mnnhpex3.cjs +0 -407
- package/dist/shared/stacks-mnnhpex3.cjs.map +0 -10
- package/dist/shared/stacks-ta1gar0b.cjs.map +0 -13
- package/dist/shared/stacks-tdsp5gsb.cjs +0 -527
- package/dist/shared/stacks-tdsp5gsb.cjs.map +0 -21
- package/dist/shared/stacks-ttdk2g2f.js.map +0 -14
- package/dist/shared/stacks-wdp5yr8n.cjs +0 -39
- package/dist/shared/stacks-wdp5yr8n.cjs.map +0 -12
- /package/dist/shared/{stacks-w23294am.js.map → stacks-51ybf135.js.map} +0 -0
- /package/dist/shared/{stacks-zcpvzbr0.js.map → stacks-8brgfvqx.js.map} +0 -0
- /package/dist/shared/{stacks-hnqt5rz4.js.map → stacks-9c1yam8b.js.map} +0 -0
- /package/dist/shared/{stacks-08y0y0t7.js.map → stacks-gjz26k6b.js.map} +0 -0
- /package/dist/shared/{stacks-ztzygy90.js.map → stacks-mftyrc60.js.map} +0 -0
- /package/dist/shared/{stacks-1arrcd11.js.map → stacks-v2rfr46a.js.map} +0 -0
- /package/dist/shared/{stacks-tjjnkt3r.js.map → stacks-wxfd6r4b.js.map} +0 -0
- /package/dist/shared/{stacks-4z72akdf.js.map → stacks-x0qqwrev.js.map} +0 -0
package/dist/src/tools/index.js
CHANGED
|
@@ -3,8 +3,13 @@ import { tool } from "ai";
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
5
|
// src/errors/base.ts
|
|
6
|
+
function codeFromName(name) {
|
|
7
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toUpperCase();
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
class BaseError extends Error {
|
|
7
11
|
name = "StacksError";
|
|
12
|
+
#code;
|
|
8
13
|
shortMessage;
|
|
9
14
|
details;
|
|
10
15
|
constructor(shortMessage, options) {
|
|
@@ -14,12 +19,21 @@ class BaseError extends Error {
|
|
|
14
19
|
${options.details}` : ""
|
|
15
20
|
].join("");
|
|
16
21
|
super(message, { cause: options?.cause });
|
|
22
|
+
if (options?.code !== undefined)
|
|
23
|
+
this.#code = options.code;
|
|
17
24
|
this.shortMessage = shortMessage;
|
|
18
25
|
this.details = options?.details;
|
|
19
26
|
}
|
|
27
|
+
get code() {
|
|
28
|
+
return this.#code ?? codeFromName(this.name);
|
|
29
|
+
}
|
|
30
|
+
set code(value) {
|
|
31
|
+
this.#code = value;
|
|
32
|
+
}
|
|
20
33
|
toJSON() {
|
|
21
34
|
return {
|
|
22
35
|
name: this.name,
|
|
36
|
+
code: this.code,
|
|
23
37
|
message: this.message,
|
|
24
38
|
shortMessage: this.shortMessage,
|
|
25
39
|
details: this.details,
|
|
@@ -358,7 +372,7 @@ function serializeCVBytes(value) {
|
|
|
358
372
|
return withTypeId(value.type, concatBytes(...parts));
|
|
359
373
|
}
|
|
360
374
|
case "tuple": {
|
|
361
|
-
const keys = Object.keys(value.value).sort((a, b) => a
|
|
375
|
+
const keys = Object.keys(value.value).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
362
376
|
const parts = [writeUInt32BE(keys.length)];
|
|
363
377
|
for (const key of keys) {
|
|
364
378
|
parts.push(serializeLPString(key));
|
|
@@ -672,14 +686,12 @@ async function estimateFee(client, params) {
|
|
|
672
686
|
// src/actions/public/getAccountHistory.ts
|
|
673
687
|
async function getAccountHistory(client, params) {
|
|
674
688
|
const limit = Math.min(params.limit ?? 20, 50);
|
|
675
|
-
return client.request(`/extended/v2/addresses/${params.address}/transactions?limit=${limit}`, { method: "GET" });
|
|
689
|
+
return client.request(`/extended/v2/addresses/${encodeURIComponent(params.address)}/transactions?limit=${limit}`, { method: "GET" });
|
|
676
690
|
}
|
|
677
691
|
|
|
678
692
|
// src/actions/public/getAccountInfo.ts
|
|
679
693
|
async function getAccountInfo(client, params) {
|
|
680
|
-
const data = await client.request(`/v2/accounts/${params.address}?proof=1`, {
|
|
681
|
-
method: "GET"
|
|
682
|
-
});
|
|
694
|
+
const data = await client.request(`/v2/accounts/${encodeURIComponent(params.address)}?proof=1`, { method: "GET" });
|
|
683
695
|
const balance = data?.balance;
|
|
684
696
|
const nonce = data?.nonce;
|
|
685
697
|
if (typeof balance !== "string" && typeof balance !== "number" || typeof nonce !== "string" && typeof nonce !== "number") {
|
|
@@ -695,7 +707,7 @@ async function getAccountInfo(client, params) {
|
|
|
695
707
|
|
|
696
708
|
// src/actions/public/getBalance.ts
|
|
697
709
|
async function getBalance(client, params) {
|
|
698
|
-
const data = await client.request(`/v2/accounts/${params.address}`, {
|
|
710
|
+
const data = await client.request(`/v2/accounts/${encodeURIComponent(params.address)}`, {
|
|
699
711
|
method: "GET"
|
|
700
712
|
});
|
|
701
713
|
const balance = data?.balance;
|
|
@@ -708,16 +720,16 @@ async function getBalance(client, params) {
|
|
|
708
720
|
// src/actions/public/getBlock.ts
|
|
709
721
|
async function getBlock(client, params) {
|
|
710
722
|
if (params?.hash) {
|
|
711
|
-
return client.request(`/extended/v2/blocks/${params.hash}`, {
|
|
712
|
-
method: "GET"
|
|
713
|
-
});
|
|
723
|
+
return client.request(`/extended/v2/blocks/${encodeURIComponent(params.hash)}`, { method: "GET" });
|
|
714
724
|
}
|
|
715
725
|
if (params?.height !== undefined) {
|
|
716
|
-
return client.request(`/extended/v2/blocks/${params.height}`, {
|
|
717
|
-
method: "GET"
|
|
718
|
-
});
|
|
726
|
+
return client.request(`/extended/v2/blocks/${encodeURIComponent(String(params.height))}`, { method: "GET" });
|
|
719
727
|
}
|
|
720
|
-
|
|
728
|
+
const data = await client.request("/extended/v2/blocks?limit=1", {
|
|
729
|
+
method: "GET"
|
|
730
|
+
});
|
|
731
|
+
const results = data?.results;
|
|
732
|
+
return Array.isArray(results) ? results[0] ?? null : data;
|
|
721
733
|
}
|
|
722
734
|
|
|
723
735
|
// src/actions/public/getBlockHeight.ts
|
|
@@ -740,6 +752,51 @@ async function getNftHoldings(client, params) {
|
|
|
740
752
|
return client.request(`/extended/v1/tokens/nft/holdings?principal=${encodeURIComponent(params.address)}&limit=${limit}`, { method: "GET" });
|
|
741
753
|
}
|
|
742
754
|
|
|
755
|
+
// src/errors/transaction.ts
|
|
756
|
+
class BroadcastError extends BaseError {
|
|
757
|
+
name = "BroadcastError";
|
|
758
|
+
txid;
|
|
759
|
+
reason;
|
|
760
|
+
reasonData;
|
|
761
|
+
constructor(message, options) {
|
|
762
|
+
super(message, options);
|
|
763
|
+
this.txid = options?.txid;
|
|
764
|
+
this.reason = options?.reason;
|
|
765
|
+
this.reasonData = options?.reasonData;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
class TransactionAbortedError extends BaseError {
|
|
770
|
+
name = "TransactionAbortedError";
|
|
771
|
+
receipt;
|
|
772
|
+
constructor(message, options) {
|
|
773
|
+
super(message, options);
|
|
774
|
+
this.receipt = options.receipt;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
class TransactionDroppedError extends BaseError {
|
|
779
|
+
name = "TransactionDroppedError";
|
|
780
|
+
txid;
|
|
781
|
+
constructor(message, options) {
|
|
782
|
+
super(message, options);
|
|
783
|
+
this.txid = options.txid;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
class WaitForTransactionTimeoutError extends BaseError {
|
|
788
|
+
name = "WaitForTransactionTimeoutError";
|
|
789
|
+
txid;
|
|
790
|
+
constructor(message, options) {
|
|
791
|
+
super(message, options);
|
|
792
|
+
this.txid = options.txid;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
class SerializationError extends BaseError {
|
|
797
|
+
name = "SerializationError";
|
|
798
|
+
}
|
|
799
|
+
|
|
743
800
|
// src/utils/bytes-reader.ts
|
|
744
801
|
class BytesReader {
|
|
745
802
|
data;
|
|
@@ -747,23 +804,32 @@ class BytesReader {
|
|
|
747
804
|
constructor(data) {
|
|
748
805
|
this.data = data;
|
|
749
806
|
}
|
|
807
|
+
remaining() {
|
|
808
|
+
return this.data.length - this.offset;
|
|
809
|
+
}
|
|
810
|
+
ensure(length) {
|
|
811
|
+
if (this.offset + length > this.data.length) {
|
|
812
|
+
throw new SerializationError(`Buffer underflow: need ${length} bytes at offset ${this.offset}, have ${this.data.length}`);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
750
815
|
readUInt8() {
|
|
816
|
+
this.ensure(1);
|
|
751
817
|
return this.data[this.offset++];
|
|
752
818
|
}
|
|
753
819
|
readUInt16BE() {
|
|
820
|
+
this.ensure(2);
|
|
754
821
|
const val = (this.data[this.offset] << 8 | this.data[this.offset + 1]) >>> 0;
|
|
755
822
|
this.offset += 2;
|
|
756
823
|
return val;
|
|
757
824
|
}
|
|
758
825
|
readUInt32BE() {
|
|
826
|
+
this.ensure(4);
|
|
759
827
|
const val = (this.data[this.offset] << 24 | this.data[this.offset + 1] << 16 | this.data[this.offset + 2] << 8 | this.data[this.offset + 3]) >>> 0;
|
|
760
828
|
this.offset += 4;
|
|
761
829
|
return val;
|
|
762
830
|
}
|
|
763
831
|
readBytes(length) {
|
|
764
|
-
|
|
765
|
-
throw new Error(`Buffer underflow: need ${length} bytes at offset ${this.offset}, have ${this.data.length}`);
|
|
766
|
-
}
|
|
832
|
+
this.ensure(length);
|
|
767
833
|
const slice = this.data.slice(this.offset, this.offset + length);
|
|
768
834
|
this.offset += length;
|
|
769
835
|
return slice;
|
|
@@ -805,11 +871,33 @@ function publicKeyToAddress(publicKey, network = "mainnet") {
|
|
|
805
871
|
const version = network === "mainnet" ? AddressVersion.MainnetSingleSig : AddressVersion.TestnetSingleSig;
|
|
806
872
|
return c32address(version, bytesToHex(hash160(bytes)));
|
|
807
873
|
}
|
|
874
|
+
var CONTRACT_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/;
|
|
875
|
+
function validateStacksAddress(address) {
|
|
876
|
+
try {
|
|
877
|
+
c32addressDecode(address);
|
|
878
|
+
return true;
|
|
879
|
+
} catch {
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
function parsePrincipal(value) {
|
|
884
|
+
const parts = value.split(".");
|
|
885
|
+
if (parts.length > 2)
|
|
886
|
+
return null;
|
|
887
|
+
const [address, contractName] = parts;
|
|
888
|
+
if (!validateStacksAddress(address))
|
|
889
|
+
return null;
|
|
890
|
+
if (contractName === undefined)
|
|
891
|
+
return { address };
|
|
892
|
+
if (!CONTRACT_NAME_REGEX.test(contractName))
|
|
893
|
+
return null;
|
|
894
|
+
return { address, contractName };
|
|
895
|
+
}
|
|
808
896
|
function parseContractId(contractId) {
|
|
809
|
-
const
|
|
810
|
-
if (!
|
|
897
|
+
const parsed = parsePrincipal(contractId);
|
|
898
|
+
if (!parsed?.contractName)
|
|
811
899
|
throw new Error(`Invalid contract identifier: ${contractId}`);
|
|
812
|
-
return [address,
|
|
900
|
+
return [parsed.address, parsed.contractName];
|
|
813
901
|
}
|
|
814
902
|
function isClarityName(name) {
|
|
815
903
|
const regex = /^[a-zA-Z]([a-zA-Z0-9]|[-_!?+<>=/*])*$|^[-+=/*]$|^[<>]=?$/;
|
|
@@ -898,10 +986,10 @@ var Cl = {
|
|
|
898
986
|
uint: uintCV,
|
|
899
987
|
bool: boolCV,
|
|
900
988
|
principal(address) {
|
|
901
|
-
const
|
|
902
|
-
if (!
|
|
903
|
-
throw new Error(
|
|
904
|
-
return
|
|
989
|
+
const parsed = parsePrincipal(address);
|
|
990
|
+
if (!parsed)
|
|
991
|
+
throw new Error(`Invalid principal: ${address}`);
|
|
992
|
+
return parsed.contractName ? contractPrincipalCV(parsed.address, parsed.contractName) : standardPrincipalCV(parsed.address);
|
|
905
993
|
},
|
|
906
994
|
address(address) {
|
|
907
995
|
return Cl.principal(address);
|
|
@@ -939,7 +1027,18 @@ function readLPString(reader, prefixBytes = 1) {
|
|
|
939
1027
|
}
|
|
940
1028
|
return bytesToUtf8(reader.readBytes(length));
|
|
941
1029
|
}
|
|
942
|
-
|
|
1030
|
+
var MAX_CV_DEPTH = 64;
|
|
1031
|
+
var MIN_LIST_ITEM_BYTES = 1;
|
|
1032
|
+
var MIN_TUPLE_ENTRY_BYTES = 2;
|
|
1033
|
+
function checkCount(reader, count, minBytes) {
|
|
1034
|
+
if (count * minBytes > reader.remaining()) {
|
|
1035
|
+
throw new SerializationError(`Clarity value declares ${count} elements but only ${reader.remaining()} bytes remain`);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
function readCV(reader, depth = 0) {
|
|
1039
|
+
if (depth > MAX_CV_DEPTH) {
|
|
1040
|
+
throw new SerializationError(`Clarity value nests deeper than ${MAX_CV_DEPTH} levels`);
|
|
1041
|
+
}
|
|
943
1042
|
const typeByte = reader.readUInt8();
|
|
944
1043
|
const type = clarityTypeFromByte(typeByte);
|
|
945
1044
|
switch (type) {
|
|
@@ -958,11 +1057,11 @@ function readCV(reader) {
|
|
|
958
1057
|
case "none":
|
|
959
1058
|
return noneCV();
|
|
960
1059
|
case "some":
|
|
961
|
-
return someCV(readCV(reader));
|
|
1060
|
+
return someCV(readCV(reader, depth + 1));
|
|
962
1061
|
case "ok":
|
|
963
|
-
return responseOkCV(readCV(reader));
|
|
1062
|
+
return responseOkCV(readCV(reader, depth + 1));
|
|
964
1063
|
case "err":
|
|
965
|
-
return responseErrorCV(readCV(reader));
|
|
1064
|
+
return responseErrorCV(readCV(reader, depth + 1));
|
|
966
1065
|
case "address":
|
|
967
1066
|
return standardPrincipalCV(readAddress(reader));
|
|
968
1067
|
case "contract": {
|
|
@@ -972,18 +1071,20 @@ function readCV(reader) {
|
|
|
972
1071
|
}
|
|
973
1072
|
case "list": {
|
|
974
1073
|
const len = reader.readUInt32BE();
|
|
1074
|
+
checkCount(reader, len, MIN_LIST_ITEM_BYTES);
|
|
975
1075
|
const items = [];
|
|
976
1076
|
for (let i = 0;i < len; i++) {
|
|
977
|
-
items.push(readCV(reader));
|
|
1077
|
+
items.push(readCV(reader, depth + 1));
|
|
978
1078
|
}
|
|
979
1079
|
return listCV(items);
|
|
980
1080
|
}
|
|
981
1081
|
case "tuple": {
|
|
982
1082
|
const len = reader.readUInt32BE();
|
|
1083
|
+
checkCount(reader, len, MIN_TUPLE_ENTRY_BYTES);
|
|
983
1084
|
const data = {};
|
|
984
1085
|
for (let i = 0;i < len; i++) {
|
|
985
1086
|
const key = readLPString(reader);
|
|
986
|
-
data[key] = readCV(reader);
|
|
1087
|
+
data[key] = readCV(reader, depth + 1);
|
|
987
1088
|
}
|
|
988
1089
|
return tupleCV(data);
|
|
989
1090
|
}
|
|
@@ -996,7 +1097,7 @@ function readCV(reader) {
|
|
|
996
1097
|
return stringUtf8CV(bytesToUtf8(reader.readBytes(len)));
|
|
997
1098
|
}
|
|
998
1099
|
default:
|
|
999
|
-
throw new
|
|
1100
|
+
throw new SerializationError(`Cannot deserialize unknown clarity type: ${type}`);
|
|
1000
1101
|
}
|
|
1001
1102
|
}
|
|
1002
1103
|
function deserializeCVBytes(input) {
|
|
@@ -1008,10 +1109,207 @@ function deserializeCVBytes(input) {
|
|
|
1008
1109
|
class HttpRequestError extends BaseError {
|
|
1009
1110
|
name = "HttpRequestError";
|
|
1010
1111
|
status;
|
|
1112
|
+
url;
|
|
1113
|
+
method;
|
|
1011
1114
|
constructor(status, options) {
|
|
1012
|
-
|
|
1115
|
+
const where = options?.url !== undefined ? ` (${options.method ?? "GET"} ${options.url})` : "";
|
|
1116
|
+
super(`HTTP request failed with status ${status}${where}`, options);
|
|
1013
1117
|
this.status = status;
|
|
1118
|
+
this.url = options?.url;
|
|
1119
|
+
this.method = options?.method;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// src/errors/transport.ts
|
|
1124
|
+
class TimeoutError extends BaseError {
|
|
1125
|
+
name = "TimeoutError";
|
|
1126
|
+
method;
|
|
1127
|
+
url;
|
|
1128
|
+
timeout;
|
|
1129
|
+
attempt;
|
|
1130
|
+
constructor(params) {
|
|
1131
|
+
super(`${params.method} ${params.url} did not complete within ${params.timeout}ms (attempt ${params.attempt + 1})`);
|
|
1132
|
+
this.method = params.method;
|
|
1133
|
+
this.url = params.url;
|
|
1134
|
+
this.timeout = params.timeout;
|
|
1135
|
+
this.attempt = params.attempt;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// src/transports/createTransport.ts
|
|
1140
|
+
function createTransport(type, config) {
|
|
1141
|
+
const { request, apiKey: _apiKey, ...exposed } = config;
|
|
1142
|
+
return {
|
|
1143
|
+
type,
|
|
1144
|
+
request,
|
|
1145
|
+
config: exposed
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
var MAX_ERROR_DETAILS_BYTES = 4096;
|
|
1149
|
+
function capDetails(body) {
|
|
1150
|
+
if (body === undefined)
|
|
1151
|
+
return;
|
|
1152
|
+
const bytes = new TextEncoder().encode(body);
|
|
1153
|
+
if (bytes.length <= MAX_ERROR_DETAILS_BYTES)
|
|
1154
|
+
return body;
|
|
1155
|
+
const head = new TextDecoder().decode(bytes.subarray(0, MAX_ERROR_DETAILS_BYTES));
|
|
1156
|
+
return `${head}... [truncated ${bytes.length - MAX_ERROR_DETAILS_BYTES} bytes]`;
|
|
1157
|
+
}
|
|
1158
|
+
function isRetryableStatus(status) {
|
|
1159
|
+
return status === 429 || status >= 500;
|
|
1160
|
+
}
|
|
1161
|
+
var MAX_RETRY_AFTER_MS = 60000;
|
|
1162
|
+
function retryAfterMs(response) {
|
|
1163
|
+
const value = response.headers.get("Retry-After");
|
|
1164
|
+
if (!value)
|
|
1165
|
+
return;
|
|
1166
|
+
const seconds = Number(value);
|
|
1167
|
+
const ms = Number.isFinite(seconds) ? seconds * 1000 : Date.parse(value) - Date.now();
|
|
1168
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > MAX_RETRY_AFTER_MS)
|
|
1169
|
+
return;
|
|
1170
|
+
return ms;
|
|
1171
|
+
}
|
|
1172
|
+
function abortReason(signal) {
|
|
1173
|
+
const reason = signal.reason;
|
|
1174
|
+
if (reason instanceof Error)
|
|
1175
|
+
return reason;
|
|
1176
|
+
return new DOMException(typeof reason === "string" ? reason : "The operation was aborted", "AbortError");
|
|
1177
|
+
}
|
|
1178
|
+
function sleep(ms, signal) {
|
|
1179
|
+
return new Promise((resolve, reject) => {
|
|
1180
|
+
if (signal?.aborted)
|
|
1181
|
+
return reject(abortReason(signal));
|
|
1182
|
+
const onAbort = () => {
|
|
1183
|
+
clearTimeout(id);
|
|
1184
|
+
reject(abortReason(signal));
|
|
1185
|
+
};
|
|
1186
|
+
const id = setTimeout(() => {
|
|
1187
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1188
|
+
resolve();
|
|
1189
|
+
}, ms);
|
|
1190
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
async function fetchWithRetry(url, options, retryCount, retryDelay, timeout, extra = {}) {
|
|
1194
|
+
const { signal } = extra;
|
|
1195
|
+
const read = extra.read ?? (async (response) => response);
|
|
1196
|
+
const method = options.method ?? "GET";
|
|
1197
|
+
let lastError;
|
|
1198
|
+
for (let attempt = 0;attempt <= retryCount; attempt++) {
|
|
1199
|
+
if (signal?.aborted)
|
|
1200
|
+
throw abortReason(signal);
|
|
1201
|
+
const controller = new AbortController;
|
|
1202
|
+
let timedOut = false;
|
|
1203
|
+
const timeoutId = setTimeout(() => {
|
|
1204
|
+
timedOut = true;
|
|
1205
|
+
controller.abort(new TimeoutError({ method, url, timeout, attempt }));
|
|
1206
|
+
}, timeout);
|
|
1207
|
+
const onCallerAbort = () => controller.abort(abortReason(signal));
|
|
1208
|
+
signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
1209
|
+
const aborted = new Promise((_, reject) => {
|
|
1210
|
+
if (controller.signal.aborted)
|
|
1211
|
+
return reject(controller.signal.reason);
|
|
1212
|
+
controller.signal.addEventListener("abort", () => reject(controller.signal.reason), { once: true });
|
|
1213
|
+
});
|
|
1214
|
+
let response;
|
|
1215
|
+
try {
|
|
1216
|
+
try {
|
|
1217
|
+
response = await Promise.race([
|
|
1218
|
+
fetch(url, { ...options, signal: controller.signal }),
|
|
1219
|
+
aborted
|
|
1220
|
+
]);
|
|
1221
|
+
} catch (error) {
|
|
1222
|
+
if (signal?.aborted)
|
|
1223
|
+
throw abortReason(signal);
|
|
1224
|
+
lastError = timedOut ? new TimeoutError({ method, url, timeout, attempt }) : error instanceof Error ? error : new Error(String(error));
|
|
1225
|
+
if (attempt < retryCount) {
|
|
1226
|
+
clearTimeout(timeoutId);
|
|
1227
|
+
await sleep(retryDelay * (attempt + 1), signal);
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
throw lastError;
|
|
1231
|
+
}
|
|
1232
|
+
if (response.ok) {
|
|
1233
|
+
try {
|
|
1234
|
+
return await Promise.race([read(response), aborted]);
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
response.body?.cancel().catch(() => {});
|
|
1237
|
+
if (signal?.aborted)
|
|
1238
|
+
throw abortReason(signal);
|
|
1239
|
+
if (!timedOut)
|
|
1240
|
+
throw error;
|
|
1241
|
+
lastError = new TimeoutError({ method, url, timeout, attempt });
|
|
1242
|
+
if (attempt < retryCount) {
|
|
1243
|
+
clearTimeout(timeoutId);
|
|
1244
|
+
await sleep(retryDelay * (attempt + 1), signal);
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
throw lastError;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
const retryable = isRetryableStatus(response.status);
|
|
1251
|
+
if (!retryable || attempt === retryCount) {
|
|
1252
|
+
const body = await Promise.race([
|
|
1253
|
+
response.text().catch(() => {
|
|
1254
|
+
return;
|
|
1255
|
+
}),
|
|
1256
|
+
aborted.catch(() => {
|
|
1257
|
+
return;
|
|
1258
|
+
})
|
|
1259
|
+
]);
|
|
1260
|
+
throw new HttpRequestError(response.status, {
|
|
1261
|
+
details: capDetails(body),
|
|
1262
|
+
url,
|
|
1263
|
+
method
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
lastError = new HttpRequestError(response.status, { url, method });
|
|
1267
|
+
const delay = retryAfterMs(response) ?? retryDelay * (attempt + 1);
|
|
1268
|
+
response.body?.cancel().catch(() => {});
|
|
1269
|
+
clearTimeout(timeoutId);
|
|
1270
|
+
await sleep(delay, signal);
|
|
1271
|
+
} finally {
|
|
1272
|
+
clearTimeout(timeoutId);
|
|
1273
|
+
signal?.removeEventListener("abort", onCallerAbort);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
throw lastError ?? new Error("Request failed");
|
|
1277
|
+
}
|
|
1278
|
+
async function readBody(response) {
|
|
1279
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
1280
|
+
if (contentType.includes("application/json")) {
|
|
1281
|
+
return response.json();
|
|
1014
1282
|
}
|
|
1283
|
+
return response.text();
|
|
1284
|
+
}
|
|
1285
|
+
function buildRequestFn(baseUrl, config) {
|
|
1286
|
+
const {
|
|
1287
|
+
timeout = 30000,
|
|
1288
|
+
retryCount = 3,
|
|
1289
|
+
retryDelay = 150,
|
|
1290
|
+
fetchOptions = {},
|
|
1291
|
+
apiKey
|
|
1292
|
+
} = config;
|
|
1293
|
+
return async (path, options) => {
|
|
1294
|
+
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
1295
|
+
const headers = {
|
|
1296
|
+
"Content-Type": "application/json",
|
|
1297
|
+
...fetchOptions.headers,
|
|
1298
|
+
...options?.headers
|
|
1299
|
+
};
|
|
1300
|
+
if (apiKey) {
|
|
1301
|
+
headers["x-api-key"] = apiKey;
|
|
1302
|
+
}
|
|
1303
|
+
const init = {
|
|
1304
|
+
...fetchOptions,
|
|
1305
|
+
method: options?.method ?? "GET",
|
|
1306
|
+
headers
|
|
1307
|
+
};
|
|
1308
|
+
if (options?.body !== undefined) {
|
|
1309
|
+
init.body = JSON.stringify(options.body);
|
|
1310
|
+
}
|
|
1311
|
+
return fetchWithRetry(url, init, options?.retryCount ?? retryCount, retryDelay, timeout, { signal: options?.signal, read: readBody });
|
|
1312
|
+
};
|
|
1015
1313
|
}
|
|
1016
1314
|
|
|
1017
1315
|
// src/actions/public/txSources.ts
|
|
@@ -1043,9 +1341,7 @@ function extendedApiSource() {
|
|
|
1043
1341
|
async get({ client, txid }) {
|
|
1044
1342
|
let data;
|
|
1045
1343
|
try {
|
|
1046
|
-
data = await client.request(`/extended/v1/tx/${normalizeTxid(txid)}`, {
|
|
1047
|
-
method: "GET"
|
|
1048
|
-
});
|
|
1344
|
+
data = await client.request(`/extended/v1/tx/${encodeURIComponent(normalizeTxid(txid))}`, { method: "GET" });
|
|
1049
1345
|
} catch (error) {
|
|
1050
1346
|
if (error instanceof HttpRequestError && error.status === 404) {
|
|
1051
1347
|
return { receipt: null };
|
|
@@ -1085,8 +1381,8 @@ async function readContract(client, params) {
|
|
|
1085
1381
|
const [address, name] = parseContractId(params.contract);
|
|
1086
1382
|
const sender = params.sender ?? address;
|
|
1087
1383
|
const serializedArgs = (params.args ?? []).map((arg) => with0x(bytesToHex(serializeCVBytes(arg))));
|
|
1088
|
-
const path = `/v2/contracts/call-read/${address}/${name}/${params.functionName}`;
|
|
1089
|
-
const data = await client.request(params.tip ? `${path}?tip=${params.tip}` : path, {
|
|
1384
|
+
const path = `/v2/contracts/call-read/${encodeURIComponent(address)}/${encodeURIComponent(name)}/${encodeURIComponent(params.functionName)}`;
|
|
1385
|
+
const data = await client.request(params.tip ? `${path}?tip=${encodeURIComponent(params.tip)}` : path, {
|
|
1090
1386
|
method: "POST",
|
|
1091
1387
|
body: {
|
|
1092
1388
|
sender,
|
|
@@ -1099,6 +1395,50 @@ async function readContract(client, params) {
|
|
|
1099
1395
|
throw new Error(data.cause ?? "Read-only call failed");
|
|
1100
1396
|
}
|
|
1101
1397
|
|
|
1398
|
+
// src/actions/wallet/utils.ts
|
|
1399
|
+
function isProviderAccount(account) {
|
|
1400
|
+
return account.type === "provider";
|
|
1401
|
+
}
|
|
1402
|
+
var FEE_TIERS = ["min", "low", "mid", "high"];
|
|
1403
|
+
var TIER_INDEX = { low: 0, mid: 1, high: 2 };
|
|
1404
|
+
function isFeeTier(fee) {
|
|
1405
|
+
return typeof fee === "string" && FEE_TIERS.includes(fee);
|
|
1406
|
+
}
|
|
1407
|
+
function minimumFee(transaction) {
|
|
1408
|
+
return BigInt(serializeTransaction(transaction).length);
|
|
1409
|
+
}
|
|
1410
|
+
function isNoEstimateAvailable(error) {
|
|
1411
|
+
return error instanceof HttpRequestError && error.status === 400 && (error.details?.includes("NoEstimateAvailable") ?? false);
|
|
1412
|
+
}
|
|
1413
|
+
async function resolveFee(client, transaction, fee) {
|
|
1414
|
+
if (fee !== undefined && !isFeeTier(fee))
|
|
1415
|
+
return { fee: intToBigInt(fee) };
|
|
1416
|
+
const tier = fee ?? "mid";
|
|
1417
|
+
if (tier === "min")
|
|
1418
|
+
return { fee: minimumFee(transaction), tier };
|
|
1419
|
+
let estimates;
|
|
1420
|
+
try {
|
|
1421
|
+
estimates = await estimateFee(client, { transaction });
|
|
1422
|
+
} catch (error) {
|
|
1423
|
+
if (!isNoEstimateAvailable(error))
|
|
1424
|
+
throw error;
|
|
1425
|
+
return { fee: minimumFee(transaction), tier: "min" };
|
|
1426
|
+
}
|
|
1427
|
+
const pick = estimates[TIER_INDEX[tier]] ?? estimates[estimates.length - 1];
|
|
1428
|
+
if (pick)
|
|
1429
|
+
return { fee: BigInt(pick.fee), tier };
|
|
1430
|
+
return { fee: minimumFee(transaction), tier: "min" };
|
|
1431
|
+
}
|
|
1432
|
+
function setUnsignedFee(transaction, fee) {
|
|
1433
|
+
transaction.auth.spendingCondition.fee = fee;
|
|
1434
|
+
clearTxCache(transaction);
|
|
1435
|
+
}
|
|
1436
|
+
function assertNoFeeTierForProvider(fee) {
|
|
1437
|
+
if (isFeeTier(fee)) {
|
|
1438
|
+
throw new Error(`Fee tier '${fee}' requires local signing; provider (wallet) accounts set their own fee`);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1102
1442
|
// src/clarity/abi/utils.ts
|
|
1103
1443
|
function toCamelCase(str) {
|
|
1104
1444
|
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/-([A-Z])/g, (_, letter) => letter).replace(/-(\d)/g, (_, digit) => digit).replace(/-/g, "").replace(/^\d/, "_$&");
|
|
@@ -1906,6 +2246,18 @@ async function getMapEntry(client, params) {
|
|
|
1906
2246
|
return deserializeCVBytes(data.data);
|
|
1907
2247
|
}
|
|
1908
2248
|
|
|
2249
|
+
// src/actions/public/getNonce.ts
|
|
2250
|
+
async function getNonce(client, params) {
|
|
2251
|
+
const data = await client.request(`/v2/accounts/${params.address}`, {
|
|
2252
|
+
method: "GET"
|
|
2253
|
+
});
|
|
2254
|
+
const nonce = data?.nonce;
|
|
2255
|
+
if (typeof nonce !== "number" && typeof nonce !== "string") {
|
|
2256
|
+
throw new Error(`getNonce: unexpected /v2/accounts response for ${params.address} (missing numeric nonce)`);
|
|
2257
|
+
}
|
|
2258
|
+
return BigInt(nonce);
|
|
2259
|
+
}
|
|
2260
|
+
|
|
1909
2261
|
// src/transactions/signer.ts
|
|
1910
2262
|
function txid(tx) {
|
|
1911
2263
|
return txidFromBytes(serializeTransaction(tx));
|
|
@@ -1938,70 +2290,17 @@ function getTransactionId(tx) {
|
|
|
1938
2290
|
return txid(tx);
|
|
1939
2291
|
}
|
|
1940
2292
|
|
|
1941
|
-
// src/errors/transaction.ts
|
|
1942
|
-
class BroadcastError extends BaseError {
|
|
1943
|
-
name = "BroadcastError";
|
|
1944
|
-
txid;
|
|
1945
|
-
reason;
|
|
1946
|
-
reasonData;
|
|
1947
|
-
constructor(message, options) {
|
|
1948
|
-
super(message, options);
|
|
1949
|
-
this.txid = options?.txid;
|
|
1950
|
-
this.reason = options?.reason;
|
|
1951
|
-
this.reasonData = options?.reasonData;
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
|
-
class TransactionAbortedError extends BaseError {
|
|
1956
|
-
name = "TransactionAbortedError";
|
|
1957
|
-
receipt;
|
|
1958
|
-
constructor(message, options) {
|
|
1959
|
-
super(message, options);
|
|
1960
|
-
this.receipt = options.receipt;
|
|
1961
|
-
}
|
|
1962
|
-
}
|
|
1963
|
-
|
|
1964
|
-
class TransactionDroppedError extends BaseError {
|
|
1965
|
-
name = "TransactionDroppedError";
|
|
1966
|
-
txid;
|
|
1967
|
-
constructor(message, options) {
|
|
1968
|
-
super(message, options);
|
|
1969
|
-
this.txid = options.txid;
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
|
|
1973
|
-
class WaitForTransactionTimeoutError extends BaseError {
|
|
1974
|
-
name = "WaitForTransactionTimeoutError";
|
|
1975
|
-
txid;
|
|
1976
|
-
constructor(message, options) {
|
|
1977
|
-
super(message, options);
|
|
1978
|
-
this.txid = options.txid;
|
|
1979
|
-
}
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
// src/actions/public/getNonce.ts
|
|
1983
|
-
async function getNonce(client, params) {
|
|
1984
|
-
const data = await client.request(`/v2/accounts/${params.address}`, {
|
|
1985
|
-
method: "GET"
|
|
1986
|
-
});
|
|
1987
|
-
const nonce = data?.nonce;
|
|
1988
|
-
if (typeof nonce !== "number" && typeof nonce !== "string") {
|
|
1989
|
-
throw new Error(`getNonce: unexpected /v2/accounts response for ${params.address} (missing numeric nonce)`);
|
|
1990
|
-
}
|
|
1991
|
-
return BigInt(nonce);
|
|
1992
|
-
}
|
|
1993
|
-
|
|
1994
2293
|
// src/actions/public/waitForTransactionReceipt.ts
|
|
1995
|
-
var
|
|
2294
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
1996
2295
|
async function waitForTransactionReceipt(client, params) {
|
|
1997
2296
|
const {
|
|
1998
2297
|
txid: txid2,
|
|
1999
2298
|
confirmations = 1,
|
|
2000
2299
|
timeout = 180000,
|
|
2001
|
-
pollingInterval = 3000
|
|
2002
|
-
droppedGracePeriod = 30000
|
|
2300
|
+
pollingInterval = 3000
|
|
2003
2301
|
} = params;
|
|
2004
2302
|
const source = params.source ?? extendedApiSource();
|
|
2303
|
+
const droppedGracePeriod = params.droppedGracePeriod ?? (source.canonicalOnly ? timeout : 30000);
|
|
2005
2304
|
const startedAt = Date.now();
|
|
2006
2305
|
let unknownSince = null;
|
|
2007
2306
|
let everPending = false;
|
|
@@ -2039,7 +2338,7 @@ async function waitForTransactionReceipt(client, params) {
|
|
|
2039
2338
|
if (Date.now() - startedAt >= timeout) {
|
|
2040
2339
|
throw new WaitForTransactionTimeoutError(`Timed out after ${timeout}ms waiting for transaction ${txid2}`, { txid: txid2 });
|
|
2041
2340
|
}
|
|
2042
|
-
await
|
|
2341
|
+
await sleep2(pollingInterval);
|
|
2043
2342
|
}
|
|
2044
2343
|
}
|
|
2045
2344
|
|
|
@@ -2052,7 +2351,11 @@ async function sendTransaction(client, params) {
|
|
|
2052
2351
|
}
|
|
2053
2352
|
let data;
|
|
2054
2353
|
try {
|
|
2055
|
-
data = await client.request("/v2/transactions", {
|
|
2354
|
+
data = await client.request("/v2/transactions", {
|
|
2355
|
+
method: "POST",
|
|
2356
|
+
body,
|
|
2357
|
+
retryCount: 0
|
|
2358
|
+
});
|
|
2056
2359
|
} catch (error) {
|
|
2057
2360
|
if (error instanceof HttpRequestError && error.details) {
|
|
2058
2361
|
try {
|
|
@@ -2060,6 +2363,12 @@ async function sendTransaction(client, params) {
|
|
|
2060
2363
|
} catch {
|
|
2061
2364
|
throw error;
|
|
2062
2365
|
}
|
|
2366
|
+
} else if (error instanceof TimeoutError) {
|
|
2367
|
+
const txid3 = getTransactionId(params.transaction);
|
|
2368
|
+
const receipt = await getTransaction(client, { txid: txid3 }).catch(() => null);
|
|
2369
|
+
if (receipt === null)
|
|
2370
|
+
throw error;
|
|
2371
|
+
data = { txid: txid3 };
|
|
2063
2372
|
} else {
|
|
2064
2373
|
throw error;
|
|
2065
2374
|
}
|
|
@@ -2089,6 +2398,13 @@ async function resolveNonce(client, address) {
|
|
|
2089
2398
|
return client.nonceManager.consume({ client, address });
|
|
2090
2399
|
return getNonce(client, { address });
|
|
2091
2400
|
}
|
|
2401
|
+
async function releaseNonce(client, address, nonce) {
|
|
2402
|
+
if (!client.nonceManager)
|
|
2403
|
+
return;
|
|
2404
|
+
try {
|
|
2405
|
+
await client.nonceManager.release({ client, address, nonce });
|
|
2406
|
+
} catch {}
|
|
2407
|
+
}
|
|
2092
2408
|
function isNonceConflictError(error) {
|
|
2093
2409
|
if (!(error instanceof BroadcastError))
|
|
2094
2410
|
return false;
|
|
@@ -2113,42 +2429,6 @@ async function broadcastWithNonceReset(client, params) {
|
|
|
2113
2429
|
}
|
|
2114
2430
|
}
|
|
2115
2431
|
|
|
2116
|
-
// src/actions/wallet/utils.ts
|
|
2117
|
-
function isProviderAccount(account) {
|
|
2118
|
-
return account.type === "provider";
|
|
2119
|
-
}
|
|
2120
|
-
var FEE_TIERS = ["min", "low", "mid", "high"];
|
|
2121
|
-
var TIER_INDEX = { low: 0, mid: 1, high: 2 };
|
|
2122
|
-
function isFeeTier(fee) {
|
|
2123
|
-
return typeof fee === "string" && FEE_TIERS.includes(fee);
|
|
2124
|
-
}
|
|
2125
|
-
function minimumFee(transaction) {
|
|
2126
|
-
return BigInt(serializeTransaction(transaction).length);
|
|
2127
|
-
}
|
|
2128
|
-
async function resolveFee(client, transaction, fee) {
|
|
2129
|
-
if (fee !== undefined && !isFeeTier(fee))
|
|
2130
|
-
return intToBigInt(fee);
|
|
2131
|
-
const tier = fee ?? "mid";
|
|
2132
|
-
if (tier === "min")
|
|
2133
|
-
return minimumFee(transaction);
|
|
2134
|
-
try {
|
|
2135
|
-
const estimates = await estimateFee(client, { transaction });
|
|
2136
|
-
const pick = estimates[TIER_INDEX[tier]] ?? estimates[estimates.length - 1];
|
|
2137
|
-
if (pick)
|
|
2138
|
-
return BigInt(pick.fee);
|
|
2139
|
-
} catch {}
|
|
2140
|
-
return minimumFee(transaction);
|
|
2141
|
-
}
|
|
2142
|
-
function setUnsignedFee(transaction, fee) {
|
|
2143
|
-
transaction.auth.spendingCondition.fee = fee;
|
|
2144
|
-
clearTxCache(transaction);
|
|
2145
|
-
}
|
|
2146
|
-
function assertNoFeeTierForProvider(fee) {
|
|
2147
|
-
if (isFeeTier(fee)) {
|
|
2148
|
-
throw new Error(`Fee tier '${fee}' requires local signing; provider (wallet) accounts set their own fee`);
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
2432
|
// src/actions/wallet/callContract.ts
|
|
2153
2433
|
async function callContract(client, params) {
|
|
2154
2434
|
const account = client.account;
|
|
@@ -2164,28 +2444,36 @@ async function callContract(client, params) {
|
|
|
2164
2444
|
});
|
|
2165
2445
|
return result.txid;
|
|
2166
2446
|
}
|
|
2447
|
+
const managed = params.nonce === undefined && client.nonceManager !== undefined;
|
|
2167
2448
|
const nonce = params.nonce ?? await resolveNonce(client, account.address);
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2449
|
+
try {
|
|
2450
|
+
const needsFeeResolution = params.fee === undefined || isFeeTier(params.fee);
|
|
2451
|
+
const unsigned = buildContractCall({
|
|
2452
|
+
contractAddress,
|
|
2453
|
+
contractName,
|
|
2454
|
+
functionName: params.functionName,
|
|
2455
|
+
functionArgs: params.functionArgs ?? [],
|
|
2456
|
+
fee: needsFeeResolution ? 0n : params.fee,
|
|
2457
|
+
nonce,
|
|
2458
|
+
publicKey: account.publicKey,
|
|
2459
|
+
chain: client.chain,
|
|
2460
|
+
postConditionMode: params.postConditionMode,
|
|
2461
|
+
postConditions: params.postConditions
|
|
2462
|
+
});
|
|
2463
|
+
if (needsFeeResolution) {
|
|
2464
|
+
const { fee } = await resolveFee(client, unsigned, params.fee);
|
|
2465
|
+
setUnsignedFee(unsigned, fee);
|
|
2466
|
+
}
|
|
2467
|
+
const signed = await signTransactionWithAccount(unsigned, account);
|
|
2468
|
+
return await broadcastWithNonceReset(client, {
|
|
2469
|
+
transaction: signed,
|
|
2470
|
+
address: account.address
|
|
2471
|
+
});
|
|
2472
|
+
} catch (error) {
|
|
2473
|
+
if (managed)
|
|
2474
|
+
await releaseNonce(client, account.address, nonce);
|
|
2475
|
+
throw error;
|
|
2183
2476
|
}
|
|
2184
|
-
const signed = await signTransactionWithAccount(unsigned, account);
|
|
2185
|
-
return broadcastWithNonceReset(client, {
|
|
2186
|
-
transaction: signed,
|
|
2187
|
-
address: account.address
|
|
2188
|
-
});
|
|
2189
2477
|
}
|
|
2190
2478
|
|
|
2191
2479
|
// src/actions/getContract.ts
|
|
@@ -2265,7 +2553,9 @@ function getContract(params) {
|
|
|
2265
2553
|
}
|
|
2266
2554
|
const functionArgs = buildFunctionArgs(fn, args);
|
|
2267
2555
|
const network = client.chain?.network ?? "mainnet";
|
|
2268
|
-
const nonce = options?.nonce ?? await
|
|
2556
|
+
const nonce = options?.nonce ?? await getNonce(client, {
|
|
2557
|
+
address: publicKeyToAddress(publicKey, network)
|
|
2558
|
+
});
|
|
2269
2559
|
const unsigned = buildContractCall({
|
|
2270
2560
|
contractAddress: address,
|
|
2271
2561
|
contractName,
|
|
@@ -2280,13 +2570,8 @@ function getContract(params) {
|
|
|
2280
2570
|
sponsored: options?.sponsored
|
|
2281
2571
|
});
|
|
2282
2572
|
if (options?.fee === undefined) {
|
|
2283
|
-
const
|
|
2284
|
-
|
|
2285
|
-
});
|
|
2286
|
-
const mid = estimates[1] ?? estimates[0];
|
|
2287
|
-
if (mid) {
|
|
2288
|
-
setUnsignedFee(unsigned, BigInt(mid.fee));
|
|
2289
|
-
}
|
|
2573
|
+
const { fee } = await resolveFee(client, unsigned, undefined);
|
|
2574
|
+
setUnsignedFee(unsigned, fee);
|
|
2290
2575
|
}
|
|
2291
2576
|
return unsigned;
|
|
2292
2577
|
};
|
|
@@ -2362,6 +2647,56 @@ var SIP018_PREFIX = new Uint8Array([
|
|
|
2362
2647
|
49,
|
|
2363
2648
|
56
|
|
2364
2649
|
]);
|
|
2650
|
+
// src/clarity/prettyPrint.ts
|
|
2651
|
+
function cvToJSON(val) {
|
|
2652
|
+
switch (val.type) {
|
|
2653
|
+
case "true":
|
|
2654
|
+
return { type: "bool", value: true };
|
|
2655
|
+
case "false":
|
|
2656
|
+
return { type: "bool", value: false };
|
|
2657
|
+
case "int":
|
|
2658
|
+
return { type: "int", value: val.value.toString() };
|
|
2659
|
+
case "uint":
|
|
2660
|
+
return { type: "uint", value: val.value.toString() };
|
|
2661
|
+
case "buffer": {
|
|
2662
|
+
const hex = without0x(val.value);
|
|
2663
|
+
return {
|
|
2664
|
+
type: `(buff ${Math.ceil(hex.length / 2)})`,
|
|
2665
|
+
value: `0x${hex}`
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
case "none":
|
|
2669
|
+
return { type: "(optional none)", value: null };
|
|
2670
|
+
case "some":
|
|
2671
|
+
return { type: "(optional)", value: cvToJSON(val.value) };
|
|
2672
|
+
case "ok":
|
|
2673
|
+
return { type: "(response)", value: cvToJSON(val.value), success: true };
|
|
2674
|
+
case "err":
|
|
2675
|
+
return { type: "(response)", value: cvToJSON(val.value), success: false };
|
|
2676
|
+
case "address":
|
|
2677
|
+
case "contract":
|
|
2678
|
+
return { type: "principal", value: val.value };
|
|
2679
|
+
case "list":
|
|
2680
|
+
return { type: "(list)", value: val.value.map(cvToJSON) };
|
|
2681
|
+
case "tuple": {
|
|
2682
|
+
const result = {};
|
|
2683
|
+
for (const key of Object.keys(val.value)) {
|
|
2684
|
+
result[key] = cvToJSON(val.value[key]);
|
|
2685
|
+
}
|
|
2686
|
+
return { type: "(tuple)", value: result };
|
|
2687
|
+
}
|
|
2688
|
+
case "ascii":
|
|
2689
|
+
return {
|
|
2690
|
+
type: `(string-ascii ${asciiToBytes(val.value).length})`,
|
|
2691
|
+
value: val.value
|
|
2692
|
+
};
|
|
2693
|
+
case "utf8":
|
|
2694
|
+
return {
|
|
2695
|
+
type: `(string-utf8 ${utf8ToBytes(val.value).length})`,
|
|
2696
|
+
value: val.value
|
|
2697
|
+
};
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2365
2700
|
// src/clarity/abi/standards.ts
|
|
2366
2701
|
var SIP010_ABI = {
|
|
2367
2702
|
functions: [
|
|
@@ -3048,16 +3383,44 @@ async function getRawBlock(client, params) {
|
|
|
3048
3383
|
}
|
|
3049
3384
|
|
|
3050
3385
|
// src/actions/public/multicall.ts
|
|
3386
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
3387
|
+
const results = new Array(items.length);
|
|
3388
|
+
let cursor = 0;
|
|
3389
|
+
const worker = async () => {
|
|
3390
|
+
while (cursor < items.length) {
|
|
3391
|
+
const index = cursor++;
|
|
3392
|
+
try {
|
|
3393
|
+
results[index] = {
|
|
3394
|
+
status: "fulfilled",
|
|
3395
|
+
value: await fn(items[index])
|
|
3396
|
+
};
|
|
3397
|
+
} catch (reason) {
|
|
3398
|
+
results[index] = { status: "rejected", reason };
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
};
|
|
3402
|
+
const workers = Math.max(1, Math.min(limit, items.length));
|
|
3403
|
+
await Promise.all(Array.from({ length: workers }, worker));
|
|
3404
|
+
return results;
|
|
3405
|
+
}
|
|
3051
3406
|
async function multicall(client, params) {
|
|
3052
|
-
const { calls, allowFailure = true } = params;
|
|
3407
|
+
const { calls, allowFailure = true, concurrency = 8 } = params;
|
|
3408
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
3409
|
+
throw new RangeError(`multicall concurrency must be a positive integer, got ${concurrency}`);
|
|
3410
|
+
}
|
|
3411
|
+
const settled = await mapWithConcurrency(calls, concurrency, (call) => readContract(client, call));
|
|
3053
3412
|
if (allowFailure) {
|
|
3054
|
-
const settled = await Promise.allSettled(calls.map((call) => readContract(client, call)));
|
|
3055
3413
|
return settled.map((r) => r.status === "fulfilled" ? { status: "success", result: r.value } : {
|
|
3056
3414
|
status: "failure",
|
|
3057
3415
|
error: r.reason instanceof Error ? r.reason : new Error(String(r.reason))
|
|
3058
3416
|
});
|
|
3059
3417
|
}
|
|
3060
|
-
const results =
|
|
3418
|
+
const results = [];
|
|
3419
|
+
for (const r of settled) {
|
|
3420
|
+
if (r.status === "rejected")
|
|
3421
|
+
throw r.reason;
|
|
3422
|
+
results.push(r.value);
|
|
3423
|
+
}
|
|
3061
3424
|
return results;
|
|
3062
3425
|
}
|
|
3063
3426
|
|
|
@@ -3219,100 +3582,6 @@ function createPublicClient(config) {
|
|
|
3219
3582
|
return createClient(config).extend(publicActions);
|
|
3220
3583
|
}
|
|
3221
3584
|
|
|
3222
|
-
// src/transports/createTransport.ts
|
|
3223
|
-
function createTransport(type, config) {
|
|
3224
|
-
return {
|
|
3225
|
-
type,
|
|
3226
|
-
request: config.request,
|
|
3227
|
-
config
|
|
3228
|
-
};
|
|
3229
|
-
}
|
|
3230
|
-
function isRetryableStatus(status) {
|
|
3231
|
-
return status === 429 || status >= 500;
|
|
3232
|
-
}
|
|
3233
|
-
var MAX_RETRY_AFTER_MS = 60000;
|
|
3234
|
-
function retryAfterMs(response) {
|
|
3235
|
-
const value = response.headers.get("Retry-After");
|
|
3236
|
-
if (!value)
|
|
3237
|
-
return;
|
|
3238
|
-
const seconds = Number(value);
|
|
3239
|
-
const ms = Number.isFinite(seconds) ? seconds * 1000 : Date.parse(value) - Date.now();
|
|
3240
|
-
if (!Number.isFinite(ms) || ms < 0 || ms > MAX_RETRY_AFTER_MS)
|
|
3241
|
-
return;
|
|
3242
|
-
return ms;
|
|
3243
|
-
}
|
|
3244
|
-
async function fetchWithRetry(url, options, retryCount, retryDelay, timeout) {
|
|
3245
|
-
let lastError;
|
|
3246
|
-
for (let attempt = 0;attempt <= retryCount; attempt++) {
|
|
3247
|
-
let response;
|
|
3248
|
-
try {
|
|
3249
|
-
const controller = new AbortController;
|
|
3250
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
3251
|
-
response = await fetch(url, {
|
|
3252
|
-
...options,
|
|
3253
|
-
signal: controller.signal
|
|
3254
|
-
});
|
|
3255
|
-
clearTimeout(timeoutId);
|
|
3256
|
-
} catch (error) {
|
|
3257
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
3258
|
-
if (attempt < retryCount) {
|
|
3259
|
-
await new Promise((r) => setTimeout(r, retryDelay * (attempt + 1)));
|
|
3260
|
-
continue;
|
|
3261
|
-
}
|
|
3262
|
-
throw lastError;
|
|
3263
|
-
}
|
|
3264
|
-
if (response.ok) {
|
|
3265
|
-
return response;
|
|
3266
|
-
}
|
|
3267
|
-
const retryable = isRetryableStatus(response.status);
|
|
3268
|
-
if (!retryable || attempt === retryCount) {
|
|
3269
|
-
throw new HttpRequestError(response.status, {
|
|
3270
|
-
details: await response.text().catch(() => {
|
|
3271
|
-
return;
|
|
3272
|
-
})
|
|
3273
|
-
});
|
|
3274
|
-
}
|
|
3275
|
-
lastError = new HttpRequestError(response.status);
|
|
3276
|
-
const delay = retryAfterMs(response) ?? retryDelay * (attempt + 1);
|
|
3277
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
3278
|
-
}
|
|
3279
|
-
throw lastError ?? new Error("Request failed");
|
|
3280
|
-
}
|
|
3281
|
-
function buildRequestFn(baseUrl, config) {
|
|
3282
|
-
const {
|
|
3283
|
-
timeout = 30000,
|
|
3284
|
-
retryCount = 3,
|
|
3285
|
-
retryDelay = 150,
|
|
3286
|
-
fetchOptions = {},
|
|
3287
|
-
apiKey
|
|
3288
|
-
} = config;
|
|
3289
|
-
return async (path, options) => {
|
|
3290
|
-
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
3291
|
-
const headers = {
|
|
3292
|
-
"Content-Type": "application/json",
|
|
3293
|
-
...fetchOptions.headers,
|
|
3294
|
-
...options?.headers
|
|
3295
|
-
};
|
|
3296
|
-
if (apiKey) {
|
|
3297
|
-
headers["x-api-key"] = apiKey;
|
|
3298
|
-
}
|
|
3299
|
-
const init = {
|
|
3300
|
-
...fetchOptions,
|
|
3301
|
-
method: options?.method ?? "GET",
|
|
3302
|
-
headers
|
|
3303
|
-
};
|
|
3304
|
-
if (options?.body !== undefined) {
|
|
3305
|
-
init.body = JSON.stringify(options.body);
|
|
3306
|
-
}
|
|
3307
|
-
const response = await fetchWithRetry(url, init, retryCount, retryDelay, timeout);
|
|
3308
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
3309
|
-
if (contentType.includes("application/json")) {
|
|
3310
|
-
return response.json();
|
|
3311
|
-
}
|
|
3312
|
-
return response.text();
|
|
3313
|
-
};
|
|
3314
|
-
}
|
|
3315
|
-
|
|
3316
3585
|
// src/transports/http.ts
|
|
3317
3586
|
function http(url, config) {
|
|
3318
3587
|
return (params) => {
|
|
@@ -3333,36 +3602,47 @@ var _defaultClient = null;
|
|
|
3333
3602
|
function getDefaultPublicClient() {
|
|
3334
3603
|
if (_defaultClient)
|
|
3335
3604
|
return _defaultClient;
|
|
3336
|
-
const
|
|
3605
|
+
const network = process.env.STACKS_NETWORK ?? process.env.STACKS_CHAIN;
|
|
3606
|
+
const chain = network === "testnet" ? testnet : mainnet;
|
|
3607
|
+
const url = process.env.STACKS_NODE_RPC_URL ?? process.env.SL_API_URL ?? process.env.STACKS_RPC_URL;
|
|
3337
3608
|
_defaultClient = createPublicClient({
|
|
3338
3609
|
chain,
|
|
3339
|
-
transport: http(
|
|
3610
|
+
transport: http(url)
|
|
3340
3611
|
});
|
|
3341
3612
|
return _defaultClient;
|
|
3342
3613
|
}
|
|
3343
3614
|
|
|
3344
3615
|
// src/tools/index.ts
|
|
3345
|
-
var PRINCIPAL = z.string().
|
|
3346
|
-
|
|
3347
|
-
|
|
3616
|
+
var PRINCIPAL = z.string().refine((v) => parsePrincipal(v) !== null, {
|
|
3617
|
+
message: "Expected a Stacks principal: a c32 address (SP…/SM… mainnet, ST… testnet), optionally followed by .contract-name"
|
|
3618
|
+
}).describe("Stacks principal (SP…/SM… mainnet, ST… testnet)");
|
|
3619
|
+
var CONTRACT_ID = z.string().refine((v) => parsePrincipal(v)?.contractName !== undefined, {
|
|
3620
|
+
message: "Expected a contract id in '{address}.{name}' form"
|
|
3621
|
+
}).describe("Fully-qualified contract id: '{address}.{name}'");
|
|
3622
|
+
var FUNCTION_NAME = z.string().refine(isClarityName, { message: "Expected a Clarity function name" });
|
|
3623
|
+
var HASH_32 = /^(0x)?[0-9a-fA-F]{64}$/;
|
|
3624
|
+
var TX_ID = z.string().regex(HASH_32, "Expected a 32-byte hex transaction id").describe("Transaction id, with or without 0x prefix");
|
|
3625
|
+
var BLOCK_HASH = z.string().regex(HASH_32, "Expected a 32-byte hex block hash");
|
|
3626
|
+
async function stxBalance(resolve, principal) {
|
|
3627
|
+
const balance = await getBalance(resolve(), { address: principal });
|
|
3348
3628
|
return { microStx: balance.toString() };
|
|
3349
3629
|
}
|
|
3350
|
-
async function accountInfo(
|
|
3351
|
-
const info = await getAccountInfo(
|
|
3630
|
+
async function accountInfo(resolve, principal) {
|
|
3631
|
+
const info = await getAccountInfo(resolve(), { address: principal });
|
|
3352
3632
|
return {
|
|
3353
3633
|
balance: info.balance.toString(),
|
|
3354
3634
|
nonce: info.nonce.toString()
|
|
3355
3635
|
};
|
|
3356
3636
|
}
|
|
3357
|
-
async function block(
|
|
3358
|
-
return getBlock(
|
|
3637
|
+
async function block(resolve, args) {
|
|
3638
|
+
return getBlock(resolve(), args);
|
|
3359
3639
|
}
|
|
3360
|
-
async function blockHeight(
|
|
3361
|
-
return { height: await getBlockHeight(
|
|
3640
|
+
async function blockHeight(resolve) {
|
|
3641
|
+
return { height: await getBlockHeight(resolve()) };
|
|
3362
3642
|
}
|
|
3363
|
-
async function contractRead(
|
|
3364
|
-
const result = await readContract(
|
|
3365
|
-
return { result:
|
|
3643
|
+
async function contractRead(resolve, args) {
|
|
3644
|
+
const result = await readContract(resolve(), args);
|
|
3645
|
+
return { result: cvToJSON(result) };
|
|
3366
3646
|
}
|
|
3367
3647
|
function assertValidHex(raw) {
|
|
3368
3648
|
if (raw.length % 2 !== 0) {
|
|
@@ -3372,199 +3652,156 @@ function assertValidHex(raw) {
|
|
|
3372
3652
|
throw new Error("serializedTxHex: contains non-hex characters");
|
|
3373
3653
|
}
|
|
3374
3654
|
}
|
|
3375
|
-
async function fee(
|
|
3655
|
+
async function fee(resolve, serializedTxHex) {
|
|
3376
3656
|
const raw = serializedTxHex.startsWith("0x") ? serializedTxHex.slice(2) : serializedTxHex;
|
|
3377
3657
|
assertValidHex(raw);
|
|
3378
|
-
const txBytes =
|
|
3658
|
+
const txBytes = hexToBytes(raw);
|
|
3379
3659
|
let transaction;
|
|
3380
3660
|
try {
|
|
3381
3661
|
transaction = deserializeTransaction(txBytes);
|
|
3382
3662
|
} catch (e) {
|
|
3383
|
-
throw new Error(`serializedTxHex: deserialization failed
|
|
3663
|
+
throw new Error(`serializedTxHex: deserialization failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
3384
3664
|
}
|
|
3385
|
-
const fees = await estimateFee(
|
|
3386
|
-
|
|
3387
|
-
|
|
3665
|
+
const fees = await estimateFee(resolve(), { transaction });
|
|
3666
|
+
if (fees.length === 0) {
|
|
3667
|
+
const min = Number(minimumFee(transaction));
|
|
3668
|
+
return {
|
|
3669
|
+
low: min,
|
|
3670
|
+
medium: min,
|
|
3671
|
+
high: min,
|
|
3672
|
+
source: "min",
|
|
3673
|
+
tiers: 0
|
|
3674
|
+
};
|
|
3675
|
+
}
|
|
3676
|
+
const low = fees[0]?.fee ?? 0;
|
|
3388
3677
|
return {
|
|
3389
|
-
low
|
|
3390
|
-
medium: fees[1]?.fee ??
|
|
3391
|
-
high: fees[2]?.fee ??
|
|
3678
|
+
low,
|
|
3679
|
+
medium: fees[1]?.fee ?? low,
|
|
3680
|
+
high: fees[2]?.fee ?? fees[1]?.fee ?? low,
|
|
3681
|
+
source: "node",
|
|
3682
|
+
tiers: fees.length
|
|
3392
3683
|
};
|
|
3393
3684
|
}
|
|
3394
|
-
async function bnsResolveImpl(
|
|
3395
|
-
return { owner: await resolveName(
|
|
3685
|
+
async function bnsResolveImpl(resolve, name) {
|
|
3686
|
+
return { owner: await resolveName(resolve(), name) };
|
|
3396
3687
|
}
|
|
3397
|
-
async function bnsReverseImpl(
|
|
3398
|
-
return { name: await getPrimaryName(
|
|
3688
|
+
async function bnsReverseImpl(resolve, principal) {
|
|
3689
|
+
return { name: await getPrimaryName(resolve(), principal) };
|
|
3399
3690
|
}
|
|
3400
|
-
async function transactionByTxId(
|
|
3401
|
-
|
|
3691
|
+
async function transactionByTxId(resolve, txId) {
|
|
3692
|
+
const receipt = await getTransaction(resolve(), { txid: txId });
|
|
3693
|
+
if (!receipt)
|
|
3694
|
+
return null;
|
|
3695
|
+
const { result, ...rest } = receipt;
|
|
3696
|
+
return result === undefined ? rest : { ...rest, result: cvToJSON(result) };
|
|
3402
3697
|
}
|
|
3403
|
-
async function accountHistory(
|
|
3404
|
-
return getAccountHistory(
|
|
3698
|
+
async function accountHistory(resolve, principal, limit) {
|
|
3699
|
+
return getAccountHistory(resolve(), { address: principal, limit });
|
|
3405
3700
|
}
|
|
3406
|
-
async function mempoolStats(
|
|
3407
|
-
return getMempoolStats(
|
|
3701
|
+
async function mempoolStats(resolve) {
|
|
3702
|
+
return getMempoolStats(resolve());
|
|
3408
3703
|
}
|
|
3409
|
-
async function nftHoldings(
|
|
3410
|
-
return getNftHoldings(
|
|
3704
|
+
async function nftHoldings(resolve, principal, limit) {
|
|
3705
|
+
return getNftHoldings(resolve(), { address: principal, limit });
|
|
3411
3706
|
}
|
|
3412
|
-
|
|
3707
|
+
var EXTENDED = "Needs a host that serves the extended API.";
|
|
3708
|
+
function buildTools(resolve) {
|
|
3413
3709
|
return {
|
|
3414
3710
|
getStxBalance: tool({
|
|
3415
3711
|
description: "Get the STX balance (in micro-STX) for a Stacks principal.",
|
|
3416
3712
|
inputSchema: z.object({ principal: PRINCIPAL }),
|
|
3417
|
-
execute: ({ principal }) => stxBalance(
|
|
3713
|
+
execute: ({ principal }) => stxBalance(resolve, principal)
|
|
3418
3714
|
}),
|
|
3419
3715
|
getAccountInfo: tool({
|
|
3420
|
-
description: "Get
|
|
3716
|
+
description: "Get the STX balance (micro-STX) and next nonce for a Stacks principal.",
|
|
3421
3717
|
inputSchema: z.object({ principal: PRINCIPAL }),
|
|
3422
|
-
execute: ({ principal }) => accountInfo(
|
|
3718
|
+
execute: ({ principal }) => accountInfo(resolve, principal)
|
|
3423
3719
|
}),
|
|
3424
3720
|
getBlock: tool({
|
|
3425
|
-
description: "Fetch
|
|
3721
|
+
description: "Fetch one Stacks block by height or hash. Omit both for the latest block. Always returns a single block object.",
|
|
3426
3722
|
inputSchema: z.object({
|
|
3427
3723
|
height: z.number().int().nonnegative().optional(),
|
|
3428
|
-
hash:
|
|
3724
|
+
hash: BLOCK_HASH.optional()
|
|
3429
3725
|
}),
|
|
3430
|
-
execute: (args) => block(
|
|
3726
|
+
execute: (args) => block(resolve, args)
|
|
3431
3727
|
}),
|
|
3432
3728
|
getBlockHeight: tool({
|
|
3433
3729
|
description: "Get the current Stacks chain tip height.",
|
|
3434
3730
|
inputSchema: z.object({}),
|
|
3435
|
-
execute: () => blockHeight(
|
|
3731
|
+
execute: () => blockHeight(resolve)
|
|
3436
3732
|
}),
|
|
3437
3733
|
readContract: tool({
|
|
3438
|
-
description: "Call a read-only Clarity function. Returns the decoded value as JSON.",
|
|
3734
|
+
description: "Call a read-only Clarity function that takes no arguments. Returns the decoded value as JSON; uint and int arrive as decimal strings.",
|
|
3439
3735
|
inputSchema: z.object({
|
|
3440
|
-
contract:
|
|
3441
|
-
functionName:
|
|
3736
|
+
contract: CONTRACT_ID,
|
|
3737
|
+
functionName: FUNCTION_NAME,
|
|
3442
3738
|
sender: PRINCIPAL.optional()
|
|
3443
3739
|
}),
|
|
3444
|
-
execute: (args) => contractRead(
|
|
3740
|
+
execute: (args) => contractRead(resolve, args)
|
|
3445
3741
|
}),
|
|
3446
3742
|
estimateFee: tool({
|
|
3447
|
-
description: "Estimate fee
|
|
3743
|
+
description: "Estimate fee tiers (low / medium / high, in micro-STX) for a serialized Stacks transaction. `source` is 'node' for a live estimate or 'min' when the node had none and the relay minimum was used. `tiers` is how many estimates the node returned; when it is below 3 the missing tiers repeat the nearest lower one.",
|
|
3448
3744
|
inputSchema: z.object({
|
|
3449
3745
|
serializedTxHex: z.string().describe("Hex-encoded serialized transaction")
|
|
3450
3746
|
}),
|
|
3451
|
-
execute: ({ serializedTxHex }) => fee(
|
|
3747
|
+
execute: ({ serializedTxHex }) => fee(resolve, serializedTxHex)
|
|
3452
3748
|
}),
|
|
3453
3749
|
bnsResolve: tool({
|
|
3454
3750
|
description: "Resolve a BNS name (e.g. 'satoshi.btc') to its owning Stacks principal.",
|
|
3455
3751
|
inputSchema: z.object({
|
|
3456
3752
|
name: z.string().describe("BNS name in 'name.namespace' form")
|
|
3457
3753
|
}),
|
|
3458
|
-
execute: ({ name }) => bnsResolveImpl(
|
|
3754
|
+
execute: ({ name }) => bnsResolveImpl(resolve, name)
|
|
3459
3755
|
}),
|
|
3460
3756
|
bnsReverse: tool({
|
|
3461
3757
|
description: "Reverse-lookup the primary BNS name for a Stacks principal, if set.",
|
|
3462
3758
|
inputSchema: z.object({ principal: PRINCIPAL }),
|
|
3463
|
-
execute: ({ principal }) => bnsReverseImpl(
|
|
3759
|
+
execute: ({ principal }) => bnsReverseImpl(resolve, principal)
|
|
3464
3760
|
}),
|
|
3465
3761
|
getTransaction: tool({
|
|
3466
|
-
description:
|
|
3467
|
-
inputSchema: z.object({
|
|
3468
|
-
|
|
3469
|
-
}),
|
|
3470
|
-
execute: ({ txId }) => transactionByTxId(client, txId)
|
|
3762
|
+
description: `Fetch a confirmed Stacks transaction by txId, with its decoded result as JSON. ${EXTENDED}`,
|
|
3763
|
+
inputSchema: z.object({ txId: TX_ID }),
|
|
3764
|
+
execute: ({ txId }) => transactionByTxId(resolve, txId)
|
|
3471
3765
|
}),
|
|
3472
3766
|
getAccountHistory: tool({
|
|
3473
|
-
description:
|
|
3767
|
+
description: `List the most recent transactions for a Stacks principal (first page only, up to 50). ${EXTENDED}`,
|
|
3474
3768
|
inputSchema: z.object({
|
|
3475
3769
|
principal: PRINCIPAL,
|
|
3476
3770
|
limit: z.number().int().min(1).max(50).default(20)
|
|
3477
3771
|
}),
|
|
3478
|
-
execute: ({ principal, limit }) => accountHistory(
|
|
3772
|
+
execute: ({ principal, limit }) => accountHistory(resolve, principal, limit)
|
|
3479
3773
|
}),
|
|
3480
3774
|
getMempoolStats: tool({
|
|
3481
|
-
description:
|
|
3775
|
+
description: `Current mempool statistics: pending count, fee distribution, age buckets. ${EXTENDED}`,
|
|
3482
3776
|
inputSchema: z.object({}),
|
|
3483
|
-
execute: () => mempoolStats(
|
|
3777
|
+
execute: () => mempoolStats(resolve)
|
|
3484
3778
|
}),
|
|
3485
3779
|
getNftHoldings: tool({
|
|
3486
|
-
description:
|
|
3780
|
+
description: `List NFTs held by a Stacks principal across all collections (first page only, up to 50). ${EXTENDED}`,
|
|
3487
3781
|
inputSchema: z.object({
|
|
3488
3782
|
principal: PRINCIPAL,
|
|
3489
3783
|
limit: z.number().int().min(1).max(50).default(20)
|
|
3490
3784
|
}),
|
|
3491
|
-
execute: ({ principal, limit }) => nftHoldings(
|
|
3785
|
+
execute: ({ principal, limit }) => nftHoldings(resolve, principal, limit)
|
|
3492
3786
|
})
|
|
3493
3787
|
};
|
|
3494
3788
|
}
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
var getAccountInfo2 =
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
var
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
execute: (args) => block(getDefaultPublicClient(), args)
|
|
3512
|
-
});
|
|
3513
|
-
var getBlockHeight2 = tool({
|
|
3514
|
-
description: "Get the current Stacks chain tip height.",
|
|
3515
|
-
inputSchema: z.object({}),
|
|
3516
|
-
execute: () => blockHeight(getDefaultPublicClient())
|
|
3517
|
-
});
|
|
3518
|
-
var readContract2 = tool({
|
|
3519
|
-
description: "Call a read-only Clarity function. Returns the decoded value as JSON.",
|
|
3520
|
-
inputSchema: z.object({
|
|
3521
|
-
contract: z.string(),
|
|
3522
|
-
functionName: z.string(),
|
|
3523
|
-
sender: PRINCIPAL.optional()
|
|
3524
|
-
}),
|
|
3525
|
-
execute: (args) => contractRead(getDefaultPublicClient(), args)
|
|
3526
|
-
});
|
|
3527
|
-
var estimateFee2 = tool({
|
|
3528
|
-
description: "Estimate fee range (low / medium / high) for a serialized Stacks transaction.",
|
|
3529
|
-
inputSchema: z.object({ serializedTxHex: z.string() }),
|
|
3530
|
-
execute: ({ serializedTxHex }) => fee(getDefaultPublicClient(), serializedTxHex)
|
|
3531
|
-
});
|
|
3532
|
-
var bnsResolve = tool({
|
|
3533
|
-
description: "Resolve a BNS name (e.g. 'satoshi.btc') to its owning Stacks principal.",
|
|
3534
|
-
inputSchema: z.object({ name: z.string() }),
|
|
3535
|
-
execute: ({ name }) => bnsResolveImpl(getDefaultPublicClient(), name)
|
|
3536
|
-
});
|
|
3537
|
-
var bnsReverse = tool({
|
|
3538
|
-
description: "Reverse-lookup the primary BNS name for a Stacks principal, if set.",
|
|
3539
|
-
inputSchema: z.object({ principal: PRINCIPAL }),
|
|
3540
|
-
execute: ({ principal }) => bnsReverseImpl(getDefaultPublicClient(), principal)
|
|
3541
|
-
});
|
|
3542
|
-
var getTransaction2 = tool({
|
|
3543
|
-
description: "Fetch a confirmed Stacks transaction by txId (Hiro extended API).",
|
|
3544
|
-
inputSchema: z.object({ txId: z.string() }),
|
|
3545
|
-
execute: ({ txId }) => transactionByTxId(getDefaultPublicClient(), txId)
|
|
3546
|
-
});
|
|
3547
|
-
var getAccountHistory2 = tool({
|
|
3548
|
-
description: "Paginated transaction history for a Stacks principal (Hiro extended API).",
|
|
3549
|
-
inputSchema: z.object({
|
|
3550
|
-
principal: PRINCIPAL,
|
|
3551
|
-
limit: z.number().int().min(1).max(50).default(20)
|
|
3552
|
-
}),
|
|
3553
|
-
execute: ({ principal, limit }) => accountHistory(getDefaultPublicClient(), principal, limit)
|
|
3554
|
-
});
|
|
3555
|
-
var getMempoolStats2 = tool({
|
|
3556
|
-
description: "Current mempool statistics: pending count, fee distribution, age buckets (Hiro extended API).",
|
|
3557
|
-
inputSchema: z.object({}),
|
|
3558
|
-
execute: () => mempoolStats(getDefaultPublicClient())
|
|
3559
|
-
});
|
|
3560
|
-
var getNftHoldings2 = tool({
|
|
3561
|
-
description: "NFT holdings for a Stacks principal across all collections (Hiro extended API).",
|
|
3562
|
-
inputSchema: z.object({
|
|
3563
|
-
principal: PRINCIPAL,
|
|
3564
|
-
limit: z.number().int().min(1).max(50).default(20)
|
|
3565
|
-
}),
|
|
3566
|
-
execute: ({ principal, limit }) => nftHoldings(getDefaultPublicClient(), principal, limit)
|
|
3567
|
-
});
|
|
3789
|
+
function createStacksTools(client) {
|
|
3790
|
+
return buildTools(() => client);
|
|
3791
|
+
}
|
|
3792
|
+
var defaultTools = buildTools(getDefaultPublicClient);
|
|
3793
|
+
var getStxBalance = defaultTools.getStxBalance;
|
|
3794
|
+
var getAccountInfo2 = defaultTools.getAccountInfo;
|
|
3795
|
+
var getBlock2 = defaultTools.getBlock;
|
|
3796
|
+
var getBlockHeight2 = defaultTools.getBlockHeight;
|
|
3797
|
+
var readContract2 = defaultTools.readContract;
|
|
3798
|
+
var estimateFee2 = defaultTools.estimateFee;
|
|
3799
|
+
var bnsResolve = defaultTools.bnsResolve;
|
|
3800
|
+
var bnsReverse = defaultTools.bnsReverse;
|
|
3801
|
+
var getTransaction2 = defaultTools.getTransaction;
|
|
3802
|
+
var getAccountHistory2 = defaultTools.getAccountHistory;
|
|
3803
|
+
var getMempoolStats2 = defaultTools.getMempoolStats;
|
|
3804
|
+
var getNftHoldings2 = defaultTools.getNftHoldings;
|
|
3568
3805
|
export {
|
|
3569
3806
|
readContract2 as readContract,
|
|
3570
3807
|
getTransaction2 as getTransaction,
|
|
@@ -3581,5 +3818,5 @@ export {
|
|
|
3581
3818
|
bnsResolve
|
|
3582
3819
|
};
|
|
3583
3820
|
|
|
3584
|
-
//# debugId=
|
|
3821
|
+
//# debugId=806015FDE8C2D90F64756E2164756E21
|
|
3585
3822
|
//# sourceMappingURL=index.js.map
|