@atomiqlabs/lp-lib 10.3.11
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 +201 -0
- package/dist/fees/IBtcFeeEstimator.d.ts +3 -0
- package/dist/fees/IBtcFeeEstimator.js +2 -0
- package/dist/fees/OneDollarFeeEstimator.d.ts +16 -0
- package/dist/fees/OneDollarFeeEstimator.js +71 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +52 -0
- package/dist/info/InfoHandler.d.ts +17 -0
- package/dist/info/InfoHandler.js +70 -0
- package/dist/plugins/IPlugin.d.ts +118 -0
- package/dist/plugins/IPlugin.js +33 -0
- package/dist/plugins/PluginManager.d.ts +89 -0
- package/dist/plugins/PluginManager.js +263 -0
- package/dist/prices/BinanceSwapPrice.d.ts +27 -0
- package/dist/prices/BinanceSwapPrice.js +106 -0
- package/dist/prices/CoinGeckoSwapPrice.d.ts +31 -0
- package/dist/prices/CoinGeckoSwapPrice.js +76 -0
- package/dist/storage/IIntermediaryStorage.d.ts +15 -0
- package/dist/storage/IIntermediaryStorage.js +2 -0
- package/dist/storagemanager/IntermediaryStorageManager.d.ts +15 -0
- package/dist/storagemanager/IntermediaryStorageManager.js +113 -0
- package/dist/storagemanager/StorageManager.d.ts +12 -0
- package/dist/storagemanager/StorageManager.js +74 -0
- package/dist/swaps/FromBtcBaseSwap.d.ts +12 -0
- package/dist/swaps/FromBtcBaseSwap.js +16 -0
- package/dist/swaps/FromBtcBaseSwapHandler.d.ts +118 -0
- package/dist/swaps/FromBtcBaseSwapHandler.js +294 -0
- package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +25 -0
- package/dist/swaps/FromBtcLnBaseSwapHandler.js +55 -0
- package/dist/swaps/ISwapPrice.d.ts +44 -0
- package/dist/swaps/ISwapPrice.js +73 -0
- package/dist/swaps/SwapHandler.d.ts +186 -0
- package/dist/swaps/SwapHandler.js +292 -0
- package/dist/swaps/SwapHandlerSwap.d.ts +75 -0
- package/dist/swaps/SwapHandlerSwap.js +72 -0
- package/dist/swaps/ToBtcBaseSwap.d.ts +35 -0
- package/dist/swaps/ToBtcBaseSwap.js +61 -0
- package/dist/swaps/ToBtcBaseSwapHandler.d.ts +94 -0
- package/dist/swaps/ToBtcBaseSwapHandler.js +233 -0
- package/dist/swaps/frombtc_abstract/FromBtcAbs.d.ts +92 -0
- package/dist/swaps/frombtc_abstract/FromBtcAbs.js +386 -0
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.d.ts +26 -0
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.js +63 -0
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.d.ts +55 -0
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.js +586 -0
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.d.ts +43 -0
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.js +99 -0
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.d.ts +105 -0
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.js +731 -0
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +29 -0
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.js +64 -0
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.d.ts +79 -0
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.js +514 -0
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +28 -0
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.js +66 -0
- package/dist/swaps/tobtc_abstract/ToBtcAbs.d.ts +290 -0
- package/dist/swaps/tobtc_abstract/ToBtcAbs.js +1056 -0
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.d.ts +29 -0
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.js +70 -0
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.d.ts +246 -0
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.js +1169 -0
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +27 -0
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.js +65 -0
- package/dist/utils/Utils.d.ts +32 -0
- package/dist/utils/Utils.js +109 -0
- package/dist/utils/coinselect2/accumulative.d.ts +6 -0
- package/dist/utils/coinselect2/accumulative.js +44 -0
- package/dist/utils/coinselect2/blackjack.d.ts +6 -0
- package/dist/utils/coinselect2/blackjack.js +41 -0
- package/dist/utils/coinselect2/index.d.ts +16 -0
- package/dist/utils/coinselect2/index.js +40 -0
- package/dist/utils/coinselect2/utils.d.ts +64 -0
- package/dist/utils/coinselect2/utils.js +121 -0
- package/dist/utils/paramcoders/IParamReader.d.ts +5 -0
- package/dist/utils/paramcoders/IParamReader.js +2 -0
- package/dist/utils/paramcoders/IParamWriter.d.ts +4 -0
- package/dist/utils/paramcoders/IParamWriter.js +2 -0
- package/dist/utils/paramcoders/LegacyParamEncoder.d.ts +10 -0
- package/dist/utils/paramcoders/LegacyParamEncoder.js +33 -0
- package/dist/utils/paramcoders/ParamDecoder.d.ts +25 -0
- package/dist/utils/paramcoders/ParamDecoder.js +234 -0
- package/dist/utils/paramcoders/ParamEncoder.d.ts +9 -0
- package/dist/utils/paramcoders/ParamEncoder.js +22 -0
- package/dist/utils/paramcoders/SchemaVerifier.d.ts +22 -0
- package/dist/utils/paramcoders/SchemaVerifier.js +85 -0
- package/dist/utils/paramcoders/server/ServerParamDecoder.d.ts +8 -0
- package/dist/utils/paramcoders/server/ServerParamDecoder.js +105 -0
- package/dist/utils/paramcoders/server/ServerParamEncoder.d.ts +11 -0
- package/dist/utils/paramcoders/server/ServerParamEncoder.js +76 -0
- package/package.json +43 -0
- package/src/fees/IBtcFeeEstimator.ts +7 -0
- package/src/fees/OneDollarFeeEstimator.ts +95 -0
- package/src/index.ts +46 -0
- package/src/info/InfoHandler.ts +106 -0
- package/src/plugins/IPlugin.ts +155 -0
- package/src/plugins/PluginManager.ts +310 -0
- package/src/prices/BinanceSwapPrice.ts +114 -0
- package/src/prices/CoinGeckoSwapPrice.ts +88 -0
- package/src/storage/IIntermediaryStorage.ts +21 -0
- package/src/storagemanager/IntermediaryStorageManager.ts +101 -0
- package/src/storagemanager/StorageManager.ts +68 -0
- package/src/swaps/FromBtcBaseSwap.ts +21 -0
- package/src/swaps/FromBtcBaseSwapHandler.ts +375 -0
- package/src/swaps/FromBtcLnBaseSwapHandler.ts +48 -0
- package/src/swaps/ISwapPrice.ts +94 -0
- package/src/swaps/SwapHandler.ts +404 -0
- package/src/swaps/SwapHandlerSwap.ts +133 -0
- package/src/swaps/ToBtcBaseSwap.ts +76 -0
- package/src/swaps/ToBtcBaseSwapHandler.ts +309 -0
- package/src/swaps/frombtc_abstract/FromBtcAbs.ts +484 -0
- package/src/swaps/frombtc_abstract/FromBtcSwapAbs.ts +77 -0
- package/src/swaps/frombtc_trusted/FromBtcTrusted.ts +661 -0
- package/src/swaps/frombtc_trusted/FromBtcTrustedSwap.ts +158 -0
- package/src/swaps/frombtcln_abstract/FromBtcLnAbs.ts +864 -0
- package/src/swaps/frombtcln_abstract/FromBtcLnSwapAbs.ts +82 -0
- package/src/swaps/frombtcln_trusted/FromBtcLnTrusted.ts +592 -0
- package/src/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.ts +90 -0
- package/src/swaps/tobtc_abstract/ToBtcAbs.ts +1249 -0
- package/src/swaps/tobtc_abstract/ToBtcSwapAbs.ts +112 -0
- package/src/swaps/tobtcln_abstract/ToBtcLnAbs.ts +1422 -0
- package/src/swaps/tobtcln_abstract/ToBtcLnSwapAbs.ts +87 -0
- package/src/utils/Utils.ts +108 -0
- package/src/utils/coinselect2/accumulative.js +32 -0
- package/src/utils/coinselect2/accumulative.ts +58 -0
- package/src/utils/coinselect2/blackjack.js +29 -0
- package/src/utils/coinselect2/blackjack.ts +54 -0
- package/src/utils/coinselect2/index.js +16 -0
- package/src/utils/coinselect2/index.ts +50 -0
- package/src/utils/coinselect2/utils.js +110 -0
- package/src/utils/coinselect2/utils.ts +183 -0
- package/src/utils/paramcoders/IParamReader.ts +8 -0
- package/src/utils/paramcoders/IParamWriter.ts +8 -0
- package/src/utils/paramcoders/LegacyParamEncoder.ts +28 -0
- package/src/utils/paramcoders/ParamDecoder.ts +219 -0
- package/src/utils/paramcoders/ParamEncoder.ts +30 -0
- package/src/utils/paramcoders/SchemaVerifier.ts +97 -0
- package/src/utils/paramcoders/server/ServerParamDecoder.ts +115 -0
- package/src/utils/paramcoders/server/ServerParamEncoder.ts +76 -0
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
import {FromBtcBaseConfig, FromBtcBaseSwapHandler} from "../FromBtcBaseSwapHandler";
|
|
2
|
+
import {FromBtcTrustedSwap, FromBtcTrustedSwapState} from "./FromBtcTrustedSwap";
|
|
3
|
+
import {BitcoinRpc, BtcBlock, BtcTx, ClaimEvent, InitializeEvent, RefundEvent, SwapData} from "@atomiqlabs/base";
|
|
4
|
+
import {Express, Request, Response} from "express";
|
|
5
|
+
import {MultichainData, SwapHandlerType} from "../SwapHandler";
|
|
6
|
+
import * as BN from "bn.js";
|
|
7
|
+
import {IIntermediaryStorage} from "../../storage/IIntermediaryStorage";
|
|
8
|
+
import {
|
|
9
|
+
AuthenticatedLnd,
|
|
10
|
+
broadcastChainTransaction,
|
|
11
|
+
ChainTransaction, createChainAddress, createHodlInvoice,
|
|
12
|
+
getChainTransactions, getHeight,
|
|
13
|
+
signPsbt,
|
|
14
|
+
subscribeToTransactions, SubscribeToTransactionsChainTransactionEvent
|
|
15
|
+
} from "lightning";
|
|
16
|
+
import {ISwapPrice} from "../ISwapPrice";
|
|
17
|
+
import {PluginManager} from "../../plugins/PluginManager";
|
|
18
|
+
import {address, networks, Psbt, Transaction, TxOutput} from "bitcoinjs-lib";
|
|
19
|
+
import {IBtcFeeEstimator} from "../../fees/IBtcFeeEstimator";
|
|
20
|
+
import {utils} from "../../utils/coinselect2/utils";
|
|
21
|
+
import {expressHandlerWrapper, HEX_REGEX} from "../../utils/Utils";
|
|
22
|
+
import {IParamReader} from "../../utils/paramcoders/IParamReader";
|
|
23
|
+
import {ServerParamEncoder} from "../../utils/paramcoders/server/ServerParamEncoder";
|
|
24
|
+
import {FieldTypeEnum, verifySchema} from "../../utils/paramcoders/SchemaVerifier";
|
|
25
|
+
import * as bitcoin from "bitcoinjs-lib";
|
|
26
|
+
import {serverParamDecoder} from "../../utils/paramcoders/server/ServerParamDecoder";
|
|
27
|
+
|
|
28
|
+
export type FromBtcTrustedConfig = FromBtcBaseConfig & {
|
|
29
|
+
bitcoinNetwork: networks.Network,
|
|
30
|
+
feeEstimator: IBtcFeeEstimator,
|
|
31
|
+
doubleSpendCheckInterval: number,
|
|
32
|
+
swapAddressExpiry: number,
|
|
33
|
+
recommendFeeMultiplier?: number,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type FromBtcTrustedRequestType = {
|
|
37
|
+
address: string,
|
|
38
|
+
refundAddress: string,
|
|
39
|
+
amount: BN,
|
|
40
|
+
exactOut?: boolean
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export class FromBtcTrusted extends FromBtcBaseSwapHandler<FromBtcTrustedSwap, FromBtcTrustedSwapState> {
|
|
44
|
+
readonly type: SwapHandlerType = SwapHandlerType.FROM_BTC_TRUSTED;
|
|
45
|
+
|
|
46
|
+
readonly config: FromBtcTrustedConfig;
|
|
47
|
+
readonly bitcoinRpc: BitcoinRpc<BtcBlock>;
|
|
48
|
+
|
|
49
|
+
readonly subscriptions: Map<string, FromBtcTrustedSwap> = new Map<string, FromBtcTrustedSwap>();
|
|
50
|
+
readonly doubleSpendWatchdogSwaps: Set<FromBtcTrustedSwap> = new Set<FromBtcTrustedSwap>();
|
|
51
|
+
|
|
52
|
+
readonly refundedSwaps: Map<string, string> = new Map();
|
|
53
|
+
readonly doubleSpentSwaps: Map<string, string> = new Map();
|
|
54
|
+
readonly processedTxIds: Map<string, { txId: string, adjustedAmount: BN, adjustedTotal: BN }> = new Map();
|
|
55
|
+
|
|
56
|
+
constructor(
|
|
57
|
+
storageDirectory: IIntermediaryStorage<FromBtcTrustedSwap>,
|
|
58
|
+
path: string,
|
|
59
|
+
chains: MultichainData,
|
|
60
|
+
lnd: AuthenticatedLnd,
|
|
61
|
+
swapPricing: ISwapPrice,
|
|
62
|
+
bitcoinRpc: BitcoinRpc<BtcBlock>,
|
|
63
|
+
config: FromBtcTrustedConfig
|
|
64
|
+
) {
|
|
65
|
+
super(storageDirectory, path, chains, lnd, swapPricing);
|
|
66
|
+
this.config = config;
|
|
67
|
+
this.config.recommendFeeMultiplier ??= 1.25;
|
|
68
|
+
this.bitcoinRpc = bitcoinRpc;
|
|
69
|
+
for(let chainId in chains.chains) {
|
|
70
|
+
this.allowedTokens[chainId] = new Set<string>([chains.chains[chainId].swapContract.getNativeCurrencyAddress()]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private getAllAncestors(tx: ChainTransaction): Promise<{tx: BtcTx, vout: number}[]> {
|
|
75
|
+
return Promise.all(tx.inputs.map(input => this.bitcoinRpc.getTransaction(input.transaction_id).then(tx => {
|
|
76
|
+
return {tx, vout: input.transaction_vout}
|
|
77
|
+
})));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async refundSwap(swap: FromBtcTrustedSwap) {
|
|
81
|
+
let unlock = swap.lock(30*1000);
|
|
82
|
+
if(unlock==null) return;
|
|
83
|
+
|
|
84
|
+
const feeRate = await this.config.feeEstimator.estimateFee();
|
|
85
|
+
|
|
86
|
+
const initialTx = Transaction.fromHex(swap.rawTx);
|
|
87
|
+
const ourOutput = initialTx.outs[swap.vout];
|
|
88
|
+
|
|
89
|
+
//Construct PSBT
|
|
90
|
+
const refundOutputScript = address.toOutputScript(swap.refundAddress, this.config.bitcoinNetwork);
|
|
91
|
+
const txBytes = utils.transactionBytes([{type: "p2wpkh"}], [{script: refundOutputScript}], "p2wpkh");
|
|
92
|
+
const txFee = txBytes*feeRate;
|
|
93
|
+
const adjustedOutput = ourOutput.value-txFee;
|
|
94
|
+
if(adjustedOutput<546) {
|
|
95
|
+
this.swapLogger.error(swap, "refundSwap(): cannot refund swap because of dust limit, txId: "+swap.txId);
|
|
96
|
+
unlock();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
//Construct PSBT
|
|
101
|
+
const _psbt = new Psbt({network: this.config.bitcoinNetwork});
|
|
102
|
+
_psbt.addInput({
|
|
103
|
+
hash: initialTx.getHash(),
|
|
104
|
+
index: swap.vout,
|
|
105
|
+
witnessUtxo: ourOutput,
|
|
106
|
+
sighashType: 0x01,
|
|
107
|
+
sequence: 0xfffffffd
|
|
108
|
+
});
|
|
109
|
+
_psbt.addOutput({
|
|
110
|
+
script: refundOutputScript,
|
|
111
|
+
value: adjustedOutput
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
//Sign
|
|
115
|
+
const {psbt, transaction} = await signPsbt({
|
|
116
|
+
lnd: this.LND,
|
|
117
|
+
psbt: _psbt.toHex()
|
|
118
|
+
});
|
|
119
|
+
if(swap.metadata!=null) swap.metadata.times.refundSignPSBT = Date.now();
|
|
120
|
+
this.swapLogger.debug(swap, "refundSwap(): signed raw transaction: "+transaction);
|
|
121
|
+
|
|
122
|
+
const signedTx = Transaction.fromHex(transaction);
|
|
123
|
+
const refundTxId = signedTx.getId();
|
|
124
|
+
swap.refundTxId = refundTxId;
|
|
125
|
+
|
|
126
|
+
//Send the refund TX
|
|
127
|
+
await broadcastChainTransaction({transaction, lnd: this.LND});
|
|
128
|
+
|
|
129
|
+
this.swapLogger.debug(swap, "refundSwap(): sent refund transaction: "+refundTxId);
|
|
130
|
+
|
|
131
|
+
this.refundedSwaps.set(swap.getHash(), refundTxId);
|
|
132
|
+
await this.removeSwapData(swap, FromBtcTrustedSwapState.REFUNDED);
|
|
133
|
+
unlock();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private async burn(swap: FromBtcTrustedSwap) {
|
|
137
|
+
const initialTx = Transaction.fromHex(swap.rawTx);
|
|
138
|
+
const ourOutput = initialTx.outs[swap.vout];
|
|
139
|
+
|
|
140
|
+
//Construct PSBT
|
|
141
|
+
const _psbt = new Psbt({network: this.config.bitcoinNetwork});
|
|
142
|
+
_psbt.addInput({
|
|
143
|
+
hash: initialTx.getHash(),
|
|
144
|
+
index: swap.vout,
|
|
145
|
+
witnessUtxo: ourOutput,
|
|
146
|
+
sighashType: 0x01,
|
|
147
|
+
sequence: 0xfffffffd
|
|
148
|
+
});
|
|
149
|
+
_psbt.addOutput({
|
|
150
|
+
script: Buffer.concat([Buffer.from([0x6a, 20]), Buffer.from("BURN, BABY, BURN! AQ", "ascii")]),
|
|
151
|
+
value: 0
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
//Sign
|
|
155
|
+
const {psbt, transaction} = await signPsbt({
|
|
156
|
+
lnd: this.LND,
|
|
157
|
+
psbt: _psbt.toHex()
|
|
158
|
+
});
|
|
159
|
+
if(swap.metadata!=null) swap.metadata.times.burnSignPSBT = Date.now();
|
|
160
|
+
this.swapLogger.debug(swap, "burn(): signed raw transaction: "+transaction);
|
|
161
|
+
|
|
162
|
+
const signedTx = Transaction.fromHex(transaction);
|
|
163
|
+
const burnTxId = signedTx.getId();
|
|
164
|
+
swap.burnTxId = burnTxId;
|
|
165
|
+
|
|
166
|
+
//Send the original TX + our burn TX as a package
|
|
167
|
+
const sendTxns = [swap.rawTx, transaction];
|
|
168
|
+
await this.bitcoinRpc.sendRawPackage(sendTxns);
|
|
169
|
+
|
|
170
|
+
this.swapLogger.debug(swap, "burn(): sent burn transaction: "+burnTxId);
|
|
171
|
+
this.doubleSpentSwaps.set(swap.getHash(), burnTxId);
|
|
172
|
+
await this.removeSwapData(swap, FromBtcTrustedSwapState.DOUBLE_SPENT);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
protected async processPastSwap(swap: FromBtcTrustedSwap, tx: ChainTransaction | null): Promise<void> {
|
|
176
|
+
let parsedTx: Transaction = null;
|
|
177
|
+
let foundVout: TxOutput = null;
|
|
178
|
+
let vout: number = -1;
|
|
179
|
+
if(tx!=null) {
|
|
180
|
+
parsedTx = Transaction.fromHex(tx.transaction);
|
|
181
|
+
const requiredOutputScript = address.toOutputScript(swap.btcAddress, this.config.bitcoinNetwork);
|
|
182
|
+
vout = parsedTx.outs.findIndex(vout => vout.script.equals(requiredOutputScript));
|
|
183
|
+
if(vout!==-1) foundVout = parsedTx.outs[vout];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const {swapContract, signer} = this.getChain(swap.chainIdentifier);
|
|
187
|
+
|
|
188
|
+
if(swap.state===FromBtcTrustedSwapState.CREATED) {
|
|
189
|
+
this.subscriptions.set(swap.btcAddress, swap);
|
|
190
|
+
if(foundVout==null) {
|
|
191
|
+
//Check expiry
|
|
192
|
+
if(swap.expiresAt<Date.now()) {
|
|
193
|
+
this.subscriptions.delete(swap.btcAddress);
|
|
194
|
+
await this.removeSwapData(swap, FromBtcTrustedSwapState.EXPIRED);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const sentSats = new BN(foundVout.value);
|
|
200
|
+
if(sentSats.eq(swap.inputSats)) {
|
|
201
|
+
swap.adjustedInput = swap.inputSats;
|
|
202
|
+
swap.adjustedOutput = swap.outputTokens;
|
|
203
|
+
} else {
|
|
204
|
+
//If lower than minimum then ignore
|
|
205
|
+
if(sentSats.lt(this.config.min)) return;
|
|
206
|
+
if(sentSats.gt(this.config.max)) {
|
|
207
|
+
swap.rawTx = tx.transaction;
|
|
208
|
+
swap.txId = tx.id;
|
|
209
|
+
swap.vout = vout;
|
|
210
|
+
this.subscriptions.delete(swap.btcAddress);
|
|
211
|
+
await this.refundSwap(swap);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
//Adjust the amount
|
|
215
|
+
swap.adjustedInput = sentSats;
|
|
216
|
+
swap.adjustedOutput = swap.outputTokens.mul(sentSats).div(swap.inputSats);
|
|
217
|
+
}
|
|
218
|
+
swap.rawTx = tx.transaction;
|
|
219
|
+
swap.txId = tx.id;
|
|
220
|
+
swap.vout = vout;
|
|
221
|
+
this.subscriptions.delete(swap.btcAddress);
|
|
222
|
+
await swap.setState(FromBtcTrustedSwapState.RECEIVED);
|
|
223
|
+
await this.storageManager.saveData(swap.getHash(), null, swap);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if(swap.state===FromBtcTrustedSwapState.RECEIVED) {
|
|
227
|
+
//Check if transaction still exists
|
|
228
|
+
if(tx==null || foundVout==null || tx.id!==swap.txId) {
|
|
229
|
+
await swap.setState(FromBtcTrustedSwapState.CREATED);
|
|
230
|
+
await this.storageManager.saveData(swap.getHash(), null, swap);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
//Check if it is confirmed
|
|
234
|
+
if(tx.confirmation_count>0) {
|
|
235
|
+
await swap.setState(FromBtcTrustedSwapState.BTC_CONFIRMED);
|
|
236
|
+
await this.storageManager.saveData(swap.getHash(), null, swap);
|
|
237
|
+
} else {
|
|
238
|
+
//Check if it pays high enough fee AND has confirmed ancestors
|
|
239
|
+
const ancestors = await this.getAllAncestors(tx);
|
|
240
|
+
const allAncestorsConfirmed = ancestors.reduce((prev, curr) => prev && curr.tx.confirmations>0, true);
|
|
241
|
+
const totalInput = ancestors.reduce((prev, curr) => prev + curr.tx.outs[curr.vout].value, 0);
|
|
242
|
+
const totalOutput = parsedTx.outs.reduce((prev, curr) => prev + curr.value, 0);
|
|
243
|
+
const fee = totalInput-totalOutput;
|
|
244
|
+
const feePerVbyte = Math.ceil(fee/parsedTx.virtualSize());
|
|
245
|
+
if(
|
|
246
|
+
allAncestorsConfirmed &&
|
|
247
|
+
(feePerVbyte>=swap.recommendedFee || feePerVbyte>=await this.config.feeEstimator.estimateFee())
|
|
248
|
+
) {
|
|
249
|
+
if(swap.state!==FromBtcTrustedSwapState.RECEIVED) return;
|
|
250
|
+
await swap.setState(FromBtcTrustedSwapState.BTC_CONFIRMED);
|
|
251
|
+
await this.storageManager.saveData(swap.getHash(), null, swap);
|
|
252
|
+
} else {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if(swap.doubleSpent || tx==null || foundVout==null || tx.id!==swap.txId) {
|
|
259
|
+
if(!swap.doubleSpent) {
|
|
260
|
+
swap.doubleSpent = true;
|
|
261
|
+
try {
|
|
262
|
+
await this.burn(swap);
|
|
263
|
+
this.doubleSpendWatchdogSwaps.delete(swap);
|
|
264
|
+
} catch (e) {
|
|
265
|
+
this.swapLogger.error(swap, "processPastSwap(): Error burning swap: ", e);
|
|
266
|
+
swap.doubleSpent = false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
} else {
|
|
271
|
+
if(!this.doubleSpendWatchdogSwaps.has(swap)) {
|
|
272
|
+
this.swapLogger.debug(swap, "processPastSwap(): Adding swap transaction to double spend watchdog list: ", swap.txId);
|
|
273
|
+
this.doubleSpendWatchdogSwaps.add(swap);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if(tx.confirmation_count > 0) {
|
|
277
|
+
this.swapLogger.debug(swap, "processPastSwap(): Removing confirmed swap transaction from double spend watchdog list: ", swap.txId);
|
|
278
|
+
this.doubleSpendWatchdogSwaps.delete(swap);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if(swap.state===FromBtcTrustedSwapState.BTC_CONFIRMED) {
|
|
282
|
+
//Send gas token
|
|
283
|
+
const balance: Promise<BN> = swapContract.getBalance(signer.getAddress(), swapContract.getNativeCurrencyAddress(), false);
|
|
284
|
+
try {
|
|
285
|
+
await this.checkBalance(swap.adjustedOutput, balance, null);
|
|
286
|
+
if(swap.metadata!=null) swap.metadata.times.receivedBalanceChecked = Date.now();
|
|
287
|
+
} catch (e) {
|
|
288
|
+
this.swapLogger.error(swap, "processPastSwap(): Error not enough balance: ", e);
|
|
289
|
+
await this.refundSwap(swap);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if(swap.state!==FromBtcTrustedSwapState.BTC_CONFIRMED) return;
|
|
294
|
+
|
|
295
|
+
let unlock = swap.lock(30*1000);
|
|
296
|
+
if(unlock==null) return;
|
|
297
|
+
|
|
298
|
+
const txns = await swapContract.txsTransfer(signer.getAddress(), swapContract.getNativeCurrencyAddress(), swap.adjustedOutput, swap.dstAddress);
|
|
299
|
+
await swapContract.sendAndConfirm(signer, txns, true, null, false, async (txId: string, rawTx: string) => {
|
|
300
|
+
swap.txIds = {init: txId};
|
|
301
|
+
swap.scRawTx = rawTx;
|
|
302
|
+
if(swap.state===FromBtcTrustedSwapState.BTC_CONFIRMED) {
|
|
303
|
+
await swap.setState(FromBtcTrustedSwapState.SENT);
|
|
304
|
+
await this.storageManager.saveData(swap.getHash(), null, swap);
|
|
305
|
+
}
|
|
306
|
+
if(unlock!=null) unlock();
|
|
307
|
+
unlock = null;
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if(swap.state===FromBtcTrustedSwapState.SENT) {
|
|
312
|
+
const txStatus = await swapContract.getTxStatus(swap.scRawTx);
|
|
313
|
+
switch(txStatus) {
|
|
314
|
+
case "not_found":
|
|
315
|
+
//Retry
|
|
316
|
+
swap.txIds = {init: null};
|
|
317
|
+
swap.scRawTx = null;
|
|
318
|
+
await swap.setState(FromBtcTrustedSwapState.RECEIVED);
|
|
319
|
+
await this.storageManager.saveData(swap.getHash(), null, swap);
|
|
320
|
+
break;
|
|
321
|
+
case "reverted":
|
|
322
|
+
//Cancel invoice
|
|
323
|
+
await this.refundSwap(swap);
|
|
324
|
+
this.swapLogger.info(swap, "processPastSwap(): transaction reverted, refunding btc on-chain: ", swap.btcAddress);
|
|
325
|
+
break;
|
|
326
|
+
case "success":
|
|
327
|
+
await swap.setState(FromBtcTrustedSwapState.CONFIRMED);
|
|
328
|
+
await this.storageManager.saveData(swap.getHash(), null, swap);
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if(swap.state===FromBtcTrustedSwapState.CONFIRMED) {
|
|
334
|
+
this.processedTxIds.set(swap.getHash(), {
|
|
335
|
+
txId: swap.txIds.init,
|
|
336
|
+
adjustedAmount: swap.adjustedInput,
|
|
337
|
+
adjustedTotal: swap.adjustedOutput
|
|
338
|
+
});
|
|
339
|
+
if(tx.confirmation_count>0) await this.removeSwapData(swap, FromBtcTrustedSwapState.FINISHED);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
protected async processPastSwaps(): Promise<void> {
|
|
344
|
+
const queriedData = await this.storageManager.query([
|
|
345
|
+
{
|
|
346
|
+
key: "state",
|
|
347
|
+
value: [
|
|
348
|
+
FromBtcTrustedSwapState.CREATED,
|
|
349
|
+
FromBtcTrustedSwapState.RECEIVED,
|
|
350
|
+
FromBtcTrustedSwapState.BTC_CONFIRMED,
|
|
351
|
+
FromBtcTrustedSwapState.SENT,
|
|
352
|
+
FromBtcTrustedSwapState.CONFIRMED
|
|
353
|
+
]
|
|
354
|
+
}
|
|
355
|
+
]);
|
|
356
|
+
|
|
357
|
+
const startingBlockheight = queriedData.reduce((prev, swap) => Math.min(prev, swap.createdHeight), Infinity);
|
|
358
|
+
if(startingBlockheight===Infinity) return;
|
|
359
|
+
const {transactions} = await getChainTransactions({lnd: this.LND, after: startingBlockheight});
|
|
360
|
+
|
|
361
|
+
for(let swap of queriedData) {
|
|
362
|
+
const tx = transactions.find(tx => tx.output_addresses.includes(swap.btcAddress));
|
|
363
|
+
await this.processPastSwap(swap, tx);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private isValidBitcoinAddress(address: string) {
|
|
368
|
+
try {
|
|
369
|
+
bitcoin.address.toOutputScript(address, this.config.bitcoinNetwork);
|
|
370
|
+
return true;
|
|
371
|
+
} catch (e) {}
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
startRestServer(restServer: Express): void {
|
|
376
|
+
|
|
377
|
+
const getAddress = expressHandlerWrapper(async (req: Request & {paramReader: IParamReader}, res: Response & {responseStream: ServerParamEncoder}) => {
|
|
378
|
+
const metadata: {
|
|
379
|
+
request: any,
|
|
380
|
+
invoiceRequest?: any,
|
|
381
|
+
invoiceResponse?: any,
|
|
382
|
+
times: {[key: string]: number}
|
|
383
|
+
} = {request: {}, times: {}};
|
|
384
|
+
|
|
385
|
+
const chainIdentifier = req.query.chain as string ?? this.chains.default;
|
|
386
|
+
const {swapContract, signer} = this.getChain(chainIdentifier);
|
|
387
|
+
|
|
388
|
+
metadata.times.requestReceived = Date.now();
|
|
389
|
+
/**
|
|
390
|
+
* address: string solana address of the recipient
|
|
391
|
+
* refundAddress: string bitcoin address to use in case of refund
|
|
392
|
+
* amount: string amount (in lamports/smart chain base units) of the invoice
|
|
393
|
+
* exactOut: boolean whether to create and exact output swap
|
|
394
|
+
*/
|
|
395
|
+
|
|
396
|
+
const parsedBody: FromBtcTrustedRequestType = await req.paramReader.getParams({
|
|
397
|
+
address: (val: string) => val!=null &&
|
|
398
|
+
typeof(val)==="string" &&
|
|
399
|
+
swapContract.isValidAddress(val) ? val : null,
|
|
400
|
+
refundAddress: (val: string) => val!=null &&
|
|
401
|
+
typeof(val)==="string" &&
|
|
402
|
+
this.isValidBitcoinAddress(val) ? val : null,
|
|
403
|
+
amount: FieldTypeEnum.BN,
|
|
404
|
+
exactOut: FieldTypeEnum.BooleanOptional
|
|
405
|
+
});
|
|
406
|
+
if(parsedBody==null) throw {
|
|
407
|
+
code: 20100,
|
|
408
|
+
msg: "Invalid request body"
|
|
409
|
+
};
|
|
410
|
+
metadata.request = parsedBody;
|
|
411
|
+
|
|
412
|
+
const requestedAmount = {input: !parsedBody.exactOut, amount: parsedBody.amount};
|
|
413
|
+
const request = {
|
|
414
|
+
chainIdentifier,
|
|
415
|
+
raw: req,
|
|
416
|
+
parsed: parsedBody,
|
|
417
|
+
metadata
|
|
418
|
+
};
|
|
419
|
+
const useToken = swapContract.getNativeCurrencyAddress();
|
|
420
|
+
|
|
421
|
+
//Check request params
|
|
422
|
+
const fees = await this.preCheckAmounts(request, requestedAmount, useToken);
|
|
423
|
+
metadata.times.requestChecked = Date.now();
|
|
424
|
+
|
|
425
|
+
//Create abortController for parallel prefetches
|
|
426
|
+
const responseStream = res.responseStream;
|
|
427
|
+
const abortController = this.getAbortController(responseStream);
|
|
428
|
+
|
|
429
|
+
//Pre-fetch data
|
|
430
|
+
const {pricePrefetchPromise} = this.getFromBtcPricePrefetches(chainIdentifier, useToken, abortController);
|
|
431
|
+
const balancePrefetch = swapContract.getBalance(signer.getAddress(), useToken, false).catch(e => {
|
|
432
|
+
this.logger.error("getBalancePrefetch(): balancePrefetch error: ", e);
|
|
433
|
+
abortController.abort(e);
|
|
434
|
+
return null;
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
//Check valid amount specified (min/max)
|
|
438
|
+
const {
|
|
439
|
+
amountBD,
|
|
440
|
+
swapFee,
|
|
441
|
+
swapFeeInToken,
|
|
442
|
+
totalInToken
|
|
443
|
+
} = await this.checkFromBtcAmount(request, requestedAmount, fees, useToken, abortController.signal, pricePrefetchPromise);
|
|
444
|
+
metadata.times.priceCalculated = Date.now();
|
|
445
|
+
|
|
446
|
+
//Check if we have enough funds to honor the request
|
|
447
|
+
await this.checkBalance(totalInToken, balancePrefetch, abortController.signal)
|
|
448
|
+
metadata.times.balanceChecked = Date.now();
|
|
449
|
+
|
|
450
|
+
const {address: receiveAddress} = await createChainAddress({
|
|
451
|
+
lnd: this.LND,
|
|
452
|
+
format: "p2wpkh"
|
|
453
|
+
});
|
|
454
|
+
abortController.signal.throwIfAborted();
|
|
455
|
+
metadata.times.addressCreated = Date.now();
|
|
456
|
+
|
|
457
|
+
const {current_block_height} = await getHeight({lnd: this.LND});
|
|
458
|
+
const feeRate = await this.config.feeEstimator.estimateFee();
|
|
459
|
+
const recommendedFee = Math.ceil(feeRate*this.config.recommendFeeMultiplier);
|
|
460
|
+
|
|
461
|
+
const createdSwap = new FromBtcTrustedSwap(
|
|
462
|
+
chainIdentifier,
|
|
463
|
+
swapFee,
|
|
464
|
+
swapFeeInToken,
|
|
465
|
+
receiveAddress,
|
|
466
|
+
amountBD,
|
|
467
|
+
parsedBody.address,
|
|
468
|
+
totalInToken,
|
|
469
|
+
current_block_height,
|
|
470
|
+
Date.now()+(this.config.swapAddressExpiry*1000),
|
|
471
|
+
recommendedFee,
|
|
472
|
+
parsedBody.refundAddress
|
|
473
|
+
);
|
|
474
|
+
metadata.times.swapCreated = Date.now();
|
|
475
|
+
createdSwap.metadata = metadata;
|
|
476
|
+
|
|
477
|
+
await PluginManager.swapCreate(createdSwap);
|
|
478
|
+
await this.storageManager.saveData(createdSwap.getHash(), null, createdSwap);
|
|
479
|
+
this.subscriptions.set(createdSwap.btcAddress, createdSwap);
|
|
480
|
+
|
|
481
|
+
this.swapLogger.info(createdSwap, "REST: /getAddress: Created swap address: "+createdSwap.btcAddress+" amount: "+amountBD.toString(10));
|
|
482
|
+
|
|
483
|
+
await responseStream.writeParamsAndEnd({
|
|
484
|
+
msg: "Success",
|
|
485
|
+
code: 10000,
|
|
486
|
+
data: {
|
|
487
|
+
paymentHash: createdSwap.getHash(),
|
|
488
|
+
btcAddress: receiveAddress,
|
|
489
|
+
amountSats: amountBD.toString(10),
|
|
490
|
+
swapFeeSats: swapFee.toString(10),
|
|
491
|
+
swapFee: swapFeeInToken.toString(10),
|
|
492
|
+
total: totalInToken.toString(10),
|
|
493
|
+
intermediaryKey: signer.getAddress(),
|
|
494
|
+
recommendedFee,
|
|
495
|
+
expiresAt: createdSwap.expiresAt
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
restServer.use(this.path+"/getAddress", serverParamDecoder(10*1000));
|
|
501
|
+
restServer.post(this.path+"/getAddress", getAddress);
|
|
502
|
+
|
|
503
|
+
const getInvoiceStatus = expressHandlerWrapper(async (req, res) => {
|
|
504
|
+
/**
|
|
505
|
+
* paymentHash: string payment hash of the invoice
|
|
506
|
+
*/
|
|
507
|
+
const parsedBody = verifySchema(req.query, {
|
|
508
|
+
paymentHash: (val: string) => val!=null &&
|
|
509
|
+
typeof(val)==="string" &&
|
|
510
|
+
val.length===64 &&
|
|
511
|
+
HEX_REGEX.test(val) ? val: null,
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
const processedTxData = this.processedTxIds.get(parsedBody.paymentHash);
|
|
515
|
+
if(processedTxData!=null) throw {
|
|
516
|
+
_httpStatus: 200,
|
|
517
|
+
code: 10000,
|
|
518
|
+
msg: "Success, tx confirmed",
|
|
519
|
+
data: processedTxData
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
const refundTxId = this.refundedSwaps.get(parsedBody.paymentHash);
|
|
523
|
+
if(refundTxId!=null) throw {
|
|
524
|
+
_httpStatus: 200,
|
|
525
|
+
code: 10014,
|
|
526
|
+
msg: "Refunded",
|
|
527
|
+
data: {
|
|
528
|
+
txId: refundTxId
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
const doubleSpendTxId = this.doubleSpentSwaps.get(parsedBody.paymentHash);
|
|
533
|
+
if(doubleSpendTxId!=null) throw {
|
|
534
|
+
_httpStatus: 200,
|
|
535
|
+
code: 10015,
|
|
536
|
+
msg: "Double spend detected, deposit burned",
|
|
537
|
+
data: {
|
|
538
|
+
txId: doubleSpendTxId
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
const invoiceData: FromBtcTrustedSwap = await this.storageManager.getData(parsedBody.paymentHash, null);
|
|
543
|
+
if (invoiceData==null) throw {
|
|
544
|
+
_httpStatus: 200,
|
|
545
|
+
code: 10001,
|
|
546
|
+
msg: "Swap expired/canceled"
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
if (invoiceData.state === FromBtcTrustedSwapState.CREATED) throw {
|
|
550
|
+
_httpStatus: 200,
|
|
551
|
+
code: 10010,
|
|
552
|
+
msg: "Bitcoin yet unpaid"
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
if (invoiceData.state === FromBtcTrustedSwapState.RECEIVED) throw {
|
|
556
|
+
_httpStatus: 200,
|
|
557
|
+
code: 10011,
|
|
558
|
+
msg: "Bitcoin received, payment processing",
|
|
559
|
+
data: {
|
|
560
|
+
adjustedAmount: invoiceData.adjustedInput.toString(10),
|
|
561
|
+
adjustedTotal: invoiceData.adjustedOutput.toString(10)
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
if (invoiceData.state === FromBtcTrustedSwapState.BTC_CONFIRMED) throw {
|
|
566
|
+
_httpStatus: 200,
|
|
567
|
+
code: 10013,
|
|
568
|
+
msg: "Bitcoin accepted, payment processing",
|
|
569
|
+
data: {
|
|
570
|
+
adjustedAmount: invoiceData.adjustedInput.toString(10),
|
|
571
|
+
adjustedTotal: invoiceData.adjustedOutput.toString(10)
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
if (invoiceData.state === FromBtcTrustedSwapState.SENT) throw {
|
|
576
|
+
_httpStatus: 200,
|
|
577
|
+
code: 10012,
|
|
578
|
+
msg: "Tx sent",
|
|
579
|
+
data: {
|
|
580
|
+
adjustedAmount: invoiceData.adjustedInput.toString(10),
|
|
581
|
+
adjustedTotal: invoiceData.adjustedOutput.toString(10),
|
|
582
|
+
txId: invoiceData.txIds.init
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
if (invoiceData.state === FromBtcTrustedSwapState.CONFIRMED || invoiceData.state === FromBtcTrustedSwapState.FINISHED) throw {
|
|
587
|
+
_httpStatus: 200,
|
|
588
|
+
code: 10000,
|
|
589
|
+
msg: "Success, tx confirmed",
|
|
590
|
+
data: {
|
|
591
|
+
adjustedAmount: invoiceData.adjustedInput.toString(10),
|
|
592
|
+
adjustedTotal: invoiceData.adjustedOutput.toString(10),
|
|
593
|
+
txId: invoiceData.txIds.init
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
restServer.get(this.path+"/getAddressStatus", getInvoiceStatus);
|
|
599
|
+
|
|
600
|
+
this.logger.info("started at path: ", this.path);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
private async checkDoubleSpends(): Promise<void> {
|
|
604
|
+
for(let swap of this.doubleSpendWatchdogSwaps.keys()) {
|
|
605
|
+
const tx = await this.bitcoinRpc.getTransaction(swap.txId);
|
|
606
|
+
if(tx==null) {
|
|
607
|
+
this.swapLogger.debug(swap, "checkDoubleSpends(): Swap was double spent, burning... - original txId: "+swap.txId);
|
|
608
|
+
this.processPastSwap(swap, null);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
private async startDoubleSpendWatchdog() {
|
|
614
|
+
let rerun: () => Promise<void>;
|
|
615
|
+
rerun = async () => {
|
|
616
|
+
await this.checkDoubleSpends().catch( e => console.error(e));
|
|
617
|
+
setTimeout(rerun, this.config.doubleSpendCheckInterval);
|
|
618
|
+
};
|
|
619
|
+
await rerun();
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
private listenToTxns() {
|
|
623
|
+
const res = subscribeToTransactions({lnd: this.LND});
|
|
624
|
+
res.on("chain_transaction", (tx: SubscribeToTransactionsChainTransactionEvent) => {
|
|
625
|
+
for(let address of tx.output_addresses) {
|
|
626
|
+
const savedSwap = this.subscriptions.get(address);
|
|
627
|
+
if(savedSwap==null) continue;
|
|
628
|
+
this.processPastSwap(savedSwap, tx);
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
async startWatchdog() {
|
|
635
|
+
await super.startWatchdog();
|
|
636
|
+
await this.startDoubleSpendWatchdog();
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
async init(): Promise<void> {
|
|
640
|
+
await this.storageManager.loadData(FromBtcTrustedSwap);
|
|
641
|
+
this.listenToTxns();
|
|
642
|
+
await PluginManager.serviceInitialize(this);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
getInfoData(): any {
|
|
646
|
+
return {};
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
protected processClaimEvent(chainIdentifier: string, event: ClaimEvent<SwapData>): Promise<void> {
|
|
650
|
+
return Promise.resolve(undefined);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
protected processInitializeEvent(chainIdentifier: string, event: InitializeEvent<SwapData>): Promise<void> {
|
|
654
|
+
return Promise.resolve(undefined);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
protected processRefundEvent(chainIdentifier: string, event: RefundEvent<SwapData>): Promise<void> {
|
|
658
|
+
return Promise.resolve(undefined);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
}
|