@unicitylabs/sphere-sdk 0.13.2 → 0.13.3-dev.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.
package/dist/index.d.ts CHANGED
@@ -472,9 +472,6 @@ type StorageEventCallback = (event: StorageEvent) => void;
472
472
  interface TxfStorageDataBase {
473
473
  _meta: TxfMeta$1;
474
474
  _tombstones?: TxfTombstone[];
475
- _outbox?: TxfOutboxEntry[];
476
- _sent?: TxfSentEntry[];
477
- _invalid?: TxfInvalidEntry[];
478
475
  _history?: HistoryRecord[];
479
476
  [key: `_${string}`]: unknown;
480
477
  }
@@ -490,25 +487,6 @@ interface TxfTombstone {
490
487
  stateHash: string;
491
488
  timestamp: number;
492
489
  }
493
- interface TxfOutboxEntry {
494
- id: string;
495
- status: string;
496
- tokenId: string;
497
- recipient: string;
498
- createdAt: number;
499
- data: unknown;
500
- }
501
- interface TxfSentEntry {
502
- tokenId: string;
503
- recipient: string;
504
- txHash: string;
505
- sentAt: number;
506
- }
507
- interface TxfInvalidEntry {
508
- tokenId: string;
509
- reason: string;
510
- detectedAt: number;
511
- }
512
490
 
513
491
  /**
514
492
  * Oracle Provider Interface
@@ -1022,49 +1000,6 @@ interface TombstoneEntry {
1022
1000
  stateHash: string;
1023
1001
  timestamp: number;
1024
1002
  }
1025
- /**
1026
- * Invalidated nametag entry
1027
- */
1028
- interface InvalidatedNametagEntry {
1029
- name: string;
1030
- token: object;
1031
- timestamp: number;
1032
- format: string;
1033
- version: string;
1034
- invalidatedAt: number;
1035
- invalidationReason: string;
1036
- }
1037
- /**
1038
- * Outbox entry for pending transfers
1039
- */
1040
- interface OutboxEntry {
1041
- id: string;
1042
- status: 'pending' | 'submitted' | 'confirmed' | 'delivered' | 'failed';
1043
- sourceTokenId: string;
1044
- salt: string;
1045
- commitmentJson: string;
1046
- recipientPubkey: string;
1047
- recipientNametag?: string;
1048
- amount: string;
1049
- createdAt: number;
1050
- updatedAt: number;
1051
- error?: string;
1052
- retryCount?: number;
1053
- }
1054
- /**
1055
- * Mint outbox entry for pending mints
1056
- */
1057
- interface MintOutboxEntry {
1058
- id: string;
1059
- status: 'pending' | 'submitted' | 'confirmed' | 'failed';
1060
- type: 'split' | 'faucet' | 'other';
1061
- salt: string;
1062
- requestIdHex: string;
1063
- mintDataJson: string;
1064
- createdAt: number;
1065
- updatedAt: number;
1066
- error?: string;
1067
- }
1068
1003
  /**
1069
1004
  * Storage metadata
1070
1005
  */
@@ -1084,10 +1019,7 @@ interface TxfStorageData {
1084
1019
  _nametag?: NametagData;
1085
1020
  _nametags?: NametagData[];
1086
1021
  _tombstones?: TombstoneEntry[];
1087
- _invalidatedNametags?: InvalidatedNametagEntry[];
1088
- _outbox?: OutboxEntry[];
1089
- _mintOutbox?: MintOutboxEntry[];
1090
- [key: string]: TxfToken | TxfMeta | NametagData | NametagData[] | TombstoneEntry[] | InvalidatedNametagEntry[] | OutboxEntry[] | MintOutboxEntry[] | undefined;
1022
+ [key: string]: TxfToken | TxfMeta | NametagData | NametagData[] | TombstoneEntry[] | undefined;
1091
1023
  }
1092
1024
  interface ValidationIssue {
1093
1025
  tokenId: string;
@@ -1097,20 +1029,11 @@ interface ValidationIssue {
1097
1029
  interface TokenValidationResult {
1098
1030
  isValid: boolean;
1099
1031
  reason?: string;
1100
- action?: 'ACCEPT' | 'RETRY_LATER' | 'DISCARD_FORK';
1101
1032
  }
1102
1033
  /**
1103
1034
  * Check if a key is an active token key
1104
1035
  */
1105
1036
  declare function isTokenKey(key: string): boolean;
1106
- /**
1107
- * Check if a key is an archived token key
1108
- */
1109
- declare function isArchivedKey(key: string): boolean;
1110
- /**
1111
- * Check if a key is a forked token key
1112
- */
1113
- declare function isForkedKey(key: string): boolean;
1114
1037
  /**
1115
1038
  * Extract token ID from storage key
1116
1039
  */
@@ -1119,101 +1042,347 @@ declare function tokenIdFromKey(key: string): string;
1119
1042
  * Create storage key from token ID
1120
1043
  */
1121
1044
  declare function keyFromTokenId(tokenId: string): string;
1122
- /**
1123
- * Extract token ID from archived key
1124
- */
1125
- declare function tokenIdFromArchivedKey(key: string): string;
1126
- /**
1127
- * Create archived key from token ID
1128
- */
1129
- declare function archivedKeyFromTokenId(tokenId: string): string;
1130
- /**
1131
- * Create forked key from token ID and state hash
1132
- */
1133
- declare function forkedKeyFromTokenIdAndState(tokenId: string, stateHash: string): string;
1134
- /**
1135
- * Parse forked key into tokenId and stateHash
1136
- */
1137
- declare function parseForkedKey(key: string): {
1138
- tokenId: string;
1139
- stateHash: string;
1140
- } | null;
1141
1045
  /**
1142
1046
  * Validate 64-character hex token ID
1143
1047
  */
1144
1048
  declare function isValidTokenId(tokenId: string): boolean;
1145
1049
 
1146
1050
  /**
1147
- * Transport Provider Interface
1148
- * Platform-independent P2P messaging abstraction
1149
- */
1150
-
1151
- /**
1152
- * P2P messaging transport provider
1051
+ * transport/delivery-provider.ts — the `DeliveryProvider` port (sdk-changes S7,
1052
+ * covenant §3.1-6).
1053
+ *
1054
+ * The seam that keeps the delivery rail swappable. In Unicity, a transfer —
1055
+ * after certification — is just a file handoff, so the port is deliberately
1056
+ * tiny: hand a finished token blob to a recipient, pull incoming deliveries,
1057
+ * acknowledge them. `WalletApiMailboxProvider`
1058
+ * (impl/shared/wallet-api/WalletApiMailboxProvider.ts) is the reference
1059
+ * implementation; anything that can move a file can implement it (the port
1060
+ * shape must not preclude the old Nostr transport or a future federated
1061
+ * transport — neither is a deliverable here).
1062
+ *
1063
+ * Normative shapes (sdk-changes S7):
1064
+ * - `DeliveryReceipt = { deliveryId }`
1065
+ * - `IncomingDelivery = { deliveryId, transferId?, senderPubkey?, memo?,
1066
+ * fetchBlob(), cursor }`
1067
+ * - `deliveryId` is the **content-derived** entry id —
1068
+ * `hex(SHA-256(tokenId bytes ‖ stateHash bytes))` — NEVER a server-assigned
1069
+ * row id or seq (covenant §3.1-4; the contract suite asserts it). It is
1070
+ * computed client-side ({@link computeDeliveryId}) and must equal the
1071
+ * backend's `entry_id` (ARCHITECTURE §6).
1072
+ * - **Custody is a composition-time property, not a per-call flag**:
1073
+ * implementations take `custody: 'inventory' | 'external'` at construction
1074
+ * and every ack sends the corresponding `intoInventory` — delivery-only
1075
+ * safety must never depend on remembering an option at a call site.
1076
+ * - Implementations MUST keep a **persistent `(tokenId, stateHash)` seen-set**
1077
+ * for incoming deliveries: the recipient-side replay guard is part of the
1078
+ * port contract, not a server promise (the recipient never trusts the
1079
+ * backend — ARCHITECTURE §8.2). `deliveryId` is the canonical hash encoding
1080
+ * of exactly that pair, so a persistent deliveryId set satisfies this.
1153
1081
  */
1154
- interface TransportProvider extends BaseProvider {
1082
+ /** Receipt for a delivered blob. `deliveryId` is content-derived — see module doc. */
1083
+ interface DeliveryReceipt {
1084
+ deliveryId: string;
1085
+ }
1086
+ /** Options for {@link DeliveryProvider.deliver}. */
1087
+ interface DeliverOptions {
1155
1088
  /**
1156
- * Set identity for signing/encryption.
1157
- * If the transport is already connected, reconnects with the new identity.
1089
+ * The send's transferId (the E.3 intent id / realization seed). Recorded
1090
+ * with the delivery so the recipient can group multi-token payments and the
1091
+ * backend can evidence-check the sender's removals (ARCHITECTURE §5.3/§6).
1158
1092
  */
1159
- setIdentity(identity: FullIdentity): void | Promise<void>;
1093
+ transferId: string;
1094
+ /** Optional human memo. Implementations encrypt it client-side (S6). */
1095
+ memo?: string;
1160
1096
  /**
1161
- * Send encrypted direct message
1162
- * @param recipientTransportPubkey - Transport-specific pubkey for messaging
1163
- * @returns Event ID
1097
+ * The SENDER's own nametag (without a leading `@`), so the recipient can
1098
+ * render the human identity instead of a raw pubkey ("Someone"). Bundled
1099
+ * with the memo into ONE recipient-addressed (ECDH) `enc1.` envelope (S6) —
1100
+ * the operator never sees it. Attached whenever the sender has a nametag OR
1101
+ * a memo (so the nametag travels even on a memo-less transfer).
1164
1102
  */
1165
- sendMessage(recipientTransportPubkey: string, content: string): Promise<string>;
1103
+ senderNametag?: string;
1104
+ }
1105
+ /** One incoming delivery pulled from the feed. */
1106
+ interface IncomingDelivery {
1107
+ /** Content-derived id — `hex(SHA-256(tokenId bytes ‖ stateHash bytes))`. */
1108
+ deliveryId: string;
1109
+ /** The sender's transferId, when the transport carries it. */
1110
+ transferId?: string;
1111
+ /** The sender's pubkey, when the transport carries it. */
1112
+ senderPubkey?: string;
1113
+ /** Decrypted memo (S6), when present and decryptable. */
1114
+ memo?: string;
1166
1115
  /**
1167
- * Subscribe to incoming direct messages
1168
- * @returns Unsubscribe function
1116
+ * The sender's nametag (without a leading `@`), decrypted from the same
1117
+ * recipient-addressed delivery envelope as {@link memo} (S6). Lets the
1118
+ * receiver render the human identity instead of a raw pubkey, with no
1119
+ * Nostr/transport lookup. Absent when the envelope carried none or could
1120
+ * not be decrypted.
1169
1121
  */
1170
- onMessage(handler: MessageHandler): () => void;
1122
+ senderNametag?: string;
1123
+ /** Fetch the finished token blob bytes (the encoded TokenBlob). */
1124
+ fetchBlob(): Promise<Uint8Array>;
1125
+ /** Transport-local resume cursor (opaque to callers). */
1126
+ cursor: string;
1127
+ }
1128
+ type DeliveryDisposition = 'claimed' | 'rejected';
1129
+ /**
1130
+ * The §9 wake streams a backend may nudge: `mailbox` (incoming deliveries),
1131
+ * `inventory` (owned-token set changed — e.g. a top-up or a claim on another
1132
+ * device), and `payment_requests` (a request created/answered). A wake on any
1133
+ * of these is a NUDGE — the consumer pulls that stream's cursor; correctness
1134
+ * never depends on the wake arriving (the poll backstop is the source of
1135
+ * truth).
1136
+ */
1137
+ type WakeStream = 'inventory' | 'mailbox' | 'payment_requests';
1138
+ /**
1139
+ * True liveness of the realtime wake channel (§9), decoupled from sign-in
1140
+ * session state: `connecting`/`connected` — a socket is (being) established;
1141
+ * `reconnecting` — it dropped and is backing off to re-establish (the poll
1142
+ * backstop carries correctness meanwhile); `closed` — torn down intentionally.
1143
+ * The wake is a nudge, so this is informational for the frontend (a "live"
1144
+ * indicator) — never a correctness gate.
1145
+ */
1146
+ type WakeChannelStatus = 'connecting' | 'connected' | 'reconnecting' | 'closed';
1147
+ /**
1148
+ * Custody mode (composition-time): `'inventory'` — acknowledged deliveries
1149
+ * enter the wallet-api inventory (the full wallet-api preset); `'external'` —
1150
+ * the app's own storage keeps custody and acks perform ZERO inventory writes
1151
+ * (the delivery-only preset, ARCHITECTURE §6 "delivery-only claim").
1152
+ */
1153
+ type DeliveryCustody = 'inventory' | 'external';
1154
+ interface DeliveryProvider {
1155
+ /** Composition-time custody property — never a per-call flag (S7). */
1156
+ readonly custody: DeliveryCustody;
1171
1157
  /**
1172
- * Send token transfer payload
1173
- * @param recipientTransportPubkey - Transport-specific pubkey for messaging
1174
- * @returns Event ID
1158
+ * Bind the wallet identity (optional — implementations that authenticate or
1159
+ * encrypt per-wallet need it; mirrors `TokenStorageProvider.setIdentity`).
1175
1160
  */
1176
- sendTokenTransfer(recipientTransportPubkey: string, payload: TokenTransferPayload): Promise<string>;
1161
+ setIdentity?(identity: {
1162
+ privateKey: string;
1163
+ chainPubkey: string;
1164
+ }): void;
1177
1165
  /**
1178
- * Subscribe to incoming token transfers
1179
- * @returns Unsubscribe function
1166
+ * #583 per-address client isolation: mint an INDEPENDENT delivery provider for
1167
+ * a different HD address, backed by its OWN authenticated client + wake socket
1168
+ * (mirrors `TokenStorageProvider.createForAddress`). Implementations that hold
1169
+ * a single mutable identity+session per instance (e.g. the wallet-api mailbox
1170
+ * over one `WalletApiClient`) provide this so `Sphere.switchToAddress` can give
1171
+ * each address its OWN delivery instance — an orphaned previous-address pump
1172
+ * then re-auths as ITS OWN owner (harmless) instead of driving a client that
1173
+ * was re-bound to the new owner. Stateless transports may omit it (the same
1174
+ * instance serves every address).
1180
1175
  */
1181
- onTokenTransfer(handler: TokenTransferHandler): () => void;
1176
+ createForAddress?(): DeliveryProvider;
1182
1177
  /**
1183
- * Resolve any identifier to full peer information.
1184
- * Accepts @nametag, bare nametag, DIRECT://, chain pubkey, or transport pubkey.
1185
- * @param identifier - Any supported identifier format
1186
- * @returns PeerInfo or null if not found
1178
+ * Hand a finished token blob to a recipient. `recipientPubkey` is the
1179
+ * recipient's CHAIN pubkey (33-byte compressed secp256k1, hex) — the
1180
+ * canonical Unicity identity (ARCHITECTURE §4); transports that address
1181
+ * recipients differently resolve it themselves.
1182
+ *
1183
+ * MUST be idempotent per (token, state): re-delivering the same finished
1184
+ * blob — including after the recipient claimed — succeeds and returns the
1185
+ * same content-derived `deliveryId` (ARCHITECTURE §6 deposit idempotency).
1187
1186
  */
1188
- resolve?(identifier: string): Promise<PeerInfo | null>;
1187
+ deliver(recipientPubkey: string, blob: Uint8Array, options: DeliverOptions): Promise<DeliveryReceipt>;
1189
1188
  /**
1190
- * Resolve nametag to public key
1189
+ * Pull-based feed of incoming deliveries since the given transport-local
1190
+ * cursor (or the provider's persisted cursor when omitted). Yields only
1191
+ * deliveries not yet in the persistent seen-set; completes when the feed is
1192
+ * drained — callers re-invoke on poll/wake. Feeds the existing
1193
+ * transport-agnostic `handleV2Transfer` (sdk-changes S3).
1191
1194
  */
1192
- resolveNametag?(nametag: string): Promise<string | null>;
1195
+ incoming(sinceCursor?: string): AsyncIterable<IncomingDelivery>;
1193
1196
  /**
1194
- * Resolve nametag to full peer information
1195
- * Returns transportPubkey, chainPubkey, directAddress
1197
+ * Acknowledge a delivery: `'claimed'` accepts it (with the provider's
1198
+ * composition-time custody), `'rejected'` marks it locally-unverifiable —
1199
+ * terminal for discovery only (the entry stays claimable server-side and
1200
+ * its blob is retained — ARCHITECTURE §6). Both record the delivery in the
1201
+ * persistent seen-set.
1196
1202
  */
1197
- resolveNametagInfo?(nametag: string): Promise<PeerInfo | null>;
1203
+ ack(deliveryId: string, disposition: DeliveryDisposition): Promise<void>;
1198
1204
  /**
1199
- * Resolve a DIRECT:// or PROXY:// address to full peer info.
1200
- * Performs reverse lookup: address → binding event → PeerInfo.
1201
- * @param address - L3 address (DIRECT://... or PROXY://...)
1202
- * @returns PeerInfo or null if no binding found for this address
1205
+ * Optional batch acknowledge (#623): claim and reject whole pages of incoming deliveries in a
1206
+ * single request each, instead of one per entry — so draining a large inbox (a long-offline or
1207
+ * service wallet) doesn't fire thousands of writes and trip the per-owner rate limit. Same
1208
+ * semantics as {@link ack}: the seen-set records only entries that were acked successfully, so a
1209
+ * partial/failed batch is re-listed and re-processed (idempotent claim, §6). A provider that does
1210
+ * not implement it (e.g. the relay no-op) is driven via per-entry {@link ack}.
1203
1211
  */
1204
- resolveAddressInfo?(address: string): Promise<PeerInfo | null>;
1212
+ ackBatch?(claimed: string[], rejected: string[]): Promise<void>;
1205
1213
  /**
1206
- * Resolve transport pubkey to full peer info.
1207
- * Queries binding events authored by the given transport pubkey.
1208
- * @param transportPubkey - Transport-specific pubkey (e.g. 64-char hex string)
1209
- * @returns PeerInfo or null if no binding found
1214
+ * Optional batch deliver (#699): hand N finished blobs to ONE recipient with a single deposit
1215
+ * request (and one upload-urls request) instead of N — a multi-source send then costs O(1)
1216
+ * against the backend's deposit rate limit regardless of fragmentation. Optional like
1217
+ * {@link ackBatch}: the port must not preclude the relay transport or a future federated one,
1218
+ * and neither has a batch primitive — callers probe and fall back to per-blob {@link deliver}.
1219
+ *
1220
+ * Semantically equivalent to awaiting {@link deliver} once per blob, in order:
1221
+ * - receipts return in REQUEST order; each `deliveryId` is the content-derived entry id
1222
+ * (covenant §3.1-4 — NEVER the batch endpoint's server-assigned seq);
1223
+ * - idempotent per (token, state) exactly like {@link deliver};
1224
+ * - `options` apply to every blob (one send = one transferId/memo/senderNametag);
1225
+ * - throws when ANY blob could not be deposited — blobs that DID land are absorbed
1226
+ * idempotently when the caller retries, batched or per-blob.
1210
1227
  */
1211
- resolveTransportPubkeyInfo?(transportPubkey: string): Promise<PeerInfo | null>;
1228
+ deliverBatch?(recipientPubkey: string, blobs: Uint8Array[], options: DeliverOptions): Promise<DeliveryReceipt[]>;
1212
1229
  /**
1213
- * Batch-resolve multiple transport pubkeys to peer info.
1214
- * Used for HD address discovery: derives transport pubkeys for indices 0..N
1215
- * and queries binding events in a single batch.
1216
- * @param transportPubkeys - Array of transport-specific pubkeys to look up
1230
+ * Optional wake hook: `callback` fires with the {@link WakeStream} that was
1231
+ * nudged when new data may be available on it (e.g. a WS nudge — never a
1232
+ * correctness dependency, ARCHITECTURE §9). The wallet-api wake socket
1233
+ * multiplexes all three owner streams (`mailbox` | `inventory` |
1234
+ * `payment_requests`); the consumer routes each to that stream's pull.
1235
+ *
1236
+ * The underlying socket SELF-HEALS (§9): it reconnects with backoff on any
1237
+ * drop and a liveness watchdog force-reconnects a half-open socket. On every
1238
+ * (re)connect the consumer MUST run a full catch-up pull of every stream —
1239
+ * wakes missed while the socket was dead are not replayed — so `callback`
1240
+ * fires once for EACH stream on (re)connect (a synthetic catch-up nudge).
1241
+ * `onStatus` (optional) surfaces true socket liveness for the frontend,
1242
+ * decoupled from sign-in state. Returns an unsubscribe function.
1243
+ */
1244
+ onWake?(callback: (stream: WakeStream) => void, onStatus?: (status: WakeChannelStatus) => void): () => void;
1245
+ /**
1246
+ * Late-bind the backend-true (tokenId, stateHash) derivation —
1247
+ * `ITokenEngine.deliveryKeys`. Compositions are engine-less (the engine is
1248
+ * built later); the module that owns both (PaymentsModule) binds this at
1249
+ * init. Implementations that derive ids (S7) MUST use it and fail loudly if
1250
+ * unbound; transports that don't derive may omit the method.
1251
+ */
1252
+ bindDeliveryKeys?(derive: (blobBytes: Uint8Array) => Promise<{
1253
+ tokenId: string;
1254
+ stateHash: string;
1255
+ }>): void;
1256
+ }
1257
+ /**
1258
+ * The content-derived delivery id:
1259
+ * `hex(SHA-256(tokenId bytes ‖ stateHash bytes))` — identical to the
1260
+ * backend's `entry_id` (ARCHITECTURE §6), computed client-side so no
1261
+ * implementation can substitute a server row id (covenant §3.1-4).
1262
+ *
1263
+ * @param tokenIdHex - genesis-stable 64-hex token id
1264
+ * @param stateHashHex - the SDK's per-state hash (DataHash imprint, hex) — the
1265
+ * backend's `state_hash` (wallet-api validation/chain.ts); NEVER a plain
1266
+ * sha256 over the token bytes (that variant 422s on deposit).
1267
+ */
1268
+ declare function computeDeliveryId(tokenIdHex: string, stateHashHex: string): string;
1269
+ /** Full delivery keys: the engine-derived pair + the composed deliveryId. */
1270
+ interface DeliveryBlobKeys {
1271
+ /** Genesis-stable 64-hex token id (from the TokenBlob envelope). */
1272
+ tokenId: string;
1273
+ /** Per-state hash: `hex(SHA-256(inner token bytes))` — changes every transfer. */
1274
+ stateHash: string;
1275
+ /** {@link computeDeliveryId} of the two above. */
1276
+ deliveryId: string;
1277
+ }
1278
+ /**
1279
+ * Derive (tokenId, stateHash, deliveryId) from encoded TokenBlob bytes.
1280
+ * Throws when the bytes are not a decodable TokenBlob.
1281
+ */
1282
+ /**
1283
+ * Compose full delivery keys from an engine-derived (tokenId, stateHash) pair.
1284
+ * The pair MUST come from `ITokenEngine.deliveryKeys` (the backend-true SDK
1285
+ * derivation) — the port module deliberately cannot decode tokens itself.
1286
+ */
1287
+ declare function composeDeliveryKeys(keys: {
1288
+ tokenId: string;
1289
+ stateHash: string;
1290
+ }): DeliveryBlobKeys;
1291
+
1292
+ /**
1293
+ * Receive + delivery: `receive()`, the `handleV2Transfer` receiver, the
1294
+ * PENDING_V2_DELIVERIES journal, the hoisted send delivery pass and the bounded
1295
+ * replay + poison budget. The token map and `save()` stay in PaymentsModule.
1296
+ */
1297
+
1298
+ /**
1299
+ * @deprecated v2 transfers arrive as finished tokens — there is no finalization
1300
+ * phase. The options are accepted for backwards compatibility and ignored.
1301
+ */
1302
+ interface ReceiveOptions {
1303
+ /** @deprecated Ignored — v2 tokens are stored confirmed on receipt. */
1304
+ finalize?: boolean;
1305
+ /** @deprecated Ignored. */
1306
+ timeout?: number;
1307
+ /** @deprecated Ignored. */
1308
+ pollInterval?: number;
1309
+ }
1310
+ interface ReceiveResult {
1311
+ /** Newly received incoming transfers. */
1312
+ transfers: IncomingTransfer[];
1313
+ }
1314
+
1315
+ /**
1316
+ * Transport Provider Interface
1317
+ * Platform-independent P2P messaging abstraction
1318
+ */
1319
+
1320
+ /**
1321
+ * P2P messaging transport provider
1322
+ */
1323
+ interface TransportProvider extends BaseProvider {
1324
+ /**
1325
+ * Set identity for signing/encryption.
1326
+ * If the transport is already connected, reconnects with the new identity.
1327
+ */
1328
+ setIdentity(identity: FullIdentity): void | Promise<void>;
1329
+ /**
1330
+ * Send encrypted direct message
1331
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
1332
+ * @returns Event ID
1333
+ */
1334
+ sendMessage(recipientTransportPubkey: string, content: string): Promise<string>;
1335
+ /**
1336
+ * Subscribe to incoming direct messages
1337
+ * @returns Unsubscribe function
1338
+ */
1339
+ onMessage(handler: MessageHandler): () => void;
1340
+ /**
1341
+ * Send token transfer payload
1342
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
1343
+ * @returns Event ID
1344
+ */
1345
+ sendTokenTransfer(recipientTransportPubkey: string, payload: TokenTransferPayload): Promise<string>;
1346
+ /**
1347
+ * Subscribe to incoming token transfers
1348
+ * @returns Unsubscribe function
1349
+ */
1350
+ onTokenTransfer(handler: TokenTransferHandler): () => void;
1351
+ /**
1352
+ * Resolve any identifier to full peer information.
1353
+ * Accepts @nametag, bare nametag, DIRECT://, chain pubkey, or transport pubkey.
1354
+ * @param identifier - Any supported identifier format
1355
+ * @returns PeerInfo or null if not found
1356
+ */
1357
+ resolve?(identifier: string): Promise<PeerInfo | null>;
1358
+ /**
1359
+ * Resolve nametag to public key
1360
+ */
1361
+ resolveNametag?(nametag: string): Promise<string | null>;
1362
+ /**
1363
+ * Resolve nametag to full peer information
1364
+ * Returns transportPubkey, chainPubkey, directAddress
1365
+ */
1366
+ resolveNametagInfo?(nametag: string): Promise<PeerInfo | null>;
1367
+ /**
1368
+ * Resolve a DIRECT:// or PROXY:// address to full peer info.
1369
+ * Performs reverse lookup: address → binding event → PeerInfo.
1370
+ * @param address - L3 address (DIRECT://... or PROXY://...)
1371
+ * @returns PeerInfo or null if no binding found for this address
1372
+ */
1373
+ resolveAddressInfo?(address: string): Promise<PeerInfo | null>;
1374
+ /**
1375
+ * Resolve transport pubkey to full peer info.
1376
+ * Queries binding events authored by the given transport pubkey.
1377
+ * @param transportPubkey - Transport-specific pubkey (e.g. 64-char hex string)
1378
+ * @returns PeerInfo or null if no binding found
1379
+ */
1380
+ resolveTransportPubkeyInfo?(transportPubkey: string): Promise<PeerInfo | null>;
1381
+ /**
1382
+ * Batch-resolve multiple transport pubkeys to peer info.
1383
+ * Used for HD address discovery: derives transport pubkeys for indices 0..N
1384
+ * and queries binding events in a single batch.
1385
+ * @param transportPubkeys - Array of transport-specific pubkeys to look up
1217
1386
  * @returns Array of PeerInfo for pubkeys that have binding events (may be shorter than input)
1218
1387
  */
1219
1388
  discoverAddresses?(transportPubkeys: string[]): Promise<PeerInfo[]>;
@@ -1490,259 +1659,17 @@ interface IncomingReadReceipt {
1490
1659
  /** Timestamp */
1491
1660
  timestamp: number;
1492
1661
  }
1493
- type ReadReceiptHandler = (receipt: IncomingReadReceipt) => void;
1494
- interface IncomingTypingIndicator {
1495
- /** Transport-specific pubkey of the sender who is typing */
1496
- senderTransportPubkey: string;
1497
- /** Sender's nametag (if known) */
1498
- senderNametag?: string;
1499
- /** Timestamp */
1500
- timestamp: number;
1501
- }
1502
- type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
1503
- type ComposingHandler = (indicator: ComposingIndicator) => void;
1504
-
1505
- /**
1506
- * transport/delivery-provider.ts — the `DeliveryProvider` port (sdk-changes S7,
1507
- * covenant §3.1-6).
1508
- *
1509
- * The seam that keeps the delivery rail swappable. In Unicity, a transfer —
1510
- * after certification — is just a file handoff, so the port is deliberately
1511
- * tiny: hand a finished token blob to a recipient, pull incoming deliveries,
1512
- * acknowledge them. `WalletApiMailboxProvider`
1513
- * (impl/shared/wallet-api/WalletApiMailboxProvider.ts) is the reference
1514
- * implementation; anything that can move a file can implement it (the port
1515
- * shape must not preclude the old Nostr transport or a future federated
1516
- * transport — neither is a deliverable here).
1517
- *
1518
- * Normative shapes (sdk-changes S7):
1519
- * - `DeliveryReceipt = { deliveryId }`
1520
- * - `IncomingDelivery = { deliveryId, transferId?, senderPubkey?, memo?,
1521
- * fetchBlob(), cursor }`
1522
- * - `deliveryId` is the **content-derived** entry id —
1523
- * `hex(SHA-256(tokenId bytes ‖ stateHash bytes))` — NEVER a server-assigned
1524
- * row id or seq (covenant §3.1-4; the contract suite asserts it). It is
1525
- * computed client-side ({@link computeDeliveryId}) and must equal the
1526
- * backend's `entry_id` (ARCHITECTURE §6).
1527
- * - **Custody is a composition-time property, not a per-call flag**:
1528
- * implementations take `custody: 'inventory' | 'external'` at construction
1529
- * and every ack sends the corresponding `intoInventory` — delivery-only
1530
- * safety must never depend on remembering an option at a call site.
1531
- * - Implementations MUST keep a **persistent `(tokenId, stateHash)` seen-set**
1532
- * for incoming deliveries: the recipient-side replay guard is part of the
1533
- * port contract, not a server promise (the recipient never trusts the
1534
- * backend — ARCHITECTURE §8.2). `deliveryId` is the canonical hash encoding
1535
- * of exactly that pair, so a persistent deliveryId set satisfies this.
1536
- */
1537
- /** Receipt for a delivered blob. `deliveryId` is content-derived — see module doc. */
1538
- interface DeliveryReceipt {
1539
- deliveryId: string;
1540
- }
1541
- /** Options for {@link DeliveryProvider.deliver}. */
1542
- interface DeliverOptions {
1543
- /**
1544
- * The send's transferId (the E.3 intent id / realization seed). Recorded
1545
- * with the delivery so the recipient can group multi-token payments and the
1546
- * backend can evidence-check the sender's removals (ARCHITECTURE §5.3/§6).
1547
- */
1548
- transferId: string;
1549
- /** Optional human memo. Implementations encrypt it client-side (S6). */
1550
- memo?: string;
1551
- /**
1552
- * The SENDER's own nametag (without a leading `@`), so the recipient can
1553
- * render the human identity instead of a raw pubkey ("Someone"). Bundled
1554
- * with the memo into ONE recipient-addressed (ECDH) `enc1.` envelope (S6) —
1555
- * the operator never sees it. Attached whenever the sender has a nametag OR
1556
- * a memo (so the nametag travels even on a memo-less transfer).
1557
- */
1558
- senderNametag?: string;
1559
- }
1560
- /** One incoming delivery pulled from the feed. */
1561
- interface IncomingDelivery {
1562
- /** Content-derived id — `hex(SHA-256(tokenId bytes ‖ stateHash bytes))`. */
1563
- deliveryId: string;
1564
- /** The sender's transferId, when the transport carries it. */
1565
- transferId?: string;
1566
- /** The sender's pubkey, when the transport carries it. */
1567
- senderPubkey?: string;
1568
- /** Decrypted memo (S6), when present and decryptable. */
1569
- memo?: string;
1570
- /**
1571
- * The sender's nametag (without a leading `@`), decrypted from the same
1572
- * recipient-addressed delivery envelope as {@link memo} (S6). Lets the
1573
- * receiver render the human identity instead of a raw pubkey, with no
1574
- * Nostr/transport lookup. Absent when the envelope carried none or could
1575
- * not be decrypted.
1576
- */
1577
- senderNametag?: string;
1578
- /** Fetch the finished token blob bytes (the encoded TokenBlob). */
1579
- fetchBlob(): Promise<Uint8Array>;
1580
- /** Transport-local resume cursor (opaque to callers). */
1581
- cursor: string;
1582
- }
1583
- type DeliveryDisposition = 'claimed' | 'rejected';
1584
- /**
1585
- * The §9 wake streams a backend may nudge: `mailbox` (incoming deliveries),
1586
- * `inventory` (owned-token set changed — e.g. a top-up or a claim on another
1587
- * device), and `payment_requests` (a request created/answered). A wake on any
1588
- * of these is a NUDGE — the consumer pulls that stream's cursor; correctness
1589
- * never depends on the wake arriving (the poll backstop is the source of
1590
- * truth).
1591
- */
1592
- type WakeStream = 'inventory' | 'mailbox' | 'payment_requests';
1593
- /**
1594
- * True liveness of the realtime wake channel (§9), decoupled from sign-in
1595
- * session state: `connecting`/`connected` — a socket is (being) established;
1596
- * `reconnecting` — it dropped and is backing off to re-establish (the poll
1597
- * backstop carries correctness meanwhile); `closed` — torn down intentionally.
1598
- * The wake is a nudge, so this is informational for the frontend (a "live"
1599
- * indicator) — never a correctness gate.
1600
- */
1601
- type WakeChannelStatus = 'connecting' | 'connected' | 'reconnecting' | 'closed';
1602
- /**
1603
- * Custody mode (composition-time): `'inventory'` — acknowledged deliveries
1604
- * enter the wallet-api inventory (the full wallet-api preset); `'external'` —
1605
- * the app's own storage keeps custody and acks perform ZERO inventory writes
1606
- * (the delivery-only preset, ARCHITECTURE §6 "delivery-only claim").
1607
- */
1608
- type DeliveryCustody = 'inventory' | 'external';
1609
- interface DeliveryProvider {
1610
- /** Composition-time custody property — never a per-call flag (S7). */
1611
- readonly custody: DeliveryCustody;
1612
- /**
1613
- * Bind the wallet identity (optional — implementations that authenticate or
1614
- * encrypt per-wallet need it; mirrors `TokenStorageProvider.setIdentity`).
1615
- */
1616
- setIdentity?(identity: {
1617
- privateKey: string;
1618
- chainPubkey: string;
1619
- }): void;
1620
- /**
1621
- * #583 per-address client isolation: mint an INDEPENDENT delivery provider for
1622
- * a different HD address, backed by its OWN authenticated client + wake socket
1623
- * (mirrors `TokenStorageProvider.createForAddress`). Implementations that hold
1624
- * a single mutable identity+session per instance (e.g. the wallet-api mailbox
1625
- * over one `WalletApiClient`) provide this so `Sphere.switchToAddress` can give
1626
- * each address its OWN delivery instance — an orphaned previous-address pump
1627
- * then re-auths as ITS OWN owner (harmless) instead of driving a client that
1628
- * was re-bound to the new owner. Stateless transports may omit it (the same
1629
- * instance serves every address).
1630
- */
1631
- createForAddress?(): DeliveryProvider;
1632
- /**
1633
- * Hand a finished token blob to a recipient. `recipientPubkey` is the
1634
- * recipient's CHAIN pubkey (33-byte compressed secp256k1, hex) — the
1635
- * canonical Unicity identity (ARCHITECTURE §4); transports that address
1636
- * recipients differently resolve it themselves.
1637
- *
1638
- * MUST be idempotent per (token, state): re-delivering the same finished
1639
- * blob — including after the recipient claimed — succeeds and returns the
1640
- * same content-derived `deliveryId` (ARCHITECTURE §6 deposit idempotency).
1641
- */
1642
- deliver(recipientPubkey: string, blob: Uint8Array, options: DeliverOptions): Promise<DeliveryReceipt>;
1643
- /**
1644
- * Pull-based feed of incoming deliveries since the given transport-local
1645
- * cursor (or the provider's persisted cursor when omitted). Yields only
1646
- * deliveries not yet in the persistent seen-set; completes when the feed is
1647
- * drained — callers re-invoke on poll/wake. Feeds the existing
1648
- * transport-agnostic `handleV2Transfer` (sdk-changes S3).
1649
- */
1650
- incoming(sinceCursor?: string): AsyncIterable<IncomingDelivery>;
1651
- /**
1652
- * Acknowledge a delivery: `'claimed'` accepts it (with the provider's
1653
- * composition-time custody), `'rejected'` marks it locally-unverifiable —
1654
- * terminal for discovery only (the entry stays claimable server-side and
1655
- * its blob is retained — ARCHITECTURE §6). Both record the delivery in the
1656
- * persistent seen-set.
1657
- */
1658
- ack(deliveryId: string, disposition: DeliveryDisposition): Promise<void>;
1659
- /**
1660
- * Optional batch acknowledge (#623): claim and reject whole pages of incoming deliveries in a
1661
- * single request each, instead of one per entry — so draining a large inbox (a long-offline or
1662
- * service wallet) doesn't fire thousands of writes and trip the per-owner rate limit. Same
1663
- * semantics as {@link ack}: the seen-set records only entries that were acked successfully, so a
1664
- * partial/failed batch is re-listed and re-processed (idempotent claim, §6). A provider that does
1665
- * not implement it (e.g. the relay no-op) is driven via per-entry {@link ack}.
1666
- */
1667
- ackBatch?(claimed: string[], rejected: string[]): Promise<void>;
1668
- /**
1669
- * Optional batch deliver (#699): hand N finished blobs to ONE recipient with a single deposit
1670
- * request (and one upload-urls request) instead of N — a multi-source send then costs O(1)
1671
- * against the backend's deposit rate limit regardless of fragmentation. Optional like
1672
- * {@link ackBatch}: the port must not preclude the relay transport or a future federated one,
1673
- * and neither has a batch primitive — callers probe and fall back to per-blob {@link deliver}.
1674
- *
1675
- * Semantically equivalent to awaiting {@link deliver} once per blob, in order:
1676
- * - receipts return in REQUEST order; each `deliveryId` is the content-derived entry id
1677
- * (covenant §3.1-4 — NEVER the batch endpoint's server-assigned seq);
1678
- * - idempotent per (token, state) exactly like {@link deliver};
1679
- * - `options` apply to every blob (one send = one transferId/memo/senderNametag);
1680
- * - throws when ANY blob could not be deposited — blobs that DID land are absorbed
1681
- * idempotently when the caller retries, batched or per-blob.
1682
- */
1683
- deliverBatch?(recipientPubkey: string, blobs: Uint8Array[], options: DeliverOptions): Promise<DeliveryReceipt[]>;
1684
- /**
1685
- * Optional wake hook: `callback` fires with the {@link WakeStream} that was
1686
- * nudged when new data may be available on it (e.g. a WS nudge — never a
1687
- * correctness dependency, ARCHITECTURE §9). The wallet-api wake socket
1688
- * multiplexes all three owner streams (`mailbox` | `inventory` |
1689
- * `payment_requests`); the consumer routes each to that stream's pull.
1690
- *
1691
- * The underlying socket SELF-HEALS (§9): it reconnects with backoff on any
1692
- * drop and a liveness watchdog force-reconnects a half-open socket. On every
1693
- * (re)connect the consumer MUST run a full catch-up pull of every stream —
1694
- * wakes missed while the socket was dead are not replayed — so `callback`
1695
- * fires once for EACH stream on (re)connect (a synthetic catch-up nudge).
1696
- * `onStatus` (optional) surfaces true socket liveness for the frontend,
1697
- * decoupled from sign-in state. Returns an unsubscribe function.
1698
- */
1699
- onWake?(callback: (stream: WakeStream) => void, onStatus?: (status: WakeChannelStatus) => void): () => void;
1700
- /**
1701
- * Late-bind the backend-true (tokenId, stateHash) derivation —
1702
- * `ITokenEngine.deliveryKeys`. Compositions are engine-less (the engine is
1703
- * built later); the module that owns both (PaymentsModule) binds this at
1704
- * init. Implementations that derive ids (S7) MUST use it and fail loudly if
1705
- * unbound; transports that don't derive may omit the method.
1706
- */
1707
- bindDeliveryKeys?(derive: (blobBytes: Uint8Array) => Promise<{
1708
- tokenId: string;
1709
- stateHash: string;
1710
- }>): void;
1711
- }
1712
- /**
1713
- * The content-derived delivery id:
1714
- * `hex(SHA-256(tokenId bytes ‖ stateHash bytes))` — identical to the
1715
- * backend's `entry_id` (ARCHITECTURE §6), computed client-side so no
1716
- * implementation can substitute a server row id (covenant §3.1-4).
1717
- *
1718
- * @param tokenIdHex - genesis-stable 64-hex token id
1719
- * @param stateHashHex - the SDK's per-state hash (DataHash imprint, hex) — the
1720
- * backend's `state_hash` (wallet-api validation/chain.ts); NEVER a plain
1721
- * sha256 over the token bytes (that variant 422s on deposit).
1722
- */
1723
- declare function computeDeliveryId(tokenIdHex: string, stateHashHex: string): string;
1724
- /** Full delivery keys: the engine-derived pair + the composed deliveryId. */
1725
- interface DeliveryBlobKeys {
1726
- /** Genesis-stable 64-hex token id (from the TokenBlob envelope). */
1727
- tokenId: string;
1728
- /** Per-state hash: `hex(SHA-256(inner token bytes))` — changes every transfer. */
1729
- stateHash: string;
1730
- /** {@link computeDeliveryId} of the two above. */
1731
- deliveryId: string;
1732
- }
1733
- /**
1734
- * Derive (tokenId, stateHash, deliveryId) from encoded TokenBlob bytes.
1735
- * Throws when the bytes are not a decodable TokenBlob.
1736
- */
1737
- /**
1738
- * Compose full delivery keys from an engine-derived (tokenId, stateHash) pair.
1739
- * The pair MUST come from `ITokenEngine.deliveryKeys` (the backend-true SDK
1740
- * derivation) — the port module deliberately cannot decode tokens itself.
1741
- */
1742
- declare function composeDeliveryKeys(keys: {
1743
- tokenId: string;
1744
- stateHash: string;
1745
- }): DeliveryBlobKeys;
1662
+ type ReadReceiptHandler = (receipt: IncomingReadReceipt) => void;
1663
+ interface IncomingTypingIndicator {
1664
+ /** Transport-specific pubkey of the sender who is typing */
1665
+ senderTransportPubkey: string;
1666
+ /** Sender's nametag (if known) */
1667
+ senderNametag?: string;
1668
+ /** Timestamp */
1669
+ timestamp: number;
1670
+ }
1671
+ type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
1672
+ type ComposingHandler = (indicator: ComposingIndicator) => void;
1746
1673
 
1747
1674
  /**
1748
1675
  * Price Provider Interface
@@ -1909,22 +1836,6 @@ declare function createPriceProvider(config: PriceProviderConfig): PriceProvider
1909
1836
  * Single source of truth: {@link HistoryRecord} in `storage/storage-provider.ts`.
1910
1837
  */
1911
1838
  type TransactionHistoryEntry = HistoryRecord;
1912
- /**
1913
- * @deprecated v2 transfers arrive as finished tokens — there is no finalization
1914
- * phase. The options are accepted for backwards compatibility and ignored.
1915
- */
1916
- interface ReceiveOptions {
1917
- /** @deprecated Ignored — v2 tokens are stored confirmed on receipt. */
1918
- finalize?: boolean;
1919
- /** @deprecated Ignored. */
1920
- timeout?: number;
1921
- /** @deprecated Ignored. */
1922
- pollInterval?: number;
1923
- }
1924
- interface ReceiveResult {
1925
- /** Newly received incoming transfers. */
1926
- transfers: IncomingTransfer[];
1927
- }
1928
1839
  interface PaymentsModuleConfig {
1929
1840
  /** Auto-sync after operations */
1930
1841
  autoSync?: boolean;
@@ -2158,15 +2069,17 @@ declare class PaymentsModule {
2158
2069
  private readonly moduleConfig;
2159
2070
  private deps;
2160
2071
  private tokens;
2161
- private tombstones;
2162
- private tombstoneKeySet;
2163
- private _historyCache;
2164
2072
  private nametags;
2165
- private paymentRequests;
2166
- private paymentRequestHandlers;
2167
- private outgoingPaymentRequests;
2168
- private paymentRequestResponseHandlers;
2169
- private pendingResponseResolvers;
2073
+ /** Inventory reads: balances/assets, the token accessors, tombstones, validate(). */
2074
+ private readonly inventory;
2075
+ /** Payment requests (incoming + outgoing, the S4 pump, the #441 journal). */
2076
+ private readonly requests;
2077
+ /** Transaction history (the cache, the dedupKey rules, the §10 server log). */
2078
+ private readonly history;
2079
+ /** E.3/E.4 intent resume (the sign-in replay of OPEN send intents). */
2080
+ private readonly intents;
2081
+ /** Receive + delivery (receive(), the v2 receiver, the journal, the replay budget). */
2082
+ private readonly deliveries;
2170
2083
  /** The single delivery seam — an injected provider or the transport adapter. */
2171
2084
  private delivery;
2172
2085
  /** Set only when a provider was INJECTED — gates the incoming pump (S3). */
@@ -2183,35 +2096,6 @@ declare class PaymentsModule {
2183
2096
  /** S6 field-encryption key (intent payloads, history memos) — per identity. */
2184
2097
  private fieldEncryptionKey;
2185
2098
  private checkpointStore;
2186
- private prPollTimer;
2187
- /** Coalesces concurrent payment-request pump runs. */
2188
- private prPumpInFlight;
2189
- /**
2190
- * Set after the once-per-session full incoming hydration (#556): the surfaced
2191
- * incoming list is in-memory only, so on a fresh engine the CURRENT state of
2192
- * ALL incoming requests — open AND resolved (paid/declined/expired) — must be
2193
- * rebuilt from a `role=incoming&since=0` pull, not just the still-open ones.
2194
- * A status-filtered bootstrap (the pre-#556 `status=open` scan) dropped
2195
- * requests resolved in a PRIOR session, so the payer reopened and the
2196
- * 'Paid Successfully' request was gone (twin of #521/#549).
2197
- */
2198
- private prBootstrapped;
2199
- /**
2200
- * #441 deferred-paid journal (durable, per network+identity): links a payment
2201
- * request to the in-flight transfer of a possibly-committed pay so the request
2202
- * is held NON-payable ('settling') until that transfer completes (→ 'paid',
2203
- * server told) or aborts (→ payable, journal cleared). Keyed by request wire id
2204
- * (== requestId for wallet-api-surfaced requests). The in-memory Map is the
2205
- * synchronous source of truth used by the reload re-apply seam; it is
2206
- * single-flight loaded and every read-modify-write is serialized through a tail
2207
- * promise (the #679/#680 lesson: an unserialized RMW drops entries under
2208
- * concurrency = a re-payable request = the double-pay this fix prevents).
2209
- */
2210
- private settlingJournal;
2211
- private settlingJournalLoad;
2212
- private settlingJournalWrite;
2213
- /** #441: guard overlapping resume reconciles (resumeOpenIntents has 2 fire-and-forget call sites). */
2214
- private reconcileInFlight;
2215
2099
  private loadedPromise;
2216
2100
  private loaded;
2217
2101
  /**
@@ -2228,20 +2112,6 @@ declare class PaymentsModule {
2228
2112
  private loadInFlightOwner;
2229
2113
  private loadRerunRequested;
2230
2114
  private loadRerunTimer;
2231
- /**
2232
- * Owner (chainPubkey) whose server history hydration last completed —
2233
- * enables the #642 incremental fast path in {@link hydrateHistoryFromServer}.
2234
- * Reset on re-init (address switch). `serverSeenHistoryKeys` holds only
2235
- * dedupKeys actually PULLED from the server (never locally-POSTed ones), so
2236
- * the incremental stop condition can't be masked by our own fresh POSTs;
2237
- * `incrementalHistoryPulls` forces a periodic full re-pull to bound the
2238
- * staleness window if server keyset order ever diverges from arrival order.
2239
- * `hydrationEpoch` guards a pull racing a same-owner re-init.
2240
- */
2241
- private historyHydratedFor;
2242
- private serverSeenHistoryKeys;
2243
- private incrementalHistoryPulls;
2244
- private hydrationEpoch;
2245
2115
  private inventoryDebounceTimer;
2246
2116
  private static readonly SYNC_DEBOUNCE_MS;
2247
2117
  /** Quiet-then-escalate logging for the background wallet-api pumps (#630). */
@@ -2252,43 +2122,45 @@ declare class PaymentsModule {
2252
2122
  private tokenChangeCallbacks;
2253
2123
  private readonly reservationLedger;
2254
2124
  private readonly spendPlanner;
2255
- /**
2256
- * Per-request single-flight for {@link payPaymentRequest}. The pay flow flips the request to
2257
- * 'accepted' before it awaits send(), and the status guard re-admits 'accepted' (intended for a
2258
- * sequential retry-after-failure) — so a concurrent double-tap / second session would otherwise
2259
- * enter send() a second time and DOUBLE-PAY (each send picks a different token; the reservation
2260
- * ledger is coin-scoped, not request-scoped). Concurrent calls for the same requestId coalesce
2261
- * onto the first in-flight pay; the entry is cleared when it settles, so a later retry is unaffected.
2262
- */
2263
- private readonly payInFlight;
2264
2125
  private spendQueue;
2265
2126
  /** Cache of parsed SdkToken data for synchronous queue re-evaluation */
2266
2127
  private readonly parsedTokenCache;
2128
+ constructor(config?: PaymentsModuleConfig);
2267
2129
  /**
2268
- * Base delay (ms) for the journaled-delivery replay backoff (#517 item 1).
2269
- * A field, not a const, so tests can drive the bounded retry loop without
2270
- * waiting real time — never mutated in production.
2130
+ * The narrow seam {@link TokenView} reaches back through. Live getters for
2131
+ * `deps` and `priceProvider` (both swapped on {@link initialize}); the token
2132
+ * map is handed over as a READ-ONLY view, so the inventory view never becomes
2133
+ * a second writer of it.
2271
2134
  */
2272
- private replayBackoffBaseMs;
2273
- /** Deferral window for recipient-quota (429) deliveries (#621). Overridable in tests. */
2274
- private deliveryDeferralMs;
2135
+ private tokenViewHost;
2275
2136
  /**
2276
- * #517: serializes {@link replayPendingV2Deliveries}. `load()` kicks replay
2277
- * off fire-and-forget and `receive()` calls `load()`, so two passes can
2278
- * overlap — duplicating delivery attempts and clobbering each other's
2279
- * `attempts` increments (both read the same stale value, both write N+1,
2280
- * delaying poison surfacing). Only one pass runs per module instance at a time.
2137
+ * The narrow seam {@link Delivery} reaches back through. Live getters for
2138
+ * `deps` and `delivery` (both swapped on every {@link initialize}); the token
2139
+ * map is handed over as a READ-ONLY view and written only by the module's own
2140
+ * `storeEngineToken`, so delivery never becomes a second writer.
2281
2141
  */
2282
- private replayInFlight;
2142
+ private deliveryHost;
2283
2143
  /**
2284
- * #517: serializes every read-modify-write of the PENDING_V2_DELIVERIES journal.
2285
- * save/remove/update each load → mutate → store the WHOLE blob, so a replay
2286
- * (fire-and-forget from load()) overlapping a send()'s journal write could
2287
- * clobber a newly-saved undelivered entry and lose it — defeating the crash-
2288
- * safety guarantee. A promise-chain mutex makes each whole RMW atomic.
2144
+ * The narrow seam {@link PaymentRequests} reaches back through. Live getters,
2145
+ * not a snapshot: `deps` is swapped on every {@link initialize} (address
2146
+ * switch) and the feature must always observe the CURRENT one.
2289
2147
  */
2290
- private journalMutation;
2291
- constructor(config?: PaymentsModuleConfig);
2148
+ private paymentRequestsHost;
2149
+ /**
2150
+ * The narrow seam {@link TransferHistory} reaches back through. Live getter
2151
+ * for `deps` (swapped on every {@link initialize}); the rest are thunks onto
2152
+ * the module's own private helpers — history never touches the token map or
2153
+ * `save()`.
2154
+ */
2155
+ private transferHistoryHost;
2156
+ /**
2157
+ * The narrow seam {@link IntentResume} reaches back through. Live getters for
2158
+ * `deps` and `delivery` (both swapped on every {@link initialize}); the rest
2159
+ * are thunks onto the module's own helpers. The token map is READ through
2160
+ * `getHeldToken` and written only by the module's `removeToken` /
2161
+ * `storeEngineToken` — resume never becomes a second writer.
2162
+ */
2163
+ private intentResumeHost;
2292
2164
  /**
2293
2165
  * Get the current module configuration.
2294
2166
  *
@@ -2611,141 +2483,40 @@ declare class PaymentsModule {
2611
2483
  * fetched only when a token is selected to be spent.
2612
2484
  */
2613
2485
  private mergeLazyInventory;
2614
- /**
2615
- * Send a payment request to someone
2616
- * @param recipientPubkeyOrNametag - Recipient's pubkey or @nametag
2617
- * @param request - Payment request details
2618
- * @returns Result with event ID
2619
- */
2486
+ /** Send a payment request to someone. @see PaymentRequests.sendPaymentRequest */
2620
2487
  sendPaymentRequest(recipientPubkeyOrNametag: string, request: Omit<PaymentRequest, 'id' | 'createdAt'>): Promise<PaymentRequestResult>;
2621
- /**
2622
- * S4: create the request via wallet-api (§16). The payer is addressed by
2623
- * CHAIN pubkey (the canonical identity); the memo is S6-encrypted client-
2624
- * side BEFORE it leaves the device (§8.3) — the operator stores ciphertext.
2625
- * Mirrors the transport path's no-throw contract: failures (including the
2626
- * §5.5 per-payer cap → 429) come back as `{ success: false, error }`.
2627
- */
2628
- private sendWalletApiPaymentRequest;
2629
- /**
2630
- * Subscribe to incoming payment requests
2631
- * @param handler - Handler function for incoming requests
2632
- * @returns Unsubscribe function
2633
- */
2488
+ /** Subscribe to incoming payment requests. @see PaymentRequests.onPaymentRequest */
2634
2489
  onPaymentRequest(handler: PaymentRequestHandler): () => void;
2635
- /**
2636
- * Get all payment requests
2637
- * @param filter - Optional status filter
2638
- */
2490
+ /** Get all payment requests. @see PaymentRequests.getPaymentRequests */
2639
2491
  getPaymentRequests(filter?: {
2640
2492
  status?: PaymentRequestStatus;
2641
2493
  }): IncomingPaymentRequest[];
2642
- /**
2643
- * Get the count of payment requests with status `'pending'`.
2644
- *
2645
- * @returns Number of pending incoming payment requests.
2646
- */
2494
+ /** Count of incoming payment requests with status `'pending'`. @see PaymentRequests.getPendingPaymentRequestsCount */
2647
2495
  getPendingPaymentRequestsCount(): number;
2648
- /**
2649
- * Accept a payment request and notify the requester.
2650
- *
2651
- * Marks the request as `'accepted'` and sends a response via transport.
2652
- * The caller should subsequently call {@link send} to fulfill the payment.
2653
- *
2654
- * @param requestId - ID of the incoming payment request to accept.
2655
- */
2656
- acceptPaymentRequest(requestId: string): Promise<void>;
2657
- /**
2658
- * Reject a payment request and notify the requester.
2659
- *
2660
- * On the wallet-api path (S4) the respond IS the state change — it is
2661
- * confirmed server-side (`action: 'declined'`, §16) before the local status
2662
- * flips, and a server rejection (403/409) propagates to the caller. The
2663
- * transport path is best-effort and never throws.
2664
- *
2665
- * @param requestId - ID of the incoming payment request to reject.
2666
- */
2496
+ /** Reject a payment request and notify the requester. @see PaymentRequests.rejectPaymentRequest */
2667
2497
  rejectPaymentRequest(requestId: string): Promise<void>;
2668
- /**
2669
- * Mark a payment request as paid (local status update only).
2670
- *
2671
- * Typically called after a successful {@link send} to record that the
2672
- * request has been fulfilled.
2673
- *
2674
- * @param requestId - ID of the incoming payment request to mark as paid.
2675
- */
2676
- markPaymentRequestPaid(requestId: string): void;
2677
- /**
2678
- * Remove resolved incoming payment requests from memory.
2679
- *
2680
- * Keeps requests with status `'pending'` OR `'settling'` (#441). A `'settling'`
2681
- * request is UNRESOLVED — its linked transfer is still in-flight — so evicting
2682
- * it would drop the in-memory hold that keeps it non-payable until the journal
2683
- * re-surfaces it. Only terminal statuses (`'paid'`/`'rejected'`/`'expired'`)
2684
- * are removed.
2685
- */
2498
+ /** Remove resolved incoming payment requests from memory. @see PaymentRequests.clearProcessedPaymentRequests */
2686
2499
  clearProcessedPaymentRequests(): void;
2687
- /**
2688
- * Remove a specific incoming payment request by ID.
2689
- *
2690
- * @param requestId - ID of the payment request to remove.
2691
- */
2500
+ /** Remove a specific incoming payment request by ID. @see PaymentRequests.removePaymentRequest */
2692
2501
  removePaymentRequest(requestId: string): void;
2693
- /**
2694
- * Pay a payment request directly
2695
- * Convenience method that accepts, sends, and marks as paid
2696
- */
2502
+ /** Pay a payment request directly. @see PaymentRequests.payPaymentRequest */
2697
2503
  payPaymentRequest(requestId: string, memo?: string): Promise<TransferResult>;
2698
- private payPaymentRequestInner;
2699
- private updatePaymentRequestStatus;
2700
- /**
2701
- * Get outgoing payment requests
2702
- * @param filter - Optional status filter
2703
- */
2504
+ /** Get outgoing payment requests. @see PaymentRequests.getOutgoingPaymentRequests */
2704
2505
  getOutgoingPaymentRequests(filter?: {
2705
2506
  status?: PaymentRequestStatus;
2706
2507
  }): OutgoingPaymentRequest[];
2707
- /**
2708
- * Subscribe to payment request responses (for outgoing requests)
2709
- * @param handler - Handler function for incoming responses
2710
- * @returns Unsubscribe function
2711
- */
2508
+ /** Subscribe to payment request responses. @see PaymentRequests.onPaymentRequestResponse */
2712
2509
  onPaymentRequestResponse(handler: PaymentRequestResponseHandler): () => void;
2713
- /**
2714
- * Wait for a response to a payment request
2715
- * @param requestId - The outgoing request ID to wait for
2716
- * @param timeoutMs - Timeout in milliseconds (default: 60000)
2717
- * @returns Promise that resolves with the response or rejects on timeout
2718
- */
2510
+ /** Wait for a response to a payment request. @see PaymentRequests.waitForPaymentResponse */
2719
2511
  waitForPaymentResponse(requestId: string, timeoutMs?: number): Promise<PaymentRequestResponse>;
2720
- /**
2721
- * Cancel an active {@link waitForPaymentResponse} call.
2722
- *
2723
- * The pending promise is rejected with a `'Cancelled'` error.
2724
- *
2725
- * @param requestId - The outgoing request ID whose wait should be cancelled.
2726
- */
2512
+ /** Cancel an active {@link waitForPaymentResponse} call. @see PaymentRequests.cancelWaitForPaymentResponse */
2727
2513
  cancelWaitForPaymentResponse(requestId: string): void;
2728
- /**
2729
- * Remove an outgoing payment request and cancel any pending wait.
2730
- *
2731
- * @param requestId - ID of the outgoing request to remove.
2732
- */
2514
+ /** Remove an outgoing payment request and cancel any pending wait. @see PaymentRequests.removeOutgoingPaymentRequest */
2733
2515
  removeOutgoingPaymentRequest(requestId: string): void;
2734
- /**
2735
- * Remove all outgoing payment requests that are `'paid'`, `'rejected'`, or `'expired'`.
2736
- */
2516
+ /** Remove all `'paid'`/`'rejected'`/`'expired'` outgoing requests. @see PaymentRequests.clearCompletedOutgoingPaymentRequests */
2737
2517
  clearCompletedOutgoingPaymentRequests(): void;
2738
- /**
2739
- * Fold a payment-request response into the outgoing surface and notify —
2740
- * shared by the transport subscription and the wallet-api outgoing refresh
2741
- * (S4): update the matched outgoing request, resolve any
2742
- * {@link waitForPaymentResponse} waiter, emit the event, run the handlers.
2743
- */
2744
- private dispatchPaymentRequestResponse;
2745
- /**
2746
- * Send a response to a payment request (used internally by accept/reject/pay methods)
2747
- */
2748
- private sendPaymentRequestResponse;
2518
+ /** Pull the wallet-api payment-request streams now (S4). @see PaymentRequests.syncPaymentRequests */
2519
+ syncPaymentRequests(): Promise<void>;
2749
2520
  /**
2750
2521
  * Fetch and process pending incoming transfers from the transport layer.
2751
2522
  *
@@ -2759,6 +2530,7 @@ declare class PaymentsModule {
2759
2530
  * @param _options - Deprecated; the v1 finalization options are ignored.
2760
2531
  * @param callback - Optional callback invoked for each newly received transfer
2761
2532
  * @returns ReceiveResult with the newly received transfers
2533
+ * @see Delivery.receive
2762
2534
  */
2763
2535
  receive(_options?: ReceiveOptions, callback?: (transfer: IncomingTransfer) => void): Promise<ReceiveResult>;
2764
2536
  /**
@@ -2768,6 +2540,8 @@ declare class PaymentsModule {
2768
2540
  /**
2769
2541
  * Get total portfolio value in USD.
2770
2542
  * Returns null if PriceProvider is not configured.
2543
+ *
2544
+ * @see TokenView.getFiatBalance
2771
2545
  */
2772
2546
  getFiatBalance(): Promise<number | null>;
2773
2547
  /**
@@ -2785,6 +2559,7 @@ declare class PaymentsModule {
2785
2559
  *
2786
2560
  * @param coinId - Optional coin ID to filter by (e.g. hex string). When omitted, all coin types are returned.
2787
2561
  * @returns Array of balance summaries (synchronous — no await needed).
2562
+ * @see TokenView.getBalance
2788
2563
  */
2789
2564
  getBalance(coinId?: string): Asset[];
2790
2565
  /**
@@ -2793,22 +2568,10 @@ declare class PaymentsModule {
2793
2568
  * (`'transferring'`) tokens are reported only in the `transferring*` fields
2794
2569
  * and excluded from `totalAmount` (#517 item 3). Fiat value derives from
2795
2570
  * `totalAmount`, so it likewise excludes in-flight value.
2796
- */
2797
- getAssets(coinId?: string): Promise<Asset[]>;
2798
- /**
2799
- * Aggregate tokens by coinId with confirmed/unconfirmed/transferring breakdown.
2800
- * Excludes tokens with status 'spent' or 'invalid'.
2801
2571
  *
2802
- * In-flight (`'transferring'`) tokens are LEAVING the wallet during an active
2803
- * send, so they are NOT counted as spendable: they are tracked in their own
2804
- * `transferring*` fields and excluded from `totalAmount`/`unconfirmedAmount`.
2805
- * Counting them as balance would show the user value they cannot spend (the
2806
- * #517 incident follow-up).
2572
+ * @see TokenView.getAssets
2807
2573
  */
2808
- private aggregateTokens;
2809
- /** Fold one token into its coin's running totals (see {@link aggregateTokens}). */
2810
- private accumulateToken;
2811
- private newAssetAccumulator;
2574
+ getAssets(coinId?: string): Promise<Asset[]>;
2812
2575
  /**
2813
2576
  * Get all tokens, optionally filtered by coin type and/or status.
2814
2577
  *
@@ -2816,6 +2579,7 @@ declare class PaymentsModule {
2816
2579
  * @param filter.coinId - Return only tokens of this coin type.
2817
2580
  * @param filter.status - Return only tokens with this status (e.g. `'submitted'` for unconfirmed).
2818
2581
  * @returns Array of matching {@link Token} objects (synchronous).
2582
+ * @see TokenView.getTokens
2819
2583
  */
2820
2584
  getTokens(filter?: {
2821
2585
  coinId?: string;
@@ -2826,6 +2590,7 @@ declare class PaymentsModule {
2826
2590
  *
2827
2591
  * @param id - The local UUID assigned when the token was added.
2828
2592
  * @returns The token, or `undefined` if not found.
2593
+ * @see TokenView.getToken
2829
2594
  */
2830
2595
  getToken(id: string): Token | undefined;
2831
2596
  /**
@@ -2883,6 +2648,7 @@ declare class PaymentsModule {
2883
2648
  * token state from being re-added (e.g. via Nostr re-delivery).
2884
2649
  *
2885
2650
  * @returns A shallow copy of the tombstone array.
2651
+ * @see TokenView.getTombstones
2886
2652
  */
2887
2653
  getTombstones(): TombstoneEntry[];
2888
2654
  /**
@@ -2892,36 +2658,23 @@ declare class PaymentsModule {
2892
2658
  * @param tokenId - The genesis token ID.
2893
2659
  * @param stateHash - The state hash of the token version to check.
2894
2660
  * @returns `true` if the exact combination has been tombstoned.
2661
+ * @see TokenView.isStateTombstoned
2895
2662
  */
2896
2663
  isStateTombstoned(tokenId: string, stateHash: string): boolean;
2897
- private rebuildTombstoneKeySet;
2898
- /**
2899
- * Merge tombstones received from a remote sync source.
2900
- *
2901
- * Any local token whose `(tokenId, stateHash)` matches a remote tombstone is
2902
- * removed. The remote tombstones are then added to the local set (union merge).
2903
- *
2904
- * @param remoteTombstones - Tombstone entries from the remote source.
2905
- * @returns Number of local tokens that were removed.
2906
- */
2907
- mergeTombstones(remoteTombstones: TombstoneEntry[]): Promise<number>;
2908
2664
  /**
2909
2665
  * Remove tombstones older than `maxAge` and cap the list at 100 entries.
2910
2666
  *
2911
2667
  * @param maxAge - Maximum age in milliseconds (default: 30 days).
2668
+ * @see TokenView.pruneTombstones
2912
2669
  */
2913
2670
  pruneTombstones(maxAge?: number): Promise<void>;
2914
2671
  /**
2915
2672
  * Get the transaction history sorted newest-first.
2916
2673
  *
2917
2674
  * @returns Array of {@link TransactionHistoryEntry} objects in descending timestamp order.
2675
+ * @see TransferHistory.getHistory
2918
2676
  */
2919
2677
  getHistory(): TransactionHistoryEntry[];
2920
- /**
2921
- * Best-effort resolve sender's DIRECT address and nametag from their transport pubkey.
2922
- * Returns empty object if transport doesn't support resolution or lookup fails.
2923
- */
2924
- private resolveSenderInfo;
2925
2678
  /**
2926
2679
  * Append an entry to the transaction history.
2927
2680
  *
@@ -2930,56 +2683,15 @@ declare class PaymentsModule {
2930
2683
  * Duplicate entries with the same `dedupKey` are silently ignored (upsert).
2931
2684
  *
2932
2685
  * @param entry - History entry fields (without `id` and `dedupKey`).
2686
+ * @see TransferHistory.addToHistory
2933
2687
  */
2934
2688
  addToHistory(entry: Omit<TransactionHistoryEntry, 'id' | 'dedupKey'>): Promise<void>;
2935
2689
  /**
2936
2690
  * Load history into the in-memory cache.
2937
2691
  *
2938
- * In the wallet-api composition (the `walletApi` client is present) the
2939
- * durable §10 history log lives on the SERVER — the thin storage provider
2940
- * keeps none — so the cache is rebuilt from `walletApi.listHistory()`. The
2941
- * twin of the #521 inventory reload bug: `_historyCache` is process-lifetime,
2942
- * so a reload (tab refresh) must re-pull it or render an empty history.
2943
- * Compositions WITHOUT `walletApi` keep the legacy local path below.
2692
+ * @see TransferHistory.loadHistory
2944
2693
  */
2945
2694
  loadHistory(): Promise<void>;
2946
- /**
2947
- * Rebuild `_historyCache` from the server's §10 history log (the wallet-api
2948
- * composition). Pages newest-first via the keyset cursor until `more:false`
2949
- * or the page cap; dedups by `dedupKey` (a hydrate-then-receive in the same
2950
- * session must not double-list). The S6 `memo` / `counterpartyNametag`
2951
- * envelopes are decrypted with the owner's own field key on the way in.
2952
- *
2953
- * #642 incremental fast path: after one completed hydration for this owner,
2954
- * later pulls stop at the first non-empty page holding nothing new — the
2955
- * §10 log is append-only (newest-first keyset), so everything past a fully
2956
- * known page is already cached. The steady-state 30s inventory resync then
2957
- * costs ONE history page instead of a full re-pagination (which on a wallet
2958
- * whose history overflows the page cap was 100 pages, every tick, forever).
2959
- *
2960
- * Best-effort, like the §10 history POST: history is untrusted DISPLAY data,
2961
- * so a backend outage during hydration must NEVER fail `load()` (the money
2962
- * path) — the in-session cache is left intact and the pull retries next load.
2963
- */
2964
- private hydrateHistoryFromServer;
2965
- /**
2966
- * Map one §16 history wire record onto the display
2967
- * {@link TransactionHistoryEntry}. `counterpartyNametag` lands on the role-
2968
- * appropriate field (sender for RECEIVED, recipient otherwise); the S6 memo +
2969
- * nametag envelopes decrypt under THIS wallet's field key (self-scoped at
2970
- * rest — §8.3), surfaced as absent if they don't decrypt rather than as
2971
- * ciphertext (same rule as mailbox/payment-request memos).
2972
- */
2973
- private historyEntryFromWire;
2974
- /** S6 field decrypt that surfaces an undecryptable envelope as absent (§8.3). */
2975
- private tryDecryptField;
2976
- /**
2977
- * Import history entries from remote TXF data into local store.
2978
- * Delegates to the local TokenStorageProvider's importHistoryEntries() for
2979
- * persistent storage, with in-memory fallback.
2980
- * Reused by both load() (initial IPFS fetch) and _doSync() (merge result).
2981
- */
2982
- private importRemoteHistoryEntries;
2983
2695
  /**
2984
2696
  * Get the first local token storage provider (for history operations).
2985
2697
  */
@@ -3102,6 +2814,7 @@ declare class PaymentsModule {
3102
2814
  * Tokens that fail validation or are detected as spent are marked `'invalid'`.
3103
2815
  *
3104
2816
  * @returns Object with arrays of valid and invalid tokens.
2817
+ * @see TokenView.validate
3105
2818
  */
3106
2819
  validate(): Promise<{
3107
2820
  valid: Token[];
@@ -3116,17 +2829,6 @@ declare class PaymentsModule {
3116
2829
  * Uses pre-resolved PeerInfo if available, otherwise resolves via transport.
3117
2830
  */
3118
2831
  private resolveTransportPubkey;
3119
- /**
3120
- * v2 engine transfer (sender-driven): the sender handed us a FINISHED token.
3121
- * Decode the blob, dedup by the genesis-stable token id, store it as a
3122
- * confirmed token, and emit/record the receipt. No commitment / inclusion-proof
3123
- * / finalization round-trip (contrast the v1 sourceToken+transferTx path).
3124
- *
3125
- * Transport-agnostic (sdk-changes S3): fed by the relay push subscription
3126
- * AND by the delivery port's incoming pump — the returned verdict lets the
3127
- * pump map outcomes onto `ack('claimed' | 'rejected')`.
3128
- */
3129
- private handleV2Transfer;
3130
2832
  private teardownDeliveryPump;
3131
2833
  /**
3132
2834
  * Route a §9 wake nudge to the matching stream's pull. The wake is
@@ -3190,143 +2892,16 @@ declare class PaymentsModule {
3190
2892
  * ack for a provider without it (e.g. the relay no-op).
3191
2893
  */
3192
2894
  private flushIncomingAcks;
3193
- /** The S4 capability slice — null unless the composed wallet-api port carries it. */
3194
- private paymentRequestsApi;
3195
- private teardownPaymentRequestPump;
3196
- private prCursorKey;
3197
- private readPrCursorState;
3198
- private persistPrCursorState;
3199
- private prSettlingKey;
3200
- /**
3201
- * Single-flight load: concurrent callers (the pump's reload re-apply, resume's
3202
- * reconcile, a live pay catch) share ONE storage.get + ONE Map instance so a
3203
- * lazy read never overwrites another context's in-memory mutation.
3204
- */
3205
- private ensureSettlingJournalLoaded;
3206
- /**
3207
- * Serialize every read-modify-write through a tail-promise chain so two
3208
- * concurrent mutations can't lose an entry (the #679/#680 mutex lesson — a
3209
- * dropped entry is a re-payable request is a double-pay). `fn` returns true
3210
- * when the Map changed and must be persisted.
3211
- */
3212
- private mutateSettlingJournal;
3213
- /**
3214
- * #441: link a request to its in-flight transfer. `committed` marks a
3215
- * DEFINITE spend whose anchor intent is soft-aborted and will NOT resume-
3216
- * complete — a `PartialSendConflictError` (≥1 leg already delivered). The
3217
- * reconcile must resolve such a link 'paid' and NEVER revert it to payable
3218
- * (re-paying the full amount would double-pay the delivered leg). A
3219
- * non-`committed` link is a keep-open outcome that resume may still complete
3220
- * OR abort (e.g. CERTIFICATION_UNCONFIRMED losing to a foreign tx delivers
3221
- * nothing) — those DO revert to payable on abort.
3222
- */
3223
- private journalSettling;
3224
- private clearSettling;
3225
- /**
3226
- * Pull the wallet-api payment-request streams now (S4): drains the payer's
3227
- * incoming `?since=<seq>` stream (gap-free — §9/§16) into the existing
3228
- * handler/event surface and refreshes outgoing requests still awaiting a
3229
- * response. The poll interval and `load()` call this automatically; it is
3230
- * public for explicit fetch-now flows (mirrors {@link receive}). A no-op in
3231
- * compositions without the wallet-api payment-request capability — there
3232
- * the Nostr subscription is push-based.
3233
- */
3234
- syncPaymentRequests(): Promise<void>;
3235
- /** Coalesces concurrent pump runs (poll + wake + load can overlap). */
3236
- private pumpPaymentRequests;
3237
- private doPumpPaymentRequests;
3238
- /**
3239
- * Drain the payer's gap-free `?since=<seq>` stream (§9/§16), mirroring the
3240
- * mailbox-cursor pattern: the persisted `{cursor, syncEpoch}` is the resume
3241
- * point; a `syncEpoch` change (server restore — §5.4) voids cursor
3242
- * continuity, so the tail re-pulls from 0 and the id-dedup in
3243
- * {@link surfaceIncomingPaymentRequest} absorbs the replays.
3244
- *
3245
- * Because the surfaced list is in-memory only, each session FIRST runs one
3246
- * full incoming hydration from `since=0` with NO status filter (#556 —
3247
- * mirrors {@link hydrateHistoryFromServer}): a fresh engine rebuilds the
3248
- * CURRENT state of ALL incoming requests — open AND resolved — so a request
3249
- * paid/declined/expired in a PRIOR session is still present (with its
3250
- * resolved status) instead of vanishing once the cursor advanced past it.
3251
- * Hydration NEVER fires the new-incoming handlers/events for resolved
3252
- * requests — only `open` ones notify (the status-aware
3253
- * {@link surfaceIncomingPaymentRequest}) — so reopening can't spam stale
3254
- * 'new request' notifications. After hydration the `since`-cursor delta poll
3255
- * picks up live updates from the resume point.
3256
- */
3257
- private pumpIncomingPaymentRequests;
3258
- /**
3259
- * Decrypt a payment-request's recipient-addressed memo envelope into
3260
- * `{ memo, senderNametag }` (the requester's message + nametag). The key is
3261
- * the ECDH shared secret between THIS wallet (the payer) and the requester's
3262
- * chain pubkey (`wire.fromPubkey`) — symmetric with the requester's
3263
- * create-time derivation. Returns an empty bundle (and logs at debug) on any
3264
- * absence/failure so the incoming view never wedges on an unreadable memo
3265
- * (PR twin of #546/#547).
3266
- */
3267
- private decryptPaymentRequestMemo;
3268
- /** §16 wire status → the public {@link PaymentRequestStatus} display status. */
3269
- private static readonly PR_WIRE_STATUS;
3270
- /** Terminal local statuses: a re-surfaced wire may advance a request INTO one, never out of it. */
3271
- private static readonly PR_TERMINAL;
3272
- /**
3273
- * Map a §16 wire request onto the public {@link IncomingPaymentRequest}
3274
- * surface, deduped by id (the in-memory id-dedup doubles as the replay guard
3275
- * for cursor resets). Requests of EVERY status are surfaced so a reloaded
3276
- * thin wallet rebuilds the CURRENT state of its incoming view (#556) — open
3277
- * ones land as actionable `pending`, resolved ones carry their paid/declined
3278
- * (→ `rejected`)/expired status. Only `open` requests fire the new-incoming
3279
- * event + handlers; resolved requests are folded into the list silently, so a
3280
- * reload (or a `syncEpoch` re-pull) never re-notifies for already-resolved
3281
- * requests. Multi-asset requests surface their first asset (the module's
3282
- * request surface is single-asset; module-created requests always are).
3283
- */
3284
- private surfaceIncomingPaymentRequest;
3285
- /**
3286
- * Outgoing requests are a `?before=` backfill view (§16 — newest-first, no
3287
- * gap-free tail): refresh only while something local still awaits a
3288
- * response, paging until every pending id is resolved or the view drains.
3289
- */
3290
- private refreshOutgoingPaymentRequests;
3291
- /** Fold a server-side status change into the outgoing surface (responses + expiry). */
3292
- private applyOutgoingPaymentRequestState;
3293
- /**
3294
- * E.3 resume: list this wallet's OPEN intents (server-side — any device),
3295
- * decrypt each payload, and re-run the engine with the SAME transferId and
3296
- * inputs — deterministic realization yields byte-identical transactions, so
3297
- * an interrupted transfer completes instead of failing (proof fetch →
3298
- * match-verify → apply, Part E). Called at sign-in (S4).
2895
+ /**
2896
+ * E.3 resume of this wallet's OPEN send intents.
2897
+ *
2898
+ * @see IntentResume.resumeOpenIntents
3299
2899
  */
3300
2900
  resumeOpenIntents(): Promise<{
3301
2901
  resumed: string[];
3302
2902
  conflicted: string[];
3303
2903
  failed: string[];
3304
2904
  }>;
3305
- /**
3306
- * #441: resolve every journaled settling payment request against a resume
3307
- * outcome. Completed → send the deferred 'paid' response (server now told) and
3308
- * resolve 'paid'. Aborted (nothing delivered) → clear journal, return to
3309
- * payable. Still open → leave it. For an id accounted for by NONE of those
3310
- * (a crash between resume-complete and the local write), consult the server
3311
- * `listIntents('aborted')` authority: aborted → payable; else → paid (a
3312
- * completed row the server GC'd). Direction-of-error is deliberate: the only
3313
- * residual false-paid is a transfer that aborted server-side AND whose local
3314
- * 'aborted' write was lost AND whose server aborted-row was later GC'd — it is
3315
- * treated as paid, erring toward PAID-NEVER-RE-PAYABLE (no double-pay), the
3316
- * invariant this fix exists to protect.
3317
- */
3318
- private reconcileSettlingPaymentRequests;
3319
- /** #441: the linked transfer completed — tell the server 'paid' and resolve 'paid'. */
3320
- private resolveSettledPaid;
3321
- /** #441: the linked transfer aborted — nothing was paid; clear the link and return to payable. */
3322
- private revertSettlingToPayable;
3323
- /**
3324
- * Re-run one intent end-to-end: getToken (works for tombstoned rows — §5.3
3325
- * recovery surface), engine re-run under the original transferId, journaled
3326
- * delivery, the single §7 apply (inventory custody only), uniform close,
3327
- * and the SENT history record (dedupKey'd by transferId — idempotent).
3328
- */
3329
- private resumeIntent;
3330
2905
  /**
3331
2906
  * Persist the token state to every (non-disabled) token storage provider.
3332
2907
  *
@@ -3342,77 +2917,6 @@ declare class PaymentsModule {
3342
2917
  * behavior.
3343
2918
  */
3344
2919
  private save;
3345
- private loadPendingV2Deliveries;
3346
- /**
3347
- * #621: journaled finished blobs for an intent, keyed by op position. opIndex when present,
3348
- * else positional among the intent's entries (legacy entries journaled in op order). Resume
3349
- * uses this to re-deliver an already-certified op instead of re-running the engine on its spent source.
3350
- */
3351
- private journaledByOp;
3352
- /** #517: run a journal read-modify-write atomically against all other journal mutations. */
3353
- private withJournalLock;
3354
- private savePendingV2Delivery;
3355
- private removePendingV2Delivery;
3356
- /**
3357
- * The hoisted send delivery pass (#699): hand a send's journaled committed
3358
- * blobs to ONE recipient — a single deliverBatch call when the port offers
3359
- * it and there is more than one blob, else per-blob deliver at the
3360
- * certification fan-out width. Returns true iff every blob was delivered
3361
- * (deferred blobs stay journaled). Never throws (§3.1).
3362
- */
3363
- private deliverCommittedBlobs;
3364
- /**
3365
- * Batch sibling of {@link tryDeliver}: success clears every journal entry;
3366
- * ANY failure keeps them ALL journaled (the deposit is idempotent by
3367
- * content-derived entry_id, so a replay absorbs entries that already
3368
- * landed). Never throws.
3369
- */
3370
- private tryDeliverBatch;
3371
- /**
3372
- * Per-blob fallback (a batch-less port, or a single blob), chunked at
3373
- * MAX_SEND_OPERATION_CONCURRENCY so the pass keeps the certification
3374
- * fan-out era's delivery width. Never throws.
3375
- */
3376
- private deliverPerBlob;
3377
- /**
3378
- * Covenant §3.1 (#621): once the source is certified on-chain, a delivery failure must NEVER
3379
- * fail the sender. Recipient-side conditions (a full mailbox / 429 from a never-claiming recipient)
3380
- * and transient delivery-infra failures (5xx/network) both leave the finished blob JOURNALED for
3381
- * (re-)delivery — the send resolves as delivery-pending and the sender moves on. The blob is already
3382
- * journaled (savePendingV2Delivery ran before this); on success we clear the journal, on any failure
3383
- * we keep it. Returns true if delivered, false if deferred. Never throws.
3384
- */
3385
- private tryDeliver;
3386
- /**
3387
- * Replay journaled finished-but-undelivered v2 blobs (kicked from load())
3388
- * through the delivery port (sdk-changes S3). Idempotent end to end: the
3389
- * mailbox deposit is idempotent by the content-derived entry_id — it succeeds
3390
- * even after the recipient claimed (§6) — and the relay path's recipient
3391
- * dedups by the genesis-stable token id.
3392
- *
3393
- * #517 item 1: instead of a silent unbounded fire-and-forget, each entry is
3394
- * retried with bounded exponential backoff, its cumulative failed-attempt
3395
- * count is journaled across loads, and an entry that exhausts
3396
- * {@link MAX_DELIVERY_REPLAY_ATTEMPTS} is SURFACED as poison
3397
- * (`delivery:undeliverable`) and left journaled but no longer auto-retried —
3398
- * so a journaled blob never sits undelivered invisibly.
3399
- */
3400
- private replayPendingV2Deliveries;
3401
- /** Replay a single journaled entry: backoff retries → success/removal, or → bounded poison. */
3402
- private replayOneDelivery;
3403
- /**
3404
- * §3.1 (#621): defer a recipient-quota (429) delivery — keep it journaled, never poison it (it
3405
- * self-heals when the recipient claims), and retry no sooner than the deferral window. Surfaced
3406
- * distinctly (delivery:deferred) so a UI can show "recipient's mailbox is full — will retry".
3407
- */
3408
- private deferDelivery;
3409
- /** One delivery with in-pass exponential backoff; throws the last error if all attempts fail. */
3410
- private attemptDeliveryWithBackoff;
3411
- /** Mark a journal entry poison (keep it, stop retrying) and surface it (#517 item 1). */
3412
- private markDeliveryPoison;
3413
- private bumpDeliveryAttempts;
3414
- /** Mutate one journaled entry in place (keyed by tokenBlob) and persist. No-op if gone. */
3415
- private updatePendingV2Delivery;
3416
2920
  private createStorageData;
3417
2921
  private loadFromStorageData;
3418
2922
  /**
@@ -4802,7 +4306,7 @@ interface IncomingTransfer {
4802
4306
  readonly memo?: string;
4803
4307
  readonly receivedAt: number;
4804
4308
  }
4805
- type PaymentRequestStatus = 'pending' | 'accepted' | 'rejected' | 'paid' | 'expired' | 'settling';
4309
+ type PaymentRequestStatus = 'pending' | 'rejected' | 'paid' | 'expired' | 'settling';
4806
4310
  /**
4807
4311
  * Outgoing payment request (requesting payment from someone)
4808
4312
  */
@@ -4861,7 +4365,7 @@ type PaymentRequestHandler = (request: IncomingPaymentRequest) => void;
4861
4365
  /**
4862
4366
  * Response type for payment requests
4863
4367
  */
4864
- type PaymentRequestResponseType = 'accepted' | 'rejected' | 'paid';
4368
+ type PaymentRequestResponseType = 'rejected' | 'paid';
4865
4369
  /**
4866
4370
  * Outgoing payment request (we sent to someone)
4867
4371
  */
@@ -4963,7 +4467,7 @@ interface TrackedAddress extends TrackedAddressEntry {
4963
4467
  /** Primary nametag (from nametag cache, without @ prefix) */
4964
4468
  readonly nametag?: string;
4965
4469
  }
4966
- type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'transfer:delivery_pending' | 'transfer:invalid' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:expired' | 'payment_request:settling' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:error' | 'storage:degraded' | 'inventory:conflict' | 'split:checkpoint-stuck' | 'send:partial-remainder' | 'delivery:undeliverable' | 'delivery:deferred' | 'walletapi:session' | 'realtime:status' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated' | 'invoice:created' | 'invoice:payment' | 'invoice:asset_covered' | 'invoice:target_covered' | 'invoice:covered' | 'invoice:closed' | 'invoice:cancelled' | 'invoice:expired' | 'invoice:unknown_reference' | 'invoice:overpayment' | 'invoice:irrelevant' | 'invoice:auto_returned' | 'invoice:auto_return_failed' | 'invoice:return_received' | 'invoice:over_refund_warning' | 'invoice:receipt_sent' | 'invoice:receipt_received' | 'invoice:cancellation_sent' | 'invoice:cancellation_received' | 'swap:proposal_received' | 'swap:proposed' | 'swap:accepted' | 'swap:rejected' | 'swap:announced' | 'swap:deposit_sent' | 'swap:deposit_confirmed' | 'swap:deposits_covered' | 'swap:concluding' | 'swap:payout_received' | 'swap:completed' | 'swap:cancelled' | 'swap:failed' | 'swap:deposit_returned' | 'swap:bounce_received';
4470
+ type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'transfer:delivery_pending' | 'transfer:invalid' | 'payment_request:incoming' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:expired' | 'payment_request:settling' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:error' | 'storage:degraded' | 'inventory:conflict' | 'split:checkpoint-stuck' | 'send:partial-remainder' | 'delivery:undeliverable' | 'delivery:deferred' | 'walletapi:session' | 'realtime:status' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated' | 'invoice:created' | 'invoice:payment' | 'invoice:asset_covered' | 'invoice:target_covered' | 'invoice:covered' | 'invoice:closed' | 'invoice:cancelled' | 'invoice:expired' | 'invoice:unknown_reference' | 'invoice:overpayment' | 'invoice:irrelevant' | 'invoice:auto_returned' | 'invoice:auto_return_failed' | 'invoice:return_received' | 'invoice:over_refund_warning' | 'invoice:receipt_sent' | 'invoice:receipt_received' | 'invoice:cancellation_sent' | 'invoice:cancellation_received' | 'swap:proposal_received' | 'swap:proposed' | 'swap:accepted' | 'swap:rejected' | 'swap:announced' | 'swap:deposit_sent' | 'swap:deposit_confirmed' | 'swap:deposits_covered' | 'swap:concluding' | 'swap:payout_received' | 'swap:completed' | 'swap:cancelled' | 'swap:failed' | 'swap:deposit_returned' | 'swap:bounce_received';
4967
4471
  interface SphereEventMap {
4968
4472
  'transfer:incoming': IncomingTransfer;
4969
4473
  'transfer:confirmed': TransferResult;
@@ -4986,7 +4490,6 @@ interface SphereEventMap {
4986
4490
  reason: string;
4987
4491
  };
4988
4492
  'payment_request:incoming': IncomingPaymentRequest;
4989
- 'payment_request:accepted': IncomingPaymentRequest;
4990
4493
  'payment_request:rejected': IncomingPaymentRequest;
4991
4494
  'payment_request:paid': IncomingPaymentRequest;
4992
4495
  'payment_request:expired': IncomingPaymentRequest;
@@ -7833,25 +7336,22 @@ interface DiscoverAddressesResult {
7833
7336
  }
7834
7337
 
7835
7338
  /**
7836
- * Legacy File Serialization Types
7339
+ * Text Wallet Backup Serialization Types
7837
7340
  */
7838
7341
 
7839
- type LegacyFileType = 'dat' | 'txt' | 'json' | 'mnemonic' | 'unknown';
7840
- interface LegacyFileInfo {
7841
- fileType: LegacyFileType;
7842
- isEncrypted: boolean;
7843
- isBIP32: boolean;
7844
- hasMnemonic: boolean;
7845
- }
7846
7342
  /**
7847
- * Result of parsing a legacy wallet file
7343
+ * Result of parsing a text wallet backup file
7848
7344
  */
7345
+ /** Backup file shapes `Sphere.importFromLegacyFile` accepts. Bitcoin Core `.dat` was removed (#604 — L3-only). */
7346
+ type LegacyFileType = 'txt' | 'json' | 'mnemonic' | 'unknown';
7347
+ /** Reports PBKDF2 progress while decrypting a password-protected backup. */
7348
+ type DecryptionProgressCallback = (iteration: number, total: number) => Promise<void> | void;
7849
7349
  interface LegacyFileParsedData {
7850
7350
  /** Master private key (hex) */
7851
7351
  masterKey: string;
7852
7352
  /** Chain code for BIP32 derivation */
7853
7353
  chainCode?: string;
7854
- /** Descriptor path from wallet.dat (e.g., "84'/1'/0'") */
7354
+ /** Descriptor path (e.g., "84'/1'/0'") */
7855
7355
  descriptorPath?: string;
7856
7356
  /** Mnemonic if available */
7857
7357
  mnemonic?: string;
@@ -7866,31 +7366,8 @@ interface LegacyFileParseResult {
7866
7366
  data?: LegacyFileParsedData;
7867
7367
  /** Indicates file needs password for decryption */
7868
7368
  needsPassword?: boolean;
7869
- /** CMasterKey data for .dat decryption */
7870
- encryptionInfo?: {
7871
- iterations: number;
7872
- salt: Uint8Array;
7873
- encryptedKey: Uint8Array;
7874
- };
7875
7369
  error?: string;
7876
7370
  }
7877
- /**
7878
- * Progress callback for decryption operations
7879
- */
7880
- type DecryptionProgressCallback = (iteration: number, total: number) => Promise<void> | void;
7881
- /**
7882
- * Options for importing from legacy file
7883
- */
7884
- interface LegacyFileImportOptions {
7885
- /** Raw file content */
7886
- fileContent: string | Uint8Array;
7887
- /** File name (for type detection) */
7888
- fileName: string;
7889
- /** Password for encrypted files */
7890
- password?: string;
7891
- /** Progress callback for long decryption operations */
7892
- onDecryptProgress?: DecryptionProgressCallback;
7893
- }
7894
7371
 
7895
7372
  /**
7896
7373
  * Sphere - Main SDK Entry Point
@@ -7933,7 +7410,6 @@ interface LegacyFileImportOptions {
7933
7410
  */
7934
7411
 
7935
7412
  declare function isValidNametag(nametag: string): boolean;
7936
-
7937
7413
  /** Steps reported by the onProgress callback during wallet init/create/load/import */
7938
7414
  type InitProgressStep = 'clearing' | 'storing_keys' | 'initializing' | 'recovering_nametag' | 'registering_nametag' | 'syncing_identity' | 'syncing_tokens' | 'discovering_addresses' | 'finalizing' | 'complete';
7939
7415
  /** Progress info passed to onProgress callback */
@@ -8541,6 +8017,43 @@ declare class Sphere {
8541
8017
  * modules fall back to their legacy path, same as init).
8542
8018
  */
8543
8019
  setOracleApiKey(apiKey: string): Promise<void>;
8020
+ /**
8021
+ * Import a wallet from a backup file: a `UNICITY WALLET DETAILS` text backup
8022
+ * (the format `exportToTxt` writes, optionally password-encrypted), a legacy
8023
+ * flat-JSON webwallet export, or a bare mnemonic in a text file.
8024
+ *
8025
+ * @example
8026
+ * const result = await Sphere.importFromLegacyFile({
8027
+ * fileContent: await file.text(),
8028
+ * fileName: file.name,
8029
+ * password, // when the backup is encrypted
8030
+ * ...providers,
8031
+ * });
8032
+ */
8033
+ static importFromLegacyFile(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
8034
+ /** The backup file's text. */
8035
+ fileContent: string;
8036
+ /** File name (used for type detection) */
8037
+ fileName: string;
8038
+ /** Password for encrypted files */
8039
+ password?: string;
8040
+ /** Progress callback for long decryption operations */
8041
+ onDecryptProgress?: DecryptionProgressCallback;
8042
+ }): Promise<{
8043
+ success: boolean;
8044
+ sphere?: Sphere;
8045
+ mnemonic?: string;
8046
+ needsPassword?: boolean;
8047
+ error?: string;
8048
+ }>;
8049
+ /**
8050
+ * Detect legacy file type from filename and content
8051
+ */
8052
+ static detectLegacyFileType(fileName: string, content: string): LegacyFileType;
8053
+ /**
8054
+ * Check if a legacy file is encrypted
8055
+ */
8056
+ static isLegacyFileEncrypted(fileName: string, content: string): boolean;
8544
8057
  /**
8545
8058
  * Check if wallet has BIP32 master key for HD derivation
8546
8059
  */
@@ -8625,60 +8138,6 @@ declare class Sphere {
8625
8138
  mnemonic?: string;
8626
8139
  error?: string;
8627
8140
  }>;
8628
- /**
8629
- * Import wallet from legacy file (.dat, .txt, or mnemonic text)
8630
- *
8631
- * Supports:
8632
- * - Bitcoin Core wallet.dat files (SQLite format, encrypted or unencrypted)
8633
- * - Text backup files (UNICITY WALLET DETAILS format)
8634
- * - Plain mnemonic text (12 or 24 words)
8635
- *
8636
- * @returns Object with success status, created Sphere instance, and optionally recovered mnemonic
8637
- *
8638
- * @example
8639
- * ```ts
8640
- * // Import from .dat file
8641
- * const fileBuffer = await file.arrayBuffer();
8642
- * const result = await Sphere.importFromLegacyFile({
8643
- * fileContent: new Uint8Array(fileBuffer),
8644
- * fileName: 'wallet.dat',
8645
- * password: 'wallet-password', // if encrypted
8646
- * storage, transport, oracle,
8647
- * });
8648
- *
8649
- * // Import from .txt file
8650
- * const textContent = await file.text();
8651
- * const result = await Sphere.importFromLegacyFile({
8652
- * fileContent: textContent,
8653
- * fileName: 'backup.txt',
8654
- * storage, transport, oracle,
8655
- * });
8656
- * ```
8657
- */
8658
- static importFromLegacyFile(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
8659
- /** File content - Uint8Array for .dat, string for .txt */
8660
- fileContent: string | Uint8Array;
8661
- /** File name (used for type detection) */
8662
- fileName: string;
8663
- /** Password for encrypted files */
8664
- password?: string;
8665
- /** Progress callback for long decryption operations */
8666
- onDecryptProgress?: DecryptionProgressCallback;
8667
- }): Promise<{
8668
- success: boolean;
8669
- sphere?: Sphere;
8670
- mnemonic?: string;
8671
- needsPassword?: boolean;
8672
- error?: string;
8673
- }>;
8674
- /**
8675
- * Detect legacy file type from filename and content
8676
- */
8677
- static detectLegacyFileType(fileName: string, content: string | Uint8Array): LegacyFileType;
8678
- /**
8679
- * Check if a legacy file is encrypted
8680
- */
8681
- static isLegacyFileEncrypted(fileName: string, content: string | Uint8Array): boolean;
8682
8141
  /**
8683
8142
  * Get the current active address index
8684
8143
  *
@@ -9325,49 +8784,6 @@ declare function formatAmount(amount: bigint | string, options?: {
9325
8784
  maxFractionDigits?: number;
9326
8785
  }): string;
9327
8786
 
9328
- /**
9329
- * Encode data to bech32 address
9330
- *
9331
- * @example
9332
- * ```ts
9333
- * const address = encodeBech32('bc', 1, pubkeyHash);
9334
- * // 'bc1qw...'
9335
- * ```
9336
- */
9337
- declare function encodeBech32(hrp: string, version: number, program: Uint8Array): string;
9338
- /**
9339
- * Decode bech32 address
9340
- *
9341
- * @example
9342
- * ```ts
9343
- * const result = decodeBech32('bc1qw...');
9344
- * // { hrp: 'bc', witnessVersion: 1, data: Uint8Array }
9345
- * ```
9346
- */
9347
- declare function decodeBech32(addr: string): {
9348
- hrp: string;
9349
- witnessVersion: number;
9350
- data: Uint8Array;
9351
- } | null;
9352
- /**
9353
- * Create address from public key hash
9354
- *
9355
- * @example
9356
- * ```ts
9357
- * const address = createAddress('bc', pubkeyHash);
9358
- * // 'bc1...'
9359
- * ```
9360
- */
9361
- declare function createAddress(hrp: string, pubkeyHash: Uint8Array | string): string;
9362
- /**
9363
- * Validate bech32 address
9364
- */
9365
- declare function isValidBech32(addr: string): boolean;
9366
- /**
9367
- * Get HRP from address
9368
- */
9369
- declare function getAddressHrp(addr: string): string | null;
9370
-
9371
8787
  /**
9372
8788
  * Browser-safe UUID v4 generation.
9373
8789
  *
@@ -10590,100 +10006,27 @@ declare function parseWalletText(content: string): LegacyFileParseResult;
10590
10006
  declare function parseAndDecryptWalletText(content: string, password: string): LegacyFileParseResult;
10591
10007
 
10592
10008
  /**
10593
- * Wallet.dat Parsing
10009
+ * TXF storage-data serializer.
10594
10010
  *
10595
- * Parses Bitcoin Core wallet.dat files (SQLite format)
10596
- * Extracts keys, chain codes, and descriptors
10597
- */
10598
-
10599
- interface CMasterKeyData {
10600
- encryptedKey: Uint8Array;
10601
- salt: Uint8Array;
10602
- derivationMethod: number;
10603
- iterations: number;
10604
- position: number;
10605
- }
10606
- interface WalletDatInfo {
10607
- isSQLite: boolean;
10608
- isEncrypted: boolean;
10609
- isDescriptorWallet: boolean;
10610
- hasHDChain: boolean;
10611
- descriptorKeys: string[];
10612
- legacyKeys: string[];
10613
- chainCode: string | null;
10614
- descriptorPath: string | null;
10615
- cmasterKeys: CMasterKeyData[];
10616
- descriptorId: Uint8Array | null;
10617
- xpubString: string | null;
10618
- }
10619
- /**
10620
- * Check if data is a valid SQLite database
10621
- */
10622
- declare function isSQLiteDatabase(data: Uint8Array): boolean;
10623
- /**
10624
- * Check if wallet.dat is encrypted
10625
- */
10626
- declare function isWalletDatEncrypted(data: Uint8Array): boolean;
10627
- /**
10628
- * Decrypt master key from CMasterKey structure
10629
- */
10630
- declare function decryptCMasterKey(cmk: CMasterKeyData, password: string, onProgress?: DecryptionProgressCallback): Promise<string>;
10631
- /**
10632
- * Decrypt private key using decrypted master key
10633
- */
10634
- declare function decryptPrivateKey(encryptedKey: Uint8Array, pubkey: Uint8Array, masterKeyHex: string): string;
10635
- /**
10636
- * Parse wallet.dat file
10637
- * For encrypted wallets, returns info for decryption
10638
- */
10639
- declare function parseWalletDat(data: Uint8Array): LegacyFileParseResult;
10640
- /**
10641
- * Parse and decrypt wallet.dat file
10642
- */
10643
- declare function parseAndDecryptWalletDat(data: Uint8Array, password: string, onProgress?: DecryptionProgressCallback): Promise<LegacyFileParseResult>;
10644
-
10645
- /**
10646
- * TXF Serializer for SDK2
10647
- * Converts between SDK Token format and TXF storage format
10011
+ * Builds and parses the `TxfStorageData` DOCUMENT — the `_meta` / `_nametags` /
10012
+ * `_tombstones` / `_history` envelope plus the per-token slots. Tokens
10013
+ * themselves are opaque v2 CBOR blobs (hex) in `Token.sdkData`; this file never
10014
+ * decodes one.
10648
10015
  *
10649
- * Platform-independent implementation that works with SDK types directly.
10016
+ * A record that is not a v2 blob is logged and skipped on both the read and the
10017
+ * write path — never reinterpreted.
10650
10018
  */
10651
10019
 
10652
10020
  /**
10653
- * Normalize SDK token JSON to canonical TXF storage format.
10654
- * Converts all bytes objects to hex strings before storage.
10655
- */
10656
- declare function normalizeSdkTokenToStorage(sdkTokenJson: unknown): TxfToken;
10657
- /**
10658
- * Extract TXF token structure from Token.sdkData (jsonData)
10659
- */
10660
- declare function tokenToTxf(token: Token): TxfToken | null;
10661
- /**
10662
- * Convert token interface to simplified Token for parsing
10663
- */
10664
- interface TokenLike {
10665
- id: string;
10666
- sdkData?: string;
10667
- }
10668
- /**
10669
- * Extract TXF from any object with id and sdkData
10670
- */
10671
- declare function objectToTxf(obj: TokenLike): TxfToken | null;
10672
- /**
10673
- * Convert TXF token to Token interface
10674
- */
10675
- declare function txfToToken(tokenId: string, txf: TxfToken): Token;
10676
- /**
10677
- * Build TXF storage data from tokens and metadata
10021
+ * Build TXF storage data from tokens and metadata.
10022
+ *
10023
+ * Only v2 blob tokens are written. Anything else in `sdkData` has no v2
10024
+ * encoding, so it is dropped with a warning rather than written back in a shape
10025
+ * the reader cannot interpret.
10678
10026
  */
10679
10027
  declare function buildTxfStorageData(tokens: Token[], meta: Omit<TxfMeta, 'formatVersion'>, options?: {
10680
10028
  nametags?: NametagData[];
10681
10029
  tombstones?: TombstoneEntry[];
10682
- archivedTokens?: Map<string, TxfToken>;
10683
- forkedTokens?: Map<string, TxfToken>;
10684
- outboxEntries?: OutboxEntry[];
10685
- mintOutboxEntries?: MintOutboxEntry[];
10686
- invalidatedNametags?: InvalidatedNametagEntry[];
10687
10030
  historyEntries?: HistoryRecord[];
10688
10031
  }): Promise<TxfStorageData>;
10689
10032
  interface ParsedStorageData {
@@ -10691,11 +10034,6 @@ interface ParsedStorageData {
10691
10034
  meta: TxfMeta | null;
10692
10035
  nametags: NametagData[];
10693
10036
  tombstones: TombstoneEntry[];
10694
- archivedTokens: Map<string, TxfToken>;
10695
- forkedTokens: Map<string, TxfToken>;
10696
- outboxEntries: OutboxEntry[];
10697
- mintOutboxEntries: MintOutboxEntry[];
10698
- invalidatedNametags: InvalidatedNametagEntry[];
10699
10037
  historyEntries: HistoryRecord[];
10700
10038
  validationErrors: string[];
10701
10039
  }
@@ -10703,35 +10041,6 @@ interface ParsedStorageData {
10703
10041
  * Parse TXF storage data
10704
10042
  */
10705
10043
  declare function parseTxfStorageData(data: unknown): ParsedStorageData;
10706
- /**
10707
- * Get token ID from Token object (prefers genesis.data.tokenId)
10708
- */
10709
- declare function getTokenId(token: Token): string;
10710
- /**
10711
- * Get the current state hash from a TXF token
10712
- * Checks multiple sources in order of preference:
10713
- * 1. Last transaction's newStateHash
10714
- * 2. _integrity.currentStateHash
10715
- * 3. Last transaction's inclusionProof authenticator stateHash
10716
- * 4. Genesis inclusionProof authenticator stateHash (for never-transferred tokens)
10717
- */
10718
- declare function getCurrentStateHash(txf: TxfToken): string | undefined;
10719
- /**
10720
- * Check if token has valid TXF data
10721
- */
10722
- declare function hasValidTxfData(token: Token): boolean;
10723
- /**
10724
- * Check if token has uncommitted transactions
10725
- */
10726
- declare function hasUncommittedTransactions(token: Token): boolean;
10727
- /**
10728
- * Check if a TXF token has missing newStateHash on any transaction
10729
- */
10730
- declare function hasMissingNewStateHash(txf: TxfToken): boolean;
10731
- /**
10732
- * Count committed transactions in a token
10733
- */
10734
- declare function countCommittedTransactions(token: Token): number;
10735
10044
 
10736
10045
  /**
10737
10046
  * Token Validation Service — engine-based (v2).
@@ -11145,9 +10454,8 @@ declare function coinIdsMatch(a: string, b: string): boolean;
11145
10454
  /**
11146
10455
  * Standard address parsing, validation, and normalization for Unicity addresses.
11147
10456
  *
11148
- * Three address formats:
10457
+ * Two address formats:
11149
10458
  * - DIRECT:// — Resolved on-chain address (hex, 64-80 chars after prefix)
11150
- * - PROXY:// — Proxy address derived from nametag hash
11151
10459
  * - @nametag — Human-readable alias resolved via transport
11152
10460
  *
11153
10461
  * This module is the single source of truth for address handling.
@@ -11155,34 +10463,33 @@ declare function coinIdsMatch(a: string, b: string): boolean;
11155
10463
  *
11156
10464
  * @module
11157
10465
  */
11158
- /** The three address format types supported by Unicity. */
11159
- type AddressType = 'DIRECT' | 'PROXY' | 'NAMETAG';
10466
+ /** The address format types supported by Unicity. */
10467
+ type AddressType = 'DIRECT' | 'NAMETAG';
11160
10468
  /** A parsed address with its type and components. */
11161
10469
  interface ParsedAddress {
11162
10470
  /** Address format type */
11163
10471
  readonly type: AddressType;
11164
10472
  /** Original raw address string */
11165
10473
  readonly raw: string;
11166
- /** The value part after the prefix (hex for DIRECT/PROXY, name for NAMETAG) */
10474
+ /** The value part after the prefix (hex for DIRECT, name for NAMETAG) */
11167
10475
  readonly value: string;
11168
10476
  }
11169
10477
  /**
11170
10478
  * Parse a Unicity address string into its components.
11171
10479
  *
11172
- * @param address - A DIRECT://, PROXY://, or @nametag address string.
10480
+ * @param address - A DIRECT:// or @nametag address string.
11173
10481
  * @returns Parsed address or null if invalid/unrecognized format.
11174
10482
  *
11175
10483
  * @example
11176
10484
  * parseAddress('DIRECT://0000ab12...') → { type: 'DIRECT', raw: '...', value: '0000ab12...' }
11177
10485
  * parseAddress('@alice') → { type: 'NAMETAG', raw: '@alice', value: 'alice' }
11178
- * parseAddress('PROXY://abc123...') → { type: 'PROXY', raw: '...', value: 'abc123...' }
11179
10486
  * parseAddress('invalid') → null
11180
10487
  */
11181
10488
  declare function parseAddress(address: string): ParsedAddress | null;
11182
10489
  /**
11183
10490
  * Check if a string is a valid Unicity address (any format).
11184
10491
  *
11185
- * Accepts DIRECT://, PROXY://, or @nametag.
10492
+ * Accepts DIRECT:// or @nametag.
11186
10493
  */
11187
10494
  declare function isValidAddress(address: string): boolean;
11188
10495
  /**
@@ -11193,7 +10500,6 @@ declare function isValidDirectAddress(address: string): boolean;
11193
10500
  * Normalize an address for comparison.
11194
10501
  *
11195
10502
  * - DIRECT:// → lowercase hex
11196
- * - PROXY:// → lowercase hex
11197
10503
  * - @nametag → lowercase name
11198
10504
  *
11199
10505
  * Returns the original string if not a recognized format.
@@ -11208,4 +10514,4 @@ declare function normalizeAddress(address: string): string;
11208
10514
  */
11209
10515
  declare function addressesMatch(a: string, b: string): boolean;
11210
10516
 
11211
- export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressMode, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type ApplyDeltaAdded, type ApplyDeltaOptions, type ApplyDeltaRequest, type Asset, type BaseProvider, type BlobUrlEntry, type BroadcastHandler, type BroadcastMessage, type CMasterKeyData, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, type CoinBalance, CoinGeckoPriceProvider, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, type CreateInvoiceRequest, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_AGGREGATOR_URL, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, DEV_AGGREGATOR_URL, type DecryptionProgressCallback, type DeliverOptions, type DeliveryBlobKeys, type DeliveryCustody, type DeliveryDisposition, type DeliveryProvider, type DeliveryReceipt, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type ExtendedValidationResult, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, type GetInvoicesOptions, type GetSwapsFilter, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingDelivery, type IncomingMessage, type IncomingPaymentRequest, type IncomingTokenTransfer, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentRecord, type IntentStatus, type IntentType, type InvalidatedNametagEntry, type InventoryAsset, type InventoryItem, type InventoryPage, type InventoryView, type InvoiceRequestedAsset, type KeyValueStore, LIMITS, type LegacyFileImportOptions, type LegacyFileInfo, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LoadResult, type LogHandler, type LogLevel, type LoggerConfig, type ManifestAuxiliary, type ManifestFields, type ManifestSignatures, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, type MintOutboxEntry, NETWORKS, NIP29_KINDS, NOSTR_EVENT_KINDS, type NametagBindingProof, type NametagData, type NetworkHealthResult, type NetworkType, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type OutboxEntry, type OutgoingPaymentRequest, type ParsedAddress, type ParsedStorageData, PartialSendConflictError, type PayInvoiceParams, type PaymentRequest, type PaymentRequestHandler, type PaymentRequestResponse, type PaymentRequestResponseHandler, type PaymentRequestResponseType, type PaymentRequestResult, type PaymentRequestStatus, PaymentsModule, type PaymentsModuleConfig, type PaymentsModuleDependencies, type PaymentsWalletApiPort, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type ReceiveOptions, type ReceiveResult, type RecoverRemovedResult, type RegistryNetwork, type ReturnPaymentParams, SIGN_MESSAGE_PREFIX, STORAGE_KEYS, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SaveResult, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, type SpentTokenInfo, type SpentTokenResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type SphereWalletApiSession, type StorageEvent, type StorageEventCallback, type StorageEventType, type StorageProvider, type SwapDeal, type SwapManifest, SwapModule, type SwapModuleConfig, type SwapProgress, type SwapProposalResult, type SwapRef, type SwapRole, type SyncResult, TEST_AGGREGATOR_URL, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenStorageProvider, type TokenTransferDetail, type TokenTransferHandler, type TokenTransferPayload, type ValidationResult as TokenValidationResult, TokenValidator, type TombstoneEntry, type TrackedAddress, type TrackedAddressEntry, type TransactionHistoryEntry, type TransferMode, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type TxfAuthenticator, type TxfGenesis, type TxfGenesisData, type TxfInclusionProof, type TxfIntegrity, type TxfInvalidEntry, type TxfMerkleStep, type TxfMerkleTreePath, type TxfMeta$1 as TxfMeta, type TxfOutboxEntry, type TxfSentEntry, type TxfState, type TxfStorageData, type TxfStorageDataBase, type TxfToken, type TxfTombstone, type TxfTransaction, type UploadUrlEntry, type UploadUrlRequest, type ValidationAction, type ValidationIssue, type WakeCallback, type WakeEvent, type WakeSocketHandle, WalletApiClient, type WalletApiClientConfig, WalletApiError, type WalletApiErrorCode, type WalletApiIdentity, type WalletDatInfo, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, WholeBlobInventoryAdapter, type WholeBlobStore, addressesMatch, archivedKeyFromTokenId, assertFieldEnvelopeShape, base58Decode, base58Encode, buildManifest, buildTxfStorageData, bytesToHex, checkNetworkHealth, coinIdsMatch, composeDeliveryKeys, computeDeliveryId, computeSwapId, countCommittedTransactions, createAddress, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createNametagBinding, createPaymentsModule, createPriceProvider, createSphere, createSwapModule, createTokenValidator, decodeBech32, decrypt, decryptCMasterKey, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptPrivateKey, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encodeBech32, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, forkedKeyFromTokenIdAndState, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressHrp, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getCurrentStateHash, getPublicKey, getSphere, getTokenDecimals, getTokenDefinition, getTokenIconUrl, getTokenId, getTokenName, getTokenSymbol, hasMissingNewStateHash, hasUncommittedTransactions, hasValidTxfData, hash160, hashSignMessage, hexToBytes, identityFromMnemonicSync, initSphere, isArchivedKey, isForkedKey, isKnownToken, isPossiblyCommittedSendOutcome, isSQLiteDatabase, isSphereError, isTextWalletEncrypted, isTokenKey, isValidAddress, isValidBech32, isValidDirectAddress, isValidNametag, isValidPrivateKey, isValidTokenId, isWalletDatEncrypted, isWalletTextFormat, keyFromTokenId, loadSphere, logger, mnemonicToSeedSync, normalizeAddress, normalizeCoinId, normalizeSdkTokenToStorage, objectToTxf, parseAddress, parseAndDecryptWalletDat, parseAndDecryptWalletText, parseForkedKey, parseTokenAmount, parseTxfStorageData, parseWalletDat, parseWalletText, randomBytes, randomHex, randomUUID, recoverPubkeyFromSignature, ripemd160, safeParseTokenAmount, sha256, signMessage, signSwapManifest, sleep, sphereExists, toHumanReadable, tokenIdFromArchivedKey, tokenIdFromKey, tokenToTxf, txfToToken, validateManifest, validateMnemonic, verifyChallengeTemplate, verifyManifestIntegrity, verifyNametagBinding, verifySignedMessage, verifySwapSignature };
10517
+ export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressMode, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type ApplyDeltaAdded, type ApplyDeltaOptions, type ApplyDeltaRequest, type Asset, type BaseProvider, type BlobUrlEntry, type BroadcastHandler, type BroadcastMessage, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, type CoinBalance, CoinGeckoPriceProvider, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, type CreateInvoiceRequest, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_AGGREGATOR_URL, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, DEV_AGGREGATOR_URL, type DecryptionProgressCallback, type DeliverOptions, type DeliveryBlobKeys, type DeliveryCustody, type DeliveryDisposition, type DeliveryProvider, type DeliveryReceipt, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type ExtendedValidationResult, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, type GetInvoicesOptions, type GetSwapsFilter, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingDelivery, type IncomingMessage, type IncomingPaymentRequest, type IncomingTokenTransfer, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentRecord, type IntentStatus, type IntentType, type InventoryAsset, type InventoryItem, type InventoryPage, type InventoryView, type InvoiceRequestedAsset, type KeyValueStore, LIMITS, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LoadResult, type LogHandler, type LogLevel, type LoggerConfig, type ManifestAuxiliary, type ManifestFields, type ManifestSignatures, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, NETWORKS, NIP29_KINDS, NOSTR_EVENT_KINDS, type NametagBindingProof, type NametagData, type NetworkHealthResult, type NetworkType, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type OutgoingPaymentRequest, type ParsedAddress, type ParsedStorageData, PartialSendConflictError, type PayInvoiceParams, type PaymentRequest, type PaymentRequestHandler, type PaymentRequestResponse, type PaymentRequestResponseHandler, type PaymentRequestResponseType, type PaymentRequestResult, type PaymentRequestStatus, PaymentsModule, type PaymentsModuleConfig, type PaymentsModuleDependencies, type PaymentsWalletApiPort, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type ReceiveOptions, type ReceiveResult, type RecoverRemovedResult, type RegistryNetwork, type ReturnPaymentParams, SIGN_MESSAGE_PREFIX, STORAGE_KEYS, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SaveResult, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, type SpentTokenInfo, type SpentTokenResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type SphereWalletApiSession, type StorageEvent, type StorageEventCallback, type StorageEventType, type StorageProvider, type SwapDeal, type SwapManifest, SwapModule, type SwapModuleConfig, type SwapProgress, type SwapProposalResult, type SwapRef, type SwapRole, type SyncResult, TEST_AGGREGATOR_URL, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenStorageProvider, type TokenTransferDetail, type TokenTransferHandler, type TokenTransferPayload, type ValidationResult as TokenValidationResult, TokenValidator, type TombstoneEntry, type TrackedAddress, type TrackedAddressEntry, type TransactionHistoryEntry, type TransferMode, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type TxfAuthenticator, type TxfGenesis, type TxfGenesisData, type TxfInclusionProof, type TxfIntegrity, type TxfMerkleStep, type TxfMerkleTreePath, type TxfMeta$1 as TxfMeta, type TxfState, type TxfStorageData, type TxfStorageDataBase, type TxfToken, type TxfTombstone, type TxfTransaction, type UploadUrlEntry, type UploadUrlRequest, type ValidationAction, type ValidationIssue, type WakeCallback, type WakeEvent, type WakeSocketHandle, WalletApiClient, type WalletApiClientConfig, WalletApiError, type WalletApiErrorCode, type WalletApiIdentity, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, WholeBlobInventoryAdapter, type WholeBlobStore, addressesMatch, assertFieldEnvelopeShape, base58Decode, base58Encode, buildManifest, buildTxfStorageData, bytesToHex, checkNetworkHealth, coinIdsMatch, composeDeliveryKeys, computeDeliveryId, computeSwapId, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createNametagBinding, createPaymentsModule, createPriceProvider, createSphere, createSwapModule, createTokenValidator, decrypt, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getPublicKey, getSphere, getTokenDecimals, getTokenDefinition, getTokenIconUrl, getTokenName, getTokenSymbol, hash160, hashSignMessage, hexToBytes, identityFromMnemonicSync, initSphere, isKnownToken, isPossiblyCommittedSendOutcome, isSphereError, isTextWalletEncrypted, isTokenKey, isValidAddress, isValidDirectAddress, isValidNametag, isValidPrivateKey, isValidTokenId, isWalletTextFormat, keyFromTokenId, loadSphere, logger, mnemonicToSeedSync, normalizeAddress, normalizeCoinId, parseAddress, parseAndDecryptWalletText, parseTokenAmount, parseTxfStorageData, parseWalletText, randomBytes, randomHex, randomUUID, recoverPubkeyFromSignature, ripemd160, safeParseTokenAmount, sha256, signMessage, signSwapManifest, sleep, sphereExists, toHumanReadable, tokenIdFromKey, validateManifest, validateMnemonic, verifyChallengeTemplate, verifyManifestIntegrity, verifyNametagBinding, verifySignedMessage, verifySwapSignature };