@atomiqlabs/lp-lib 14.0.0-dev.12 → 14.0.0-dev.14
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/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.js +46 -19
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.js +46 -20
- package/dist/swaps/spv_vault_swap/SpvVault.d.ts +2 -3
- package/dist/swaps/spv_vault_swap/SpvVault.js +2 -2
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +2 -1
- package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +3 -3
- package/dist/swaps/spv_vault_swap/SpvVaults.js +40 -18
- package/package.json +2 -2
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.ts +52 -24
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.ts +51 -24
- package/src/swaps/spv_vault_swap/SpvVault.ts +3 -3
- package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +2 -1
- package/src/swaps/spv_vault_swap/SpvVaults.ts +42 -19
|
@@ -55,30 +55,57 @@ class FromBtcLnAbs extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
|
|
|
55
55
|
}
|
|
56
56
|
return null;
|
|
57
57
|
}
|
|
58
|
-
if (swap.state === FromBtcLnSwapAbs_1.FromBtcLnSwapState.RECEIVED) {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
await
|
|
65
|
-
|
|
58
|
+
if (swap.state === FromBtcLnSwapAbs_1.FromBtcLnSwapState.RECEIVED || swap.state === FromBtcLnSwapAbs_1.FromBtcLnSwapState.COMMITED) {
|
|
59
|
+
const onchainStatus = await swapContract.getCommitStatus(signer.getAddress(), swap.data);
|
|
60
|
+
const state = swap.state;
|
|
61
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.PAID) {
|
|
62
|
+
//Extract the swap secret
|
|
63
|
+
if (state !== FromBtcLnSwapAbs_1.FromBtcLnSwapState.CLAIMED && state !== FromBtcLnSwapAbs_1.FromBtcLnSwapState.SETTLED) {
|
|
64
|
+
const secretHex = await onchainStatus.getClaimResult();
|
|
65
|
+
const secret = Buffer.from(secretHex, "hex");
|
|
66
|
+
const paymentHash = (0, crypto_1.createHash)("sha256").update(secret).digest();
|
|
67
|
+
const paymentHashHex = paymentHash.toString("hex");
|
|
68
|
+
if (swap.lnPaymentHash !== paymentHashHex) {
|
|
69
|
+
//TODO: Possibly fatal failure
|
|
70
|
+
this.swapLogger.error(swap, "processPastSwap(state=RECEIVED|COMMITED): onchainStatus=PAID, Invalid swap secret specified: " + secretHex + " for paymentHash: " + paymentHashHex);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
swap.secret = secretHex;
|
|
74
|
+
await swap.setState(FromBtcLnSwapAbs_1.FromBtcLnSwapState.CLAIMED);
|
|
75
|
+
await this.saveSwapData(swap);
|
|
76
|
+
this.swapLogger.warn(swap, "processPastSwap(state=RECEIVED|COMMITED): swap settled (detected from processPastSwap), invoice: " + swap.pr);
|
|
77
|
+
return "SETTLE";
|
|
66
78
|
}
|
|
67
|
-
|
|
68
|
-
await swap.setState(FromBtcLnSwapAbs_1.FromBtcLnSwapState.COMMITED);
|
|
69
|
-
await this.saveSwapData(swap);
|
|
79
|
+
return null;
|
|
70
80
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
81
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.COMMITED) {
|
|
82
|
+
if (state === FromBtcLnSwapAbs_1.FromBtcLnSwapState.RECEIVED) {
|
|
83
|
+
await swap.setState(FromBtcLnSwapAbs_1.FromBtcLnSwapState.COMMITED);
|
|
84
|
+
await this.saveSwapData(swap);
|
|
85
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap committed (detected from processPastSwap), invoice: " + swap.pr);
|
|
86
|
+
}
|
|
74
87
|
return null;
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
|
|
88
|
+
}
|
|
89
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.NOT_COMMITED || onchainStatus.type === base_1.SwapCommitStateType.EXPIRED) {
|
|
90
|
+
if (swap.state === FromBtcLnSwapAbs_1.FromBtcLnSwapState.RECEIVED) {
|
|
91
|
+
const isAuthorizationExpired = await swapContract.isInitAuthorizationExpired(swap.data, swap);
|
|
92
|
+
if (isAuthorizationExpired) {
|
|
93
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap not committed before authorization expiry, cancelling the LN invoice, invoice: " + swap.pr);
|
|
94
|
+
await swap.setState(FromBtcLnSwapAbs_1.FromBtcLnSwapState.CANCELED);
|
|
95
|
+
return "CANCEL";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (await swapContract.isExpired(signer.getAddress(), swap.data)) {
|
|
100
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap timed out, refunding to self, invoice: " + swap.pr);
|
|
101
|
+
return "REFUND";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.REFUNDABLE) {
|
|
106
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap timed out, refunding to self, invoice: " + swap.pr);
|
|
78
107
|
return "REFUND";
|
|
79
108
|
}
|
|
80
|
-
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED): swap timed out, cancelling the LN invoice, invoice: " + swap.pr);
|
|
81
|
-
return "CANCEL";
|
|
82
109
|
}
|
|
83
110
|
if (swap.state === FromBtcLnSwapAbs_1.FromBtcLnSwapState.CLAIMED)
|
|
84
111
|
return "SETTLE";
|
|
@@ -65,31 +65,57 @@ class FromBtcLnAuto extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
|
|
|
65
65
|
}
|
|
66
66
|
return null;
|
|
67
67
|
}
|
|
68
|
-
if (swap.state === FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.TXS_SENT) {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await
|
|
75
|
-
|
|
68
|
+
if (swap.state === FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.TXS_SENT || swap.state === FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.COMMITED) {
|
|
69
|
+
const onchainStatus = await swapContract.getCommitStatus(signer.getAddress(), swap.data);
|
|
70
|
+
const state = swap.state;
|
|
71
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.PAID) {
|
|
72
|
+
//Extract the swap secret
|
|
73
|
+
if (state !== FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.CLAIMED && state !== FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.SETTLED) {
|
|
74
|
+
const secretHex = await onchainStatus.getClaimResult();
|
|
75
|
+
const secret = Buffer.from(secretHex, "hex");
|
|
76
|
+
const paymentHash = (0, crypto_1.createHash)("sha256").update(secret).digest();
|
|
77
|
+
const paymentHashHex = paymentHash.toString("hex");
|
|
78
|
+
if (swap.lnPaymentHash !== paymentHashHex) {
|
|
79
|
+
//TODO: Possibly fatal failure
|
|
80
|
+
this.swapLogger.error(swap, "processPastSwap(state=TXS_SENT|COMMITED): onchainStatus=PAID, Invalid swap secret specified: " + secretHex + " for paymentHash: " + paymentHashHex);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
swap.secret = secretHex;
|
|
84
|
+
await swap.setState(FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.CLAIMED);
|
|
85
|
+
await this.saveSwapData(swap);
|
|
86
|
+
this.swapLogger.warn(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap settled (detected from processPastSwap), invoice: " + swap.pr);
|
|
87
|
+
return "SETTLE";
|
|
76
88
|
}
|
|
77
|
-
|
|
78
|
-
await swap.setState(FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.COMMITED);
|
|
79
|
-
await this.saveSwapData(swap);
|
|
89
|
+
return null;
|
|
80
90
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.COMMITED) {
|
|
92
|
+
if (state === FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.TXS_SENT) {
|
|
93
|
+
await swap.setState(FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.COMMITED);
|
|
94
|
+
await this.saveSwapData(swap);
|
|
95
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap committed (detected from processPastSwap), invoice: " + swap.pr);
|
|
96
|
+
}
|
|
84
97
|
return null;
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
|
|
98
|
+
}
|
|
99
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.NOT_COMMITED || onchainStatus.type === base_1.SwapCommitStateType.EXPIRED) {
|
|
100
|
+
if (swap.state === FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.TXS_SENT) {
|
|
101
|
+
const isAuthorizationExpired = await swapContract.isInitAuthorizationExpired(swap.data, swap);
|
|
102
|
+
if (isAuthorizationExpired) {
|
|
103
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap not committed before authorization expiry, cancelling the LN invoice, invoice: " + swap.pr);
|
|
104
|
+
await this.cancelSwapAndInvoice(swap);
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
if (await swapContract.isExpired(signer.getAddress(), swap.data)) {
|
|
110
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap timed out, refunding to self, invoice: " + swap.pr);
|
|
111
|
+
return "REFUND";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (onchainStatus.type === base_1.SwapCommitStateType.REFUNDABLE) {
|
|
116
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap timed out, refunding to self, invoice: " + swap.pr);
|
|
88
117
|
return "REFUND";
|
|
89
118
|
}
|
|
90
|
-
this.swapLogger.info(swap, "processPastSwap(state=COMMITED): swap timed out, cancelling the LN invoice, invoice: " + swap.pr);
|
|
91
|
-
await this.cancelSwapAndInvoice(swap);
|
|
92
|
-
return null;
|
|
93
119
|
}
|
|
94
120
|
if (swap.state === FromBtcLnAutoSwap_1.FromBtcLnAutoSwapState.CLAIMED)
|
|
95
121
|
return "SETTLE";
|
|
@@ -13,9 +13,8 @@ export declare class SpvVault<D extends SpvWithdrawalTransactionData = SpvWithdr
|
|
|
13
13
|
data: T;
|
|
14
14
|
state: SpvVaultState;
|
|
15
15
|
balances: SpvVaultTokenBalance[];
|
|
16
|
-
|
|
17
|
-
txId: string;
|
|
18
|
-
rawTx: string;
|
|
16
|
+
scOpenTxs: {
|
|
17
|
+
[txId: string]: string;
|
|
19
18
|
};
|
|
20
19
|
constructor(chainId: string, vault: T, btcAddress: string);
|
|
21
20
|
constructor(obj: any);
|
|
@@ -27,7 +27,7 @@ class SpvVault extends base_1.Lockable {
|
|
|
27
27
|
this.initialUtxo = chainIdOrObj.initialUtxo;
|
|
28
28
|
this.btcAddress = chainIdOrObj.btcAddress;
|
|
29
29
|
this.pendingWithdrawals = chainIdOrObj.pendingWithdrawals.map((base_1.SpvWithdrawalTransactionData.deserialize));
|
|
30
|
-
this.
|
|
30
|
+
this.scOpenTxs = chainIdOrObj.scOpenTxs;
|
|
31
31
|
}
|
|
32
32
|
this.balances = this.data.calculateStateAfter(this.pendingWithdrawals).balances;
|
|
33
33
|
}
|
|
@@ -83,7 +83,7 @@ class SpvVault extends base_1.Lockable {
|
|
|
83
83
|
initialUtxo: this.initialUtxo,
|
|
84
84
|
btcAddress: this.btcAddress,
|
|
85
85
|
pendingWithdrawals: this.pendingWithdrawals.map(val => val.serialize()),
|
|
86
|
-
|
|
86
|
+
scOpenTxs: this.scOpenTxs
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
getIdentifier() {
|
|
@@ -23,7 +23,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
23
23
|
this.vaultSigner = spvVaultSigner;
|
|
24
24
|
this.config = config;
|
|
25
25
|
this.AmountAssertions = new FromBtcAmountAssertions_1.FromBtcAmountAssertions(config, swapPricing);
|
|
26
|
-
this.Vaults = new SpvVaults_1.SpvVaults(vaultStorage, bitcoin, spvVaultSigner, bitcoinRpc, this.
|
|
26
|
+
this.Vaults = new SpvVaults_1.SpvVaults(vaultStorage, bitcoin, spvVaultSigner, bitcoinRpc, this.chains, config);
|
|
27
27
|
}
|
|
28
28
|
async processClaimEvent(swap, event) {
|
|
29
29
|
if (swap == null)
|
|
@@ -372,6 +372,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
372
372
|
data.executionFeeRate !== swap.executionFeeShare ||
|
|
373
373
|
data.rawAmounts[0] !== swap.rawAmountToken ||
|
|
374
374
|
data.rawAmounts[1] !== swap.rawAmountGasToken ||
|
|
375
|
+
data.getExecutionData() != null ||
|
|
375
376
|
data.getSpentVaultUtxo() !== swap.vaultUtxo ||
|
|
376
377
|
data.btcTx.outs[0].value !== SpvVaults_1.VAULT_DUST_AMOUNT ||
|
|
377
378
|
!Buffer.from(data.btcTx.outs[0].scriptPubKey.hex, "hex").equals(this.bitcoin.toOutputScript(swap.vaultAddress)) ||
|
|
@@ -3,7 +3,7 @@ import { BitcoinRpc, IStorageManager, SpvVaultClaimEvent, SpvVaultCloseEvent, Sp
|
|
|
3
3
|
import { SpvVaultSwap } from "./SpvVaultSwap";
|
|
4
4
|
import { IBitcoinWallet } from "../../wallets/IBitcoinWallet";
|
|
5
5
|
import { ISpvVaultSigner } from "../../wallets/ISpvVaultSigner";
|
|
6
|
-
import {
|
|
6
|
+
import { MultichainData } from "../SwapHandler";
|
|
7
7
|
export declare const VAULT_DUST_AMOUNT = 600;
|
|
8
8
|
export declare class SpvVaults {
|
|
9
9
|
readonly vaultStorage: IStorageManager<SpvVault>;
|
|
@@ -14,9 +14,9 @@ export declare class SpvVaults {
|
|
|
14
14
|
vaultsCheckInterval: number;
|
|
15
15
|
maxUnclaimedWithdrawals?: number;
|
|
16
16
|
};
|
|
17
|
-
readonly
|
|
17
|
+
readonly chains: MultichainData;
|
|
18
18
|
readonly logger: import("../../utils/Utils").LoggerType;
|
|
19
|
-
constructor(vaultStorage: IStorageManager<SpvVault>, bitcoin: IBitcoinWallet, vaultSigner: ISpvVaultSigner, bitcoinRpc: BitcoinRpc<any>,
|
|
19
|
+
constructor(vaultStorage: IStorageManager<SpvVault>, bitcoin: IBitcoinWallet, vaultSigner: ISpvVaultSigner, bitcoinRpc: BitcoinRpc<any>, chains: MultichainData, config: {
|
|
20
20
|
vaultsCheckInterval: number;
|
|
21
21
|
maxUnclaimedWithdrawals?: number;
|
|
22
22
|
});
|
|
@@ -10,14 +10,27 @@ exports.VAULT_DUST_AMOUNT = 600;
|
|
|
10
10
|
const VAULT_INIT_CONFIRMATIONS = 2;
|
|
11
11
|
const BTC_FINALIZATION_CONFIRMATIONS = 6;
|
|
12
12
|
class SpvVaults {
|
|
13
|
-
constructor(vaultStorage, bitcoin, vaultSigner, bitcoinRpc,
|
|
13
|
+
constructor(vaultStorage, bitcoin, vaultSigner, bitcoinRpc, chains, config) {
|
|
14
14
|
this.logger = (0, Utils_1.getLogger)("SpvVaults: ");
|
|
15
15
|
this.vaultStorage = vaultStorage;
|
|
16
16
|
this.bitcoin = bitcoin;
|
|
17
17
|
this.vaultSigner = vaultSigner;
|
|
18
18
|
this.bitcoinRpc = bitcoinRpc;
|
|
19
|
-
this.
|
|
19
|
+
this.chains = chains;
|
|
20
20
|
this.config = config;
|
|
21
|
+
for (let chainId in chains.chains) {
|
|
22
|
+
const { chainInterface } = chains.chains[chainId];
|
|
23
|
+
chainInterface.onBeforeTxReplace(async (oldTx, oldTxId, newTx, newTxId) => {
|
|
24
|
+
for (let key in this.vaultStorage.data) {
|
|
25
|
+
const vaultData = this.vaultStorage.data[key];
|
|
26
|
+
if (vaultData.scOpenTxs != null && vaultData.scOpenTxs[oldTxId] != null) {
|
|
27
|
+
vaultData.scOpenTxs[newTxId] = newTx;
|
|
28
|
+
await this.saveVault(vaultData);
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
21
34
|
}
|
|
22
35
|
async processDepositEvent(vault, event) {
|
|
23
36
|
vault.update(event);
|
|
@@ -46,7 +59,7 @@ class SpvVaults {
|
|
|
46
59
|
await this.saveVault(vault);
|
|
47
60
|
}
|
|
48
61
|
async createVaults(chainId, count, token, confirmations = 2, feeRate) {
|
|
49
|
-
const { signer, chainInterface, tokenMultipliers, spvVaultContract } = this.
|
|
62
|
+
const { signer, chainInterface, tokenMultipliers, spvVaultContract } = this.chains.chains[chainId];
|
|
50
63
|
const signerAddress = signer.getAddress();
|
|
51
64
|
//Check vaultId of the latest saved vault
|
|
52
65
|
let latestVaultId = -1n;
|
|
@@ -101,14 +114,14 @@ class SpvVaults {
|
|
|
101
114
|
return Object.keys(this.vaultStorage.data)
|
|
102
115
|
.map(key => this.vaultStorage.data[key])
|
|
103
116
|
.filter(val => chainId == null ? true : val.chainId === chainId)
|
|
104
|
-
.filter(val => val.data.getOwner() === this.
|
|
117
|
+
.filter(val => val.data.getOwner() === this.chains.chains[val.chainId]?.signer?.getAddress())
|
|
105
118
|
.filter(val => token == null ? true : val.data.getTokenData()[0].token === token);
|
|
106
119
|
}
|
|
107
120
|
async fundVault(vault, tokenAmounts) {
|
|
108
121
|
if (vault.state !== SpvVault_1.SpvVaultState.OPENED)
|
|
109
122
|
throw new Error("Vault not opened!");
|
|
110
123
|
this.logger.info("fundVault(): Depositing tokens to the vault " + vault.data.getVaultId().toString(10) + ", amounts: " + tokenAmounts.map(val => val.toString(10)).join(", "));
|
|
111
|
-
const { signer, spvVaultContract } = this.
|
|
124
|
+
const { signer, spvVaultContract } = this.chains.chains[vault.chainId];
|
|
112
125
|
const txId = await spvVaultContract.deposit(signer, vault.data, tokenAmounts, { waitForConfirmation: true });
|
|
113
126
|
this.logger.info("fundVault(): Tokens deposited to vault " + vault.data.getVaultId().toString(10) + ", amounts: " + tokenAmounts.map(val => val.toString(10)).join(", ") + ", txId: " + txId);
|
|
114
127
|
return txId;
|
|
@@ -122,7 +135,7 @@ class SpvVaults {
|
|
|
122
135
|
});
|
|
123
136
|
if (!vault.isReady())
|
|
124
137
|
throw new Error("Vault not ready, wait for the latest swap to get at least 1 confirmation!");
|
|
125
|
-
const { signer, spvVaultContract } = this.
|
|
138
|
+
const { signer, spvVaultContract } = this.chains.chains[vault.chainId];
|
|
126
139
|
const latestUtxo = vault.getLatestUtxo();
|
|
127
140
|
const [txId, voutStr] = latestUtxo.split(":");
|
|
128
141
|
const opReturnData = spvVaultContract.toOpReturnData(signer.getAddress(), tokenAmounts);
|
|
@@ -186,7 +199,7 @@ class SpvVaults {
|
|
|
186
199
|
const vaults = Object.keys(this.vaultStorage.data).map(key => this.vaultStorage.data[key]);
|
|
187
200
|
const claimWithdrawals = [];
|
|
188
201
|
for (let vault of vaults) {
|
|
189
|
-
const { signer, spvVaultContract, chainInterface } = this.
|
|
202
|
+
const { signer, spvVaultContract, chainInterface } = this.chains.chains[vault.chainId];
|
|
190
203
|
if (vault.data.getOwner() !== signer.getAddress())
|
|
191
204
|
continue;
|
|
192
205
|
if (vault.state === SpvVault_1.SpvVaultState.BTC_INITIATED) {
|
|
@@ -204,16 +217,25 @@ class SpvVaults {
|
|
|
204
217
|
}
|
|
205
218
|
if (vault.state === SpvVault_1.SpvVaultState.BTC_CONFIRMED) {
|
|
206
219
|
//Check if open txs were sent already
|
|
207
|
-
if (vault.
|
|
220
|
+
if (vault.scOpenTxs != null) {
|
|
208
221
|
//Check if confirmed
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
222
|
+
let _continue = false;
|
|
223
|
+
for (let txId in vault.scOpenTxs) {
|
|
224
|
+
const tx = vault.scOpenTxs[txId];
|
|
225
|
+
const status = await chainInterface.getTxStatus(tx);
|
|
226
|
+
if (status === "pending") {
|
|
227
|
+
_continue = true;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
if (status === "success") {
|
|
231
|
+
vault.state = SpvVault_1.SpvVaultState.OPENED;
|
|
232
|
+
await this.saveVault(vault);
|
|
233
|
+
_continue = true;
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
216
236
|
}
|
|
237
|
+
if (_continue)
|
|
238
|
+
continue;
|
|
217
239
|
}
|
|
218
240
|
const txs = await spvVaultContract.txsOpen(signer.getAddress(), vault.data);
|
|
219
241
|
let numTx = 0;
|
|
@@ -221,7 +243,7 @@ class SpvVaults {
|
|
|
221
243
|
numTx++;
|
|
222
244
|
if (numTx === txs.length) {
|
|
223
245
|
//Final tx
|
|
224
|
-
vault.
|
|
246
|
+
vault.scOpenTxs = { [txId]: rawTx };
|
|
225
247
|
await this.saveVault(vault);
|
|
226
248
|
}
|
|
227
249
|
});
|
|
@@ -289,7 +311,7 @@ class SpvVaults {
|
|
|
289
311
|
}
|
|
290
312
|
}
|
|
291
313
|
async claimWithdrawals(vault, withdrawal) {
|
|
292
|
-
const { signer, spvVaultContract } = this.
|
|
314
|
+
const { signer, spvVaultContract } = this.chains.chains[vault.chainId];
|
|
293
315
|
try {
|
|
294
316
|
const txId = await spvVaultContract.claim(signer, vault.data, withdrawal.map(tx => {
|
|
295
317
|
return { tx };
|
|
@@ -317,7 +339,7 @@ class SpvVaults {
|
|
|
317
339
|
* @protected
|
|
318
340
|
*/
|
|
319
341
|
async findVaultForSwap(chainIdentifier, totalSats, token, amount, gasToken, gasTokenAmount) {
|
|
320
|
-
const { signer } = this.
|
|
342
|
+
const { signer } = this.chains.chains[chainIdentifier];
|
|
321
343
|
const pluginResponse = await PluginManager_1.PluginManager.onVaultSelection(chainIdentifier, totalSats, { token, amount }, { token: gasToken, amount: gasTokenAmount });
|
|
322
344
|
if (pluginResponse != null) {
|
|
323
345
|
AmountAssertions_1.AmountAssertions.handlePluginErrorResponses(pluginResponse);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomiqlabs/lp-lib",
|
|
3
|
-
"version": "14.0.0-dev.
|
|
3
|
+
"version": "14.0.0-dev.14",
|
|
4
4
|
"description": "Main functionality implementation for atomiq LP node",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types:": "./dist/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"author": "adambor",
|
|
23
23
|
"license": "ISC",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@atomiqlabs/base": "^10.0.0-dev.
|
|
25
|
+
"@atomiqlabs/base": "^10.0.0-dev.9",
|
|
26
26
|
"@atomiqlabs/server-base": "2.0.0",
|
|
27
27
|
"@scure/btc-signer": "1.6.0",
|
|
28
28
|
"express": "4.21.1",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
ClaimEvent,
|
|
10
10
|
InitializeEvent,
|
|
11
11
|
RefundEvent,
|
|
12
|
+
SwapCommitStateType,
|
|
12
13
|
SwapData
|
|
13
14
|
} from "@atomiqlabs/base";
|
|
14
15
|
import {expressHandlerWrapper, getAbortController, HEX_REGEX, isDefinedRuntimeError} from "../../../utils/Utils";
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
LightningNetworkChannel,
|
|
26
27
|
LightningNetworkInvoice
|
|
27
28
|
} from "../../../wallets/ILightningWallet";
|
|
28
|
-
import {
|
|
29
|
+
import {LightningAssertions} from "../../assertions/LightningAssertions";
|
|
29
30
|
|
|
30
31
|
export type FromBtcLnConfig = FromBtcBaseConfig & {
|
|
31
32
|
invoiceTimeoutSeconds?: number,
|
|
@@ -103,34 +104,61 @@ export class FromBtcLnAbs extends FromBtcBaseSwapHandler<FromBtcLnSwapAbs, FromB
|
|
|
103
104
|
return null;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
if(swap.state===FromBtcLnSwapState.RECEIVED) {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
if(swap.state===FromBtcLnSwapState.RECEIVED || swap.state===FromBtcLnSwapState.COMMITED) {
|
|
108
|
+
const onchainStatus = await swapContract.getCommitStatus(signer.getAddress(), swap.data);
|
|
109
|
+
const state: FromBtcLnSwapState = swap.state as FromBtcLnSwapState;
|
|
110
|
+
if(onchainStatus.type===SwapCommitStateType.PAID) {
|
|
111
|
+
//Extract the swap secret
|
|
112
|
+
if(state!==FromBtcLnSwapState.CLAIMED && state!==FromBtcLnSwapState.SETTLED) {
|
|
113
|
+
const secretHex = await onchainStatus.getClaimResult();
|
|
114
|
+
const secret: Buffer = Buffer.from(secretHex, "hex");
|
|
115
|
+
const paymentHash: Buffer = createHash("sha256").update(secret).digest();
|
|
116
|
+
const paymentHashHex = paymentHash.toString("hex");
|
|
117
|
+
|
|
118
|
+
if (swap.lnPaymentHash!==paymentHashHex) {
|
|
119
|
+
//TODO: Possibly fatal failure
|
|
120
|
+
this.swapLogger.error(swap, "processPastSwap(state=RECEIVED|COMMITED): onchainStatus=PAID, Invalid swap secret specified: "+secretHex+" for paymentHash: "+paymentHashHex);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
swap.secret = secretHex;
|
|
125
|
+
await swap.setState(FromBtcLnSwapState.CLAIMED);
|
|
126
|
+
await this.saveSwapData(swap);
|
|
127
|
+
|
|
128
|
+
this.swapLogger.warn(swap, "processPastSwap(state=RECEIVED|COMMITED): swap settled (detected from processPastSwap), invoice: "+swap.pr);
|
|
129
|
+
|
|
130
|
+
return "SETTLE";
|
|
115
131
|
}
|
|
116
|
-
|
|
117
|
-
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED): swap committed (detected from processPastSwap), invoice: "+swap.pr);
|
|
118
|
-
await swap.setState(FromBtcLnSwapState.COMMITED);
|
|
119
|
-
await this.saveSwapData(swap);
|
|
132
|
+
return null;
|
|
120
133
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
134
|
+
if(onchainStatus.type===SwapCommitStateType.COMMITED) {
|
|
135
|
+
if(state===FromBtcLnSwapState.RECEIVED) {
|
|
136
|
+
await swap.setState(FromBtcLnSwapState.COMMITED);
|
|
137
|
+
await this.saveSwapData(swap);
|
|
125
138
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
139
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap committed (detected from processPastSwap), invoice: "+swap.pr);
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
if(onchainStatus.type===SwapCommitStateType.NOT_COMMITED || onchainStatus.type===SwapCommitStateType.EXPIRED) {
|
|
144
|
+
if(swap.state===FromBtcLnSwapState.RECEIVED) {
|
|
145
|
+
const isAuthorizationExpired = await swapContract.isInitAuthorizationExpired(swap.data, swap);
|
|
146
|
+
if(isAuthorizationExpired) {
|
|
147
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap not committed before authorization expiry, cancelling the LN invoice, invoice: "+swap.pr);
|
|
148
|
+
await swap.setState(FromBtcLnSwapState.CANCELED);
|
|
149
|
+
return "CANCEL";
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
if(await swapContract.isExpired(signer.getAddress(), swap.data)) {
|
|
153
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap timed out, refunding to self, invoice: "+swap.pr);
|
|
154
|
+
return "REFUND";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if(onchainStatus.type===SwapCommitStateType.REFUNDABLE) {
|
|
159
|
+
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED|COMMITED): swap timed out, refunding to self, invoice: "+swap.pr);
|
|
129
160
|
return "REFUND";
|
|
130
161
|
}
|
|
131
|
-
|
|
132
|
-
this.swapLogger.info(swap, "processPastSwap(state=RECEIVED): swap timed out, cancelling the LN invoice, invoice: "+swap.pr);
|
|
133
|
-
return "CANCEL";
|
|
134
162
|
}
|
|
135
163
|
|
|
136
164
|
if(swap.state===FromBtcLnSwapState.CLAIMED) return "SETTLE";
|
|
@@ -3,7 +3,7 @@ import {createHash} from "crypto";
|
|
|
3
3
|
import {FromBtcLnAutoSwap, FromBtcLnAutoSwapState} from "./FromBtcLnAutoSwap";
|
|
4
4
|
import {MultichainData, SwapHandlerType} from "../../SwapHandler";
|
|
5
5
|
import {ISwapPrice} from "../../../prices/ISwapPrice";
|
|
6
|
-
import {ChainSwapType, ClaimEvent, InitializeEvent, RefundEvent, SwapData} from "@atomiqlabs/base";
|
|
6
|
+
import {ChainSwapType, ClaimEvent, InitializeEvent, RefundEvent, SwapCommitStateType, SwapData} from "@atomiqlabs/base";
|
|
7
7
|
import {expressHandlerWrapper, getAbortController, HEX_REGEX} from "../../../utils/Utils";
|
|
8
8
|
import {PluginManager} from "../../../plugins/PluginManager";
|
|
9
9
|
import {IIntermediaryStorage} from "../../../storage/IIntermediaryStorage";
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
LightningNetworkInvoice
|
|
20
20
|
} from "../../../wallets/ILightningWallet";
|
|
21
21
|
import {LightningAssertions} from "../../assertions/LightningAssertions";
|
|
22
|
+
import {FromBtcLnSwapState} from "../frombtcln_abstract/FromBtcLnSwapAbs";
|
|
22
23
|
|
|
23
24
|
export type FromBtcLnAutoConfig = FromBtcBaseConfig & {
|
|
24
25
|
invoiceTimeoutSeconds?: number,
|
|
@@ -110,35 +111,61 @@ export class FromBtcLnAuto extends FromBtcBaseSwapHandler<FromBtcLnAutoSwap, Fro
|
|
|
110
111
|
return null;
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
if(swap.state===FromBtcLnAutoSwapState.TXS_SENT) {
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
if(swap.state===FromBtcLnAutoSwapState.TXS_SENT || swap.state===FromBtcLnAutoSwapState.COMMITED) {
|
|
115
|
+
const onchainStatus = await swapContract.getCommitStatus(signer.getAddress(), swap.data);
|
|
116
|
+
const state: FromBtcLnAutoSwapState = swap.state as FromBtcLnAutoSwapState;
|
|
117
|
+
if(onchainStatus.type===SwapCommitStateType.PAID) {
|
|
118
|
+
//Extract the swap secret
|
|
119
|
+
if(state!==FromBtcLnAutoSwapState.CLAIMED && state!==FromBtcLnAutoSwapState.SETTLED) {
|
|
120
|
+
const secretHex = await onchainStatus.getClaimResult();
|
|
121
|
+
const secret: Buffer = Buffer.from(secretHex, "hex");
|
|
122
|
+
const paymentHash: Buffer = createHash("sha256").update(secret).digest();
|
|
123
|
+
const paymentHashHex = paymentHash.toString("hex");
|
|
124
|
+
|
|
125
|
+
if (swap.lnPaymentHash!==paymentHashHex) {
|
|
126
|
+
//TODO: Possibly fatal failure
|
|
127
|
+
this.swapLogger.error(swap, "processPastSwap(state=TXS_SENT|COMMITED): onchainStatus=PAID, Invalid swap secret specified: "+secretHex+" for paymentHash: "+paymentHashHex);
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
117
130
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
await this.
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
131
|
+
swap.secret = secretHex;
|
|
132
|
+
await swap.setState(FromBtcLnAutoSwapState.CLAIMED);
|
|
133
|
+
await this.saveSwapData(swap);
|
|
123
134
|
|
|
124
|
-
|
|
125
|
-
await swap.setState(FromBtcLnAutoSwapState.COMMITED);
|
|
126
|
-
await this.saveSwapData(swap);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
135
|
+
this.swapLogger.warn(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap settled (detected from processPastSwap), invoice: "+swap.pr);
|
|
129
136
|
|
|
130
|
-
|
|
131
|
-
|
|
137
|
+
return "SETTLE";
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
if(onchainStatus.type===SwapCommitStateType.COMMITED) {
|
|
142
|
+
if(state===FromBtcLnAutoSwapState.TXS_SENT) {
|
|
143
|
+
await swap.setState(FromBtcLnAutoSwapState.COMMITED);
|
|
144
|
+
await this.saveSwapData(swap);
|
|
132
145
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
146
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap committed (detected from processPastSwap), invoice: "+swap.pr);
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
if(onchainStatus.type===SwapCommitStateType.NOT_COMMITED || onchainStatus.type===SwapCommitStateType.EXPIRED) {
|
|
151
|
+
if(swap.state===FromBtcLnAutoSwapState.TXS_SENT) {
|
|
152
|
+
const isAuthorizationExpired = await swapContract.isInitAuthorizationExpired(swap.data, swap);
|
|
153
|
+
if(isAuthorizationExpired) {
|
|
154
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap not committed before authorization expiry, cancelling the LN invoice, invoice: "+swap.pr);
|
|
155
|
+
await this.cancelSwapAndInvoice(swap);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
if(await swapContract.isExpired(signer.getAddress(), swap.data)) {
|
|
160
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap timed out, refunding to self, invoice: "+swap.pr);
|
|
161
|
+
return "REFUND";
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if(onchainStatus.type===SwapCommitStateType.REFUNDABLE) {
|
|
166
|
+
this.swapLogger.info(swap, "processPastSwap(state=TXS_SENT|COMMITED): swap timed out, refunding to self, invoice: "+swap.pr);
|
|
136
167
|
return "REFUND";
|
|
137
168
|
}
|
|
138
|
-
|
|
139
|
-
this.swapLogger.info(swap, "processPastSwap(state=COMMITED): swap timed out, cancelling the LN invoice, invoice: "+swap.pr);
|
|
140
|
-
await this.cancelSwapAndInvoice(swap);
|
|
141
|
-
return null;
|
|
142
169
|
}
|
|
143
170
|
|
|
144
171
|
if(swap.state===FromBtcLnAutoSwapState.CLAIMED) return "SETTLE";
|
|
@@ -34,7 +34,7 @@ export class SpvVault<
|
|
|
34
34
|
|
|
35
35
|
balances: SpvVaultTokenBalance[];
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
scOpenTxs: {[txId: string]: string};
|
|
38
38
|
|
|
39
39
|
constructor(chainId: string, vault: T, btcAddress: string);
|
|
40
40
|
constructor(obj: any);
|
|
@@ -54,7 +54,7 @@ export class SpvVault<
|
|
|
54
54
|
this.initialUtxo = chainIdOrObj.initialUtxo;
|
|
55
55
|
this.btcAddress = chainIdOrObj.btcAddress;
|
|
56
56
|
this.pendingWithdrawals = chainIdOrObj.pendingWithdrawals.map(SpvWithdrawalTransactionData.deserialize<D>);
|
|
57
|
-
this.
|
|
57
|
+
this.scOpenTxs = chainIdOrObj.scOpenTxs;
|
|
58
58
|
}
|
|
59
59
|
this.balances = this.data.calculateStateAfter(this.pendingWithdrawals).balances;
|
|
60
60
|
}
|
|
@@ -113,7 +113,7 @@ export class SpvVault<
|
|
|
113
113
|
initialUtxo: this.initialUtxo,
|
|
114
114
|
btcAddress: this.btcAddress,
|
|
115
115
|
pendingWithdrawals: this.pendingWithdrawals.map(val => val.serialize()),
|
|
116
|
-
|
|
116
|
+
scOpenTxs: this.scOpenTxs
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -86,7 +86,7 @@ export class SpvVaultSwapHandler extends SwapHandler<SpvVaultSwap, SpvVaultSwapS
|
|
|
86
86
|
this.vaultSigner = spvVaultSigner;
|
|
87
87
|
this.config = config;
|
|
88
88
|
this.AmountAssertions = new FromBtcAmountAssertions(config, swapPricing);
|
|
89
|
-
this.Vaults = new SpvVaults(vaultStorage, bitcoin, spvVaultSigner, bitcoinRpc, this.
|
|
89
|
+
this.Vaults = new SpvVaults(vaultStorage, bitcoin, spvVaultSigner, bitcoinRpc, this.chains, config);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
protected async processClaimEvent(swap: SpvVaultSwap | null, event: SpvVaultClaimEvent): Promise<void> {
|
|
@@ -502,6 +502,7 @@ export class SpvVaultSwapHandler extends SwapHandler<SpvVaultSwap, SpvVaultSwapS
|
|
|
502
502
|
data.executionFeeRate!==swap.executionFeeShare ||
|
|
503
503
|
data.rawAmounts[0]!==swap.rawAmountToken ||
|
|
504
504
|
data.rawAmounts[1]!==swap.rawAmountGasToken ||
|
|
505
|
+
data.getExecutionData()!=null ||
|
|
505
506
|
data.getSpentVaultUtxo()!==swap.vaultUtxo ||
|
|
506
507
|
data.btcTx.outs[0].value!==VAULT_DUST_AMOUNT ||
|
|
507
508
|
!Buffer.from(data.btcTx.outs[0].scriptPubKey.hex, "hex").equals(this.bitcoin.toOutputScript(swap.vaultAddress)) ||
|
|
@@ -13,7 +13,7 @@ import {PluginManager} from "../../plugins/PluginManager";
|
|
|
13
13
|
import {IBitcoinWallet} from "../../wallets/IBitcoinWallet";
|
|
14
14
|
import {ISpvVaultSigner} from "../../wallets/ISpvVaultSigner";
|
|
15
15
|
import {AmountAssertions} from "../assertions/AmountAssertions";
|
|
16
|
-
import {
|
|
16
|
+
import {MultichainData} from "../SwapHandler";
|
|
17
17
|
import {Transaction} from "@scure/btc-signer";
|
|
18
18
|
|
|
19
19
|
export const VAULT_DUST_AMOUNT = 600;
|
|
@@ -28,7 +28,7 @@ export class SpvVaults {
|
|
|
28
28
|
readonly vaultSigner: ISpvVaultSigner;
|
|
29
29
|
readonly bitcoinRpc: BitcoinRpc<any>;
|
|
30
30
|
readonly config: {vaultsCheckInterval: number, maxUnclaimedWithdrawals?: number};
|
|
31
|
-
readonly
|
|
31
|
+
readonly chains: MultichainData;
|
|
32
32
|
|
|
33
33
|
readonly logger = getLogger("SpvVaults: ");
|
|
34
34
|
|
|
@@ -37,15 +37,29 @@ export class SpvVaults {
|
|
|
37
37
|
bitcoin: IBitcoinWallet,
|
|
38
38
|
vaultSigner: ISpvVaultSigner,
|
|
39
39
|
bitcoinRpc: BitcoinRpc<any>,
|
|
40
|
-
|
|
40
|
+
chains: MultichainData,
|
|
41
41
|
config: {vaultsCheckInterval: number, maxUnclaimedWithdrawals?: number}
|
|
42
42
|
) {
|
|
43
43
|
this.vaultStorage = vaultStorage;
|
|
44
44
|
this.bitcoin = bitcoin;
|
|
45
45
|
this.vaultSigner = vaultSigner;
|
|
46
46
|
this.bitcoinRpc = bitcoinRpc;
|
|
47
|
-
this.
|
|
47
|
+
this.chains = chains;
|
|
48
48
|
this.config = config;
|
|
49
|
+
|
|
50
|
+
for(let chainId in chains.chains) {
|
|
51
|
+
const {chainInterface} = chains.chains[chainId];
|
|
52
|
+
chainInterface.onBeforeTxReplace(async (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => {
|
|
53
|
+
for(let key in this.vaultStorage.data) {
|
|
54
|
+
const vaultData = this.vaultStorage.data[key];
|
|
55
|
+
if(vaultData.scOpenTxs!=null && vaultData.scOpenTxs[oldTxId]!=null){
|
|
56
|
+
vaultData.scOpenTxs[newTxId] = newTx;
|
|
57
|
+
await this.saveVault(vaultData);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
49
63
|
}
|
|
50
64
|
|
|
51
65
|
async processDepositEvent(vault: SpvVault, event: SpvVaultDepositEvent): Promise<void> {
|
|
@@ -78,7 +92,7 @@ export class SpvVaults {
|
|
|
78
92
|
}
|
|
79
93
|
|
|
80
94
|
async createVaults(chainId: string, count: number, token: string, confirmations: number = 2, feeRate?: number): Promise<{vaultsCreated: bigint[], btcTxId: string}> {
|
|
81
|
-
const {signer, chainInterface, tokenMultipliers, spvVaultContract} = this.
|
|
95
|
+
const {signer, chainInterface, tokenMultipliers, spvVaultContract} = this.chains.chains[chainId];
|
|
82
96
|
|
|
83
97
|
const signerAddress = signer.getAddress();
|
|
84
98
|
|
|
@@ -141,7 +155,7 @@ export class SpvVaults {
|
|
|
141
155
|
return Object.keys(this.vaultStorage.data)
|
|
142
156
|
.map(key => this.vaultStorage.data[key])
|
|
143
157
|
.filter(val => chainId==null ? true : val.chainId===chainId)
|
|
144
|
-
.filter(val => val.data.getOwner()===this.
|
|
158
|
+
.filter(val => val.data.getOwner()===this.chains.chains[val.chainId]?.signer?.getAddress())
|
|
145
159
|
.filter(val => token==null ? true : val.data.getTokenData()[0].token===token);
|
|
146
160
|
}
|
|
147
161
|
|
|
@@ -150,7 +164,7 @@ export class SpvVaults {
|
|
|
150
164
|
|
|
151
165
|
this.logger.info("fundVault(): Depositing tokens to the vault "+vault.data.getVaultId().toString(10)+", amounts: "+tokenAmounts.map(val => val.toString(10)).join(", "));
|
|
152
166
|
|
|
153
|
-
const {signer, spvVaultContract} = this.
|
|
167
|
+
const {signer, spvVaultContract} = this.chains.chains[vault.chainId];
|
|
154
168
|
|
|
155
169
|
const txId = await spvVaultContract.deposit(signer, vault.data, tokenAmounts, {waitForConfirmation: true});
|
|
156
170
|
|
|
@@ -167,7 +181,7 @@ export class SpvVaults {
|
|
|
167
181
|
|
|
168
182
|
if(!vault.isReady()) throw new Error("Vault not ready, wait for the latest swap to get at least 1 confirmation!");
|
|
169
183
|
|
|
170
|
-
const {signer, spvVaultContract} = this.
|
|
184
|
+
const {signer, spvVaultContract} = this.chains.chains[vault.chainId];
|
|
171
185
|
|
|
172
186
|
const latestUtxo = vault.getLatestUtxo();
|
|
173
187
|
const [txId, voutStr] = latestUtxo.split(":");
|
|
@@ -239,7 +253,7 @@ export class SpvVaults {
|
|
|
239
253
|
const claimWithdrawals: {vault: SpvVault, withdrawals: SpvWithdrawalTransactionData[]}[] = [];
|
|
240
254
|
|
|
241
255
|
for(let vault of vaults) {
|
|
242
|
-
const {signer, spvVaultContract, chainInterface} = this.
|
|
256
|
+
const {signer, spvVaultContract, chainInterface} = this.chains.chains[vault.chainId];
|
|
243
257
|
if(vault.data.getOwner()!==signer.getAddress()) continue;
|
|
244
258
|
|
|
245
259
|
if(vault.state===SpvVaultState.BTC_INITIATED) {
|
|
@@ -258,15 +272,24 @@ export class SpvVaults {
|
|
|
258
272
|
|
|
259
273
|
if(vault.state===SpvVaultState.BTC_CONFIRMED) {
|
|
260
274
|
//Check if open txs were sent already
|
|
261
|
-
if(vault.
|
|
275
|
+
if(vault.scOpenTxs!=null) {
|
|
262
276
|
//Check if confirmed
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
277
|
+
let _continue = false;
|
|
278
|
+
for(let txId in vault.scOpenTxs) {
|
|
279
|
+
const tx = vault.scOpenTxs[txId];
|
|
280
|
+
const status = await chainInterface.getTxStatus(tx);
|
|
281
|
+
if(status==="pending") {
|
|
282
|
+
_continue = true;
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
if(status==="success") {
|
|
286
|
+
vault.state = SpvVaultState.OPENED;
|
|
287
|
+
await this.saveVault(vault);
|
|
288
|
+
_continue = true;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
269
291
|
}
|
|
292
|
+
if(_continue) continue;
|
|
270
293
|
}
|
|
271
294
|
|
|
272
295
|
const txs = await spvVaultContract.txsOpen(signer.getAddress(), vault.data);
|
|
@@ -277,7 +300,7 @@ export class SpvVaults {
|
|
|
277
300
|
numTx++;
|
|
278
301
|
if(numTx===txs.length) {
|
|
279
302
|
//Final tx
|
|
280
|
-
vault.
|
|
303
|
+
vault.scOpenTxs = {[txId]: rawTx};
|
|
281
304
|
await this.saveVault(vault);
|
|
282
305
|
}
|
|
283
306
|
}
|
|
@@ -349,7 +372,7 @@ export class SpvVaults {
|
|
|
349
372
|
}
|
|
350
373
|
|
|
351
374
|
async claimWithdrawals(vault: SpvVault, withdrawal: SpvWithdrawalTransactionData[]): Promise<boolean> {
|
|
352
|
-
const {signer, spvVaultContract} = this.
|
|
375
|
+
const {signer, spvVaultContract} = this.chains.chains[vault.chainId];
|
|
353
376
|
|
|
354
377
|
try {
|
|
355
378
|
const txId = await spvVaultContract.claim(signer, vault.data, withdrawal.map(tx => {
|
|
@@ -379,7 +402,7 @@ export class SpvVaults {
|
|
|
379
402
|
* @protected
|
|
380
403
|
*/
|
|
381
404
|
async findVaultForSwap(chainIdentifier: string, totalSats: bigint, token: string, amount: bigint, gasToken: string, gasTokenAmount: bigint): Promise<SpvVault | null> {
|
|
382
|
-
const {signer} = this.
|
|
405
|
+
const {signer} = this.chains.chains[chainIdentifier];
|
|
383
406
|
|
|
384
407
|
const pluginResponse = await PluginManager.onVaultSelection(
|
|
385
408
|
chainIdentifier, totalSats, {token, amount}, {token: gasToken, amount: gasTokenAmount}
|