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