@miradexio/client 0.1.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/LICENSE +21 -0
- package/README.md +405 -0
- package/dist/address/base58.d.ts +9 -0
- package/dist/address/base58.d.ts.map +1 -0
- package/dist/address/base58.js +33 -0
- package/dist/address/base58.js.map +1 -0
- package/dist/address/bech32.d.ts +13 -0
- package/dist/address/bech32.d.ts.map +1 -0
- package/dist/address/bech32.js +41 -0
- package/dist/address/bech32.js.map +1 -0
- package/dist/address/evm.d.ts +5 -0
- package/dist/address/evm.d.ts.map +1 -0
- package/dist/address/evm.js +27 -0
- package/dist/address/evm.js.map +1 -0
- package/dist/address/index.d.ts +15 -0
- package/dist/address/index.d.ts.map +1 -0
- package/dist/address/index.js +134 -0
- package/dist/address/index.js.map +1 -0
- package/dist/address/monero.d.ts +15 -0
- package/dist/address/monero.d.ts.map +1 -0
- package/dist/address/monero.js +30 -0
- package/dist/address/monero.js.map +1 -0
- package/dist/address/polkadot.d.ts +10 -0
- package/dist/address/polkadot.d.ts.map +1 -0
- package/dist/address/polkadot.js +36 -0
- package/dist/address/polkadot.js.map +1 -0
- package/dist/address/solana.d.ts +5 -0
- package/dist/address/solana.d.ts.map +1 -0
- package/dist/address/solana.js +17 -0
- package/dist/address/solana.js.map +1 -0
- package/dist/address/ton.d.ts +11 -0
- package/dist/address/ton.d.ts.map +1 -0
- package/dist/address/ton.js +28 -0
- package/dist/address/ton.js.map +1 -0
- package/dist/api/index.d.ts +80 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +213 -0
- package/dist/api/index.js.map +1 -0
- package/dist/atomic-swap/drive.d.ts +22 -0
- package/dist/atomic-swap/drive.d.ts.map +1 -0
- package/dist/atomic-swap/drive.js +713 -0
- package/dist/atomic-swap/drive.js.map +1 -0
- package/dist/atomic-swap/extract.d.ts +46 -0
- package/dist/atomic-swap/extract.d.ts.map +1 -0
- package/dist/atomic-swap/extract.js +55 -0
- package/dist/atomic-swap/extract.js.map +1 -0
- package/dist/atomic-swap/index.d.ts +15 -0
- package/dist/atomic-swap/index.d.ts.map +1 -0
- package/dist/atomic-swap/index.js +13 -0
- package/dist/atomic-swap/index.js.map +1 -0
- package/dist/atomic-swap/monero-sweep/errors.d.ts +2 -0
- package/dist/atomic-swap/monero-sweep/errors.d.ts.map +1 -0
- package/dist/atomic-swap/monero-sweep/errors.js +43 -0
- package/dist/atomic-swap/monero-sweep/errors.js.map +1 -0
- package/dist/atomic-swap/monero-sweep/index.d.ts +33 -0
- package/dist/atomic-swap/monero-sweep/index.d.ts.map +1 -0
- package/dist/atomic-swap/monero-sweep/index.js +415 -0
- package/dist/atomic-swap/monero-sweep/index.js.map +1 -0
- package/dist/atomic-swap/monero-sweep/ring-select.d.ts +12 -0
- package/dist/atomic-swap/monero-sweep/ring-select.d.ts.map +1 -0
- package/dist/atomic-swap/monero-sweep/ring-select.js +61 -0
- package/dist/atomic-swap/monero-sweep/ring-select.js.map +1 -0
- package/dist/atomic-swap/presign.d.ts +101 -0
- package/dist/atomic-swap/presign.d.ts.map +1 -0
- package/dist/atomic-swap/presign.js +460 -0
- package/dist/atomic-swap/presign.js.map +1 -0
- package/dist/atomic-swap/refund.d.ts +72 -0
- package/dist/atomic-swap/refund.d.ts.map +1 -0
- package/dist/atomic-swap/refund.js +224 -0
- package/dist/atomic-swap/refund.js.map +1 -0
- package/dist/atomic-swap/run.d.ts +27 -0
- package/dist/atomic-swap/run.d.ts.map +1 -0
- package/dist/atomic-swap/run.js +282 -0
- package/dist/atomic-swap/run.js.map +1 -0
- package/dist/atomic-swap/snapshot.d.ts +111 -0
- package/dist/atomic-swap/snapshot.d.ts.map +1 -0
- package/dist/atomic-swap/snapshot.js +69 -0
- package/dist/atomic-swap/snapshot.js.map +1 -0
- package/dist/atomic-swap/submit-encsig.d.ts +10 -0
- package/dist/atomic-swap/submit-encsig.d.ts.map +1 -0
- package/dist/atomic-swap/submit-encsig.js +56 -0
- package/dist/atomic-swap/submit-encsig.js.map +1 -0
- package/dist/atomic-swap/types.d.ts +168 -0
- package/dist/atomic-swap/types.d.ts.map +1 -0
- package/dist/atomic-swap/types.js +5 -0
- package/dist/atomic-swap/types.js.map +1 -0
- package/dist/blockchain/quorum-provider.d.ts +25 -0
- package/dist/blockchain/quorum-provider.d.ts.map +1 -0
- package/dist/blockchain/quorum-provider.js +144 -0
- package/dist/blockchain/quorum-provider.js.map +1 -0
- package/dist/cooperative-redeem.d.ts +23 -0
- package/dist/cooperative-redeem.d.ts.map +1 -0
- package/dist/cooperative-redeem.js +40 -0
- package/dist/cooperative-redeem.js.map +1 -0
- package/dist/engine/blockchain-querier.d.ts +34 -0
- package/dist/engine/blockchain-querier.d.ts.map +1 -0
- package/dist/engine/blockchain-querier.js +2 -0
- package/dist/engine/blockchain-querier.js.map +1 -0
- package/dist/engine/engine-state.d.ts +20 -0
- package/dist/engine/engine-state.d.ts.map +1 -0
- package/dist/engine/engine-state.js +9 -0
- package/dist/engine/engine-state.js.map +1 -0
- package/dist/engine/flow-context.d.ts +494 -0
- package/dist/engine/flow-context.d.ts.map +1 -0
- package/dist/engine/flow-context.js +147 -0
- package/dist/engine/flow-context.js.map +1 -0
- package/dist/engine/flows/atomic-flow-state.d.ts +124 -0
- package/dist/engine/flows/atomic-flow-state.d.ts.map +1 -0
- package/dist/engine/flows/atomic-flow-state.js +2 -0
- package/dist/engine/flows/atomic-flow-state.js.map +1 -0
- package/dist/engine/flows/atomic-flow.d.ts +88 -0
- package/dist/engine/flows/atomic-flow.d.ts.map +1 -0
- package/dist/engine/flows/atomic-flow.js +1192 -0
- package/dist/engine/flows/atomic-flow.js.map +1 -0
- package/dist/engine/flows/history-flow-state.d.ts +19 -0
- package/dist/engine/flows/history-flow-state.d.ts.map +1 -0
- package/dist/engine/flows/history-flow-state.js +2 -0
- package/dist/engine/flows/history-flow-state.js.map +1 -0
- package/dist/engine/flows/providers-flow-state.d.ts +14 -0
- package/dist/engine/flows/providers-flow-state.d.ts.map +1 -0
- package/dist/engine/flows/providers-flow-state.js +2 -0
- package/dist/engine/flows/providers-flow-state.js.map +1 -0
- package/dist/engine/flows/quote-flow-state.d.ts +20 -0
- package/dist/engine/flows/quote-flow-state.d.ts.map +1 -0
- package/dist/engine/flows/quote-flow-state.js +2 -0
- package/dist/engine/flows/quote-flow-state.js.map +1 -0
- package/dist/engine/flows/swap-flow-state.d.ts +155 -0
- package/dist/engine/flows/swap-flow-state.d.ts.map +1 -0
- package/dist/engine/flows/swap-flow-state.js +2 -0
- package/dist/engine/flows/swap-flow-state.js.map +1 -0
- package/dist/engine/flows/swap-flow.d.ts +81 -0
- package/dist/engine/flows/swap-flow.d.ts.map +1 -0
- package/dist/engine/flows/swap-flow.js +720 -0
- package/dist/engine/flows/swap-flow.js.map +1 -0
- package/dist/engine/flows/tokens-flow-state.d.ts +16 -0
- package/dist/engine/flows/tokens-flow-state.d.ts.map +1 -0
- package/dist/engine/flows/tokens-flow-state.js +2 -0
- package/dist/engine/flows/tokens-flow-state.js.map +1 -0
- package/dist/engine/miradex-engine.d.ts +152 -0
- package/dist/engine/miradex-engine.d.ts.map +1 -0
- package/dist/engine/miradex-engine.js +278 -0
- package/dist/engine/miradex-engine.js.map +1 -0
- package/dist/engine/pipeline.d.ts +27 -0
- package/dist/engine/pipeline.d.ts.map +1 -0
- package/dist/engine/pipeline.js +166 -0
- package/dist/engine/pipeline.js.map +1 -0
- package/dist/engine/platform.d.ts +220 -0
- package/dist/engine/platform.d.ts.map +1 -0
- package/dist/engine/platform.js +2 -0
- package/dist/engine/platform.js.map +1 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/blockchain.d.ts +33 -0
- package/dist/interfaces/blockchain.d.ts.map +1 -0
- package/dist/interfaces/blockchain.js +2 -0
- package/dist/interfaces/blockchain.js.map +1 -0
- package/dist/interfaces/logger.d.ts +14 -0
- package/dist/interfaces/logger.d.ts.map +1 -0
- package/dist/interfaces/logger.js +7 -0
- package/dist/interfaces/logger.js.map +1 -0
- package/dist/lib/bitcoin/deposit-watcher.d.ts +66 -0
- package/dist/lib/bitcoin/deposit-watcher.d.ts.map +1 -0
- package/dist/lib/bitcoin/deposit-watcher.js +218 -0
- package/dist/lib/bitcoin/deposit-watcher.js.map +1 -0
- package/dist/lib/bitcoin/script-hash.d.ts +8 -0
- package/dist/lib/bitcoin/script-hash.d.ts.map +1 -0
- package/dist/lib/bitcoin/script-hash.js +29 -0
- package/dist/lib/bitcoin/script-hash.js.map +1 -0
- package/dist/lib/bitcoin/sweep.d.ts +56 -0
- package/dist/lib/bitcoin/sweep.d.ts.map +1 -0
- package/dist/lib/bitcoin/sweep.js +185 -0
- package/dist/lib/bitcoin/sweep.js.map +1 -0
- package/dist/lib/bitcoin/tx-verify.d.ts +43 -0
- package/dist/lib/bitcoin/tx-verify.d.ts.map +1 -0
- package/dist/lib/bitcoin/tx-verify.js +202 -0
- package/dist/lib/bitcoin/tx-verify.js.map +1 -0
- package/dist/lib/bitcoin/wallet.d.ts +71 -0
- package/dist/lib/bitcoin/wallet.d.ts.map +1 -0
- package/dist/lib/bitcoin/wallet.js +141 -0
- package/dist/lib/bitcoin/wallet.js.map +1 -0
- package/dist/lib/crypto/bytes.d.ts +21 -0
- package/dist/lib/crypto/bytes.d.ts.map +1 -0
- package/dist/lib/crypto/bytes.js +39 -0
- package/dist/lib/crypto/bytes.js.map +1 -0
- package/dist/lib/crypto/errors.d.ts +12 -0
- package/dist/lib/crypto/errors.d.ts.map +1 -0
- package/dist/lib/crypto/errors.js +16 -0
- package/dist/lib/crypto/errors.js.map +1 -0
- package/dist/lib/crypto/keygen.d.ts +19 -0
- package/dist/lib/crypto/keygen.d.ts.map +1 -0
- package/dist/lib/crypto/keygen.js +24 -0
- package/dist/lib/crypto/keygen.js.map +1 -0
- package/dist/lib/crypto/libp2p-identity.d.ts +25 -0
- package/dist/lib/crypto/libp2p-identity.d.ts.map +1 -0
- package/dist/lib/crypto/libp2p-identity.js +80 -0
- package/dist/lib/crypto/libp2p-identity.js.map +1 -0
- package/dist/lib/crypto/mnemonic.d.ts +28 -0
- package/dist/lib/crypto/mnemonic.d.ts.map +1 -0
- package/dist/lib/crypto/mnemonic.js +97 -0
- package/dist/lib/crypto/mnemonic.js.map +1 -0
- package/dist/lib/crypto/platform.d.ts +10 -0
- package/dist/lib/crypto/platform.d.ts.map +1 -0
- package/dist/lib/crypto/platform.js +38 -0
- package/dist/lib/crypto/platform.js.map +1 -0
- package/dist/lib/crypto/scalars.d.ts +33 -0
- package/dist/lib/crypto/scalars.d.ts.map +1 -0
- package/dist/lib/crypto/scalars.js +81 -0
- package/dist/lib/crypto/scalars.js.map +1 -0
- package/dist/lib/crypto/types.d.ts +24 -0
- package/dist/lib/crypto/types.d.ts.map +1 -0
- package/dist/lib/crypto/types.js +2 -0
- package/dist/lib/crypto/types.js.map +1 -0
- package/dist/lib/crypto/wasm.d.ts +51 -0
- package/dist/lib/crypto/wasm.d.ts.map +1 -0
- package/dist/lib/crypto/wasm.js +192 -0
- package/dist/lib/crypto/wasm.js.map +1 -0
- package/dist/lib/default-config.d.ts +140 -0
- package/dist/lib/default-config.d.ts.map +1 -0
- package/dist/lib/default-config.js +239 -0
- package/dist/lib/default-config.js.map +1 -0
- package/dist/lib/delay.d.ts +6 -0
- package/dist/lib/delay.d.ts.map +1 -0
- package/dist/lib/delay.js +20 -0
- package/dist/lib/delay.js.map +1 -0
- package/dist/lib/errors.d.ts +90 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +129 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/format.d.ts +7 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +43 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/keystore.d.ts +85 -0
- package/dist/lib/keystore.d.ts.map +1 -0
- package/dist/lib/keystore.js +105 -0
- package/dist/lib/keystore.js.map +1 -0
- package/dist/lib/monero/output-scanner.d.ts +53 -0
- package/dist/lib/monero/output-scanner.d.ts.map +1 -0
- package/dist/lib/monero/output-scanner.js +180 -0
- package/dist/lib/monero/output-scanner.js.map +1 -0
- package/dist/lib/monero/rpc.d.ts +131 -0
- package/dist/lib/monero/rpc.d.ts.map +1 -0
- package/dist/lib/monero/rpc.js +267 -0
- package/dist/lib/monero/rpc.js.map +1 -0
- package/dist/lib/monero/verify-lock.d.ts +50 -0
- package/dist/lib/monero/verify-lock.d.ts.map +1 -0
- package/dist/lib/monero/verify-lock.js +161 -0
- package/dist/lib/monero/verify-lock.js.map +1 -0
- package/dist/lib/monero/verify-sweep.d.ts +59 -0
- package/dist/lib/monero/verify-sweep.d.ts.map +1 -0
- package/dist/lib/monero/verify-sweep.js +82 -0
- package/dist/lib/monero/verify-sweep.js.map +1 -0
- package/dist/lib/monero/wasm.d.ts +19 -0
- package/dist/lib/monero/wasm.d.ts.map +1 -0
- package/dist/lib/monero/wasm.js +24 -0
- package/dist/lib/monero/wasm.js.map +1 -0
- package/dist/lib/pow-solver.d.ts +4 -0
- package/dist/lib/pow-solver.d.ts.map +1 -0
- package/dist/lib/pow-solver.js +37 -0
- package/dist/lib/pow-solver.js.map +1 -0
- package/dist/lib/retry.d.ts +86 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/lib/retry.js +104 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/portable.d.ts +23 -0
- package/dist/portable.d.ts.map +1 -0
- package/dist/portable.js +13 -0
- package/dist/portable.js.map +1 -0
- package/dist/quote-binding.d.ts +31 -0
- package/dist/quote-binding.d.ts.map +1 -0
- package/dist/quote-binding.js +40 -0
- package/dist/quote-binding.js.map +1 -0
- package/dist/swap-executor.d.ts +51 -0
- package/dist/swap-executor.d.ts.map +1 -0
- package/dist/swap-executor.js +138 -0
- package/dist/swap-executor.js.map +1 -0
- package/dist/types/api.d.ts +34 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +18 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/errors.d.ts +94 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +93 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/keys.d.ts +33 -0
- package/dist/types/keys.d.ts.map +1 -0
- package/dist/types/keys.js +2 -0
- package/dist/types/keys.js.map +1 -0
- package/dist/types/protocol.d.ts +93 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +18 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types/status.d.ts +3 -0
- package/dist/types/status.d.ts.map +1 -0
- package/dist/types/status.js +23 -0
- package/dist/types/status.js.map +1 -0
- package/dist/types/verification.d.ts +49 -0
- package/dist/types/verification.d.ts.map +1 -0
- package/dist/types/verification.js +34 -0
- package/dist/types/verification.js.map +1 -0
- package/dist/verification/atomic-swap.d.ts +9 -0
- package/dist/verification/atomic-swap.d.ts.map +1 -0
- package/dist/verification/atomic-swap.js +22 -0
- package/dist/verification/atomic-swap.js.map +1 -0
- package/dist/verification/chainflip-networks.d.ts +46 -0
- package/dist/verification/chainflip-networks.d.ts.map +1 -0
- package/dist/verification/chainflip-networks.js +24 -0
- package/dist/verification/chainflip-networks.js.map +1 -0
- package/dist/verification/chainflip.d.ts +61 -0
- package/dist/verification/chainflip.d.ts.map +1 -0
- package/dist/verification/chainflip.js +377 -0
- package/dist/verification/chainflip.js.map +1 -0
- package/dist/verification/constants.d.ts +52 -0
- package/dist/verification/constants.d.ts.map +1 -0
- package/dist/verification/constants.js +54 -0
- package/dist/verification/constants.js.map +1 -0
- package/dist/verification/index.d.ts +71 -0
- package/dist/verification/index.d.ts.map +1 -0
- package/dist/verification/index.js +91 -0
- package/dist/verification/index.js.map +1 -0
- package/dist/verification/memo.d.ts +27 -0
- package/dist/verification/memo.d.ts.map +1 -0
- package/dist/verification/memo.js +52 -0
- package/dist/verification/memo.js.map +1 -0
- package/dist/verification/near-intents.d.ts +91 -0
- package/dist/verification/near-intents.d.ts.map +1 -0
- package/dist/verification/near-intents.js +213 -0
- package/dist/verification/near-intents.js.map +1 -0
- package/dist/verification/rate-oracle.d.ts +32 -0
- package/dist/verification/rate-oracle.d.ts.map +1 -0
- package/dist/verification/rate-oracle.js +43 -0
- package/dist/verification/rate-oracle.js.map +1 -0
- package/dist/verification/shared.d.ts +20 -0
- package/dist/verification/shared.d.ts.map +1 -0
- package/dist/verification/shared.js +25 -0
- package/dist/verification/shared.js.map +1 -0
- package/dist/verification/thorchain-networks.d.ts +35 -0
- package/dist/verification/thorchain-networks.d.ts.map +1 -0
- package/dist/verification/thorchain-networks.js +35 -0
- package/dist/verification/thorchain-networks.js.map +1 -0
- package/dist/verification/thorchain.d.ts +55 -0
- package/dist/verification/thorchain.d.ts.map +1 -0
- package/dist/verification/thorchain.js +232 -0
- package/dist/verification/thorchain.js.map +1 -0
- package/dist/wasm-pins.d.ts +4 -0
- package/dist/wasm-pins.d.ts.map +1 -0
- package/dist/wasm-pins.js +6 -0
- package/dist/wasm-pins.js.map +1 -0
- package/dist/wire/chainflip.zod.d.ts +144 -0
- package/dist/wire/chainflip.zod.d.ts.map +1 -0
- package/dist/wire/chainflip.zod.js +33 -0
- package/dist/wire/chainflip.zod.js.map +1 -0
- package/dist/wire/near-intents.zod.d.ts +376 -0
- package/dist/wire/near-intents.zod.d.ts.map +1 -0
- package/dist/wire/near-intents.zod.js +101 -0
- package/dist/wire/near-intents.zod.js.map +1 -0
- package/dist/wire/server/action.zod.d.ts +1119 -0
- package/dist/wire/server/action.zod.d.ts.map +1 -0
- package/dist/wire/server/action.zod.js +173 -0
- package/dist/wire/server/action.zod.js.map +1 -0
- package/dist/wire/server/common.zod.d.ts +62 -0
- package/dist/wire/server/common.zod.d.ts.map +1 -0
- package/dist/wire/server/common.zod.js +43 -0
- package/dist/wire/server/common.zod.js.map +1 -0
- package/dist/wire/server/index.d.ts +8 -0
- package/dist/wire/server/index.d.ts.map +1 -0
- package/dist/wire/server/index.js +8 -0
- package/dist/wire/server/index.js.map +1 -0
- package/dist/wire/server/pow.zod.d.ts +45 -0
- package/dist/wire/server/pow.zod.d.ts.map +1 -0
- package/dist/wire/server/pow.zod.js +18 -0
- package/dist/wire/server/pow.zod.js.map +1 -0
- package/dist/wire/server/quotes.zod.d.ts +694 -0
- package/dist/wire/server/quotes.zod.d.ts.map +1 -0
- package/dist/wire/server/quotes.zod.js +103 -0
- package/dist/wire/server/quotes.zod.js.map +1 -0
- package/dist/wire/server/swap.zod.d.ts +1981 -0
- package/dist/wire/server/swap.zod.d.ts.map +1 -0
- package/dist/wire/server/swap.zod.js +270 -0
- package/dist/wire/server/swap.zod.js.map +1 -0
- package/dist/wire/server/tokens.zod.d.ts +93 -0
- package/dist/wire/server/tokens.zod.d.ts.map +1 -0
- package/dist/wire/server/tokens.zod.js +28 -0
- package/dist/wire/server/tokens.zod.js.map +1 -0
- package/dist/wire/server/verify.zod.d.ts +30 -0
- package/dist/wire/server/verify.zod.d.ts.map +1 -0
- package/dist/wire/server/verify.zod.js +12 -0
- package/dist/wire/server/verify.zod.js.map +1 -0
- package/dist/wire/thorchain.zod.d.ts +224 -0
- package/dist/wire/thorchain.zod.d.ts.map +1 -0
- package/dist/wire/thorchain.zod.js +51 -0
- package/dist/wire/thorchain.zod.js.map +1 -0
- package/package.json +128 -0
- package/wasm/miradex-rust/README.md +74 -0
- package/wasm/miradex-rust/miradex_rust.d.ts +149 -0
- package/wasm/miradex-rust/miradex_rust.js +943 -0
- package/wasm/miradex-rust/miradex_rust_bg.wasm +0 -0
- package/wasm/miradex-rust/miradex_rust_bg.wasm.d.ts +31 -0
- package/wasm/miradex-rust/package.json +24 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monero sweep protocol for atomic swaps — fully client-side.
|
|
3
|
+
*
|
|
4
|
+
* After the maker redeems BTC, the server reveals s_a (its key share).
|
|
5
|
+
* This module combines s_a + s_b to derive the full Monero spend key,
|
|
6
|
+
* fetches the lock transaction directly from public monerod nodes,
|
|
7
|
+
* selects decoys, builds construction data, signs via WASM, and
|
|
8
|
+
* broadcasts the raw transaction — all without server involvement
|
|
9
|
+
* beyond the initial key share retrieval.
|
|
10
|
+
*
|
|
11
|
+
* The private key s_b never leaves this process.
|
|
12
|
+
*/
|
|
13
|
+
import { Point } from '@noble/ed25519';
|
|
14
|
+
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
15
|
+
import { noopLogger } from '../../interfaces/logger.js';
|
|
16
|
+
import { delay } from '../../lib/delay.js';
|
|
17
|
+
import { VerificationError } from '../../types/index.js';
|
|
18
|
+
import { addScalars, hexToBytes, bytesToHex as scalarBytesToHex, bytesToBigInt, } from '../../lib/crypto/scalars.js';
|
|
19
|
+
import { wipe } from '../../lib/crypto/bytes.js';
|
|
20
|
+
import { ensureWasm, deriveKeyImages, signSweepTx, selectDecoys, computeCommitmentMask, decryptAmount, verifyCommitment, } from '../../lib/crypto/wasm.js';
|
|
21
|
+
import { verifySweepTx } from '../../lib/monero/verify-sweep.js';
|
|
22
|
+
import { scanTransactionOutputs, hexToScalar } from '../../lib/monero/output-scanner.js';
|
|
23
|
+
import { fetchTransaction, fetchOutputKeys, fetchOutputDistribution, fetchFeeEstimate, broadcastTransaction, MAINNET_NODES, STAGENET_NODES, } from '../../lib/monero/rpc.js';
|
|
24
|
+
/**
|
|
25
|
+
* Normalise both the snake_case (s_a_hex) and camelCase (sAHex) shapes the
|
|
26
|
+
* sidecar may emit into one strongly-typed record. Unknown fields are dropped.
|
|
27
|
+
*/
|
|
28
|
+
function parseSweepOutputs(pd) {
|
|
29
|
+
if (!pd || typeof pd !== 'object') {
|
|
30
|
+
return { sAHex: undefined, vHex: undefined, lockTxHash: undefined, lockAddress: undefined, serverReceiveAddr: undefined };
|
|
31
|
+
}
|
|
32
|
+
const rec = pd;
|
|
33
|
+
const pick = (...keys) => {
|
|
34
|
+
for (const k of keys) {
|
|
35
|
+
const v = rec[k];
|
|
36
|
+
if (typeof v === 'string' && v.length > 0)
|
|
37
|
+
return v;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
sAHex: pick('s_a_hex', 'sAHex'),
|
|
43
|
+
vHex: pick('v_hex', 'vHex'),
|
|
44
|
+
lockTxHash: pick('lock_tx_hash', 'lockTxHash'),
|
|
45
|
+
lockAddress: pick('monero_lock_address', 'moneroLockAddress'),
|
|
46
|
+
serverReceiveAddr: pick('receive_address', 'receiveAddress'),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const SWEEP_SYNC_TIMEOUT_MS = 120_000;
|
|
50
|
+
const SWEEP_RETRY_INTERVAL_MS = 15_000;
|
|
51
|
+
const SWEEP_ACTION_TIMEOUT_MS = 120_000;
|
|
52
|
+
/** Max attempts for the full sweep (scan → decoys → sign → broadcast).
|
|
53
|
+
* Retries cover transient monerod failures and intermittent `invalid_input`
|
|
54
|
+
* caused by unlucky decoy selection. */
|
|
55
|
+
const SWEEP_MAX_ATTEMPTS = 15;
|
|
56
|
+
/** Backoff between sweep retries (doubles each attempt, capped at 60s). */
|
|
57
|
+
const SWEEP_RETRY_BASE_MS = 5_000;
|
|
58
|
+
/** Estimated tx size for fee calculation (1-in/2-out CLSAG + BP+, ring size 16).
|
|
59
|
+
* Measured from actual signed transactions: ~3200 bytes. */
|
|
60
|
+
const ESTIMATED_TX_SIZE = 3200;
|
|
61
|
+
/** Fallback fee per byte if get_fee_estimate RPC is unavailable.
|
|
62
|
+
* Uses the Monero default normal priority from cryptonote_config.h. */
|
|
63
|
+
const FALLBACK_FEE_PER_BYTE = 23_000;
|
|
64
|
+
/** Ring size for CLSAG + Bulletproofs+ (current Monero network). */
|
|
65
|
+
const RING_SIZE = 16;
|
|
66
|
+
import { validateRingMembers } from './ring-select.js';
|
|
67
|
+
import { isRetryableSweepError } from './errors.js';
|
|
68
|
+
export async function sweepMonero(api, params) {
|
|
69
|
+
const { swapId, s_b, receiveAddress, onProgress, logger: log = noopLogger } = params;
|
|
70
|
+
onProgress?.('Loading sweep module...');
|
|
71
|
+
log.info({ swapId }, 'Sweep: loading monero-sweep-wasm');
|
|
72
|
+
await ensureWasm();
|
|
73
|
+
log.info({ swapId }, 'Sweep: WASM module loaded');
|
|
74
|
+
onProgress?.('Loading sweep data from server...');
|
|
75
|
+
log.info({ swapId }, 'Sweep step 1: requesting redemption keys from server');
|
|
76
|
+
const syncStart = Date.now();
|
|
77
|
+
let sAHex;
|
|
78
|
+
let vHex;
|
|
79
|
+
let lockTxHash;
|
|
80
|
+
let lockAddress;
|
|
81
|
+
let serverReceiveAddr;
|
|
82
|
+
while (true) {
|
|
83
|
+
const outputsAction = await api.executeAction(swapId, { type: 'get-outputs' }, SWEEP_ACTION_TIMEOUT_MS);
|
|
84
|
+
const sweepData = parseSweepOutputs(outputsAction.protocolData);
|
|
85
|
+
sAHex = sweepData.sAHex;
|
|
86
|
+
vHex = sweepData.vHex;
|
|
87
|
+
lockTxHash = sweepData.lockTxHash;
|
|
88
|
+
lockAddress = sweepData.lockAddress;
|
|
89
|
+
serverReceiveAddr = sweepData.serverReceiveAddr;
|
|
90
|
+
if (sAHex && vHex && lockTxHash)
|
|
91
|
+
break;
|
|
92
|
+
if (Date.now() - syncStart >= SWEEP_SYNC_TIMEOUT_MS) {
|
|
93
|
+
log.error({ swapId, elapsed: Date.now() - syncStart }, 'Sweep key retrieval timed out');
|
|
94
|
+
throw new Error('Sweep key retrieval timed out');
|
|
95
|
+
}
|
|
96
|
+
onProgress?.('Waiting for sweep data...');
|
|
97
|
+
log.debug({ swapId, elapsed: Date.now() - syncStart, hasSA: !!sAHex, hasV: !!vHex, hasHash: !!lockTxHash }, 'Not ready, retrying');
|
|
98
|
+
await delay(SWEEP_RETRY_INTERVAL_MS);
|
|
99
|
+
}
|
|
100
|
+
if (!lockAddress)
|
|
101
|
+
throw new Error('Server did not return monero_lock_address');
|
|
102
|
+
if (serverReceiveAddr && serverReceiveAddr !== receiveAddress) {
|
|
103
|
+
throw new Error('Receive address mismatch — keystore and server disagree on XMR destination');
|
|
104
|
+
}
|
|
105
|
+
const s_a = hexToBytes(sAHex);
|
|
106
|
+
// AV-invariant C.5: the sidecar's s_a must multiply to S_a_monero before
|
|
107
|
+
// we combine it with s_b. Wrong s_a signs the sweep with a wrong key and
|
|
108
|
+
// silently produces a tx that cannot spend the joint output.
|
|
109
|
+
{
|
|
110
|
+
const s_aScalar = bytesToBigInt(s_a);
|
|
111
|
+
const s_aPoint = Point.BASE.multiply(s_aScalar);
|
|
112
|
+
const expectedS_aBytes = Point.fromHex(params.expectedSAMonero).toBytes();
|
|
113
|
+
if (bytesToHex(s_aPoint.toBytes()) !== bytesToHex(expectedS_aBytes)) {
|
|
114
|
+
throw new VerificationError('E_S_A_MISMATCH', 's_a returned by sidecar does not match S_a_monero, aborting sweep');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const v = hexToBytes(vHex);
|
|
118
|
+
const s_full = addScalars(s_a, s_b);
|
|
119
|
+
const spendKeyHex = scalarBytesToHex(s_full);
|
|
120
|
+
const viewKeyHex = scalarBytesToHex(v);
|
|
121
|
+
// AV-G.2: zero the individual share now that the combined key is derived.
|
|
122
|
+
wipe(s_a);
|
|
123
|
+
wipe(s_full);
|
|
124
|
+
const spendPubScalar = hexToScalar(spendKeyHex);
|
|
125
|
+
const spendPub = Point.BASE.multiply(spendPubScalar);
|
|
126
|
+
const spendPubHex = bytesToHex(spendPub.toBytes());
|
|
127
|
+
// Detect network from lock address prefix
|
|
128
|
+
const isMainnet = lockAddress.startsWith('4');
|
|
129
|
+
const monerodConfig = {
|
|
130
|
+
nodes: params.monerodNodes ?? (isMainnet ? [...MAINNET_NODES] : [...STAGENET_NODES]),
|
|
131
|
+
logger: log,
|
|
132
|
+
};
|
|
133
|
+
log.info({
|
|
134
|
+
swapId,
|
|
135
|
+
lockTxHash,
|
|
136
|
+
lockAddress,
|
|
137
|
+
network: isMainnet ? 'mainnet' : 'stagenet',
|
|
138
|
+
nodeCount: monerodConfig.nodes.length,
|
|
139
|
+
}, 'Sweep step 1 complete: keys received, scanning lock tx');
|
|
140
|
+
// Retry on transient network errors and intermittent `invalid_input`
|
|
141
|
+
// (caused by unlucky decoy selection on stagenet).
|
|
142
|
+
let lastSweepError;
|
|
143
|
+
for (let attempt = 0; attempt < SWEEP_MAX_ATTEMPTS; attempt++) {
|
|
144
|
+
try {
|
|
145
|
+
const result = await sweepScanSignBroadcast({
|
|
146
|
+
swapId, monerodConfig, lockTxHash, viewKeyHex, spendKeyHex,
|
|
147
|
+
spendPubHex, receiveAddress, api, log, onProgress,
|
|
148
|
+
unlockWindowBlocks: params.unlockWindowBlocks,
|
|
149
|
+
});
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
lastSweepError = err;
|
|
154
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
155
|
+
const isRetryable = isRetryableSweepError(msg);
|
|
156
|
+
log.warn({ swapId, attempt: attempt + 1, maxAttempts: SWEEP_MAX_ATTEMPTS, error: msg, isRetryable }, isRetryable
|
|
157
|
+
? 'Sweep attempt failed (retryable) — will retry'
|
|
158
|
+
: 'Sweep attempt failed (non-retryable)');
|
|
159
|
+
if (!isRetryable)
|
|
160
|
+
break;
|
|
161
|
+
if (attempt < SWEEP_MAX_ATTEMPTS - 1) {
|
|
162
|
+
const backoffMs = Math.min(SWEEP_RETRY_BASE_MS * (2 ** attempt), 60_000);
|
|
163
|
+
onProgress?.(`Sweep failed, retrying in ${Math.round(backoffMs / 1000)}s...`);
|
|
164
|
+
await delay(backoffMs);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
throw lastSweepError ?? new Error('Sweep failed after all attempts');
|
|
169
|
+
}
|
|
170
|
+
/** Errors that warrant a retry (network failures + intermittent daemon rejections). */
|
|
171
|
+
/** Steps 2–5: fetch lock tx → select decoys → sign → broadcast. */
|
|
172
|
+
async function sweepScanSignBroadcast(ctx) {
|
|
173
|
+
const { swapId, monerodConfig, lockTxHash, viewKeyHex, spendKeyHex, spendPubHex, receiveAddress, api, log, onProgress, unlockWindowBlocks, } = ctx;
|
|
174
|
+
const buildDecoyInput = (distribution) => JSON.stringify(unlockWindowBlocks === undefined
|
|
175
|
+
? { distribution }
|
|
176
|
+
: { distribution, unlock_window_blocks: unlockWindowBlocks });
|
|
177
|
+
onProgress?.('Scanning lock transaction...');
|
|
178
|
+
log.info({ swapId, lockTxHash }, 'Sweep step 2: fetching lock tx from monerod');
|
|
179
|
+
const fetched = await fetchTransaction(monerodConfig, lockTxHash);
|
|
180
|
+
log.info({
|
|
181
|
+
swapId,
|
|
182
|
+
confirmations: fetched.confirmations,
|
|
183
|
+
blockHeight: fetched.blockHeight,
|
|
184
|
+
outputCount: fetched.txJson.vout.length,
|
|
185
|
+
outputIndicesCount: fetched.outputIndices.length,
|
|
186
|
+
}, 'Lock tx fetched, scanning outputs');
|
|
187
|
+
const scannedOutputs = scanTransactionOutputs({
|
|
188
|
+
txJson: fetched.txJson,
|
|
189
|
+
globalOutputIndices: fetched.outputIndices,
|
|
190
|
+
viewKeyHex,
|
|
191
|
+
spendPubHex,
|
|
192
|
+
computeMask: computeCommitmentMask,
|
|
193
|
+
decryptAmountFn: decryptAmount,
|
|
194
|
+
logger: log,
|
|
195
|
+
});
|
|
196
|
+
if (scannedOutputs.length === 0) {
|
|
197
|
+
throw new Error('No outputs found at lock address — output scanning failed');
|
|
198
|
+
}
|
|
199
|
+
const realOutput = scannedOutputs[0];
|
|
200
|
+
if (!realOutput)
|
|
201
|
+
throw new Error('Scanned output is undefined');
|
|
202
|
+
log.info({
|
|
203
|
+
swapId,
|
|
204
|
+
outputIndex: realOutput.outputIndex,
|
|
205
|
+
globalOutputIndex: realOutput.globalOutputIndex,
|
|
206
|
+
amount: realOutput.amount.toString(),
|
|
207
|
+
amountXmr: (Number(realOutput.amount) / 1e12).toFixed(12),
|
|
208
|
+
rctMaskLen: realOutput.rctMask.length,
|
|
209
|
+
}, 'Sweep step 2 complete: real output found');
|
|
210
|
+
onProgress?.('Selecting decoys...');
|
|
211
|
+
log.info({ swapId }, 'Sweep step 3: selecting decoys via WASM');
|
|
212
|
+
// Fetch cumulative output distribution for gamma selection
|
|
213
|
+
const distribution = await fetchOutputDistribution(monerodConfig);
|
|
214
|
+
log.info({ swapId, distributionLen: distribution.length }, 'Output distribution fetched');
|
|
215
|
+
// Select decoys via WASM (gamma distribution matching wallet2)
|
|
216
|
+
const decoyResultJson = selectDecoys(realOutput.globalOutputIndex, buildDecoyInput(distribution), RING_SIZE);
|
|
217
|
+
const decoyResult = JSON.parse(decoyResultJson);
|
|
218
|
+
log.info({
|
|
219
|
+
swapId,
|
|
220
|
+
ringSize: decoyResult.indices.length,
|
|
221
|
+
realIndexInRing: decoyResult.real_index_in_ring,
|
|
222
|
+
firstIndices: decoyResult.indices.slice(0, 4).map(String),
|
|
223
|
+
}, 'Decoys selected');
|
|
224
|
+
// Fetch ring member public keys + commitments from monerod, validating
|
|
225
|
+
// each candidate ring is usable for CLSAG (reject torsion/identity keys —
|
|
226
|
+
// matches monero-oxide wallet2 select_n). On invalid ring, re-pick decoys
|
|
227
|
+
// and retry. Bumped from 5 → 50 because regtest's auto-miner constantly
|
|
228
|
+
// produces immature coinbase outputs at the chain tip; the gamma decoy
|
|
229
|
+
// distribution is recency-biased so a fresh draw can land 2-5 immature
|
|
230
|
+
// members per ring. Each retry is one monerod RPC + WASM decoy re-pick
|
|
231
|
+
// (~5ms), so 50 attempts per outer call is still under a second. Mainnet
|
|
232
|
+
// chains rarely need more than a couple of retries.
|
|
233
|
+
onProgress?.('Fetching ring member keys...');
|
|
234
|
+
const MAX_RING_RETRIES = 50;
|
|
235
|
+
let currentDecoyResult = decoyResult;
|
|
236
|
+
let ringMemberKeys = await fetchOutputKeys(monerodConfig, currentDecoyResult.indices);
|
|
237
|
+
for (let ringAttempt = 0; ringAttempt < MAX_RING_RETRIES; ringAttempt++) {
|
|
238
|
+
const invalidMembers = validateRingMembers(ringMemberKeys, log);
|
|
239
|
+
if (invalidMembers.length === 0)
|
|
240
|
+
break;
|
|
241
|
+
log.warn({
|
|
242
|
+
swapId,
|
|
243
|
+
attempt: ringAttempt + 1,
|
|
244
|
+
invalidCount: invalidMembers.length,
|
|
245
|
+
invalidIndices: invalidMembers.map((m) => m.ringIndex),
|
|
246
|
+
}, 'Ring contains invalid members (torsion/identity) — re-selecting decoys');
|
|
247
|
+
if (ringAttempt === MAX_RING_RETRIES - 1) {
|
|
248
|
+
throw new Error(`Failed to find valid ring after ${MAX_RING_RETRIES} attempts — ` +
|
|
249
|
+
`${invalidMembers.length} invalid members on last attempt`);
|
|
250
|
+
}
|
|
251
|
+
const retryDecoyJson = selectDecoys(realOutput.globalOutputIndex, buildDecoyInput(distribution), RING_SIZE);
|
|
252
|
+
currentDecoyResult = JSON.parse(retryDecoyJson);
|
|
253
|
+
ringMemberKeys = await fetchOutputKeys(monerodConfig, currentDecoyResult.indices);
|
|
254
|
+
}
|
|
255
|
+
const finalDecoyResult = currentDecoyResult;
|
|
256
|
+
log.info({ swapId, ringMemberCount: ringMemberKeys.length }, 'Ring member keys fetched (all valid)');
|
|
257
|
+
// Verify our commitment matches on-chain (debug check)
|
|
258
|
+
const realRingMember = ringMemberKeys[finalDecoyResult.real_index_in_ring];
|
|
259
|
+
if (realRingMember) {
|
|
260
|
+
const commitmentMatch = verifyCommitment(viewKeyHex, realOutput.txPublicKey, realOutput.outputIndex, realOutput.amount, realRingMember.mask);
|
|
261
|
+
log.info({
|
|
262
|
+
swapId,
|
|
263
|
+
commitmentMatch,
|
|
264
|
+
onChainMask: realRingMember.mask.slice(0, 16) + '...',
|
|
265
|
+
computedMask: realOutput.rctMask.slice(0, 16) + '...',
|
|
266
|
+
amount: realOutput.amount.toString(),
|
|
267
|
+
}, commitmentMatch
|
|
268
|
+
? 'Commitment verification PASSED — mask + amount match on-chain'
|
|
269
|
+
: 'Commitment verification FAILED — mask derivation is wrong');
|
|
270
|
+
if (!commitmentMatch) {
|
|
271
|
+
throw new Error('Commitment verification failed: computed mask + amount does not match on-chain commitment. ' +
|
|
272
|
+
'The sweep transaction would be rejected.');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Get fee estimate from monerod (adjusts based on mempool, like Feather wallet)
|
|
276
|
+
let feePerByte = FALLBACK_FEE_PER_BYTE;
|
|
277
|
+
let quantizationMask = 10_000;
|
|
278
|
+
try {
|
|
279
|
+
const estimate = await fetchFeeEstimate(monerodConfig);
|
|
280
|
+
feePerByte = estimate.feePerByte;
|
|
281
|
+
quantizationMask = estimate.quantizationMask || 10_000;
|
|
282
|
+
log.info({ swapId, feePerByte, quantizationMask }, 'Fee estimate received from monerod');
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
log.warn({ swapId, error: err instanceof Error ? err.message : String(err) }, 'Fee estimate failed, using fallback');
|
|
286
|
+
}
|
|
287
|
+
// Fee = fee_per_byte * estimated_tx_size, rounded up to quantization mask
|
|
288
|
+
let networkFee = feePerByte * ESTIMATED_TX_SIZE;
|
|
289
|
+
if (quantizationMask > 0) {
|
|
290
|
+
networkFee = Math.ceil(networkFee / quantizationMask) * quantizationMask;
|
|
291
|
+
}
|
|
292
|
+
log.info({ swapId, feePerByte, estimatedTxSize: ESTIMATED_TX_SIZE, networkFee, quantizationMask }, 'Fee calculated');
|
|
293
|
+
const destinationAmount = Number(realOutput.amount) - networkFee;
|
|
294
|
+
if (destinationAmount <= 0) {
|
|
295
|
+
throw new Error(`Output amount ${realOutput.amount.toString()} is less than network fee ${String(networkFee)}`);
|
|
296
|
+
}
|
|
297
|
+
const structuredOutput = {
|
|
298
|
+
one_time_public_key: realOutput.oneTimePublicKey,
|
|
299
|
+
tx_public_key: realOutput.txPublicKey,
|
|
300
|
+
output_index: realOutput.outputIndex,
|
|
301
|
+
global_output_index: realOutput.globalOutputIndex,
|
|
302
|
+
amount: Number(realOutput.amount),
|
|
303
|
+
rct_mask: realOutput.rctMask,
|
|
304
|
+
additional_tx_keys: [],
|
|
305
|
+
subaddr_major: 0,
|
|
306
|
+
subaddr_minor: 0,
|
|
307
|
+
};
|
|
308
|
+
const constructionData = {
|
|
309
|
+
inputs: [
|
|
310
|
+
{
|
|
311
|
+
ring_members: ringMemberKeys.map((rm) => ({
|
|
312
|
+
public_key: rm.key,
|
|
313
|
+
commitment: rm.mask,
|
|
314
|
+
})),
|
|
315
|
+
real_output_index: finalDecoyResult.real_index_in_ring,
|
|
316
|
+
real_output: structuredOutput,
|
|
317
|
+
key_offsets: [...finalDecoyResult.indices],
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
destination: {
|
|
321
|
+
address: receiveAddress,
|
|
322
|
+
amount: destinationAmount,
|
|
323
|
+
},
|
|
324
|
+
fee: networkFee,
|
|
325
|
+
tx_extra: '',
|
|
326
|
+
rct_type: 6,
|
|
327
|
+
};
|
|
328
|
+
log.info({
|
|
329
|
+
swapId,
|
|
330
|
+
inputCount: constructionData.inputs.length,
|
|
331
|
+
destinationAmount,
|
|
332
|
+
networkFee,
|
|
333
|
+
ringSize: ringMemberKeys.length,
|
|
334
|
+
rctType: 6,
|
|
335
|
+
}, 'Construction data built');
|
|
336
|
+
onProgress?.('Verifying transaction...');
|
|
337
|
+
log.info({ swapId }, 'Sweep step 4: verifying + signing');
|
|
338
|
+
const verification = verifySweepTx(constructionData, receiveAddress, log);
|
|
339
|
+
if (!verification.valid) {
|
|
340
|
+
throw new Error(`Sweep verification failed: ${verification.reason}`);
|
|
341
|
+
}
|
|
342
|
+
log.info({
|
|
343
|
+
swapId,
|
|
344
|
+
amount: verification.amount,
|
|
345
|
+
fee: verification.fee,
|
|
346
|
+
amountXmr: (Number(BigInt(verification.amount)) / 1e12).toFixed(12),
|
|
347
|
+
}, 'Sweep tx verified — signing via WASM');
|
|
348
|
+
// Derive key images (needed internally by sign_sweep_tx)
|
|
349
|
+
onProgress?.('Signing sweep transaction...');
|
|
350
|
+
const keyImagesJson = deriveKeyImages(JSON.stringify([structuredOutput]), viewKeyHex, spendKeyHex);
|
|
351
|
+
log.debug({ swapId, keyImagesJson: keyImagesJson.slice(0, 60) + '...' }, 'Key images derived');
|
|
352
|
+
// Sign
|
|
353
|
+
const rawTxHex = signSweepTx(JSON.stringify(constructionData), spendKeyHex, viewKeyHex);
|
|
354
|
+
log.info({ swapId, rawTxLen: rawTxHex.length, rawTxPrefix: rawTxHex.slice(0, 32) + '...' }, 'Transaction signed');
|
|
355
|
+
// Diagnostic: dump full construction data for debugging invalid_input
|
|
356
|
+
log.info({
|
|
357
|
+
swapId,
|
|
358
|
+
realOutput: {
|
|
359
|
+
oneTimePublicKey: structuredOutput.one_time_public_key,
|
|
360
|
+
txPublicKey: structuredOutput.tx_public_key,
|
|
361
|
+
outputIndex: structuredOutput.output_index,
|
|
362
|
+
globalOutputIndex: structuredOutput.global_output_index,
|
|
363
|
+
amount: structuredOutput.amount,
|
|
364
|
+
rctMask: structuredOutput.rct_mask,
|
|
365
|
+
},
|
|
366
|
+
realRingMemberKey: ringMemberKeys[finalDecoyResult.real_index_in_ring]?.key,
|
|
367
|
+
realRingMemberMask: ringMemberKeys[finalDecoyResult.real_index_in_ring]?.mask,
|
|
368
|
+
realIndexInRing: finalDecoyResult.real_index_in_ring,
|
|
369
|
+
keyImage: JSON.parse(keyImagesJson)[0]?.key_image,
|
|
370
|
+
allIndices: finalDecoyResult.indices,
|
|
371
|
+
fee: constructionData.fee,
|
|
372
|
+
destinationAmount: constructionData.destination.amount,
|
|
373
|
+
}, 'Sweep diagnostic: full construction data');
|
|
374
|
+
// Dump the full signed tx for external decoding if broadcast fails
|
|
375
|
+
log.debug({ swapId, rawTxHex }, 'Full signed transaction hex');
|
|
376
|
+
onProgress?.('Broadcasting sweep transaction...');
|
|
377
|
+
log.info({ swapId }, 'Sweep step 5: broadcasting to monerod');
|
|
378
|
+
const broadcastResult = await broadcastTransaction(monerodConfig, rawTxHex);
|
|
379
|
+
if (broadcastResult.alreadySpent) {
|
|
380
|
+
// Key image already used — we must have broadcast this in a previous attempt.
|
|
381
|
+
// Only we have the spend key, so this is our own prior transaction.
|
|
382
|
+
log.info({ swapId }, 'Sweep tx already broadcast (double_spend) — prior attempt succeeded');
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
log.info({ swapId, txHash: broadcastResult.txHash, status: broadcastResult.status }, 'Sweep tx broadcast to network');
|
|
386
|
+
}
|
|
387
|
+
// Notify server that sweep is complete. This updates the DB status to
|
|
388
|
+
// 'completed' so the poll loop stops triggering duplicate sweep attempts.
|
|
389
|
+
// Retry a few times — without this the swap stays in 'sending' forever.
|
|
390
|
+
const sweepTxHash = broadcastResult.txHash || `sweep-${swapId}`;
|
|
391
|
+
for (let notifyAttempt = 0; notifyAttempt < 3; notifyAttempt++) {
|
|
392
|
+
try {
|
|
393
|
+
await api.executeAction(swapId, { type: 'sweep-complete', txHash: sweepTxHash }, 15_000);
|
|
394
|
+
log.info({ swapId, txHash: sweepTxHash }, 'Server notified of sweep completion');
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
catch (err) {
|
|
398
|
+
log.warn({ swapId, attempt: notifyAttempt + 1, error: err instanceof Error ? err.message : String(err) }, 'Server notification failed, retrying');
|
|
399
|
+
if (notifyAttempt < 2) {
|
|
400
|
+
await delay(3_000);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const sweepAmount = String(destinationAmount);
|
|
405
|
+
onProgress?.('Sweep complete');
|
|
406
|
+
log.info({
|
|
407
|
+
swapId,
|
|
408
|
+
txHash: sweepTxHash,
|
|
409
|
+
amount: sweepAmount,
|
|
410
|
+
amountXmr: (destinationAmount / 1e12).toFixed(12),
|
|
411
|
+
alreadySpent: broadcastResult.alreadySpent,
|
|
412
|
+
}, broadcastResult.alreadySpent ? 'Sweep already completed (prior broadcast)' : 'Sweep broadcast complete');
|
|
413
|
+
return { txHash: sweepTxHash, amount: sweepAmount };
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/atomic-swap/monero-sweep/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Logger } from '../../interfaces/logger.js';
|
|
2
|
+
import type { OutputKeyInfo } from '../../lib/monero/rpc.js';
|
|
3
|
+
export interface InvalidRingMember {
|
|
4
|
+
readonly ringIndex: number;
|
|
5
|
+
readonly reason: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Validate a ring's output keys, commitment points, and unlock state.
|
|
9
|
+
* Returns the indices that must be replaced before signing.
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateRingMembers(members: readonly OutputKeyInfo[], log: Logger): InvalidRingMember[];
|
|
12
|
+
//# sourceMappingURL=ring-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ring-select.d.ts","sourceRoot":"","sources":["../../../src/atomic-swap/monero-sweep/ring-select.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,GAAG,EAAE,MAAM,GACV,iBAAiB,EAAE,CA0CrB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ring-member validation for CLSAG signing.
|
|
3
|
+
*
|
|
4
|
+
* Each ring member must satisfy three conditions before we sign with it:
|
|
5
|
+
* 1. The output public key decompresses to a valid ed25519 point and is
|
|
6
|
+
* not the identity.
|
|
7
|
+
* 2. The Pedersen commitment decompresses to a valid ed25519 point.
|
|
8
|
+
* 3. The output is *unlocked* — monerod returns `unlocked: false` for
|
|
9
|
+
* coinbase outputs that have not yet cleared their 60-block lock window
|
|
10
|
+
* (`CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW`) or RingCT outputs younger
|
|
11
|
+
* than `DEFAULT_TX_SPENDABLE_AGE` blocks.
|
|
12
|
+
*
|
|
13
|
+
* Picking a locked ring member is the most common cause of a daemon
|
|
14
|
+
* `[flags: invalid_input]` rejection at broadcast time. wallet2 catches this
|
|
15
|
+
* via `get_outs.unlocked`; we do the same here, then re-roll the entire ring
|
|
16
|
+
* if any slot is invalid.
|
|
17
|
+
*/
|
|
18
|
+
import { Point } from '@noble/ed25519';
|
|
19
|
+
const IDENTITY_HEX = '01' + '00'.repeat(31);
|
|
20
|
+
/**
|
|
21
|
+
* Validate a ring's output keys, commitment points, and unlock state.
|
|
22
|
+
* Returns the indices that must be replaced before signing.
|
|
23
|
+
*/
|
|
24
|
+
export function validateRingMembers(members, log) {
|
|
25
|
+
const invalid = [];
|
|
26
|
+
for (let i = 0; i < members.length; i++) {
|
|
27
|
+
const member = members[i];
|
|
28
|
+
if (!member)
|
|
29
|
+
continue;
|
|
30
|
+
try {
|
|
31
|
+
Point.fromHex(member.key);
|
|
32
|
+
if (member.key === IDENTITY_HEX) {
|
|
33
|
+
invalid.push({ ringIndex: i, reason: 'identity key' });
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
invalid.push({ ringIndex: i, reason: 'invalid key point' });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
Point.fromHex(member.mask);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
invalid.push({ ringIndex: i, reason: 'invalid commitment point' });
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (member.unlocked === false) {
|
|
49
|
+
invalid.push({
|
|
50
|
+
ringIndex: i,
|
|
51
|
+
reason: `output not yet unlocked (height=${String(member.height)})`,
|
|
52
|
+
});
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (invalid.length > 0) {
|
|
57
|
+
log.warn({ invalidCount: invalid.length, details: invalid }, 'Ring contains invalid members');
|
|
58
|
+
}
|
|
59
|
+
return invalid;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ring-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ring-select.js","sourceRoot":"","sources":["../../../src/atomic-swap/monero-sweep/ring-select.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AASvC,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE5C;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAiC,EACjC,GAAW;IAEX,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM;YAAE,SAAS;QAEtB,IAAI,CAAC;YACH,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,IAAI,MAAM,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;gBACvD,SAAS;YACX,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;YAC5D,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACnE,SAAS;QACX,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,CAAC;gBACZ,MAAM,EAAE,mCAAmC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG;aACpE,CAAC,CAAC;YACH,SAAS;QACX,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,GAAG,CAAC,IAAI,CACN,EAAE,YAAY,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAClD,+BAA+B,CAChC,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side pre-signing for non-custodial atomic swaps.
|
|
3
|
+
*
|
|
4
|
+
* Constructs the same Bitcoin transactions (TxCancel, TxPunish, TxEarlyRefund,
|
|
5
|
+
* TxRedeem) that the Rust sidecar builds, computes their BIP143 segwit sighashes,
|
|
6
|
+
* and signs them with Bob's secret key `b` — all client-side. The server never
|
|
7
|
+
* sees `b`.
|
|
8
|
+
*
|
|
9
|
+
* The miniscript `c:and_v(v:pk(A),pk_k(B))` compiles to:
|
|
10
|
+
* <A> OP_CHECKSIGVERIFY <B> OP_CHECKSIG
|
|
11
|
+
*
|
|
12
|
+
* This is the witness script for the 2-of-2 P2WSH used in TxLock and TxCancel.
|
|
13
|
+
*/
|
|
14
|
+
import type { ProtocolParams, PreSigs, FeePolicy, AmnestyPolicy, DustPolicy } from '../types/index.js';
|
|
15
|
+
export type NetworkName = 'mainnet' | 'testnet' | 'regtest' | 'regtest';
|
|
16
|
+
export interface ComputePreSigsParams {
|
|
17
|
+
readonly bHex: string;
|
|
18
|
+
readonly signedPsbtBase64: string;
|
|
19
|
+
readonly protocolParams: ProtocolParams;
|
|
20
|
+
readonly refundAddress: string;
|
|
21
|
+
readonly network: NetworkName;
|
|
22
|
+
readonly amnestyPolicy?: AmnestyPolicy;
|
|
23
|
+
readonly feePolicy?: FeePolicy;
|
|
24
|
+
readonly dustPolicy?: DustPolicy;
|
|
25
|
+
}
|
|
26
|
+
export interface ComputeRedeemDigestParams {
|
|
27
|
+
readonly signedPsbtBase64: string;
|
|
28
|
+
readonly protocolParams: ProtocolParams;
|
|
29
|
+
readonly bPubHex: string;
|
|
30
|
+
readonly network: NetworkName;
|
|
31
|
+
readonly feePolicy?: FeePolicy;
|
|
32
|
+
readonly dustPolicy?: DustPolicy;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Derive the canonical 2-of-2 P2WSH lock address from Alice's and Bob's
|
|
36
|
+
* compressed secp256k1 public keys. Callers must compare this against any
|
|
37
|
+
* sidecar-claimed lock address before signing.
|
|
38
|
+
*
|
|
39
|
+
* @param params.aHex Alice's 33-byte compressed secp256k1 public key (hex).
|
|
40
|
+
* @param params.bHex Bob's 33-byte compressed secp256k1 public key (hex).
|
|
41
|
+
* @param params.network `'mainnet'` or `'testnet'`; selects the bech32 HRP.
|
|
42
|
+
* @returns The bech32 P2WSH address derived from `(A, B)`.
|
|
43
|
+
* @throws {VerificationError} `E_LOCK_SCRIPT` if p2wsh derivation fails.
|
|
44
|
+
* @security Closes AV-B.1 / AV-C.1 — always prefer this over a sidecar-supplied address.
|
|
45
|
+
*/
|
|
46
|
+
export declare function deriveLockAddress(params: {
|
|
47
|
+
readonly aHex: string;
|
|
48
|
+
readonly bHex: string;
|
|
49
|
+
readonly network: NetworkName;
|
|
50
|
+
}): string;
|
|
51
|
+
/**
|
|
52
|
+
* Build the 2-of-2 witness script: <A> OP_CHECKSIGVERIFY <B> OP_CHECKSIG
|
|
53
|
+
*
|
|
54
|
+
* This matches the Rust miniscript `c:and_v(v:pk(A),pk_k(B))`.
|
|
55
|
+
* A and B are 33-byte compressed secp256k1 public keys (hex).
|
|
56
|
+
*/
|
|
57
|
+
export declare function buildMultisigWitnessScript(aHex: string, bHex: string): Buffer;
|
|
58
|
+
/**
|
|
59
|
+
* Compute the 3 pre-signatures (TxCancel, TxPunish, TxEarlyRefund) for a client-side swap.
|
|
60
|
+
*
|
|
61
|
+
* These are standard ECDSA signatures that the sidecar sends to Alice in Message4.
|
|
62
|
+
* The TxRedeem encrypted signature is computed separately (requires WASM adaptor crypto).
|
|
63
|
+
*
|
|
64
|
+
* @param params - All parameters needed for pre-signature computation
|
|
65
|
+
* @returns 3 hex-encoded compact ECDSA signatures (64 bytes each)
|
|
66
|
+
*/
|
|
67
|
+
export declare function computePreSigs(params: ComputePreSigsParams): PreSigs;
|
|
68
|
+
/**
|
|
69
|
+
* Compute the TxRedeem BIP143 sighash digest.
|
|
70
|
+
*
|
|
71
|
+
* The client uses this digest with WASM `encsign_digest(b, S_a_bitcoin, digest)`
|
|
72
|
+
* to produce the adaptor-encrypted signature for Alice.
|
|
73
|
+
*
|
|
74
|
+
* @param params - All parameters needed for redeem digest computation
|
|
75
|
+
* @returns Hex-encoded sighash (32 bytes)
|
|
76
|
+
*/
|
|
77
|
+
export declare function computeRedeemDigest(params: ComputeRedeemDigestParams): string;
|
|
78
|
+
export interface ComputeRedeemDigestFromTxHexParams {
|
|
79
|
+
readonly lockTxRawHex: string;
|
|
80
|
+
readonly protocolParams: ProtocolParams;
|
|
81
|
+
readonly bPubHex: string;
|
|
82
|
+
readonly network: NetworkName;
|
|
83
|
+
readonly feePolicy?: FeePolicy;
|
|
84
|
+
readonly dustPolicy?: DustPolicy;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Recompute the TxRedeem BIP143 sighash from a raw, already-broadcast TxLock
|
|
88
|
+
* rather than a signed PSBT. Used on the resume path: when the driver comes
|
|
89
|
+
* up after a restart, `signedPsbtBase64` is no longer in memory, but the
|
|
90
|
+
* lock tx is permanently on-chain and any `BlockchainDataProvider` can
|
|
91
|
+
* return its raw hex.
|
|
92
|
+
*
|
|
93
|
+
* Produces a byte-identical digest to `computeRedeemDigest` for the same
|
|
94
|
+
* underlying transaction.
|
|
95
|
+
*
|
|
96
|
+
* @security Preserves Fix 1 / AV-B.2 guarantees on resume — the digest is
|
|
97
|
+
* still derived independently from chain data; the caller CT-compares the
|
|
98
|
+
* result against the sidecar's claimed digest.
|
|
99
|
+
*/
|
|
100
|
+
export declare function computeRedeemDigestFromTxHex(params: ComputeRedeemDigestFromTxHexParams): string;
|
|
101
|
+
//# sourceMappingURL=presign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presign.d.ts","sourceRoot":"","sources":["../../src/atomic-swap/presign.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAkBvG,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAUxE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC;AAuED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B,GAAG,MAAM,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAc7E;AA+DD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CA0PpE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAa7E;AAED,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kCAAkC,GACzC,MAAM,CAUR"}
|