@arkade-os/swap 0.0.3 → 0.0.5
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/README.md +189 -54
- package/dist/{chunk-HLMMA3LJ.js → chunk-Q4FAYBXS.js} +60 -247
- package/dist/index.cjs +212 -301
- package/dist/index.d.cts +283 -10
- package/dist/index.d.ts +283 -10
- package/dist/index.js +150 -69
- package/dist/nostr.cjs +21 -14
- package/dist/nostr.d.cts +14 -3
- package/dist/nostr.d.ts +14 -3
- package/dist/nostr.js +10 -2
- package/dist/{rfq-CCAFoFtR.d.cts → rfq-BH2yvo3O.d.cts} +50 -335
- package/dist/{rfq-CCAFoFtR.d.ts → rfq-BH2yvo3O.d.ts} +50 -335
- package/package.json +2 -2
package/dist/nostr.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as RfqTransport } from './rfq-BH2yvo3O.js';
|
|
2
2
|
import { SimplePool } from 'nostr-tools';
|
|
3
3
|
import '@arkade-os/sdk';
|
|
4
|
-
import '@arkade-os/solver-discovery';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* The Nostr RFQ transport — the PRODUCTION one (docs/rfq-protocol.md § 3.1 in
|
|
@@ -71,6 +70,18 @@ declare class RelayUnavailable extends Error {
|
|
|
71
70
|
readonly reasons: string[];
|
|
72
71
|
constructor(reasons: string[]);
|
|
73
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* `close()` was called while a negotiation was still waiting on a reply.
|
|
75
|
+
*
|
|
76
|
+
* Distinct from both a timeout and {@link RelayUnavailable}, which describe the
|
|
77
|
+
* wire; this describes a decision on our own side of it. A caller that closed
|
|
78
|
+
* deliberately — a user leaving the screen, a flow abandoning its request — can
|
|
79
|
+
* match on this and stay quiet, rather than reporting a solver failure that
|
|
80
|
+
* never happened.
|
|
81
|
+
*/
|
|
82
|
+
declare class TransportClosed extends Error {
|
|
83
|
+
constructor();
|
|
84
|
+
}
|
|
74
85
|
interface NostrRfqOptions {
|
|
75
86
|
/** Relay URLs from the solver's card. The rendezvous, not solver endpoints. */
|
|
76
87
|
relays: string[];
|
|
@@ -96,4 +107,4 @@ interface NostrRfqOptions {
|
|
|
96
107
|
*/
|
|
97
108
|
declare const nostrRfqTransport: (options: NostrRfqOptions) => RfqTransport;
|
|
98
109
|
|
|
99
|
-
export { type NostrRfqOptions, RFQ_AD_KIND, RFQ_DIRECTED_KIND, RelayUnavailable, nostrRfqTransport };
|
|
110
|
+
export { type NostrRfqOptions, RFQ_AD_KIND, RFQ_DIRECTED_KIND, RelayUnavailable, TransportClosed, nostrRfqTransport };
|
package/dist/nostr.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SwapRefusal
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Q4FAYBXS.js";
|
|
4
4
|
|
|
5
5
|
// src/nostr.ts
|
|
6
6
|
import {
|
|
@@ -21,6 +21,12 @@ var RelayUnavailable = class extends Error {
|
|
|
21
21
|
this.reasons = reasons;
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
+
var TransportClosed = class extends Error {
|
|
25
|
+
constructor() {
|
|
26
|
+
super("transport closed before the solver replied");
|
|
27
|
+
this.name = "TransportClosed";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
24
30
|
var closeReasons = (raw) => raw.map((entry) => {
|
|
25
31
|
if (typeof entry === "string") return entry;
|
|
26
32
|
const { url, reason } = entry ?? {};
|
|
@@ -120,9 +126,10 @@ var nostrRfqTransport = (options) => {
|
|
|
120
126
|
},
|
|
121
127
|
async close() {
|
|
122
128
|
closed = true;
|
|
123
|
-
|
|
129
|
+
for (const waiter of waiters.values()) waiter.reject(new TransportClosed());
|
|
124
130
|
waiters.clear();
|
|
125
131
|
if (ownsPool) pool.close(relays);
|
|
132
|
+
else subscription.close();
|
|
126
133
|
}
|
|
127
134
|
};
|
|
128
135
|
};
|
|
@@ -130,5 +137,6 @@ export {
|
|
|
130
137
|
RFQ_AD_KIND,
|
|
131
138
|
RFQ_DIRECTED_KIND,
|
|
132
139
|
RelayUnavailable,
|
|
140
|
+
TransportClosed,
|
|
133
141
|
nostrRfqTransport
|
|
134
142
|
};
|
|
@@ -1,150 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DiscoveredMarket } from '@arkade-os/solver-discovery';
|
|
3
|
-
|
|
4
|
-
type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
|
|
5
|
-
/** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
|
|
6
|
-
* Lives here with the {@link AssetSwap} fields it describes so the market and
|
|
7
|
-
* restore layers share one spelling instead of re-typing the literal. */
|
|
8
|
-
declare const BTC_ASSET_ID = "btc";
|
|
9
|
-
interface AssetSwapFallbackSecretsV1 {
|
|
10
|
-
version: 1;
|
|
11
|
-
type: "stored";
|
|
12
|
-
senderPrivateKeyHex: string;
|
|
13
|
-
/** Onchain-send only. A lightning send's preimage belongs to the payee. */
|
|
14
|
-
preimageHex?: string;
|
|
15
|
-
}
|
|
16
|
-
type AssetSwapFallbackSecrets = AssetSwapFallbackSecretsV1;
|
|
17
|
-
interface AssetSwap {
|
|
18
|
-
/** Funding txid — the swap's identity. */
|
|
19
|
-
id: string;
|
|
20
|
-
/** 'btc' or a 68-hex asset id. */
|
|
21
|
-
fromAsset: string;
|
|
22
|
-
toAsset: string;
|
|
23
|
-
/** Atomic amounts as strings (bigint is not JSON-safe). */
|
|
24
|
-
fromAmount: string;
|
|
25
|
-
/** The covenant wantAmount — a floor, the fill pays >= this. */
|
|
26
|
-
toAmount: string;
|
|
27
|
-
swapAddress: string;
|
|
28
|
-
/** Hex pkScript of the swap contract — the indexer monitoring key. */
|
|
29
|
-
swapPkScript: string;
|
|
30
|
-
/** TLV offer — needed to rebuild the contract for cancel. */
|
|
31
|
-
offerHex: string;
|
|
32
|
-
fundingTxid: string;
|
|
33
|
-
spentTxid?: string;
|
|
34
|
-
status: AssetSwapStatus;
|
|
35
|
-
createdAt: number;
|
|
36
|
-
completedAt?: number;
|
|
37
|
-
/** RFQ pair string, e.g. `arkade:BTC->onchain:BTC`. */
|
|
38
|
-
pair?: string;
|
|
39
|
-
/** `sha256(P)`, hex. Public, and how a restore confirms a candidate
|
|
40
|
-
* derivation is the right one. */
|
|
41
|
-
paymentHash?: string;
|
|
42
|
-
/**
|
|
43
|
-
* The HD descriptor this swap's secrets derive from. Public — it is what
|
|
44
|
-
* lets the record carry no secrets at all. Present iff the swap was
|
|
45
|
-
* created on a wallet that can allocate.
|
|
46
|
-
*/
|
|
47
|
-
signingDescriptor?: string;
|
|
48
|
-
/** P, hex, when the user supplied a preimage that is not seed-derived. */
|
|
49
|
-
preimageHex?: string;
|
|
50
|
-
/**
|
|
51
|
-
* Complete stored-arm secrets for wallets that cannot derive. Versioned
|
|
52
|
-
* and discriminated so restore can rebuild both the sender identity and,
|
|
53
|
-
* for onchain sends, P.
|
|
54
|
-
*/
|
|
55
|
-
fallbackSecrets?: AssetSwapFallbackSecrets;
|
|
56
|
-
/** The L1 HTLC's pkScript, hex — the chain-watch key. */
|
|
57
|
-
htlcPkScriptHex?: string;
|
|
58
|
-
htlcLocktime?: number;
|
|
59
|
-
/** The L1 funding txid, once observed. */
|
|
60
|
-
l1Txid?: string;
|
|
61
|
-
}
|
|
62
|
-
/** All swaps, newest-first. Insertion order is not chronological — the restore
|
|
63
|
-
* scan rebuilds records in tx-scan order — so sort at read to keep
|
|
64
|
-
* newest-first canonical for every consumer. */
|
|
65
|
-
declare const getAssetSwapsOrThrow: (repository: AssetSwapRepository) => Promise<AssetSwap[]>;
|
|
66
|
-
/** The consumer read: a broken backend reads as no swaps rather than crashing
|
|
67
|
-
* a history view. Mutations must use {@link getAssetSwapsOrThrow} instead —
|
|
68
|
-
* swallowing the read there would let "the backend is gone" masquerade as "no
|
|
69
|
-
* such swap" and skip the write silently. */
|
|
70
|
-
declare const getAssetSwaps: (repository: AssetSwapRepository) => Promise<AssetSwap[]>;
|
|
71
|
-
/** Add a swap; no-op if the id is already stored. Returns the updated list.
|
|
72
|
-
* THROWS on a failed write — nothing irreversible may happen until this record
|
|
73
|
-
* is durable, so the caller must not fund on a failure. */
|
|
74
|
-
declare const addAssetSwap: (repository: AssetSwapRepository, swap: AssetSwap) => Promise<AssetSwap[]>;
|
|
75
|
-
/** Merge changes into a swap by id. Returns the updated list.
|
|
76
|
-
* THROWS on a failed read or write, like {@link addAssetSwap} — use this for a
|
|
77
|
-
* write that gates something irreversible. Transitions written *after* the
|
|
78
|
-
* irreversible act belong on {@link updateAssetSwapBestEffort}. */
|
|
79
|
-
declare const updateAssetSwap: (repository: AssetSwapRepository, id: string, changes: Partial<Omit<AssetSwap, "id">>) => Promise<AssetSwap[]>;
|
|
80
|
-
/**
|
|
81
|
-
* {@link updateAssetSwap} for transitions that follow an irreversible action (a
|
|
82
|
-
* broadcast claim, a spent lockup): failing the caller there would report as
|
|
83
|
-
* failed a swap whose funds already moved, and a stale status is recoverable —
|
|
84
|
-
* crash recovery re-derives the true state from the chain
|
|
85
|
-
* (`classifyOnchainHtlc`).
|
|
86
|
-
*
|
|
87
|
-
* `persisted` is the part that must not be hidden: a caller that notifies on a
|
|
88
|
-
* change, or treats one as terminal, has to know the store did not agree.
|
|
89
|
-
*/
|
|
90
|
-
declare const updateAssetSwapBestEffort: (repository: AssetSwapRepository, id: string, changes: Partial<Omit<AssetSwap, "id">>) => Promise<{
|
|
91
|
-
swaps: AssetSwap[];
|
|
92
|
-
persisted: boolean;
|
|
93
|
-
}>;
|
|
94
|
-
|
|
95
|
-
/** A registry discovery result held for reuse. Refetchable — unlike a swap
|
|
96
|
-
* record, losing it costs one network round trip — but it must survive a cold
|
|
97
|
-
* boot: serving it stale is what keeps quoting alive while a registry is down. */
|
|
98
|
-
interface MarketsCacheEntry {
|
|
99
|
-
markets: DiscoveredMarket[];
|
|
100
|
-
fetchedAt: number;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Everything the package persists, following the monorepo repository
|
|
104
|
-
* convention (versioned interface, AsyncDisposable, one backend per
|
|
105
|
-
* platform — see the Boltz plugin's SwapRepository). Consumers construct
|
|
106
|
-
* exactly one of these; there is no second storage seam.
|
|
107
|
-
*
|
|
108
|
-
* Durable records (swaps) and rebuildable state (the restore scan's txid
|
|
109
|
-
* cursor, the markets cache) live side by side because they share a
|
|
110
|
-
* lifetime: all three belong to one wallet on one device, and a consumer
|
|
111
|
-
* that wipes one wants all three gone.
|
|
112
|
-
*
|
|
113
|
-
* ponytail: no query filters — every consumer reads all swaps and filters
|
|
114
|
-
* in memory; mirror the Boltz plugin's GetSwapsFilter when a consumer needs
|
|
115
|
-
* subset queries.
|
|
116
|
-
*/
|
|
117
|
-
interface AssetSwapRepository extends AsyncDisposable {
|
|
118
|
-
readonly version: 1;
|
|
119
|
-
/** Insert or replace a swap by id. Store the record whole: `fallbackSecrets`
|
|
120
|
-
* is secret-bearing, and a field-mapped backend that drops it loses the
|
|
121
|
-
* stored arm's claim and refund keys. */
|
|
122
|
-
saveSwap(swap: AssetSwap): Promise<void>;
|
|
123
|
-
/** All stored swaps, in no particular order — `getAssetSwaps` is the
|
|
124
|
-
* canonical newest-first read. */
|
|
125
|
-
getAllSwaps(): Promise<AssetSwap[]>;
|
|
126
|
-
/** Sent txids already checked for offer packets (see restore.ts). */
|
|
127
|
-
getScannedTxids(): Promise<Set<string>>;
|
|
128
|
-
markTxidsScanned(txids: Iterable<string>): Promise<void>;
|
|
129
|
-
/** Cached registry markets, or undefined on a miss. */
|
|
130
|
-
getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
|
|
131
|
-
saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
|
|
132
|
-
clear(): Promise<void>;
|
|
133
|
-
}
|
|
134
|
-
declare class InMemoryAssetSwapRepository implements AssetSwapRepository {
|
|
135
|
-
readonly version: 1;
|
|
136
|
-
private readonly swaps;
|
|
137
|
-
private readonly scanned;
|
|
138
|
-
private readonly markets;
|
|
139
|
-
saveSwap(swap: AssetSwap): Promise<void>;
|
|
140
|
-
getAllSwaps(): Promise<AssetSwap[]>;
|
|
141
|
-
getScannedTxids(): Promise<Set<string>>;
|
|
142
|
-
markTxidsScanned(txids: Iterable<string>): Promise<void>;
|
|
143
|
-
getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
|
|
144
|
-
saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
|
|
145
|
-
clear(): Promise<void>;
|
|
146
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
147
|
-
}
|
|
1
|
+
import { asset, VHTLC, IWallet, ProvisionedClaimSecret, ProvisionedKey } from '@arkade-os/sdk';
|
|
148
2
|
|
|
149
3
|
/** L1 confirmation-depth and reorg margin between dependent timelocks. */
|
|
150
4
|
declare const ONCHAIN_ORDER_MARGIN_SECONDS: number;
|
|
@@ -356,168 +210,6 @@ declare function classifyOnchainHtlc(chain: ChainSource, input: {
|
|
|
356
210
|
};
|
|
357
211
|
}): Promise<OnchainHtlcPhase>;
|
|
358
212
|
|
|
359
|
-
/**
|
|
360
|
-
* Domain separator for the preimage derivation.
|
|
361
|
-
*
|
|
362
|
-
* NArk scopes its tag by protocol+provider (`Arkade-Boltz-Preimage-v1`,
|
|
363
|
-
* `SwapsManagementService.cs:128`) so any Arkade SDK reproduces the same
|
|
364
|
-
* preimage. NArk has no RFQ corridor yet, so this tag defines the scheme
|
|
365
|
-
* rather than mirroring one; it is deliberately distinct from the Boltz tag,
|
|
366
|
-
* or the same wallet key would derive one preimage for both corridors.
|
|
367
|
-
*/
|
|
368
|
-
declare const RFQ_PREIMAGE_TAG = "Arkade-RFQ-Preimage-v1";
|
|
369
|
-
/**
|
|
370
|
-
* `TAG ‖ xonly(32) ‖ u32le(index)` — the message that gets BIP-340 signed.
|
|
371
|
-
*
|
|
372
|
-
* Anchored on the canonical x-only key rather than the descriptor string:
|
|
373
|
-
* restore reconstructs a bare descriptor that serialises differently from the
|
|
374
|
-
* signing descriptor used at create time, and only the key agrees across both.
|
|
375
|
-
*/
|
|
376
|
-
declare function buildPreimageMessage(xonly: Uint8Array, index: number): Uint8Array;
|
|
377
|
-
/** No secrets at rest: everything re-derives from the seed plus this. */
|
|
378
|
-
interface DerivedSwapSecrets {
|
|
379
|
-
derivable: true;
|
|
380
|
-
/** Public. Persist it on the swap record; it is what restore keys off. */
|
|
381
|
-
signingDescriptor: string;
|
|
382
|
-
/** Onchain-send only, when the caller supplied P instead of deriving it. */
|
|
383
|
-
preimage?: Uint8Array;
|
|
384
|
-
}
|
|
385
|
-
/** The wallet could not allocate. These are real secrets — persist them. */
|
|
386
|
-
interface StoredSwapSecrets {
|
|
387
|
-
derivable: false;
|
|
388
|
-
senderPrivateKey: Uint8Array;
|
|
389
|
-
/** Onchain-send only. A lightning send's preimage belongs to the payee. */
|
|
390
|
-
preimage?: Uint8Array;
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Which arm a swap got. The discriminant makes the persistence obligation a
|
|
394
|
-
* type-level fact: a consumer written against {@link DerivedSwapSecrets} alone
|
|
395
|
-
* fails to compile when handed the stored arm.
|
|
396
|
-
*/
|
|
397
|
-
type SwapSecrets = DerivedSwapSecrets | StoredSwapSecrets;
|
|
398
|
-
/**
|
|
399
|
-
* Allocate a descriptor for one swap, or `undefined` when the wallet cannot.
|
|
400
|
-
*
|
|
401
|
-
* Allocates — never peeks. `getCurrentSigningDescriptor` returns the same
|
|
402
|
-
* descriptor until the wallet rotates, and two swaps sharing a descriptor
|
|
403
|
-
* derive the *identical* preimage, so one solver learning its own preimage
|
|
404
|
-
* would learn the other swap's.
|
|
405
|
-
*
|
|
406
|
-
* Cost of allocating: the index is consumed even when the quote is later
|
|
407
|
-
* refused, and a swap index never turns into a funded receive contract, so a
|
|
408
|
-
* long run of swaps widens the "unused" gap a seed-only `restore()` scan sees
|
|
409
|
-
* (see the README's gap-limit note). Restores that keep the swap repository
|
|
410
|
-
* are unaffected — `adoptSwapDescriptor` re-claims each record's index.
|
|
411
|
-
*/
|
|
412
|
-
declare function deriveSwapSecrets(wallet: IWallet): Promise<DerivedSwapSecrets | undefined>;
|
|
413
|
-
/**
|
|
414
|
-
* The fallback arm. Separate from {@link deriveSwapSecrets} so nothing can
|
|
415
|
-
* fabricate a preimage while probing for a derived one.
|
|
416
|
-
*/
|
|
417
|
-
declare function randomSwapSecrets(opts?: {
|
|
418
|
-
preimage?: boolean | Uint8Array;
|
|
419
|
-
}): StoredSwapSecrets;
|
|
420
|
-
/**
|
|
421
|
-
* Serialize or restore the secrets arm a persisted record describes. Normal
|
|
422
|
-
* HD swaps store only `signingDescriptor`; caller-supplied preimages add
|
|
423
|
-
* `preimageHex`; fallback swaps use `fallbackSecrets` so both P and the
|
|
424
|
-
* sender identity survive a restart.
|
|
425
|
-
*/
|
|
426
|
-
declare function rfqSecretsToRecord(secrets: SwapSecrets): {
|
|
427
|
-
signingDescriptor?: string;
|
|
428
|
-
preimageHex?: string;
|
|
429
|
-
fallbackSecrets?: AssetSwapFallbackSecrets;
|
|
430
|
-
};
|
|
431
|
-
declare function rfqSecretsOfRecord(record: {
|
|
432
|
-
signingDescriptor?: string;
|
|
433
|
-
preimageHex?: string;
|
|
434
|
-
fallbackSecrets?: AssetSwapFallbackSecrets;
|
|
435
|
-
}): SwapSecrets | undefined;
|
|
436
|
-
/**
|
|
437
|
-
* Claim a restored swap's index so a later allocation cannot reissue it —
|
|
438
|
-
* which would derive that swap's preimage a second time, for a different swap.
|
|
439
|
-
* Monotonic; a no-op on a wallet that cannot allocate.
|
|
440
|
-
*/
|
|
441
|
-
declare function adoptSwapDescriptor(wallet: IWallet, signingDescriptor: string): Promise<void>;
|
|
442
|
-
/** Why a wallet cannot produce a swap's sender key. Different instructions to
|
|
443
|
-
* a user: restore the other wallet, or accept that this record never carried
|
|
444
|
-
* the secrets at all. */
|
|
445
|
-
type RefundBlockedReason =
|
|
446
|
-
/** The record names no arm: neither `signingDescriptor` nor `fallbackSecrets`. */
|
|
447
|
-
"no-secrets"
|
|
448
|
-
/** It names an arm this version cannot read. */
|
|
449
|
-
| "unreadable-secrets"
|
|
450
|
-
/** The descriptor belongs to another seed, or this wallet is static. */
|
|
451
|
-
| "foreign-descriptor";
|
|
452
|
-
/**
|
|
453
|
-
* The wallet cannot produce this swap's sender key, so no local refund is
|
|
454
|
-
* possible: not a failure to retry, a capability this wallet does not have.
|
|
455
|
-
*
|
|
456
|
-
* Thrown where the cause is discovered rather than translated at the edge, so
|
|
457
|
-
* a `refundArkade` wired through {@link senderIdentityForSwapRecord} reports it
|
|
458
|
-
* to `RfqSwapManager` unwrapped — which is what stops the manager grinding
|
|
459
|
-
* against a push that can never work for the whole refund window.
|
|
460
|
-
*/
|
|
461
|
-
declare class RefundNotLocallyPossibleError extends Error {
|
|
462
|
-
readonly reason: RefundBlockedReason;
|
|
463
|
-
readonly name = "RefundNotLocallyPossibleError";
|
|
464
|
-
constructor(reason: RefundBlockedReason, message: string, options?: {
|
|
465
|
-
cause?: unknown;
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
/**
|
|
469
|
-
* The VHTLC `sender` identity — the signer for every interactive refund.
|
|
470
|
-
*
|
|
471
|
-
* The capability probe is not the check that matters: `signerForDescriptor`
|
|
472
|
-
* falls back to the plain wallet identity for a descriptor it cannot derive —
|
|
473
|
-
* a different seed, a static wallet — and that identity signs happily with the
|
|
474
|
-
* wrong key, which surfaces only as a solver rejection or a dead claim script.
|
|
475
|
-
* So the check is on what comes back: only a descriptor-bound signer carries
|
|
476
|
-
* `signSchnorrDeterministic`.
|
|
477
|
-
*/
|
|
478
|
-
declare function senderIdentityForRfqSecrets(wallet: IWallet, secrets: SwapSecrets): Promise<Identity>;
|
|
479
|
-
/**
|
|
480
|
-
* The VHTLC `sender` identity for a stored swap record, or a typed refusal.
|
|
481
|
-
*
|
|
482
|
-
* The record→identity composition {@link rfqSecretsOfRecord} deliberately does
|
|
483
|
-
* not do: it stays total so history iteration can call it, so *this* is where
|
|
484
|
-
* "no secrets on the record" becomes a refusal rather than an `undefined` the
|
|
485
|
-
* caller has to remember to check.
|
|
486
|
-
*
|
|
487
|
-
* **Wire `refundArkade` here, not to {@link senderIdentityForRfqSecrets}.**
|
|
488
|
-
* Only two of the three causes are throws; a caller one level down would skip
|
|
489
|
-
* the third silently and turn it into a `TypeError` at the push site, which
|
|
490
|
-
* `RfqSwapManager` then treats as retryable and grinds against for the whole
|
|
491
|
-
* refund window.
|
|
492
|
-
*
|
|
493
|
-
* Takes the record shape structurally, matching {@link rfqSecretsOfRecord}, so
|
|
494
|
-
* either record type can be passed.
|
|
495
|
-
*/
|
|
496
|
-
declare function senderIdentityForSwapRecord(wallet: IWallet, record: {
|
|
497
|
-
signingDescriptor?: string;
|
|
498
|
-
preimageHex?: string;
|
|
499
|
-
fallbackSecrets?: AssetSwapFallbackSecrets;
|
|
500
|
-
}): Promise<Identity>;
|
|
501
|
-
/** The `sender` x-only pubkey, the only half the request flow needs. */
|
|
502
|
-
declare function senderPubkeyForRfqSecrets(wallet: IWallet, secrets: SwapSecrets): Promise<Uint8Array>;
|
|
503
|
-
/**
|
|
504
|
-
* An identity that signs with `aux_rand = 0`, which is what makes the
|
|
505
|
-
* derivation reproducible. `DescriptorIdentity` satisfies it and throws rather
|
|
506
|
-
* than degrading to a random-aux signer.
|
|
507
|
-
*/
|
|
508
|
-
interface DeterministicSigner extends ReadonlyIdentity {
|
|
509
|
-
signSchnorrDeterministic(messageHash: Uint8Array): Promise<Uint8Array>;
|
|
510
|
-
}
|
|
511
|
-
declare function isDeterministicSigner(value: unknown): value is DeterministicSigner;
|
|
512
|
-
/**
|
|
513
|
-
* `sha256(sign(sha256(msg)))`, with the signing key and the message key being
|
|
514
|
-
* the same identity — passing a key in separately is how this silently derives
|
|
515
|
-
* an unrecoverable preimage.
|
|
516
|
-
*/
|
|
517
|
-
declare function derivePreimage(signer: DeterministicSigner): Promise<Uint8Array>;
|
|
518
|
-
/** The onchain-send preimage, re-derived or read back off the stored arm. */
|
|
519
|
-
declare function preimageForRfqSecrets(wallet: IWallet, secrets: SwapSecrets): Promise<Uint8Array>;
|
|
520
|
-
|
|
521
213
|
/** Legs are `<corridor>:<asset>`; a pair is directional, `from->to`. Arkade
|
|
522
214
|
* asset legs stay coarse (`arkade:ASSET`) — the exact asset ids ride the
|
|
523
215
|
* request profile, mirroring how the offer TLV identifies assets. */
|
|
@@ -663,20 +355,38 @@ declare const relayTransport: (relayUrl: string, options: {
|
|
|
663
355
|
WebSocketCtor?: new (url: string) => RelaySocket;
|
|
664
356
|
timeoutMs?: number;
|
|
665
357
|
}) => RfqTransport;
|
|
358
|
+
/**
|
|
359
|
+
* How long the sender's SOLO refund opens after the receiver's claim, seconds.
|
|
360
|
+
*
|
|
361
|
+
* This is the window in which a claimant holding the preimage must be able to
|
|
362
|
+
* finish taking their money before the funder could take it back. On a live
|
|
363
|
+
* Arkade server that is one collaborative spend; with the server gone it is a
|
|
364
|
+
* full unilateral exit — an unroll broadcast per chain step, each waiting on a
|
|
365
|
+
* confirmation, then the CSV spend.
|
|
366
|
+
*
|
|
367
|
+
* 4096s (eight 512s units, ~68 minutes) is sized for that worst case. It is
|
|
368
|
+
* REASONED, not measured, and it mirrors `SOLO_REFUND_HEADROOM_SECONDS` in the
|
|
369
|
+
* reference solver's `src/core/timelocks.ts` — the two must move together or a
|
|
370
|
+
* trader derives an address the solver never quoted.
|
|
371
|
+
*
|
|
372
|
+
* A multiple of the granularity on purpose: BIP68 would round anything else,
|
|
373
|
+
* making the encoded timelock differ from the number written here.
|
|
374
|
+
*/
|
|
375
|
+
declare const SOLO_REFUND_HEADROOM_SECONDS: number;
|
|
666
376
|
/** The solver's unilateral-claim delay, derived from the Ark server's reported
|
|
667
377
|
* exit delay exactly as the reference solver derives it — both sides read the
|
|
668
378
|
* SAME server, so the derivation (not a quote field) is what keeps the two
|
|
669
379
|
* scripts identical. */
|
|
670
380
|
declare const unilateralClaimDelay: (serverExitDelaySeconds: number) => number;
|
|
671
|
-
/** VHTLC's `unilateralRefund` tier: sender +
|
|
672
|
-
*
|
|
673
|
-
* and
|
|
674
|
-
*
|
|
675
|
-
* produces — one rounding, shared across all three tiers. */
|
|
381
|
+
/** VHTLC's `unilateralRefund` tier: sender + receiver, no server — LEVEL with
|
|
382
|
+
* `claimDelay`, not above it. Neither party can spend a two-signature leaf
|
|
383
|
+
* alone, so separating it buys no safety, and every second spent separating it
|
|
384
|
+
* is a second taken off the headroom that does matter. */
|
|
676
385
|
declare const unilateralRefundDelay: (claimDelay: number) => number;
|
|
677
|
-
/** VHTLC's `unilateralRefundWithoutReceiver` tier: sender alone,
|
|
678
|
-
* nobody
|
|
679
|
-
*
|
|
386
|
+
/** VHTLC's `unilateralRefundWithoutReceiver` tier: sender alone, needing
|
|
387
|
+
* nobody. The only leaf whose timing can steal — a funder able to refund
|
|
388
|
+
* before the claimant can claim takes money from someone holding the preimage
|
|
389
|
+
* — so it opens last, by {@link SOLO_REFUND_HEADROOM_SECONDS}. */
|
|
680
390
|
declare const unilateralRefundWithoutReceiverDelay: (claimDelay: number) => number;
|
|
681
391
|
/** Compile the lightning-send VHTLC from the quote's binding fields plus the
|
|
682
392
|
* trader's own data. `paymentHash` is the BOLT11 payment hash (`sha256(P)`,
|
|
@@ -754,13 +464,13 @@ interface InvoiceFacts {
|
|
|
754
464
|
* throws while nothing is funded. `RfqSwapManager` re-registers as a backstop
|
|
755
465
|
* for older records; a repeat write is a no-op.
|
|
756
466
|
*
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
*
|
|
763
|
-
*
|
|
467
|
+
* The `sender` key comes from the wallet — a fresh HD descriptor per call, or
|
|
468
|
+
* the wallet's static key — and is returned as `senderPubkey` plus `secrets`.
|
|
469
|
+
* `secrets` holds only a public descriptor; the signer re-derives from the
|
|
470
|
+
* wallet, so nothing secret is at rest. Persist `secrets` with the record
|
|
471
|
+
* anyway: it is how the refund signer is found again. `nonInteractiveRefund`
|
|
472
|
+
* recovers the funds even without it — but it needs the SOLVER's active
|
|
473
|
+
* cooperation, not just infrastructure uptime.
|
|
764
474
|
*/
|
|
765
475
|
declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, transport: RfqTransport, params: {
|
|
766
476
|
invoice: InvoiceFacts;
|
|
@@ -786,9 +496,9 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
|
|
|
786
496
|
refundAddress: string;
|
|
787
497
|
/** The VHTLC `sender` x-only key, bound into the covenant. Public. */
|
|
788
498
|
senderPubkey: Uint8Array;
|
|
789
|
-
/** How the `sender` key is recovered later. Persist it with the record
|
|
790
|
-
*
|
|
791
|
-
secrets:
|
|
499
|
+
/** How the `sender` key is recovered later. Persist it with the record;
|
|
500
|
+
* it holds nothing secret. */
|
|
501
|
+
secrets: ProvisionedKey;
|
|
792
502
|
}>;
|
|
793
503
|
/**
|
|
794
504
|
* Map an arkade↔arkade quote onto `createOffer` terms. The trader takes the
|
|
@@ -939,9 +649,10 @@ declare function requestOnchainSend(wallet: IWallet, arkServerUrl: string, trans
|
|
|
939
649
|
htlc: OnchainHtlc;
|
|
940
650
|
/** The VHTLC `sender` x-only key, bound into the covenant. Public. */
|
|
941
651
|
senderPubkey: Uint8Array;
|
|
942
|
-
/** How the preimage and the `sender` key are recovered later
|
|
943
|
-
*
|
|
944
|
-
|
|
652
|
+
/** How the preimage and the `sender` key are recovered later — map it
|
|
653
|
+
* through `swapSecretsToRecord` and persist BEFORE funding. Public unless
|
|
654
|
+
* `mustPersistPreimage` says the wallet could not derive P. */
|
|
655
|
+
secrets: ProvisionedClaimSecret;
|
|
945
656
|
}>;
|
|
946
657
|
/** Default floor for the window between the last moment the hold invoice can
|
|
947
658
|
* be paid and the solver's refund leaf opening. */
|
|
@@ -1128,9 +839,10 @@ declare function requestLightningReceive(wallet: IWallet, arkServerUrl: string,
|
|
|
1128
839
|
payoutAddress: string;
|
|
1129
840
|
/** The trader's covenant `receiver` key, bound into the tree. Public. */
|
|
1130
841
|
payoutPubkey: Uint8Array;
|
|
1131
|
-
/** How the preimage and the payout key are recovered later
|
|
1132
|
-
*
|
|
1133
|
-
|
|
842
|
+
/** How the preimage and the payout key are recovered later — map it
|
|
843
|
+
* through `swapSecretsToRecord` and persist BEFORE paying the invoice.
|
|
844
|
+
* Public unless `mustPersistPreimage` says the wallet could not derive P. */
|
|
845
|
+
secrets: ProvisionedClaimSecret;
|
|
1134
846
|
}>;
|
|
1135
847
|
/**
|
|
1136
848
|
* The pure core of {@link requestOnchainReceive}: derive BOTH contracts
|
|
@@ -1201,7 +913,10 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
|
|
|
1201
913
|
htlc: OnchainHtlc;
|
|
1202
914
|
payoutAddress: string;
|
|
1203
915
|
payoutPubkey: Uint8Array;
|
|
1204
|
-
|
|
916
|
+
/** How the preimage and the payout key are recovered later — map it
|
|
917
|
+
* through `swapSecretsToRecord` and persist BEFORE funding. Public unless
|
|
918
|
+
* `mustPersistPreimage` says the wallet could not derive P. */
|
|
919
|
+
secrets: ProvisionedClaimSecret;
|
|
1205
920
|
}>;
|
|
1206
921
|
|
|
1207
|
-
export {
|
|
922
|
+
export { onchainSendRequest as $, ARKADE_ASSET as A, awaitOnchainFill as B, type ChainSource as C, buildHtlcClaim as D, buildHtlcRefund as E, claimOnchainFill as F, classifyOnchainHtlc as G, type HtlcUtxo as H, type InvoiceFacts as I, deriveLightningReceive as J, deriveOnchainReceive as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, deriveOnchainSend as N, type OnchainHtlc as O, extractPreimage as P, httpTransport as Q, type RfqStatus as R, SOLO_REFUND_HEADROOM_SECONDS as S, lightningReceiveRequest as T, lightningSendRequest as U, lightningSendVtxoScript as V, newPreimage as W, newRfqId as X, offerTermsFromQuote as Y, onchainHtlcScript as Z, onchainReceiveRequest as _, type RfqTransport as a, paymentHashOf as a0, receiveVtxoScript as a1, relayTransport as a2, requestLightningReceive as a3, requestLightningSend as a4, requestOnchainReceive as a5, requestOnchainSend as a6, rfqPair as a7, unilateralClaimDelay as a8, unilateralRefundDelay as a9, unilateralRefundWithoutReceiverDelay as aa, verifyLockupAddress as ab, verifyReceiveInvoice as ac, type ChainUtxo as b, type OnchainHtlcPhase as c, ARKADE_BTC as d, AddressMismatch as e, LIGHTNING_RECEIVE_PAIR as f, LIGHTNING_SEND_PAIR as g, MIN_CLAIM_WINDOW_SECONDS as h, MIN_HEADROOM_SECONDS as i, ONCHAIN_BTC as j, ONCHAIN_CLAIM_MARGIN_SECONDS as k, ONCHAIN_DUST_SATS as l, ONCHAIN_ORDER_MARGIN_SECONDS as m, ONCHAIN_RECEIVE_PAIR as n, ONCHAIN_SECONDS_PER_BLOCK as o, ONCHAIN_SEND_PAIR as p, type OnchainHtlcParams as q, type OnchainNetwork as r, RFQ_TERMINAL_STATES as s, type RelaySocket as t, type RfqQuote as u, type RfqRefusalReason as v, SwapRefusal as w, arkadeSwapRequest as x, assertFundable as y, assertReceivable as z };
|