@miradexio/client 0.1.1 → 0.1.3
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 +57 -292
- package/dist/address/base58.d.ts.map +1 -1
- package/dist/address/base58.js +1 -2
- package/dist/address/base58.js.map +1 -1
- package/dist/address/bech32.d.ts +0 -8
- package/dist/address/bech32.d.ts.map +1 -1
- package/dist/address/bech32.js +3 -9
- package/dist/address/bech32.js.map +1 -1
- package/dist/address/evm.d.ts.map +1 -1
- package/dist/address/evm.js +1 -2
- package/dist/address/evm.js.map +1 -1
- package/dist/address/index.d.ts +0 -6
- package/dist/address/index.d.ts.map +1 -1
- package/dist/address/index.js +6 -9
- package/dist/address/index.js.map +1 -1
- package/dist/address/monero.d.ts +0 -10
- package/dist/address/monero.d.ts.map +1 -1
- package/dist/address/monero.js +4 -10
- package/dist/address/monero.js.map +1 -1
- package/dist/address/polkadot.d.ts +0 -5
- package/dist/address/polkadot.d.ts.map +1 -1
- package/dist/address/polkadot.js +2 -6
- package/dist/address/polkadot.js.map +1 -1
- package/dist/address/ton.d.ts +0 -6
- package/dist/address/ton.d.ts.map +1 -1
- package/dist/address/ton.js +3 -8
- package/dist/address/ton.js.map +1 -1
- package/dist/api/index.d.ts +0 -19
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +18 -37
- package/dist/api/index.js.map +1 -1
- package/dist/atomic-swap/drive.d.ts +0 -13
- package/dist/atomic-swap/drive.d.ts.map +1 -1
- package/dist/atomic-swap/drive.js +72 -114
- package/dist/atomic-swap/drive.js.map +1 -1
- package/dist/atomic-swap/extract.d.ts +0 -23
- package/dist/atomic-swap/extract.d.ts.map +1 -1
- package/dist/atomic-swap/extract.js +6 -16
- package/dist/atomic-swap/extract.js.map +1 -1
- package/dist/atomic-swap/index.d.ts +0 -7
- package/dist/atomic-swap/index.d.ts.map +1 -1
- package/dist/atomic-swap/index.js +1 -7
- package/dist/atomic-swap/index.js.map +1 -1
- package/dist/atomic-swap/monero-sweep/errors.d.ts.map +1 -1
- package/dist/atomic-swap/monero-sweep/errors.js +5 -20
- package/dist/atomic-swap/monero-sweep/errors.js.map +1 -1
- package/dist/atomic-swap/monero-sweep/index.d.ts +1 -13
- package/dist/atomic-swap/monero-sweep/index.d.ts.map +1 -1
- package/dist/atomic-swap/monero-sweep/index.js +36 -65
- package/dist/atomic-swap/monero-sweep/index.js.map +1 -1
- package/dist/atomic-swap/monero-sweep/ring-select.d.ts +0 -4
- package/dist/atomic-swap/monero-sweep/ring-select.d.ts.map +1 -1
- package/dist/atomic-swap/monero-sweep/ring-select.js +9 -21
- package/dist/atomic-swap/monero-sweep/ring-select.js.map +1 -1
- package/dist/atomic-swap/presign.d.ts +0 -63
- package/dist/atomic-swap/presign.d.ts.map +1 -1
- package/dist/atomic-swap/presign.js +30 -90
- package/dist/atomic-swap/presign.js.map +1 -1
- package/dist/atomic-swap/refund.d.ts +0 -18
- package/dist/atomic-swap/refund.d.ts.map +1 -1
- package/dist/atomic-swap/refund.js +16 -32
- package/dist/atomic-swap/refund.js.map +1 -1
- package/dist/atomic-swap/run.d.ts +0 -17
- package/dist/atomic-swap/run.d.ts.map +1 -1
- package/dist/atomic-swap/run.js +11 -25
- package/dist/atomic-swap/run.js.map +1 -1
- package/dist/atomic-swap/snapshot.d.ts +0 -30
- package/dist/atomic-swap/snapshot.d.ts.map +1 -1
- package/dist/atomic-swap/snapshot.js +8 -23
- package/dist/atomic-swap/snapshot.js.map +1 -1
- package/dist/atomic-swap/submit-encsig.d.ts +0 -7
- package/dist/atomic-swap/submit-encsig.d.ts.map +1 -1
- package/dist/atomic-swap/submit-encsig.js +8 -15
- package/dist/atomic-swap/submit-encsig.js.map +1 -1
- package/dist/atomic-swap/types.d.ts +2 -55
- package/dist/atomic-swap/types.d.ts.map +1 -1
- package/dist/atomic-swap/types.js +2 -3
- package/dist/atomic-swap/types.js.map +1 -1
- package/dist/blockchain/quorum-provider.d.ts +0 -15
- package/dist/blockchain/quorum-provider.d.ts.map +1 -1
- package/dist/blockchain/quorum-provider.js +7 -9
- package/dist/blockchain/quorum-provider.js.map +1 -1
- package/dist/cooperative-redeem.d.ts +5 -14
- package/dist/cooperative-redeem.d.ts.map +1 -1
- package/dist/cooperative-redeem.js +3 -20
- package/dist/cooperative-redeem.js.map +1 -1
- package/dist/engine/blockchain-querier.d.ts +0 -22
- package/dist/engine/blockchain-querier.d.ts.map +1 -1
- package/dist/engine/engine-state.d.ts +0 -8
- package/dist/engine/engine-state.d.ts.map +1 -1
- package/dist/engine/engine-state.js.map +1 -1
- package/dist/engine/flow-context.d.ts +0 -20
- package/dist/engine/flow-context.d.ts.map +1 -1
- package/dist/engine/flow-context.js +17 -41
- package/dist/engine/flow-context.js.map +1 -1
- package/dist/engine/flows/atomic-flow-state.d.ts +8 -1
- package/dist/engine/flows/atomic-flow-state.d.ts.map +1 -1
- package/dist/engine/flows/atomic-flow.d.ts +1 -28
- package/dist/engine/flows/atomic-flow.d.ts.map +1 -1
- package/dist/engine/flows/atomic-flow.js +98 -128
- package/dist/engine/flows/atomic-flow.js.map +1 -1
- package/dist/engine/flows/error-routing.d.ts +11 -0
- package/dist/engine/flows/error-routing.d.ts.map +1 -0
- package/dist/engine/flows/error-routing.js +17 -0
- package/dist/engine/flows/error-routing.js.map +1 -0
- package/dist/engine/flows/swap-flow.d.ts +0 -19
- package/dist/engine/flows/swap-flow.d.ts.map +1 -1
- package/dist/engine/flows/swap-flow.js +41 -83
- package/dist/engine/flows/swap-flow.js.map +1 -1
- package/dist/engine/miradex-engine.d.ts +1 -62
- package/dist/engine/miradex-engine.d.ts.map +1 -1
- package/dist/engine/miradex-engine.js +18 -50
- package/dist/engine/miradex-engine.js.map +1 -1
- package/dist/engine/pipeline.d.ts +0 -11
- package/dist/engine/pipeline.d.ts.map +1 -1
- package/dist/engine/pipeline.js +11 -21
- package/dist/engine/pipeline.js.map +1 -1
- package/dist/engine/platform.d.ts +0 -160
- package/dist/engine/platform.d.ts.map +1 -1
- package/dist/engine/platform.js +2 -0
- package/dist/engine/platform.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -11
- package/dist/index.js.map +1 -1
- package/dist/interfaces/blockchain.d.ts +1 -13
- package/dist/interfaces/blockchain.d.ts.map +1 -1
- package/dist/interfaces/blockchain.js +1 -0
- package/dist/interfaces/blockchain.js.map +1 -1
- package/dist/interfaces/logger.d.ts +0 -6
- package/dist/interfaces/logger.d.ts.map +1 -1
- package/dist/interfaces/logger.js.map +1 -1
- package/dist/lib/bitcoin/deposit-watcher.d.ts +0 -23
- package/dist/lib/bitcoin/deposit-watcher.d.ts.map +1 -1
- package/dist/lib/bitcoin/deposit-watcher.js +7 -31
- package/dist/lib/bitcoin/deposit-watcher.js.map +1 -1
- package/dist/lib/bitcoin/script-hash.d.ts.map +1 -1
- package/dist/lib/bitcoin/script-hash.js +2 -6
- package/dist/lib/bitcoin/script-hash.js.map +1 -1
- package/dist/lib/bitcoin/sweep.d.ts +0 -30
- package/dist/lib/bitcoin/sweep.d.ts.map +1 -1
- package/dist/lib/bitcoin/sweep.js +11 -40
- package/dist/lib/bitcoin/sweep.js.map +1 -1
- package/dist/lib/bitcoin/tx-verify.d.ts +0 -28
- package/dist/lib/bitcoin/tx-verify.d.ts.map +1 -1
- package/dist/lib/bitcoin/tx-verify.js +20 -61
- package/dist/lib/bitcoin/tx-verify.js.map +1 -1
- package/dist/lib/bitcoin/wallet.d.ts +0 -38
- package/dist/lib/bitcoin/wallet.d.ts.map +1 -1
- package/dist/lib/bitcoin/wallet.js +13 -38
- package/dist/lib/bitcoin/wallet.js.map +1 -1
- package/dist/lib/crypto/bytes.d.ts +0 -14
- package/dist/lib/crypto/bytes.d.ts.map +1 -1
- package/dist/lib/crypto/bytes.js +5 -14
- package/dist/lib/crypto/bytes.js.map +1 -1
- package/dist/lib/crypto/errors.d.ts +0 -5
- package/dist/lib/crypto/errors.d.ts.map +1 -1
- package/dist/lib/crypto/errors.js +2 -5
- package/dist/lib/crypto/errors.js.map +1 -1
- package/dist/lib/crypto/libp2p-identity.d.ts +0 -15
- package/dist/lib/crypto/libp2p-identity.d.ts.map +1 -1
- package/dist/lib/crypto/libp2p-identity.js +16 -28
- package/dist/lib/crypto/libp2p-identity.js.map +1 -1
- package/dist/lib/crypto/mnemonic.d.ts +0 -9
- package/dist/lib/crypto/mnemonic.d.ts.map +1 -1
- package/dist/lib/crypto/mnemonic.js +11 -27
- package/dist/lib/crypto/mnemonic.js.map +1 -1
- package/dist/lib/crypto/platform.d.ts +0 -6
- package/dist/lib/crypto/platform.d.ts.map +1 -1
- package/dist/lib/crypto/platform.js +2 -6
- package/dist/lib/crypto/platform.js.map +1 -1
- package/dist/lib/crypto/scalars.d.ts +0 -23
- package/dist/lib/crypto/scalars.d.ts.map +1 -1
- package/dist/lib/crypto/scalars.js +10 -23
- package/dist/lib/crypto/scalars.js.map +1 -1
- package/dist/lib/crypto/types.d.ts +0 -4
- package/dist/lib/crypto/types.d.ts.map +1 -1
- package/dist/lib/crypto/wasm.d.ts +0 -23
- package/dist/lib/crypto/wasm.d.ts.map +1 -1
- package/dist/lib/crypto/wasm.js +9 -16
- package/dist/lib/crypto/wasm.js.map +1 -1
- package/dist/lib/default-config.d.ts +1 -59
- package/dist/lib/default-config.d.ts.map +1 -1
- package/dist/lib/default-config.js +22 -61
- package/dist/lib/default-config.js.map +1 -1
- package/dist/lib/errors.d.ts +0 -54
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +12 -35
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/keystore.d.ts +0 -24
- package/dist/lib/keystore.d.ts.map +1 -1
- package/dist/lib/keystore.js +3 -10
- package/dist/lib/keystore.js.map +1 -1
- package/dist/lib/monero/output-scanner.d.ts +0 -18
- package/dist/lib/monero/output-scanner.d.ts.map +1 -1
- package/dist/lib/monero/output-scanner.js +17 -40
- package/dist/lib/monero/output-scanner.js.map +1 -1
- package/dist/lib/monero/rpc.d.ts +0 -64
- package/dist/lib/monero/rpc.d.ts.map +1 -1
- package/dist/lib/monero/rpc.js +17 -59
- package/dist/lib/monero/rpc.js.map +1 -1
- package/dist/lib/monero/verify-lock.d.ts +0 -12
- package/dist/lib/monero/verify-lock.d.ts.map +1 -1
- package/dist/lib/monero/verify-lock.js +9 -24
- package/dist/lib/monero/verify-lock.js.map +1 -1
- package/dist/lib/monero/verify-sweep.d.ts +0 -20
- package/dist/lib/monero/verify-sweep.d.ts.map +1 -1
- package/dist/lib/monero/verify-sweep.js +7 -25
- package/dist/lib/monero/verify-sweep.js.map +1 -1
- package/dist/lib/pow-solver.d.ts.map +1 -1
- package/dist/lib/pow-solver.js +3 -8
- package/dist/lib/pow-solver.js.map +1 -1
- package/dist/lib/retry.d.ts +7 -64
- package/dist/lib/retry.d.ts.map +1 -1
- package/dist/lib/retry.js +13 -13
- package/dist/lib/retry.js.map +1 -1
- package/dist/portable.d.ts.map +1 -1
- package/dist/portable.js +3 -4
- package/dist/portable.js.map +1 -1
- package/dist/quote-binding.d.ts +0 -13
- package/dist/quote-binding.d.ts.map +1 -1
- package/dist/quote-binding.js +3 -18
- package/dist/quote-binding.js.map +1 -1
- package/dist/swap-executor.d.ts +1 -5
- package/dist/swap-executor.d.ts.map +1 -1
- package/dist/swap-executor.js +1 -1
- package/dist/swap-executor.js.map +1 -1
- package/dist/types/api.d.ts +0 -6
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/api.js +6 -9
- package/dist/types/api.js.map +1 -1
- package/dist/types/errors.d.ts +0 -7
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +2 -7
- package/dist/types/errors.js.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/keys.d.ts +0 -15
- package/dist/types/keys.d.ts.map +1 -1
- package/dist/types/protocol.d.ts +0 -51
- package/dist/types/protocol.d.ts.map +1 -1
- package/dist/types/protocol.js +3 -8
- package/dist/types/protocol.js.map +1 -1
- package/dist/types/status.d.ts +2 -0
- package/dist/types/status.d.ts.map +1 -1
- package/dist/types/status.js +17 -14
- package/dist/types/status.js.map +1 -1
- package/dist/types/verification.d.ts +0 -10
- package/dist/types/verification.d.ts.map +1 -1
- package/dist/types/verification.js +7 -15
- package/dist/types/verification.js.map +1 -1
- package/dist/verification/chainflip-networks.d.ts +2 -35
- package/dist/verification/chainflip-networks.d.ts.map +1 -1
- package/dist/verification/chainflip-networks.js +12 -4
- package/dist/verification/chainflip-networks.js.map +1 -1
- package/dist/verification/chainflip.d.ts +0 -40
- package/dist/verification/chainflip.d.ts.map +1 -1
- package/dist/verification/chainflip.js +49 -129
- package/dist/verification/chainflip.js.map +1 -1
- package/dist/verification/constants.d.ts +0 -40
- package/dist/verification/constants.d.ts.map +1 -1
- package/dist/verification/constants.js +14 -40
- package/dist/verification/constants.js.map +1 -1
- package/dist/verification/index.d.ts +0 -26
- package/dist/verification/index.d.ts.map +1 -1
- package/dist/verification/index.js +8 -12
- package/dist/verification/index.js.map +1 -1
- package/dist/verification/memo.d.ts +0 -15
- package/dist/verification/memo.d.ts.map +1 -1
- package/dist/verification/memo.js +9 -27
- package/dist/verification/memo.js.map +1 -1
- package/dist/verification/near-intents.d.ts +0 -63
- package/dist/verification/near-intents.d.ts.map +1 -1
- package/dist/verification/near-intents.js +25 -67
- package/dist/verification/near-intents.js.map +1 -1
- package/dist/verification/rate-oracle.d.ts +0 -22
- package/dist/verification/rate-oracle.d.ts.map +1 -1
- package/dist/verification/rate-oracle.js +6 -11
- package/dist/verification/rate-oracle.js.map +1 -1
- package/dist/verification/thorchain-networks.d.ts +0 -27
- package/dist/verification/thorchain-networks.d.ts.map +1 -1
- package/dist/verification/thorchain-networks.js +13 -15
- package/dist/verification/thorchain-networks.js.map +1 -1
- package/dist/verification/thorchain.d.ts +0 -30
- package/dist/verification/thorchain.d.ts.map +1 -1
- package/dist/verification/thorchain.js +24 -47
- package/dist/verification/thorchain.js.map +1 -1
- package/dist/wasm-pins.d.ts +3 -3
- package/dist/wasm-pins.js +1 -1
- package/dist/wire/near-intents.zod.d.ts +0 -27
- package/dist/wire/near-intents.zod.d.ts.map +1 -1
- package/dist/wire/near-intents.zod.js +15 -23
- package/dist/wire/near-intents.zod.js.map +1 -1
- package/dist/wire/server/action.zod.d.ts +0 -10
- package/dist/wire/server/action.zod.d.ts.map +1 -1
- package/dist/wire/server/action.zod.js +8 -14
- package/dist/wire/server/action.zod.js.map +1 -1
- package/dist/wire/server/common.zod.d.ts +0 -13
- package/dist/wire/server/common.zod.d.ts.map +1 -1
- package/dist/wire/server/common.zod.js +6 -14
- package/dist/wire/server/common.zod.js.map +1 -1
- package/dist/wire/server/quotes.zod.d.ts +35 -20
- package/dist/wire/server/quotes.zod.d.ts.map +1 -1
- package/dist/wire/server/quotes.zod.js +1 -0
- package/dist/wire/server/quotes.zod.js.map +1 -1
- package/dist/wire/server/swap.zod.d.ts +0 -42
- package/dist/wire/server/swap.zod.d.ts.map +1 -1
- package/dist/wire/server/swap.zod.js +12 -26
- package/dist/wire/server/swap.zod.js.map +1 -1
- package/dist/wire/thorchain.zod.d.ts +0 -8
- package/dist/wire/thorchain.zod.d.ts.map +1 -1
- package/dist/wire/thorchain.zod.js +3 -8
- package/dist/wire/thorchain.zod.js.map +1 -1
- package/package.json +4 -4
- package/wasm/miradex-rust/README.md +3 -4
- package/wasm/miradex-rust/miradex_rust.d.ts +4 -6
- package/wasm/miradex-rust/miradex_rust.js +4 -6
- package/wasm/miradex-rust/miradex_rust_bg.wasm +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ApiError, NetworkError } from '../../api/index.js';
|
|
2
2
|
import { TERMINAL_STATUSES, ProtocolError } from '../../types/index.js';
|
|
3
|
+
import { routeError } from './error-routing.js';
|
|
3
4
|
import { createFlowContext, mergeFlowContext, validatePopulated, validateVerified, } from '../flow-context.js';
|
|
4
5
|
import { resumeAtomicSwap as coreResumeAtomicSwap, SwapCancelledError, } from '../../atomic-swap/index.js';
|
|
5
6
|
import { generateMnemonicKeys } from '../../lib/crypto/mnemonic.js';
|
|
@@ -16,6 +17,15 @@ import { buildMultisigWitnessScript } from '../../atomic-swap/presign.js';
|
|
|
16
17
|
import { extractProtocolData } from '../../atomic-swap/extract.js';
|
|
17
18
|
const DEFAULT_POLL_MS = 5_000;
|
|
18
19
|
const MAX_TRANSIENT_RETRIES = 5;
|
|
20
|
+
const SWAP_STATUS_STAGES = new Set([
|
|
21
|
+
'pending',
|
|
22
|
+
'awaiting_funding',
|
|
23
|
+
'initializing',
|
|
24
|
+
'deposited',
|
|
25
|
+
'swapping',
|
|
26
|
+
'sending',
|
|
27
|
+
'punished',
|
|
28
|
+
]);
|
|
19
29
|
function isTransientError(err) {
|
|
20
30
|
if (err instanceof NetworkError)
|
|
21
31
|
return true;
|
|
@@ -27,16 +37,14 @@ function isTransientError(err) {
|
|
|
27
37
|
}
|
|
28
38
|
return false;
|
|
29
39
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* until a separate TxReclaim phase (not yet implemented client-side).
|
|
39
|
-
*/
|
|
40
|
+
// True if the params carry enough material to refund without the sidecar.
|
|
41
|
+
// Two valid shapes:
|
|
42
|
+
// Legacy/Full: tx_full_refund_encsig alone (client builds + broadcasts
|
|
43
|
+
// TxFullRefund spending TxCancel).
|
|
44
|
+
// Partial: tx_partial_refund_encsig + amnesty triple
|
|
45
|
+
// (amnesty_amount_sats, tx_partial_refund_fee_sats). Amnesty
|
|
46
|
+
// output stays at multisig pending TxReclaim (not implemented
|
|
47
|
+
// client-side yet).
|
|
40
48
|
function hasRefundEscapeHatch(params) {
|
|
41
49
|
if (params.tx_full_refund_encsig)
|
|
42
50
|
return true;
|
|
@@ -59,22 +67,15 @@ export class AtomicFlow {
|
|
|
59
67
|
lastEmittedState = { phase: 'idle', snapshot: null };
|
|
60
68
|
flowCtx = null;
|
|
61
69
|
lastProgressKey = null;
|
|
70
|
+
lastSeenStatus = null;
|
|
62
71
|
pollMs;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
* second sweep — the server has no scanner for the on-chain XMR sweep,
|
|
68
|
-
* so a fresh `getSwapDetail` right after the driver completes still
|
|
69
|
-
* reports `requiredAction.type === 'sweep'`.
|
|
70
|
-
*/
|
|
72
|
+
// Set once the driver emits a terminal phase. Suppresses the post-driver
|
|
73
|
+
// requiredAction re-check that would otherwise trigger a phantom second
|
|
74
|
+
// sweep — the server has no scanner for the on-chain XMR sweep so a fresh
|
|
75
|
+
// getSwapDetail still reports requiredAction.type === 'sweep'.
|
|
71
76
|
hasReachedTerminal = false;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
* `params.variantId`. Set by `start()` from `StartAtomicSwapParams`;
|
|
75
|
-
* unused (and irrelevant) on the resume path because the maker is
|
|
76
|
-
* already chosen at that point.
|
|
77
|
-
*/
|
|
77
|
+
// Forwarded to coreResumeAtomicSwap as params.variantId. Set by start();
|
|
78
|
+
// ignored on resume (maker already chosen).
|
|
78
79
|
variantId;
|
|
79
80
|
constructor(api, platform, config, emitFn, options) {
|
|
80
81
|
this.api = api;
|
|
@@ -94,10 +95,7 @@ export class AtomicFlow {
|
|
|
94
95
|
? mergeFlowContext(this.flowCtx, partial)
|
|
95
96
|
: createFlowContext(partial);
|
|
96
97
|
}
|
|
97
|
-
|
|
98
|
-
* Validate FlowContext as PopulatedFlowContext.
|
|
99
|
-
* On failure, emits a 'failed' phase with structured error and returns null.
|
|
100
|
-
*/
|
|
98
|
+
// On failure, emits 'failed' with a structured error and returns null.
|
|
101
99
|
requirePopulated(phase) {
|
|
102
100
|
if (!this.flowCtx) {
|
|
103
101
|
this.emitError(phase, 'FlowContext not initialized');
|
|
@@ -110,10 +108,7 @@ export class AtomicFlow {
|
|
|
110
108
|
this.emitError(phase, result.error.message);
|
|
111
109
|
return null;
|
|
112
110
|
}
|
|
113
|
-
|
|
114
|
-
* Validate FlowContext as VerifiedFlowContext.
|
|
115
|
-
* On failure, emits a 'failed' phase with structured error and returns null.
|
|
116
|
-
*/
|
|
111
|
+
// On failure, emits 'failed' with a structured error and returns null.
|
|
117
112
|
requireVerified(phase) {
|
|
118
113
|
if (!this.flowCtx) {
|
|
119
114
|
this.emitError(phase, 'FlowContext not initialized');
|
|
@@ -168,17 +163,14 @@ export class AtomicFlow {
|
|
|
168
163
|
this.transition({ phase: 'keygen', snapshot: this.flowCtx, message: 'Initializing keygen...' });
|
|
169
164
|
await ensureWasm();
|
|
170
165
|
const network = this.config.network;
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
// flow is identical from this point forward — same deposit polling,
|
|
174
|
-
// same swap creation, same drive loop.
|
|
166
|
+
// Reuse an existing keystore (re-quote-after-failure) or generate a
|
|
167
|
+
// fresh one. Flow is identical past this point.
|
|
175
168
|
let wallet;
|
|
176
169
|
if (params.existingKeystoreId !== undefined) {
|
|
177
170
|
this.setFlowContext({ extra: { text: 'Loading keystore...', type: 'message' } });
|
|
178
171
|
this.transition({ phase: 'keygen', snapshot: this.flowCtx, message: 'Loading keystore...' });
|
|
179
|
-
// Trust
|
|
180
|
-
//
|
|
181
|
-
// doubling the call's transient-failure surface for a no-op check.
|
|
172
|
+
// Trust the keystore: it was created here and its keys already
|
|
173
|
+
// passed verifyKeys. Re-checking adds a transient-failure surface.
|
|
182
174
|
this.keystore = await this.platform.loadKeystore(params.existingKeystoreId);
|
|
183
175
|
this.keystoreId = params.existingKeystoreId;
|
|
184
176
|
wallet = walletFromWif(this.keystore.btc.wif, network);
|
|
@@ -216,16 +208,10 @@ export class AtomicFlow {
|
|
|
216
208
|
this.keystoreId = saveResult.id;
|
|
217
209
|
this.logger.info({ keystoreId: this.keystoreId }, 'Keystore saved');
|
|
218
210
|
}
|
|
219
|
-
// Emit
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
// snapshot.keystoreId` to decide whether to keep this engine; if
|
|
224
|
-
// the slow chain below blows the budget the engine is destroyed
|
|
225
|
-
// mid-flight and the user has to retry. Emitting a placeholder
|
|
226
|
-
// keystore-saved transition here guarantees the registry binds
|
|
227
|
-
// the engine on first save, regardless of subsequent network
|
|
228
|
-
// latency.
|
|
211
|
+
// Emit keystoreId before the slow pre-deposit chain (estimateFee,
|
|
212
|
+
// getQuotes, generateQr). EngineRegistry races a 30s timeout against
|
|
213
|
+
// state.atomic.snapshot.keystoreId — without this early emit the
|
|
214
|
+
// engine gets destroyed mid-flight on slow networks.
|
|
229
215
|
this.setFlowContext({ keystoreId: this.keystoreId });
|
|
230
216
|
this.transition({
|
|
231
217
|
phase: 'keystore-saved',
|
|
@@ -244,12 +230,8 @@ export class AtomicFlow {
|
|
|
244
230
|
}
|
|
245
231
|
catch { /* non-fatal */ }
|
|
246
232
|
const qr = await this.platform.generateQr(wallet.address);
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
// QR. The first `keystore-saved` transition above was the bare-
|
|
250
|
-
// bones state emit needed to keep the registry from destroying
|
|
251
|
-
// this engine; this second `setFlowContext` enriches it before
|
|
252
|
-
// `awaiting-deposit` validates against `PopulatedFlowContext`.
|
|
233
|
+
// Slow chain done: enrich FlowContext before awaiting-deposit validates
|
|
234
|
+
// against PopulatedFlowContext.
|
|
253
235
|
this.setFlowContext({
|
|
254
236
|
depositAddr: wallet.address,
|
|
255
237
|
depositAmount: requiredBtc,
|
|
@@ -258,7 +240,6 @@ export class AtomicFlow {
|
|
|
258
240
|
extra: { text: `Send ${requiredBtc} BTC to the address above.`, type: 'message' },
|
|
259
241
|
});
|
|
260
242
|
this.checkAborted();
|
|
261
|
-
// Validate before emitting awaiting-deposit
|
|
262
243
|
const populated = this.requirePopulated('awaiting-deposit');
|
|
263
244
|
if (!populated)
|
|
264
245
|
return;
|
|
@@ -334,15 +315,10 @@ export class AtomicFlow {
|
|
|
334
315
|
this.emitTerminal(existingSwapId, detail.status, detail);
|
|
335
316
|
return;
|
|
336
317
|
}
|
|
337
|
-
// Funding-address UTXO is only meaningful pre-broadcast
|
|
338
|
-
// swap is
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
// testnet/stagenet electrs (cold TLS, multi-server fallback,
|
|
342
|
-
// flaky public endpoints) and the result feeds nothing
|
|
343
|
-
// downstream once the protocol is past funding. Skip it for
|
|
344
|
-
// post-funding statuses so resume settles immediately on the
|
|
345
|
-
// current state instead of stalling on a useless network probe.
|
|
318
|
+
// Funding-address UTXO is only meaningful pre-broadcast; once the
|
|
319
|
+
// swap is 'deposited' or past, BTC is in TxLock and the funding
|
|
320
|
+
// address is empty. Re-querying costs 2-15s on flaky public
|
|
321
|
+
// electrs and feeds nothing downstream — skip for post-funding.
|
|
346
322
|
const PRE_FUNDING_STATUSES = new Set([
|
|
347
323
|
'initializing',
|
|
348
324
|
'pending',
|
|
@@ -353,7 +329,6 @@ export class AtomicFlow {
|
|
|
353
329
|
: null;
|
|
354
330
|
if (deposit)
|
|
355
331
|
this.deposit = deposit;
|
|
356
|
-
// Verify the contract for the resumed swap
|
|
357
332
|
let verification = null;
|
|
358
333
|
if (detail.depositAddress && detail.verification) {
|
|
359
334
|
const { verifyDepositAddress } = await import('../../verification/index.js');
|
|
@@ -364,8 +339,7 @@ export class AtomicFlow {
|
|
|
364
339
|
refundAddress: this.keystore.swap.refundAddress,
|
|
365
340
|
toToken: 'XMR',
|
|
366
341
|
amount: '',
|
|
367
|
-
//
|
|
368
|
-
// blocks come from the typed atomicswap params when present.
|
|
342
|
+
// lock_address = SwapDetail.depositAddress; timelock from typed params.
|
|
369
343
|
protocol: detail.depositAddress &&
|
|
370
344
|
detail.protocolData?.type === 'atomicswap' &&
|
|
371
345
|
detail.protocolData.params
|
|
@@ -379,7 +353,7 @@ export class AtomicFlow {
|
|
|
379
353
|
fetchFn: this.config.fetchFn,
|
|
380
354
|
});
|
|
381
355
|
}
|
|
382
|
-
//
|
|
356
|
+
// Server is past the verification gate; trust it.
|
|
383
357
|
if (!verification) {
|
|
384
358
|
verification = { verified: true, provider: 'atomicswap', checks: [], timestamp: Date.now() };
|
|
385
359
|
}
|
|
@@ -390,8 +364,8 @@ export class AtomicFlow {
|
|
|
390
364
|
depositAmount: deposit ? (deposit.value / 1e8).toFixed(8) : this.flowCtx?.depositAmount ?? null,
|
|
391
365
|
extra: { text: `Resuming swap (${detail.status})...`, type: 'message' },
|
|
392
366
|
});
|
|
393
|
-
//
|
|
394
|
-
//
|
|
367
|
+
// Core supplies verification via progress callbacks on resume; base
|
|
368
|
+
// FlowContext is enough for the entry transition.
|
|
395
369
|
this.transition({
|
|
396
370
|
phase: 'creating-swap',
|
|
397
371
|
snapshot: this.flowCtx,
|
|
@@ -402,10 +376,9 @@ export class AtomicFlow {
|
|
|
402
376
|
}
|
|
403
377
|
this.logger.info({ btcAddress }, 'Resume Path B: local keystore');
|
|
404
378
|
const deposit = await this.platform.fetchUtxo(btcAddress, network);
|
|
405
|
-
//
|
|
406
|
-
//
|
|
407
|
-
//
|
|
408
|
-
// with from the keystore metadata (saved by saveKeystore as `label`).
|
|
379
|
+
// expectedOut is required for PopulatedFlowContext. Pre-funding resume
|
|
380
|
+
// has no on-chain deposit, so pull the original amount from the
|
|
381
|
+
// keystore metadata (saveKeystore stores it as `label`).
|
|
409
382
|
let amountForQuote;
|
|
410
383
|
if (deposit) {
|
|
411
384
|
amountForQuote = (deposit.value / 1e8).toFixed(8);
|
|
@@ -522,9 +495,8 @@ export class AtomicFlow {
|
|
|
522
495
|
throw new Error('keystore must be set before driving swap');
|
|
523
496
|
}
|
|
524
497
|
const network = (this.keystore.btc?.network ?? 'mainnet');
|
|
525
|
-
//
|
|
526
|
-
//
|
|
527
|
-
// on resume). The provider is shared across the driver's lifetime.
|
|
498
|
+
// AV-B.2 (resume): the driver reconstructs TxLock via this provider when
|
|
499
|
+
// recomputing the redeem digest. Shared across the driver's lifetime.
|
|
528
500
|
const blockchain = await this.platform.createBlockchainProvider(network);
|
|
529
501
|
const result = await coreResumeAtomicSwap({
|
|
530
502
|
api: this.api,
|
|
@@ -544,13 +516,10 @@ export class AtomicFlow {
|
|
|
544
516
|
saveProtocolSnapshot: this.platform.saveProtocolSnapshot,
|
|
545
517
|
loadProtocolSnapshot: this.platform.loadProtocolSnapshot,
|
|
546
518
|
});
|
|
547
|
-
//
|
|
548
|
-
//
|
|
549
|
-
//
|
|
550
|
-
//
|
|
551
|
-
// status=sending right after the client broadcast its sweep tx. Treating
|
|
552
|
-
// that as actionable triggers a phantom second executeSweep that emits a
|
|
553
|
-
// spurious `completed → sweeping` transition.
|
|
519
|
+
// Skip the server re-check if mapCoreProgress already emitted terminal:
|
|
520
|
+
// the server has no on-chain XMR scanner so it still reports
|
|
521
|
+
// requiredAction=sweep right after our broadcast, which would trigger a
|
|
522
|
+
// phantom second executeSweep and a spurious completed -> sweeping flicker.
|
|
554
523
|
if (this.hasReachedTerminal)
|
|
555
524
|
return;
|
|
556
525
|
let finalStatus = 'completed';
|
|
@@ -574,11 +543,9 @@ export class AtomicFlow {
|
|
|
574
543
|
this.emitTerminal(result.swapId, finalStatus, undefined);
|
|
575
544
|
return;
|
|
576
545
|
}
|
|
577
|
-
// Non-terminal
|
|
578
|
-
//
|
|
579
|
-
//
|
|
580
|
-
// needs to watch for the requiredAction to flip to 'refund' (or the
|
|
581
|
-
// swap to reach terminal). pollUntilTerminal does both.
|
|
546
|
+
// Non-terminal with no actionable requiredAction (e.g. server still
|
|
547
|
+
// broadcasting TxCancel). Sidecar handles cancel; we wait for the
|
|
548
|
+
// action to flip to 'refund' or the swap to reach terminal.
|
|
582
549
|
this.setFlowContext({
|
|
583
550
|
extra: { text: requiredAction?.message ?? 'Waiting for server...', type: 'message' },
|
|
584
551
|
});
|
|
@@ -596,6 +563,9 @@ export class AtomicFlow {
|
|
|
596
563
|
this.setFlowContext({ swapNumber: p.swapNumber });
|
|
597
564
|
if (p.verification)
|
|
598
565
|
this.setFlowContext({ verification: p.verification });
|
|
566
|
+
if (SWAP_STATUS_STAGES.has(p.stage)) {
|
|
567
|
+
this.lastSeenStatus = p.stage;
|
|
568
|
+
}
|
|
599
569
|
switch (p.stage) {
|
|
600
570
|
case 'keygen':
|
|
601
571
|
case 'keystore_saved':
|
|
@@ -671,10 +641,9 @@ export class AtomicFlow {
|
|
|
671
641
|
phase: 'completed',
|
|
672
642
|
snapshot: this.flowCtx,
|
|
673
643
|
outputTxHash: p.txHash ?? null,
|
|
674
|
-
// Atomic swaps have no slippage
|
|
675
|
-
//
|
|
676
|
-
//
|
|
677
|
-
// even when the in-flight progress event doesn't carry it.
|
|
644
|
+
// Atomic swaps have no slippage; buyer receives exactly rate * deposit.
|
|
645
|
+
// Fall back to expectedOut so the receipt shows the right number even
|
|
646
|
+
// when the progress event doesn't carry it.
|
|
678
647
|
actualOut: this.flowCtx?.expectedOut ?? '',
|
|
679
648
|
durationSec: null,
|
|
680
649
|
});
|
|
@@ -708,9 +677,8 @@ export class AtomicFlow {
|
|
|
708
677
|
});
|
|
709
678
|
break;
|
|
710
679
|
case 'cancelling':
|
|
711
|
-
//
|
|
712
|
-
//
|
|
713
|
-
// settles in `refunded` (or `failed` if the refund never lands).
|
|
680
|
+
// TxCancel in flight; refund follows. Stay watching until the row
|
|
681
|
+
// settles in 'refunded' (or 'failed' if the refund never lands).
|
|
714
682
|
this.setFlowContext({ extra: { text: p.message, type: 'warning' } });
|
|
715
683
|
this.transition({
|
|
716
684
|
phase: 'creating-swap',
|
|
@@ -720,11 +688,8 @@ export class AtomicFlow {
|
|
|
720
688
|
break;
|
|
721
689
|
case 'withheld':
|
|
722
690
|
case 'expired':
|
|
723
|
-
//
|
|
724
|
-
//
|
|
725
|
-
// terminal statuses in `TerminalStatus`. Emit a `failed` phase so
|
|
726
|
-
// poll consumers (engine driver, TUI exec state) observe a terminal
|
|
727
|
-
// transition and resolve.
|
|
691
|
+
// Both are terminal in TerminalStatus. Emit 'failed' so poll
|
|
692
|
+
// consumers see a terminal transition and resolve.
|
|
728
693
|
this.transition({
|
|
729
694
|
phase: 'failed',
|
|
730
695
|
snapshot: this.flowCtx,
|
|
@@ -733,12 +698,9 @@ export class AtomicFlow {
|
|
|
733
698
|
break;
|
|
734
699
|
case 'punished': {
|
|
735
700
|
// Not terminal. Alice published TxPunish (Bob missed the refund
|
|
736
|
-
// window), but the sidecar
|
|
737
|
-
//
|
|
738
|
-
//
|
|
739
|
-
// the driver finishes the swap with an XMR sweep that lands the row
|
|
740
|
-
// in `completed`. Stay in a watching phase so `drive.ts`'s existing
|
|
741
|
-
// sweep branch can pick up the action transition.
|
|
701
|
+
// window), but the sidecar runs cooperative_xmr_redeem_after_punish
|
|
702
|
+
// to recover s_a; the server then flips requiredAction to 'sweep'
|
|
703
|
+
// and drive.ts finishes via the sweep branch.
|
|
742
704
|
const reason = p.message ||
|
|
743
705
|
'BTC punished — recovering XMR via cooperative_xmr_redeem_after_punish...';
|
|
744
706
|
this.setFlowContext({ extra: { text: reason, type: 'warning' } });
|
|
@@ -836,6 +798,7 @@ export class AtomicFlow {
|
|
|
836
798
|
receiveAddress: this.keystore.swap.receiveAddress,
|
|
837
799
|
expectedSAMonero: pp.S_a_monero,
|
|
838
800
|
monerodNodes: this.config.monerodNodes,
|
|
801
|
+
signal: this.signal,
|
|
839
802
|
onProgress: (stage) => {
|
|
840
803
|
const sweepStep = stage.includes('key') ? 'key-images'
|
|
841
804
|
: stage.includes('submit') || stage.includes('broadcast') ? 'broadcasting'
|
|
@@ -1052,12 +1015,10 @@ export class AtomicFlow {
|
|
|
1052
1015
|
}
|
|
1053
1016
|
return '';
|
|
1054
1017
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
* refunds survive a briefly-unreachable backend.
|
|
1060
|
-
*/
|
|
1018
|
+
// Server response first; fall back to the platform adapter's optional
|
|
1019
|
+
// write-through cache when the server omitted the refund encsig. On a
|
|
1020
|
+
// good server response, prime the cache so later refunds survive a brief
|
|
1021
|
+
// backend outage.
|
|
1061
1022
|
async resolveProtocolParams(swapId, detail) {
|
|
1062
1023
|
const fromServer = extractProtocolData(detail).params;
|
|
1063
1024
|
if (fromServer && hasRefundEscapeHatch(fromServer)) {
|
|
@@ -1109,17 +1070,14 @@ export class AtomicFlow {
|
|
|
1109
1070
|
this.emitTerminal(swapId, detail.status, detail);
|
|
1110
1071
|
return;
|
|
1111
1072
|
}
|
|
1112
|
-
//
|
|
1113
|
-
//
|
|
1114
|
-
// briefly unreachable later.
|
|
1073
|
+
// Prime the protocol cache while the server is up; the refund path
|
|
1074
|
+
// falls back to it if the server goes down later.
|
|
1115
1075
|
const polledParams = extractProtocolData(detail).params;
|
|
1116
1076
|
if (polledParams?.tx_full_refund_encsig) {
|
|
1117
1077
|
await this.cacheProtocolParams(swapId, polledParams);
|
|
1118
1078
|
}
|
|
1119
|
-
//
|
|
1120
|
-
//
|
|
1121
|
-
// the client-side refund so we don't drift toward the punish
|
|
1122
|
-
// deadline while idly polling.
|
|
1079
|
+
// 'refund' flip means TxCancel confirmed and the refund window is
|
|
1080
|
+
// open. Auto-trigger so we don't drift toward the punish deadline.
|
|
1123
1081
|
const action = detail.requiredAction ?? null;
|
|
1124
1082
|
if (action?.type === 'refund') {
|
|
1125
1083
|
this.logger.info({ swapId, blocksRemaining: action.blocksRemaining ?? null }, 'Required action flipped to refund — auto-triggering client-side refund');
|
|
@@ -1170,17 +1128,29 @@ export class AtomicFlow {
|
|
|
1170
1128
|
throw new SwapCancelledError();
|
|
1171
1129
|
}
|
|
1172
1130
|
handleError(err) {
|
|
1173
|
-
|
|
1174
|
-
|
|
1131
|
+
const route = routeError(err, this.signal.aborted, this.lastSeenStatus);
|
|
1132
|
+
const swapId = this.flowCtx?.swapId ?? null;
|
|
1133
|
+
if (route.kind === 'cancelled') {
|
|
1134
|
+
this.logger.info({ swapId }, 'AtomicFlow cancelled');
|
|
1175
1135
|
this.transition({ phase: 'cancelled', snapshot: this.flowCtx, swapId: null, txCancelTxid: null });
|
|
1176
1136
|
return;
|
|
1177
1137
|
}
|
|
1178
|
-
|
|
1179
|
-
this.
|
|
1180
|
-
|
|
1138
|
+
this.logger.error({ swapId, error: route.message, kind: route.kind }, 'AtomicFlow error');
|
|
1139
|
+
this.setFlowContext({ extra: { text: route.message, type: 'error' } });
|
|
1140
|
+
if (route.kind === 'stalled') {
|
|
1141
|
+
this.transition({
|
|
1142
|
+
phase: 'stalled',
|
|
1143
|
+
snapshot: this.flowCtx,
|
|
1144
|
+
error: route.message,
|
|
1145
|
+
swapId,
|
|
1146
|
+
keystoreId: this.keystoreId.length > 0 ? this.keystoreId : null,
|
|
1147
|
+
});
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1181
1150
|
this.transition({
|
|
1182
|
-
phase: 'failed',
|
|
1183
|
-
|
|
1151
|
+
phase: 'failed',
|
|
1152
|
+
snapshot: this.flowCtx,
|
|
1153
|
+
error: route.message,
|
|
1184
1154
|
});
|
|
1185
1155
|
}
|
|
1186
1156
|
getCurrentAwaitingActionState() {
|