@secondlayer/stacks 4.3.1 → 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.
Files changed (164) hide show
  1. package/README.md +27 -11
  2. package/dist/shared/{stacks-gxq2pbky.js → stacks-2as26bcg.js} +10 -7
  3. package/dist/shared/stacks-2as26bcg.js.map +13 -0
  4. package/dist/shared/{stacks-bfan7ex7.js → stacks-4d7c3x27.js} +5 -5
  5. package/dist/shared/{stacks-bfan7ex7.js.map → stacks-4d7c3x27.js.map} +3 -3
  6. package/dist/shared/{stacks-709tra19.js → stacks-4hs8r4q2.js} +16 -2
  7. package/dist/shared/stacks-4hs8r4q2.js.map +10 -0
  8. package/dist/shared/{stacks-w23294am.js → stacks-51ybf135.js} +3 -3
  9. package/dist/shared/{stacks-0jk7vd8r.cjs → stacks-69nq48jp.js} +120 -17
  10. package/dist/shared/stacks-69nq48jp.js.map +15 -0
  11. package/dist/shared/{stacks-8pfdscq6.js → stacks-6gavarmy.js} +37 -9
  12. package/dist/shared/stacks-6gavarmy.js.map +12 -0
  13. package/dist/shared/{stacks-7wkf2rph.js → stacks-7bqkf3b0.js} +86 -71
  14. package/dist/shared/{stacks-7wkf2rph.js.map → stacks-7bqkf3b0.js.map} +9 -10
  15. package/dist/shared/{stacks-zcpvzbr0.js → stacks-8brgfvqx.js} +3 -3
  16. package/dist/shared/{stacks-4vzmhw3q.cjs → stacks-8vzxax5e.cjs} +13 -3
  17. package/dist/shared/stacks-8vzxax5e.cjs.map +10 -0
  18. package/dist/shared/{stacks-hnqt5rz4.js → stacks-9c1yam8b.js} +3 -3
  19. package/dist/shared/{stacks-bnbdqznq.cjs → stacks-bdgh9n83.cjs} +11 -10
  20. package/dist/shared/{stacks-bnbdqznq.cjs.map → stacks-bdgh9n83.cjs.map} +3 -3
  21. package/dist/shared/{stacks-fb75yew8.js → stacks-db3kwavg.cjs} +346 -138
  22. package/dist/shared/stacks-db3kwavg.cjs.map +23 -0
  23. package/dist/shared/{stacks-jpt52csy.js → stacks-e3nwm1dz.js} +14 -17
  24. package/dist/shared/stacks-e3nwm1dz.js.map +10 -0
  25. package/dist/shared/{stacks-27fmgajb.js → stacks-ga026yxz.js} +9 -9
  26. package/dist/shared/{stacks-27fmgajb.js.map → stacks-ga026yxz.js.map} +3 -3
  27. package/dist/shared/{stacks-nyaw1z2a.cjs → stacks-ggdz96r1.cjs} +4 -4
  28. package/dist/shared/{stacks-nyaw1z2a.cjs.map → stacks-ggdz96r1.cjs.map} +3 -3
  29. package/dist/shared/{stacks-08y0y0t7.js → stacks-gjz26k6b.js} +2 -2
  30. package/dist/shared/{stacks-x5386y2y.cjs → stacks-gza2n1zs.cjs} +5 -5
  31. package/dist/shared/{stacks-x5386y2y.cjs.map → stacks-gza2n1zs.cjs.map} +3 -3
  32. package/dist/shared/{stacks-ta1gar0b.cjs → stacks-kqn4y8kq.cjs} +7 -5
  33. package/dist/shared/{stacks-ta1gar0b.cjs.map → stacks-kqn4y8kq.cjs.map} +3 -3
  34. package/dist/shared/{stacks-ztzygy90.js → stacks-mftyrc60.js} +2 -2
  35. package/dist/shared/stacks-n4d8j8q3.js +801 -0
  36. package/dist/shared/stacks-n4d8j8q3.js.map +23 -0
  37. package/dist/shared/{stacks-ycbq8pf7.cjs → stacks-p337hp6m.cjs} +74 -59
  38. package/dist/shared/{stacks-ycbq8pf7.cjs.map → stacks-p337hp6m.cjs.map} +9 -10
  39. package/dist/shared/{stacks-ttdk2g2f.js → stacks-s5vej5z6.cjs} +92 -41
  40. package/dist/shared/stacks-s5vej5z6.cjs.map +15 -0
  41. package/dist/shared/stacks-sdqkapct.cjs +67 -0
  42. package/dist/shared/stacks-sdqkapct.cjs.map +12 -0
  43. package/dist/shared/{stacks-1arrcd11.js → stacks-v2rfr46a.js} +2 -2
  44. package/dist/shared/{stacks-9mqveyjv.cjs → stacks-w9t61fra.cjs} +7 -10
  45. package/dist/shared/stacks-w9t61fra.cjs.map +10 -0
  46. package/dist/shared/{stacks-tjjnkt3r.js → stacks-wxfd6r4b.js} +2 -2
  47. package/dist/shared/{stacks-4z72akdf.js → stacks-x0qqwrev.js} +3 -3
  48. package/dist/shared/{stacks-gck1sq7h.cjs → stacks-xjkn3en1.cjs} +16 -2
  49. package/dist/shared/stacks-xjkn3en1.cjs.map +10 -0
  50. package/dist/shared/stacks-xnrywjf1.cjs +131 -0
  51. package/dist/shared/stacks-xnrywjf1.cjs.map +11 -0
  52. package/dist/shared/stacks-yajyej2y.js +139 -0
  53. package/dist/shared/stacks-yajyej2y.js.map +11 -0
  54. package/dist/shared/{stacks-913a2rx7.js → stacks-yvb7rvwk.js} +13 -3
  55. package/dist/shared/stacks-yvb7rvwk.js.map +10 -0
  56. package/dist/shared/{stacks-0cdm20eh.js → stacks-z90xdr1x.js} +7 -11
  57. package/dist/shared/{stacks-0cdm20eh.js.map → stacks-z90xdr1x.js.map} +3 -3
  58. package/dist/src/accounts/index.js +2 -3
  59. package/dist/src/accounts/index.js.map +2 -2
  60. package/dist/src/actions/index.cjs +2 -1
  61. package/dist/src/actions/index.cjs.map +1 -1
  62. package/dist/src/actions/index.d.cts +108 -20
  63. package/dist/src/actions/index.d.ts +108 -20
  64. package/dist/src/actions/index.js +17 -15
  65. package/dist/src/actions/index.js.map +1 -1
  66. package/dist/src/bitcoin/index.d.cts +27 -0
  67. package/dist/src/bitcoin/index.d.ts +27 -0
  68. package/dist/src/bitcoin/index.js +10 -11
  69. package/dist/src/bitcoin/index.js.map +2 -2
  70. package/dist/src/bns/index.d.cts +27 -0
  71. package/dist/src/bns/index.d.ts +27 -0
  72. package/dist/src/bns/index.js +13 -13
  73. package/dist/src/bns/index.js.map +1 -1
  74. package/dist/src/clarity/index.js +7 -6
  75. package/dist/src/clarity/index.js.map +1 -1
  76. package/dist/src/connect/index.cjs +44 -30
  77. package/dist/src/connect/index.cjs.map +7 -7
  78. package/dist/src/connect/index.d.cts +16 -1
  79. package/dist/src/connect/index.d.ts +16 -1
  80. package/dist/src/connect/index.js +44 -30
  81. package/dist/src/connect/index.js.map +7 -7
  82. package/dist/src/connect/walletconnect/index.cjs +49 -413
  83. package/dist/src/connect/walletconnect/index.cjs.map +4 -4
  84. package/dist/src/connect/walletconnect/index.js +47 -411
  85. package/dist/src/connect/walletconnect/index.js.map +4 -4
  86. package/dist/src/filters/index.js +2 -2
  87. package/dist/src/index.cjs +49 -124
  88. package/dist/src/index.cjs.map +6 -8
  89. package/dist/src/index.d.cts +163 -54
  90. package/dist/src/index.d.ts +163 -54
  91. package/dist/src/index.js +79 -147
  92. package/dist/src/index.js.map +6 -8
  93. package/dist/src/postconditions/index.js +6 -5
  94. package/dist/src/postconditions/index.js.map +1 -1
  95. package/dist/src/pox/index.cjs +7 -83
  96. package/dist/src/pox/index.cjs.map +3 -3
  97. package/dist/src/pox/index.d.cts +32 -1
  98. package/dist/src/pox/index.d.ts +32 -1
  99. package/dist/src/pox/index.js +22 -102
  100. package/dist/src/pox/index.js.map +3 -3
  101. package/dist/src/pox5/index.cjs +4 -129
  102. package/dist/src/pox5/index.cjs.map +3 -4
  103. package/dist/src/pox5/index.d.cts +27 -0
  104. package/dist/src/pox5/index.d.ts +27 -0
  105. package/dist/src/pox5/index.js +20 -148
  106. package/dist/src/pox5/index.js.map +3 -4
  107. package/dist/src/sbtc/index.cjs +2 -59
  108. package/dist/src/sbtc/index.cjs.map +3 -3
  109. package/dist/src/sbtc/index.d.cts +30 -2
  110. package/dist/src/sbtc/index.d.ts +30 -2
  111. package/dist/src/sbtc/index.js +15 -74
  112. package/dist/src/sbtc/index.js.map +3 -3
  113. package/dist/src/stackingdao/index.d.cts +27 -0
  114. package/dist/src/stackingdao/index.d.ts +27 -0
  115. package/dist/src/stackingdao/index.js +11 -11
  116. package/dist/src/stackingdao/index.js.map +1 -1
  117. package/dist/src/subscriptions/index.d.cts +27 -0
  118. package/dist/src/subscriptions/index.d.ts +27 -0
  119. package/dist/src/subscriptions/index.js +2 -2
  120. package/dist/src/tools/btc/index.cjs.map +2 -2
  121. package/dist/src/tools/btc/index.js.map +2 -2
  122. package/dist/src/tools/index.cjs +629 -392
  123. package/dist/src/tools/index.cjs.map +30 -28
  124. package/dist/src/tools/index.d.cts +44 -0
  125. package/dist/src/tools/index.d.ts +44 -0
  126. package/dist/src/tools/index.js +628 -391
  127. package/dist/src/tools/index.js.map +30 -28
  128. package/dist/src/transactions/index.js +6 -5
  129. package/dist/src/transactions/index.js.map +1 -1
  130. package/dist/src/utils/index.d.cts +2 -5
  131. package/dist/src/utils/index.d.ts +2 -5
  132. package/dist/src/utils/index.js +2 -2
  133. package/package.json +18 -7
  134. package/dist/shared/stacks-0eatsx6d.cjs +0 -25
  135. package/dist/shared/stacks-0eatsx6d.cjs.map +0 -10
  136. package/dist/shared/stacks-0jk7vd8r.cjs.map +0 -14
  137. package/dist/shared/stacks-4vzmhw3q.cjs.map +0 -10
  138. package/dist/shared/stacks-5nmz5ad9.js +0 -409
  139. package/dist/shared/stacks-5nmz5ad9.js.map +0 -10
  140. package/dist/shared/stacks-709tra19.js.map +0 -10
  141. package/dist/shared/stacks-8pfdscq6.js.map +0 -12
  142. package/dist/shared/stacks-913a2rx7.js.map +0 -10
  143. package/dist/shared/stacks-9mqveyjv.cjs.map +0 -10
  144. package/dist/shared/stacks-e4xn4m7j.js +0 -27
  145. package/dist/shared/stacks-e4xn4m7j.js.map +0 -10
  146. package/dist/shared/stacks-fb75yew8.js.map +0 -21
  147. package/dist/shared/stacks-gck1sq7h.cjs.map +0 -10
  148. package/dist/shared/stacks-gxq2pbky.js.map +0 -13
  149. package/dist/shared/stacks-jpt52csy.js.map +0 -10
  150. package/dist/shared/stacks-mnnhpex3.cjs +0 -407
  151. package/dist/shared/stacks-mnnhpex3.cjs.map +0 -10
  152. package/dist/shared/stacks-tdsp5gsb.cjs +0 -527
  153. package/dist/shared/stacks-tdsp5gsb.cjs.map +0 -21
  154. package/dist/shared/stacks-ttdk2g2f.js.map +0 -14
  155. package/dist/shared/stacks-wdp5yr8n.cjs +0 -39
  156. package/dist/shared/stacks-wdp5yr8n.cjs.map +0 -12
  157. /package/dist/shared/{stacks-w23294am.js.map → stacks-51ybf135.js.map} +0 -0
  158. /package/dist/shared/{stacks-zcpvzbr0.js.map → stacks-8brgfvqx.js.map} +0 -0
  159. /package/dist/shared/{stacks-hnqt5rz4.js.map → stacks-9c1yam8b.js.map} +0 -0
  160. /package/dist/shared/{stacks-08y0y0t7.js.map → stacks-gjz26k6b.js.map} +0 -0
  161. /package/dist/shared/{stacks-ztzygy90.js.map → stacks-mftyrc60.js.map} +0 -0
  162. /package/dist/shared/{stacks-1arrcd11.js.map → stacks-v2rfr46a.js.map} +0 -0
  163. /package/dist/shared/{stacks-tjjnkt3r.js.map → stacks-wxfd6r4b.js.map} +0 -0
  164. /package/dist/shared/{stacks-4z72akdf.js.map → stacks-x0qqwrev.js.map} +0 -0
@@ -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.localeCompare(b));
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
- return client.request("/extended/v2/blocks?limit=1", { method: "GET" });
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
- if (this.offset + length > this.data.length) {
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 [address, name] = contractId.split(".");
866
- if (!address || !name)
953
+ const parsed = parsePrincipal(contractId);
954
+ if (!parsed?.contractName)
867
955
  throw new Error(`Invalid contract identifier: ${contractId}`);
868
- return [address, name];
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 [addr, name] = address.split(".");
958
- if (!addr)
959
- throw new Error("Invalid principal address");
960
- return name ? contractPrincipalCV(addr, name) : standardPrincipalCV(addr);
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
- function readCV(reader) {
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 Error(`Cannot deserialize unknown clarity type: ${type}`);
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
- super(`HTTP request failed with status ${status}`, options);
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 sleep = (ms) => new Promise((r) => setTimeout(r, ms));
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 sleep(pollingInterval);
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", { method: "POST", body });
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
- const needsFeeResolution = params.fee === undefined || isFeeTier(params.fee);
2222
- const unsigned = buildContractCall({
2223
- contractAddress,
2224
- contractName,
2225
- functionName: params.functionName,
2226
- functionArgs: params.functionArgs ?? [],
2227
- fee: needsFeeResolution ? 0n : params.fee,
2228
- nonce,
2229
- publicKey: account.publicKey,
2230
- chain: client.chain,
2231
- postConditionMode: params.postConditionMode,
2232
- postConditions: params.postConditions
2233
- });
2234
- if (needsFeeResolution) {
2235
- setUnsignedFee(unsigned, await resolveFee(client, unsigned, params.fee));
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 resolveNonce(client, publicKeyToAddress(publicKey, network));
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 estimates = await estimateFee(client, {
2337
- transaction: unsigned
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 = await Promise.all(calls.map((call) => readContract(client, call)));
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 chain = process.env.STACKS_CHAIN === "testnet" ? testnet : mainnet;
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(process.env.STACKS_RPC_URL)
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().describe("Stacks principal (SP…/SM… mainnet, ST… testnet)");
3399
- async function stxBalance(client, principal) {
3400
- const balance = await getBalance(client, { address: principal });
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(client, principal) {
3404
- const info = await getAccountInfo(client, { address: principal });
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(client, args) {
3411
- return getBlock(client, args);
3690
+ async function block(resolve, args) {
3691
+ return getBlock(resolve(), args);
3412
3692
  }
3413
- async function blockHeight(client) {
3414
- return { height: await getBlockHeight(client) };
3693
+ async function blockHeight(resolve) {
3694
+ return { height: await getBlockHeight(resolve()) };
3415
3695
  }
3416
- async function contractRead(client, args) {
3417
- const result = await readContract(client, args);
3418
- return { result: JSON.stringify(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(client, serializedTxHex) {
3708
+ async function fee(resolve, serializedTxHex) {
3429
3709
  const raw = serializedTxHex.startsWith("0x") ? serializedTxHex.slice(2) : serializedTxHex;
3430
3710
  assertValidHex(raw);
3431
- const txBytes = new Uint8Array(Buffer.from(raw, "hex"));
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 — ${e instanceof Error ? e.message : String(e)}`);
3716
+ throw new Error(`serializedTxHex: deserialization failed: ${e instanceof Error ? e.message : String(e)}`);
3437
3717
  }
3438
- const fees = await estimateFee(client, {
3439
- transaction
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: fees[0]?.fee ?? 0,
3443
- medium: fees[1]?.fee ?? 0,
3444
- high: fees[2]?.fee ?? 0
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(client, name) {
3448
- return { owner: await resolveName(client, name) };
3738
+ async function bnsResolveImpl(resolve, name) {
3739
+ return { owner: await resolveName(resolve(), name) };
3449
3740
  }
3450
- async function bnsReverseImpl(client, principal) {
3451
- return { name: await getPrimaryName(client, principal) };
3741
+ async function bnsReverseImpl(resolve, principal) {
3742
+ return { name: await getPrimaryName(resolve(), principal) };
3452
3743
  }
3453
- async function transactionByTxId(client, txId) {
3454
- return getTransaction(client, { txid: txId });
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(client, principal, limit) {
3457
- return getAccountHistory(client, { address: principal, limit });
3751
+ async function accountHistory(resolve, principal, limit) {
3752
+ return getAccountHistory(resolve(), { address: principal, limit });
3458
3753
  }
3459
- async function mempoolStats(client) {
3460
- return getMempoolStats(client);
3754
+ async function mempoolStats(resolve) {
3755
+ return getMempoolStats(resolve());
3461
3756
  }
3462
- async function nftHoldings(client, principal, limit) {
3463
- return getNftHoldings(client, { address: principal, limit });
3757
+ async function nftHoldings(resolve, principal, limit) {
3758
+ return getNftHoldings(resolve(), { address: principal, limit });
3464
3759
  }
3465
- function createStacksTools(client) {
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(client, principal)
3766
+ execute: ({ principal }) => stxBalance(resolve, principal)
3471
3767
  }),
3472
3768
  getAccountInfo: import_ai.tool({
3473
- description: "Get account info (balance, locked, nonce) for a Stacks principal.",
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(client, principal)
3771
+ execute: ({ principal }) => accountInfo(resolve, principal)
3476
3772
  }),
3477
3773
  getBlock: import_ai.tool({
3478
- description: "Fetch a Stacks block by height or hash. Omit both for the latest block.",
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: import_zod.z.string().optional()
3777
+ hash: BLOCK_HASH.optional()
3482
3778
  }),
3483
- execute: (args) => block(client, args)
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(client)
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: import_zod.z.string().describe("Fully-qualified contract id: '{address}.{name}'"),
3494
- functionName: import_zod.z.string(),
3789
+ contract: CONTRACT_ID,
3790
+ functionName: FUNCTION_NAME,
3495
3791
  sender: PRINCIPAL.optional()
3496
3792
  }),
3497
- execute: (args) => contractRead(client, args)
3793
+ execute: (args) => contractRead(resolve, args)
3498
3794
  }),
3499
3795
  estimateFee: import_ai.tool({
3500
- description: "Estimate fee range (low / medium / high) for a serialized Stacks transaction.",
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(client, serializedTxHex)
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(client, name)
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(client, principal)
3812
+ execute: ({ principal }) => bnsReverseImpl(resolve, principal)
3517
3813
  }),
3518
3814
  getTransaction: import_ai.tool({
3519
- description: "Fetch a confirmed Stacks transaction by txId (Hiro extended API).",
3520
- inputSchema: import_zod.z.object({
3521
- txId: import_zod.z.string().describe("Transaction id, with or without 0x prefix")
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: "Paginated transaction history for a Stacks principal (Hiro extended API).",
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(client, principal, limit)
3825
+ execute: ({ principal, limit }) => accountHistory(resolve, principal, limit)
3532
3826
  }),
3533
3827
  getMempoolStats: import_ai.tool({
3534
- description: "Current mempool statistics: pending count, fee distribution, age buckets (Hiro extended API).",
3828
+ description: `Current mempool statistics: pending count, fee distribution, age buckets. ${EXTENDED}`,
3535
3829
  inputSchema: import_zod.z.object({}),
3536
- execute: () => mempoolStats(client)
3830
+ execute: () => mempoolStats(resolve)
3537
3831
  }),
3538
3832
  getNftHoldings: import_ai.tool({
3539
- description: "NFT holdings for a Stacks principal across all collections (Hiro extended API).",
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(client, principal, limit)
3838
+ execute: ({ principal, limit }) => nftHoldings(resolve, principal, limit)
3545
3839
  })
3546
3840
  };
3547
3841
  }
3548
- var getStxBalance = import_ai.tool({
3549
- description: "Get the STX balance (in micro-STX) for a Stacks principal. Uses default client.",
3550
- inputSchema: import_zod.z.object({ principal: PRINCIPAL }),
3551
- execute: ({ principal }) => stxBalance(getDefaultPublicClient(), principal)
3552
- });
3553
- var getAccountInfo2 = import_ai.tool({
3554
- description: "Get account info (balance, locked, nonce) for a Stacks principal.",
3555
- inputSchema: import_zod.z.object({ principal: PRINCIPAL }),
3556
- execute: ({ principal }) => accountInfo(getDefaultPublicClient(), principal)
3557
- });
3558
- var getBlock2 = import_ai.tool({
3559
- description: "Fetch a Stacks block by height or hash. Omit both for the latest block.",
3560
- inputSchema: import_zod.z.object({
3561
- height: import_zod.z.number().int().nonnegative().optional(),
3562
- hash: import_zod.z.string().optional()
3563
- }),
3564
- execute: (args) => block(getDefaultPublicClient(), args)
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