@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.
@@ -101,6 +101,214 @@ interface SplitCheckpointStore {
101
101
  get(transferId: string, opIndex: number): Promise<Uint8Array | null>;
102
102
  }
103
103
 
104
+ /**
105
+ * transport/delivery-provider.ts — the `DeliveryProvider` port (sdk-changes S7,
106
+ * covenant §3.1-6).
107
+ *
108
+ * The seam that keeps the delivery rail swappable. In Unicity, a transfer —
109
+ * after certification — is just a file handoff, so the port is deliberately
110
+ * tiny: hand a finished token blob to a recipient, pull incoming deliveries,
111
+ * acknowledge them. `WalletApiMailboxProvider`
112
+ * (impl/shared/wallet-api/WalletApiMailboxProvider.ts) is the reference
113
+ * implementation; anything that can move a file can implement it (the port
114
+ * shape must not preclude the old Nostr transport or a future federated
115
+ * transport — neither is a deliverable here).
116
+ *
117
+ * Normative shapes (sdk-changes S7):
118
+ * - `DeliveryReceipt = { deliveryId }`
119
+ * - `IncomingDelivery = { deliveryId, transferId?, senderPubkey?, memo?,
120
+ * fetchBlob(), cursor }`
121
+ * - `deliveryId` is the **content-derived** entry id —
122
+ * `hex(SHA-256(tokenId bytes ‖ stateHash bytes))` — NEVER a server-assigned
123
+ * row id or seq (covenant §3.1-4; the contract suite asserts it). It is
124
+ * computed client-side ({@link computeDeliveryId}) and must equal the
125
+ * backend's `entry_id` (ARCHITECTURE §6).
126
+ * - **Custody is a composition-time property, not a per-call flag**:
127
+ * implementations take `custody: 'inventory' | 'external'` at construction
128
+ * and every ack sends the corresponding `intoInventory` — delivery-only
129
+ * safety must never depend on remembering an option at a call site.
130
+ * - Implementations MUST keep a **persistent `(tokenId, stateHash)` seen-set**
131
+ * for incoming deliveries: the recipient-side replay guard is part of the
132
+ * port contract, not a server promise (the recipient never trusts the
133
+ * backend — ARCHITECTURE §8.2). `deliveryId` is the canonical hash encoding
134
+ * of exactly that pair, so a persistent deliveryId set satisfies this.
135
+ */
136
+ /** Receipt for a delivered blob. `deliveryId` is content-derived — see module doc. */
137
+ interface DeliveryReceipt {
138
+ deliveryId: string;
139
+ }
140
+ /** Options for {@link DeliveryProvider.deliver}. */
141
+ interface DeliverOptions {
142
+ /**
143
+ * The send's transferId (the E.3 intent id / realization seed). Recorded
144
+ * with the delivery so the recipient can group multi-token payments and the
145
+ * backend can evidence-check the sender's removals (ARCHITECTURE §5.3/§6).
146
+ */
147
+ transferId: string;
148
+ /** Optional human memo. Implementations encrypt it client-side (S6). */
149
+ memo?: string;
150
+ /**
151
+ * The SENDER's own nametag (without a leading `@`), so the recipient can
152
+ * render the human identity instead of a raw pubkey ("Someone"). Bundled
153
+ * with the memo into ONE recipient-addressed (ECDH) `enc1.` envelope (S6) —
154
+ * the operator never sees it. Attached whenever the sender has a nametag OR
155
+ * a memo (so the nametag travels even on a memo-less transfer).
156
+ */
157
+ senderNametag?: string;
158
+ }
159
+ /** One incoming delivery pulled from the feed. */
160
+ interface IncomingDelivery {
161
+ /** Content-derived id — `hex(SHA-256(tokenId bytes ‖ stateHash bytes))`. */
162
+ deliveryId: string;
163
+ /** The sender's transferId, when the transport carries it. */
164
+ transferId?: string;
165
+ /** The sender's pubkey, when the transport carries it. */
166
+ senderPubkey?: string;
167
+ /** Decrypted memo (S6), when present and decryptable. */
168
+ memo?: string;
169
+ /**
170
+ * The sender's nametag (without a leading `@`), decrypted from the same
171
+ * recipient-addressed delivery envelope as {@link memo} (S6). Lets the
172
+ * receiver render the human identity instead of a raw pubkey, with no
173
+ * Nostr/transport lookup. Absent when the envelope carried none or could
174
+ * not be decrypted.
175
+ */
176
+ senderNametag?: string;
177
+ /** Fetch the finished token blob bytes (the encoded TokenBlob). */
178
+ fetchBlob(): Promise<Uint8Array>;
179
+ /** Transport-local resume cursor (opaque to callers). */
180
+ cursor: string;
181
+ }
182
+ type DeliveryDisposition = 'claimed' | 'rejected';
183
+ /**
184
+ * The §9 wake streams a backend may nudge: `mailbox` (incoming deliveries),
185
+ * `inventory` (owned-token set changed — e.g. a top-up or a claim on another
186
+ * device), and `payment_requests` (a request created/answered). A wake on any
187
+ * of these is a NUDGE — the consumer pulls that stream's cursor; correctness
188
+ * never depends on the wake arriving (the poll backstop is the source of
189
+ * truth).
190
+ */
191
+ type WakeStream = 'inventory' | 'mailbox' | 'payment_requests';
192
+ /**
193
+ * True liveness of the realtime wake channel (§9), decoupled from sign-in
194
+ * session state: `connecting`/`connected` — a socket is (being) established;
195
+ * `reconnecting` — it dropped and is backing off to re-establish (the poll
196
+ * backstop carries correctness meanwhile); `closed` — torn down intentionally.
197
+ * The wake is a nudge, so this is informational for the frontend (a "live"
198
+ * indicator) — never a correctness gate.
199
+ */
200
+ type WakeChannelStatus = 'connecting' | 'connected' | 'reconnecting' | 'closed';
201
+ /**
202
+ * Custody mode (composition-time): `'inventory'` — acknowledged deliveries
203
+ * enter the wallet-api inventory (the full wallet-api preset); `'external'` —
204
+ * the app's own storage keeps custody and acks perform ZERO inventory writes
205
+ * (the delivery-only preset, ARCHITECTURE §6 "delivery-only claim").
206
+ */
207
+ type DeliveryCustody = 'inventory' | 'external';
208
+ interface DeliveryProvider {
209
+ /** Composition-time custody property — never a per-call flag (S7). */
210
+ readonly custody: DeliveryCustody;
211
+ /**
212
+ * Bind the wallet identity (optional — implementations that authenticate or
213
+ * encrypt per-wallet need it; mirrors `TokenStorageProvider.setIdentity`).
214
+ */
215
+ setIdentity?(identity: {
216
+ privateKey: string;
217
+ chainPubkey: string;
218
+ }): void;
219
+ /**
220
+ * #583 per-address client isolation: mint an INDEPENDENT delivery provider for
221
+ * a different HD address, backed by its OWN authenticated client + wake socket
222
+ * (mirrors `TokenStorageProvider.createForAddress`). Implementations that hold
223
+ * a single mutable identity+session per instance (e.g. the wallet-api mailbox
224
+ * over one `WalletApiClient`) provide this so `Sphere.switchToAddress` can give
225
+ * each address its OWN delivery instance — an orphaned previous-address pump
226
+ * then re-auths as ITS OWN owner (harmless) instead of driving a client that
227
+ * was re-bound to the new owner. Stateless transports may omit it (the same
228
+ * instance serves every address).
229
+ */
230
+ createForAddress?(): DeliveryProvider;
231
+ /**
232
+ * Hand a finished token blob to a recipient. `recipientPubkey` is the
233
+ * recipient's CHAIN pubkey (33-byte compressed secp256k1, hex) — the
234
+ * canonical Unicity identity (ARCHITECTURE §4); transports that address
235
+ * recipients differently resolve it themselves.
236
+ *
237
+ * MUST be idempotent per (token, state): re-delivering the same finished
238
+ * blob — including after the recipient claimed — succeeds and returns the
239
+ * same content-derived `deliveryId` (ARCHITECTURE §6 deposit idempotency).
240
+ */
241
+ deliver(recipientPubkey: string, blob: Uint8Array, options: DeliverOptions): Promise<DeliveryReceipt>;
242
+ /**
243
+ * Pull-based feed of incoming deliveries since the given transport-local
244
+ * cursor (or the provider's persisted cursor when omitted). Yields only
245
+ * deliveries not yet in the persistent seen-set; completes when the feed is
246
+ * drained — callers re-invoke on poll/wake. Feeds the existing
247
+ * transport-agnostic `handleV2Transfer` (sdk-changes S3).
248
+ */
249
+ incoming(sinceCursor?: string): AsyncIterable<IncomingDelivery>;
250
+ /**
251
+ * Acknowledge a delivery: `'claimed'` accepts it (with the provider's
252
+ * composition-time custody), `'rejected'` marks it locally-unverifiable —
253
+ * terminal for discovery only (the entry stays claimable server-side and
254
+ * its blob is retained — ARCHITECTURE §6). Both record the delivery in the
255
+ * persistent seen-set.
256
+ */
257
+ ack(deliveryId: string, disposition: DeliveryDisposition): Promise<void>;
258
+ /**
259
+ * Optional batch acknowledge (#623): claim and reject whole pages of incoming deliveries in a
260
+ * single request each, instead of one per entry — so draining a large inbox (a long-offline or
261
+ * service wallet) doesn't fire thousands of writes and trip the per-owner rate limit. Same
262
+ * semantics as {@link ack}: the seen-set records only entries that were acked successfully, so a
263
+ * partial/failed batch is re-listed and re-processed (idempotent claim, §6). A provider that does
264
+ * not implement it (e.g. the relay no-op) is driven via per-entry {@link ack}.
265
+ */
266
+ ackBatch?(claimed: string[], rejected: string[]): Promise<void>;
267
+ /**
268
+ * Optional batch deliver (#699): hand N finished blobs to ONE recipient with a single deposit
269
+ * request (and one upload-urls request) instead of N — a multi-source send then costs O(1)
270
+ * against the backend's deposit rate limit regardless of fragmentation. Optional like
271
+ * {@link ackBatch}: the port must not preclude the relay transport or a future federated one,
272
+ * and neither has a batch primitive — callers probe and fall back to per-blob {@link deliver}.
273
+ *
274
+ * Semantically equivalent to awaiting {@link deliver} once per blob, in order:
275
+ * - receipts return in REQUEST order; each `deliveryId` is the content-derived entry id
276
+ * (covenant §3.1-4 — NEVER the batch endpoint's server-assigned seq);
277
+ * - idempotent per (token, state) exactly like {@link deliver};
278
+ * - `options` apply to every blob (one send = one transferId/memo/senderNametag);
279
+ * - throws when ANY blob could not be deposited — blobs that DID land are absorbed
280
+ * idempotently when the caller retries, batched or per-blob.
281
+ */
282
+ deliverBatch?(recipientPubkey: string, blobs: Uint8Array[], options: DeliverOptions): Promise<DeliveryReceipt[]>;
283
+ /**
284
+ * Optional wake hook: `callback` fires with the {@link WakeStream} that was
285
+ * nudged when new data may be available on it (e.g. a WS nudge — never a
286
+ * correctness dependency, ARCHITECTURE §9). The wallet-api wake socket
287
+ * multiplexes all three owner streams (`mailbox` | `inventory` |
288
+ * `payment_requests`); the consumer routes each to that stream's pull.
289
+ *
290
+ * The underlying socket SELF-HEALS (§9): it reconnects with backoff on any
291
+ * drop and a liveness watchdog force-reconnects a half-open socket. On every
292
+ * (re)connect the consumer MUST run a full catch-up pull of every stream —
293
+ * wakes missed while the socket was dead are not replayed — so `callback`
294
+ * fires once for EACH stream on (re)connect (a synthetic catch-up nudge).
295
+ * `onStatus` (optional) surfaces true socket liveness for the frontend,
296
+ * decoupled from sign-in state. Returns an unsubscribe function.
297
+ */
298
+ onWake?(callback: (stream: WakeStream) => void, onStatus?: (status: WakeChannelStatus) => void): () => void;
299
+ /**
300
+ * Late-bind the backend-true (tokenId, stateHash) derivation —
301
+ * `ITokenEngine.deliveryKeys`. Compositions are engine-less (the engine is
302
+ * built later); the module that owns both (PaymentsModule) binds this at
303
+ * init. Implementations that derive ids (S7) MUST use it and fail loudly if
304
+ * unbound; transports that don't derive may omit the method.
305
+ */
306
+ bindDeliveryKeys?(derive: (blobBytes: Uint8Array) => Promise<{
307
+ tokenId: string;
308
+ stateHash: string;
309
+ }>): void;
310
+ }
311
+
104
312
  /**
105
313
  * Transport Provider Interface
106
314
  * Platform-independent P2P messaging abstraction
@@ -452,214 +660,6 @@ interface IncomingTypingIndicator {
452
660
  type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
453
661
  type ComposingHandler = (indicator: ComposingIndicator) => void;
454
662
 
455
- /**
456
- * transport/delivery-provider.ts — the `DeliveryProvider` port (sdk-changes S7,
457
- * covenant §3.1-6).
458
- *
459
- * The seam that keeps the delivery rail swappable. In Unicity, a transfer —
460
- * after certification — is just a file handoff, so the port is deliberately
461
- * tiny: hand a finished token blob to a recipient, pull incoming deliveries,
462
- * acknowledge them. `WalletApiMailboxProvider`
463
- * (impl/shared/wallet-api/WalletApiMailboxProvider.ts) is the reference
464
- * implementation; anything that can move a file can implement it (the port
465
- * shape must not preclude the old Nostr transport or a future federated
466
- * transport — neither is a deliverable here).
467
- *
468
- * Normative shapes (sdk-changes S7):
469
- * - `DeliveryReceipt = { deliveryId }`
470
- * - `IncomingDelivery = { deliveryId, transferId?, senderPubkey?, memo?,
471
- * fetchBlob(), cursor }`
472
- * - `deliveryId` is the **content-derived** entry id —
473
- * `hex(SHA-256(tokenId bytes ‖ stateHash bytes))` — NEVER a server-assigned
474
- * row id or seq (covenant §3.1-4; the contract suite asserts it). It is
475
- * computed client-side ({@link computeDeliveryId}) and must equal the
476
- * backend's `entry_id` (ARCHITECTURE §6).
477
- * - **Custody is a composition-time property, not a per-call flag**:
478
- * implementations take `custody: 'inventory' | 'external'` at construction
479
- * and every ack sends the corresponding `intoInventory` — delivery-only
480
- * safety must never depend on remembering an option at a call site.
481
- * - Implementations MUST keep a **persistent `(tokenId, stateHash)` seen-set**
482
- * for incoming deliveries: the recipient-side replay guard is part of the
483
- * port contract, not a server promise (the recipient never trusts the
484
- * backend — ARCHITECTURE §8.2). `deliveryId` is the canonical hash encoding
485
- * of exactly that pair, so a persistent deliveryId set satisfies this.
486
- */
487
- /** Receipt for a delivered blob. `deliveryId` is content-derived — see module doc. */
488
- interface DeliveryReceipt {
489
- deliveryId: string;
490
- }
491
- /** Options for {@link DeliveryProvider.deliver}. */
492
- interface DeliverOptions {
493
- /**
494
- * The send's transferId (the E.3 intent id / realization seed). Recorded
495
- * with the delivery so the recipient can group multi-token payments and the
496
- * backend can evidence-check the sender's removals (ARCHITECTURE §5.3/§6).
497
- */
498
- transferId: string;
499
- /** Optional human memo. Implementations encrypt it client-side (S6). */
500
- memo?: string;
501
- /**
502
- * The SENDER's own nametag (without a leading `@`), so the recipient can
503
- * render the human identity instead of a raw pubkey ("Someone"). Bundled
504
- * with the memo into ONE recipient-addressed (ECDH) `enc1.` envelope (S6) —
505
- * the operator never sees it. Attached whenever the sender has a nametag OR
506
- * a memo (so the nametag travels even on a memo-less transfer).
507
- */
508
- senderNametag?: string;
509
- }
510
- /** One incoming delivery pulled from the feed. */
511
- interface IncomingDelivery {
512
- /** Content-derived id — `hex(SHA-256(tokenId bytes ‖ stateHash bytes))`. */
513
- deliveryId: string;
514
- /** The sender's transferId, when the transport carries it. */
515
- transferId?: string;
516
- /** The sender's pubkey, when the transport carries it. */
517
- senderPubkey?: string;
518
- /** Decrypted memo (S6), when present and decryptable. */
519
- memo?: string;
520
- /**
521
- * The sender's nametag (without a leading `@`), decrypted from the same
522
- * recipient-addressed delivery envelope as {@link memo} (S6). Lets the
523
- * receiver render the human identity instead of a raw pubkey, with no
524
- * Nostr/transport lookup. Absent when the envelope carried none or could
525
- * not be decrypted.
526
- */
527
- senderNametag?: string;
528
- /** Fetch the finished token blob bytes (the encoded TokenBlob). */
529
- fetchBlob(): Promise<Uint8Array>;
530
- /** Transport-local resume cursor (opaque to callers). */
531
- cursor: string;
532
- }
533
- type DeliveryDisposition = 'claimed' | 'rejected';
534
- /**
535
- * The §9 wake streams a backend may nudge: `mailbox` (incoming deliveries),
536
- * `inventory` (owned-token set changed — e.g. a top-up or a claim on another
537
- * device), and `payment_requests` (a request created/answered). A wake on any
538
- * of these is a NUDGE — the consumer pulls that stream's cursor; correctness
539
- * never depends on the wake arriving (the poll backstop is the source of
540
- * truth).
541
- */
542
- type WakeStream = 'inventory' | 'mailbox' | 'payment_requests';
543
- /**
544
- * True liveness of the realtime wake channel (§9), decoupled from sign-in
545
- * session state: `connecting`/`connected` — a socket is (being) established;
546
- * `reconnecting` — it dropped and is backing off to re-establish (the poll
547
- * backstop carries correctness meanwhile); `closed` — torn down intentionally.
548
- * The wake is a nudge, so this is informational for the frontend (a "live"
549
- * indicator) — never a correctness gate.
550
- */
551
- type WakeChannelStatus = 'connecting' | 'connected' | 'reconnecting' | 'closed';
552
- /**
553
- * Custody mode (composition-time): `'inventory'` — acknowledged deliveries
554
- * enter the wallet-api inventory (the full wallet-api preset); `'external'` —
555
- * the app's own storage keeps custody and acks perform ZERO inventory writes
556
- * (the delivery-only preset, ARCHITECTURE §6 "delivery-only claim").
557
- */
558
- type DeliveryCustody = 'inventory' | 'external';
559
- interface DeliveryProvider {
560
- /** Composition-time custody property — never a per-call flag (S7). */
561
- readonly custody: DeliveryCustody;
562
- /**
563
- * Bind the wallet identity (optional — implementations that authenticate or
564
- * encrypt per-wallet need it; mirrors `TokenStorageProvider.setIdentity`).
565
- */
566
- setIdentity?(identity: {
567
- privateKey: string;
568
- chainPubkey: string;
569
- }): void;
570
- /**
571
- * #583 per-address client isolation: mint an INDEPENDENT delivery provider for
572
- * a different HD address, backed by its OWN authenticated client + wake socket
573
- * (mirrors `TokenStorageProvider.createForAddress`). Implementations that hold
574
- * a single mutable identity+session per instance (e.g. the wallet-api mailbox
575
- * over one `WalletApiClient`) provide this so `Sphere.switchToAddress` can give
576
- * each address its OWN delivery instance — an orphaned previous-address pump
577
- * then re-auths as ITS OWN owner (harmless) instead of driving a client that
578
- * was re-bound to the new owner. Stateless transports may omit it (the same
579
- * instance serves every address).
580
- */
581
- createForAddress?(): DeliveryProvider;
582
- /**
583
- * Hand a finished token blob to a recipient. `recipientPubkey` is the
584
- * recipient's CHAIN pubkey (33-byte compressed secp256k1, hex) — the
585
- * canonical Unicity identity (ARCHITECTURE §4); transports that address
586
- * recipients differently resolve it themselves.
587
- *
588
- * MUST be idempotent per (token, state): re-delivering the same finished
589
- * blob — including after the recipient claimed — succeeds and returns the
590
- * same content-derived `deliveryId` (ARCHITECTURE §6 deposit idempotency).
591
- */
592
- deliver(recipientPubkey: string, blob: Uint8Array, options: DeliverOptions): Promise<DeliveryReceipt>;
593
- /**
594
- * Pull-based feed of incoming deliveries since the given transport-local
595
- * cursor (or the provider's persisted cursor when omitted). Yields only
596
- * deliveries not yet in the persistent seen-set; completes when the feed is
597
- * drained — callers re-invoke on poll/wake. Feeds the existing
598
- * transport-agnostic `handleV2Transfer` (sdk-changes S3).
599
- */
600
- incoming(sinceCursor?: string): AsyncIterable<IncomingDelivery>;
601
- /**
602
- * Acknowledge a delivery: `'claimed'` accepts it (with the provider's
603
- * composition-time custody), `'rejected'` marks it locally-unverifiable —
604
- * terminal for discovery only (the entry stays claimable server-side and
605
- * its blob is retained — ARCHITECTURE §6). Both record the delivery in the
606
- * persistent seen-set.
607
- */
608
- ack(deliveryId: string, disposition: DeliveryDisposition): Promise<void>;
609
- /**
610
- * Optional batch acknowledge (#623): claim and reject whole pages of incoming deliveries in a
611
- * single request each, instead of one per entry — so draining a large inbox (a long-offline or
612
- * service wallet) doesn't fire thousands of writes and trip the per-owner rate limit. Same
613
- * semantics as {@link ack}: the seen-set records only entries that were acked successfully, so a
614
- * partial/failed batch is re-listed and re-processed (idempotent claim, §6). A provider that does
615
- * not implement it (e.g. the relay no-op) is driven via per-entry {@link ack}.
616
- */
617
- ackBatch?(claimed: string[], rejected: string[]): Promise<void>;
618
- /**
619
- * Optional batch deliver (#699): hand N finished blobs to ONE recipient with a single deposit
620
- * request (and one upload-urls request) instead of N — a multi-source send then costs O(1)
621
- * against the backend's deposit rate limit regardless of fragmentation. Optional like
622
- * {@link ackBatch}: the port must not preclude the relay transport or a future federated one,
623
- * and neither has a batch primitive — callers probe and fall back to per-blob {@link deliver}.
624
- *
625
- * Semantically equivalent to awaiting {@link deliver} once per blob, in order:
626
- * - receipts return in REQUEST order; each `deliveryId` is the content-derived entry id
627
- * (covenant §3.1-4 — NEVER the batch endpoint's server-assigned seq);
628
- * - idempotent per (token, state) exactly like {@link deliver};
629
- * - `options` apply to every blob (one send = one transferId/memo/senderNametag);
630
- * - throws when ANY blob could not be deposited — blobs that DID land are absorbed
631
- * idempotently when the caller retries, batched or per-blob.
632
- */
633
- deliverBatch?(recipientPubkey: string, blobs: Uint8Array[], options: DeliverOptions): Promise<DeliveryReceipt[]>;
634
- /**
635
- * Optional wake hook: `callback` fires with the {@link WakeStream} that was
636
- * nudged when new data may be available on it (e.g. a WS nudge — never a
637
- * correctness dependency, ARCHITECTURE §9). The wallet-api wake socket
638
- * multiplexes all three owner streams (`mailbox` | `inventory` |
639
- * `payment_requests`); the consumer routes each to that stream's pull.
640
- *
641
- * The underlying socket SELF-HEALS (§9): it reconnects with backoff on any
642
- * drop and a liveness watchdog force-reconnects a half-open socket. On every
643
- * (re)connect the consumer MUST run a full catch-up pull of every stream —
644
- * wakes missed while the socket was dead are not replayed — so `callback`
645
- * fires once for EACH stream on (re)connect (a synthetic catch-up nudge).
646
- * `onStatus` (optional) surfaces true socket liveness for the frontend,
647
- * decoupled from sign-in state. Returns an unsubscribe function.
648
- */
649
- onWake?(callback: (stream: WakeStream) => void, onStatus?: (status: WakeChannelStatus) => void): () => void;
650
- /**
651
- * Late-bind the backend-true (tokenId, stateHash) derivation —
652
- * `ITokenEngine.deliveryKeys`. Compositions are engine-less (the engine is
653
- * built later); the module that owns both (PaymentsModule) binds this at
654
- * init. Implementations that derive ids (S7) MUST use it and fail loudly if
655
- * unbound; transports that don't derive may omit the method.
656
- */
657
- bindDeliveryKeys?(derive: (blobBytes: Uint8Array) => Promise<{
658
- tokenId: string;
659
- stateHash: string;
660
- }>): void;
661
- }
662
-
663
663
  /**
664
664
  * SDK2 Core Types
665
665
  * Platform-independent type definitions
@@ -1042,9 +1042,6 @@ interface TokenStorageProvider<TData = unknown> extends BaseProvider {
1042
1042
  interface TxfStorageDataBase {
1043
1043
  _meta: TxfMeta;
1044
1044
  _tombstones?: TxfTombstone[];
1045
- _outbox?: TxfOutboxEntry[];
1046
- _sent?: TxfSentEntry[];
1047
- _invalid?: TxfInvalidEntry[];
1048
1045
  _history?: HistoryRecord[];
1049
1046
  [key: `_${string}`]: unknown;
1050
1047
  }
@@ -1060,25 +1057,6 @@ interface TxfTombstone {
1060
1057
  stateHash: string;
1061
1058
  timestamp: number;
1062
1059
  }
1063
- interface TxfOutboxEntry {
1064
- id: string;
1065
- status: string;
1066
- tokenId: string;
1067
- recipient: string;
1068
- createdAt: number;
1069
- data: unknown;
1070
- }
1071
- interface TxfSentEntry {
1072
- tokenId: string;
1073
- recipient: string;
1074
- txHash: string;
1075
- sentAt: number;
1076
- }
1077
- interface TxfInvalidEntry {
1078
- tokenId: string;
1079
- reason: string;
1080
- detectedAt: number;
1081
- }
1082
1060
 
1083
1061
  /**
1084
1062
  * wallet-api/types.ts — sphere-domain types for the wallet-api client (S1).