@arkade-os/sdk 0.4.34 → 0.4.35

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 (69) hide show
  1. package/dist/adapters/expo.cjs +4 -4
  2. package/dist/adapters/expo.d.cts +2 -2
  3. package/dist/adapters/expo.d.ts +2 -2
  4. package/dist/adapters/expo.js +2 -2
  5. package/dist/adapters/indexedDB.cjs +3 -3
  6. package/dist/adapters/indexedDB.js +2 -2
  7. package/dist/{ark-Dsv5Jq4E.d.cts → ark-D6sau_6-.d.cts} +458 -3
  8. package/dist/{ark-Dsv5Jq4E.d.ts → ark-D6sau_6-.d.ts} +458 -3
  9. package/dist/{asyncStorageTaskQueue-D92ch8yI.d.cts → asyncStorageTaskQueue-CpC027t_.d.cts} +2 -2
  10. package/dist/{asyncStorageTaskQueue-BH-zuth5.d.ts → asyncStorageTaskQueue-GT8fmPUG.d.ts} +2 -2
  11. package/dist/{chunk-FXFBPXV3.js → chunk-3JR77WQ4.js} +139 -41
  12. package/dist/chunk-3JR77WQ4.js.map +1 -0
  13. package/dist/{chunk-ZS3OZHC7.cjs → chunk-FM7T7JVL.cjs} +7 -7
  14. package/dist/{chunk-ZS3OZHC7.cjs.map → chunk-FM7T7JVL.cjs.map} +1 -1
  15. package/dist/{chunk-XCHBQVMK.cjs → chunk-H2LX2KKY.cjs} +1540 -265
  16. package/dist/chunk-H2LX2KKY.cjs.map +1 -0
  17. package/dist/{chunk-HFXEUW55.js → chunk-NOR7XOKN.js} +1472 -202
  18. package/dist/chunk-NOR7XOKN.js.map +1 -0
  19. package/dist/{chunk-VVGD3JIP.js → chunk-OURFR4UR.js} +3 -3
  20. package/dist/{chunk-VVGD3JIP.js.map → chunk-OURFR4UR.js.map} +1 -1
  21. package/dist/{chunk-CCLNFHJ5.cjs → chunk-VYS3KGRI.cjs} +16 -10
  22. package/dist/chunk-VYS3KGRI.cjs.map +1 -0
  23. package/dist/{chunk-FSAXPBGP.cjs → chunk-X2EQLK4O.cjs} +143 -40
  24. package/dist/chunk-X2EQLK4O.cjs.map +1 -0
  25. package/dist/{chunk-5WDBHWX3.js → chunk-XQS2HW4Q.js} +10 -4
  26. package/dist/chunk-XQS2HW4Q.js.map +1 -0
  27. package/dist/contracts/handlers/index.d.cts +3 -3
  28. package/dist/contracts/handlers/index.d.ts +3 -3
  29. package/dist/{delegate-BaS5SCIW.d.cts → delegate-C-L6gSZx.d.cts} +1 -1
  30. package/dist/{delegate-Baz_hb83.d.ts → delegate-De5__fpZ.d.ts} +1 -1
  31. package/dist/{index-FwXZveaX.d.ts → index-BETdjE_o.d.ts} +2 -2
  32. package/dist/{index-lNZ6qaO3.d.cts → index-jwQfHP6D.d.cts} +2 -2
  33. package/dist/index.cjs +129 -105
  34. package/dist/index.d.cts +69 -9
  35. package/dist/index.d.ts +69 -9
  36. package/dist/index.js +2 -2
  37. package/dist/repositories/realm/index.cjs +12 -12
  38. package/dist/repositories/realm/index.cjs.map +1 -1
  39. package/dist/repositories/realm/index.d.cts +2 -2
  40. package/dist/repositories/realm/index.d.ts +2 -2
  41. package/dist/repositories/realm/index.js +3 -3
  42. package/dist/repositories/realm/index.js.map +1 -1
  43. package/dist/repositories/sqlite/index.cjs +11 -11
  44. package/dist/repositories/sqlite/index.d.cts +1 -1
  45. package/dist/repositories/sqlite/index.d.ts +1 -1
  46. package/dist/repositories/sqlite/index.js +2 -2
  47. package/dist/{taskRunner-vFRA3F9b.d.cts → taskRunner-DCyp6Gea.d.cts} +2 -2
  48. package/dist/{taskRunner-B1NUWyWR.d.ts → taskRunner-DnxtObeq.d.ts} +2 -2
  49. package/dist/wallet/expo/background.cjs +12 -12
  50. package/dist/wallet/expo/background.d.cts +3 -3
  51. package/dist/wallet/expo/background.d.ts +3 -3
  52. package/dist/wallet/expo/background.js +4 -4
  53. package/dist/wallet/expo/index.cjs +11 -11
  54. package/dist/wallet/expo/index.d.cts +4 -4
  55. package/dist/wallet/expo/index.d.ts +4 -4
  56. package/dist/wallet/expo/index.js +3 -3
  57. package/dist/{wallet-D6uoBLmS.d.ts → wallet-BWHbd5b1.d.cts} +231 -8
  58. package/dist/{wallet-By9HIo0Q.d.cts → wallet-Bth5uucA.d.ts} +231 -8
  59. package/dist/worker/expo/index.cjs +7 -7
  60. package/dist/worker/expo/index.d.cts +4 -4
  61. package/dist/worker/expo/index.d.ts +4 -4
  62. package/dist/worker/expo/index.js +3 -3
  63. package/package.json +2 -2
  64. package/dist/chunk-5WDBHWX3.js.map +0 -1
  65. package/dist/chunk-CCLNFHJ5.cjs.map +0 -1
  66. package/dist/chunk-FSAXPBGP.cjs.map +0 -1
  67. package/dist/chunk-FXFBPXV3.js.map +0 -1
  68. package/dist/chunk-HFXEUW55.js.map +0 -1
  69. package/dist/chunk-XCHBQVMK.cjs.map +0 -1
@@ -136,23 +136,27 @@ function maybeArkError(error) {
136
136
  try {
137
137
  if (!(error instanceof Error)) return void 0;
138
138
  const decoded = JSON.parse(error.message);
139
- if (!("details" in decoded)) return void 0;
140
- if (!Array.isArray(decoded.details)) return void 0;
141
- for (const details of decoded.details) {
142
- if (!("@type" in details)) continue;
143
- const type = details["@type"];
144
- if (type !== "type.googleapis.com/ark.v1.ErrorDetails") continue;
145
- if (!("code" in details)) continue;
146
- const code = details.code;
147
- if (!("message" in details)) continue;
148
- const message = details.message;
149
- if (!("name" in details)) continue;
150
- const name = details.name;
151
- let metadata;
152
- if ("metadata" in details && isMetadata(details.metadata)) {
153
- metadata = details.metadata;
139
+ if (Array.isArray(decoded.details)) {
140
+ for (const details of decoded.details) {
141
+ if (!("@type" in details)) continue;
142
+ const type = details["@type"];
143
+ if (type !== "type.googleapis.com/ark.v1.ErrorDetails") continue;
144
+ if (!("code" in details)) continue;
145
+ const code = details.code;
146
+ if (!("message" in details)) continue;
147
+ const message = details.message;
148
+ if (!("name" in details)) continue;
149
+ const name = details.name;
150
+ let metadata;
151
+ if ("metadata" in details && isMetadata(details.metadata)) {
152
+ metadata = details.metadata;
153
+ }
154
+ return new ArkError(code, message, name, metadata);
154
155
  }
155
- return new ArkError(code, message, name, metadata);
156
+ }
157
+ if (typeof decoded.message === "string") {
158
+ const m = decoded.message.match(/^([A-Z][A-Z0-9_]*) \((\d+)\): ([\s\S]*)$/);
159
+ if (m) return new ArkError(Number(m[2]), m[3], m[1]);
156
160
  }
157
161
  return void 0;
158
162
  } catch (e) {
@@ -435,7 +439,32 @@ function isEventSourceError(error) {
435
439
  return error instanceof Error && error.name === "EventSourceError";
436
440
  }
437
441
 
442
+ // package.json
443
+ var version = "0.4.35";
444
+
445
+ // src/utils/fetch.ts
446
+ var buildVersion = "0.9.9";
447
+ var sdkVersion = `ts-sdk/${version}`;
448
+ function baseFetch(input, init) {
449
+ if (typeof globalThis.fetch !== "function") {
450
+ throw new Error("Fetch API is not available in this environment.");
451
+ }
452
+ return globalThis.fetch(input, init);
453
+ }
454
+ function fetch(input, init) {
455
+ const headers = new Headers(init?.headers);
456
+ headers.set("X-Build-Version", buildVersion);
457
+ headers.set("X-SDK-VERSION", sdkVersion);
458
+ return baseFetch(input, { ...init, headers });
459
+ }
460
+
438
461
  // src/providers/ark.ts
462
+ var DigestMismatchError = class extends Error {
463
+ constructor(message) {
464
+ super(message);
465
+ this.name = "DigestMismatchError";
466
+ }
467
+ };
439
468
  var SettlementEventType = /* @__PURE__ */ ((SettlementEventType2) => {
440
469
  SettlementEventType2["BatchStarted"] = "batch_started";
441
470
  SettlementEventType2["BatchFinalization"] = "batch_finalization";
@@ -452,6 +481,67 @@ var RestArkProvider = class {
452
481
  constructor(serverUrl = DEFAULT_ARKADE_SERVER_URL) {
453
482
  this.serverUrl = serverUrl;
454
483
  }
484
+ /**
485
+ * Last server-info digest seen (from {@link getInfo}). Sent as `X-Digest`
486
+ * on outgoing requests so arkd can reject a client whose cached info is
487
+ * stale. Empty until the first {@link getInfo}.
488
+ */
489
+ _digest = "";
490
+ _serverInfoListeners = /* @__PURE__ */ new Set();
491
+ /**
492
+ * Subscribe to server-info changes. Fired when a request is rejected with
493
+ * `DIGEST_MISMATCH` and fresh info is re-fetched, so consumers (the wallet)
494
+ * can re-derive signer-dependent state mid-session without polling. Returns
495
+ * an unsubscribe function.
496
+ */
497
+ onServerInfoChanged(listener) {
498
+ this._serverInfoListeners.add(listener);
499
+ return () => {
500
+ this._serverInfoListeners.delete(listener);
501
+ };
502
+ }
503
+ emitServerInfoChanged(info) {
504
+ for (const listener of this._serverInfoListeners) {
505
+ try {
506
+ listener(info);
507
+ } catch (e) {
508
+ console.warn("onServerInfoChanged listener threw", e);
509
+ }
510
+ }
511
+ }
512
+ /**
513
+ * `fetch` wrapper for arkd requests that participates in server-info digest
514
+ * negotiation. Sends the cached `X-Digest`; when arkd rejects a request with
515
+ * `DIGEST_MISMATCH`, refreshes {@link getInfo} (updating the digest), fires
516
+ * {@link onServerInfoChanged}, and THROWS {@link DigestMismatchError} — it
517
+ * never silently retries, since the in-flight request was built against the
518
+ * now-stale config. Dormant until arkd returns the error — then it is the
519
+ * instant, event-driven signer-rotation trigger. {@link getInfo} itself never
520
+ * routes through here: it is the refresh path and must not be digest-gated.
521
+ */
522
+ async authedFetch(url, init) {
523
+ const digest = this._digest;
524
+ const headers = {
525
+ ...init.headers
526
+ };
527
+ if (digest) headers["X-Digest"] = digest;
528
+ const response = await fetch(url, { ...init, headers });
529
+ if (response.ok) return response;
530
+ let body;
531
+ try {
532
+ body = await response.clone().text();
533
+ } catch (e) {
534
+ console.warn("authedFetch could not read response body for digest check", e);
535
+ return response;
536
+ }
537
+ if (maybeArkError(new Error(body))?.name !== "DIGEST_MISMATCH") return response;
538
+ this._digest = "";
539
+ const info = await this.getInfo();
540
+ this.emitServerInfoChanged(info);
541
+ throw new DigestMismatchError(
542
+ "Arkade server reported a configuration digest mismatch; server info was refreshed. Rebuild and retry the request under the new server info."
543
+ );
544
+ }
455
545
  async getInfo() {
456
546
  const url = `${this.serverUrl}/v1/info`;
457
547
  const response = await fetch(url);
@@ -460,10 +550,16 @@ var RestArkProvider = class {
460
550
  handleError(errorText, `Failed to get server info: ${response.statusText}`);
461
551
  }
462
552
  const fromServer = await response.json();
463
- return {
553
+ const info = {
464
554
  boardingExitDelay: BigInt(fromServer.boardingExitDelay ?? 0),
465
555
  checkpointTapscript: fromServer.checkpointTapscript ?? "",
466
556
  deprecatedSigners: fromServer.deprecatedSigners?.map((signer) => ({
557
+ // arkd advertises `cutoffDate` as a non-nullable field, so it
558
+ // is always a bigint here — `0n` is the sentinel for "no
559
+ // cutoff" (the classifier maps it to DUE_NOW). The grpc-gateway
560
+ // marshals with EmitUnpopulated, so an unset `cutoff_date`
561
+ // already arrives as `"0"`; a genuinely missing field defaults
562
+ // to `0n` too. Never collapse to `undefined`.
467
563
  cutoffDate: BigInt(signer.cutoffDate ?? 0),
468
564
  pubkey: signer.pubkey ?? ""
469
565
  })) ?? [],
@@ -493,10 +589,12 @@ var RestArkProvider = class {
493
589
  vtxoMaxAmount: BigInt(fromServer.vtxoMaxAmount ?? -1),
494
590
  vtxoMinAmount: BigInt(fromServer.vtxoMinAmount ?? 0)
495
591
  };
592
+ this._digest = info.digest;
593
+ return info;
496
594
  }
497
595
  async submitTx(signedArkTx, checkpointTxs) {
498
596
  const url = `${this.serverUrl}/v1/tx/submit`;
499
- const response = await fetch(url, {
597
+ const response = await this.authedFetch(url, {
500
598
  method: "POST",
501
599
  headers: {
502
600
  "Content-Type": "application/json"
@@ -519,7 +617,7 @@ var RestArkProvider = class {
519
617
  }
520
618
  async finalizeTx(arkTxid, finalCheckpointTxs) {
521
619
  const url = `${this.serverUrl}/v1/tx/finalize`;
522
- const response = await fetch(url, {
620
+ const response = await this.authedFetch(url, {
523
621
  method: "POST",
524
622
  headers: {
525
623
  "Content-Type": "application/json"
@@ -536,7 +634,7 @@ var RestArkProvider = class {
536
634
  }
537
635
  async registerIntent(intent) {
538
636
  const url = `${this.serverUrl}/v1/batch/registerIntent`;
539
- const response = await fetch(url, {
637
+ const response = await this.authedFetch(url, {
540
638
  method: "POST",
541
639
  headers: {
542
640
  "Content-Type": "application/json"
@@ -557,7 +655,7 @@ var RestArkProvider = class {
557
655
  }
558
656
  async deleteIntent(intent) {
559
657
  const url = `${this.serverUrl}/v1/batch/deleteIntent`;
560
- const response = await fetch(url, {
658
+ const response = await this.authedFetch(url, {
561
659
  method: "POST",
562
660
  headers: {
563
661
  "Content-Type": "application/json"
@@ -576,7 +674,7 @@ var RestArkProvider = class {
576
674
  }
577
675
  async confirmRegistration(intentId) {
578
676
  const url = `${this.serverUrl}/v1/batch/ack`;
579
- const response = await fetch(url, {
677
+ const response = await this.authedFetch(url, {
580
678
  method: "POST",
581
679
  headers: {
582
680
  "Content-Type": "application/json"
@@ -592,7 +690,7 @@ var RestArkProvider = class {
592
690
  }
593
691
  async submitTreeNonces(batchId, pubkey, nonces) {
594
692
  const url = `${this.serverUrl}/v1/batch/tree/submitNonces`;
595
- const response = await fetch(url, {
693
+ const response = await this.authedFetch(url, {
596
694
  method: "POST",
597
695
  headers: {
598
696
  "Content-Type": "application/json"
@@ -610,7 +708,7 @@ var RestArkProvider = class {
610
708
  }
611
709
  async submitTreeSignatures(batchId, pubkey, signatures) {
612
710
  const url = `${this.serverUrl}/v1/batch/tree/submitSignatures`;
613
- const response = await fetch(url, {
711
+ const response = await this.authedFetch(url, {
614
712
  method: "POST",
615
713
  headers: {
616
714
  "Content-Type": "application/json"
@@ -628,7 +726,7 @@ var RestArkProvider = class {
628
726
  }
629
727
  async submitSignedForfeitTxs(signedForfeitTxs, signedCommitmentTx) {
630
728
  const url = `${this.serverUrl}/v1/batch/submitForfeitTxs`;
631
- const response = await fetch(url, {
729
+ const response = await this.authedFetch(url, {
632
730
  method: "POST",
633
731
  headers: {
634
732
  "Content-Type": "application/json"
@@ -758,7 +856,7 @@ var RestArkProvider = class {
758
856
  }
759
857
  async getPendingTxs(intent) {
760
858
  const url = `${this.serverUrl}/v1/tx/pending`;
761
- const response = await fetch(url, {
859
+ const response = await this.authedFetch(url, {
762
860
  method: "POST",
763
861
  headers: {
764
862
  "Content-Type": "application/json"
@@ -2201,7 +2299,7 @@ var RestIndexerProvider = class {
2201
2299
  if (params.toString()) {
2202
2300
  url += "?" + params.toString();
2203
2301
  }
2204
- const res = await fetch(url);
2302
+ const res = await baseFetch(url);
2205
2303
  if (!res.ok) {
2206
2304
  throw new Error(`Failed to fetch vtxo tree: ${res.statusText}`);
2207
2305
  }
@@ -2227,7 +2325,7 @@ var RestIndexerProvider = class {
2227
2325
  if (params.toString()) {
2228
2326
  url += "?" + params.toString();
2229
2327
  }
2230
- const res = await fetch(url);
2328
+ const res = await baseFetch(url);
2231
2329
  if (!res.ok) {
2232
2330
  throw new Error(`Failed to fetch vtxo tree leaves: ${res.statusText}`);
2233
2331
  }
@@ -2239,7 +2337,7 @@ var RestIndexerProvider = class {
2239
2337
  }
2240
2338
  async getBatchSweepTransactions(batchOutpoint) {
2241
2339
  const url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/sweepTxs`;
2242
- const res = await fetch(url);
2340
+ const res = await baseFetch(url);
2243
2341
  if (!res.ok) {
2244
2342
  throw new Error(`Failed to fetch batch sweep transactions: ${res.statusText}`);
2245
2343
  }
@@ -2251,7 +2349,7 @@ var RestIndexerProvider = class {
2251
2349
  }
2252
2350
  async getCommitmentTx(txid) {
2253
2351
  const url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}`;
2254
- const res = await fetch(url);
2352
+ const res = await baseFetch(url);
2255
2353
  if (!res.ok) {
2256
2354
  throw new Error(`Failed to fetch commitment tx: ${res.statusText}`);
2257
2355
  }
@@ -2272,7 +2370,7 @@ var RestIndexerProvider = class {
2272
2370
  if (params.toString()) {
2273
2371
  url += "?" + params.toString();
2274
2372
  }
2275
- const res = await fetch(url);
2373
+ const res = await baseFetch(url);
2276
2374
  if (!res.ok) {
2277
2375
  throw new Error(`Failed to fetch commitment tx connectors: ${res.statusText}`);
2278
2376
  }
@@ -2298,7 +2396,7 @@ var RestIndexerProvider = class {
2298
2396
  if (params.toString()) {
2299
2397
  url += "?" + params.toString();
2300
2398
  }
2301
- const res = await fetch(url);
2399
+ const res = await baseFetch(url);
2302
2400
  if (!res.ok) {
2303
2401
  throw new Error(`Failed to fetch commitment tx forfeitTxs: ${res.statusText}`);
2304
2402
  }
@@ -2381,7 +2479,7 @@ var RestIndexerProvider = class {
2381
2479
  if (params.toString()) {
2382
2480
  url += "?" + params.toString();
2383
2481
  }
2384
- const res = await fetch(url);
2482
+ const res = await baseFetch(url);
2385
2483
  if (!res.ok) {
2386
2484
  throw new Error(`Failed to fetch virtual txs: ${res.statusText}`);
2387
2485
  }
@@ -2402,7 +2500,7 @@ var RestIndexerProvider = class {
2402
2500
  if (params.toString()) {
2403
2501
  url += "?" + params.toString();
2404
2502
  }
2405
- const res = await fetch(url);
2503
+ const res = await baseFetch(url);
2406
2504
  if (!res.ok) {
2407
2505
  throw new Error(`Failed to fetch vtxo chain: ${res.statusText}`);
2408
2506
  }
@@ -2461,7 +2559,7 @@ var RestIndexerProvider = class {
2461
2559
  if (params.toString()) {
2462
2560
  url += "?" + params.toString();
2463
2561
  }
2464
- const res = await fetch(url);
2562
+ const res = await baseFetch(url);
2465
2563
  if (!res.ok) {
2466
2564
  throw new Error(`Failed to fetch vtxos: ${res.statusText}`);
2467
2565
  }
@@ -2476,7 +2574,7 @@ var RestIndexerProvider = class {
2476
2574
  }
2477
2575
  async getAssetDetails(assetId) {
2478
2576
  const url = `${this.serverUrl}/v1/indexer/asset/${encodeURIComponent(assetId)}`;
2479
- const res = await fetch(url);
2577
+ const res = await baseFetch(url);
2480
2578
  if (!res.ok) {
2481
2579
  throw new Error(`Failed to fetch asset details: ${res.statusText}`);
2482
2580
  }
@@ -2494,7 +2592,7 @@ var RestIndexerProvider = class {
2494
2592
  }
2495
2593
  async subscribeForScripts(scripts, subscriptionId) {
2496
2594
  const url = `${this.serverUrl}/v1/indexer/script/subscribe`;
2497
- const res = await fetch(url, {
2595
+ const res = await baseFetch(url, {
2498
2596
  headers: {
2499
2597
  "Content-Type": "application/json"
2500
2598
  },
@@ -2511,7 +2609,7 @@ var RestIndexerProvider = class {
2511
2609
  }
2512
2610
  async unsubscribeForScripts(subscriptionId, scripts) {
2513
2611
  const url = `${this.serverUrl}/v1/indexer/script/unsubscribe`;
2514
- const res = await fetch(url, {
2612
+ const res = await baseFetch(url, {
2515
2613
  headers: {
2516
2614
  "Content-Type": "application/json"
2517
2615
  },
@@ -2666,6 +2764,6 @@ var Response;
2666
2764
  Response2.isGetAssetResponse = isGetAssetResponse;
2667
2765
  })(Response || (Response = {}));
2668
2766
 
2669
- export { ArkError, ArkPsbtFieldKey, ArkPsbtFieldKeyType, AssetGroup, AssetId, AssetInput, AssetOutput, AssetRef, BufferReader, ChainTxType, ConditionWitness, CosignerPublicKey, IndexerTxType, Intent, Metadata, OP_RETURN_EMPTY_PKSCRIPT, Packet, RestArkProvider, RestIndexerProvider, SettlementEventType, Transaction, VtxoTaprootTree, VtxoTreeExpiry, asset_exports, craftToSpendTx, getArkPsbtFields, isEventSourceError, isFetchTimeoutError, maybeArkError, setArkPsbtField };
2670
- //# sourceMappingURL=chunk-FXFBPXV3.js.map
2671
- //# sourceMappingURL=chunk-FXFBPXV3.js.map
2767
+ export { ArkError, ArkPsbtFieldKey, ArkPsbtFieldKeyType, AssetGroup, AssetId, AssetInput, AssetOutput, AssetRef, BufferReader, ChainTxType, ConditionWitness, CosignerPublicKey, DigestMismatchError, IndexerTxType, Intent, Metadata, OP_RETURN_EMPTY_PKSCRIPT, Packet, RestArkProvider, RestIndexerProvider, SettlementEventType, Transaction, VtxoTaprootTree, VtxoTreeExpiry, asset_exports, baseFetch, buildVersion, craftToSpendTx, fetch, getArkPsbtFields, isEventSourceError, isFetchTimeoutError, maybeArkError, sdkVersion, setArkPsbtField };
2768
+ //# sourceMappingURL=chunk-3JR77WQ4.js.map
2769
+ //# sourceMappingURL=chunk-3JR77WQ4.js.map