@ninsei-labs/sdk 0.52.0 → 0.54.0
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/CHANGELOG.md +266 -0
- package/README.md +83 -5
- package/engine/atomic/order-worker.js +29 -2
- package/engine/atomic/order.js +24 -0
- package/engine/core/store.js +60 -12
- package/engine/evm/funding.js +65 -18
- package/engine/monero/arrivalRead.js +3 -22
- package/engine/monero/halvesSweep.js +5 -1
- package/engine/monero/scan.js +144 -33
- package/index.d.ts +154 -26
- package/package.json +35 -3
- package/src/adapters/monero-wallet.mjs +13 -6
- package/src/adapters/monero.mjs +5 -7
- package/src/codes.mjs +4 -0
- package/src/config.mjs +6 -3
- package/src/decline.mjs +6 -1
- package/src/feeEstimate.mjs +20 -13
- package/src/index.mjs +7 -4
- package/src/legs/index.mjs +8 -0
- package/src/legs/profiles.mjs +51 -0
- package/src/lock.mjs +4 -6
- package/src/order.mjs +53 -7
- package/src/public/networks.d.ts +14 -1
- package/src/public/recovery.d.ts +53 -5
- package/src/public/recovery.mjs +6 -0
- package/src/public/xmr.d.ts +26 -8
- package/src/quotes.mjs +410 -3
- package/src/recovery-key.mjs +217 -39
- package/src/recovery.mjs +9 -1
- package/src/relayFeatures.mjs +191 -0
- package/src/relayFirmClient.mjs +86 -0
- package/src/relayQuote.mjs +209 -0
- package/src/relayRequest.mjs +188 -0
- package/src/relayTerms.mjs +145 -0
- package/src/relayView.mjs +110 -0
- package/src/swap-flow.mjs +3 -2
- package/src/swaps.mjs +402 -80
- package/src/sweep-fees.mjs +32 -0
- package/src/sweep-restore.mjs +30 -9
- package/src/sweep.mjs +28 -5
- package/src/version.mjs +1 -1
- package/src/xmr-arrival.mjs +76 -32
package/src/lock.mjs
CHANGED
|
@@ -99,12 +99,10 @@ export async function send(request, wallet, deps = {}) {
|
|
|
99
99
|
send: (tx) => wallet.send(tx),
|
|
100
100
|
// NORMALISING THE RECEIPT ARGUMENT'S SHAPE - HERE, AT THE CORE'S BOUNDARY, NOT AT EVERY CALLER.
|
|
101
101
|
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
// normalise the argument to a string here: funding.js is foreign code and must not be edited, and every
|
|
107
|
-
// adapter should not repeat the normalisation.
|
|
102
|
+
// funding.js calls the receipt with an OBJECT { hash } (waitReceipt), while the adapter contract declares
|
|
103
|
+
// receipt(txHash: string). A strict adapter (sdk/src/adapters/evm-wallet.mjs) answers bad-input to an object,
|
|
104
|
+
// the refusal is SWALLOWED by the receipt wait, and the address would silently fall back. We normalise the
|
|
105
|
+
// argument to a string at this boundary so every adapter sees one shape.
|
|
108
106
|
receipt: (arg) => wallet.receipt(typeof arg === "string" ? arg : (arg && typeof arg.hash === "string" ? arg.hash : arg)),
|
|
109
107
|
});
|
|
110
108
|
} catch (error) {
|
package/src/order.mjs
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
// THE COUNTERPARTY'S SIDE AND THE JOINT ADDRESS.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
3
|
+
// THREE CHECKS, ALL MANDATORY BEFORE SIGNING - after it there is nothing to fix:
|
|
4
4
|
//
|
|
5
5
|
// 1) the DLEQ proof stands in the CONTEXT OF THIS order: the counterparty proved for our terms, not for others.
|
|
6
6
|
// The context is the same one the quote signature is bound to (see quotes.firm);
|
|
7
7
|
// 2) the proven ed25519 point is THE VERY ONE that will go into the contract and from which the address is
|
|
8
8
|
// assembled. Without this check the counterparty could prove one thing and substitute another: on our side
|
|
9
9
|
// everything would look sound, and the discrepancy would surface when claiming the XMR, with nothing left to
|
|
10
|
-
// fix
|
|
10
|
+
// fix;
|
|
11
|
+
// 3) the proven secp256k1 point matches `commitHalfClaimer`, the commitment the contract compares on claim and
|
|
12
|
+
// refund. A proof without this comparison binds the wrong half and the escrow rejects it after the other side
|
|
13
|
+
// has paid.
|
|
11
14
|
//
|
|
12
|
-
//
|
|
15
|
+
// All three are done by the engine (order.js: the verifying code is the same for us and for the counterparty). The
|
|
13
16
|
// core has no cryptography of its own and should not: a copy would silently drift from the original.
|
|
14
17
|
import { SdkError } from "./errors.mjs";
|
|
15
18
|
import { primitives } from "./primitives.mjs";
|
|
@@ -86,6 +89,43 @@ const sameFormAsPoint = (proof) => (proof && typeof proof === "object" && proof.
|
|
|
86
89
|
// "no point", not "point in another form".
|
|
87
90
|
const pointForm = (v) => (typeof v === "string" && v ? norm(v) : v);
|
|
88
91
|
|
|
92
|
+
// THE COUNTERPARTY'S VIEW MATERIAL HAS TWO SPELLINGS, AND THEY MUST AGREE. A quote carries `viewHalfClaimer`
|
|
93
|
+
// (and sometimes `viewHalf`), a point as `viewPoint` or `viewPub`. The guard and the builder used to prefer
|
|
94
|
+
// different names: the guard took the half first and ignored the point, the builder took the point first. A
|
|
95
|
+
// counterparty could then supply a half and a different point, the address was built from one and the recovery
|
|
96
|
+
// words from the other. Normalise once, refuse conflicting aliases, and derive the point from the half when only
|
|
97
|
+
// the half is present.
|
|
98
|
+
export function normalizeCounterpartyView(counterparty) {
|
|
99
|
+
const cp = counterparty && typeof counterparty === "object" ? counterparty : {};
|
|
100
|
+
const halves = [cp.viewHalf, cp.viewHalfClaimer].filter((v) => v !== undefined && v !== null && v !== "");
|
|
101
|
+
let half = null;
|
|
102
|
+
if (halves.length) {
|
|
103
|
+
try { half = BigInt(String(halves[0])); } catch { throw new SdkError("bad-input", { field: "counterparty", why: "view-half" }); }
|
|
104
|
+
for (const other of halves.slice(1)) {
|
|
105
|
+
let n = null;
|
|
106
|
+
try { n = BigInt(String(other)); } catch { n = null; }
|
|
107
|
+
if (n === null || n !== half) throw new SdkError("bad-input", { field: "counterparty", why: "conflicting-view-half" });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const points = [cp.viewPoint, cp.viewPub].filter((v) => v !== undefined && v !== null && v !== "");
|
|
111
|
+
let point = null;
|
|
112
|
+
if (points.length) {
|
|
113
|
+
point = pointForm(points[0]);
|
|
114
|
+
if (!isPoint(point)) throw new SdkError("bad-input", { field: "counterparty", why: "view-point" });
|
|
115
|
+
for (const other of points.slice(1)) {
|
|
116
|
+
if (pointForm(other) !== point) throw new SdkError("bad-input", { field: "counterparty", why: "conflicting-view-point" });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (half !== null) {
|
|
120
|
+
let derived = null;
|
|
121
|
+
try { derived = pointForm(builder().pointOf(half)); } catch { derived = null; }
|
|
122
|
+
if (!derived) throw new SdkError("bad-input", { field: "counterparty", why: "view-half" });
|
|
123
|
+
if (point !== null && point !== derived) throw new SdkError("bad-input", { field: "counterparty", why: "view-half-point-mismatch" });
|
|
124
|
+
point = derived;
|
|
125
|
+
}
|
|
126
|
+
return { half: half === null ? null : halves[0], point };
|
|
127
|
+
}
|
|
128
|
+
|
|
89
129
|
/**
|
|
90
130
|
* Our side of the order. It is built by the engine's builder: two halves, their points, the DLEQ PROOF (it is
|
|
91
131
|
* bound to the order terms and so is not computed without the context) and the side's encryption key.
|
|
@@ -136,11 +176,12 @@ export function acceptCounterparty({ context, side = null, counterparty = null,
|
|
|
136
176
|
// (rfq/orderQuote.mjs). While only `edPub`/`viewPub` were accepted, the facade's own side was NOT accepted:
|
|
137
177
|
// start answered bad-input { field: "counterparty", missing: ["edPub"] } to its own answer. The engine knew
|
|
138
178
|
// this mapping (sdk/src/swap-flow.mjs: edPub: quote.edPointClaimer). We accept BOTH names.
|
|
179
|
+
const view = normalizeCounterpartyView(counterparty);
|
|
139
180
|
accepted = {
|
|
140
181
|
proof: sameFormAsPoint(counterparty.proof),
|
|
141
182
|
edPub: pointForm(counterparty.edPub || counterparty.edPoint || counterparty.edPointClaimer || pub.ed || null),
|
|
142
|
-
viewPoint:
|
|
143
|
-
viewHalf:
|
|
183
|
+
viewPoint: view.point,
|
|
184
|
+
viewHalf: view.half,
|
|
144
185
|
// THE COUNTERPARTY'S SPEND HALF: HIS commitment (commitHalfClaimer) is computed from it where it did not
|
|
145
186
|
// arrive ready-made. Without the half the commitment cannot be obtained - and that is named null, not invented.
|
|
146
187
|
half: counterparty.half !== undefined ? counterparty.half : null,
|
|
@@ -155,13 +196,18 @@ export function acceptCounterparty({ context, side = null, counterparty = null,
|
|
|
155
196
|
// not what the page runs on.
|
|
156
197
|
const mock = builder().newSide(context, true);
|
|
157
198
|
accepted = { proof: sameFormAsPoint(mock.proof), edPub: norm(mock.pub.ed), viewPoint: norm(mock.viewPub),
|
|
158
|
-
viewHalf: mock.viewHalf, half: mock.half,
|
|
199
|
+
viewHalf: mock.viewHalf, half: mock.half,
|
|
200
|
+
// THE STAND-IN DOES CARRY A COMMITMENT: it is derived from the half it just built, by the same formula
|
|
201
|
+
// the contract uses. The proof check below is therefore the real one, not a path that skips it.
|
|
202
|
+
commitHalfClaimer: norm(builder().halfCommitment(mock.half)), sealed: null, providerId: null, standIn: true, mock };
|
|
159
203
|
} else {
|
|
160
204
|
throw new SdkError("bad-input", { field: "counterparty" });
|
|
161
205
|
}
|
|
162
206
|
const missing = [];
|
|
163
207
|
if (!accepted.proof) missing.push("proof");
|
|
164
208
|
if (!accepted.edPub) missing.push("edPub");
|
|
209
|
+
// THE COMMITMENT IS NOT OPTIONAL. Without it the proof says nothing about the half the contract will compare.
|
|
210
|
+
if (!accepted.commitHalfClaimer) missing.push("commitHalfClaimer");
|
|
165
211
|
if (missing.length) throw new SdkError("bad-input", { field: "counterparty", missing });
|
|
166
212
|
// OPENING THE SEALED PACKAGE - BY THE SAME ENGINE CALL, and the key is OURS (the package is addressed to us).
|
|
167
213
|
// The envelope's composition is locked separately (www/js/atomic/halfenc.js, HALFENC_LOCK_REASON): in the live
|
|
@@ -169,7 +215,7 @@ export function acceptCounterparty({ context, side = null, counterparty = null,
|
|
|
169
215
|
// with a refusal rather than passing itself off as a working key handover.
|
|
170
216
|
const ownEncPriv = accepted.sealed && side && side.enc ? side.enc.priv : null;
|
|
171
217
|
let verdict = null;
|
|
172
|
-
try { verdict = builder().verifySide({ proof: accepted.proof, pub: { ed: accepted.edPub } }, context, accepted.sealed, ownEncPriv); }
|
|
218
|
+
try { verdict = builder().verifySide({ proof: accepted.proof, pub: { ed: accepted.edPub }, commitHalfClaimer: accepted.commitHalfClaimer }, context, accepted.sealed, ownEncPriv); }
|
|
173
219
|
catch { throw new SdkError("bad-input", { field: "counterparty" }); }
|
|
174
220
|
if (!verdict || verdict.ok !== true) {
|
|
175
221
|
throw new SdkError("quote-refused", { step: "proof", why: verdict && verdict.reason ? "rejected" : "unknown" });
|
package/src/public/networks.d.ts
CHANGED
|
@@ -21,10 +21,23 @@ export interface ChainUniswap {
|
|
|
21
21
|
[field: string]: unknown;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/** What a settlement side looks like: address format, account/UTXO settlement and reference shape. Metadata, not a
|
|
25
|
+
* claim that a driver exists. */
|
|
26
|
+
export interface SettlementProfile {
|
|
27
|
+
vm: string;
|
|
28
|
+
addressFormat: string;
|
|
29
|
+
settlementKind: "contract" | "program" | "utxo-script" | string;
|
|
30
|
+
refKind: "address" | "pda" | "script" | string;
|
|
31
|
+
txRef: "hash" | "signature" | "txid" | string;
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
export interface Chain {
|
|
25
35
|
id: string;
|
|
26
36
|
name: string;
|
|
27
|
-
|
|
37
|
+
/** A registry chain names its VM; the type allows null so an unknown network is never read as EVM. */
|
|
38
|
+
vm: string | null;
|
|
39
|
+
/** Present when the VM has a profile; unknown VMs are null, never silently EVM. */
|
|
40
|
+
settlementProfile?: SettlementProfile | null;
|
|
28
41
|
chainId: number;
|
|
29
42
|
caip2?: string;
|
|
30
43
|
testnet?: boolean;
|
package/src/public/recovery.d.ts
CHANGED
|
@@ -269,12 +269,16 @@ export declare function recoveryFileName(swapId?: string | null): string;
|
|
|
269
269
|
export declare const RECOVERY_KEY_VERSION: number;
|
|
270
270
|
/** Twelve words, by the BIP39 rules. */
|
|
271
271
|
export declare const RECOVERY_KEY_WORDS: number;
|
|
272
|
+
/** The default number of v1 indices one `findSwaps` call scans. */
|
|
273
|
+
export declare const RECOVERY_SCAN_DEFAULT: number;
|
|
272
274
|
/** The store key a browser adapter keeps the key under. */
|
|
273
275
|
export declare const RECOVERY_KEY_STORE: string;
|
|
274
276
|
/** The first line of a plain backup file. */
|
|
275
277
|
export declare const RECOVERY_KEY_FILE_MAGIC: string;
|
|
276
278
|
/** The domain half derivation binds to; the chain id and swap number join it. */
|
|
277
279
|
export declare const RECOVERY_KEY_DOMAIN: string;
|
|
280
|
+
/** The salt-based derivation domain; the chain, factory, role and order salt join it. */
|
|
281
|
+
export declare const RECOVERY_KEY_DOMAIN_V2: string;
|
|
278
282
|
/** The domain of the counterparty's view half, derived from the same one key. */
|
|
279
283
|
export declare const MAKER_VIEW_HALF_DOMAIN: string;
|
|
280
284
|
/** The encrypted backup envelope version. */
|
|
@@ -290,6 +294,8 @@ export interface RecoveryKey {
|
|
|
290
294
|
readonly mnemonic: string;
|
|
291
295
|
readonly fingerprint: string;
|
|
292
296
|
readonly createdAt: string;
|
|
297
|
+
/** True only after the person confirmed that the key is saved; a key in storage is not proof of that. */
|
|
298
|
+
readonly backupConfirmed?: boolean;
|
|
293
299
|
}
|
|
294
300
|
|
|
295
301
|
/** A derived swap number: the halves cross JSON as hex scalars. */
|
|
@@ -305,6 +311,15 @@ export interface TakerHalves {
|
|
|
305
311
|
readonly spendCommitment: string;
|
|
306
312
|
}
|
|
307
313
|
|
|
314
|
+
/** A salt-based derivation: no number is reserved, and the public order salt is the input. */
|
|
315
|
+
export interface TakerHalvesV2 extends Omit<TakerHalves, "index"> {
|
|
316
|
+
readonly index: null;
|
|
317
|
+
readonly derivation: "salt-v2";
|
|
318
|
+
readonly factory: string;
|
|
319
|
+
readonly role: string;
|
|
320
|
+
readonly salt: string;
|
|
321
|
+
}
|
|
322
|
+
|
|
308
323
|
/** One order found by the key's commitments. */
|
|
309
324
|
export interface FoundSwap {
|
|
310
325
|
readonly escrow: string;
|
|
@@ -338,12 +353,17 @@ export interface FoundSwap {
|
|
|
338
353
|
* the expected clone. */
|
|
339
354
|
readonly xmrAmount: string | null;
|
|
340
355
|
readonly xmrAmountReason: "event" | "no-code-reader" | "code" | "not-clone" | null;
|
|
341
|
-
|
|
356
|
+
/** The v1 swap number; null for a salt-based v2 order. */
|
|
357
|
+
readonly index: number | null;
|
|
358
|
+
/** Which derivation found this order. v1 orders keep recovering through the index path. */
|
|
359
|
+
readonly derivation: "index-v1" | "salt-v2";
|
|
360
|
+
/** The factory the order was read from; the v2 binding needs it. */
|
|
361
|
+
readonly factory: string;
|
|
342
362
|
readonly side: "locker" | "claimer";
|
|
343
363
|
/** The Monero height a withdrawal may start from, derived from the order's block time. Null when the caller did
|
|
344
364
|
* not pass the readers; `startHeightReason` then names why. */
|
|
345
365
|
readonly startHeight: number | null;
|
|
346
|
-
readonly startHeightReason: "no-block-number" | "no-height-readers" | "monero-nodes-unreachable" | "monero-network-mismatch" | "no-block-time" | "monero-header" | null;
|
|
366
|
+
readonly startHeightReason: "no-block-number" | "no-height-readers" | "monero-nodes-unreachable" | "monero-network-mismatch" | "no-block-time" | "block-time-read" | "monero-header" | null;
|
|
347
367
|
}
|
|
348
368
|
|
|
349
369
|
/** A storage adapter: the same shape the SDK store takes. */
|
|
@@ -361,8 +381,16 @@ export declare function importRecoveryKey(mnemonic: string, options?: { createdA
|
|
|
361
381
|
export declare function fingerprintOf(mnemonic: string): string;
|
|
362
382
|
/** The binding for a chain and swap number: `ninsei-taker-v1|<chainId>|<index>`. */
|
|
363
383
|
export declare function recoveryBinding(chainId: number, index: number): string;
|
|
384
|
+
/** The salt-based binding: `ninsei-taker-v2|<chainId>|<factory>|<role>|<salt>`. */
|
|
385
|
+
export declare function recoveryBindingV2(request: { chainId: number; factory: string; role?: string; salt: string }): string;
|
|
386
|
+
/** Normalises a 32-byte salt from an event word, a hex string, a bigint or a safe integer. */
|
|
387
|
+
export declare function recoverySaltOf(value: string | number | bigint): string;
|
|
388
|
+
/** A fresh 32-byte public salt for one salt-based order. */
|
|
389
|
+
export declare function newRecoverySalt(): string;
|
|
364
390
|
/** Derives the taker spend and view halves for one swap number. */
|
|
365
391
|
export declare function takerHalves(request: { mnemonic: string; chainId: number; index: number }): TakerHalves;
|
|
392
|
+
/** Derives the taker halves from a public per-order salt; no index is reserved. */
|
|
393
|
+
export declare function takerHalvesV2(request: { mnemonic: string; chainId: number; factory: string; role?: string; salt: string }): TakerHalvesV2;
|
|
366
394
|
/** The stable backup name, with `DO-NOT-DELETE` in it on purpose. */
|
|
367
395
|
export declare function recoveryKeyFileName(request: { mnemonic?: string; fingerprint?: string; createdAt?: string | Date }): string;
|
|
368
396
|
/** A plain backup file: readable header above the words. */
|
|
@@ -372,9 +400,9 @@ export declare function createRecoveryKeyFile(request: { mnemonic: string; creat
|
|
|
372
400
|
/** Reads a plain or encrypted backup file and validates the words. */
|
|
373
401
|
export declare function openRecoveryKeyFile(contents: string, passphrase?: string): Promise<RecoveryKey>;
|
|
374
402
|
/** Saves the key through a storage adapter. */
|
|
375
|
-
export declare function saveRecoveryKey(storage: RecoveryKeyStorage, key: RecoveryKey & { nextIndex?: number; reserved?: Record<string, unknown>; retired?: Record<string, unknown
|
|
403
|
+
export declare function saveRecoveryKey(storage: RecoveryKeyStorage, key: RecoveryKey & { nextIndex?: number; reserved?: Record<string, unknown>; retired?: Record<string, unknown>; backupConfirmed?: boolean }): RecoveryKey;
|
|
376
404
|
/** Reads the key from a storage adapter, or null. */
|
|
377
|
-
export declare function loadRecoveryKey(storage: RecoveryKeyStorage): (RecoveryKey & { nextIndex: number; reserved: Record<string, unknown>; retired: Record<string, unknown
|
|
405
|
+
export declare function loadRecoveryKey(storage: RecoveryKeyStorage): (RecoveryKey & { nextIndex: number; reserved: Record<string, unknown>; retired: Record<string, unknown>; backupConfirmed?: boolean }) | null;
|
|
378
406
|
/** Reserves a swap number; the caller releases it if the request is abandoned. */
|
|
379
407
|
export declare function reserveRecoveryIndex(storage: RecoveryKeyStorage, request: { chainId: number; swapId?: string | null }): number;
|
|
380
408
|
/** True when an order already holds this number's commitment on chain. A page that starts swaps without the SDK's
|
|
@@ -403,8 +431,17 @@ export declare function findSwaps(request: {
|
|
|
403
431
|
/** The factory's deployment block from the chain registry; used when `fromBlock` is omitted. */
|
|
404
432
|
deploymentBlock?: number | null;
|
|
405
433
|
toBlock?: number | string;
|
|
434
|
+
/** Deprecated and ignored: discovery no longer stops after a run of empty numbers. */
|
|
406
435
|
gap?: number;
|
|
436
|
+
/** The first index to try. Defaults to 0; a continuation passes the previous `nextIndex`. */
|
|
437
|
+
fromIndex?: number;
|
|
438
|
+
/** How many indices this call may try. Defaults to `RECOVERY_SCAN_DEFAULT` (1000), not the allocator ceiling. */
|
|
407
439
|
maxIndex?: number;
|
|
440
|
+
/** Stop the scan between chunks. An aborted scan returns `complete: false`, `incompleteReason: "aborted"` and
|
|
441
|
+
* the `nextIndex` to resume from. */
|
|
442
|
+
signal?: { readonly aborted: boolean } | null;
|
|
443
|
+
/** Called after every chunk and after the last index, with the count and the index just scanned. */
|
|
444
|
+
onProgress?: ((value: { readonly scanned: number; readonly index: number }) => void) | null;
|
|
408
445
|
/** Reads the settlement block timestamp, in seconds: (blockNumber) -> seconds. */
|
|
409
446
|
evmBlockTime?: (blockNumber: number) => Promise<number>;
|
|
410
447
|
/** Reads contract code: (address) -> 0x-hex. Used to read the XMR amount from an order clone. */
|
|
@@ -420,4 +457,15 @@ export declare function findSwaps(request: {
|
|
|
420
457
|
moneroNetwork?: string | null;
|
|
421
458
|
/** The fetch used for those node requests; absent - the global fetch. */
|
|
422
459
|
fetchImpl?: typeof fetch;
|
|
423
|
-
}): Promise<{
|
|
460
|
+
}): Promise<{
|
|
461
|
+
swaps: FoundSwap[];
|
|
462
|
+
scanned: number;
|
|
463
|
+
/** The last index tried, or null when no index was scanned. */
|
|
464
|
+
searchedUpTo: number | null;
|
|
465
|
+
/** True when every order in the logs was matched, or when the allocator range was searched to its end. */
|
|
466
|
+
complete: boolean;
|
|
467
|
+
/** `max-index` or `aborted` when a bound or the caller stopped the search before every order was matched. */
|
|
468
|
+
incompleteReason?: string;
|
|
469
|
+
/** The next index to pass as `fromIndex`; absent when the search is complete. */
|
|
470
|
+
nextIndex?: number;
|
|
471
|
+
}>;
|
package/src/public/recovery.mjs
CHANGED
|
@@ -25,6 +25,7 @@ export {
|
|
|
25
25
|
export {
|
|
26
26
|
RECOVERY_KEY_ALG,
|
|
27
27
|
RECOVERY_KEY_DOMAIN,
|
|
28
|
+
RECOVERY_KEY_DOMAIN_V2,
|
|
28
29
|
RECOVERY_KEY_ENVELOPE_VERSION,
|
|
29
30
|
RECOVERY_KEY_FILE_MAGIC,
|
|
30
31
|
RECOVERY_KEY_ITER,
|
|
@@ -32,6 +33,7 @@ export {
|
|
|
32
33
|
RECOVERY_KEY_VERSION,
|
|
33
34
|
MAKER_VIEW_HALF_DOMAIN,
|
|
34
35
|
RECOVERY_KEY_WORDS,
|
|
36
|
+
RECOVERY_SCAN_DEFAULT,
|
|
35
37
|
commitRecoveryIndex,
|
|
36
38
|
createRecoveryKey,
|
|
37
39
|
createRecoveryKeyFile,
|
|
@@ -39,13 +41,17 @@ export {
|
|
|
39
41
|
fingerprintOf,
|
|
40
42
|
importRecoveryKey,
|
|
41
43
|
loadRecoveryKey,
|
|
44
|
+
newRecoverySalt,
|
|
42
45
|
openRecoveryKeyFile,
|
|
43
46
|
recoveryBinding,
|
|
47
|
+
recoveryBindingV2,
|
|
44
48
|
recoveryIndexTaken,
|
|
49
|
+
recoverySaltOf,
|
|
45
50
|
recoveryKeyFileName,
|
|
46
51
|
recoveryKeyText,
|
|
47
52
|
releaseRecoveryIndex,
|
|
48
53
|
reserveRecoveryIndex,
|
|
49
54
|
saveRecoveryKey,
|
|
50
55
|
takerHalves,
|
|
56
|
+
takerHalvesV2,
|
|
51
57
|
} from "../recovery-key.mjs";
|
package/src/public/xmr.d.ts
CHANGED
|
@@ -407,17 +407,18 @@ export declare function judgeDaemonAddress(
|
|
|
407
407
|
options?: { network?: string; allowPlainLoopback?: boolean },
|
|
408
408
|
): DaemonAddressJudgement;
|
|
409
409
|
|
|
410
|
-
/** A per-
|
|
411
|
-
export declare function feeForBytes(
|
|
410
|
+
/** A per-byte price -> the fee for a transaction of `bytes`/weight. Exact integer multiplication. */
|
|
411
|
+
export declare function feeForBytes(feePerByte: bigint | number | string, bytes: bigint | number | string): string;
|
|
412
412
|
|
|
413
413
|
export interface FeeEstimateOk {
|
|
414
414
|
readonly ok: true;
|
|
415
415
|
readonly url: string;
|
|
416
|
-
/** The price per
|
|
417
|
-
readonly
|
|
418
|
-
|
|
419
|
-
/** The daemon's own priority list, in its order, or null. */
|
|
416
|
+
/** The price per byte for the next block, in atomic units, or null when the daemon did not send it. */
|
|
417
|
+
readonly feePerByte: string | null;
|
|
418
|
+
/** The daemon's own priority list, per byte and in its order, or null. */
|
|
420
419
|
readonly perPriority: readonly string[] | null;
|
|
420
|
+
/** The unit the final fee is rounded to, or null when the daemon did not send it. */
|
|
421
|
+
readonly quantizationMask: string | null;
|
|
421
422
|
}
|
|
422
423
|
|
|
423
424
|
export interface FeeEstimateRefusal {
|
|
@@ -430,7 +431,7 @@ export interface FeeEstimateRefusal {
|
|
|
430
431
|
|
|
431
432
|
/**
|
|
432
433
|
* ASK A NODE WHAT A TRANSACTION WILL COST (`get_fee_estimate`). The exact sum needs the assembled transaction, so
|
|
433
|
-
* this is a price per
|
|
434
|
+
* this is a price per byte; `feeForBytes` is the only arithmetic that turns it into a fee. Never throws.
|
|
434
435
|
*/
|
|
435
436
|
export declare function moneroFeeEstimate(options: {
|
|
436
437
|
url: string;
|
|
@@ -483,6 +484,19 @@ export interface ScannedMatch {
|
|
|
483
484
|
[field: string]: unknown;
|
|
484
485
|
}
|
|
485
486
|
|
|
487
|
+
/** A range scan's answer: the per-address totals and whether every block was read. */
|
|
488
|
+
export interface ScanRangeResult {
|
|
489
|
+
readonly fromHeight: number;
|
|
490
|
+
readonly toHeight: number;
|
|
491
|
+
readonly results: ScannedMatch[];
|
|
492
|
+
/** False when at least one block or its transactions could not be read. */
|
|
493
|
+
readonly complete: boolean;
|
|
494
|
+
/** The heights that failed; empty when `complete` is true. */
|
|
495
|
+
readonly missingHeights: number[];
|
|
496
|
+
/** `blocks-unreadable` when `complete` is false. */
|
|
497
|
+
readonly incompleteReason?: "blocks-unreadable";
|
|
498
|
+
}
|
|
499
|
+
|
|
486
500
|
/** Walk a block range and return the transactions that pay a watched address. */
|
|
487
501
|
export declare function scanRange(options: {
|
|
488
502
|
daemonUrl: string;
|
|
@@ -492,4 +506,8 @@ export declare function scanRange(options: {
|
|
|
492
506
|
log?: (event: unknown) => void;
|
|
493
507
|
concurrency?: number;
|
|
494
508
|
nowSec?: number | null;
|
|
495
|
-
|
|
509
|
+
/** The chain tip used to judge a height lock; defaults to `toHeight`. Inclusion height still drives confirmations. */
|
|
510
|
+
tipHeight?: number | null;
|
|
511
|
+
/** The fetch used for the daemon requests; absent - the global fetch. */
|
|
512
|
+
fetchImpl?: typeof fetch;
|
|
513
|
+
}): Promise<ScanRangeResult>;
|