@unicitylabs/sphere-sdk 0.14.1-dev.2 → 0.14.2

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 (39) hide show
  1. package/dist/connect/index.cjs +1 -1
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.js +1 -1
  4. package/dist/connect/index.js.map +1 -1
  5. package/dist/core/index.cjs +69 -27
  6. package/dist/core/index.cjs.map +1 -1
  7. package/dist/core/index.d.cts +21 -1
  8. package/dist/core/index.d.ts +21 -1
  9. package/dist/core/index.js +69 -27
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/impl/browser/connect/index.cjs +1 -1
  12. package/dist/impl/browser/connect/index.cjs.map +1 -1
  13. package/dist/impl/browser/connect/index.js +1 -1
  14. package/dist/impl/browser/connect/index.js.map +1 -1
  15. package/dist/impl/browser/index.cjs +33 -0
  16. package/dist/impl/browser/index.cjs.map +1 -1
  17. package/dist/impl/browser/index.js +33 -0
  18. package/dist/impl/browser/index.js.map +1 -1
  19. package/dist/impl/nodejs/index.cjs +33 -0
  20. package/dist/impl/nodejs/index.cjs.map +1 -1
  21. package/dist/impl/nodejs/index.d.cts +41 -1
  22. package/dist/impl/nodejs/index.d.ts +41 -1
  23. package/dist/impl/nodejs/index.js +33 -0
  24. package/dist/impl/nodejs/index.js.map +1 -1
  25. package/dist/impl/shared/wallet-api/index.d.cts +21 -1
  26. package/dist/impl/shared/wallet-api/index.d.ts +21 -1
  27. package/dist/index.cjs +69 -27
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +21 -1
  30. package/dist/index.d.ts +21 -1
  31. package/dist/index.js +69 -27
  32. package/dist/index.js.map +1 -1
  33. package/dist/modules/payments-v2/index.cjs +36 -26
  34. package/dist/modules/payments-v2/index.cjs.map +1 -1
  35. package/dist/modules/payments-v2/index.d.cts +16 -6
  36. package/dist/modules/payments-v2/index.d.ts +16 -6
  37. package/dist/modules/payments-v2/index.js +35 -26
  38. package/dist/modules/payments-v2/index.js.map +1 -1
  39. package/package.json +1 -1
@@ -226,6 +226,7 @@ interface PendingTransfer {
226
226
  deliveryPending: boolean;
227
227
  createdAt: number;
228
228
  }
229
+ type ConnectionStatus = 'connected' | 'degraded' | 'offline';
229
230
  interface PaymentsV2 {
230
231
  assets(coinId?: string): Promise<Asset[]>;
231
232
  tokens(filter?: {
@@ -242,6 +243,7 @@ interface PaymentsV2 {
242
243
  }>;
243
244
  pendingTransfers(): Promise<PendingTransfer[]>;
244
245
  resumeNow(): Promise<void>;
246
+ connectionStatus(): ConnectionStatus;
245
247
  readonly requests: PaymentsRequestsApi;
246
248
  }
247
249
  interface PaymentsV2Events {
@@ -261,7 +263,7 @@ interface PaymentsV2Events {
261
263
  status: PaymentRequestStatus;
262
264
  };
263
265
  'connection:status': {
264
- status: 'connected' | 'degraded' | 'offline';
266
+ status: ConnectionStatus;
265
267
  };
266
268
  }
267
269
 
@@ -955,7 +957,8 @@ interface DeterministicMintCapable {
955
957
  declare function supportsDeterministicMint(engine: ITokenEngine): engine is ITokenEngine & DeterministicMintCapable;
956
958
  interface RecipientInfo {
957
959
  chainPubkey: string;
958
- network: string;
960
+ /** The recipient's PROVEN network — `null` when nothing proved one (§5.6). */
961
+ network: string | null;
959
962
  nametag?: string;
960
963
  }
961
964
  interface FacadeSession {
@@ -970,12 +973,17 @@ interface FacadeSession {
970
973
  * stream nudge resumes. The facade registers handleEpochChange here.
971
974
  */
972
975
  subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
976
+ /**
977
+ * The session's CURRENT status — REQUIRED, and the ONE source `connectionStatus()`
978
+ * and `connection:status` both come from ('offline' before first contact).
979
+ */
980
+ status(): ConnectionStatus;
973
981
  /**
974
982
  * Optional connection-status feed (same wiring pattern as the streams; the
975
983
  * emission point is the session's existing `connection:status` transition).
976
984
  * The facade's heartbeat resets its backoff on a 'connected' recovery.
977
985
  */
978
- subscribeStatus?(handler: (status: 'connected' | 'degraded' | 'offline') => void): () => void;
986
+ subscribeStatus?(handler: (status: ConnectionStatus) => void): () => void;
979
987
  }
980
988
  /**
981
989
  * §5.1/§6 restore surface of the checkpoint store: re-POST the slot's cached
@@ -1027,6 +1035,8 @@ interface PaymentsFacadeDeps {
1027
1035
  receivePollMs?: number;
1028
1036
  }
1029
1037
 
1038
+ declare const ATTENTION_RECIPIENT_NETWORK_UNVERIFIED = "recipient:network-unverified";
1039
+
1030
1040
  /** Max re-plans after a conflicted attempt (#625/#677 parity with the old send loop). */
1031
1041
  declare const MAX_RESELECT = 8;
1032
1042
  declare const ATTENTION_MINT_UNRESOLVED = "mint:unresolved";
@@ -1070,6 +1080,8 @@ declare class PaymentsFacade implements PaymentsV2 {
1070
1080
  before?: string;
1071
1081
  limit?: number;
1072
1082
  }): Promise<HistoryPage>;
1083
+ /** §4: read through to the session — the same value `connection:status` carries (sphere#473). No session ⇒ 'offline'. */
1084
+ connectionStatus(): ConnectionStatus;
1073
1085
  /** §4 pending-transfers UI surface — derived on read, never cached (convergence.ts). */
1074
1086
  pendingTransfers(): Promise<PendingTransfer[]>;
1075
1087
  send(request: SendRequest): Promise<TransferResult>;
@@ -1092,8 +1104,6 @@ declare class PaymentsFacade implements PaymentsV2 {
1092
1104
  * 'failed' invites a dApp re-send, i.e. a double-pay (#631/#676). */
1093
1105
  private emitCleanFailure;
1094
1106
  private sendWithPolicy;
1095
- /** §5.6 cross-network deposit trap: refused BEFORE any reserve/certification. */
1096
- private requireSameNetworkRecipient;
1097
1107
  private runAttempt;
1098
1108
  /** Partial (#677/#690): shortfall already durable (machine wrote it BEFORE
1099
1109
  * complete); accumulate settled, re-plan ONLY the remainder, NEW transferId. */
@@ -1143,4 +1153,4 @@ declare class PaymentsFacade implements PaymentsV2 {
1143
1153
  declare const HEARTBEAT_SEED_MS = 5000;
1144
1154
  declare const HEARTBEAT_CAP_MS = 120000;
1145
1155
 
1146
- export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RESEED_REJECTED, type ApplyDeltaResult, type CheckpointReseeder, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, supportsDeterministicMint };
1156
+ export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, supportsDeterministicMint };
@@ -226,6 +226,7 @@ interface PendingTransfer {
226
226
  deliveryPending: boolean;
227
227
  createdAt: number;
228
228
  }
229
+ type ConnectionStatus = 'connected' | 'degraded' | 'offline';
229
230
  interface PaymentsV2 {
230
231
  assets(coinId?: string): Promise<Asset[]>;
231
232
  tokens(filter?: {
@@ -242,6 +243,7 @@ interface PaymentsV2 {
242
243
  }>;
243
244
  pendingTransfers(): Promise<PendingTransfer[]>;
244
245
  resumeNow(): Promise<void>;
246
+ connectionStatus(): ConnectionStatus;
245
247
  readonly requests: PaymentsRequestsApi;
246
248
  }
247
249
  interface PaymentsV2Events {
@@ -261,7 +263,7 @@ interface PaymentsV2Events {
261
263
  status: PaymentRequestStatus;
262
264
  };
263
265
  'connection:status': {
264
- status: 'connected' | 'degraded' | 'offline';
266
+ status: ConnectionStatus;
265
267
  };
266
268
  }
267
269
 
@@ -955,7 +957,8 @@ interface DeterministicMintCapable {
955
957
  declare function supportsDeterministicMint(engine: ITokenEngine): engine is ITokenEngine & DeterministicMintCapable;
956
958
  interface RecipientInfo {
957
959
  chainPubkey: string;
958
- network: string;
960
+ /** The recipient's PROVEN network — `null` when nothing proved one (§5.6). */
961
+ network: string | null;
959
962
  nametag?: string;
960
963
  }
961
964
  interface FacadeSession {
@@ -970,12 +973,17 @@ interface FacadeSession {
970
973
  * stream nudge resumes. The facade registers handleEpochChange here.
971
974
  */
972
975
  subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
976
+ /**
977
+ * The session's CURRENT status — REQUIRED, and the ONE source `connectionStatus()`
978
+ * and `connection:status` both come from ('offline' before first contact).
979
+ */
980
+ status(): ConnectionStatus;
973
981
  /**
974
982
  * Optional connection-status feed (same wiring pattern as the streams; the
975
983
  * emission point is the session's existing `connection:status` transition).
976
984
  * The facade's heartbeat resets its backoff on a 'connected' recovery.
977
985
  */
978
- subscribeStatus?(handler: (status: 'connected' | 'degraded' | 'offline') => void): () => void;
986
+ subscribeStatus?(handler: (status: ConnectionStatus) => void): () => void;
979
987
  }
980
988
  /**
981
989
  * §5.1/§6 restore surface of the checkpoint store: re-POST the slot's cached
@@ -1027,6 +1035,8 @@ interface PaymentsFacadeDeps {
1027
1035
  receivePollMs?: number;
1028
1036
  }
1029
1037
 
1038
+ declare const ATTENTION_RECIPIENT_NETWORK_UNVERIFIED = "recipient:network-unverified";
1039
+
1030
1040
  /** Max re-plans after a conflicted attempt (#625/#677 parity with the old send loop). */
1031
1041
  declare const MAX_RESELECT = 8;
1032
1042
  declare const ATTENTION_MINT_UNRESOLVED = "mint:unresolved";
@@ -1070,6 +1080,8 @@ declare class PaymentsFacade implements PaymentsV2 {
1070
1080
  before?: string;
1071
1081
  limit?: number;
1072
1082
  }): Promise<HistoryPage>;
1083
+ /** §4: read through to the session — the same value `connection:status` carries (sphere#473). No session ⇒ 'offline'. */
1084
+ connectionStatus(): ConnectionStatus;
1073
1085
  /** §4 pending-transfers UI surface — derived on read, never cached (convergence.ts). */
1074
1086
  pendingTransfers(): Promise<PendingTransfer[]>;
1075
1087
  send(request: SendRequest): Promise<TransferResult>;
@@ -1092,8 +1104,6 @@ declare class PaymentsFacade implements PaymentsV2 {
1092
1104
  * 'failed' invites a dApp re-send, i.e. a double-pay (#631/#676). */
1093
1105
  private emitCleanFailure;
1094
1106
  private sendWithPolicy;
1095
- /** §5.6 cross-network deposit trap: refused BEFORE any reserve/certification. */
1096
- private requireSameNetworkRecipient;
1097
1107
  private runAttempt;
1098
1108
  /** Partial (#677/#690): shortfall already durable (machine wrote it BEFORE
1099
1109
  * complete); accumulate settled, re-plan ONLY the remainder, NEW transferId. */
@@ -1143,4 +1153,4 @@ declare class PaymentsFacade implements PaymentsV2 {
1143
1153
  declare const HEARTBEAT_SEED_MS = 5000;
1144
1154
  declare const HEARTBEAT_CAP_MS = 120000;
1145
1155
 
1146
- export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RESEED_REJECTED, type ApplyDeltaResult, type CheckpointReseeder, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, supportsDeterministicMint };
1156
+ export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, supportsDeterministicMint };
@@ -1476,6 +1476,31 @@ function distinctOpCount(entries) {
1476
1476
  return new Set(entries.map((entry) => entry.opIndex)).size;
1477
1477
  }
1478
1478
 
1479
+ // modules/payments-v2/recipient.ts
1480
+ var ATTENTION_RECIPIENT_NETWORK_UNVERIFIED = "recipient:network-unverified";
1481
+ async function requireSameNetworkRecipient(deps, identifier) {
1482
+ const recipient = await deps.resolveRecipient(identifier);
1483
+ if (recipient === null || recipient.chainPubkey === "") {
1484
+ throw new SphereError(`Recipient ${identifier} has no published chain pubkey`, "INVALID_RECIPIENT");
1485
+ }
1486
+ if (recipient.network === null) {
1487
+ deps.emit("transfer:attention", {
1488
+ transferId: "",
1489
+ // the gate precedes plan allocation — no transferId exists yet
1490
+ code: ATTENTION_RECIPIENT_NETWORK_UNVERIFIED,
1491
+ detail: `could not verify the network of recipient ${identifier} \u2014 assuming this session's "${deps.network}"`
1492
+ });
1493
+ return recipient;
1494
+ }
1495
+ if (recipient.network !== deps.network) {
1496
+ throw new SphereError(
1497
+ `Recipient ${identifier} is on network "${recipient.network}" but this session is on "${deps.network}" \u2014 a cross-network deposit is unrecoverable`,
1498
+ "INVALID_RECIPIENT"
1499
+ );
1500
+ }
1501
+ return recipient;
1502
+ }
1503
+
1479
1504
  // modules/payments-v2/restore.ts
1480
1505
  var ATTENTION_RESEED_REJECTED = "intent:reseed-rejected";
1481
1506
  var ALL_STREAMS = ["inventory", "mailbox", "payment_requests", "history"];
@@ -4010,6 +4035,10 @@ var PaymentsFacade = class {
4010
4035
  history(page) {
4011
4036
  return this.historyStore.page(page ?? {});
4012
4037
  }
4038
+ /** §4: read through to the session — the same value `connection:status` carries (sphere#473). No session ⇒ 'offline'. */
4039
+ connectionStatus() {
4040
+ return this.started ? this.deps.session.status() : "offline";
4041
+ }
4013
4042
  /** §4 pending-transfers UI surface — derived on read, never cached (convergence.ts). */
4014
4043
  pendingTransfers() {
4015
4044
  return derivePendingTransfers(this.machineStores, this.machineDeps.decryptPayload);
@@ -4084,7 +4113,7 @@ var PaymentsFacade = class {
4084
4113
  this.deps.emit("transfer:updated", failed);
4085
4114
  }
4086
4115
  async sendWithPolicy(request, run) {
4087
- const recipient = await this.requireSameNetworkRecipient(request.recipient);
4116
+ const recipient = await requireSameNetworkRecipient(this.deps, request.recipient);
4088
4117
  for (let attempt = 0; ; attempt++) {
4089
4118
  let ctx;
4090
4119
  try {
@@ -4107,20 +4136,6 @@ var PaymentsFacade = class {
4107
4136
  if (surfaced !== null) return surfaced;
4108
4137
  }
4109
4138
  }
4110
- /** §5.6 cross-network deposit trap: refused BEFORE any reserve/certification. */
4111
- async requireSameNetworkRecipient(identifier) {
4112
- const recipient = await this.deps.resolveRecipient(identifier);
4113
- if (recipient === null || recipient.chainPubkey === "") {
4114
- throw new SphereError(`Recipient ${identifier} has no published chain pubkey`, "INVALID_RECIPIENT");
4115
- }
4116
- if (recipient.network !== this.deps.network) {
4117
- throw new SphereError(
4118
- `Recipient ${identifier} is on network "${recipient.network}" but this session is on "${this.deps.network}" \u2014 a cross-network deposit is unrecoverable`,
4119
- "INVALID_RECIPIENT"
4120
- );
4121
- }
4122
- return recipient;
4123
- }
4124
4139
  async runAttempt(ctx) {
4125
4140
  this.activeMoneyOps.add(ctx.transferId);
4126
4141
  try {
@@ -4497,19 +4512,12 @@ var PaymentsFacade = class {
4497
4512
  }
4498
4513
  toUiToken(tokenId, coinId, amount) {
4499
4514
  const now = this.nowMs();
4500
- return toToken(
4501
- tokenId,
4502
- { assets: [], createdAt: now, updatedAt: now },
4503
- { coinId, amount: amount.toString() },
4504
- this.deps.registry,
4505
- { transferring: true, suspectedSpent: false }
4506
- );
4515
+ const snapshot = { assets: [], createdAt: now, updatedAt: now };
4516
+ const flags = { transferring: true, suspectedSpent: false };
4517
+ return toToken(tokenId, snapshot, { coinId, amount: amount.toString() }, this.deps.registry, flags);
4507
4518
  }
4508
4519
  track(op) {
4509
- const settled = op.then(
4510
- () => void 0,
4511
- () => void 0
4512
- );
4520
+ const settled = op.then(() => void 0, () => void 0);
4513
4521
  this.pendingOps.add(settled);
4514
4522
  void settled.finally(() => this.pendingOps.delete(settled));
4515
4523
  return op;
@@ -4520,6 +4528,7 @@ var PaymentsFacade = class {
4520
4528
  };
4521
4529
  export {
4522
4530
  ATTENTION_MINT_UNRESOLVED,
4531
+ ATTENTION_RECIPIENT_NETWORK_UNVERIFIED,
4523
4532
  ATTENTION_RESEED_REJECTED,
4524
4533
  HEARTBEAT_CAP_MS,
4525
4534
  HEARTBEAT_SEED_MS,