@arkade-os/sdk 0.4.66 → 0.4.67

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 (80) hide show
  1. package/README.md +66 -15
  2. package/dist/adapters/expo.cjs +5 -5
  3. package/dist/adapters/expo.d.cts +2 -2
  4. package/dist/adapters/expo.d.ts +2 -2
  5. package/dist/adapters/expo.js +3 -3
  6. package/dist/adapters/indexedDB.cjs +5 -5
  7. package/dist/adapters/indexedDB.js +4 -4
  8. package/dist/{asyncStorageTaskQueue-BZcIN7sA.d.cts → asyncStorageTaskQueue-LTpeXYaD.d.cts} +2 -2
  9. package/dist/{asyncStorageTaskQueue-B6SijMi3.d.ts → asyncStorageTaskQueue-Za-e_zMk.d.ts} +2 -2
  10. package/dist/{chunk-ZIRFXBKL.cjs → chunk-2JV4VQ7C.cjs} +33 -13
  11. package/dist/chunk-2JV4VQ7C.cjs.map +1 -0
  12. package/dist/{chunk-J33ZEM3A.js → chunk-3WIWNE4P.js} +33 -14
  13. package/dist/chunk-3WIWNE4P.js.map +1 -0
  14. package/dist/{chunk-CYOI4PEA.js → chunk-6TAQF6EV.js} +107 -13
  15. package/dist/chunk-6TAQF6EV.js.map +1 -0
  16. package/dist/{chunk-DSC3G6QZ.js → chunk-AEWJU6NZ.js} +1006 -167
  17. package/dist/chunk-AEWJU6NZ.js.map +1 -0
  18. package/dist/{chunk-3S3JZUEN.cjs → chunk-CO3KKSWM.cjs} +17 -17
  19. package/dist/{chunk-3S3JZUEN.cjs.map → chunk-CO3KKSWM.cjs.map} +1 -1
  20. package/dist/{chunk-55ZZ6RBL.js → chunk-EALWOVHK.js} +4 -4
  21. package/dist/{chunk-55ZZ6RBL.js.map → chunk-EALWOVHK.js.map} +1 -1
  22. package/dist/{chunk-5E6IZNRG.cjs → chunk-MJUTO3PY.cjs} +1413 -563
  23. package/dist/chunk-MJUTO3PY.cjs.map +1 -0
  24. package/dist/{chunk-R5POS3RS.js → chunk-MZFUZUTQ.js} +4 -4
  25. package/dist/{chunk-R5POS3RS.js.map → chunk-MZFUZUTQ.js.map} +1 -1
  26. package/dist/{chunk-PXPPZF5K.cjs → chunk-OIZ2V2VD.cjs} +152 -58
  27. package/dist/chunk-OIZ2V2VD.cjs.map +1 -0
  28. package/dist/{chunk-IM6IKNSL.cjs → chunk-R2YAMONM.cjs} +17 -17
  29. package/dist/{chunk-IM6IKNSL.cjs.map → chunk-R2YAMONM.cjs.map} +1 -1
  30. package/dist/{chunk-2JZGPXU4.js → chunk-X3VEMUVV.js} +3 -3
  31. package/dist/{chunk-2JZGPXU4.js.map → chunk-X3VEMUVV.js.map} +1 -1
  32. package/dist/{chunk-LL47QIHD.cjs → chunk-YDRZDZPP.cjs} +10 -10
  33. package/dist/{chunk-LL47QIHD.cjs.map → chunk-YDRZDZPP.cjs.map} +1 -1
  34. package/dist/contracts/handlers/index.cjs +9 -9
  35. package/dist/contracts/handlers/index.d.cts +3 -3
  36. package/dist/contracts/handlers/index.d.ts +3 -3
  37. package/dist/contracts/handlers/index.js +2 -2
  38. package/dist/{delegate-YXupcWWJ.d.cts → delegate-Bz2e2zXY.d.cts} +1 -1
  39. package/dist/{delegate-T-vgxMYZ.d.ts → delegate-cdmzb2f9.d.ts} +1 -1
  40. package/dist/{wallet-CNibc3yJ.d.ts → hdWalletCapable-BSjuUYOO.d.cts} +318 -127
  41. package/dist/{wallet-DJN1QgFt.d.cts → hdWalletCapable-Hi12xjCJ.d.ts} +318 -127
  42. package/dist/{index-e7LYXk1d.d.cts → index-BiACuWaf.d.ts} +109 -13
  43. package/dist/{index-D_FgwLH9.d.ts → index-D2GjZxBr.d.cts} +109 -13
  44. package/dist/{index-uUE_uQPn.d.ts → index-DU5o_hz7.d.cts} +206 -19
  45. package/dist/{index-uUE_uQPn.d.cts → index-DU5o_hz7.d.ts} +206 -19
  46. package/dist/index.cjs +322 -278
  47. package/dist/index.d.cts +291 -41
  48. package/dist/index.d.ts +291 -41
  49. package/dist/index.js +4 -4
  50. package/dist/repositories/realm/index.cjs +19 -19
  51. package/dist/repositories/realm/index.d.cts +2 -2
  52. package/dist/repositories/realm/index.d.ts +2 -2
  53. package/dist/repositories/realm/index.js +5 -5
  54. package/dist/repositories/sqlite/index.cjs +18 -18
  55. package/dist/repositories/sqlite/index.d.cts +2 -2
  56. package/dist/repositories/sqlite/index.d.ts +2 -2
  57. package/dist/repositories/sqlite/index.js +5 -5
  58. package/dist/{taskRunner-BOVcIH1N.d.cts → taskRunner-BZJMLQ6g.d.cts} +2 -2
  59. package/dist/{taskRunner-DNyD1kXG.d.ts → taskRunner-DATaRQus.d.ts} +2 -2
  60. package/dist/wallet/expo/background.cjs +14 -14
  61. package/dist/wallet/expo/background.d.cts +3 -3
  62. package/dist/wallet/expo/background.d.ts +3 -3
  63. package/dist/wallet/expo/background.js +6 -6
  64. package/dist/wallet/expo/index.cjs +18 -14
  65. package/dist/wallet/expo/index.cjs.map +1 -1
  66. package/dist/wallet/expo/index.d.cts +7 -5
  67. package/dist/wallet/expo/index.d.ts +7 -5
  68. package/dist/wallet/expo/index.js +10 -6
  69. package/dist/wallet/expo/index.js.map +1 -1
  70. package/dist/worker/expo/index.cjs +9 -9
  71. package/dist/worker/expo/index.d.cts +4 -4
  72. package/dist/worker/expo/index.d.ts +4 -4
  73. package/dist/worker/expo/index.js +5 -5
  74. package/package.json +3 -3
  75. package/dist/chunk-5E6IZNRG.cjs.map +0 -1
  76. package/dist/chunk-CYOI4PEA.js.map +0 -1
  77. package/dist/chunk-DSC3G6QZ.js.map +0 -1
  78. package/dist/chunk-J33ZEM3A.js.map +0 -1
  79. package/dist/chunk-PXPPZF5K.cjs.map +0 -1
  80. package/dist/chunk-ZIRFXBKL.cjs.map +0 -1
package/README.md CHANGED
@@ -215,6 +215,29 @@ await wallet.send({ address: 'ark1q...', amount: 1000 })
215
215
 
216
216
  Identities without `signMultiple` continue to work unchanged — each checkpoint is signed individually via `sign()`.
217
217
 
218
+ ### Ark Provider Caching
219
+
220
+ `RestArkProvider.getInfo()` fetches current Arkade server parameters on every call. Wrap it
221
+ with `CachingArkProvider` when you reuse that response for fee, signer, or limit lookups:
222
+
223
+ ```typescript
224
+ import { CachingArkProvider, RestArkProvider, Wallet } from '@arkade-os/sdk'
225
+
226
+ const arkProvider = new CachingArkProvider(
227
+ new RestArkProvider('https://arkade.computer'),
228
+ 60_000, // optional TTL in milliseconds; defaults to 60 seconds
229
+ )
230
+
231
+ const wallet = await Wallet.create({ identity, arkProvider })
232
+ ```
233
+
234
+ Only `getInfo()` is cached; all other Ark provider methods pass through. The cache expires
235
+ after the TTL and updates when the inner provider reports server-info changes, including
236
+ signer rotation. Wrapping `RestArkProvider` preserves its `serverUrl`, so `Wallet.create`
237
+ can still derive the default indexer URL. Expired refresh failures propagate;
238
+ wallet boot fallback lives in the persisted ArkInfo snapshot. Call `dispose()` if the
239
+ inner provider outlives the wrapper, to drop its server-info subscription.
240
+
218
241
  ### Onchain Providers
219
242
 
220
243
  Wallets read onchain state (UTXOs, transactions, fee rates, chain tip) through an `OnchainProvider`. The SDK ships with two implementations and a single transport-agnostic interface so you can swap them without touching wallet code.
@@ -226,6 +249,8 @@ Wallets read onchain state (UTXOs, transactions, fee rates, chain tip) through a
226
249
 
227
250
  If you don't pass a provider explicitly, `OnchainWallet` and `Wallet.create({ ... })` both default to `EsploraProvider` pointing at the URL in `ESPLORA_URL[networkName]`.
228
251
 
252
+ > **New:** the interface also requires `getRawTransaction(txid): Promise<Uint8Array>`, the raw wire bytes of a transaction. Emulator v0.0.7+ demands the previous transaction of every input a covenant spend or intent proof carries, and a boarding or commitment parent has no off-chain source. Both shipped providers implement it; a custom `OnchainProvider` has to add it.
253
+
229
254
  #### Default URLs
230
255
 
231
256
  The SDK ships with reachable defaults for each network — bitcoin, signet, and mutinynet point at Ark Labs–operated deployments; testnet falls back to mempool.space; regtest assumes a local [arkade-regtest](https://github.com/ArkLabsHQ/arkade-regtest) stack (esplora API on `http://localhost:3000/api`).
@@ -345,21 +370,27 @@ console.log('Gated by a contract:', balance.gated) // swap escrow, chiefly
345
370
  console.log('Locked by an in-flight intent:', balance.intentLocked)
346
371
  console.log('Recoverable:', balance.recoverable)
347
372
  console.log('Awaiting recovery:', balance.pendingRecovery)
373
+ console.log('Unilaterally exited:', balance.unrolled)
348
374
  ```
349
375
 
350
376
  `settled` and `preconfirmed` are the owned offchain buckets this relationship is
351
- about — `recoverable` and `pendingRecovery` are the wallet's funds too, just held
352
- under a different predicate. `available` is what generic spending will actually
353
- pick, and the difference between the two is accounted for exactly:
377
+ about — `recoverable`, `pendingRecovery` and `unrolled` are the wallet's funds
378
+ too, just held under a different predicate. `available` is what generic spending
379
+ will actually pick, and the difference between the two is accounted for exactly:
354
380
 
355
381
  ```text
356
382
  settled + preconfirmed === available + gated + intentLocked
357
383
  ```
358
384
 
385
+ `unrolled` holds virtual outputs whose unilateral exit already happened: they sit
386
+ onchain behind their CSV timelock, so nothing offchain can move them and
387
+ `Unroll.completeUnroll` is the only thing that will. They are never `available` and
388
+ never `recoverable` — but they are still your money, so they still count in `total`.
389
+
359
390
  To show "your money, minus what is tied up", subtract from `settled + preconfirmed`
360
- — **not from `total`**, which also contains `boarding.total`, `recoverable` and
361
- `pendingRecovery`. Those are still your funds, so subtracting a bucket from `total`
362
- silently drops them from the figure.
391
+ — **not from `total`**, which also contains `boarding.total`, `recoverable`,
392
+ `pendingRecovery` and `unrolled`. Those are still your funds, so subtracting a bucket
393
+ from `total` silently drops them from the figure.
363
394
 
364
395
  ```typescript
365
396
 
@@ -747,12 +778,7 @@ const onchainWallet = await OnchainWallet.create(onchainIdentity, 'regtest');
747
778
 
748
779
  // Unroll a specific virtual output
749
780
  const vtxo = { txid: 'your_vtxo_txid', vout: 0 };
750
- const session = await Unroll.Session.create(
751
- vtxo,
752
- onchainWallet,
753
- onchainWallet.provider,
754
- wallet.indexerProvider
755
- );
781
+ const session = await Unroll.sessionFor(wallet, vtxo, onchainWallet);
756
782
 
757
783
  // Iterate through the unrolling steps
758
784
  for await (const step of session) {
@@ -770,6 +796,24 @@ for await (const step of session) {
770
796
  }
771
797
  ```
772
798
 
799
+ `Unroll.sessionFor` is `Session.create` with the wallet's explorer, indexer and
800
+ virtual-tx cache filled in, plus the exit observer wired: at `StepType.DONE` it re-reads
801
+ the outpoint from the indexer, so the value moves into the `unrolled` balance bucket
802
+ without waiting for a sync that would never bring it. Nothing else would tell the wallet
803
+ — delta sync filters on creation time, so it never sees a status change on an older
804
+ virtual output.
805
+
806
+ That re-read is a prompt rather than a guarantee: `StepType.DONE` means your Esplora
807
+ endpoint saw the exit confirm, and the Arkade indexer may not have marked the output
808
+ `isUnrolled` yet. The session fires once, so a re-read that lands early simply leaves the
809
+ wallet where it would have been anyway, and the next thing to refresh that outpoint picks
810
+ the exit up. `UnilateralExit` fires twice per virtual output — branch-confirmed and
811
+ sweep-confirmed — and by the sweep the exit has been onchain for at least the CSV delay.
812
+
813
+ If you hold no `Wallet` — driving an exit from providers alone — build the session with
814
+ the lower-level `Unroll.Session.create(vtxo, bumper, explorer, indexer,
815
+ virtualTxRepository?, onExitObserved?)`, whose last two parameters are optional.
816
+
773
817
  The unrolling process works by:
774
818
 
775
819
  - Traversing the transaction chain from the root (most recent) to the leaf (oldest)
@@ -819,9 +863,10 @@ await Unroll.completeUnroll(
819
863
 
820
864
  ### Unilateral Exit Packages (pre-signed)
821
865
 
822
- `Unroll.Session` requires the wallet (keys + indexer access) to stay online for the whole
823
- multi-day exit. `UnilateralExit` removes that requirement: it pre-signs **every** transaction
824
- needed to unroll a VTXO's offchain transaction chain onchain **and** sweep each matured output
866
+ `Unroll.sessionFor` (and the `Unroll.Session` it builds) requires the wallet keys plus
867
+ indexer access — to stay online for the whole multi-day exit. `UnilateralExit` removes that
868
+ requirement: it pre-signs **every** transaction needed to unroll a VTXO's offchain
869
+ transaction chain onchain **and** sweep each matured output
825
870
  to an address you solely control, then emits a versioned JSON package that anything with an
826
871
  Esplora-compatible endpoint can execute — no keys, no Arkade infrastructure.
827
872
 
@@ -858,6 +903,12 @@ for await (const event of executor) {
858
903
  }
859
904
  ```
860
905
 
906
+ Where the executing machine does hold the `Wallet`, `UnilateralExit.execute(wallet, pkg, opts?)`
907
+ returns the same executor with the exit observer already wired, so the repository re-reads each
908
+ branch as it confirms and again as its sweep does — picking the exit up as it lands, indexer lag
909
+ permitting. The same prompt-not-guarantee caveat as `Unroll.sessionFor` above applies, with the
910
+ sweep-confirm re-read as its own retry.
911
+
861
912
  Every exit terminates in a **sweep**. Unrolling only lands a VTXO back onchain still encumbered
862
913
  by its Arkade script; the funds become yours unilaterally only once a sweep spends that output
863
914
  through the CSV-timelocked exit path to `sweepAddress`. So the package always pairs each exited
@@ -1,19 +1,19 @@
1
1
  'use strict';
2
2
 
3
- var chunkIM6IKNSL_cjs = require('../chunk-IM6IKNSL.cjs');
4
- require('../chunk-3S3JZUEN.cjs');
5
- require('../chunk-ZIRFXBKL.cjs');
3
+ var chunkR2YAMONM_cjs = require('../chunk-R2YAMONM.cjs');
4
+ require('../chunk-CO3KKSWM.cjs');
5
+ require('../chunk-2JV4VQ7C.cjs');
6
6
  require('../chunk-5BLDMQED.cjs');
7
7
 
8
8
 
9
9
 
10
10
  Object.defineProperty(exports, "ExpoArkProvider", {
11
11
  enumerable: true,
12
- get: function () { return chunkIM6IKNSL_cjs.ExpoArkProvider; }
12
+ get: function () { return chunkR2YAMONM_cjs.ExpoArkProvider; }
13
13
  });
14
14
  Object.defineProperty(exports, "ExpoIndexerProvider", {
15
15
  enumerable: true,
16
- get: function () { return chunkIM6IKNSL_cjs.ExpoIndexerProvider; }
16
+ get: function () { return chunkR2YAMONM_cjs.ExpoIndexerProvider; }
17
17
  });
18
18
  //# sourceMappingURL=expo.cjs.map
19
19
  //# sourceMappingURL=expo.cjs.map
@@ -1,5 +1,5 @@
1
- import { l as RestArkProvider, i as SettlementEvent, T as TxNotificationEvent, m as RestIndexerProvider, n as SubscriptionResponse } from '../index-uUE_uQPn.cjs';
2
- export { o as ArkProvider, p as IndexerProvider } from '../index-uUE_uQPn.cjs';
1
+ import { n as RestArkProvider, k as SettlementEvent, T as TxNotificationEvent, o as RestIndexerProvider, p as SubscriptionResponse } from '../index-DU5o_hz7.cjs';
2
+ export { q as ArkProvider, r as IndexerProvider } from '../index-DU5o_hz7.cjs';
3
3
  import '@scure/btc-signer/utils.js';
4
4
  import '@scure/btc-signer/transaction.js';
5
5
  import '@scure/btc-signer';
@@ -1,5 +1,5 @@
1
- import { l as RestArkProvider, i as SettlementEvent, T as TxNotificationEvent, m as RestIndexerProvider, n as SubscriptionResponse } from '../index-uUE_uQPn.js';
2
- export { o as ArkProvider, p as IndexerProvider } from '../index-uUE_uQPn.js';
1
+ import { n as RestArkProvider, k as SettlementEvent, T as TxNotificationEvent, o as RestIndexerProvider, p as SubscriptionResponse } from '../index-DU5o_hz7.js';
2
+ export { q as ArkProvider, r as IndexerProvider } from '../index-DU5o_hz7.js';
3
3
  import '@scure/btc-signer/utils.js';
4
4
  import '@scure/btc-signer/transaction.js';
5
5
  import '@scure/btc-signer';
@@ -1,6 +1,6 @@
1
- export { ExpoArkProvider, ExpoIndexerProvider } from '../chunk-R5POS3RS.js';
2
- import '../chunk-2JZGPXU4.js';
3
- import '../chunk-J33ZEM3A.js';
1
+ export { ExpoArkProvider, ExpoIndexerProvider } from '../chunk-MZFUZUTQ.js';
2
+ import '../chunk-X3VEMUVV.js';
3
+ import '../chunk-3WIWNE4P.js';
4
4
  import '../chunk-NSBPE2FW.js';
5
5
  //# sourceMappingURL=expo.js.map
6
6
  //# sourceMappingURL=expo.js.map
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunk5E6IZNRG_cjs = require('../chunk-5E6IZNRG.cjs');
4
- require('../chunk-3S3JZUEN.cjs');
5
- require('../chunk-PXPPZF5K.cjs');
6
- require('../chunk-ZIRFXBKL.cjs');
3
+ var chunkMJUTO3PY_cjs = require('../chunk-MJUTO3PY.cjs');
4
+ require('../chunk-CO3KKSWM.cjs');
5
+ require('../chunk-OIZ2V2VD.cjs');
6
+ require('../chunk-2JV4VQ7C.cjs');
7
7
  require('../chunk-5BLDMQED.cjs');
8
8
 
9
9
  // src/storage/indexedDB.ts
@@ -11,7 +11,7 @@ var IndexedDBStorageAdapter = class {
11
11
  dbName;
12
12
  version;
13
13
  db = null;
14
- constructor(dbName, version = chunk5E6IZNRG_cjs.DB_VERSION) {
14
+ constructor(dbName, version = chunkMJUTO3PY_cjs.DB_VERSION) {
15
15
  this.dbName = dbName;
16
16
  this.version = version;
17
17
  }
@@ -1,7 +1,7 @@
1
- import { DB_VERSION } from '../chunk-DSC3G6QZ.js';
2
- import '../chunk-2JZGPXU4.js';
3
- import '../chunk-CYOI4PEA.js';
4
- import '../chunk-J33ZEM3A.js';
1
+ import { DB_VERSION } from '../chunk-AEWJU6NZ.js';
2
+ import '../chunk-X3VEMUVV.js';
3
+ import '../chunk-6TAQF6EV.js';
4
+ import '../chunk-3WIWNE4P.js';
5
5
  import '../chunk-NSBPE2FW.js';
6
6
 
7
7
  // src/storage/indexedDB.ts
@@ -1,4 +1,4 @@
1
- import { a as TaskQueue, c as TaskItem, d as TaskResult } from './taskRunner-BOVcIH1N.cjs';
1
+ import { c as TaskQueue, b as TaskItem, d as TaskResult } from './taskRunner-BZJMLQ6g.cjs';
2
2
 
3
3
  /**
4
4
  * Minimal async key-value storage interface.
@@ -46,4 +46,4 @@ declare class AsyncStorageTaskQueue implements TaskQueue {
46
46
  private writeList;
47
47
  }
48
48
 
49
- export { AsyncStorageTaskQueue as A, type AsyncStorageLike as a };
49
+ export { type AsyncStorageLike as A, AsyncStorageTaskQueue as a };
@@ -1,4 +1,4 @@
1
- import { a as TaskQueue, c as TaskItem, d as TaskResult } from './taskRunner-DNyD1kXG.js';
1
+ import { c as TaskQueue, b as TaskItem, d as TaskResult } from './taskRunner-DATaRQus.js';
2
2
 
3
3
  /**
4
4
  * Minimal async key-value storage interface.
@@ -46,4 +46,4 @@ declare class AsyncStorageTaskQueue implements TaskQueue {
46
46
  private writeList;
47
47
  }
48
48
 
49
- export { AsyncStorageTaskQueue as A, type AsyncStorageLike as a };
49
+ export { type AsyncStorageLike as A, AsyncStorageTaskQueue as a };
@@ -1032,7 +1032,7 @@ function resolveEventSource(override) {
1032
1032
  }
1033
1033
 
1034
1034
  // package.json
1035
- var version = "0.4.66";
1035
+ var version = "0.4.67";
1036
1036
 
1037
1037
  // src/utils/fetch.ts
1038
1038
  var buildVersion = "0.9.9";
@@ -1349,6 +1349,9 @@ function prepareCoinAsIntentProofInput(coin) {
1349
1349
  if (coin.extraWitness) {
1350
1350
  unknown.push(ConditionWitness.encode(coin.extraWitness));
1351
1351
  }
1352
+ if (coin.prevTx) {
1353
+ unknown.push(PrevArkTxField.encode(coin.prevTx));
1354
+ }
1352
1355
  return {
1353
1356
  txid: base.hex.decode(coin.txid),
1354
1357
  index: coin.vout,
@@ -1627,17 +1630,17 @@ var RestArkProvider = class {
1627
1630
  /** Overrides {@link configureEventSource} for this provider's streams. */
1628
1631
  eventSource;
1629
1632
  /**
1630
- * Last server-info digest seen (from {@link getInfo}). Sent as `X-Digest`
1631
- * on outgoing requests so arkd can reject a client whose cached info is
1632
- * stale. Empty until the first {@link getInfo}.
1633
+ * Last server-info digest seen from {@link getInfo}. Sent as `X-Digest`
1634
+ * so arkd can reject stale client configuration.
1633
1635
  */
1634
1636
  _digest = "";
1637
+ _hasServerInfo = false;
1638
+ _suppressNextGetInfoChangeEmit = false;
1635
1639
  _serverInfoListeners = /* @__PURE__ */ new Set();
1636
1640
  /**
1637
- * Subscribe to server-info changes. Fired when a request is rejected with
1638
- * `DIGEST_MISMATCH` and fresh info is re-fetched, so consumers (the wallet)
1639
- * can re-derive signer-dependent state mid-session without polling. Returns
1640
- * an unsubscribe function.
1641
+ * Subscribe to server-info changes. Fired after a stale-info
1642
+ * `DIGEST_MISMATCH` refresh or when {@link getInfo} observes a changed digest.
1643
+ * Returns an unsubscribe function.
1641
1644
  */
1642
1645
  onServerInfoChanged(listener) {
1643
1646
  this._serverInfoListeners.add(listener);
@@ -1692,7 +1695,13 @@ var RestArkProvider = class {
1692
1695
  if (!arkError) throwIfHttpUnavailable(response, "arkade");
1693
1696
  if (!isArkError(arkError, ArkErrorName.DIGEST_MISMATCH)) return response;
1694
1697
  this._digest = "";
1695
- const info = await this.getInfo();
1698
+ this._suppressNextGetInfoChangeEmit = true;
1699
+ let info;
1700
+ try {
1701
+ info = await this.getInfo();
1702
+ } finally {
1703
+ this._suppressNextGetInfoChangeEmit = false;
1704
+ }
1696
1705
  this.emitServerInfoChanged(info);
1697
1706
  throw new DigestMismatchError(
1698
1707
  "Arkade server reported a configuration digest mismatch; server info was refreshed. Rebuild and retry the request under the new server info."
@@ -1749,7 +1758,13 @@ var RestArkProvider = class {
1749
1758
  vtxoMaxAmount: BigInt(fromServer.vtxoMaxAmount ?? -1),
1750
1759
  vtxoMinAmount: BigInt(fromServer.vtxoMinAmount ?? 0)
1751
1760
  };
1761
+ const previousDigest = this._digest;
1762
+ const hadServerInfo = this._hasServerInfo;
1752
1763
  this._digest = info.digest;
1764
+ this._hasServerInfo = true;
1765
+ if (hadServerInfo && previousDigest !== info.digest && !this._suppressNextGetInfoChangeEmit) {
1766
+ this.emitServerInfoChanged(info);
1767
+ }
1753
1768
  return info;
1754
1769
  }
1755
1770
  async submitTx(signedArkTx, checkpointTxs) {
@@ -2384,11 +2399,15 @@ function isPastExpiry(vtxo, now) {
2384
2399
  }
2385
2400
  function canSpendOffchain(vtxo, now) {
2386
2401
  const n = normalizeVtxo(vtxo);
2387
- return !hasTerminalSpend(n) && !(n.isSwept || isPastExpiry(n, now));
2402
+ return !hasTerminalSpend(n) && !n.isUnrolled && !(n.isSwept || isPastExpiry(n, now));
2388
2403
  }
2389
2404
  function canRecoverOnchain(vtxo, now) {
2390
2405
  const n = normalizeVtxo(vtxo);
2391
- return !hasTerminalSpend(n) && (n.isSwept || isPastExpiry(n, now));
2406
+ return !hasTerminalSpend(n) && !n.isUnrolled && (n.isSwept || isPastExpiry(n, now));
2407
+ }
2408
+ function canSweepOnchain(vtxo) {
2409
+ const n = normalizeVtxo(vtxo);
2410
+ return !hasTerminalSpend(n) && !!n.isUnrolled;
2392
2411
  }
2393
2412
  function toOffchainInputFeeParams(vtxo) {
2394
2413
  const batchExpiry = toBatchExpiry(vtxo);
@@ -2450,6 +2469,7 @@ exports.baseFetch = baseFetch;
2450
2469
  exports.buildVersion = buildVersion;
2451
2470
  exports.canRecoverOnchain = canRecoverOnchain;
2452
2471
  exports.canSpendOffchain = canSpendOffchain;
2472
+ exports.canSweepOnchain = canSweepOnchain;
2453
2473
  exports.configureEventSource = configureEventSource;
2454
2474
  exports.convertVtxo = convertVtxo;
2455
2475
  exports.craftToSpendTx = craftToSpendTx;
@@ -2493,5 +2513,5 @@ exports.toBatchExpiry = toBatchExpiry;
2493
2513
  exports.toOffchainInputFeeParams = toOffchainInputFeeParams;
2494
2514
  exports.toProviderUnavailable = toProviderUnavailable;
2495
2515
  exports.toVirtualStatus = toVirtualStatus;
2496
- //# sourceMappingURL=chunk-ZIRFXBKL.cjs.map
2497
- //# sourceMappingURL=chunk-ZIRFXBKL.cjs.map
2516
+ //# sourceMappingURL=chunk-2JV4VQ7C.cjs.map
2517
+ //# sourceMappingURL=chunk-2JV4VQ7C.cjs.map