@secondlayer/stacks 4.3.2 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -11
- package/dist/shared/{stacks-gxq2pbky.js → stacks-2as26bcg.js} +10 -7
- package/dist/shared/stacks-2as26bcg.js.map +13 -0
- 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-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-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-ta1gar0b.cjs → stacks-kqn4y8kq.cjs} +7 -5
- package/dist/shared/{stacks-ta1gar0b.cjs.map → stacks-kqn4y8kq.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-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.cjs
CHANGED
|
@@ -59,8 +59,13 @@ var import_ai = require("ai");
|
|
|
59
59
|
var import_zod = require("zod");
|
|
60
60
|
|
|
61
61
|
// src/errors/base.ts
|
|
62
|
+
function codeFromName(name) {
|
|
63
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toUpperCase();
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
class BaseError extends Error {
|
|
63
67
|
name = "StacksError";
|
|
68
|
+
#code;
|
|
64
69
|
shortMessage;
|
|
65
70
|
details;
|
|
66
71
|
constructor(shortMessage, options) {
|
|
@@ -70,12 +75,21 @@ class BaseError extends Error {
|
|
|
70
75
|
${options.details}` : ""
|
|
71
76
|
].join("");
|
|
72
77
|
super(message, { cause: options?.cause });
|
|
78
|
+
if (options?.code !== undefined)
|
|
79
|
+
this.#code = options.code;
|
|
73
80
|
this.shortMessage = shortMessage;
|
|
74
81
|
this.details = options?.details;
|
|
75
82
|
}
|
|
83
|
+
get code() {
|
|
84
|
+
return this.#code ?? codeFromName(this.name);
|
|
85
|
+
}
|
|
86
|
+
set code(value) {
|
|
87
|
+
this.#code = value;
|
|
88
|
+
}
|
|
76
89
|
toJSON() {
|
|
77
90
|
return {
|
|
78
91
|
name: this.name,
|
|
92
|
+
code: this.code,
|
|
79
93
|
message: this.message,
|
|
80
94
|
shortMessage: this.shortMessage,
|
|
81
95
|
details: this.details,
|
|
@@ -414,7 +428,7 @@ function serializeCVBytes(value) {
|
|
|
414
428
|
return withTypeId(value.type, concatBytes(...parts));
|
|
415
429
|
}
|
|
416
430
|
case "tuple": {
|
|
417
|
-
const keys = Object.keys(value.value).sort((a, b) => a
|
|
431
|
+
const keys = Object.keys(value.value).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
418
432
|
const parts = [writeUInt32BE(keys.length)];
|
|
419
433
|
for (const key of keys) {
|
|
420
434
|
parts.push(serializeLPString(key));
|
|
@@ -728,14 +742,12 @@ async function estimateFee(client, params) {
|
|
|
728
742
|
// src/actions/public/getAccountHistory.ts
|
|
729
743
|
async function getAccountHistory(client, params) {
|
|
730
744
|
const limit = Math.min(params.limit ?? 20, 50);
|
|
731
|
-
return client.request(`/extended/v2/addresses/${params.address}/transactions?limit=${limit}`, { method: "GET" });
|
|
745
|
+
return client.request(`/extended/v2/addresses/${encodeURIComponent(params.address)}/transactions?limit=${limit}`, { method: "GET" });
|
|
732
746
|
}
|
|
733
747
|
|
|
734
748
|
// src/actions/public/getAccountInfo.ts
|
|
735
749
|
async function getAccountInfo(client, params) {
|
|
736
|
-
const data = await client.request(`/v2/accounts/${params.address}?proof=1`, {
|
|
737
|
-
method: "GET"
|
|
738
|
-
});
|
|
750
|
+
const data = await client.request(`/v2/accounts/${encodeURIComponent(params.address)}?proof=1`, { method: "GET" });
|
|
739
751
|
const balance = data?.balance;
|
|
740
752
|
const nonce = data?.nonce;
|
|
741
753
|
if (typeof balance !== "string" && typeof balance !== "number" || typeof nonce !== "string" && typeof nonce !== "number") {
|
|
@@ -751,7 +763,7 @@ async function getAccountInfo(client, params) {
|
|
|
751
763
|
|
|
752
764
|
// src/actions/public/getBalance.ts
|
|
753
765
|
async function getBalance(client, params) {
|
|
754
|
-
const data = await client.request(`/v2/accounts/${params.address}`, {
|
|
766
|
+
const data = await client.request(`/v2/accounts/${encodeURIComponent(params.address)}`, {
|
|
755
767
|
method: "GET"
|
|
756
768
|
});
|
|
757
769
|
const balance = data?.balance;
|
|
@@ -764,16 +776,16 @@ async function getBalance(client, params) {
|
|
|
764
776
|
// src/actions/public/getBlock.ts
|
|
765
777
|
async function getBlock(client, params) {
|
|
766
778
|
if (params?.hash) {
|
|
767
|
-
return client.request(`/extended/v2/blocks/${params.hash}`, {
|
|
768
|
-
method: "GET"
|
|
769
|
-
});
|
|
779
|
+
return client.request(`/extended/v2/blocks/${encodeURIComponent(params.hash)}`, { method: "GET" });
|
|
770
780
|
}
|
|
771
781
|
if (params?.height !== undefined) {
|
|
772
|
-
return client.request(`/extended/v2/blocks/${params.height}`, {
|
|
773
|
-
method: "GET"
|
|
774
|
-
});
|
|
782
|
+
return client.request(`/extended/v2/blocks/${encodeURIComponent(String(params.height))}`, { method: "GET" });
|
|
775
783
|
}
|
|
776
|
-
|
|
784
|
+
const data = await client.request("/extended/v2/blocks?limit=1", {
|
|
785
|
+
method: "GET"
|
|
786
|
+
});
|
|
787
|
+
const results = data?.results;
|
|
788
|
+
return Array.isArray(results) ? results[0] ?? null : data;
|
|
777
789
|
}
|
|
778
790
|
|
|
779
791
|
// src/actions/public/getBlockHeight.ts
|
|
@@ -796,6 +808,51 @@ async function getNftHoldings(client, params) {
|
|
|
796
808
|
return client.request(`/extended/v1/tokens/nft/holdings?principal=${encodeURIComponent(params.address)}&limit=${limit}`, { method: "GET" });
|
|
797
809
|
}
|
|
798
810
|
|
|
811
|
+
// src/errors/transaction.ts
|
|
812
|
+
class BroadcastError extends BaseError {
|
|
813
|
+
name = "BroadcastError";
|
|
814
|
+
txid;
|
|
815
|
+
reason;
|
|
816
|
+
reasonData;
|
|
817
|
+
constructor(message, options) {
|
|
818
|
+
super(message, options);
|
|
819
|
+
this.txid = options?.txid;
|
|
820
|
+
this.reason = options?.reason;
|
|
821
|
+
this.reasonData = options?.reasonData;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
class TransactionAbortedError extends BaseError {
|
|
826
|
+
name = "TransactionAbortedError";
|
|
827
|
+
receipt;
|
|
828
|
+
constructor(message, options) {
|
|
829
|
+
super(message, options);
|
|
830
|
+
this.receipt = options.receipt;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
class TransactionDroppedError extends BaseError {
|
|
835
|
+
name = "TransactionDroppedError";
|
|
836
|
+
txid;
|
|
837
|
+
constructor(message, options) {
|
|
838
|
+
super(message, options);
|
|
839
|
+
this.txid = options.txid;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
class WaitForTransactionTimeoutError extends BaseError {
|
|
844
|
+
name = "WaitForTransactionTimeoutError";
|
|
845
|
+
txid;
|
|
846
|
+
constructor(message, options) {
|
|
847
|
+
super(message, options);
|
|
848
|
+
this.txid = options.txid;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
class SerializationError extends BaseError {
|
|
853
|
+
name = "SerializationError";
|
|
854
|
+
}
|
|
855
|
+
|
|
799
856
|
// src/utils/bytes-reader.ts
|
|
800
857
|
class BytesReader {
|
|
801
858
|
data;
|
|
@@ -803,23 +860,32 @@ class BytesReader {
|
|
|
803
860
|
constructor(data) {
|
|
804
861
|
this.data = data;
|
|
805
862
|
}
|
|
863
|
+
remaining() {
|
|
864
|
+
return this.data.length - this.offset;
|
|
865
|
+
}
|
|
866
|
+
ensure(length) {
|
|
867
|
+
if (this.offset + length > this.data.length) {
|
|
868
|
+
throw new SerializationError(`Buffer underflow: need ${length} bytes at offset ${this.offset}, have ${this.data.length}`);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
806
871
|
readUInt8() {
|
|
872
|
+
this.ensure(1);
|
|
807
873
|
return this.data[this.offset++];
|
|
808
874
|
}
|
|
809
875
|
readUInt16BE() {
|
|
876
|
+
this.ensure(2);
|
|
810
877
|
const val = (this.data[this.offset] << 8 | this.data[this.offset + 1]) >>> 0;
|
|
811
878
|
this.offset += 2;
|
|
812
879
|
return val;
|
|
813
880
|
}
|
|
814
881
|
readUInt32BE() {
|
|
882
|
+
this.ensure(4);
|
|
815
883
|
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;
|
|
816
884
|
this.offset += 4;
|
|
817
885
|
return val;
|
|
818
886
|
}
|
|
819
887
|
readBytes(length) {
|
|
820
|
-
|
|
821
|
-
throw new Error(`Buffer underflow: need ${length} bytes at offset ${this.offset}, have ${this.data.length}`);
|
|
822
|
-
}
|
|
888
|
+
this.ensure(length);
|
|
823
889
|
const slice = this.data.slice(this.offset, this.offset + length);
|
|
824
890
|
this.offset += length;
|
|
825
891
|
return slice;
|
|
@@ -861,11 +927,33 @@ function publicKeyToAddress(publicKey, network = "mainnet") {
|
|
|
861
927
|
const version = network === "mainnet" ? AddressVersion.MainnetSingleSig : AddressVersion.TestnetSingleSig;
|
|
862
928
|
return c32address(version, bytesToHex(hash160(bytes)));
|
|
863
929
|
}
|
|
930
|
+
var CONTRACT_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/;
|
|
931
|
+
function validateStacksAddress(address) {
|
|
932
|
+
try {
|
|
933
|
+
c32addressDecode(address);
|
|
934
|
+
return true;
|
|
935
|
+
} catch {
|
|
936
|
+
return false;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
function parsePrincipal(value) {
|
|
940
|
+
const parts = value.split(".");
|
|
941
|
+
if (parts.length > 2)
|
|
942
|
+
return null;
|
|
943
|
+
const [address, contractName] = parts;
|
|
944
|
+
if (!validateStacksAddress(address))
|
|
945
|
+
return null;
|
|
946
|
+
if (contractName === undefined)
|
|
947
|
+
return { address };
|
|
948
|
+
if (!CONTRACT_NAME_REGEX.test(contractName))
|
|
949
|
+
return null;
|
|
950
|
+
return { address, contractName };
|
|
951
|
+
}
|
|
864
952
|
function parseContractId(contractId) {
|
|
865
|
-
const
|
|
866
|
-
if (!
|
|
953
|
+
const parsed = parsePrincipal(contractId);
|
|
954
|
+
if (!parsed?.contractName)
|
|
867
955
|
throw new Error(`Invalid contract identifier: ${contractId}`);
|
|
868
|
-
return [address,
|
|
956
|
+
return [parsed.address, parsed.contractName];
|
|
869
957
|
}
|
|
870
958
|
function isClarityName(name) {
|
|
871
959
|
const regex = /^[a-zA-Z]([a-zA-Z0-9]|[-_!?+<>=/*])*$|^[-+=/*]$|^[<>]=?$/;
|
|
@@ -954,10 +1042,10 @@ var Cl = {
|
|
|
954
1042
|
uint: uintCV,
|
|
955
1043
|
bool: boolCV,
|
|
956
1044
|
principal(address) {
|
|
957
|
-
const
|
|
958
|
-
if (!
|
|
959
|
-
throw new Error(
|
|
960
|
-
return
|
|
1045
|
+
const parsed = parsePrincipal(address);
|
|
1046
|
+
if (!parsed)
|
|
1047
|
+
throw new Error(`Invalid principal: ${address}`);
|
|
1048
|
+
return parsed.contractName ? contractPrincipalCV(parsed.address, parsed.contractName) : standardPrincipalCV(parsed.address);
|
|
961
1049
|
},
|
|
962
1050
|
address(address) {
|
|
963
1051
|
return Cl.principal(address);
|
|
@@ -995,7 +1083,18 @@ function readLPString(reader, prefixBytes = 1) {
|
|
|
995
1083
|
}
|
|
996
1084
|
return bytesToUtf8(reader.readBytes(length));
|
|
997
1085
|
}
|
|
998
|
-
|
|
1086
|
+
var MAX_CV_DEPTH = 64;
|
|
1087
|
+
var MIN_LIST_ITEM_BYTES = 1;
|
|
1088
|
+
var MIN_TUPLE_ENTRY_BYTES = 2;
|
|
1089
|
+
function checkCount(reader, count, minBytes) {
|
|
1090
|
+
if (count * minBytes > reader.remaining()) {
|
|
1091
|
+
throw new SerializationError(`Clarity value declares ${count} elements but only ${reader.remaining()} bytes remain`);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
function readCV(reader, depth = 0) {
|
|
1095
|
+
if (depth > MAX_CV_DEPTH) {
|
|
1096
|
+
throw new SerializationError(`Clarity value nests deeper than ${MAX_CV_DEPTH} levels`);
|
|
1097
|
+
}
|
|
999
1098
|
const typeByte = reader.readUInt8();
|
|
1000
1099
|
const type = clarityTypeFromByte(typeByte);
|
|
1001
1100
|
switch (type) {
|
|
@@ -1014,11 +1113,11 @@ function readCV(reader) {
|
|
|
1014
1113
|
case "none":
|
|
1015
1114
|
return noneCV();
|
|
1016
1115
|
case "some":
|
|
1017
|
-
return someCV(readCV(reader));
|
|
1116
|
+
return someCV(readCV(reader, depth + 1));
|
|
1018
1117
|
case "ok":
|
|
1019
|
-
return responseOkCV(readCV(reader));
|
|
1118
|
+
return responseOkCV(readCV(reader, depth + 1));
|
|
1020
1119
|
case "err":
|
|
1021
|
-
return responseErrorCV(readCV(reader));
|
|
1120
|
+
return responseErrorCV(readCV(reader, depth + 1));
|
|
1022
1121
|
case "address":
|
|
1023
1122
|
return standardPrincipalCV(readAddress(reader));
|
|
1024
1123
|
case "contract": {
|
|
@@ -1028,18 +1127,20 @@ function readCV(reader) {
|
|
|
1028
1127
|
}
|
|
1029
1128
|
case "list": {
|
|
1030
1129
|
const len = reader.readUInt32BE();
|
|
1130
|
+
checkCount(reader, len, MIN_LIST_ITEM_BYTES);
|
|
1031
1131
|
const items = [];
|
|
1032
1132
|
for (let i = 0;i < len; i++) {
|
|
1033
|
-
items.push(readCV(reader));
|
|
1133
|
+
items.push(readCV(reader, depth + 1));
|
|
1034
1134
|
}
|
|
1035
1135
|
return listCV(items);
|
|
1036
1136
|
}
|
|
1037
1137
|
case "tuple": {
|
|
1038
1138
|
const len = reader.readUInt32BE();
|
|
1139
|
+
checkCount(reader, len, MIN_TUPLE_ENTRY_BYTES);
|
|
1039
1140
|
const data = {};
|
|
1040
1141
|
for (let i = 0;i < len; i++) {
|
|
1041
1142
|
const key = readLPString(reader);
|
|
1042
|
-
data[key] = readCV(reader);
|
|
1143
|
+
data[key] = readCV(reader, depth + 1);
|
|
1043
1144
|
}
|
|
1044
1145
|
return tupleCV(data);
|
|
1045
1146
|
}
|
|
@@ -1052,7 +1153,7 @@ function readCV(reader) {
|
|
|
1052
1153
|
return stringUtf8CV(bytesToUtf8(reader.readBytes(len)));
|
|
1053
1154
|
}
|
|
1054
1155
|
default:
|
|
1055
|
-
throw new
|
|
1156
|
+
throw new SerializationError(`Cannot deserialize unknown clarity type: ${type}`);
|
|
1056
1157
|
}
|
|
1057
1158
|
}
|
|
1058
1159
|
function deserializeCVBytes(input) {
|
|
@@ -1064,12 +1165,209 @@ function deserializeCVBytes(input) {
|
|
|
1064
1165
|
class HttpRequestError extends BaseError {
|
|
1065
1166
|
name = "HttpRequestError";
|
|
1066
1167
|
status;
|
|
1168
|
+
url;
|
|
1169
|
+
method;
|
|
1067
1170
|
constructor(status, options) {
|
|
1068
|
-
|
|
1171
|
+
const where = options?.url !== undefined ? ` (${options.method ?? "GET"} ${options.url})` : "";
|
|
1172
|
+
super(`HTTP request failed with status ${status}${where}`, options);
|
|
1069
1173
|
this.status = status;
|
|
1174
|
+
this.url = options?.url;
|
|
1175
|
+
this.method = options?.method;
|
|
1070
1176
|
}
|
|
1071
1177
|
}
|
|
1072
1178
|
|
|
1179
|
+
// src/errors/transport.ts
|
|
1180
|
+
class TimeoutError extends BaseError {
|
|
1181
|
+
name = "TimeoutError";
|
|
1182
|
+
method;
|
|
1183
|
+
url;
|
|
1184
|
+
timeout;
|
|
1185
|
+
attempt;
|
|
1186
|
+
constructor(params) {
|
|
1187
|
+
super(`${params.method} ${params.url} did not complete within ${params.timeout}ms (attempt ${params.attempt + 1})`);
|
|
1188
|
+
this.method = params.method;
|
|
1189
|
+
this.url = params.url;
|
|
1190
|
+
this.timeout = params.timeout;
|
|
1191
|
+
this.attempt = params.attempt;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// src/transports/createTransport.ts
|
|
1196
|
+
function createTransport(type, config) {
|
|
1197
|
+
const { request, apiKey: _apiKey, ...exposed } = config;
|
|
1198
|
+
return {
|
|
1199
|
+
type,
|
|
1200
|
+
request,
|
|
1201
|
+
config: exposed
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
var MAX_ERROR_DETAILS_BYTES = 4096;
|
|
1205
|
+
function capDetails(body) {
|
|
1206
|
+
if (body === undefined)
|
|
1207
|
+
return;
|
|
1208
|
+
const bytes = new TextEncoder().encode(body);
|
|
1209
|
+
if (bytes.length <= MAX_ERROR_DETAILS_BYTES)
|
|
1210
|
+
return body;
|
|
1211
|
+
const head = new TextDecoder().decode(bytes.subarray(0, MAX_ERROR_DETAILS_BYTES));
|
|
1212
|
+
return `${head}... [truncated ${bytes.length - MAX_ERROR_DETAILS_BYTES} bytes]`;
|
|
1213
|
+
}
|
|
1214
|
+
function isRetryableStatus(status) {
|
|
1215
|
+
return status === 429 || status >= 500;
|
|
1216
|
+
}
|
|
1217
|
+
var MAX_RETRY_AFTER_MS = 60000;
|
|
1218
|
+
function retryAfterMs(response) {
|
|
1219
|
+
const value = response.headers.get("Retry-After");
|
|
1220
|
+
if (!value)
|
|
1221
|
+
return;
|
|
1222
|
+
const seconds = Number(value);
|
|
1223
|
+
const ms = Number.isFinite(seconds) ? seconds * 1000 : Date.parse(value) - Date.now();
|
|
1224
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > MAX_RETRY_AFTER_MS)
|
|
1225
|
+
return;
|
|
1226
|
+
return ms;
|
|
1227
|
+
}
|
|
1228
|
+
function abortReason(signal) {
|
|
1229
|
+
const reason = signal.reason;
|
|
1230
|
+
if (reason instanceof Error)
|
|
1231
|
+
return reason;
|
|
1232
|
+
return new DOMException(typeof reason === "string" ? reason : "The operation was aborted", "AbortError");
|
|
1233
|
+
}
|
|
1234
|
+
function sleep(ms, signal) {
|
|
1235
|
+
return new Promise((resolve, reject) => {
|
|
1236
|
+
if (signal?.aborted)
|
|
1237
|
+
return reject(abortReason(signal));
|
|
1238
|
+
const onAbort = () => {
|
|
1239
|
+
clearTimeout(id);
|
|
1240
|
+
reject(abortReason(signal));
|
|
1241
|
+
};
|
|
1242
|
+
const id = setTimeout(() => {
|
|
1243
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1244
|
+
resolve();
|
|
1245
|
+
}, ms);
|
|
1246
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
async function fetchWithRetry(url, options, retryCount, retryDelay, timeout, extra = {}) {
|
|
1250
|
+
const { signal } = extra;
|
|
1251
|
+
const read = extra.read ?? (async (response) => response);
|
|
1252
|
+
const method = options.method ?? "GET";
|
|
1253
|
+
let lastError;
|
|
1254
|
+
for (let attempt = 0;attempt <= retryCount; attempt++) {
|
|
1255
|
+
if (signal?.aborted)
|
|
1256
|
+
throw abortReason(signal);
|
|
1257
|
+
const controller = new AbortController;
|
|
1258
|
+
let timedOut = false;
|
|
1259
|
+
const timeoutId = setTimeout(() => {
|
|
1260
|
+
timedOut = true;
|
|
1261
|
+
controller.abort(new TimeoutError({ method, url, timeout, attempt }));
|
|
1262
|
+
}, timeout);
|
|
1263
|
+
const onCallerAbort = () => controller.abort(abortReason(signal));
|
|
1264
|
+
signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
1265
|
+
const aborted = new Promise((_, reject) => {
|
|
1266
|
+
if (controller.signal.aborted)
|
|
1267
|
+
return reject(controller.signal.reason);
|
|
1268
|
+
controller.signal.addEventListener("abort", () => reject(controller.signal.reason), { once: true });
|
|
1269
|
+
});
|
|
1270
|
+
let response;
|
|
1271
|
+
try {
|
|
1272
|
+
try {
|
|
1273
|
+
response = await Promise.race([
|
|
1274
|
+
fetch(url, { ...options, signal: controller.signal }),
|
|
1275
|
+
aborted
|
|
1276
|
+
]);
|
|
1277
|
+
} catch (error) {
|
|
1278
|
+
if (signal?.aborted)
|
|
1279
|
+
throw abortReason(signal);
|
|
1280
|
+
lastError = timedOut ? new TimeoutError({ method, url, timeout, attempt }) : error instanceof Error ? error : new Error(String(error));
|
|
1281
|
+
if (attempt < retryCount) {
|
|
1282
|
+
clearTimeout(timeoutId);
|
|
1283
|
+
await sleep(retryDelay * (attempt + 1), signal);
|
|
1284
|
+
continue;
|
|
1285
|
+
}
|
|
1286
|
+
throw lastError;
|
|
1287
|
+
}
|
|
1288
|
+
if (response.ok) {
|
|
1289
|
+
try {
|
|
1290
|
+
return await Promise.race([read(response), aborted]);
|
|
1291
|
+
} catch (error) {
|
|
1292
|
+
response.body?.cancel().catch(() => {});
|
|
1293
|
+
if (signal?.aborted)
|
|
1294
|
+
throw abortReason(signal);
|
|
1295
|
+
if (!timedOut)
|
|
1296
|
+
throw error;
|
|
1297
|
+
lastError = new TimeoutError({ method, url, timeout, attempt });
|
|
1298
|
+
if (attempt < retryCount) {
|
|
1299
|
+
clearTimeout(timeoutId);
|
|
1300
|
+
await sleep(retryDelay * (attempt + 1), signal);
|
|
1301
|
+
continue;
|
|
1302
|
+
}
|
|
1303
|
+
throw lastError;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
const retryable = isRetryableStatus(response.status);
|
|
1307
|
+
if (!retryable || attempt === retryCount) {
|
|
1308
|
+
const body = await Promise.race([
|
|
1309
|
+
response.text().catch(() => {
|
|
1310
|
+
return;
|
|
1311
|
+
}),
|
|
1312
|
+
aborted.catch(() => {
|
|
1313
|
+
return;
|
|
1314
|
+
})
|
|
1315
|
+
]);
|
|
1316
|
+
throw new HttpRequestError(response.status, {
|
|
1317
|
+
details: capDetails(body),
|
|
1318
|
+
url,
|
|
1319
|
+
method
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
lastError = new HttpRequestError(response.status, { url, method });
|
|
1323
|
+
const delay = retryAfterMs(response) ?? retryDelay * (attempt + 1);
|
|
1324
|
+
response.body?.cancel().catch(() => {});
|
|
1325
|
+
clearTimeout(timeoutId);
|
|
1326
|
+
await sleep(delay, signal);
|
|
1327
|
+
} finally {
|
|
1328
|
+
clearTimeout(timeoutId);
|
|
1329
|
+
signal?.removeEventListener("abort", onCallerAbort);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
throw lastError ?? new Error("Request failed");
|
|
1333
|
+
}
|
|
1334
|
+
async function readBody(response) {
|
|
1335
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
1336
|
+
if (contentType.includes("application/json")) {
|
|
1337
|
+
return response.json();
|
|
1338
|
+
}
|
|
1339
|
+
return response.text();
|
|
1340
|
+
}
|
|
1341
|
+
function buildRequestFn(baseUrl, config) {
|
|
1342
|
+
const {
|
|
1343
|
+
timeout = 30000,
|
|
1344
|
+
retryCount = 3,
|
|
1345
|
+
retryDelay = 150,
|
|
1346
|
+
fetchOptions = {},
|
|
1347
|
+
apiKey
|
|
1348
|
+
} = config;
|
|
1349
|
+
return async (path, options) => {
|
|
1350
|
+
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
1351
|
+
const headers = {
|
|
1352
|
+
"Content-Type": "application/json",
|
|
1353
|
+
...fetchOptions.headers,
|
|
1354
|
+
...options?.headers
|
|
1355
|
+
};
|
|
1356
|
+
if (apiKey) {
|
|
1357
|
+
headers["x-api-key"] = apiKey;
|
|
1358
|
+
}
|
|
1359
|
+
const init = {
|
|
1360
|
+
...fetchOptions,
|
|
1361
|
+
method: options?.method ?? "GET",
|
|
1362
|
+
headers
|
|
1363
|
+
};
|
|
1364
|
+
if (options?.body !== undefined) {
|
|
1365
|
+
init.body = JSON.stringify(options.body);
|
|
1366
|
+
}
|
|
1367
|
+
return fetchWithRetry(url, init, options?.retryCount ?? retryCount, retryDelay, timeout, { signal: options?.signal, read: readBody });
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1073
1371
|
// src/actions/public/txSources.ts
|
|
1074
1372
|
function normalizeTxid(txid) {
|
|
1075
1373
|
return txid.startsWith("0x") ? txid : `0x${txid}`;
|
|
@@ -1099,9 +1397,7 @@ function extendedApiSource() {
|
|
|
1099
1397
|
async get({ client, txid }) {
|
|
1100
1398
|
let data;
|
|
1101
1399
|
try {
|
|
1102
|
-
data = await client.request(`/extended/v1/tx/${normalizeTxid(txid)}`, {
|
|
1103
|
-
method: "GET"
|
|
1104
|
-
});
|
|
1400
|
+
data = await client.request(`/extended/v1/tx/${encodeURIComponent(normalizeTxid(txid))}`, { method: "GET" });
|
|
1105
1401
|
} catch (error) {
|
|
1106
1402
|
if (error instanceof HttpRequestError && error.status === 404) {
|
|
1107
1403
|
return { receipt: null };
|
|
@@ -1141,8 +1437,8 @@ async function readContract(client, params) {
|
|
|
1141
1437
|
const [address, name] = parseContractId(params.contract);
|
|
1142
1438
|
const sender = params.sender ?? address;
|
|
1143
1439
|
const serializedArgs = (params.args ?? []).map((arg) => with0x(bytesToHex(serializeCVBytes(arg))));
|
|
1144
|
-
const path = `/v2/contracts/call-read/${address}/${name}/${params.functionName}`;
|
|
1145
|
-
const data = await client.request(params.tip ? `${path}?tip=${params.tip}` : path, {
|
|
1440
|
+
const path = `/v2/contracts/call-read/${encodeURIComponent(address)}/${encodeURIComponent(name)}/${encodeURIComponent(params.functionName)}`;
|
|
1441
|
+
const data = await client.request(params.tip ? `${path}?tip=${encodeURIComponent(params.tip)}` : path, {
|
|
1146
1442
|
method: "POST",
|
|
1147
1443
|
body: {
|
|
1148
1444
|
sender,
|
|
@@ -1155,6 +1451,50 @@ async function readContract(client, params) {
|
|
|
1155
1451
|
throw new Error(data.cause ?? "Read-only call failed");
|
|
1156
1452
|
}
|
|
1157
1453
|
|
|
1454
|
+
// src/actions/wallet/utils.ts
|
|
1455
|
+
function isProviderAccount(account) {
|
|
1456
|
+
return account.type === "provider";
|
|
1457
|
+
}
|
|
1458
|
+
var FEE_TIERS = ["min", "low", "mid", "high"];
|
|
1459
|
+
var TIER_INDEX = { low: 0, mid: 1, high: 2 };
|
|
1460
|
+
function isFeeTier(fee) {
|
|
1461
|
+
return typeof fee === "string" && FEE_TIERS.includes(fee);
|
|
1462
|
+
}
|
|
1463
|
+
function minimumFee(transaction) {
|
|
1464
|
+
return BigInt(serializeTransaction(transaction).length);
|
|
1465
|
+
}
|
|
1466
|
+
function isNoEstimateAvailable(error) {
|
|
1467
|
+
return error instanceof HttpRequestError && error.status === 400 && (error.details?.includes("NoEstimateAvailable") ?? false);
|
|
1468
|
+
}
|
|
1469
|
+
async function resolveFee(client, transaction, fee) {
|
|
1470
|
+
if (fee !== undefined && !isFeeTier(fee))
|
|
1471
|
+
return { fee: intToBigInt(fee) };
|
|
1472
|
+
const tier = fee ?? "mid";
|
|
1473
|
+
if (tier === "min")
|
|
1474
|
+
return { fee: minimumFee(transaction), tier };
|
|
1475
|
+
let estimates;
|
|
1476
|
+
try {
|
|
1477
|
+
estimates = await estimateFee(client, { transaction });
|
|
1478
|
+
} catch (error) {
|
|
1479
|
+
if (!isNoEstimateAvailable(error))
|
|
1480
|
+
throw error;
|
|
1481
|
+
return { fee: minimumFee(transaction), tier: "min" };
|
|
1482
|
+
}
|
|
1483
|
+
const pick = estimates[TIER_INDEX[tier]] ?? estimates[estimates.length - 1];
|
|
1484
|
+
if (pick)
|
|
1485
|
+
return { fee: BigInt(pick.fee), tier };
|
|
1486
|
+
return { fee: minimumFee(transaction), tier: "min" };
|
|
1487
|
+
}
|
|
1488
|
+
function setUnsignedFee(transaction, fee) {
|
|
1489
|
+
transaction.auth.spendingCondition.fee = fee;
|
|
1490
|
+
clearTxCache(transaction);
|
|
1491
|
+
}
|
|
1492
|
+
function assertNoFeeTierForProvider(fee) {
|
|
1493
|
+
if (isFeeTier(fee)) {
|
|
1494
|
+
throw new Error(`Fee tier '${fee}' requires local signing; provider (wallet) accounts set their own fee`);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1158
1498
|
// src/clarity/abi/utils.ts
|
|
1159
1499
|
function toCamelCase(str) {
|
|
1160
1500
|
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/-([A-Z])/g, (_, letter) => letter).replace(/-(\d)/g, (_, digit) => digit).replace(/-/g, "").replace(/^\d/, "_$&");
|
|
@@ -1959,6 +2299,18 @@ async function getMapEntry(client, params) {
|
|
|
1959
2299
|
return deserializeCVBytes(data.data);
|
|
1960
2300
|
}
|
|
1961
2301
|
|
|
2302
|
+
// src/actions/public/getNonce.ts
|
|
2303
|
+
async function getNonce(client, params) {
|
|
2304
|
+
const data = await client.request(`/v2/accounts/${params.address}`, {
|
|
2305
|
+
method: "GET"
|
|
2306
|
+
});
|
|
2307
|
+
const nonce = data?.nonce;
|
|
2308
|
+
if (typeof nonce !== "number" && typeof nonce !== "string") {
|
|
2309
|
+
throw new Error(`getNonce: unexpected /v2/accounts response for ${params.address} (missing numeric nonce)`);
|
|
2310
|
+
}
|
|
2311
|
+
return BigInt(nonce);
|
|
2312
|
+
}
|
|
2313
|
+
|
|
1962
2314
|
// src/transactions/signer.ts
|
|
1963
2315
|
function txid(tx) {
|
|
1964
2316
|
return txidFromBytes(serializeTransaction(tx));
|
|
@@ -1991,70 +2343,17 @@ function getTransactionId(tx) {
|
|
|
1991
2343
|
return txid(tx);
|
|
1992
2344
|
}
|
|
1993
2345
|
|
|
1994
|
-
// src/errors/transaction.ts
|
|
1995
|
-
class BroadcastError extends BaseError {
|
|
1996
|
-
name = "BroadcastError";
|
|
1997
|
-
txid;
|
|
1998
|
-
reason;
|
|
1999
|
-
reasonData;
|
|
2000
|
-
constructor(message, options) {
|
|
2001
|
-
super(message, options);
|
|
2002
|
-
this.txid = options?.txid;
|
|
2003
|
-
this.reason = options?.reason;
|
|
2004
|
-
this.reasonData = options?.reasonData;
|
|
2005
|
-
}
|
|
2006
|
-
}
|
|
2007
|
-
|
|
2008
|
-
class TransactionAbortedError extends BaseError {
|
|
2009
|
-
name = "TransactionAbortedError";
|
|
2010
|
-
receipt;
|
|
2011
|
-
constructor(message, options) {
|
|
2012
|
-
super(message, options);
|
|
2013
|
-
this.receipt = options.receipt;
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
|
|
2017
|
-
class TransactionDroppedError extends BaseError {
|
|
2018
|
-
name = "TransactionDroppedError";
|
|
2019
|
-
txid;
|
|
2020
|
-
constructor(message, options) {
|
|
2021
|
-
super(message, options);
|
|
2022
|
-
this.txid = options.txid;
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
class WaitForTransactionTimeoutError extends BaseError {
|
|
2027
|
-
name = "WaitForTransactionTimeoutError";
|
|
2028
|
-
txid;
|
|
2029
|
-
constructor(message, options) {
|
|
2030
|
-
super(message, options);
|
|
2031
|
-
this.txid = options.txid;
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
// src/actions/public/getNonce.ts
|
|
2036
|
-
async function getNonce(client, params) {
|
|
2037
|
-
const data = await client.request(`/v2/accounts/${params.address}`, {
|
|
2038
|
-
method: "GET"
|
|
2039
|
-
});
|
|
2040
|
-
const nonce = data?.nonce;
|
|
2041
|
-
if (typeof nonce !== "number" && typeof nonce !== "string") {
|
|
2042
|
-
throw new Error(`getNonce: unexpected /v2/accounts response for ${params.address} (missing numeric nonce)`);
|
|
2043
|
-
}
|
|
2044
|
-
return BigInt(nonce);
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
2346
|
// src/actions/public/waitForTransactionReceipt.ts
|
|
2048
|
-
var
|
|
2347
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2049
2348
|
async function waitForTransactionReceipt(client, params) {
|
|
2050
2349
|
const {
|
|
2051
2350
|
txid: txid2,
|
|
2052
2351
|
confirmations = 1,
|
|
2053
2352
|
timeout = 180000,
|
|
2054
|
-
pollingInterval = 3000
|
|
2055
|
-
droppedGracePeriod = 30000
|
|
2353
|
+
pollingInterval = 3000
|
|
2056
2354
|
} = params;
|
|
2057
2355
|
const source = params.source ?? extendedApiSource();
|
|
2356
|
+
const droppedGracePeriod = params.droppedGracePeriod ?? (source.canonicalOnly ? timeout : 30000);
|
|
2058
2357
|
const startedAt = Date.now();
|
|
2059
2358
|
let unknownSince = null;
|
|
2060
2359
|
let everPending = false;
|
|
@@ -2092,7 +2391,7 @@ async function waitForTransactionReceipt(client, params) {
|
|
|
2092
2391
|
if (Date.now() - startedAt >= timeout) {
|
|
2093
2392
|
throw new WaitForTransactionTimeoutError(`Timed out after ${timeout}ms waiting for transaction ${txid2}`, { txid: txid2 });
|
|
2094
2393
|
}
|
|
2095
|
-
await
|
|
2394
|
+
await sleep2(pollingInterval);
|
|
2096
2395
|
}
|
|
2097
2396
|
}
|
|
2098
2397
|
|
|
@@ -2105,7 +2404,11 @@ async function sendTransaction(client, params) {
|
|
|
2105
2404
|
}
|
|
2106
2405
|
let data;
|
|
2107
2406
|
try {
|
|
2108
|
-
data = await client.request("/v2/transactions", {
|
|
2407
|
+
data = await client.request("/v2/transactions", {
|
|
2408
|
+
method: "POST",
|
|
2409
|
+
body,
|
|
2410
|
+
retryCount: 0
|
|
2411
|
+
});
|
|
2109
2412
|
} catch (error) {
|
|
2110
2413
|
if (error instanceof HttpRequestError && error.details) {
|
|
2111
2414
|
try {
|
|
@@ -2113,6 +2416,12 @@ async function sendTransaction(client, params) {
|
|
|
2113
2416
|
} catch {
|
|
2114
2417
|
throw error;
|
|
2115
2418
|
}
|
|
2419
|
+
} else if (error instanceof TimeoutError) {
|
|
2420
|
+
const txid3 = getTransactionId(params.transaction);
|
|
2421
|
+
const receipt = await getTransaction(client, { txid: txid3 }).catch(() => null);
|
|
2422
|
+
if (receipt === null)
|
|
2423
|
+
throw error;
|
|
2424
|
+
data = { txid: txid3 };
|
|
2116
2425
|
} else {
|
|
2117
2426
|
throw error;
|
|
2118
2427
|
}
|
|
@@ -2142,6 +2451,13 @@ async function resolveNonce(client, address) {
|
|
|
2142
2451
|
return client.nonceManager.consume({ client, address });
|
|
2143
2452
|
return getNonce(client, { address });
|
|
2144
2453
|
}
|
|
2454
|
+
async function releaseNonce(client, address, nonce) {
|
|
2455
|
+
if (!client.nonceManager)
|
|
2456
|
+
return;
|
|
2457
|
+
try {
|
|
2458
|
+
await client.nonceManager.release({ client, address, nonce });
|
|
2459
|
+
} catch {}
|
|
2460
|
+
}
|
|
2145
2461
|
function isNonceConflictError(error) {
|
|
2146
2462
|
if (!(error instanceof BroadcastError))
|
|
2147
2463
|
return false;
|
|
@@ -2166,42 +2482,6 @@ async function broadcastWithNonceReset(client, params) {
|
|
|
2166
2482
|
}
|
|
2167
2483
|
}
|
|
2168
2484
|
|
|
2169
|
-
// src/actions/wallet/utils.ts
|
|
2170
|
-
function isProviderAccount(account) {
|
|
2171
|
-
return account.type === "provider";
|
|
2172
|
-
}
|
|
2173
|
-
var FEE_TIERS = ["min", "low", "mid", "high"];
|
|
2174
|
-
var TIER_INDEX = { low: 0, mid: 1, high: 2 };
|
|
2175
|
-
function isFeeTier(fee) {
|
|
2176
|
-
return typeof fee === "string" && FEE_TIERS.includes(fee);
|
|
2177
|
-
}
|
|
2178
|
-
function minimumFee(transaction) {
|
|
2179
|
-
return BigInt(serializeTransaction(transaction).length);
|
|
2180
|
-
}
|
|
2181
|
-
async function resolveFee(client, transaction, fee) {
|
|
2182
|
-
if (fee !== undefined && !isFeeTier(fee))
|
|
2183
|
-
return intToBigInt(fee);
|
|
2184
|
-
const tier = fee ?? "mid";
|
|
2185
|
-
if (tier === "min")
|
|
2186
|
-
return minimumFee(transaction);
|
|
2187
|
-
try {
|
|
2188
|
-
const estimates = await estimateFee(client, { transaction });
|
|
2189
|
-
const pick = estimates[TIER_INDEX[tier]] ?? estimates[estimates.length - 1];
|
|
2190
|
-
if (pick)
|
|
2191
|
-
return BigInt(pick.fee);
|
|
2192
|
-
} catch {}
|
|
2193
|
-
return minimumFee(transaction);
|
|
2194
|
-
}
|
|
2195
|
-
function setUnsignedFee(transaction, fee) {
|
|
2196
|
-
transaction.auth.spendingCondition.fee = fee;
|
|
2197
|
-
clearTxCache(transaction);
|
|
2198
|
-
}
|
|
2199
|
-
function assertNoFeeTierForProvider(fee) {
|
|
2200
|
-
if (isFeeTier(fee)) {
|
|
2201
|
-
throw new Error(`Fee tier '${fee}' requires local signing; provider (wallet) accounts set their own fee`);
|
|
2202
|
-
}
|
|
2203
|
-
}
|
|
2204
|
-
|
|
2205
2485
|
// src/actions/wallet/callContract.ts
|
|
2206
2486
|
async function callContract(client, params) {
|
|
2207
2487
|
const account = client.account;
|
|
@@ -2217,28 +2497,36 @@ async function callContract(client, params) {
|
|
|
2217
2497
|
});
|
|
2218
2498
|
return result.txid;
|
|
2219
2499
|
}
|
|
2500
|
+
const managed = params.nonce === undefined && client.nonceManager !== undefined;
|
|
2220
2501
|
const nonce = params.nonce ?? await resolveNonce(client, account.address);
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2502
|
+
try {
|
|
2503
|
+
const needsFeeResolution = params.fee === undefined || isFeeTier(params.fee);
|
|
2504
|
+
const unsigned = buildContractCall({
|
|
2505
|
+
contractAddress,
|
|
2506
|
+
contractName,
|
|
2507
|
+
functionName: params.functionName,
|
|
2508
|
+
functionArgs: params.functionArgs ?? [],
|
|
2509
|
+
fee: needsFeeResolution ? 0n : params.fee,
|
|
2510
|
+
nonce,
|
|
2511
|
+
publicKey: account.publicKey,
|
|
2512
|
+
chain: client.chain,
|
|
2513
|
+
postConditionMode: params.postConditionMode,
|
|
2514
|
+
postConditions: params.postConditions
|
|
2515
|
+
});
|
|
2516
|
+
if (needsFeeResolution) {
|
|
2517
|
+
const { fee } = await resolveFee(client, unsigned, params.fee);
|
|
2518
|
+
setUnsignedFee(unsigned, fee);
|
|
2519
|
+
}
|
|
2520
|
+
const signed = await signTransactionWithAccount(unsigned, account);
|
|
2521
|
+
return await broadcastWithNonceReset(client, {
|
|
2522
|
+
transaction: signed,
|
|
2523
|
+
address: account.address
|
|
2524
|
+
});
|
|
2525
|
+
} catch (error) {
|
|
2526
|
+
if (managed)
|
|
2527
|
+
await releaseNonce(client, account.address, nonce);
|
|
2528
|
+
throw error;
|
|
2236
2529
|
}
|
|
2237
|
-
const signed = await signTransactionWithAccount(unsigned, account);
|
|
2238
|
-
return broadcastWithNonceReset(client, {
|
|
2239
|
-
transaction: signed,
|
|
2240
|
-
address: account.address
|
|
2241
|
-
});
|
|
2242
2530
|
}
|
|
2243
2531
|
|
|
2244
2532
|
// src/actions/getContract.ts
|
|
@@ -2318,7 +2606,9 @@ function getContract(params) {
|
|
|
2318
2606
|
}
|
|
2319
2607
|
const functionArgs = buildFunctionArgs(fn, args);
|
|
2320
2608
|
const network = client.chain?.network ?? "mainnet";
|
|
2321
|
-
const nonce = options?.nonce ?? await
|
|
2609
|
+
const nonce = options?.nonce ?? await getNonce(client, {
|
|
2610
|
+
address: publicKeyToAddress(publicKey, network)
|
|
2611
|
+
});
|
|
2322
2612
|
const unsigned = buildContractCall({
|
|
2323
2613
|
contractAddress: address,
|
|
2324
2614
|
contractName,
|
|
@@ -2333,13 +2623,8 @@ function getContract(params) {
|
|
|
2333
2623
|
sponsored: options?.sponsored
|
|
2334
2624
|
});
|
|
2335
2625
|
if (options?.fee === undefined) {
|
|
2336
|
-
const
|
|
2337
|
-
|
|
2338
|
-
});
|
|
2339
|
-
const mid = estimates[1] ?? estimates[0];
|
|
2340
|
-
if (mid) {
|
|
2341
|
-
setUnsignedFee(unsigned, BigInt(mid.fee));
|
|
2342
|
-
}
|
|
2626
|
+
const { fee } = await resolveFee(client, unsigned, undefined);
|
|
2627
|
+
setUnsignedFee(unsigned, fee);
|
|
2343
2628
|
}
|
|
2344
2629
|
return unsigned;
|
|
2345
2630
|
};
|
|
@@ -2415,6 +2700,56 @@ var SIP018_PREFIX = new Uint8Array([
|
|
|
2415
2700
|
49,
|
|
2416
2701
|
56
|
|
2417
2702
|
]);
|
|
2703
|
+
// src/clarity/prettyPrint.ts
|
|
2704
|
+
function cvToJSON(val) {
|
|
2705
|
+
switch (val.type) {
|
|
2706
|
+
case "true":
|
|
2707
|
+
return { type: "bool", value: true };
|
|
2708
|
+
case "false":
|
|
2709
|
+
return { type: "bool", value: false };
|
|
2710
|
+
case "int":
|
|
2711
|
+
return { type: "int", value: val.value.toString() };
|
|
2712
|
+
case "uint":
|
|
2713
|
+
return { type: "uint", value: val.value.toString() };
|
|
2714
|
+
case "buffer": {
|
|
2715
|
+
const hex = without0x(val.value);
|
|
2716
|
+
return {
|
|
2717
|
+
type: `(buff ${Math.ceil(hex.length / 2)})`,
|
|
2718
|
+
value: `0x${hex}`
|
|
2719
|
+
};
|
|
2720
|
+
}
|
|
2721
|
+
case "none":
|
|
2722
|
+
return { type: "(optional none)", value: null };
|
|
2723
|
+
case "some":
|
|
2724
|
+
return { type: "(optional)", value: cvToJSON(val.value) };
|
|
2725
|
+
case "ok":
|
|
2726
|
+
return { type: "(response)", value: cvToJSON(val.value), success: true };
|
|
2727
|
+
case "err":
|
|
2728
|
+
return { type: "(response)", value: cvToJSON(val.value), success: false };
|
|
2729
|
+
case "address":
|
|
2730
|
+
case "contract":
|
|
2731
|
+
return { type: "principal", value: val.value };
|
|
2732
|
+
case "list":
|
|
2733
|
+
return { type: "(list)", value: val.value.map(cvToJSON) };
|
|
2734
|
+
case "tuple": {
|
|
2735
|
+
const result = {};
|
|
2736
|
+
for (const key of Object.keys(val.value)) {
|
|
2737
|
+
result[key] = cvToJSON(val.value[key]);
|
|
2738
|
+
}
|
|
2739
|
+
return { type: "(tuple)", value: result };
|
|
2740
|
+
}
|
|
2741
|
+
case "ascii":
|
|
2742
|
+
return {
|
|
2743
|
+
type: `(string-ascii ${asciiToBytes(val.value).length})`,
|
|
2744
|
+
value: val.value
|
|
2745
|
+
};
|
|
2746
|
+
case "utf8":
|
|
2747
|
+
return {
|
|
2748
|
+
type: `(string-utf8 ${utf8ToBytes(val.value).length})`,
|
|
2749
|
+
value: val.value
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2418
2753
|
// src/clarity/abi/standards.ts
|
|
2419
2754
|
var SIP010_ABI = {
|
|
2420
2755
|
functions: [
|
|
@@ -3101,16 +3436,44 @@ async function getRawBlock(client, params) {
|
|
|
3101
3436
|
}
|
|
3102
3437
|
|
|
3103
3438
|
// src/actions/public/multicall.ts
|
|
3439
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
3440
|
+
const results = new Array(items.length);
|
|
3441
|
+
let cursor = 0;
|
|
3442
|
+
const worker = async () => {
|
|
3443
|
+
while (cursor < items.length) {
|
|
3444
|
+
const index = cursor++;
|
|
3445
|
+
try {
|
|
3446
|
+
results[index] = {
|
|
3447
|
+
status: "fulfilled",
|
|
3448
|
+
value: await fn(items[index])
|
|
3449
|
+
};
|
|
3450
|
+
} catch (reason) {
|
|
3451
|
+
results[index] = { status: "rejected", reason };
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
};
|
|
3455
|
+
const workers = Math.max(1, Math.min(limit, items.length));
|
|
3456
|
+
await Promise.all(Array.from({ length: workers }, worker));
|
|
3457
|
+
return results;
|
|
3458
|
+
}
|
|
3104
3459
|
async function multicall(client, params) {
|
|
3105
|
-
const { calls, allowFailure = true } = params;
|
|
3460
|
+
const { calls, allowFailure = true, concurrency = 8 } = params;
|
|
3461
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
3462
|
+
throw new RangeError(`multicall concurrency must be a positive integer, got ${concurrency}`);
|
|
3463
|
+
}
|
|
3464
|
+
const settled = await mapWithConcurrency(calls, concurrency, (call) => readContract(client, call));
|
|
3106
3465
|
if (allowFailure) {
|
|
3107
|
-
const settled = await Promise.allSettled(calls.map((call) => readContract(client, call)));
|
|
3108
3466
|
return settled.map((r) => r.status === "fulfilled" ? { status: "success", result: r.value } : {
|
|
3109
3467
|
status: "failure",
|
|
3110
3468
|
error: r.reason instanceof Error ? r.reason : new Error(String(r.reason))
|
|
3111
3469
|
});
|
|
3112
3470
|
}
|
|
3113
|
-
const results =
|
|
3471
|
+
const results = [];
|
|
3472
|
+
for (const r of settled) {
|
|
3473
|
+
if (r.status === "rejected")
|
|
3474
|
+
throw r.reason;
|
|
3475
|
+
results.push(r.value);
|
|
3476
|
+
}
|
|
3114
3477
|
return results;
|
|
3115
3478
|
}
|
|
3116
3479
|
|
|
@@ -3272,100 +3635,6 @@ function createPublicClient(config) {
|
|
|
3272
3635
|
return createClient(config).extend(publicActions);
|
|
3273
3636
|
}
|
|
3274
3637
|
|
|
3275
|
-
// src/transports/createTransport.ts
|
|
3276
|
-
function createTransport(type, config) {
|
|
3277
|
-
return {
|
|
3278
|
-
type,
|
|
3279
|
-
request: config.request,
|
|
3280
|
-
config
|
|
3281
|
-
};
|
|
3282
|
-
}
|
|
3283
|
-
function isRetryableStatus(status) {
|
|
3284
|
-
return status === 429 || status >= 500;
|
|
3285
|
-
}
|
|
3286
|
-
var MAX_RETRY_AFTER_MS = 60000;
|
|
3287
|
-
function retryAfterMs(response) {
|
|
3288
|
-
const value = response.headers.get("Retry-After");
|
|
3289
|
-
if (!value)
|
|
3290
|
-
return;
|
|
3291
|
-
const seconds = Number(value);
|
|
3292
|
-
const ms = Number.isFinite(seconds) ? seconds * 1000 : Date.parse(value) - Date.now();
|
|
3293
|
-
if (!Number.isFinite(ms) || ms < 0 || ms > MAX_RETRY_AFTER_MS)
|
|
3294
|
-
return;
|
|
3295
|
-
return ms;
|
|
3296
|
-
}
|
|
3297
|
-
async function fetchWithRetry(url, options, retryCount, retryDelay, timeout) {
|
|
3298
|
-
let lastError;
|
|
3299
|
-
for (let attempt = 0;attempt <= retryCount; attempt++) {
|
|
3300
|
-
let response;
|
|
3301
|
-
try {
|
|
3302
|
-
const controller = new AbortController;
|
|
3303
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
3304
|
-
response = await fetch(url, {
|
|
3305
|
-
...options,
|
|
3306
|
-
signal: controller.signal
|
|
3307
|
-
});
|
|
3308
|
-
clearTimeout(timeoutId);
|
|
3309
|
-
} catch (error) {
|
|
3310
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
3311
|
-
if (attempt < retryCount) {
|
|
3312
|
-
await new Promise((r) => setTimeout(r, retryDelay * (attempt + 1)));
|
|
3313
|
-
continue;
|
|
3314
|
-
}
|
|
3315
|
-
throw lastError;
|
|
3316
|
-
}
|
|
3317
|
-
if (response.ok) {
|
|
3318
|
-
return response;
|
|
3319
|
-
}
|
|
3320
|
-
const retryable = isRetryableStatus(response.status);
|
|
3321
|
-
if (!retryable || attempt === retryCount) {
|
|
3322
|
-
throw new HttpRequestError(response.status, {
|
|
3323
|
-
details: await response.text().catch(() => {
|
|
3324
|
-
return;
|
|
3325
|
-
})
|
|
3326
|
-
});
|
|
3327
|
-
}
|
|
3328
|
-
lastError = new HttpRequestError(response.status);
|
|
3329
|
-
const delay = retryAfterMs(response) ?? retryDelay * (attempt + 1);
|
|
3330
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
3331
|
-
}
|
|
3332
|
-
throw lastError ?? new Error("Request failed");
|
|
3333
|
-
}
|
|
3334
|
-
function buildRequestFn(baseUrl, config) {
|
|
3335
|
-
const {
|
|
3336
|
-
timeout = 30000,
|
|
3337
|
-
retryCount = 3,
|
|
3338
|
-
retryDelay = 150,
|
|
3339
|
-
fetchOptions = {},
|
|
3340
|
-
apiKey
|
|
3341
|
-
} = config;
|
|
3342
|
-
return async (path, options) => {
|
|
3343
|
-
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
3344
|
-
const headers = {
|
|
3345
|
-
"Content-Type": "application/json",
|
|
3346
|
-
...fetchOptions.headers,
|
|
3347
|
-
...options?.headers
|
|
3348
|
-
};
|
|
3349
|
-
if (apiKey) {
|
|
3350
|
-
headers["x-api-key"] = apiKey;
|
|
3351
|
-
}
|
|
3352
|
-
const init = {
|
|
3353
|
-
...fetchOptions,
|
|
3354
|
-
method: options?.method ?? "GET",
|
|
3355
|
-
headers
|
|
3356
|
-
};
|
|
3357
|
-
if (options?.body !== undefined) {
|
|
3358
|
-
init.body = JSON.stringify(options.body);
|
|
3359
|
-
}
|
|
3360
|
-
const response = await fetchWithRetry(url, init, retryCount, retryDelay, timeout);
|
|
3361
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
3362
|
-
if (contentType.includes("application/json")) {
|
|
3363
|
-
return response.json();
|
|
3364
|
-
}
|
|
3365
|
-
return response.text();
|
|
3366
|
-
};
|
|
3367
|
-
}
|
|
3368
|
-
|
|
3369
3638
|
// src/transports/http.ts
|
|
3370
3639
|
function http(url, config) {
|
|
3371
3640
|
return (params) => {
|
|
@@ -3386,36 +3655,47 @@ var _defaultClient = null;
|
|
|
3386
3655
|
function getDefaultPublicClient() {
|
|
3387
3656
|
if (_defaultClient)
|
|
3388
3657
|
return _defaultClient;
|
|
3389
|
-
const
|
|
3658
|
+
const network = process.env.STACKS_NETWORK ?? process.env.STACKS_CHAIN;
|
|
3659
|
+
const chain = network === "testnet" ? testnet : mainnet;
|
|
3660
|
+
const url = process.env.STACKS_NODE_RPC_URL ?? process.env.SL_API_URL ?? process.env.STACKS_RPC_URL;
|
|
3390
3661
|
_defaultClient = createPublicClient({
|
|
3391
3662
|
chain,
|
|
3392
|
-
transport: http(
|
|
3663
|
+
transport: http(url)
|
|
3393
3664
|
});
|
|
3394
3665
|
return _defaultClient;
|
|
3395
3666
|
}
|
|
3396
3667
|
|
|
3397
3668
|
// src/tools/index.ts
|
|
3398
|
-
var PRINCIPAL = import_zod.z.string().
|
|
3399
|
-
|
|
3400
|
-
|
|
3669
|
+
var PRINCIPAL = import_zod.z.string().refine((v) => parsePrincipal(v) !== null, {
|
|
3670
|
+
message: "Expected a Stacks principal: a c32 address (SP…/SM… mainnet, ST… testnet), optionally followed by .contract-name"
|
|
3671
|
+
}).describe("Stacks principal (SP…/SM… mainnet, ST… testnet)");
|
|
3672
|
+
var CONTRACT_ID = import_zod.z.string().refine((v) => parsePrincipal(v)?.contractName !== undefined, {
|
|
3673
|
+
message: "Expected a contract id in '{address}.{name}' form"
|
|
3674
|
+
}).describe("Fully-qualified contract id: '{address}.{name}'");
|
|
3675
|
+
var FUNCTION_NAME = import_zod.z.string().refine(isClarityName, { message: "Expected a Clarity function name" });
|
|
3676
|
+
var HASH_32 = /^(0x)?[0-9a-fA-F]{64}$/;
|
|
3677
|
+
var TX_ID = import_zod.z.string().regex(HASH_32, "Expected a 32-byte hex transaction id").describe("Transaction id, with or without 0x prefix");
|
|
3678
|
+
var BLOCK_HASH = import_zod.z.string().regex(HASH_32, "Expected a 32-byte hex block hash");
|
|
3679
|
+
async function stxBalance(resolve, principal) {
|
|
3680
|
+
const balance = await getBalance(resolve(), { address: principal });
|
|
3401
3681
|
return { microStx: balance.toString() };
|
|
3402
3682
|
}
|
|
3403
|
-
async function accountInfo(
|
|
3404
|
-
const info = await getAccountInfo(
|
|
3683
|
+
async function accountInfo(resolve, principal) {
|
|
3684
|
+
const info = await getAccountInfo(resolve(), { address: principal });
|
|
3405
3685
|
return {
|
|
3406
3686
|
balance: info.balance.toString(),
|
|
3407
3687
|
nonce: info.nonce.toString()
|
|
3408
3688
|
};
|
|
3409
3689
|
}
|
|
3410
|
-
async function block(
|
|
3411
|
-
return getBlock(
|
|
3690
|
+
async function block(resolve, args) {
|
|
3691
|
+
return getBlock(resolve(), args);
|
|
3412
3692
|
}
|
|
3413
|
-
async function blockHeight(
|
|
3414
|
-
return { height: await getBlockHeight(
|
|
3693
|
+
async function blockHeight(resolve) {
|
|
3694
|
+
return { height: await getBlockHeight(resolve()) };
|
|
3415
3695
|
}
|
|
3416
|
-
async function contractRead(
|
|
3417
|
-
const result = await readContract(
|
|
3418
|
-
return { result:
|
|
3696
|
+
async function contractRead(resolve, args) {
|
|
3697
|
+
const result = await readContract(resolve(), args);
|
|
3698
|
+
return { result: cvToJSON(result) };
|
|
3419
3699
|
}
|
|
3420
3700
|
function assertValidHex(raw) {
|
|
3421
3701
|
if (raw.length % 2 !== 0) {
|
|
@@ -3425,199 +3705,156 @@ function assertValidHex(raw) {
|
|
|
3425
3705
|
throw new Error("serializedTxHex: contains non-hex characters");
|
|
3426
3706
|
}
|
|
3427
3707
|
}
|
|
3428
|
-
async function fee(
|
|
3708
|
+
async function fee(resolve, serializedTxHex) {
|
|
3429
3709
|
const raw = serializedTxHex.startsWith("0x") ? serializedTxHex.slice(2) : serializedTxHex;
|
|
3430
3710
|
assertValidHex(raw);
|
|
3431
|
-
const txBytes =
|
|
3711
|
+
const txBytes = hexToBytes(raw);
|
|
3432
3712
|
let transaction;
|
|
3433
3713
|
try {
|
|
3434
3714
|
transaction = deserializeTransaction(txBytes);
|
|
3435
3715
|
} catch (e) {
|
|
3436
|
-
throw new Error(`serializedTxHex: deserialization failed
|
|
3716
|
+
throw new Error(`serializedTxHex: deserialization failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
3437
3717
|
}
|
|
3438
|
-
const fees = await estimateFee(
|
|
3439
|
-
|
|
3440
|
-
|
|
3718
|
+
const fees = await estimateFee(resolve(), { transaction });
|
|
3719
|
+
if (fees.length === 0) {
|
|
3720
|
+
const min = Number(minimumFee(transaction));
|
|
3721
|
+
return {
|
|
3722
|
+
low: min,
|
|
3723
|
+
medium: min,
|
|
3724
|
+
high: min,
|
|
3725
|
+
source: "min",
|
|
3726
|
+
tiers: 0
|
|
3727
|
+
};
|
|
3728
|
+
}
|
|
3729
|
+
const low = fees[0]?.fee ?? 0;
|
|
3441
3730
|
return {
|
|
3442
|
-
low
|
|
3443
|
-
medium: fees[1]?.fee ??
|
|
3444
|
-
high: fees[2]?.fee ??
|
|
3731
|
+
low,
|
|
3732
|
+
medium: fees[1]?.fee ?? low,
|
|
3733
|
+
high: fees[2]?.fee ?? fees[1]?.fee ?? low,
|
|
3734
|
+
source: "node",
|
|
3735
|
+
tiers: fees.length
|
|
3445
3736
|
};
|
|
3446
3737
|
}
|
|
3447
|
-
async function bnsResolveImpl(
|
|
3448
|
-
return { owner: await resolveName(
|
|
3738
|
+
async function bnsResolveImpl(resolve, name) {
|
|
3739
|
+
return { owner: await resolveName(resolve(), name) };
|
|
3449
3740
|
}
|
|
3450
|
-
async function bnsReverseImpl(
|
|
3451
|
-
return { name: await getPrimaryName(
|
|
3741
|
+
async function bnsReverseImpl(resolve, principal) {
|
|
3742
|
+
return { name: await getPrimaryName(resolve(), principal) };
|
|
3452
3743
|
}
|
|
3453
|
-
async function transactionByTxId(
|
|
3454
|
-
|
|
3744
|
+
async function transactionByTxId(resolve, txId) {
|
|
3745
|
+
const receipt = await getTransaction(resolve(), { txid: txId });
|
|
3746
|
+
if (!receipt)
|
|
3747
|
+
return null;
|
|
3748
|
+
const { result, ...rest } = receipt;
|
|
3749
|
+
return result === undefined ? rest : { ...rest, result: cvToJSON(result) };
|
|
3455
3750
|
}
|
|
3456
|
-
async function accountHistory(
|
|
3457
|
-
return getAccountHistory(
|
|
3751
|
+
async function accountHistory(resolve, principal, limit) {
|
|
3752
|
+
return getAccountHistory(resolve(), { address: principal, limit });
|
|
3458
3753
|
}
|
|
3459
|
-
async function mempoolStats(
|
|
3460
|
-
return getMempoolStats(
|
|
3754
|
+
async function mempoolStats(resolve) {
|
|
3755
|
+
return getMempoolStats(resolve());
|
|
3461
3756
|
}
|
|
3462
|
-
async function nftHoldings(
|
|
3463
|
-
return getNftHoldings(
|
|
3757
|
+
async function nftHoldings(resolve, principal, limit) {
|
|
3758
|
+
return getNftHoldings(resolve(), { address: principal, limit });
|
|
3464
3759
|
}
|
|
3465
|
-
|
|
3760
|
+
var EXTENDED = "Needs a host that serves the extended API.";
|
|
3761
|
+
function buildTools(resolve) {
|
|
3466
3762
|
return {
|
|
3467
3763
|
getStxBalance: import_ai.tool({
|
|
3468
3764
|
description: "Get the STX balance (in micro-STX) for a Stacks principal.",
|
|
3469
3765
|
inputSchema: import_zod.z.object({ principal: PRINCIPAL }),
|
|
3470
|
-
execute: ({ principal }) => stxBalance(
|
|
3766
|
+
execute: ({ principal }) => stxBalance(resolve, principal)
|
|
3471
3767
|
}),
|
|
3472
3768
|
getAccountInfo: import_ai.tool({
|
|
3473
|
-
description: "Get
|
|
3769
|
+
description: "Get the STX balance (micro-STX) and next nonce for a Stacks principal.",
|
|
3474
3770
|
inputSchema: import_zod.z.object({ principal: PRINCIPAL }),
|
|
3475
|
-
execute: ({ principal }) => accountInfo(
|
|
3771
|
+
execute: ({ principal }) => accountInfo(resolve, principal)
|
|
3476
3772
|
}),
|
|
3477
3773
|
getBlock: import_ai.tool({
|
|
3478
|
-
description: "Fetch
|
|
3774
|
+
description: "Fetch one Stacks block by height or hash. Omit both for the latest block. Always returns a single block object.",
|
|
3479
3775
|
inputSchema: import_zod.z.object({
|
|
3480
3776
|
height: import_zod.z.number().int().nonnegative().optional(),
|
|
3481
|
-
hash:
|
|
3777
|
+
hash: BLOCK_HASH.optional()
|
|
3482
3778
|
}),
|
|
3483
|
-
execute: (args) => block(
|
|
3779
|
+
execute: (args) => block(resolve, args)
|
|
3484
3780
|
}),
|
|
3485
3781
|
getBlockHeight: import_ai.tool({
|
|
3486
3782
|
description: "Get the current Stacks chain tip height.",
|
|
3487
3783
|
inputSchema: import_zod.z.object({}),
|
|
3488
|
-
execute: () => blockHeight(
|
|
3784
|
+
execute: () => blockHeight(resolve)
|
|
3489
3785
|
}),
|
|
3490
3786
|
readContract: import_ai.tool({
|
|
3491
|
-
description: "Call a read-only Clarity function. Returns the decoded value as JSON.",
|
|
3787
|
+
description: "Call a read-only Clarity function that takes no arguments. Returns the decoded value as JSON; uint and int arrive as decimal strings.",
|
|
3492
3788
|
inputSchema: import_zod.z.object({
|
|
3493
|
-
contract:
|
|
3494
|
-
functionName:
|
|
3789
|
+
contract: CONTRACT_ID,
|
|
3790
|
+
functionName: FUNCTION_NAME,
|
|
3495
3791
|
sender: PRINCIPAL.optional()
|
|
3496
3792
|
}),
|
|
3497
|
-
execute: (args) => contractRead(
|
|
3793
|
+
execute: (args) => contractRead(resolve, args)
|
|
3498
3794
|
}),
|
|
3499
3795
|
estimateFee: import_ai.tool({
|
|
3500
|
-
description: "Estimate fee
|
|
3796
|
+
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.",
|
|
3501
3797
|
inputSchema: import_zod.z.object({
|
|
3502
3798
|
serializedTxHex: import_zod.z.string().describe("Hex-encoded serialized transaction")
|
|
3503
3799
|
}),
|
|
3504
|
-
execute: ({ serializedTxHex }) => fee(
|
|
3800
|
+
execute: ({ serializedTxHex }) => fee(resolve, serializedTxHex)
|
|
3505
3801
|
}),
|
|
3506
3802
|
bnsResolve: import_ai.tool({
|
|
3507
3803
|
description: "Resolve a BNS name (e.g. 'satoshi.btc') to its owning Stacks principal.",
|
|
3508
3804
|
inputSchema: import_zod.z.object({
|
|
3509
3805
|
name: import_zod.z.string().describe("BNS name in 'name.namespace' form")
|
|
3510
3806
|
}),
|
|
3511
|
-
execute: ({ name }) => bnsResolveImpl(
|
|
3807
|
+
execute: ({ name }) => bnsResolveImpl(resolve, name)
|
|
3512
3808
|
}),
|
|
3513
3809
|
bnsReverse: import_ai.tool({
|
|
3514
3810
|
description: "Reverse-lookup the primary BNS name for a Stacks principal, if set.",
|
|
3515
3811
|
inputSchema: import_zod.z.object({ principal: PRINCIPAL }),
|
|
3516
|
-
execute: ({ principal }) => bnsReverseImpl(
|
|
3812
|
+
execute: ({ principal }) => bnsReverseImpl(resolve, principal)
|
|
3517
3813
|
}),
|
|
3518
3814
|
getTransaction: import_ai.tool({
|
|
3519
|
-
description:
|
|
3520
|
-
inputSchema: import_zod.z.object({
|
|
3521
|
-
|
|
3522
|
-
}),
|
|
3523
|
-
execute: ({ txId }) => transactionByTxId(client, txId)
|
|
3815
|
+
description: `Fetch a confirmed Stacks transaction by txId, with its decoded result as JSON. ${EXTENDED}`,
|
|
3816
|
+
inputSchema: import_zod.z.object({ txId: TX_ID }),
|
|
3817
|
+
execute: ({ txId }) => transactionByTxId(resolve, txId)
|
|
3524
3818
|
}),
|
|
3525
3819
|
getAccountHistory: import_ai.tool({
|
|
3526
|
-
description:
|
|
3820
|
+
description: `List the most recent transactions for a Stacks principal (first page only, up to 50). ${EXTENDED}`,
|
|
3527
3821
|
inputSchema: import_zod.z.object({
|
|
3528
3822
|
principal: PRINCIPAL,
|
|
3529
3823
|
limit: import_zod.z.number().int().min(1).max(50).default(20)
|
|
3530
3824
|
}),
|
|
3531
|
-
execute: ({ principal, limit }) => accountHistory(
|
|
3825
|
+
execute: ({ principal, limit }) => accountHistory(resolve, principal, limit)
|
|
3532
3826
|
}),
|
|
3533
3827
|
getMempoolStats: import_ai.tool({
|
|
3534
|
-
description:
|
|
3828
|
+
description: `Current mempool statistics: pending count, fee distribution, age buckets. ${EXTENDED}`,
|
|
3535
3829
|
inputSchema: import_zod.z.object({}),
|
|
3536
|
-
execute: () => mempoolStats(
|
|
3830
|
+
execute: () => mempoolStats(resolve)
|
|
3537
3831
|
}),
|
|
3538
3832
|
getNftHoldings: import_ai.tool({
|
|
3539
|
-
description:
|
|
3833
|
+
description: `List NFTs held by a Stacks principal across all collections (first page only, up to 50). ${EXTENDED}`,
|
|
3540
3834
|
inputSchema: import_zod.z.object({
|
|
3541
3835
|
principal: PRINCIPAL,
|
|
3542
3836
|
limit: import_zod.z.number().int().min(1).max(50).default(20)
|
|
3543
3837
|
}),
|
|
3544
|
-
execute: ({ principal, limit }) => nftHoldings(
|
|
3838
|
+
execute: ({ principal, limit }) => nftHoldings(resolve, principal, limit)
|
|
3545
3839
|
})
|
|
3546
3840
|
};
|
|
3547
3841
|
}
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
var getAccountInfo2 =
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
var
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
var getBlockHeight2 = import_ai.tool({
|
|
3567
|
-
description: "Get the current Stacks chain tip height.",
|
|
3568
|
-
inputSchema: import_zod.z.object({}),
|
|
3569
|
-
execute: () => blockHeight(getDefaultPublicClient())
|
|
3570
|
-
});
|
|
3571
|
-
var readContract2 = import_ai.tool({
|
|
3572
|
-
description: "Call a read-only Clarity function. Returns the decoded value as JSON.",
|
|
3573
|
-
inputSchema: import_zod.z.object({
|
|
3574
|
-
contract: import_zod.z.string(),
|
|
3575
|
-
functionName: import_zod.z.string(),
|
|
3576
|
-
sender: PRINCIPAL.optional()
|
|
3577
|
-
}),
|
|
3578
|
-
execute: (args) => contractRead(getDefaultPublicClient(), args)
|
|
3579
|
-
});
|
|
3580
|
-
var estimateFee2 = import_ai.tool({
|
|
3581
|
-
description: "Estimate fee range (low / medium / high) for a serialized Stacks transaction.",
|
|
3582
|
-
inputSchema: import_zod.z.object({ serializedTxHex: import_zod.z.string() }),
|
|
3583
|
-
execute: ({ serializedTxHex }) => fee(getDefaultPublicClient(), serializedTxHex)
|
|
3584
|
-
});
|
|
3585
|
-
var bnsResolve = import_ai.tool({
|
|
3586
|
-
description: "Resolve a BNS name (e.g. 'satoshi.btc') to its owning Stacks principal.",
|
|
3587
|
-
inputSchema: import_zod.z.object({ name: import_zod.z.string() }),
|
|
3588
|
-
execute: ({ name }) => bnsResolveImpl(getDefaultPublicClient(), name)
|
|
3589
|
-
});
|
|
3590
|
-
var bnsReverse = import_ai.tool({
|
|
3591
|
-
description: "Reverse-lookup the primary BNS name for a Stacks principal, if set.",
|
|
3592
|
-
inputSchema: import_zod.z.object({ principal: PRINCIPAL }),
|
|
3593
|
-
execute: ({ principal }) => bnsReverseImpl(getDefaultPublicClient(), principal)
|
|
3594
|
-
});
|
|
3595
|
-
var getTransaction2 = import_ai.tool({
|
|
3596
|
-
description: "Fetch a confirmed Stacks transaction by txId (Hiro extended API).",
|
|
3597
|
-
inputSchema: import_zod.z.object({ txId: import_zod.z.string() }),
|
|
3598
|
-
execute: ({ txId }) => transactionByTxId(getDefaultPublicClient(), txId)
|
|
3599
|
-
});
|
|
3600
|
-
var getAccountHistory2 = import_ai.tool({
|
|
3601
|
-
description: "Paginated transaction history for a Stacks principal (Hiro extended API).",
|
|
3602
|
-
inputSchema: import_zod.z.object({
|
|
3603
|
-
principal: PRINCIPAL,
|
|
3604
|
-
limit: import_zod.z.number().int().min(1).max(50).default(20)
|
|
3605
|
-
}),
|
|
3606
|
-
execute: ({ principal, limit }) => accountHistory(getDefaultPublicClient(), principal, limit)
|
|
3607
|
-
});
|
|
3608
|
-
var getMempoolStats2 = import_ai.tool({
|
|
3609
|
-
description: "Current mempool statistics: pending count, fee distribution, age buckets (Hiro extended API).",
|
|
3610
|
-
inputSchema: import_zod.z.object({}),
|
|
3611
|
-
execute: () => mempoolStats(getDefaultPublicClient())
|
|
3612
|
-
});
|
|
3613
|
-
var getNftHoldings2 = import_ai.tool({
|
|
3614
|
-
description: "NFT holdings for a Stacks principal across all collections (Hiro extended API).",
|
|
3615
|
-
inputSchema: import_zod.z.object({
|
|
3616
|
-
principal: PRINCIPAL,
|
|
3617
|
-
limit: import_zod.z.number().int().min(1).max(50).default(20)
|
|
3618
|
-
}),
|
|
3619
|
-
execute: ({ principal, limit }) => nftHoldings(getDefaultPublicClient(), principal, limit)
|
|
3620
|
-
});
|
|
3621
|
-
|
|
3622
|
-
//# debugId=A0859ACF613066D264756E2164756E21
|
|
3842
|
+
function createStacksTools(client) {
|
|
3843
|
+
return buildTools(() => client);
|
|
3844
|
+
}
|
|
3845
|
+
var defaultTools = buildTools(getDefaultPublicClient);
|
|
3846
|
+
var getStxBalance = defaultTools.getStxBalance;
|
|
3847
|
+
var getAccountInfo2 = defaultTools.getAccountInfo;
|
|
3848
|
+
var getBlock2 = defaultTools.getBlock;
|
|
3849
|
+
var getBlockHeight2 = defaultTools.getBlockHeight;
|
|
3850
|
+
var readContract2 = defaultTools.readContract;
|
|
3851
|
+
var estimateFee2 = defaultTools.estimateFee;
|
|
3852
|
+
var bnsResolve = defaultTools.bnsResolve;
|
|
3853
|
+
var bnsReverse = defaultTools.bnsReverse;
|
|
3854
|
+
var getTransaction2 = defaultTools.getTransaction;
|
|
3855
|
+
var getAccountHistory2 = defaultTools.getAccountHistory;
|
|
3856
|
+
var getMempoolStats2 = defaultTools.getMempoolStats;
|
|
3857
|
+
var getNftHoldings2 = defaultTools.getNftHoldings;
|
|
3858
|
+
|
|
3859
|
+
//# debugId=BA352497F272866664756E2164756E21
|
|
3623
3860
|
//# sourceMappingURL=index.cjs.map
|