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