@ninsei-labs/sdk 0.40.0 → 0.42.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 +37 -0
- package/README.md +11 -0
- package/engine/core/config.js +1 -1
- package/engine/evm/factory.js +0 -12
- package/engine/evm/funding.js +6 -22
- package/engine/evm/index.js +3 -7
- package/engine/evm/permit.js +3 -3
- package/engine/evm/session.js +3 -5
- package/engine/sdk/bridge.js +1 -1
- package/index.d.ts +53 -0
- package/package.json +25 -3
- package/src/index.mjs +1 -0
- package/src/public/core.d.ts +13 -0
- package/src/public/core.mjs +6 -0
- package/src/public/evm.d.ts +184 -0
- package/src/public/evm.mjs +29 -0
- package/src/public/order.d.ts +161 -0
- package/src/public/order.mjs +22 -0
- package/src/public/recovery.d.ts +243 -0
- package/src/public/recovery.mjs +19 -0
- package/src/public/xmr.d.ts +318 -0
- package/src/public/xmr.mjs +29 -0
- package/src/quoteEip712Spec.mjs +1 -1
- package/src/swap-flow.mjs +0 -7
- package/src/version.mjs +9 -0
- package/engine/evm/depositor.js +0 -123
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// DECLARATIONS FOR THE `./order` ENTRY: what a signature commits to, and the quote types it commits under.
|
|
2
|
+
//
|
|
3
|
+
// src/public/order.mjs only NAMES what the engine already offers; these declarations NAME the same thing for a
|
|
4
|
+
// TypeScript consumer. Every signature is copied from the modules the barrel re-exports
|
|
5
|
+
// (`../../engine/atomic/orderContext.js`, `../../engine/atomic/orderHalfCommit.js`,
|
|
6
|
+
// `../quoteEip712Spec.mjs`), and a symbol the barrel does not re-export is not declared here.
|
|
7
|
+
|
|
8
|
+
/** The order conditions a context is built from. Numbers may be decimal text, hex text or a bigint: one order. */
|
|
9
|
+
export interface OrderContextFields {
|
|
10
|
+
/** The network: the same order on another network is another order. */
|
|
11
|
+
readonly chainId: string | number | bigint;
|
|
12
|
+
/** The factory that creates the escrow. */
|
|
13
|
+
readonly factory: string;
|
|
14
|
+
/** The address that deposits the settlement coin. */
|
|
15
|
+
readonly locker: string;
|
|
16
|
+
/** The address the contract pays. */
|
|
17
|
+
readonly claimer: string;
|
|
18
|
+
/** The amount in wei. */
|
|
19
|
+
readonly amount: string | number | bigint;
|
|
20
|
+
/** The readiness deadline. */
|
|
21
|
+
readonly readyBy: string | number | bigint;
|
|
22
|
+
/** The settlement deadline. */
|
|
23
|
+
readonly t1: string | number | bigint;
|
|
24
|
+
/** The order salt. */
|
|
25
|
+
readonly salt: string | number | bigint;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The prefix that separates the order context from any other signature or proof, and the version of its field
|
|
30
|
+
* set. It moves only together with that set, so a proof made under an older prefix never verifies under this one.
|
|
31
|
+
*/
|
|
32
|
+
export declare const ORDER_CONTEXT_VERSION: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The canonical context string the DLEQ proof binds to, built from the order fields alone and identically in
|
|
36
|
+
* every implementation, so the proof can be checked from the on-chain order.
|
|
37
|
+
*
|
|
38
|
+
* Refuses (throws) an object without the fields: a partial set is not a context.
|
|
39
|
+
*/
|
|
40
|
+
export declare function orderContextString(order: OrderContextFields): string;
|
|
41
|
+
|
|
42
|
+
/** The secp256k1 members the half commitment calls: the base point and its uncompressed encoding. */
|
|
43
|
+
export interface Secp256k1BasePoint {
|
|
44
|
+
readonly multiply: (scalar: bigint) => { readonly toBytes: (isCompressed: boolean) => Uint8Array };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The secp256k1 primitive, as the engine and the SDK's own `primitives` module hand it in. */
|
|
48
|
+
export interface Secp256k1Primitive {
|
|
49
|
+
readonly Point: { readonly BASE: Secp256k1BasePoint };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** keccak256 over bytes - the same function Solidity's `keccak256` computes. */
|
|
53
|
+
export type Keccak256 = (bytes: Uint8Array) => Uint8Array;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The commitment to a half: `keccak256(x || y)` of the secp256k1 point `half*G`, taken UNCOMPRESSED (64 bytes,
|
|
57
|
+
* big-byte-first, like Ethereum key coordinates). The chain compares the presented half against the POINT behind
|
|
58
|
+
* this hash, not against a hash of the number, so this formula must match everywhere it is computed.
|
|
59
|
+
*/
|
|
60
|
+
export declare function halfCommitmentHex(
|
|
61
|
+
half: bigint | string | number,
|
|
62
|
+
secp256k1: Secp256k1Primitive,
|
|
63
|
+
keccak256: Keccak256,
|
|
64
|
+
): string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The crypto the quote spec is bound to. The spec signs nothing itself: it is handed keccak256 and secp256k1 -
|
|
68
|
+
* the same two the SDK's `primitives` module exports.
|
|
69
|
+
*/
|
|
70
|
+
export interface QuoteCrypto {
|
|
71
|
+
readonly keccak256: (bytes: Uint8Array) => Uint8Array;
|
|
72
|
+
readonly secp256k1: {
|
|
73
|
+
/** A signature over the digest, `format: "recovered"`, as 65 bytes [recovery, r, s]. */
|
|
74
|
+
readonly sign: (
|
|
75
|
+
message: Uint8Array,
|
|
76
|
+
privateKey: Uint8Array,
|
|
77
|
+
options?: { readonly format?: string; readonly prehash?: boolean },
|
|
78
|
+
) => Uint8Array;
|
|
79
|
+
readonly Signature: {
|
|
80
|
+
readonly fromBytes: (bytes: Uint8Array) => {
|
|
81
|
+
readonly addRecoveryBit: (bit: number) => {
|
|
82
|
+
readonly recoverPublicKey: (message: Uint8Array) => { readonly toBytes: (isCompressed: boolean) => Uint8Array };
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A signed quote: the fields the provider's signature covers, the factory the EIP-712 domain names, and the
|
|
91
|
+
* signature itself. Field names and values are the protocol's; a missing field is refused, never read as zero.
|
|
92
|
+
*/
|
|
93
|
+
export interface OrderQuote {
|
|
94
|
+
readonly provider: string;
|
|
95
|
+
readonly quoteKey: string;
|
|
96
|
+
readonly registry: string;
|
|
97
|
+
readonly cashier: string;
|
|
98
|
+
readonly locker: string;
|
|
99
|
+
readonly claimer: string;
|
|
100
|
+
readonly amount: string | number | bigint;
|
|
101
|
+
readonly readyBy: string | number | bigint;
|
|
102
|
+
readonly t1: string | number | bigint;
|
|
103
|
+
readonly salt: string;
|
|
104
|
+
readonly commitHalfClaimer: string;
|
|
105
|
+
readonly edPointClaimer: string;
|
|
106
|
+
readonly chainId: string | number | bigint;
|
|
107
|
+
readonly feeBps: string | number | bigint;
|
|
108
|
+
readonly fee: string | number | bigint;
|
|
109
|
+
readonly feeRecipient: string;
|
|
110
|
+
readonly validUntil: string | number | bigint;
|
|
111
|
+
readonly nonce: string | number | bigint;
|
|
112
|
+
readonly xmrAmount: string | number | bigint;
|
|
113
|
+
/** The escrow factory the domain names as `verifyingContract`. */
|
|
114
|
+
readonly factory: string;
|
|
115
|
+
/** r || s || v over the digest, 65 bytes, with or without the `0x` prefix; v is normalised to 27/28. */
|
|
116
|
+
readonly signature: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The EIP-712 domain type string, assembled from its parts. */
|
|
120
|
+
export declare const EIP712_DOMAIN_TYPE: string;
|
|
121
|
+
|
|
122
|
+
/** The domain name and its version string: the domain's identity, not the message shape. */
|
|
123
|
+
export declare const ORDER_QUOTE_DOMAIN_NAME: string;
|
|
124
|
+
export declare const ORDER_QUOTE_DOMAIN_VERSION: string;
|
|
125
|
+
|
|
126
|
+
/** The request-shape generation label. It moves WITH the signed field set; the domain identity does not. */
|
|
127
|
+
export declare const ORDER_QUOTE_VERSION: number;
|
|
128
|
+
|
|
129
|
+
/** `[name, type]` pairs IN CONTRACT ORDER. The order is the protocol: a rearrangement moves every digest. */
|
|
130
|
+
export declare const ORDER_QUOTE_FIELDS: readonly (readonly [string, string])[];
|
|
131
|
+
|
|
132
|
+
/** The message type string, assembled from `ORDER_QUOTE_FIELDS`. */
|
|
133
|
+
export declare const ORDER_QUOTE_TYPE: string;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Names of the signed-set fields (`factory` and `signature` included) the quote does not carry. A non-empty
|
|
137
|
+
* answer means the quote is not verifiable at all.
|
|
138
|
+
*/
|
|
139
|
+
export declare function quoteMissingFields(quote: Partial<OrderQuote> | null | undefined): string[];
|
|
140
|
+
|
|
141
|
+
/** The EIP-712 domain separator, with `chainId` and the factory taken live from the quote. */
|
|
142
|
+
export declare function quoteDomainSeparator(request: { readonly crypto: QuoteCrypto; readonly quote: OrderQuote }): Uint8Array;
|
|
143
|
+
|
|
144
|
+
/** The hash of the message struct. */
|
|
145
|
+
export declare function quoteStructHash(request: { readonly crypto: QuoteCrypto; readonly quote: OrderQuote }): Uint8Array;
|
|
146
|
+
|
|
147
|
+
/** The digest the provider's key signs: `0x1901` || domain separator || struct hash. */
|
|
148
|
+
export declare function quoteDigest(request: { readonly crypto: QuoteCrypto; readonly quote: OrderQuote }): Uint8Array;
|
|
149
|
+
|
|
150
|
+
/** The signature on the wire: r || s || v with v in {27, 28}, `0x`-prefixed. */
|
|
151
|
+
export declare function signQuoteDigest(request: {
|
|
152
|
+
readonly crypto: QuoteCrypto;
|
|
153
|
+
readonly digest: Uint8Array;
|
|
154
|
+
readonly privateKey: string;
|
|
155
|
+
}): string;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The address that signed the quote, recovered without knowing it beforehand, or null when the quote cannot be
|
|
159
|
+
* verified at all. Null is a refusal for the caller to name, never consent.
|
|
160
|
+
*/
|
|
161
|
+
export declare function recoverQuoteKey(request: { readonly crypto: QuoteCrypto; readonly quote: OrderQuote }): string | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// THE ORDER SIDE: what a signature commits to, and the quote types it commits under.
|
|
2
|
+
//
|
|
3
|
+
// The canonical context string, the commitment on a half key, the EIP-712 quote types and digests. Same rule
|
|
4
|
+
// as ./xmr: names only, no second implementation, no browser.
|
|
5
|
+
|
|
6
|
+
export { ORDER_CONTEXT_VERSION, orderContextString } from "../../engine/atomic/orderContext.js";
|
|
7
|
+
export { halfCommitmentHex } from "../../engine/atomic/orderHalfCommit.js";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
EIP712_DOMAIN_TYPE,
|
|
11
|
+
ORDER_QUOTE_DOMAIN_NAME,
|
|
12
|
+
ORDER_QUOTE_DOMAIN_VERSION,
|
|
13
|
+
ORDER_QUOTE_FIELDS,
|
|
14
|
+
ORDER_QUOTE_TYPE,
|
|
15
|
+
ORDER_QUOTE_VERSION,
|
|
16
|
+
quoteDigest,
|
|
17
|
+
quoteDomainSeparator,
|
|
18
|
+
quoteMissingFields,
|
|
19
|
+
quoteStructHash,
|
|
20
|
+
recoverQuoteKey,
|
|
21
|
+
signQuoteDigest,
|
|
22
|
+
} from "../quoteEip712Spec.mjs";
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// DECLARATIONS FOR THE `./recovery` ENTRY: the recovery file as it travels - the envelope a wallet writes and a
|
|
2
|
+
// sweep page reads back.
|
|
3
|
+
//
|
|
4
|
+
// src/public/recovery.mjs only NAMES what the engine already offers; these declarations NAME the same thing for a
|
|
5
|
+
// TypeScript consumer. Every signature is copied from the module the barrel re-exports
|
|
6
|
+
// (`engine/recovery/recoveryFile.js`, itself a generated byte-for-byte copy of the engine source), and a symbol
|
|
7
|
+
// the barrel does not re-export is not declared here.
|
|
8
|
+
//
|
|
9
|
+
// NO DOM AND NO ARGUMENTS: the module touches WebCrypto (`crypto.subtle`), `btoa`/`atob` and the text encoders,
|
|
10
|
+
// so the environment hands those in and nothing has to be passed as a parameter here.
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The envelope version (encryption) - NOT the payload version inside it. 1 is a file written without AAD, 2 is a
|
|
14
|
+
* file whose header is authenticated. Both stay readable: people hold version-1 files, and a recovery file is the
|
|
15
|
+
* only way to claim their XMR.
|
|
16
|
+
*/
|
|
17
|
+
export declare const ENVELOPE_VERSION: number;
|
|
18
|
+
|
|
19
|
+
/** The payload version (deal content), raised independently of the envelope: 1 keys as fields, 2 the mnemonic, 3 halves. */
|
|
20
|
+
export declare const PAYLOAD_VERSION: number;
|
|
21
|
+
|
|
22
|
+
/** The mark every Ninsei recovery file carries in its payload, so a foreign file is refused by name. */
|
|
23
|
+
export declare const FILE_MAGIC: string;
|
|
24
|
+
|
|
25
|
+
/** The deal fields of the envelope header that sit under authentication (`meta`). Each one is optional: a header without `meta` is still a header. */
|
|
26
|
+
export interface RecoveryEnvelopeMeta {
|
|
27
|
+
/** The deal id the file belongs to. */
|
|
28
|
+
readonly id?: string | null;
|
|
29
|
+
/** The side of the deal the file was issued for. */
|
|
30
|
+
readonly side?: string | null;
|
|
31
|
+
/** When the file was written, as the deal record carries it. */
|
|
32
|
+
readonly createdAt?: string | number | null;
|
|
33
|
+
/** The order terms hash from the contract: the file's tie to the chain. */
|
|
34
|
+
readonly termsHash?: string | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The envelope header BEFORE encryption: the same fields also form the AAD of the ciphertext, which is why the writer and the reader build them from one place. */
|
|
38
|
+
export interface RecoveryEnvelopeHeader {
|
|
39
|
+
readonly v: number;
|
|
40
|
+
/** The algorithm identifier: one string for the whole module. */
|
|
41
|
+
readonly alg: string;
|
|
42
|
+
/** The PBKDF2 iteration count, read FROM THE FILE on decryption so it can be raised without losing already issued files. */
|
|
43
|
+
readonly iter: number;
|
|
44
|
+
/** The PBKDF2 salt, base64. */
|
|
45
|
+
readonly salt: string;
|
|
46
|
+
/** The AES-GCM IV, base64. */
|
|
47
|
+
readonly iv: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The recovery file object as it is written (`ninsei-<id>.json.enc`) and read back. */
|
|
51
|
+
export interface RecoveryEnvelope extends RecoveryEnvelopeHeader {
|
|
52
|
+
/** The AES-GCM ciphertext of the payload, base64. */
|
|
53
|
+
readonly ciphertext: string;
|
|
54
|
+
/** The authenticated deal fields of the header. */
|
|
55
|
+
readonly meta?: RecoveryEnvelopeMeta | null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The AAD string: the header fields, in one FIXED order, that AES-GCM authenticates beside the ciphertext.
|
|
60
|
+
*
|
|
61
|
+
* Exported on purpose - the string is part of the format, so a check builds it with this same code instead of its
|
|
62
|
+
* own copy. An absent `meta` contributes nulls; any edit to a header field changes the string and decryption is
|
|
63
|
+
* refused.
|
|
64
|
+
*/
|
|
65
|
+
export declare function envelopeAad(envelope: RecoveryEnvelope): string;
|
|
66
|
+
|
|
67
|
+
/** The heights a recovery scan may start from. All three are optional; a source that did not answer is simply not a source. */
|
|
68
|
+
export interface RecoveryScanHeightRequest {
|
|
69
|
+
/** The escrow's birth height, from the creation receipt. */
|
|
70
|
+
readonly escrowBirthHeight?: string | number | null;
|
|
71
|
+
/** The height the application stored when it registered the watch - the source that survives a deal record without one. */
|
|
72
|
+
readonly serverRestoreHeight?: string | number | null;
|
|
73
|
+
/** The Monero node's current height. */
|
|
74
|
+
readonly nodeHeight?: string | number | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The height to start the recovery scan from: the smallest KNOWN height, one block lower and never below 1, or null
|
|
79
|
+
* when no source answered. A scan that starts below the money finds it; one that starts above never does.
|
|
80
|
+
*/
|
|
81
|
+
export declare function scanStartHeight(request?: RecoveryScanHeightRequest): number | null;
|
|
82
|
+
|
|
83
|
+
/** One side of the payment the payload carries. */
|
|
84
|
+
export interface RecoveryPayment {
|
|
85
|
+
readonly token?: string | null;
|
|
86
|
+
readonly amount?: string | number | null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** What the deal receives: XMR, at the address the file was issued for. */
|
|
90
|
+
export interface RecoveryReceive {
|
|
91
|
+
readonly token?: string | null;
|
|
92
|
+
readonly amount?: string | number | null;
|
|
93
|
+
readonly address?: string | null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** The signed quote as the payload carries it: the signature, and the last eight characters of it as the nonce. */
|
|
97
|
+
export interface RecoveryQuote {
|
|
98
|
+
readonly signature?: string | null;
|
|
99
|
+
readonly nonce?: string | null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** The escrow of the deal, as the deal record carries it. Fields beyond these travel through unchanged. */
|
|
103
|
+
export interface RecoveryEscrow {
|
|
104
|
+
readonly address?: string | null;
|
|
105
|
+
readonly termsHash?: string | null;
|
|
106
|
+
readonly [key: string]: unknown;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** A wallet built from HALVES (payload v3): no full spend key exists for anyone, so there is no mnemonic here. */
|
|
110
|
+
export interface RecoveryWalletHalves {
|
|
111
|
+
readonly source?: string | null;
|
|
112
|
+
readonly library?: string | null;
|
|
113
|
+
readonly network?: string | null;
|
|
114
|
+
readonly address?: string | null;
|
|
115
|
+
readonly subaddress?: string | null;
|
|
116
|
+
/** MY half of the spend key. */
|
|
117
|
+
readonly spendHalf?: string | null;
|
|
118
|
+
/** MY half of the view key. */
|
|
119
|
+
readonly viewHalf?: string | null;
|
|
120
|
+
/** The counterparty's public spend point. */
|
|
121
|
+
readonly otherSpendPoint?: string | null;
|
|
122
|
+
/** The counterparty's public view point. */
|
|
123
|
+
readonly otherViewPoint?: string | null;
|
|
124
|
+
/** The counterparty's view HALF - not a secret: the full view key sees funds and cannot spend them. */
|
|
125
|
+
readonly otherViewHalf?: string | null;
|
|
126
|
+
/** The escrow address the revealed half is read from. */
|
|
127
|
+
readonly escrowAddress?: string | null;
|
|
128
|
+
readonly restoreHeight?: number | null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** A wallet built from a MNEMONIC (payload v1/v2): the phrase is the single source of both keys. */
|
|
132
|
+
export interface RecoveryWalletMnemonic {
|
|
133
|
+
readonly source?: string | null;
|
|
134
|
+
readonly library?: string | null;
|
|
135
|
+
readonly network?: string | null;
|
|
136
|
+
readonly address?: string | null;
|
|
137
|
+
readonly subaddress?: string | null;
|
|
138
|
+
readonly mnemonic?: string | null;
|
|
139
|
+
readonly publicSpendKey?: string | null;
|
|
140
|
+
readonly publicViewKey?: string | null;
|
|
141
|
+
readonly restoreHeight?: number | null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** The Monero wallet data of the payload. Which shape it is follows the payload version. */
|
|
145
|
+
export type RecoveryWallet = RecoveryWalletHalves | RecoveryWalletMnemonic;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The payload inside the ciphertext: everything needed to complete or roll back the deal without the site.
|
|
149
|
+
*
|
|
150
|
+
* The fields are OPTIONAL on purpose - a file issued earlier carries fewer of them and must still read, and an
|
|
151
|
+
* unknown extra key is tolerated rather than refused. `magic`, `swapId`, `moneroWallet` and a supported `version`
|
|
152
|
+
* are what validation requires, and it names the one that is missing.
|
|
153
|
+
*/
|
|
154
|
+
export interface RecoveryPayload {
|
|
155
|
+
readonly magic?: string;
|
|
156
|
+
readonly version?: number;
|
|
157
|
+
readonly swapId?: string;
|
|
158
|
+
readonly termsHash?: string | null;
|
|
159
|
+
readonly side?: string | null;
|
|
160
|
+
readonly network?: string | null;
|
|
161
|
+
readonly moneroNetwork?: string | null;
|
|
162
|
+
readonly createdAt?: string | number | null;
|
|
163
|
+
readonly pay?: RecoveryPayment | null;
|
|
164
|
+
readonly receive?: RecoveryReceive | null;
|
|
165
|
+
readonly rate?: string | number | null;
|
|
166
|
+
readonly maker?: string | null;
|
|
167
|
+
readonly quote?: RecoveryQuote | null;
|
|
168
|
+
readonly escrow?: RecoveryEscrow | null;
|
|
169
|
+
readonly moneroWallet?: RecoveryWallet | null;
|
|
170
|
+
/** The deal's timeline, taken from the record unchanged. */
|
|
171
|
+
readonly deadlines?: unknown;
|
|
172
|
+
readonly recoveryClient?: string;
|
|
173
|
+
readonly [key: string]: unknown;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** The deal record the payload is built from. Only the fields `buildPayload` reads are named here. */
|
|
177
|
+
export interface RecoverySwapRecord {
|
|
178
|
+
readonly id: string;
|
|
179
|
+
readonly side?: string | null;
|
|
180
|
+
readonly network?: string | null;
|
|
181
|
+
readonly moneroNetwork?: string | null;
|
|
182
|
+
readonly createdAt?: string | number | null;
|
|
183
|
+
readonly payToken?: string | null;
|
|
184
|
+
readonly payAmount?: string | number | null;
|
|
185
|
+
readonly xmrAmount?: string | number | null;
|
|
186
|
+
readonly rate?: string | number | null;
|
|
187
|
+
readonly maker?: string | null;
|
|
188
|
+
readonly quoteSignature?: string | null;
|
|
189
|
+
readonly escrow?: RecoveryEscrow | null;
|
|
190
|
+
readonly timeline?: unknown;
|
|
191
|
+
readonly [key: string]: unknown;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Everything `buildPayload` assembles the payload from. `escrow` is the sender's COPY, not necessarily the one on the deal. */
|
|
195
|
+
export interface RecoveryBuildRequest {
|
|
196
|
+
readonly swap: RecoverySwapRecord;
|
|
197
|
+
/** The wallet the file is issued for; without it no wallet block is written at all. */
|
|
198
|
+
readonly swapWallet?: RecoveryWallet | null;
|
|
199
|
+
readonly escrow?: RecoveryEscrow | null;
|
|
200
|
+
readonly receiveAddress?: string | null;
|
|
201
|
+
readonly restoreHeight?: number | null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* The payload of one deal: the deal fields, the escrow, the wallet data and the deadlines.
|
|
206
|
+
*
|
|
207
|
+
* The version tells the truth about the CONTENT, not about the module: a halves wallet is 3 and a mnemonic wallet
|
|
208
|
+
* is 2, whatever version this build happens to be.
|
|
209
|
+
*/
|
|
210
|
+
export declare function buildPayload(request: RecoveryBuildRequest): RecoveryPayload;
|
|
211
|
+
|
|
212
|
+
/** The verdict of a successful validation: the warnings a sweep page should show, each one naming what is missing. */
|
|
213
|
+
export interface RecoveryValidation {
|
|
214
|
+
readonly warnings: readonly string[];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Validates a payload AFTER decryption: garbage can decrypt too, so the magic, the version, the deal id and the
|
|
219
|
+
* wallet fields are each checked, and a refusal throws with a clear cause - and never with a secret in its text.
|
|
220
|
+
*/
|
|
221
|
+
export declare function validatePayload(payload: RecoveryPayload): RecoveryValidation;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Encrypts one payload into a recovery file envelope: a fresh salt and IV, the key derived from the passphrase, and
|
|
225
|
+
* the header authenticated as AAD. A passphrase shorter than 12 characters is refused.
|
|
226
|
+
*/
|
|
227
|
+
export declare function encryptPayload(payload: RecoveryPayload, passphrase: string): Promise<RecoveryEnvelope>;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Decrypts a recovery file: the envelope version, the algorithm, the required fields and the iteration count are
|
|
231
|
+
* checked BEFORE the key is derived, a version-1 file is read without AAD, and the payload is validated before it
|
|
232
|
+
* is returned. A wrong password and an altered file are both named refusals, never a silent failure.
|
|
233
|
+
*/
|
|
234
|
+
export declare function decryptFile(fileObject: unknown, passphrase: string): Promise<RecoveryPayload>;
|
|
235
|
+
|
|
236
|
+
/** The whole file as TEXT, ready to be written: the envelope, pretty-printed, with BigInt key halves as hex strings. */
|
|
237
|
+
export declare function createRecoveryFile(payload: RecoveryPayload, passphrase: string): Promise<string>;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The name the file is written under: lowercase, tied to the deal, `ninsei-pending.json.enc` while there is no id
|
|
241
|
+
* yet. Stable, so a repeated download shows up as a second copy of one name rather than a new random file.
|
|
242
|
+
*/
|
|
243
|
+
export declare function recoveryFileName(swapId?: string | null): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// THE RECOVERY FILE AS IT TRAVELS: the envelope a wallet writes and a sweep page reads back.
|
|
2
|
+
//
|
|
3
|
+
// A sweep page opens a file the user was given earlier and has to prove it is the file this protocol wrote, take
|
|
4
|
+
// the keys out of it and start scanning from the right height. Those rules live in the engine next to this file;
|
|
5
|
+
// this entry only NAMES them, so the page does not keep a copy of them to stay in step with the package.
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
ENVELOPE_VERSION,
|
|
9
|
+
FILE_MAGIC,
|
|
10
|
+
PAYLOAD_VERSION,
|
|
11
|
+
buildPayload,
|
|
12
|
+
createRecoveryFile,
|
|
13
|
+
decryptFile,
|
|
14
|
+
encryptPayload,
|
|
15
|
+
envelopeAad,
|
|
16
|
+
recoveryFileName,
|
|
17
|
+
scanStartHeight,
|
|
18
|
+
validatePayload,
|
|
19
|
+
} from "../../engine/recovery/recoveryFile.js";
|