@arkade-os/sdk 0.4.47 → 0.4.48

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 (85) hide show
  1. package/dist/adapters/expo.cjs +5 -5
  2. package/dist/adapters/expo.d.cts +2 -2
  3. package/dist/adapters/expo.d.ts +2 -2
  4. package/dist/adapters/expo.js +3 -3
  5. package/dist/adapters/indexedDB.cjs +5 -5
  6. package/dist/adapters/indexedDB.js +4 -4
  7. package/dist/{ark-CoJgwTi_.d.cts → ark-CjE0KkGp.d.cts} +405 -250
  8. package/dist/{ark-CoJgwTi_.d.ts → ark-CjE0KkGp.d.ts} +405 -250
  9. package/dist/{asyncStorageTaskQueue-Dowyo59a.d.cts → asyncStorageTaskQueue-CeLZhZFU.d.cts} +2 -2
  10. package/dist/{asyncStorageTaskQueue-Z3aFoXCl.d.ts → asyncStorageTaskQueue-D9SOPMPC.d.ts} +2 -2
  11. package/dist/{chunk-XN3554FT.js → chunk-4VVTRPH3.js} +4 -4
  12. package/dist/chunk-4VVTRPH3.js.map +1 -0
  13. package/dist/{chunk-RQSA7ADZ.cjs → chunk-5XMVTK5S.cjs} +37 -37
  14. package/dist/chunk-5XMVTK5S.cjs.map +1 -0
  15. package/dist/{chunk-L5ND2FJJ.cjs → chunk-7TXSPRN5.cjs} +161 -2
  16. package/dist/chunk-7TXSPRN5.cjs.map +1 -0
  17. package/dist/{chunk-CDDWXBEM.js → chunk-BHHLRZCS.js} +169 -42
  18. package/dist/chunk-BHHLRZCS.js.map +1 -0
  19. package/dist/{chunk-HHV5FPC6.cjs → chunk-EB3ALGTM.cjs} +178 -50
  20. package/dist/chunk-EB3ALGTM.cjs.map +1 -0
  21. package/dist/{chunk-JAYOXOLT.cjs → chunk-ENDNQPZA.cjs} +17 -44
  22. package/dist/chunk-ENDNQPZA.cjs.map +1 -0
  23. package/dist/{chunk-WTTLIFS7.cjs → chunk-ENZ4YPR2.cjs} +944 -544
  24. package/dist/chunk-ENZ4YPR2.cjs.map +1 -0
  25. package/dist/{chunk-3N5I6GT6.js → chunk-G6J6AEMH.js} +5 -4
  26. package/dist/chunk-G6J6AEMH.js.map +1 -0
  27. package/dist/{chunk-OCS5S3L3.js → chunk-NYR5H6GR.js} +685 -284
  28. package/dist/chunk-NYR5H6GR.js.map +1 -0
  29. package/dist/{chunk-VE67GMGM.cjs → chunk-SYDANBJI.cjs} +9 -8
  30. package/dist/chunk-SYDANBJI.cjs.map +1 -0
  31. package/dist/{chunk-AJQ4AOT3.js → chunk-XFMGIFBL.js} +4 -31
  32. package/dist/chunk-XFMGIFBL.js.map +1 -0
  33. package/dist/{chunk-C7TXXTMS.js → chunk-ZDDBTFVO.js} +146 -3
  34. package/dist/chunk-ZDDBTFVO.js.map +1 -0
  35. package/dist/contracts/handlers/index.cjs +8 -8
  36. package/dist/contracts/handlers/index.d.cts +3 -3
  37. package/dist/contracts/handlers/index.d.ts +3 -3
  38. package/dist/contracts/handlers/index.js +2 -2
  39. package/dist/{delegate-Dl87_zMA.d.cts → delegate-D3dY-2vS.d.cts} +1 -1
  40. package/dist/{delegate-CuaDqqQi.d.ts → delegate-DhGZk1r2.d.ts} +1 -1
  41. package/dist/{index-BC_G0VTh.d.cts → index-D6RQROds.d.cts} +2 -2
  42. package/dist/{index-CKwpZEpw.d.ts → index-DK4_iWYy.d.ts} +2 -2
  43. package/dist/index.cjs +211 -183
  44. package/dist/index.d.cts +61 -11
  45. package/dist/index.d.ts +61 -11
  46. package/dist/index.js +4 -4
  47. package/dist/repositories/realm/index.cjs +19 -19
  48. package/dist/repositories/realm/index.d.cts +2 -2
  49. package/dist/repositories/realm/index.d.ts +2 -2
  50. package/dist/repositories/realm/index.js +5 -5
  51. package/dist/repositories/sqlite/index.cjs +18 -18
  52. package/dist/repositories/sqlite/index.d.cts +2 -2
  53. package/dist/repositories/sqlite/index.d.ts +2 -2
  54. package/dist/repositories/sqlite/index.js +5 -5
  55. package/dist/{taskRunner-Dz-TI4Rb.d.ts → taskRunner-B-2MHCYG.d.ts} +2 -2
  56. package/dist/{taskRunner-Dz47k0lp.d.cts → taskRunner-Brnak0Rc.d.cts} +2 -2
  57. package/dist/wallet/expo/background.cjs +14 -14
  58. package/dist/wallet/expo/background.d.cts +3 -3
  59. package/dist/wallet/expo/background.d.ts +3 -3
  60. package/dist/wallet/expo/background.js +6 -6
  61. package/dist/wallet/expo/index.cjs +14 -14
  62. package/dist/wallet/expo/index.cjs.map +1 -1
  63. package/dist/wallet/expo/index.d.cts +5 -5
  64. package/dist/wallet/expo/index.d.ts +5 -5
  65. package/dist/wallet/expo/index.js +5 -5
  66. package/dist/wallet/expo/index.js.map +1 -1
  67. package/dist/{wallet-Oxz_wLxo.d.cts → wallet-B5bwixQa.d.ts} +130 -7
  68. package/dist/{wallet-x7egmXq6.d.ts → wallet-DiOrtYic.d.cts} +130 -7
  69. package/dist/worker/expo/index.cjs +9 -9
  70. package/dist/worker/expo/index.d.cts +4 -4
  71. package/dist/worker/expo/index.d.ts +4 -4
  72. package/dist/worker/expo/index.js +5 -5
  73. package/package.json +3 -2
  74. package/dist/chunk-3N5I6GT6.js.map +0 -1
  75. package/dist/chunk-AJQ4AOT3.js.map +0 -1
  76. package/dist/chunk-C7TXXTMS.js.map +0 -1
  77. package/dist/chunk-CDDWXBEM.js.map +0 -1
  78. package/dist/chunk-HHV5FPC6.cjs.map +0 -1
  79. package/dist/chunk-JAYOXOLT.cjs.map +0 -1
  80. package/dist/chunk-L5ND2FJJ.cjs.map +0 -1
  81. package/dist/chunk-OCS5S3L3.js.map +0 -1
  82. package/dist/chunk-RQSA7ADZ.cjs.map +0 -1
  83. package/dist/chunk-VE67GMGM.cjs.map +0 -1
  84. package/dist/chunk-WTTLIFS7.cjs.map +0 -1
  85. package/dist/chunk-XN3554FT.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkL5ND2FJJ_cjs = require('./chunk-L5ND2FJJ.cjs');
3
+ var chunk7TXSPRN5_cjs = require('./chunk-7TXSPRN5.cjs');
4
4
  var chunk5BLDMQED_cjs = require('./chunk-5BLDMQED.cjs');
5
5
  var btcSigner = require('@scure/btc-signer');
6
6
  var secp256k1_js = require('@noble/curves/secp256k1.js');
@@ -136,7 +136,7 @@ var VtxoTreeExpiry = {
136
136
  if (!checkKeyMatch(unknown[0], "expiry" /* VtxoTreeExpiry */)) return null;
137
137
  const v = btcSigner.ScriptNum(6, true).decode(unknown[1]);
138
138
  if (!v) return null;
139
- return chunkL5ND2FJJ_cjs.sequenceToTimelock(Number(v));
139
+ return chunk7TXSPRN5_cjs.sequenceToTimelock(Number(v));
140
140
  })
141
141
  };
142
142
  var encodedPsbtFieldKey = Object.fromEntries(
@@ -161,7 +161,7 @@ function checkKeyMatch(key, arkPsbtFieldKey, prefixOnly = false) {
161
161
  }
162
162
 
163
163
  // package.json
164
- var version = "0.4.47";
164
+ var version = "0.4.48";
165
165
 
166
166
  // src/utils/fetch.ts
167
167
  var buildVersion = "0.9.9";
@@ -465,8 +465,8 @@ function prepareCoinAsIntentProofInput(coin) {
465
465
  if (!("tapTree" in coin)) {
466
466
  return coin;
467
467
  }
468
- const vtxoScript = chunkL5ND2FJJ_cjs.VtxoScript.decode(coin.tapTree);
469
- const sequence = chunkL5ND2FJJ_cjs.getSequence(coin.intentTapLeafScript);
468
+ const vtxoScript = chunk7TXSPRN5_cjs.VtxoScript.decode(coin.tapTree);
469
+ const sequence = chunk7TXSPRN5_cjs.getSequence(coin.intentTapLeafScript);
470
470
  const unknown = [VtxoTaprootTree.encode(coin.tapTree)];
471
471
  if (coin.extraWitness) {
472
472
  unknown.push(ConditionWitness.encode(coin.extraWitness));
@@ -584,6 +584,138 @@ function isEventSourceError(error) {
584
584
  return error instanceof Error && error.name === "EventSourceError";
585
585
  }
586
586
 
587
+ // src/providers/rateGate.ts
588
+ var DEFAULT_MAX_CONCURRENT = 6;
589
+ var DEFAULT_COOLDOWN_MS = 5e3;
590
+ var MAX_COOLDOWN_MS = 6e4;
591
+ var DEFAULT_JITTER_MS = 500;
592
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
593
+ function parseRetryAfterMs(header) {
594
+ if (header === null || header === void 0) return void 0;
595
+ const trimmed = header.trim();
596
+ if (trimmed === "") return void 0;
597
+ const seconds = Number(trimmed);
598
+ if (Number.isFinite(seconds)) return seconds < 0 ? void 0 : seconds * 1e3;
599
+ const at = Date.parse(trimmed);
600
+ if (!Number.isNaN(at)) return Math.max(0, at - Date.now());
601
+ return void 0;
602
+ }
603
+ function requestOrigin(input) {
604
+ let url;
605
+ if (typeof input === "string") {
606
+ url = input;
607
+ } else if (input instanceof URL) {
608
+ url = input.href;
609
+ } else {
610
+ url = input.url;
611
+ }
612
+ try {
613
+ return new URL(url).origin;
614
+ } catch {
615
+ return url;
616
+ }
617
+ }
618
+ var OriginRateGate = class {
619
+ states = /* @__PURE__ */ new Map();
620
+ maxConcurrent;
621
+ defaultCooldownMs;
622
+ maxCooldownMs;
623
+ jitterMs;
624
+ constructor(options) {
625
+ this.maxConcurrent = options?.maxConcurrent ?? DEFAULT_MAX_CONCURRENT;
626
+ this.defaultCooldownMs = options?.defaultCooldownMs ?? DEFAULT_COOLDOWN_MS;
627
+ this.maxCooldownMs = options?.maxCooldownMs ?? MAX_COOLDOWN_MS;
628
+ this.jitterMs = options?.jitterMs ?? DEFAULT_JITTER_MS;
629
+ }
630
+ /**
631
+ * Run `fn` under the origin's concurrency cap and behind any active
632
+ * cooldown. Put only the request in `fn`: the slot is released as soon as
633
+ * it settles, so body parsing doesn't hold one.
634
+ */
635
+ async run(input, fn) {
636
+ const state = this.stateFor(requestOrigin(input));
637
+ await this.acquire(state);
638
+ try {
639
+ for (; ; ) {
640
+ const remaining = state.blockedUntil - Date.now();
641
+ if (remaining <= 0) break;
642
+ await sleep(remaining + Math.random() * this.jitterMs);
643
+ }
644
+ return await fn();
645
+ } finally {
646
+ this.release(state);
647
+ }
648
+ }
649
+ /**
650
+ * {@link run} for a request whose response the gate should inspect: a `429`
651
+ * is recorded *before* the slot is released. Reporting after `run()` resolves
652
+ * is too late — `release()` hands the slot to the next queued waiter, which
653
+ * resumes, sees no cooldown, and sends into the limiter that just refused us.
654
+ *
655
+ * Prefer this over `run` for anything returning a `Response`.
656
+ */
657
+ runHttp(input, fn) {
658
+ return this.run(input, async () => {
659
+ const response = await fn();
660
+ if (response.status === 429) {
661
+ this.reportRateLimited(input, response.headers?.get("retry-after"));
662
+ }
663
+ return response;
664
+ });
665
+ }
666
+ /**
667
+ * Record an observed `429`, pausing every gated request to that origin.
668
+ * Monotonic: a shorter cooldown never shortens one already in effect.
669
+ */
670
+ reportRateLimited(input, retryAfterHeader) {
671
+ const cooldown = Math.min(
672
+ parseRetryAfterMs(retryAfterHeader) ?? this.defaultCooldownMs,
673
+ this.maxCooldownMs
674
+ );
675
+ const state = this.stateFor(requestOrigin(input));
676
+ state.blockedUntil = Math.max(state.blockedUntil, Date.now() + cooldown);
677
+ }
678
+ /** Milliseconds left on `input` origin's cooldown; `0` when not cooling down. */
679
+ cooldownRemainingMs(input) {
680
+ const state = this.states.get(requestOrigin(input));
681
+ if (!state) return 0;
682
+ return Math.max(0, state.blockedUntil - Date.now());
683
+ }
684
+ /**
685
+ * Drop all per-origin state, so test suites don't inherit each other's
686
+ * cooldowns. Waiters queued on the discarded state still drain normally.
687
+ */
688
+ reset() {
689
+ this.states.clear();
690
+ }
691
+ stateFor(origin) {
692
+ let state = this.states.get(origin);
693
+ if (!state) {
694
+ state = { blockedUntil: 0, active: 0, queue: [] };
695
+ this.states.set(origin, state);
696
+ }
697
+ return state;
698
+ }
699
+ acquire(state) {
700
+ if (state.active < this.maxConcurrent) {
701
+ state.active += 1;
702
+ return Promise.resolve();
703
+ }
704
+ return new Promise((resolve) => {
705
+ state.queue.push(() => {
706
+ state.active += 1;
707
+ resolve();
708
+ });
709
+ });
710
+ }
711
+ release(state) {
712
+ state.active -= 1;
713
+ const next = state.queue.shift();
714
+ if (next) next();
715
+ }
716
+ };
717
+ var rateGate = new OriginRateGate();
718
+
587
719
  // src/providers/ark.ts
588
720
  var DigestMismatchError = class extends Error {
589
721
  constructor(message) {
@@ -604,7 +736,7 @@ var SettlementEventType = /* @__PURE__ */ ((SettlementEventType2) => {
604
736
  return SettlementEventType2;
605
737
  })(SettlementEventType || {});
606
738
  var RestArkProvider = class {
607
- constructor(serverUrl = chunkL5ND2FJJ_cjs.DEFAULT_ARKADE_SERVER_URL) {
739
+ constructor(serverUrl = chunk7TXSPRN5_cjs.DEFAULT_ARKADE_SERVER_URL) {
608
740
  this.serverUrl = serverUrl;
609
741
  }
610
742
  serverUrl;
@@ -659,6 +791,9 @@ var RestArkProvider = class {
659
791
  throw toProviderUnavailable(err, "arkade");
660
792
  }
661
793
  if (response.ok) return response;
794
+ if (response.status === 429) {
795
+ rateGate.reportRateLimited(url, response.headers?.get("retry-after"));
796
+ }
662
797
  let body;
663
798
  try {
664
799
  body = await response.clone().text();
@@ -679,7 +814,7 @@ var RestArkProvider = class {
679
814
  }
680
815
  async getInfo() {
681
816
  const url = `${this.serverUrl}/v1/info`;
682
- const response = await fetch(url);
817
+ const response = await rateGate.runHttp(url, () => fetch(url));
683
818
  if (!response.ok) {
684
819
  const errorText = await response.text();
685
820
  throwIfHttpUnavailable(response, "arkade", errorText);
@@ -2457,24 +2592,43 @@ var Packet = class _Packet {
2457
2592
  return packet;
2458
2593
  }
2459
2594
  };
2595
+ var INDEXER_MAX_ATTEMPTS = 3;
2596
+ var INDEXER_RETRY_BASE_MS = 250;
2460
2597
  async function indexerFetch(input, init) {
2461
- let res;
2462
- try {
2463
- res = await baseFetch(input, init);
2464
- } catch (err) {
2465
- throw toProviderUnavailable(err, "indexer");
2466
- }
2467
- if (!res.ok) {
2598
+ const method = (init?.method ?? "GET").toUpperCase();
2599
+ const maxAttempts = method === "GET" || method === "HEAD" ? INDEXER_MAX_ATTEMPTS : 1;
2600
+ for (let attempt = 1; ; attempt++) {
2601
+ const lastAttempt = attempt >= maxAttempts;
2602
+ let res;
2603
+ try {
2604
+ res = await rateGate.runHttp(input, () => baseFetch(input, init));
2605
+ } catch (err) {
2606
+ const mapped = toProviderUnavailable(err, "indexer");
2607
+ if (lastAttempt || !(mapped instanceof ProviderUnavailableError)) throw mapped;
2608
+ await sleep2(retryDelayMs(attempt));
2609
+ continue;
2610
+ }
2611
+ if (res.ok) return res;
2468
2612
  let body;
2469
2613
  try {
2470
2614
  body = await res.clone().text();
2471
2615
  } catch {
2472
2616
  body = void 0;
2473
2617
  }
2474
- throwIfHttpUnavailable(res, "indexer", body);
2618
+ try {
2619
+ throwIfHttpUnavailable(res, "indexer", body);
2620
+ } catch (err) {
2621
+ if (lastAttempt) throw err;
2622
+ await sleep2(retryDelayMs(attempt));
2623
+ continue;
2624
+ }
2625
+ return res;
2475
2626
  }
2476
- return res;
2477
2627
  }
2628
+ function retryDelayMs(attempt) {
2629
+ return INDEXER_RETRY_BASE_MS * 2 ** (attempt - 1);
2630
+ }
2631
+ var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2478
2632
  var IndexerTxType = /* @__PURE__ */ ((IndexerTxType2) => {
2479
2633
  IndexerTxType2[IndexerTxType2["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
2480
2634
  IndexerTxType2[IndexerTxType2["INDEXER_TX_TYPE_RECEIVED"] = 1] = "INDEXER_TX_TYPE_RECEIVED";
@@ -2490,7 +2644,7 @@ var ChainTxType = /* @__PURE__ */ ((ChainTxType2) => {
2490
2644
  return ChainTxType2;
2491
2645
  })(ChainTxType || {});
2492
2646
  var RestIndexerProvider = class {
2493
- constructor(serverUrl = chunkL5ND2FJJ_cjs.DEFAULT_ARKADE_SERVER_URL) {
2647
+ constructor(serverUrl = chunk7TXSPRN5_cjs.DEFAULT_ARKADE_SERVER_URL) {
2494
2648
  this.serverUrl = serverUrl;
2495
2649
  }
2496
2650
  serverUrl;
@@ -2632,9 +2786,9 @@ var RestIndexerProvider = class {
2632
2786
  yield {
2633
2787
  txid: data.event.txid,
2634
2788
  scripts: data.event.scripts || [],
2635
- newVtxos: (data.event.newVtxos || []).map(convertVtxo),
2636
- spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
2637
- sweptVtxos: (data.event.sweptVtxos || []).map(convertVtxo),
2789
+ newVtxos: (data.event.newVtxos || []).map(chunk7TXSPRN5_cjs.convertVtxo),
2790
+ spentVtxos: (data.event.spentVtxos || []).map(chunk7TXSPRN5_cjs.convertVtxo),
2791
+ sweptVtxos: (data.event.sweptVtxos || []).map(chunk7TXSPRN5_cjs.convertVtxo),
2638
2792
  tx: data.event.tx,
2639
2793
  checkpointTxs: data.event.checkpointTxs
2640
2794
  };
@@ -2780,7 +2934,7 @@ var RestIndexerProvider = class {
2780
2934
  throw new Error("Invalid vtxos data received");
2781
2935
  }
2782
2936
  return {
2783
- vtxos: data.vtxos.map(convertVtxo),
2937
+ vtxos: data.vtxos.map(chunk7TXSPRN5_cjs.convertVtxo),
2784
2938
  page: data.page
2785
2939
  };
2786
2940
  }
@@ -2857,33 +3011,6 @@ function parseAssetMetadata(metadata) {
2857
3011
  }
2858
3012
  return out;
2859
3013
  }
2860
- function convertVtxo(vtxo) {
2861
- return {
2862
- txid: vtxo.outpoint.txid,
2863
- vout: vtxo.outpoint.vout,
2864
- value: Number(vtxo.amount),
2865
- status: {
2866
- confirmed: !vtxo.isSwept && !vtxo.isPreconfirmed,
2867
- isLeaf: !vtxo.isPreconfirmed
2868
- },
2869
- virtualStatus: {
2870
- state: vtxo.isSpent ? "spent" : vtxo.isSwept ? "swept" : vtxo.isPreconfirmed ? "preconfirmed" : "settled",
2871
- commitmentTxIds: vtxo.commitmentTxids,
2872
- batchExpiry: vtxo.expiresAt ? Number(vtxo.expiresAt) * 1e3 : void 0
2873
- },
2874
- spentBy: vtxo.spentBy ?? "",
2875
- settledBy: vtxo.settledBy,
2876
- arkTxId: vtxo.arkTxid,
2877
- createdAt: new Date(Number(vtxo.createdAt) * 1e3),
2878
- isUnrolled: vtxo.isUnrolled,
2879
- isSpent: vtxo.isSpent,
2880
- script: vtxo.script,
2881
- assets: vtxo.assets?.map((a) => ({
2882
- assetId: a.assetId,
2883
- amount: BigInt(a.amount)
2884
- }))
2885
- };
2886
- }
2887
3014
  var Response;
2888
3015
  ((Response2) => {
2889
3016
  function isBatchInfo(data) {
@@ -3015,7 +3142,8 @@ exports.isArkError = isArkError;
3015
3142
  exports.isEventSourceError = isEventSourceError;
3016
3143
  exports.isFetchTimeoutError = isFetchTimeoutError;
3017
3144
  exports.maybeArkError = maybeArkError;
3145
+ exports.rateGate = rateGate;
3018
3146
  exports.sdkVersion = sdkVersion;
3019
3147
  exports.setArkPsbtField = setArkPsbtField;
3020
- //# sourceMappingURL=chunk-HHV5FPC6.cjs.map
3021
- //# sourceMappingURL=chunk-HHV5FPC6.cjs.map
3148
+ //# sourceMappingURL=chunk-EB3ALGTM.cjs.map
3149
+ //# sourceMappingURL=chunk-EB3ALGTM.cjs.map