@qntx/spark 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,820 @@
1
+ import { i as SparkOperatorConfig, n as SparkNetwork, o as Signature, r as SparkNetworkConfig } from "./lightning-address-CRULmi9v.mjs";
2
+ import { g as SparkSigner } from "./types-jBCznYd6.mjs";
3
+ import "@bufbuild/protobuf/codegenv2";
4
+ import "@bufbuild/protobuf/wkt";
5
+ import { Message, UnknownEnum } from "@bufbuild/protobuf";
6
+ import "@connectrpc/connect";
7
+ import "@scure/btc-signer/utils.js";
8
+ //#region src/connection/index.d.ts
9
+ /**
10
+ * A Spark protocol event delivered by the coordinator's `subscribe_to_events` stream. Plain types;
11
+ * unknown oneof variants are skipped.
12
+ */
13
+ type SparkEvent = {
14
+ readonly type: "connected";
15
+ } | {
16
+ readonly type: "heartbeat";
17
+ } | {
18
+ readonly type: "transfer";
19
+ readonly direction: "incoming" | "outgoing";
20
+ readonly transferId: string;
21
+ readonly senderIdentityPublicKey: Uint8Array;
22
+ readonly receiverIdentityPublicKey: Uint8Array;
23
+ } | {
24
+ readonly type: "deposit";
25
+ readonly leafId: string;
26
+ } | {
27
+ readonly type: "token-transaction";
28
+ readonly transactionHash: Uint8Array;
29
+ readonly tokenIdentifiers: ReadonlyArray<Uint8Array>;
30
+ };
31
+ //#endregion
32
+ //#region src/tree/index.d.ts
33
+ type SparkLeaf = {
34
+ readonly id: string;
35
+ readonly treeId: string;
36
+ readonly valueSats: number;
37
+ readonly status: string;
38
+ readonly nodeTx: Uint8Array;
39
+ readonly refundTx: Uint8Array;
40
+ readonly directTx?: Uint8Array;
41
+ readonly directRefundTx?: Uint8Array;
42
+ readonly directFromCpfpRefundTx?: Uint8Array;
43
+ readonly verifyingPublicKey: Uint8Array;
44
+ readonly ownerIdentityPublicKey: Uint8Array;
45
+ readonly ownerSigningPublicKey: Uint8Array;
46
+ readonly signingKeyshare: {
47
+ readonly ownerIdentifiers: ReadonlyArray<string>;
48
+ readonly threshold: number;
49
+ readonly publicKey: Uint8Array;
50
+ };
51
+ readonly vout: number;
52
+ readonly parentNodeId?: string;
53
+ };
54
+ //#endregion
55
+ //#region src/deposit/index.d.ts
56
+ type UnusedDepositAddress = {
57
+ readonly address: string;
58
+ readonly leafId: string;
59
+ readonly verifyingPublicKey: Uint8Array;
60
+ };
61
+ //#endregion
62
+ //#region src/ssp/types.d.ts
63
+ /** Speed tier accepted by `request_coop_exit` (upstream `ExitSpeed`). */
64
+ type SspCoopExitSpeed = "FAST" | "MEDIUM" | "SLOW";
65
+ type SspCoopExitFeeQuote = {
66
+ readonly id: string;
67
+ readonly expiresAtMs: number;
68
+ /** `user_fee + l1_broadcast_fee` per speed, in sats. */
69
+ readonly fees: {
70
+ readonly fast: number;
71
+ readonly medium: number;
72
+ readonly slow: number;
73
+ };
74
+ };
75
+ type SspCoopExitStatus = {
76
+ readonly id: string;
77
+ readonly status: string;
78
+ readonly transferId?: string;
79
+ /** The SSP-built payout transaction, when the request record carries it. */
80
+ readonly rawCoopExitTransaction?: Uint8Array;
81
+ };
82
+ //#endregion
83
+ //#region src/deposit/static.d.ts
84
+ /** Upstream's minimum spend-tx fee (spark-wallet.ts MIN_SPEND_TX_FEE_SATS). */
85
+ declare const MIN_STATIC_REFUND_FEE_SATS = 194;
86
+ type StaticDepositUtxo = {
87
+ /** Display-order hex txid. */
88
+ readonly txid: string;
89
+ readonly vout: number;
90
+ /** Amount from the SO's `raw_tx`; absent when the SO does not return it. */
91
+ readonly amountSats?: number;
92
+ /** The deposit transaction when the SO returns it. */
93
+ readonly rawTx?: Uint8Array;
94
+ };
95
+ type StaticDepositClaim = {
96
+ readonly creditAmountSats: number;
97
+ /** `utxo amount − creditAmountSats`. */
98
+ readonly feeSats: number;
99
+ /** The SSP's inbound transfer id, when the claim response carries one. */
100
+ readonly transferId?: string;
101
+ };
102
+ type StaticDepositRefund = {
103
+ /** The signed refund transaction (not broadcast — broadcasting is the caller's job). */
104
+ readonly transaction: Uint8Array;
105
+ /** Display-order txid of the signed transaction. */
106
+ readonly txid: string;
107
+ };
108
+ //#endregion
109
+ //#region src/exit/coop.d.ts
110
+ type CooperativeExitResult = {
111
+ /** The cooperative-exit transfer id — the idempotency handle for retries. */
112
+ readonly transferId: string;
113
+ /** The SSP exit request id — pass to `cooperativeExitStatus`. */
114
+ readonly requestId: string;
115
+ readonly coopExitTxid: string;
116
+ readonly payoutSats: number;
117
+ readonly feeSats: number;
118
+ readonly status: string;
119
+ };
120
+ /** `FAST` | `MEDIUM` | `SLOW` — the SSP's broadcast-speed tiers. */
121
+ type CooperativeExitSpeed = SspCoopExitSpeed;
122
+ type CooperativeExitQuote = SspCoopExitFeeQuote;
123
+ type CooperativeExitStatus = SspCoopExitStatus;
124
+ //#endregion
125
+ //#region src/exit/store.d.ts
126
+ /**
127
+ * Every pre-signed transaction needed to exit one leaf unilaterally. The `directTx`,
128
+ * `directRefundTx` and `directFromCpfpRefundTx` fields are witness-stripped templates — the SO's
129
+ * DirectTransactionResponseInterceptor drops the witness from every `direct_*` transaction field it
130
+ * serves. Their txids still match the signed copies, so they can recognise the watchtower's
131
+ * broadcast on chain and feed `sweepRefund`, but the wallet can never broadcast them: the
132
+ * signatures exist only server-side.
133
+ */
134
+ type SparkExitChain = {
135
+ readonly leafId: string;
136
+ /** Root → leaf. */
137
+ readonly nodes: ReadonlyArray<{
138
+ readonly nodeId: string;
139
+ readonly nodeTx: Uint8Array;
140
+ readonly directTx?: Uint8Array;
141
+ }>;
142
+ readonly refundTx: Uint8Array;
143
+ readonly directRefundTx?: Uint8Array;
144
+ readonly directFromCpfpRefundTx?: Uint8Array;
145
+ };
146
+ type SparkStore = {
147
+ readonly exitChains: () => Promise<ReadonlyArray<SparkExitChain>>;
148
+ /** Upsert by leafId. */
149
+ readonly putExitChains: (chains: ReadonlyArray<SparkExitChain>) => Promise<void>;
150
+ readonly deleteExitChains: (leafIds: ReadonlyArray<string>) => Promise<void>;
151
+ };
152
+ /**
153
+ * In-memory `SparkStore` — the default when no persistence is injected. Byte arrays are copied on
154
+ * write and on read so callers can never alias stored state.
155
+ */
156
+ declare function createMemorySparkStore(): SparkStore;
157
+ //#endregion
158
+ //#region src/exit/unilateral.d.ts
159
+ /**
160
+ * A pre-signed exit transaction plus the context needed to broadcast it. Broadcasting is
161
+ * deadline-bound: once `parentTxid` confirms and `relativeTimelock` blocks pass, this must confirm
162
+ * within DIRECT_TIMELOCK_OFFSET blocks or the SO watchtower replaces it with the direct variant
163
+ * (see the module doc).
164
+ */
165
+ type ExitTransaction = {
166
+ /** The tree node this transaction belongs to (the leaf's id for refunds). */
167
+ readonly nodeId: string;
168
+ readonly kind: "node" | "refund";
169
+ /** Zero-fee v3 transaction with a P2A anchor output. */
170
+ readonly transaction: Uint8Array;
171
+ /** Display-order txid. */
172
+ readonly txid: string;
173
+ /** Display-order txid spent by input 0 (the deposit tx for a root node tx). */
174
+ readonly parentTxid: string;
175
+ /** BIP-68 blocks the input must wait after its parent confirms. */
176
+ readonly relativeTimelock: number;
177
+ };
178
+ /**
179
+ * Flattens stored chains into broadcast order: for each leaf's chain root→leaf, ancestor node txs
180
+ * deduplicated by node id at first use, then that leaf's refund right after its leaf node tx.
181
+ * Broadcast strictly in this order — each transaction's deadline is its parent's confirmation
182
+ * height plus its own relative timelock plus DIRECT_TIMELOCK_OFFSET, so a stalled package endangers
183
+ * every transaction below it.
184
+ */
185
+ declare function exitTransactions(chains: ReadonlyArray<SparkExitChain>): ExitTransaction[];
186
+ //#endregion
187
+ //#region src/exit/watchtower.d.ts
188
+ type WatchtowerExitedLeaf = {
189
+ readonly leafId: string;
190
+ readonly status: "WATCHTOWER_EXITED" | "WATCHTOWER_EXIT_RECOVERED";
191
+ readonly valueSats: number;
192
+ /** The confirmed ancestor output the leaf can still spend, when one resolves locally. */
193
+ readonly recovery?: {
194
+ readonly txid: string;
195
+ readonly outputIndex: number;
196
+ readonly valueSats: number;
197
+ };
198
+ };
199
+ //#endregion
200
+ //#region src/lightning/receive.d.ts
201
+ type LightningInvoice = {
202
+ /** The SSP lightning receive request id — pass to `lightningReceiveStatus`. */
203
+ readonly id: string;
204
+ /** The encoded BOLT-11 invoice to hand to the payer. */
205
+ readonly invoice: string;
206
+ readonly paymentHash: Uint8Array;
207
+ readonly amountSats: number;
208
+ readonly expiresAtMs: number;
209
+ };
210
+ //#endregion
211
+ //#region src/lightning/send.d.ts
212
+ type LightningPayment = {
213
+ /** The preimage-swap transfer id — the idempotency handle for retries. */
214
+ readonly transferId: string;
215
+ /** The SSP lightning send request id — pass to `lightningSendStatus`. */
216
+ readonly requestId: string;
217
+ readonly status: string;
218
+ readonly paymentHash: Uint8Array;
219
+ readonly amountSats: number;
220
+ readonly feeSats: number;
221
+ };
222
+ //#endregion
223
+ //#region src/lightning/status.d.ts
224
+ /** Coarse outcome of a lightning send, derived from the SSP status and the verified preimage. */
225
+ type LightningSendOutcome = "pending" | "succeeded" | "failed" | "returned";
226
+ type LightningSendStatus = {
227
+ readonly status: string;
228
+ /**
229
+ * "succeeded" once a verified preimage is present; "returned" once the SSP reports
230
+ * `USER_SWAP_RETURNED` — the leaves reappear in `leaves()` on the next sync. "failed" means the
231
+ * payment will not settle but the swap return has not finished — keep polling until "returned".
232
+ * Everything else is "pending".
233
+ */
234
+ readonly outcome: LightningSendOutcome;
235
+ /** The settled payment preimage — present once the SSP reports the send paid. */
236
+ readonly preimage?: Uint8Array;
237
+ };
238
+ type LightningReceiveStatus = {
239
+ readonly status: string;
240
+ /** The inbound transfer's spark id, once the SSP reports the payment arrived. */
241
+ readonly transferId?: string;
242
+ /** The settled payment preimage — verified against the request invoice's payment hash. */
243
+ readonly preimage?: Uint8Array;
244
+ };
245
+ /** A `LightningPayment` satisfies this shape — pass the pay() result straight in. */
246
+ type LightningSendStatusRequest = {
247
+ readonly requestId: string;
248
+ /** The payment hash of the invoice we paid — the proof target, not SSP-supplied data. */
249
+ readonly paymentHash: Uint8Array;
250
+ };
251
+ /** A `LightningInvoice` satisfies this shape — pass the createInvoice result straight in. */
252
+ type LightningReceiveStatusRequest = {
253
+ readonly requestId: string;
254
+ /** The payment hash the invoice was created for — the proof target, not SSP-supplied data. */
255
+ readonly paymentHash: Uint8Array;
256
+ };
257
+ //#endregion
258
+ //#region src/settings/index.d.ts
259
+ type SparkWalletSettings = {
260
+ /**
261
+ * When true, only the owner's (or master's) session may read this wallet's nodes and transfers.
262
+ * Other identities get no error — their queries simply come back empty (observed on hosted).
263
+ */
264
+ readonly privateEnabled: boolean;
265
+ };
266
+ //#endregion
267
+ //#region src/tokens/model.d.ts
268
+ /**
269
+ * Mapped `query_token_outputs` status. `"unknown"` marks an enum value this SDK does not recognize
270
+ * — it must never be spendable; an unset status field stays absent instead.
271
+ */
272
+ type SparkTokenOutputStatus = "available" | "pending-outbound" | "unknown";
273
+ /** One owned token output, keyed by its previous transaction location. */
274
+ type SparkTokenOutput = {
275
+ readonly id: string;
276
+ /** Raw 32-byte token identifier (bech32m-encode for display). */
277
+ readonly tokenIdentifier: Uint8Array;
278
+ /** Decoded 128-bit amount. */
279
+ readonly amount: bigint;
280
+ readonly prevTransactionHash: Uint8Array;
281
+ readonly prevTransactionVout: number;
282
+ readonly ownerPublicKey: Uint8Array;
283
+ readonly status?: SparkTokenOutputStatus;
284
+ };
285
+ /** Aggregate balance for one token identifier, display-ready. */
286
+ type SparkTokenBalance = {
287
+ /** Bech32m `btkn`/`btknrt` token identifier. */
288
+ readonly tokenIdentifier: string;
289
+ readonly amount: bigint;
290
+ readonly outputCount: number;
291
+ };
292
+ //#endregion
293
+ //#region src/transfer/model.d.ts
294
+ type SparkTransferLeaf = {
295
+ readonly leaf: SparkLeaf;
296
+ /** ECIES(receiver identity) ciphertext sealing the leaf key the sender generated. */
297
+ readonly secretCipher: Uint8Array;
298
+ /** Sender's per-leaf authorization: legacy bare signature or scheme-tagged `common.Signature`. */
299
+ readonly sig: {
300
+ readonly case: "signature";
301
+ readonly value: Uint8Array;
302
+ } | {
303
+ readonly case: "typedSignature";
304
+ readonly value: Signature;
305
+ } | undefined;
306
+ /** Receiver-edge id that owns this leaf on multi-receiver transfers ("" when unset). */
307
+ readonly transferReceiverId: string;
308
+ /** Receiver-side refund txs captured at send time; they are the leaf's current refund state. */
309
+ readonly intermediateRefundTx: Uint8Array;
310
+ readonly intermediateDirectRefundTx: Uint8Array;
311
+ readonly intermediateDirectFromCpfpRefundTx: Uint8Array;
312
+ };
313
+ type SparkTransferReceiver = {
314
+ readonly id: string;
315
+ readonly identityPublicKey: Uint8Array;
316
+ /** Sats this receiver edge carries (0 on single-receiver transfers that leave it unset). */
317
+ readonly amountSats: number;
318
+ readonly status: string;
319
+ };
320
+ type SparkTransfer = {
321
+ readonly id: string;
322
+ readonly senderIdentityPublicKey: Uint8Array;
323
+ readonly receiverIdentityPublicKey: Uint8Array;
324
+ readonly receivers: ReadonlyArray<SparkTransferReceiver>;
325
+ readonly status: string;
326
+ readonly type: string;
327
+ readonly network: SparkNetwork;
328
+ readonly totalValueSats: number;
329
+ readonly expiryTimeMs?: number;
330
+ readonly createdTimeMs?: number;
331
+ readonly updatedTimeMs?: number;
332
+ readonly sparkInvoice?: string;
333
+ readonly leaves: ReadonlyArray<SparkTransferLeaf>;
334
+ };
335
+ //#endregion
336
+ //#region src/core/bitcoin/cpfp.d.ts
337
+ type FundingInput = {
338
+ /** Display-order hex txid of the confirmed funding output. */
339
+ readonly txid: string;
340
+ readonly vout: number;
341
+ /** Witness program scriptPubKey (P2WPKH, P2TR, …). */
342
+ readonly script: Uint8Array;
343
+ readonly amountSats: number;
344
+ /** Caller's upper bound for this input once signed (68 vB P2WPKH, 58 vB P2TR). */
345
+ readonly signedInputVbytes: number;
346
+ };
347
+ /**
348
+ * Builds the unsigned fee-paying child for a zero-fee v3 parent: inputs are the caller's confirmed
349
+ * funding UTXOs (kept in the given order — a TRUC child may have only one unconfirmed ancestor, so
350
+ * funding must be confirmed) followed by the parent's P2A anchor carrying only its `witness_utxo`.
351
+ * Signing software finalizes the anyone-can-spend anchor with an empty witness (Bitcoin Core's
352
+ * `walletprocesspsbt`/`finalizepsbt` does), so only the funding inputs need signatures. Returns the
353
+ * PSBT, the package fee (covering parent + child at `feeRateSatPerVbyte`), and the estimated child
354
+ * vsize.
355
+ */
356
+ declare function buildCpfpChild(options: {
357
+ readonly parent: Uint8Array;
358
+ readonly funding: ReadonlyArray<FundingInput>;
359
+ readonly changeScript: Uint8Array;
360
+ /** Fee rate in sats per virtual byte; no upper cap is enforced — the caller picks the value. */
361
+ readonly feeRateSatPerVbyte: number;
362
+ }): {
363
+ readonly psbt: Uint8Array;
364
+ readonly feeSats: number;
365
+ readonly vsize: number;
366
+ };
367
+ //#endregion
368
+ //#region src/client/deposits.d.ts
369
+ /** `claim_static_deposit` plus the leaves its inbound transfer credited. */
370
+ type StaticDepositClaimResult = StaticDepositClaim & {
371
+ readonly leaves: ReadonlyArray<SparkLeaf>;
372
+ };
373
+ //#endregion
374
+ //#region src/client/optimize.d.ts
375
+ type OptimizeLeavesOptions = {
376
+ /**
377
+ * 0 consolidates dust into the fewest leaves (cheapest unilateral exit); 1–5 keeps every
378
+ * power-of-two denomination that many times so sends can pay from exact leaves without a swap.
379
+ */
380
+ readonly multiplicity?: number;
381
+ /** Soft bound on swap inputs per round — well under the SO's 1000-leaf transfer limit. */
382
+ readonly maxLeavesPerSwap?: number;
383
+ /** Checked between swaps; an in-flight swap completes first. */
384
+ readonly signal?: AbortSignal;
385
+ };
386
+ type OptimizeLeavesResult = {
387
+ /** Swaps actually executed. */
388
+ readonly swaps: number;
389
+ readonly leavesBefore: number;
390
+ readonly leavesAfter: number;
391
+ };
392
+ //#endregion
393
+ //#region src/client/index.d.ts
394
+ /**
395
+ * `transfers.claimPending` result: the leaves claimed this round plus one entry per transfer whose
396
+ * claim failed. Transfers in non-claimable statuses are skipped, not failures.
397
+ */
398
+ type ClaimPendingResult = {
399
+ readonly leaves: ReadonlyArray<SparkLeaf>;
400
+ readonly failures: ReadonlyArray<{
401
+ readonly transferId: string;
402
+ readonly error: unknown;
403
+ }>;
404
+ };
405
+ type SparkClient = {
406
+ /** The 33-byte compressed secp256k1 identity public key. */
407
+ readonly identityPublicKey: () => Promise<Uint8Array>;
408
+ /** Sum of the owner's `AVAILABLE` leaf values, in sats. */
409
+ readonly balance: () => Promise<number>;
410
+ /** The owner's `AVAILABLE` leaves from the coordinator's `query_nodes`. */
411
+ readonly leaves: () => Promise<ReadonlyArray<SparkLeaf>>;
412
+ /**
413
+ * Reshapes leaf denominations through zero-fee SSP swaps (upstream `optimizeLeaves`): with
414
+ * `multiplicity` 1–5 (default 1) each power of two is kept up to that many times so sends can pay
415
+ * from exact leaves without a swap; `multiplicity` 0 consolidates into the fewest leaves
416
+ * (cheapest unilateral exit). Swaps run one at a time under the leaf lock — a concurrent spend
417
+ * sees a consistent leaf set between rounds. The wallet decides when to call this (e.g. after
418
+ * claims); nothing schedules it. Returns the executed swap count and leaf counts before/after.
419
+ *
420
+ * Swap fee note: the SSP response carries no fee before the inbound counter transfer is claimed,
421
+ * and the primary transfer is already committed by then — claiming anyway is the only safe move,
422
+ * so a non-zero SSP swap fee is detected only after the claim. Funds are never stranded or lost:
423
+ * the thrown error states the leaves are already ours.
424
+ */
425
+ readonly optimizeLeaves: (optimizeOptions?: OptimizeLeavesOptions) => Promise<OptimizeLeavesResult>;
426
+ readonly transfers: {
427
+ /** Transfers awaiting this identity as receiver. */
428
+ readonly pending: () => Promise<ReadonlyArray<SparkTransfer>>;
429
+ /** All transfers where the identity is sender or receiver. */
430
+ readonly list: (options?: {
431
+ readonly limit?: number;
432
+ readonly offset?: number;
433
+ }) => Promise<ReadonlyArray<SparkTransfer>>;
434
+ /**
435
+ * Sends exactly `amountSats` to `receiver` (a `spark1…`/`sparkrt1…` address string or a 33-byte
436
+ * identity public key) via `start_transfer_v2` — selecting exact leaves, or swapping with the
437
+ * SSP first when no exact combination exists. Pass the same `transferId` to retry a call whose
438
+ * response was lost.
439
+ *
440
+ * Once the transfer commits (sender key tweaked) it stays claimable indefinitely: the sender
441
+ * cannot cancel it and its expiry does not return it — the pre-claim refund already pays the
442
+ * receiver's identity key.
443
+ *
444
+ * Leaf selection through the commit runs under the wallet's leaf lock, across leaf renewal and
445
+ * the signing-operator calls — the lock's hold time grows with the number of stale leaves
446
+ * renewed and each remote round trip (bounded by the RPC timeouts).
447
+ */
448
+ readonly send: (sendOptions: {
449
+ readonly receiver: string | Uint8Array;
450
+ readonly amountSats: number;
451
+ readonly transferId?: string;
452
+ }) => Promise<SparkTransfer>;
453
+ /**
454
+ * Sends to several receivers in one `start_transfer_v3` — one exact leaf group per entry, or a
455
+ * single SSP swap minting every amount. `receiver` accepts the same shapes as `send` (invoice
456
+ * addresses are rejected); duplicate receivers are rejected. `transferId` has the same retry
457
+ * semantics as `send`. Committed transfers share `send`'s claimability: no sender cancel, no
458
+ * expiry return.
459
+ */
460
+ readonly sendMany: (sendOptions: {
461
+ readonly receivers: ReadonlyArray<{
462
+ readonly receiver: string | Uint8Array;
463
+ readonly amountSats: number;
464
+ }>;
465
+ readonly transferId?: string;
466
+ }) => Promise<SparkTransfer>;
467
+ /** Verifies and claims a pending transfer addressed to this identity; returns the new leaves. */
468
+ readonly claim: (transfer: SparkTransfer) => Promise<ReadonlyArray<SparkLeaf>>;
469
+ /**
470
+ * Claims every pending incoming transfer; returns the new leaves plus one failure entry per
471
+ * transfer that could not be claimed — a single poisoned transfer does not abort the rest. A
472
+ * committed transfer stays claimable indefinitely — the sender cannot cancel it and its expiry
473
+ * does not return it, so a receiver may stay offline across the sender's expiry and claim
474
+ * later.
475
+ */
476
+ readonly claimPending: () => Promise<ClaimPendingResult>;
477
+ };
478
+ readonly tokens: {
479
+ /** Token outputs owned by this identity, optionally narrowed to one bech32m identifier. */
480
+ readonly outputs: (options?: {
481
+ readonly tokenIdentifier?: string;
482
+ }) => Promise<ReadonlyArray<SparkTokenOutput>>;
483
+ /** Per-identifier aggregate balances. */
484
+ readonly balances: () => Promise<ReadonlyArray<SparkTokenBalance>>;
485
+ /**
486
+ * Sends exactly `amount` of the bech32m token to `receiver` (a spark address string or a
487
+ * 33-byte identity public key) via `broadcast_transaction`; returns the hex final transaction
488
+ * hash. Change returns to the sender.
489
+ *
490
+ * A lost broadcast response is recovered automatically: the identical partial re-broadcasts
491
+ * once (the SO dedups by partial hash), then the committed transaction is probed by the spent
492
+ * input ids. If that cannot resolve the outcome the call throws `SparkTokenBroadcastError`
493
+ * carrying the spent `inputOutputIds` — retry with `inputOutputIds: error.inputOutputIds` and
494
+ * the same receiver and amount; that retry either returns the committed transaction's hash or
495
+ * broadcasts exactly those inputs once. Retrying without them would select different outputs
496
+ * and pay twice.
497
+ */
498
+ readonly transfer: (transferOptions: {
499
+ readonly tokenIdentifier: string;
500
+ readonly amount: bigint;
501
+ readonly receiver: string | Uint8Array;
502
+ /** Output ids from a `SparkTokenBroadcastError`, to retry the same transaction safely. */
503
+ readonly inputOutputIds?: ReadonlyArray<string>;
504
+ }) => Promise<string>;
505
+ /**
506
+ * Merges this identity's available outputs for `tokenIdentifier` into a single self-owned
507
+ * output (upstream `optimizeTokenOutputs`): smallest-first, at most 500 inputs per transaction,
508
+ * on demand — no change output is created. Returns `undefined` when fewer than two available
509
+ * outputs exist; call again to keep merging when more than 500 were owned.
510
+ *
511
+ * Shares `transfer`'s lost-response recovery: on `SparkTokenBroadcastError`, retry with
512
+ * `inputOutputIds: error.inputOutputIds` — at least two, as the failed call's inputs were.
513
+ */
514
+ readonly consolidate: (options: {
515
+ readonly tokenIdentifier: string;
516
+ /** Output ids from a `SparkTokenBroadcastError`, to retry the same transaction safely. */
517
+ readonly inputOutputIds?: ReadonlyArray<string>;
518
+ }) => Promise<{
519
+ readonly transactionHash: string;
520
+ } | undefined>;
521
+ };
522
+ readonly invoices: {
523
+ /**
524
+ * Creates a signed sats invoice address for this identity. `amountSats` omitted means the payer
525
+ * picks the amount.
526
+ */
527
+ readonly createSats: (options?: {
528
+ readonly amountSats?: number;
529
+ readonly memo?: string;
530
+ readonly senderPublicKey?: Uint8Array;
531
+ readonly expiresAtMs?: number;
532
+ }) => Promise<string>;
533
+ /**
534
+ * Creates a signed token invoice address for this identity. `tokenIdentifier` is the bech32m
535
+ * identifier; omit it (with `amount`) for any-token invoices.
536
+ */
537
+ readonly createTokens: (options?: {
538
+ readonly tokenIdentifier?: string;
539
+ readonly amount?: bigint;
540
+ readonly memo?: string;
541
+ readonly senderPublicKey?: Uint8Array;
542
+ readonly expiresAtMs?: number;
543
+ }) => Promise<string>;
544
+ /**
545
+ * Pays a Spark invoice address. `amount` is required for open invoices and must equal a fixed
546
+ * invoice amount when set. Unsigned invoices are accepted too: invoice fields (amount, sender
547
+ * restriction, expiry) are then only hints, and the receiver is always the identity key inside
548
+ * the address. Resolves to the `SparkTransfer` for sats invoices or the hex final token
549
+ * transaction hash for token invoices.
550
+ *
551
+ * `transferId` (sats invoices) and `inputOutputIds` (token invoices) are the retry handles
552
+ * after a lost response: a retry under the same handle recovers the committed result instead of
553
+ * paying twice, and a committed result under different terms fails rather than riding along.
554
+ */
555
+ readonly pay: (invoice: string, options?: {
556
+ readonly amount?: number | bigint;
557
+ /** Sats invoices: idempotent transfer id, like `transfers.send`'s. */
558
+ readonly transferId?: string;
559
+ /** Token invoices: ids of the spent outputs, like `tokens.transfer`'s. */
560
+ readonly inputOutputIds?: ReadonlyArray<string>;
561
+ }) => Promise<SparkTransfer | string>;
562
+ /** Coordinator `query_spark_invoices` statuses for the given invoice address strings. */
563
+ readonly status: (invoices: ReadonlyArray<string>) => Promise<ReadonlyArray<SparkInvoiceStatus>>;
564
+ };
565
+ /**
566
+ * This wallet's coordinator settings. `setPrivate(true)` restricts node and transfer reads to
567
+ * this identity's own session on every operator; `get` reports `privateEnabled: false` for a
568
+ * wallet that never stored a setting.
569
+ */
570
+ readonly walletSettings: {
571
+ readonly get: () => Promise<SparkWalletSettings>;
572
+ readonly setPrivate: (enabled: boolean) => Promise<SparkWalletSettings>;
573
+ };
574
+ /** SSP leaves-swap fee quote in sats. */
575
+ readonly swapFeeEstimate: (amountSats: number) => Promise<number>;
576
+ readonly lightning: {
577
+ /**
578
+ * Asks the SSP for a BOLT-11 invoice paying this identity. `amountSats` of 0 requests an
579
+ * amountless invoice; `includeSparkAddress` embeds a Spark fallback address payers can settle
580
+ * directly. `receiver` (a spark address string or 33-byte identity key) creates the invoice for
581
+ * another identity instead — the SSP routes its payment there and the payee claims it. The
582
+ * returned invoice is verified field-by-field before it is handed out.
583
+ */
584
+ readonly createInvoice: (options: {
585
+ readonly amountSats: number;
586
+ readonly memo?: string;
587
+ readonly descriptionHash?: Uint8Array;
588
+ readonly expirySecs?: number;
589
+ readonly includeSparkAddress?: boolean;
590
+ readonly receiver?: string | Uint8Array;
591
+ }) => Promise<LightningInvoice>;
592
+ /**
593
+ * Pays a BOLT-11 invoice via a preimage swap with the SSP. `amountSats` is required for
594
+ * zero-amount invoices and rejected otherwise; `transferId` makes a retry resume the same
595
+ * transfer instead of paying twice.
596
+ *
597
+ * On a `transferId` retry the reported `feeSats` is derived as the committed transfer total
598
+ * minus the amount passed in this call — pass the same invoice and `amountSats` as the first
599
+ * attempt. The SSP send request's echoed invoice is still verified before continuing.
600
+ *
601
+ * The leaf lock is held across the SSP call — see `transfers.send` for what that covers.
602
+ */
603
+ readonly pay: (options: {
604
+ readonly invoice: string;
605
+ readonly maxFeeSats: number;
606
+ readonly amountSats?: number;
607
+ readonly transferId?: string;
608
+ }) => Promise<LightningPayment>;
609
+ /**
610
+ * `user_request` status of a send; `preimage` appears once the SSP settled it. Pass the
611
+ * `LightningPayment` from `pay` — the request's invoice and preimage are verified against its
612
+ * payment hash, not the hash the SSP reports. `outcome` maps the SSP status to
613
+ * "pending"/"succeeded"/"failed"/"returned": "failed" means the payment will not settle but the
614
+ * funds are not back — keep polling until "returned" (≈5 min on hosted; the leaves then
615
+ * reappear in `leaves()` on the next sync).
616
+ */
617
+ readonly sendStatus: (request: LightningSendStatusRequest) => Promise<LightningSendStatus>;
618
+ /**
619
+ * `user_request` status of a receive, with the inbound transfer id once present and the settled
620
+ * `preimage` once the SSP reports it — the request's invoice and preimage are both checked
621
+ * against the payment hash of the invoice we created (a mismatch throws).
622
+ */
623
+ readonly receiveStatus: (request: LightningReceiveStatusRequest) => Promise<LightningReceiveStatus>;
624
+ /**
625
+ * Signs the sender timeout spend of a Lightning HTLC output — output `vout` of `htlcTx`, a
626
+ * committed refund transaction of an in-flight `pay` whose SSP never settled. Once `htlcTx` is
627
+ * `LIGHTNING_HTLC_SEQUENCE` (2160) blocks deep the output can be spent through the
628
+ * sequence-lock leaf back to `destinationAddress`. Returns the signed transaction UNBROADCAST —
629
+ * broadcast it yourself after the CSV wait; bitcoind rejects it earlier as non-BIP68-final.
630
+ * `paymentHash` and the SSP identity bind the output, which is verified before signing. Stored
631
+ * exit chains do not cover in-flight Lightning sends, so keep `htlcTx` until the sweep
632
+ * confirms.
633
+ */
634
+ readonly sweepHtlcTimeout: (options: {
635
+ readonly htlcTx: Uint8Array;
636
+ readonly vout: number;
637
+ readonly paymentHash: Uint8Array;
638
+ readonly destinationAddress: string;
639
+ readonly feeRateSatPerVbyte: number;
640
+ }) => Promise<Uint8Array>;
641
+ };
642
+ readonly deposits: {
643
+ /** Fresh single-use deposit address with a verified proof-of-possession. */
644
+ readonly newAddress: () => Promise<string>;
645
+ /** Deposit addresses the SO still considers unused. */
646
+ readonly unused: () => Promise<ReadonlyArray<UnusedDepositAddress>>;
647
+ /**
648
+ * Claims an on-chain deposit paying to one of the unused addresses. When the transaction has
649
+ * multiple matching outputs `vout` selects which one.
650
+ */
651
+ readonly claim: (options: {
652
+ readonly transaction: Uint8Array;
653
+ readonly vout?: number;
654
+ }) => Promise<SparkLeaf>;
655
+ /**
656
+ * Claims several confirmed UTXOs paying the SAME single-use address into one leaf — the only
657
+ * way to claim more than one UTXO, since a single-use address is consumed by a claim. At most
658
+ * 11 outputs; `vout` is resolved by unique match when omitted.
659
+ */
660
+ readonly claimMany: (options: {
661
+ readonly outputs: ReadonlyArray<{
662
+ readonly transaction: Uint8Array;
663
+ readonly vout?: number;
664
+ }>;
665
+ }) => Promise<SparkLeaf>;
666
+ /** The identity's reusable static deposit address — the same address on every call. */
667
+ readonly staticAddress: () => Promise<string>;
668
+ /** Confirmed, unclaimed UTXOs paying the static deposit address. */
669
+ readonly staticUtxos: () => Promise<ReadonlyArray<StaticDepositUtxo>>;
670
+ /**
671
+ * Claims a static-deposit UTXO through the SSP: quotes the credit, rejects fees over
672
+ * `maxFeeSats`, then claims the SSP's inbound transfer. `rawTx` supplies the deposit
673
+ * transaction when the SO's utxo listing does not return it.
674
+ */
675
+ readonly claimStatic: (options: {
676
+ readonly txid: string;
677
+ readonly vout: number;
678
+ readonly maxFeeSats: number;
679
+ readonly rawTx?: Uint8Array;
680
+ }) => Promise<StaticDepositClaimResult>;
681
+ /**
682
+ * Signs a version-3 refund spending a static-deposit UTXO to `destinationAddress` at
683
+ * `feeRateSatPerVbyte` (fee floored at 194 sats; output must clear dust). The signed
684
+ * transaction is returned unbroadcast.
685
+ */
686
+ readonly refundStatic: (options: {
687
+ readonly txid: string;
688
+ readonly vout: number;
689
+ readonly destinationAddress: string;
690
+ readonly feeRateSatPerVbyte: number;
691
+ readonly rawTx?: Uint8Array;
692
+ }) => Promise<StaticDepositRefund>;
693
+ };
694
+ readonly withdrawals: {
695
+ /**
696
+ * Pre-signed exit transactions for the given leaves, root first (see ExitTransaction), from a
697
+ * live `query_nodes` call the coordinator and every other operator must answer identically —
698
+ * use `offlineExitTransactions` when the operators are unreachable or withholding data. Each
699
+ * transaction carries a hard deadline: once its parent confirms and its relative timelock
700
+ * passes, it must confirm within DIRECT_TIMELOCK_OFFSET blocks; otherwise the operators'
701
+ * watchtower may publish a self-fee variant instead. For intermediate nodes this strands
702
+ * descendants as WATCHTOWER_EXITED (recover with recoverWatchtowerExit while the SO is online);
703
+ * for refunds the watchtower publishes direct_from_cpfp_refund_tx, which pays the leaf key
704
+ * (sweep with sweepRefund). Keep each exit package confirming promptly.
705
+ */
706
+ readonly unilateralExit: (leafIds: ReadonlyArray<string>) => Promise<ReadonlyArray<ExitTransaction>>;
707
+ /**
708
+ * The same broadcast list `unilateralExit` returns, built purely from the exit chains the
709
+ * SparkStore persists — this method performs no network calls. Stored chains are refreshed by
710
+ * every leaves sync, so this is the recovery path when the operators are unreachable or
711
+ * withholding data. Throws a SparkInputError naming any leaf that has no stored chain. The same
712
+ * broadcast deadlines apply: each transaction must confirm within DIRECT_TIMELOCK_OFFSET blocks
713
+ * once its parent's relative timelock matures.
714
+ */
715
+ readonly offlineExitTransactions: (leafIds: ReadonlyArray<string>) => Promise<ReadonlyArray<ExitTransaction>>;
716
+ /**
717
+ * The SSP's per-speed cooperative-exit fees for `address`. `amountSats` selects exactly that
718
+ * much to exit (swapping if needed); omitting it quotes for the whole balance.
719
+ */
720
+ readonly quoteCooperativeExit: (options: {
721
+ readonly address: string;
722
+ readonly amountSats?: number;
723
+ }) => Promise<CooperativeExitQuote>;
724
+ /**
725
+ * Cooperatively exits leaves to `address`, deducting `speed`'s quoted fee from the payout.
726
+ * `amountSats` exits exactly that much; omitting it exits the whole balance. Pass the same
727
+ * `transferId` to retry a call whose response was lost — a committed exit resumes with the
728
+ * committed leaves. Note the SSP request expires ~2 minutes after creation unless the transfer
729
+ * commits: an uncommitted id is burned, retry with a fresh `transferId`.
730
+ *
731
+ * The leaf lock is held across the fee quote and the SSP request — see `transfers.send` for
732
+ * what that covers.
733
+ */
734
+ readonly cooperativeExit: (options: {
735
+ readonly address: string;
736
+ readonly speed: CooperativeExitSpeed;
737
+ readonly maxFeeSats: number;
738
+ readonly amountSats?: number;
739
+ readonly transferId?: string;
740
+ }) => Promise<CooperativeExitResult>;
741
+ /** The SSP's status for a cooperative-exit request id. */
742
+ readonly cooperativeExitStatus: (requestId: string) => Promise<CooperativeExitStatus>;
743
+ /**
744
+ * The leaves a watchtower exit cut off from their exit path, each with the confirmed ancestor
745
+ * output it can still spend when one resolves. Entries stay listed after a recovery — the SE
746
+ * never sees the broadcast, so check the chain for whether a recovery landed.
747
+ */
748
+ readonly watchtowerExitedLeaves: () => Promise<ReadonlyArray<WatchtowerExitedLeaf>>;
749
+ /**
750
+ * Co-signs a transaction spending the on-chain output a watchtower exit stranded under
751
+ * `leafId`, returned signed but NOT broadcast. Re-call with a higher fee to re-sign the same
752
+ * outpoint — at most one recovery can confirm.
753
+ */
754
+ readonly recoverWatchtowerExit: (options: {
755
+ readonly leafId: string;
756
+ readonly destinationScript: Uint8Array;
757
+ readonly feeRateSatPerVbyte: number;
758
+ readonly recoveryTxid?: string;
759
+ readonly outputIndex?: number;
760
+ }) => Promise<{
761
+ readonly transaction: Uint8Array;
762
+ readonly txid: string;
763
+ }>;
764
+ /**
765
+ * Signed key-path sweep of a confirmed refund output (any of the leaf's refund variants, output 0)
766
+ * to `destinationScript`. `refundTx` may be the stored witness-less `directFromCpfpRefundTx`
767
+ * template — only its txid and output 0 are read.
768
+ */
769
+ readonly sweepRefund: (options: {
770
+ readonly leafId: string;
771
+ readonly refundTx: Uint8Array;
772
+ readonly destinationScript: Uint8Array;
773
+ readonly feeRateSatPerVbyte: number;
774
+ }) => Promise<Uint8Array>;
775
+ };
776
+ /** Coordinator `subscribe_to_events`; reconnects until `signal` aborts or `close()` runs. */
777
+ readonly events: (signal?: AbortSignal) => AsyncIterable<SparkEvent>;
778
+ /** Aborts all outstanding event streams (including caller-signaled ones). */
779
+ readonly close: () => void;
780
+ };
781
+ /** One entry of `query_spark_invoices`: the invoice string, its status name, and the payment. */
782
+ type SparkInvoiceStatus = {
783
+ readonly invoice: string;
784
+ /** `InvoiceStatus` enum name, e.g. `"PENDING"`, `"FINALIZED"`. */
785
+ readonly status: string;
786
+ /** Hex transfer id when a sats transfer paid the invoice. */
787
+ readonly satsTransferId?: string | undefined;
788
+ /** Hex `hashFinalTokenTransaction` when a token transfer paid the invoice. */
789
+ readonly tokenTransactionHash?: string | undefined;
790
+ };
791
+ type SparkClientOptions = {
792
+ readonly network: SparkNetwork;
793
+ readonly signer: SparkSigner;
794
+ /**
795
+ * On React Native inject a streaming fetch (`expo/fetch`, the global from Expo SDK 56): RN's
796
+ * XHR-based fetch (e.g. with `EXPO_PUBLIC_USE_RN_FETCH=1`) has no streaming body, so `events()`
797
+ * cannot work with it.
798
+ */
799
+ readonly fetch: typeof globalThis.fetch;
800
+ /**
801
+ * Exit-chain persistence (e.g. `createMemorySparkStore()`). Required: stored chains are the
802
+ * wallet's unilateral-exit data, so durability is a caller decision — a silent in-memory default
803
+ * would lose them on restart.
804
+ */
805
+ readonly store: SparkStore;
806
+ readonly random?: (length: number) => Uint8Array;
807
+ readonly now?: () => number;
808
+ readonly sleep?: (ms: number) => Promise<void>;
809
+ readonly operators?: ReadonlyArray<SparkOperatorConfig>;
810
+ readonly ssp?: SparkNetworkConfig["ssp"];
811
+ };
812
+ /**
813
+ * Builds a Spark client over one operator set. All spend paths are concurrency-safe within one
814
+ * client instance — sends, swaps, lightning payments, exits and claims serialize leaf selection and
815
+ * exit-chain bookkeeping on an internal lock, and token transfers likewise — but several client
816
+ * instances or devices on one identity are not coordinated: the SO rejects the conflicting spend.
817
+ */
818
+ declare function createSparkClient(options: SparkClientOptions): SparkClient;
819
+ //#endregion
820
+ export { CooperativeExitStatus as A, exitTransactions as C, CooperativeExitQuote as D, createMemorySparkStore as E, UnusedDepositAddress as F, SparkLeaf as I, SparkEvent as L, StaticDepositClaim as M, StaticDepositRefund as N, CooperativeExitResult as O, StaticDepositUtxo as P, ExitTransaction as S, SparkStore as T, LightningSendStatus as _, createSparkClient as a, LightningInvoice as b, buildCpfpChild as c, SparkTokenBalance as d, SparkTokenOutput as f, LightningSendOutcome as g, LightningReceiveStatus as h, SparkInvoiceStatus as i, MIN_STATIC_REFUND_FEE_SATS as j, CooperativeExitSpeed as k, SparkTransfer as l, SparkWalletSettings as m, SparkClient as n, StaticDepositClaimResult as o, SparkTokenOutputStatus as p, SparkClientOptions as r, FundingInput as s, ClaimPendingResult as t, SparkTransferLeaf as u, LightningSendStatusRequest as v, SparkExitChain as w, WatchtowerExitedLeaf as x, LightningPayment as y };