@shieldedtech/moth-wallet 0.2.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/README.md +62 -0
- package/dist/contract/args-parser.d.ts +29 -0
- package/dist/contract/args-parser.d.ts.map +1 -0
- package/dist/contract/args-parser.js +123 -0
- package/dist/contract/args-parser.js.map +1 -0
- package/dist/contract/artifact-loader.d.ts +26 -0
- package/dist/contract/artifact-loader.d.ts.map +1 -0
- package/dist/contract/artifact-loader.js +129 -0
- package/dist/contract/artifact-loader.js.map +1 -0
- package/dist/contract/call.d.ts +32 -0
- package/dist/contract/call.d.ts.map +1 -0
- package/dist/contract/call.js +245 -0
- package/dist/contract/call.js.map +1 -0
- package/dist/contract/deploy.d.ts +36 -0
- package/dist/contract/deploy.d.ts.map +1 -0
- package/dist/contract/deploy.js +388 -0
- package/dist/contract/deploy.js.map +1 -0
- package/dist/contract/fungible-token.d.ts +40 -0
- package/dist/contract/fungible-token.d.ts.map +1 -0
- package/dist/contract/fungible-token.js +88 -0
- package/dist/contract/fungible-token.js.map +1 -0
- package/dist/contract/initial-private-state.d.ts +18 -0
- package/dist/contract/initial-private-state.d.ts.map +1 -0
- package/dist/contract/initial-private-state.js +44 -0
- package/dist/contract/initial-private-state.js.map +1 -0
- package/dist/contract/maintenance.d.ts +72 -0
- package/dist/contract/maintenance.d.ts.map +1 -0
- package/dist/contract/maintenance.js +430 -0
- package/dist/contract/maintenance.js.map +1 -0
- package/dist/contract/state.d.ts +16 -0
- package/dist/contract/state.d.ts.map +1 -0
- package/dist/contract/state.js +18 -0
- package/dist/contract/state.js.map +1 -0
- package/dist/contract/witness-loader.d.ts +3 -0
- package/dist/contract/witness-loader.d.ts.map +1 -0
- package/dist/contract/witness-loader.js +27 -0
- package/dist/contract/witness-loader.js.map +1 -0
- package/dist/daemon/api-keys.d.ts +66 -0
- package/dist/daemon/api-keys.d.ts.map +1 -0
- package/dist/daemon/api-keys.js +222 -0
- package/dist/daemon/api-keys.js.map +1 -0
- package/dist/daemon/audit-log.d.ts +65 -0
- package/dist/daemon/audit-log.d.ts.map +1 -0
- package/dist/daemon/audit-log.js +73 -0
- package/dist/daemon/audit-log.js.map +1 -0
- package/dist/daemon/client.d.ts +63 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +214 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/confirmation-queue.d.ts +46 -0
- package/dist/daemon/confirmation-queue.d.ts.map +1 -0
- package/dist/daemon/confirmation-queue.js +92 -0
- package/dist/daemon/confirmation-queue.js.map +1 -0
- package/dist/daemon/index.d.ts +23 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +26 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/protocol.d.ts +40 -0
- package/dist/daemon/protocol.d.ts.map +1 -0
- package/dist/daemon/protocol.js +104 -0
- package/dist/daemon/protocol.js.map +1 -0
- package/dist/daemon/server.d.ts +158 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +297 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/wallet-handlers.d.ts +37 -0
- package/dist/daemon/wallet-handlers.d.ts.map +1 -0
- package/dist/daemon/wallet-handlers.js +533 -0
- package/dist/daemon/wallet-handlers.js.map +1 -0
- package/dist/daemon/wallet-rpc-parsers.d.ts +14 -0
- package/dist/daemon/wallet-rpc-parsers.d.ts.map +1 -0
- package/dist/daemon/wallet-rpc-parsers.js +259 -0
- package/dist/daemon/wallet-rpc-parsers.js.map +1 -0
- package/dist/daemon/wallet-rpc-types.d.ts +138 -0
- package/dist/daemon/wallet-rpc-types.d.ts.map +1 -0
- package/dist/daemon/wallet-rpc-types.js +11 -0
- package/dist/daemon/wallet-rpc-types.js.map +1 -0
- package/dist/diagnostics/fs-timing-store.d.ts +29 -0
- package/dist/diagnostics/fs-timing-store.d.ts.map +1 -0
- package/dist/diagnostics/fs-timing-store.js +81 -0
- package/dist/diagnostics/fs-timing-store.js.map +1 -0
- package/dist/diagnostics/timings.d.ts +64 -0
- package/dist/diagnostics/timings.d.ts.map +1 -0
- package/dist/diagnostics/timings.js +100 -0
- package/dist/diagnostics/timings.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/network/indexer-client.d.ts +66 -0
- package/dist/network/indexer-client.d.ts.map +1 -0
- package/dist/network/indexer-client.js +112 -0
- package/dist/network/indexer-client.js.map +1 -0
- package/dist/network/node-client.d.ts +27 -0
- package/dist/network/node-client.d.ts.map +1 -0
- package/dist/network/node-client.js +94 -0
- package/dist/network/node-client.js.map +1 -0
- package/dist/proof/client.d.ts +15 -0
- package/dist/proof/client.d.ts.map +1 -0
- package/dist/proof/client.js +77 -0
- package/dist/proof/client.js.map +1 -0
- package/dist/proof/provider.d.ts +12 -0
- package/dist/proof/provider.d.ts.map +1 -0
- package/dist/proof/provider.js +96 -0
- package/dist/proof/provider.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/midnight-provider.d.ts +11 -0
- package/dist/providers/midnight-provider.d.ts.map +1 -0
- package/dist/providers/midnight-provider.js +30 -0
- package/dist/providers/midnight-provider.js.map +1 -0
- package/dist/storage/adapter.d.ts +8 -0
- package/dist/storage/adapter.d.ts.map +1 -0
- package/dist/storage/adapter.js +2 -0
- package/dist/storage/adapter.js.map +1 -0
- package/dist/storage/fs-adapter.d.ts +14 -0
- package/dist/storage/fs-adapter.d.ts.map +1 -0
- package/dist/storage/fs-adapter.js +126 -0
- package/dist/storage/fs-adapter.js.map +1 -0
- package/dist/storage/safe-path.d.ts +13 -0
- package/dist/storage/safe-path.d.ts.map +1 -0
- package/dist/storage/safe-path.js +35 -0
- package/dist/storage/safe-path.js.map +1 -0
- package/dist/sync/activity.d.ts +53 -0
- package/dist/sync/activity.d.ts.map +1 -0
- package/dist/sync/activity.js +92 -0
- package/dist/sync/activity.js.map +1 -0
- package/dist/sync/dust-registration-estimate.d.ts +54 -0
- package/dist/sync/dust-registration-estimate.d.ts.map +1 -0
- package/dist/sync/dust-registration-estimate.js +103 -0
- package/dist/sync/dust-registration-estimate.js.map +1 -0
- package/dist/sync/node-sync-store.d.ts +10 -0
- package/dist/sync/node-sync-store.d.ts.map +1 -0
- package/dist/sync/node-sync-store.js +42 -0
- package/dist/sync/node-sync-store.js.map +1 -0
- package/dist/sync/operations.d.ts +138 -0
- package/dist/sync/operations.d.ts.map +1 -0
- package/dist/sync/operations.js +395 -0
- package/dist/sync/operations.js.map +1 -0
- package/dist/sync/preseed-parts.d.ts +18 -0
- package/dist/sync/preseed-parts.d.ts.map +1 -0
- package/dist/sync/preseed-parts.js +33 -0
- package/dist/sync/preseed-parts.js.map +1 -0
- package/dist/sync/preseed.d.ts +95 -0
- package/dist/sync/preseed.d.ts.map +1 -0
- package/dist/sync/preseed.js +365 -0
- package/dist/sync/preseed.js.map +1 -0
- package/dist/sync/progress.d.ts +45 -0
- package/dist/sync/progress.d.ts.map +1 -0
- package/dist/sync/progress.js +51 -0
- package/dist/sync/progress.js.map +1 -0
- package/dist/sync/sdk-dedup.d.ts +53 -0
- package/dist/sync/sdk-dedup.d.ts.map +1 -0
- package/dist/sync/sdk-dedup.js +134 -0
- package/dist/sync/sdk-dedup.js.map +1 -0
- package/dist/sync/sync-store.d.ts +33 -0
- package/dist/sync/sync-store.d.ts.map +1 -0
- package/dist/sync/sync-store.js +45 -0
- package/dist/sync/sync-store.js.map +1 -0
- package/dist/sync/wallet-sync.d.ts +153 -0
- package/dist/sync/wallet-sync.d.ts.map +1 -0
- package/dist/sync/wallet-sync.js +943 -0
- package/dist/sync/wallet-sync.js.map +1 -0
- package/dist/types/errors.d.ts +18 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +33 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/exit-codes.d.ts +8 -0
- package/dist/types/exit-codes.d.ts.map +1 -0
- package/dist/types/exit-codes.js +7 -0
- package/dist/types/exit-codes.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/network.d.ts +65 -0
- package/dist/types/network.d.ts.map +1 -0
- package/dist/types/network.js +108 -0
- package/dist/types/network.js.map +1 -0
- package/dist/types/tokens.d.ts +3 -0
- package/dist/types/tokens.d.ts.map +1 -0
- package/dist/types/tokens.js +11 -0
- package/dist/types/tokens.js.map +1 -0
- package/dist/types/transaction.d.ts +13 -0
- package/dist/types/transaction.d.ts.map +1 -0
- package/dist/types/transaction.js +2 -0
- package/dist/types/transaction.js.map +1 -0
- package/dist/types/wallet.d.ts +82 -0
- package/dist/types/wallet.d.ts.map +1 -0
- package/dist/types/wallet.js +2 -0
- package/dist/types/wallet.js.map +1 -0
- package/dist/wallet/address-validate.d.ts +7 -0
- package/dist/wallet/address-validate.d.ts.map +1 -0
- package/dist/wallet/address-validate.js +28 -0
- package/dist/wallet/address-validate.js.map +1 -0
- package/dist/wallet/address.d.ts +32 -0
- package/dist/wallet/address.d.ts.map +1 -0
- package/dist/wallet/address.js +107 -0
- package/dist/wallet/address.js.map +1 -0
- package/dist/wallet/app-secret.d.ts +15 -0
- package/dist/wallet/app-secret.d.ts.map +1 -0
- package/dist/wallet/app-secret.js +45 -0
- package/dist/wallet/app-secret.js.map +1 -0
- package/dist/wallet/balance-format.d.ts +12 -0
- package/dist/wallet/balance-format.d.ts.map +1 -0
- package/dist/wallet/balance-format.js +51 -0
- package/dist/wallet/balance-format.js.map +1 -0
- package/dist/wallet/batch-transfer.d.ts +36 -0
- package/dist/wallet/batch-transfer.d.ts.map +1 -0
- package/dist/wallet/batch-transfer.js +93 -0
- package/dist/wallet/batch-transfer.js.map +1 -0
- package/dist/wallet/keystore.d.ts +16 -0
- package/dist/wallet/keystore.d.ts.map +1 -0
- package/dist/wallet/keystore.js +76 -0
- package/dist/wallet/keystore.js.map +1 -0
- package/dist/wallet/manager.d.ts +77 -0
- package/dist/wallet/manager.d.ts.map +1 -0
- package/dist/wallet/manager.js +474 -0
- package/dist/wallet/manager.js.map +1 -0
- package/dist/wallet/mnemonic.d.ts +5 -0
- package/dist/wallet/mnemonic.d.ts.map +1 -0
- package/dist/wallet/mnemonic.js +28 -0
- package/dist/wallet/mnemonic.js.map +1 -0
- package/dist/wallet/sign-message.d.ts +20 -0
- package/dist/wallet/sign-message.d.ts.map +1 -0
- package/dist/wallet/sign-message.js +58 -0
- package/dist/wallet/sign-message.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
// Wallet operations via WalletFacade — send, designate, dedesignate.
|
|
2
|
+
// Architecture follows mn-tui's wallet.ts pattern. See NOTICE for attribution.
|
|
3
|
+
import * as Rx from 'rxjs';
|
|
4
|
+
import * as ledger from '@midnight-ntwrk/ledger-v8';
|
|
5
|
+
import { MidnightBech32m, ShieldedAddress, UnshieldedAddress, DustAddress, } from '@midnightntwrk/wallet-sdk/address-format';
|
|
6
|
+
import { createKeystore } from '@midnightntwrk/wallet-sdk/unshielded';
|
|
7
|
+
import { HDWallet, Roles } from '@midnightntwrk/wallet-sdk/hd';
|
|
8
|
+
import { setNetworkId } from '@midnight-ntwrk/midnight-js/network-id';
|
|
9
|
+
import { NIGHT_TOKEN_ID } from './wallet-sync.js';
|
|
10
|
+
import { estimateRegistrationAffordability, DustRegistrationNotYetError, } from './dust-registration-estimate.js';
|
|
11
|
+
// Re-exported from the module that throws it, so a consumer importing the
|
|
12
|
+
// registration API by subpath (packages/browser does) gets the error type it has
|
|
13
|
+
// to catch from the same place — without also reaching for the estimate module.
|
|
14
|
+
export { DustRegistrationNotYetError };
|
|
15
|
+
// Multi-output transfer builder (kept from main): groups requests by kind so a
|
|
16
|
+
// single transaction can carry several tokens/recipients — the extension's
|
|
17
|
+
// batch send and the CLI both rely on it.
|
|
18
|
+
function combinedTransfers(networkId, requests) {
|
|
19
|
+
const grouped = new Map();
|
|
20
|
+
for (const req of requests) {
|
|
21
|
+
const parsed = MidnightBech32m.parse(req.to);
|
|
22
|
+
const receiverAddress = req.type === 'unshielded'
|
|
23
|
+
? parsed.decode(UnshieldedAddress, networkId)
|
|
24
|
+
: parsed.decode(ShieldedAddress, networkId);
|
|
25
|
+
const outputs = grouped.get(req.type) ?? [];
|
|
26
|
+
outputs.push({ type: req.tokenId, amount: req.amount, receiverAddress });
|
|
27
|
+
grouped.set(req.type, outputs);
|
|
28
|
+
}
|
|
29
|
+
// The map already pairs each kind with same-kind outputs; the cast collapses
|
|
30
|
+
// the inferred shape onto the SDK's discriminated CombinedTokenTransfer union.
|
|
31
|
+
return [...grouped.entries()].map(([type, outputs]) => ({ type, outputs }));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Derive the typed key bundle from a 64-char BIP-39 hex seed. Option A key
|
|
35
|
+
* model (v8's D-KM-3): callers derive once at unlock and discard the raw seed
|
|
36
|
+
* immediately — the bundle holds everything the write paths need, so the seed
|
|
37
|
+
* is never threaded through the daemon or the extension messaging layers.
|
|
38
|
+
*/
|
|
39
|
+
export function deriveWalletKeys(seedHex) {
|
|
40
|
+
const hdWallet = HDWallet.fromSeed(Buffer.from(seedHex, 'hex'));
|
|
41
|
+
if (hdWallet.type !== 'seedOk')
|
|
42
|
+
throw new Error('Invalid seed');
|
|
43
|
+
const result = hdWallet.hdWallet
|
|
44
|
+
.selectAccount(0)
|
|
45
|
+
.selectRoles([Roles.Zswap, Roles.NightExternal, Roles.Dust])
|
|
46
|
+
.deriveKeysAt(0);
|
|
47
|
+
if (result.type !== 'keysDerived')
|
|
48
|
+
throw new Error('Key derivation failed');
|
|
49
|
+
hdWallet.hdWallet.clear();
|
|
50
|
+
return {
|
|
51
|
+
shieldedSecretKeys: ledger.ZswapSecretKeys.fromSeed(result.keys[Roles.Zswap]),
|
|
52
|
+
dustSecretKey: ledger.DustSecretKey.fromSeed(result.keys[Roles.Dust]),
|
|
53
|
+
nightExternalKey: result.keys[Roles.NightExternal],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Legacy private alias — internal callers that predate deriveWalletKeys.
|
|
57
|
+
function deriveKeysFromSeed(seedHex) {
|
|
58
|
+
return deriveWalletKeys(seedHex);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Substrate tx-pool rejects a transaction whose hash is already in the pool
|
|
62
|
+
* with error 1013 "Transaction Already Imported". Because a finalized tx has a
|
|
63
|
+
* fixed hash, this fires whenever we resubmit identical bytes — which means the
|
|
64
|
+
* transaction already reached the node, so it should be treated as success.
|
|
65
|
+
*/
|
|
66
|
+
function isAlreadyImported(e) {
|
|
67
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
68
|
+
return msg.includes('1013') || /already imported/i.test(msg);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A connection-level failure where the transaction likely never reached the
|
|
72
|
+
* node — the only case worth resending. A node that evaluated the transaction
|
|
73
|
+
* and rejected it (bad proof, insufficient funds, low priority, …) returns a
|
|
74
|
+
* deterministic verdict; resending the identical bytes only makes the user
|
|
75
|
+
* wait for the same answer, so those rejections must surface immediately.
|
|
76
|
+
*/
|
|
77
|
+
function isTransient(e) {
|
|
78
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
79
|
+
return /disconnect|not connected|connection|websocket|socket hang up|time\s?d?\s?out|timeout|ECONN|ENOTFOUND|network|fetch failed|1006/i.test(msg);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Submit an already-finalized transaction, classifying failures so the user
|
|
83
|
+
* only waits through a retry when one could actually help:
|
|
84
|
+
*
|
|
85
|
+
* - "Already Imported" (1013): a prior attempt's identical bytes already reached
|
|
86
|
+
* the pool — that IS submitted, so report success with the tx's own hash.
|
|
87
|
+
* - Transient connection failure: resend (the tx may never have arrived).
|
|
88
|
+
* - Any other error is the node's deterministic rejection: surface it at once,
|
|
89
|
+
* without burning retries the user has to wait through.
|
|
90
|
+
*/
|
|
91
|
+
async function submitWithRetry(facade, finalized, attempts = 3, delayMs = 5_000) {
|
|
92
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
93
|
+
try {
|
|
94
|
+
// The facade resolves to an intent identifier (`identifiers().at(-1)`),
|
|
95
|
+
// but everything downstream — indexer status queries, tx-history entries
|
|
96
|
+
// (WalletEntry.hash), explorers, and the activity feed's pending-row
|
|
97
|
+
// reconciliation — is keyed by the transaction hash. Return that.
|
|
98
|
+
await facade.submitTransaction(finalized);
|
|
99
|
+
return finalized.transactionHash();
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
if (isAlreadyImported(e))
|
|
103
|
+
return finalized.transactionHash();
|
|
104
|
+
if (attempt === attempts || !isTransient(e))
|
|
105
|
+
throw e;
|
|
106
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
throw new Error('unreachable');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Build, prove and sign a transfer, stopping short of submission.
|
|
113
|
+
* The dApp connector's makeTransfer/submitTransaction split needs the
|
|
114
|
+
* finalized transaction as a standalone artifact; sendTokens composes this
|
|
115
|
+
* with submission.
|
|
116
|
+
*/
|
|
117
|
+
export async function buildTransferTransaction(facade, keys, networkId, requests, onProgress) {
|
|
118
|
+
setNetworkId(networkId);
|
|
119
|
+
const ks = createKeystore(keys.nightExternalKey, networkId);
|
|
120
|
+
const transfers = combinedTransfers(networkId, requests);
|
|
121
|
+
const ttl = new Date(Date.now() + 30 * 60_000);
|
|
122
|
+
onProgress?.('building');
|
|
123
|
+
const recipe = await facade.transferTransaction(transfers, { shieldedSecretKeys: keys.shieldedSecretKeys, dustSecretKey: keys.dustSecretKey }, { ttl });
|
|
124
|
+
onProgress?.('proving');
|
|
125
|
+
const signed = await facade.signRecipe(recipe, (payload) => ks.signData(payload));
|
|
126
|
+
return facade.finalizeRecipe(signed);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Estimate the complete DUST fee for a transfer, including the balancing
|
|
130
|
+
* transaction that pays it. The facade's transfer builder books selected
|
|
131
|
+
* inputs even when fee payment is disabled, so the temporary base transaction
|
|
132
|
+
* is always reverted before returning.
|
|
133
|
+
*/
|
|
134
|
+
export async function estimateTransferFee(facade, keys, networkId, requests) {
|
|
135
|
+
setNetworkId(networkId);
|
|
136
|
+
const transfers = combinedTransfers(networkId, requests);
|
|
137
|
+
const ttl = new Date(Date.now() + 30 * 60_000);
|
|
138
|
+
const recipe = await facade.transferTransaction(transfers, { shieldedSecretKeys: keys.shieldedSecretKeys, dustSecretKey: keys.dustSecretKey }, { ttl, payFees: false });
|
|
139
|
+
try {
|
|
140
|
+
return await facade.estimateTransactionFee(recipe.transaction, keys.dustSecretKey, { ttl });
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await facade.revertTransaction(recipe.transaction);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Submit a previously built transfer with retries.
|
|
148
|
+
*/
|
|
149
|
+
export async function submitFinalizedTransaction(facade, finalized) {
|
|
150
|
+
return submitWithRetry(facade, finalized);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Send tokens via the wallet facade using a pre-derived key bundle. Prefer this
|
|
154
|
+
* over {@link sendTokens} when the caller already holds WalletKeys (the daemon
|
|
155
|
+
* and the extension, which derive once at unlock and drop the seed — Option A /
|
|
156
|
+
* D-KM-3, docs/spec/wallet-service/05-key-management.md).
|
|
157
|
+
*/
|
|
158
|
+
export async function sendTokensWithKeys(facade, keys, networkId, requests, onProgress) {
|
|
159
|
+
const finalized = await buildTransferTransaction(facade, keys, networkId, requests, onProgress);
|
|
160
|
+
onProgress?.('submitting');
|
|
161
|
+
return submitFinalizedTransaction(facade, finalized);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Balance a dApp-supplied transaction (connector `balanceSealedTransaction` /
|
|
165
|
+
* `balanceUnsealedTransaction`): pay fees and add wallet inputs/outputs to
|
|
166
|
+
* remove imbalances, then prove + bind into a submit-ready FinalizedTransaction.
|
|
167
|
+
*
|
|
168
|
+
* `sealed` selects the input stage:
|
|
169
|
+
* - sealed → Transaction<SignatureEnabled, Proof, Binding> (FinalizedTransaction)
|
|
170
|
+
* - unsealed → Transaction<SignatureEnabled, Proof, PreBinding> (UnboundTransaction)
|
|
171
|
+
*
|
|
172
|
+
* The prove/finalize tail is the same as {@link buildTransferTransaction}.
|
|
173
|
+
*/
|
|
174
|
+
export async function balanceTransaction(facade, keys, networkId, txBytes, sealed, onProgress) {
|
|
175
|
+
setNetworkId(networkId);
|
|
176
|
+
const ks = createKeystore(keys.nightExternalKey, networkId);
|
|
177
|
+
const secretKeys = { shieldedSecretKeys: keys.shieldedSecretKeys, dustSecretKey: keys.dustSecretKey };
|
|
178
|
+
const ttl = new Date(Date.now() + 30 * 60_000);
|
|
179
|
+
onProgress?.('building');
|
|
180
|
+
const recipe = sealed
|
|
181
|
+
? await facade.balanceFinalizedTransaction(ledger.Transaction.deserialize('signature', 'proof', 'binding', txBytes), secretKeys, { ttl })
|
|
182
|
+
: await facade.balanceUnboundTransaction(ledger.Transaction.deserialize('signature', 'proof', 'pre-binding', txBytes), secretKeys, { ttl });
|
|
183
|
+
onProgress?.('proving');
|
|
184
|
+
const signed = await facade.signRecipe(recipe, (payload) => ks.signData(payload));
|
|
185
|
+
return facade.finalizeRecipe(signed);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Build a swap intent (connector `makeIntent`): the wallet's half of a swap,
|
|
189
|
+
* providing `inputs` (spent) and `outputs` (sent to recipients). Returns the
|
|
190
|
+
* raw unproven, unbound transaction from the SDK's `initSwap` — deliberately
|
|
191
|
+
* NOT proven or bound, so the dApp can combine it with the counterparty's half
|
|
192
|
+
* before the combined transaction is proven, balanced, and submitted.
|
|
193
|
+
*
|
|
194
|
+
* NOTE: the connector's `intentId` option is not honored — the SDK's `initSwap`
|
|
195
|
+
* exposes no segment-id control, so callers cannot pin the intent's id or opt
|
|
196
|
+
* out of transaction merging.
|
|
197
|
+
*/
|
|
198
|
+
export async function buildSwapIntent(facade, keys, networkId, inputs, outputs, payFees, onProgress) {
|
|
199
|
+
setNetworkId(networkId);
|
|
200
|
+
const swapInputs = {};
|
|
201
|
+
for (const input of inputs) {
|
|
202
|
+
const bucket = (swapInputs[input.type] ??= {});
|
|
203
|
+
bucket[input.tokenId] = (bucket[input.tokenId] ?? 0n) + input.amount;
|
|
204
|
+
}
|
|
205
|
+
const grouped = new Map();
|
|
206
|
+
for (const out of outputs) {
|
|
207
|
+
const parsed = MidnightBech32m.parse(out.to);
|
|
208
|
+
const receiverAddress = out.type === 'unshielded'
|
|
209
|
+
? parsed.decode(UnshieldedAddress, networkId)
|
|
210
|
+
: parsed.decode(ShieldedAddress, networkId);
|
|
211
|
+
const list = grouped.get(out.type) ?? [];
|
|
212
|
+
list.push({ type: out.tokenId, amount: out.amount, receiverAddress });
|
|
213
|
+
grouped.set(out.type, list);
|
|
214
|
+
}
|
|
215
|
+
const swapOutputs = [...grouped.entries()].map(([type, outs]) => ({ type, outputs: outs }));
|
|
216
|
+
const ttl = new Date(Date.now() + 30 * 60_000);
|
|
217
|
+
onProgress?.('building');
|
|
218
|
+
const recipe = await facade.initSwap(swapInputs, swapOutputs, { shieldedSecretKeys: keys.shieldedSecretKeys, dustSecretKey: keys.dustSecretKey }, { ttl, payFees });
|
|
219
|
+
return recipe.transaction;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Send tokens via the wallet facade. Convenience wrapper that derives a
|
|
223
|
+
* WalletKeys bundle from the seed and delegates to
|
|
224
|
+
* {@link sendTokensWithKeys}. Holds the seed in memory only for the
|
|
225
|
+
* duration of derivation — used by paths like the in-process `moth
|
|
226
|
+
* transfer` CLI command that already work in terms of seedHex.
|
|
227
|
+
*/
|
|
228
|
+
export async function sendTokens(facade, seedHex, networkId, requests, onProgress) {
|
|
229
|
+
return sendTokensWithKeys(facade, deriveWalletKeys(seedHex), networkId, requests, onProgress);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* List the active wallet's NIGHT UTXOs (registered + unregistered).
|
|
233
|
+
* Waits for the unshielded sub-wallet to be strict-complete — does NOT gate on
|
|
234
|
+
* aggregate `isSynced`, which never becomes true for a fresh wallet whose only
|
|
235
|
+
* activity is unshielded (e.g. a faucet-funded test wallet pre-dust-register).
|
|
236
|
+
*/
|
|
237
|
+
export async function listNightUtxos(facade) {
|
|
238
|
+
const state = await Rx.firstValueFrom(facade.state().pipe(Rx.filter((s) => s.unshielded?.progress?.isStrictlyComplete?.() === true)));
|
|
239
|
+
const coins = state.unshielded.availableCoins.filter((c) => c.utxo.type === NIGHT_TOKEN_ID);
|
|
240
|
+
return coins.map((c) => ({
|
|
241
|
+
raw: c,
|
|
242
|
+
value: BigInt(c.utxo.value),
|
|
243
|
+
registered: c.meta.registeredForDustGeneration,
|
|
244
|
+
}));
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Register NIGHT UTXOs for DUST generation, using a pre-derived
|
|
248
|
+
* WalletKeys bundle (D-KM-3 path — preferred over the seedHex variant
|
|
249
|
+
* for daemon callers).
|
|
250
|
+
*/
|
|
251
|
+
export async function designateForDustWithKeys(facade, keys, networkId, receiver, onProgress, selectedUtxos) {
|
|
252
|
+
setNetworkId(networkId);
|
|
253
|
+
const ks = createKeystore(keys.nightExternalKey, networkId);
|
|
254
|
+
return designateForDustImpl(facade, ks, networkId, receiver, onProgress, selectedUtxos);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Register NIGHT UTXOs for DUST generation.
|
|
258
|
+
* If `selectedUtxos` is provided, registers exactly those; otherwise auto-selects
|
|
259
|
+
* all currently unregistered NIGHT UTXOs.
|
|
260
|
+
*/
|
|
261
|
+
export async function designateForDust(facade, seedHex, networkId, receiver, onProgress, selectedUtxos) {
|
|
262
|
+
setNetworkId(networkId);
|
|
263
|
+
const keys = deriveKeysFromSeed(seedHex);
|
|
264
|
+
const ks = createKeystore(keys.nightExternalKey, networkId);
|
|
265
|
+
return designateForDustImpl(facade, ks, networkId, receiver, onProgress, selectedUtxos);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Whether registration can pay its own fee yet, and if not, how long until it
|
|
269
|
+
* can. Reads state and builds a throwaway transaction for costing; books
|
|
270
|
+
* nothing and spends nothing.
|
|
271
|
+
*
|
|
272
|
+
* Registration is self-funding — it draws on the DUST its NIGHT would have
|
|
273
|
+
* generated had it been registered all along — but that backdated amount starts
|
|
274
|
+
* at zero and grows with the NIGHT's age, so a freshly funded wallet cannot
|
|
275
|
+
* cover the fee yet. Without asking first, the wallet builds, proves, fails on
|
|
276
|
+
* the SDK's guard, and reports a defect where the honest answer is "not yet, try
|
|
277
|
+
* in about six minutes". See sync/dust-registration-estimate.ts.
|
|
278
|
+
*/
|
|
279
|
+
export async function estimateDustRegistration(facade, selectedUtxos) {
|
|
280
|
+
const utxos = selectedUtxos?.length
|
|
281
|
+
? selectedUtxos.map((u) => u.raw)
|
|
282
|
+
: await unregisteredNightUtxos(facade);
|
|
283
|
+
// Nothing to register: no fee, and no accrual to wait for. The caller
|
|
284
|
+
// distinguishes this from "not yet" via its own no-night handling.
|
|
285
|
+
if (utxos.length === 0) {
|
|
286
|
+
return { fee: 0n, available: 0n, rate: 0n, maxAvailable: 0n, affordable: true, secondsUntilAffordable: 0 };
|
|
287
|
+
}
|
|
288
|
+
const { fee, dustGenerationEstimations } = await facade.estimateRegistration(utxos);
|
|
289
|
+
return estimateRegistrationAffordability(fee, dustGenerationEstimations.map((e) => ({
|
|
290
|
+
generatedNow: e.dust.generatedNow,
|
|
291
|
+
rate: e.dust.rate,
|
|
292
|
+
maxCap: e.dust.maxCap,
|
|
293
|
+
registeredForDustGeneration: e.utxo.registeredForDustGeneration,
|
|
294
|
+
})));
|
|
295
|
+
}
|
|
296
|
+
/** Unshielded NIGHT not yet backing DUST — the set a registration would use.
|
|
297
|
+
* Gates on unshielded strict-complete only; see designateForDustImpl. */
|
|
298
|
+
async function unregisteredNightUtxos(facade) {
|
|
299
|
+
const state = await Rx.firstValueFrom(facade.state().pipe(Rx.filter((s) => s.unshielded?.progress?.isStrictlyComplete?.() === true)));
|
|
300
|
+
return state.unshielded.availableCoins.filter((c) => c.utxo.type === NIGHT_TOKEN_ID && !c.meta.registeredForDustGeneration);
|
|
301
|
+
}
|
|
302
|
+
// Shared body used by both designateForDust(seedHex) and
|
|
303
|
+
// designateForDustWithKeys(walletKeys).
|
|
304
|
+
async function designateForDustImpl(facade, ks, networkId, receiver, onProgress, selectedUtxos) {
|
|
305
|
+
let utxos;
|
|
306
|
+
if (selectedUtxos && selectedUtxos.length > 0) {
|
|
307
|
+
utxos = selectedUtxos.map((u) => u.raw);
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
// Registration only reads unshielded NIGHT UTXOs; gating on aggregate
|
|
311
|
+
// `isSynced` deadlocks a fresh wallet whose shielded/DUST streams have no
|
|
312
|
+
// events yet (registration itself creates the first DUST event). Shared with
|
|
313
|
+
// estimateDustRegistration so the pre-flight cannot cost a different set
|
|
314
|
+
// from the one the registration actually uses.
|
|
315
|
+
utxos = await unregisteredNightUtxos(facade);
|
|
316
|
+
}
|
|
317
|
+
if (utxos.length === 0)
|
|
318
|
+
return null;
|
|
319
|
+
onProgress?.('building');
|
|
320
|
+
let dustReceiver;
|
|
321
|
+
if (receiver) {
|
|
322
|
+
try {
|
|
323
|
+
dustReceiver = MidnightBech32m.parse(receiver).decode(DustAddress, networkId);
|
|
324
|
+
}
|
|
325
|
+
catch (e) {
|
|
326
|
+
// Never fall back silently: the caller explicitly chose a receiver, and
|
|
327
|
+
// defaulting would quietly send their DUST somewhere they didn't pick.
|
|
328
|
+
throw new Error(`Invalid DUST address "${receiver}" for network "${networkId}": ${e instanceof Error ? e.message : e}`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
let recipe;
|
|
332
|
+
try {
|
|
333
|
+
recipe = await facade.registerNightUtxosForDustGeneration(utxos, ks.getPublicKey(), (payload) => ks.signData(payload), dustReceiver);
|
|
334
|
+
}
|
|
335
|
+
catch (e) {
|
|
336
|
+
// Registration self-funds from the DUST its NIGHT would already have
|
|
337
|
+
// generated, and that amount starts at zero — so on a freshly funded wallet
|
|
338
|
+
// the SDK refuses before proving. Re-costing tells us whether that is what
|
|
339
|
+
// happened, and by how much: the affordability figures are the ground truth
|
|
340
|
+
// here, not the SDK's message text, which we would otherwise have to match
|
|
341
|
+
// by string and re-match on every SDK release.
|
|
342
|
+
//
|
|
343
|
+
// Only on the failure path, so a registration that was always going to
|
|
344
|
+
// succeed pays nothing for this.
|
|
345
|
+
const estimate = await estimateDustRegistration(facade, selectedUtxos).catch(() => null);
|
|
346
|
+
if (estimate && !estimate.affordable)
|
|
347
|
+
throw new DustRegistrationNotYetError(estimate, e);
|
|
348
|
+
throw e;
|
|
349
|
+
}
|
|
350
|
+
onProgress?.('proving');
|
|
351
|
+
const finalized = await facade.finalizeRecipe(recipe);
|
|
352
|
+
onProgress?.('submitting');
|
|
353
|
+
return submitWithRetry(facade, finalized);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Deregister NIGHT UTXOs from DUST generation, using a pre-derived
|
|
357
|
+
* WalletKeys bundle (D-KM-3 path).
|
|
358
|
+
*/
|
|
359
|
+
export async function dedesignateFromDustWithKeys(facade, keys, networkId, onProgress, selectedUtxos) {
|
|
360
|
+
setNetworkId(networkId);
|
|
361
|
+
const ks = createKeystore(keys.nightExternalKey, networkId);
|
|
362
|
+
return dedesignateFromDustImpl(facade, ks, keys, onProgress, selectedUtxos);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Deregister NIGHT UTXOs from DUST generation.
|
|
366
|
+
* If `selectedUtxos` is provided, deregisters exactly those; otherwise auto-selects
|
|
367
|
+
* all currently registered NIGHT UTXOs.
|
|
368
|
+
*/
|
|
369
|
+
export async function dedesignateFromDust(facade, seedHex, networkId, onProgress, selectedUtxos) {
|
|
370
|
+
setNetworkId(networkId);
|
|
371
|
+
const keys = deriveKeysFromSeed(seedHex);
|
|
372
|
+
const ks = createKeystore(keys.nightExternalKey, networkId);
|
|
373
|
+
return dedesignateFromDustImpl(facade, ks, keys, onProgress, selectedUtxos);
|
|
374
|
+
}
|
|
375
|
+
async function dedesignateFromDustImpl(facade, ks, keys, onProgress, selectedUtxos) {
|
|
376
|
+
let utxos;
|
|
377
|
+
if (selectedUtxos && selectedUtxos.length > 0) {
|
|
378
|
+
utxos = selectedUtxos.map((u) => u.raw);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
// Gate on unshielded strict-complete only — see designateForDustImpl
|
|
382
|
+
// above for why `s.isSynced` is the wrong predicate here.
|
|
383
|
+
const state = await Rx.firstValueFrom(facade.state().pipe(Rx.filter((s) => s.unshielded?.progress?.isStrictlyComplete?.() === true)));
|
|
384
|
+
utxos = state.unshielded.availableCoins.filter((c) => c.meta.registeredForDustGeneration === true);
|
|
385
|
+
}
|
|
386
|
+
if (utxos.length === 0)
|
|
387
|
+
throw new Error('No registered NIGHT UTXOs to deregister');
|
|
388
|
+
onProgress?.('building');
|
|
389
|
+
const recipe = await facade.deregisterFromDustGeneration(utxos, ks.getPublicKey(), (payload) => ks.signData(payload));
|
|
390
|
+
const balancedRecipe = await facade.balanceUnprovenTransaction(recipe.transaction, { shieldedSecretKeys: keys.shieldedSecretKeys, dustSecretKey: keys.dustSecretKey }, { ttl: new Date(Date.now() + 30 * 60_000) });
|
|
391
|
+
onProgress?.('submitting');
|
|
392
|
+
const finalized = await facade.finalizeRecipe(balancedRecipe);
|
|
393
|
+
return submitWithRetry(facade, finalized);
|
|
394
|
+
}
|
|
395
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/sync/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { WalletPart } from './sync-store.js';
|
|
2
|
+
/** The parts a pre-seed can supply. History is not seeded; it rebuilds itself. */
|
|
3
|
+
export declare const SEEDABLE_PARTS: readonly ["shielded", "unshielded", "dust"];
|
|
4
|
+
export type SeedablePart = (typeof SEEDABLE_PARTS)[number];
|
|
5
|
+
/**
|
|
6
|
+
* The seedable parts with no cached state, in a fixed order.
|
|
7
|
+
*
|
|
8
|
+
* A part that already has a cache is at least as far along as the reference, so
|
|
9
|
+
* seeding over it would discard progress. Anything absent is a candidate,
|
|
10
|
+
* whether this is a brand-new wallet (all three) or a rebuild of one
|
|
11
|
+
* (just the evicted part).
|
|
12
|
+
*/
|
|
13
|
+
export declare function partsToSeed(cached: Partial<Record<SeedablePart, string | null>>): SeedablePart[];
|
|
14
|
+
/** Whether a pre-seed attempt is worth making at all. */
|
|
15
|
+
export declare function shouldAttemptPreSeed(cached: Partial<Record<SeedablePart, string | null>>): boolean;
|
|
16
|
+
/** Narrowing helper for callers holding the wider WalletPart union. */
|
|
17
|
+
export declare function isSeedablePart(part: WalletPart): part is SeedablePart;
|
|
18
|
+
//# sourceMappingURL=preseed-parts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preseed-parts.d.ts","sourceRoot":"","sources":["../../src/sync/preseed-parts.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAEhD,kFAAkF;AAClF,eAAO,MAAM,cAAc,6CAA8C,CAAC;AAE1E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,YAAY,EAAE,CAEhG;AAED,yDAAyD;AACzD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,OAAO,CAElG;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,IAAI,YAAY,CAErE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Which sub-wallet caches a pre-seed should fill in.
|
|
2
|
+
//
|
|
3
|
+
// Split out and WASM-free so the decision is unit-testable without loading the
|
|
4
|
+
// ledger — the same split as sync/progress.ts.
|
|
5
|
+
//
|
|
6
|
+
// This exists because the decision was once made by proxy: the pre-seed gate
|
|
7
|
+
// tested the SHIELDED cache alone, standing in for "this wallet has no state
|
|
8
|
+
// yet". That proxy failed exactly where it mattered. A DUST rebuild evicts the
|
|
9
|
+
// dust cache and nothing else, so shielded was still present, the gate stayed
|
|
10
|
+
// shut, and dust walked all 1.4M events from genesis — 78.6 min on preprod —
|
|
11
|
+
// while a usable reference sat unused.
|
|
12
|
+
/** The parts a pre-seed can supply. History is not seeded; it rebuilds itself. */
|
|
13
|
+
export const SEEDABLE_PARTS = ['shielded', 'unshielded', 'dust'];
|
|
14
|
+
/**
|
|
15
|
+
* The seedable parts with no cached state, in a fixed order.
|
|
16
|
+
*
|
|
17
|
+
* A part that already has a cache is at least as far along as the reference, so
|
|
18
|
+
* seeding over it would discard progress. Anything absent is a candidate,
|
|
19
|
+
* whether this is a brand-new wallet (all three) or a rebuild of one
|
|
20
|
+
* (just the evicted part).
|
|
21
|
+
*/
|
|
22
|
+
export function partsToSeed(cached) {
|
|
23
|
+
return SEEDABLE_PARTS.filter((part) => !cached[part]);
|
|
24
|
+
}
|
|
25
|
+
/** Whether a pre-seed attempt is worth making at all. */
|
|
26
|
+
export function shouldAttemptPreSeed(cached) {
|
|
27
|
+
return partsToSeed(cached).length > 0;
|
|
28
|
+
}
|
|
29
|
+
/** Narrowing helper for callers holding the wider WalletPart union. */
|
|
30
|
+
export function isSeedablePart(part) {
|
|
31
|
+
return SEEDABLE_PARTS.includes(part);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=preseed-parts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preseed-parts.js","sourceRoot":"","sources":["../../src/sync/preseed-parts.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,+EAA+E;AAC/E,+CAA+C;AAC/C,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,uCAAuC;AAIvC,kFAAkF;AAClF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,CAAU,CAAC;AAI1E;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,MAAoD;IAC9E,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,oBAAoB,CAAC,MAAoD;IACvF,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACxC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAAC,IAAgB;IAC7C,OAAQ,cAAoC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { NetworkConfig } from '../types/network.js';
|
|
2
|
+
import { type SyncStateStore } from './sync-store.js';
|
|
3
|
+
import { type WalletKeys } from './operations.js';
|
|
4
|
+
export interface EmptyRefStates {
|
|
5
|
+
shielded: string;
|
|
6
|
+
unshielded: string;
|
|
7
|
+
dust: string;
|
|
8
|
+
/**
|
|
9
|
+
* Chain height this reference was synced to. Callers MUST refuse to pre-seed a
|
|
10
|
+
* wallet whose birthday precedes it: the reference carries the chain's state at
|
|
11
|
+
* this height, so seeding a wallet that was already active earlier would skip
|
|
12
|
+
* that wallet's own history. Compared against `birthday` (also a height) —
|
|
13
|
+
* never against a snapshot `offset`, which is an event index.
|
|
14
|
+
*/
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
17
|
+
/** Reference-build progress, for surfacing an hour-long job in the UI. */
|
|
18
|
+
export interface WarmProgress {
|
|
19
|
+
/** Dust events applied so far — the sub-wallet that dominates the build. */
|
|
20
|
+
applied: number;
|
|
21
|
+
/** Dust events the chain currently has. Grows slowly as the chain advances. */
|
|
22
|
+
total: number;
|
|
23
|
+
synced: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Ensure an empty reference wallet is synced to chain tip for this network.
|
|
27
|
+
* The first call per network syncs from genesis (or restores from cache).
|
|
28
|
+
* Subsequent calls return the cached result immediately.
|
|
29
|
+
*/
|
|
30
|
+
export declare function ensureEmptyRefCache(network: NetworkConfig, onProgress?: (msg: string) => void, store?: SyncStateStore,
|
|
31
|
+
/**
|
|
32
|
+
* Build the reference if none is warm yet. OFF by default, and deliberately
|
|
33
|
+
* so: building means syncing an empty wallet to chain tip, which dust makes a
|
|
34
|
+
* tens-of-minutes job. On the wallet-startup path that would block the user's
|
|
35
|
+
* own wallet from starting, which is far worse than letting it sync from
|
|
36
|
+
* genesis in the background. Callers that mean to pay the cost use
|
|
37
|
+
* warmEmptyRefCache().
|
|
38
|
+
*/
|
|
39
|
+
opts?: {
|
|
40
|
+
build?: boolean;
|
|
41
|
+
onWarmProgress?: (p: WarmProgress) => void;
|
|
42
|
+
}): Promise<EmptyRefStates | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Build (or resume building) the empty reference wallet for a network, syncing
|
|
45
|
+
* it all the way to chain tip so it can actually pre-seed new wallets.
|
|
46
|
+
*
|
|
47
|
+
* This is the slow one: the first build walks the whole chain, which dust makes
|
|
48
|
+
* a tens-of-minutes job on preprod. It is worth paying once per network per
|
|
49
|
+
* machine, because afterwards every new wallet — and every dust rebuild — starts
|
|
50
|
+
* at tip instead of genesis. Intended for a background task or an explicit
|
|
51
|
+
* command, never the wallet-startup path.
|
|
52
|
+
*/
|
|
53
|
+
/**
|
|
54
|
+
* Sync an EXISTING reference forward to chain tip, instead of rebuilding it.
|
|
55
|
+
*
|
|
56
|
+
* ensureEmptyRefCache short-circuits on a warm reference, so before this the only
|
|
57
|
+
* way to update one was to delete it and walk the chain again — 53.6 min on
|
|
58
|
+
* preprod. That was never a limitation of the mechanism, only of the entry
|
|
59
|
+
* points: buildEmptyRefCache already resumes from whatever reference state the
|
|
60
|
+
* store holds (it syncs under EMPTY_REF_WALLET, and startWalletSync restores that
|
|
61
|
+
* wallet's cache like any other), so catching up costs the drift and nothing more.
|
|
62
|
+
*
|
|
63
|
+
* A stale reference is safe to use — it only means more catch-up for the wallets
|
|
64
|
+
* it seeds, at roughly half a second per hour of age — so this is an optimisation,
|
|
65
|
+
* not a repair. Run it before cutting a release, or on a schedule.
|
|
66
|
+
*/
|
|
67
|
+
export declare function refreshEmptyRefCache(network: NetworkConfig, onProgress?: (msg: string) => void, store?: SyncStateStore, onWarmProgress?: (p: WarmProgress) => void): Promise<EmptyRefStates | null>;
|
|
68
|
+
export declare function warmEmptyRefCache(network: NetworkConfig, onProgress?: (msg: string) => void, store?: SyncStateStore, onWarmProgress?: (p: WarmProgress) => void): Promise<EmptyRefStates | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Whether this network has a reference at chain tip, without building anything.
|
|
71
|
+
* Lets a UI distinguish "not started" from "in progress" from "done" — a build
|
|
72
|
+
* runs for an hour, so reporting it as perpetually in progress is misleading.
|
|
73
|
+
*/
|
|
74
|
+
export declare function preseedReferenceStatus(network: NetworkConfig, store?: SyncStateStore): Promise<{
|
|
75
|
+
ready: boolean;
|
|
76
|
+
height: number | null;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Pre-seed a newly generated wallet's sync state from the empty reference.
|
|
80
|
+
*
|
|
81
|
+
* - Shielded: reference's Zswap tree + offset, new wallet's public keys, empty coins
|
|
82
|
+
* - Unshielded: new wallet's public key, reference's indexer cursor, empty UTXOs
|
|
83
|
+
* - Dust: reference state as-is with the new wallet's dust public key swapped in.
|
|
84
|
+
* Dust ledger events are global (the indexer streams `dustLedgerEvents` keyed
|
|
85
|
+
* by a global id), and a wallet holding no NIGHT has no designations of its
|
|
86
|
+
* own to preserve, so the reference's generation tree and cursor transfer
|
|
87
|
+
* directly. This is the expensive one to get right: without it dust walks the
|
|
88
|
+
* whole chain, which is minutes-to-an-hour where shielded takes seconds.
|
|
89
|
+
*/
|
|
90
|
+
export declare function preSeedNewWallet(walletKeys: WalletKeys, networkId: string, emptyRef: EmptyRefStates): {
|
|
91
|
+
shielded: string;
|
|
92
|
+
unshielded: string;
|
|
93
|
+
dust?: string;
|
|
94
|
+
} | null;
|
|
95
|
+
//# sourceMappingURL=preseed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preseed.d.ts","sourceRoot":"","sources":["../../src/sync/preseed.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAA6E,KAAK,cAAc,EAAkB,MAAM,iBAAiB,CAAC;AAEjJ,OAAO,EAAmB,KAAK,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AA+FD;;;;GAIG;AAOH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,aAAa,EACtB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAClC,KAAK,CAAC,EAAE,cAAc;AACtB;;;;;;;GAOG;AACH,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;CAAE,GACrE,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA8BhC;AAED;;;;;;;;;GASG;AACH;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,aAAa,EACtB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAClC,KAAK,CAAC,EAAE,cAAc,EACtB,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACzC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAiBhC;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAClC,KAAK,CAAC,EAAE,cAAc,EACtB,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACzC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAEhC;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,aAAa,EACtB,KAAK,CAAC,EAAE,cAAc,GACrB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAIpD;AA+FD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,GACvB;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAC,GAAG,IAAI,CAgE9D"}
|