@atomiqlabs/chain-evm 2.0.9 → 2.1.10
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/chains/alpen/AlpenInitializer.d.ts +2 -1
- package/dist/chains/alpen/AlpenInitializer.js +4 -1
- package/dist/chains/botanix/BotanixInitializer.d.ts +2 -1
- package/dist/chains/botanix/BotanixInitializer.js +3 -1
- package/dist/chains/citrea/CitreaInitializer.d.ts +2 -1
- package/dist/chains/citrea/CitreaInitializer.js +3 -1
- package/dist/chains/goat/GoatInitializer.d.ts +2 -1
- package/dist/chains/goat/GoatInitializer.js +4 -1
- package/dist/evm/contract/modules/EVMContractEvents.js +7 -1
- package/dist/evm/events/EVMChainEventsBrowser.d.ts +0 -3
- package/dist/evm/events/EVMChainEventsBrowser.js +1 -27
- package/dist/evm/spv_swap/EVMSpvVaultContract.d.ts +7 -1
- package/dist/evm/spv_swap/EVMSpvVaultContract.js +35 -6
- package/dist/evm/swaps/EVMSwapContract.d.ts +19 -2
- package/dist/evm/swaps/EVMSwapContract.js +117 -2
- package/package.json +2 -2
- package/src/chains/alpen/AlpenInitializer.ts +7 -2
- package/src/chains/botanix/BotanixInitializer.ts +6 -2
- package/src/chains/citrea/CitreaInitializer.ts +6 -2
- package/src/chains/goat/GoatInitializer.ts +7 -2
- package/src/evm/contract/modules/EVMContractEvents.ts +11 -3
- package/src/evm/events/EVMChainEventsBrowser.ts +1 -28
- package/src/evm/spv_swap/EVMSpvVaultContract.ts +51 -7
- package/src/evm/swaps/EVMSwapContract.ts +175 -4
|
@@ -22,6 +22,7 @@ export type AlpenOptions = {
|
|
|
22
22
|
retryPolicy?: EVMRetryPolicy;
|
|
23
23
|
chainType?: "MAINNET" | "TESTNET" | "TESTNET4";
|
|
24
24
|
swapContract?: string;
|
|
25
|
+
swapContractDeploymentHeight?: number;
|
|
25
26
|
btcRelayContract?: string;
|
|
26
27
|
btcRelayDeploymentHeight?: number;
|
|
27
28
|
spvVaultContract?: string;
|
|
@@ -35,7 +36,7 @@ export type AlpenOptions = {
|
|
|
35
36
|
};
|
|
36
37
|
};
|
|
37
38
|
fees?: EVMFees;
|
|
38
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
39
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>;
|
|
39
40
|
};
|
|
40
41
|
/**
|
|
41
42
|
* Initialize Alpen chain integration
|
|
@@ -21,6 +21,7 @@ const AlpenContractAddresses = {
|
|
|
21
21
|
MAINNET: {
|
|
22
22
|
executionContract: "",
|
|
23
23
|
swapContract: "",
|
|
24
|
+
swapContractDeploymentHeight: 0,
|
|
24
25
|
btcRelayContract: "",
|
|
25
26
|
btcRelayDeploymentHeight: 0,
|
|
26
27
|
spvVaultContract: "",
|
|
@@ -40,6 +41,7 @@ const AlpenContractAddresses = {
|
|
|
40
41
|
TESTNET: {
|
|
41
42
|
executionContract: "0x32EB4DbDdC31e19ba908fecc7cae03F0d04F01Fa",
|
|
42
43
|
swapContract: "0x2920EE496693A5027249a027A6FD3F643E743745",
|
|
44
|
+
swapContractDeploymentHeight: 532614,
|
|
43
45
|
btcRelayContract: "0x59A54378B6bA9C21ba66487C6A701D702baDEabE",
|
|
44
46
|
btcRelayDeploymentHeight: 532610,
|
|
45
47
|
spvVaultContract: "0xaB2D14745362B26a732dD8B7F95daAE3D2914bBF",
|
|
@@ -59,6 +61,7 @@ const AlpenContractAddresses = {
|
|
|
59
61
|
TESTNET4: {
|
|
60
62
|
executionContract: "0xa2698D2fBE3f7c74cCca428a5fd968411644C641",
|
|
61
63
|
swapContract: "0xb0226bAC3BD30179fb66A43cEA212AbBC988e004",
|
|
64
|
+
swapContractDeploymentHeight: 843614,
|
|
62
65
|
btcRelayContract: "0xfFA842529977a40A3fdb988cdDC9CB5c39bAcF26",
|
|
63
66
|
btcRelayDeploymentHeight: 843611,
|
|
64
67
|
spvVaultContract: "0x62a718348081F9CF9a8E3dF4B4EA6d6349991ad9",
|
|
@@ -128,7 +131,7 @@ function initializeAlpen(options, bitcoinRpc, network) {
|
|
|
128
131
|
...defaultContractAddresses.handlerContracts.claim,
|
|
129
132
|
...options?.handlerContracts?.claim
|
|
130
133
|
}
|
|
131
|
-
});
|
|
134
|
+
}, options.swapContractDeploymentHeight ?? defaultContractAddresses.swapContractDeploymentHeight);
|
|
132
135
|
const spvVaultContract = new EVMSpvVaultContract_1.EVMSpvVaultContract(chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract ?? defaultContractAddresses.spvVaultContract, options.spvVaultDeploymentHeight ?? defaultContractAddresses.spvVaultDeploymentHeight);
|
|
133
136
|
const chainEvents = new EVMChainEventsBrowser_1.EVMChainEventsBrowser(chainInterface, swapContract, spvVaultContract);
|
|
134
137
|
return {
|
|
@@ -22,6 +22,7 @@ export type BotanixOptions = {
|
|
|
22
22
|
retryPolicy?: EVMRetryPolicy;
|
|
23
23
|
chainType?: "MAINNET" | "TESTNET";
|
|
24
24
|
swapContract?: string;
|
|
25
|
+
swapContractDeploymentHeight?: number;
|
|
25
26
|
btcRelayContract?: string;
|
|
26
27
|
btcRelayDeploymentHeight?: number;
|
|
27
28
|
spvVaultContract?: string;
|
|
@@ -35,7 +36,7 @@ export type BotanixOptions = {
|
|
|
35
36
|
};
|
|
36
37
|
};
|
|
37
38
|
fees?: EVMFees;
|
|
38
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
39
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>;
|
|
39
40
|
};
|
|
40
41
|
/**
|
|
41
42
|
* Initialize Botanix chain integration
|
|
@@ -20,6 +20,7 @@ const BotanixContractAddresses = {
|
|
|
20
20
|
MAINNET: {
|
|
21
21
|
executionContract: "0x71Bc44F3F7203fC1279107D924e418F02b0d4029",
|
|
22
22
|
swapContract: "0x9a027B5Bf43382Cc4A5134d9EFD389f61ece27B9",
|
|
23
|
+
swapContractDeploymentHeight: 2320403,
|
|
23
24
|
btcRelayContract: "0xe8be24CF21341c9567664009a8a82C9Dc1eE90D6",
|
|
24
25
|
btcRelayDeploymentHeight: 2320400,
|
|
25
26
|
spvVaultContract: "0xe510D5781C6C849284Fb25Dc20b1684cEC445C8B",
|
|
@@ -39,6 +40,7 @@ const BotanixContractAddresses = {
|
|
|
39
40
|
TESTNET: {
|
|
40
41
|
executionContract: "0xe510D5781C6C849284Fb25Dc20b1684cEC445C8B",
|
|
41
42
|
swapContract: "0xfFA842529977a40A3fdb988cdDC9CB5c39bAcF26",
|
|
43
|
+
swapContractDeploymentHeight: 4173454,
|
|
42
44
|
btcRelayContract: "0xba7E78011909e3501027FBc226a04DCC837a555D",
|
|
43
45
|
btcRelayDeploymentHeight: 3462466,
|
|
44
46
|
spvVaultContract: "0x9a027B5Bf43382Cc4A5134d9EFD389f61ece27B9",
|
|
@@ -111,7 +113,7 @@ function initializeBotanix(options, bitcoinRpc, network) {
|
|
|
111
113
|
...defaultContractAddresses.handlerContracts.claim,
|
|
112
114
|
...options?.handlerContracts?.claim
|
|
113
115
|
}
|
|
114
|
-
});
|
|
116
|
+
}, options.swapContractDeploymentHeight ?? defaultContractAddresses.swapContractDeploymentHeight);
|
|
115
117
|
const spvVaultContract = new EVMSpvVaultContract_1.EVMSpvVaultContract(chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract ?? defaultContractAddresses.spvVaultContract, options.spvVaultDeploymentHeight ?? defaultContractAddresses.spvVaultDeploymentHeight);
|
|
116
118
|
const chainEvents = new EVMChainEventsBrowser_1.EVMChainEventsBrowser(chainInterface, swapContract, spvVaultContract);
|
|
117
119
|
return {
|
|
@@ -22,6 +22,7 @@ export type CitreaOptions = {
|
|
|
22
22
|
retryPolicy?: EVMRetryPolicy;
|
|
23
23
|
chainType?: "MAINNET" | "TESTNET4";
|
|
24
24
|
swapContract?: string;
|
|
25
|
+
swapContractDeploymentHeight?: number;
|
|
25
26
|
btcRelayContract?: string;
|
|
26
27
|
btcRelayDeploymentHeight?: number;
|
|
27
28
|
spvVaultContract?: string;
|
|
@@ -35,7 +36,7 @@ export type CitreaOptions = {
|
|
|
35
36
|
};
|
|
36
37
|
};
|
|
37
38
|
fees?: CitreaFees;
|
|
38
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
39
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>;
|
|
39
40
|
};
|
|
40
41
|
/**
|
|
41
42
|
* Initialize Citrea chain integration
|
|
@@ -21,6 +21,7 @@ const CitreaContractAddresses = {
|
|
|
21
21
|
MAINNET: {
|
|
22
22
|
executionContract: "0x6a373b6Adad83964727bA0fa15E22Be05173fc12",
|
|
23
23
|
swapContract: "0xc98Ef084d3911C8447DBbE4dDa18bC2c9bB0584e",
|
|
24
|
+
swapContractDeploymentHeight: 2452632,
|
|
24
25
|
btcRelayContract: "0x11ac854A68830d61af975063c91602f878C36fA6",
|
|
25
26
|
btcRelayDeploymentHeight: 2452629,
|
|
26
27
|
spvVaultContract: "0x5bb0C725939cB825d1322A99a3FeB570097628c3",
|
|
@@ -40,6 +41,7 @@ const CitreaContractAddresses = {
|
|
|
40
41
|
TESTNET4: {
|
|
41
42
|
executionContract: "0x9e289512965A0842b342A6BB3F3c41F22a555Cfe",
|
|
42
43
|
swapContract: "0xBbf7755b674dD107d59F0650D1A3fA9C60bf6Fe6",
|
|
44
|
+
swapContractDeploymentHeight: 12346224,
|
|
43
45
|
btcRelayContract: "0x00D122E9f9766cd81a38D2dd44f9AFfb94c67Af7",
|
|
44
46
|
btcRelayDeploymentHeight: 12346223,
|
|
45
47
|
spvVaultContract: "0x9Bf990C6088F716279797a602b05941c40591533",
|
|
@@ -121,7 +123,7 @@ function initializeCitrea(options, bitcoinRpc, network) {
|
|
|
121
123
|
...defaultContractAddresses.handlerContracts.claim,
|
|
122
124
|
...options?.handlerContracts?.claim
|
|
123
125
|
}
|
|
124
|
-
});
|
|
126
|
+
}, options.swapContractDeploymentHeight ?? defaultContractAddresses.swapContractDeploymentHeight);
|
|
125
127
|
const spvVaultContract = new CitreaSpvVaultContract_1.CitreaSpvVaultContract(chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract ?? defaultContractAddresses.spvVaultContract, options.spvVaultDeploymentHeight ?? defaultContractAddresses.spvVaultDeploymentHeight);
|
|
126
128
|
const chainEvents = new EVMChainEventsBrowser_1.EVMChainEventsBrowser(chainInterface, swapContract, spvVaultContract);
|
|
127
129
|
return {
|
|
@@ -22,6 +22,7 @@ export type GoatOptions = {
|
|
|
22
22
|
retryPolicy?: EVMRetryPolicy;
|
|
23
23
|
chainType?: "MAINNET" | "TESTNET" | "TESTNET4";
|
|
24
24
|
swapContract?: string;
|
|
25
|
+
swapContractDeploymentHeight?: number;
|
|
25
26
|
btcRelayContract?: string;
|
|
26
27
|
btcRelayDeploymentHeight?: number;
|
|
27
28
|
spvVaultContract?: string;
|
|
@@ -35,7 +36,7 @@ export type GoatOptions = {
|
|
|
35
36
|
};
|
|
36
37
|
};
|
|
37
38
|
fees?: EVMFees;
|
|
38
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
39
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>;
|
|
39
40
|
};
|
|
40
41
|
/**
|
|
41
42
|
* Initialize GOAT Network chain integration
|
|
@@ -21,6 +21,7 @@ const GoatContractAddresses = {
|
|
|
21
21
|
MAINNET: {
|
|
22
22
|
executionContract: "",
|
|
23
23
|
swapContract: "",
|
|
24
|
+
swapContractDeploymentHeight: 0,
|
|
24
25
|
btcRelayContract: "",
|
|
25
26
|
btcRelayDeploymentHeight: 0,
|
|
26
27
|
spvVaultContract: "",
|
|
@@ -40,6 +41,7 @@ const GoatContractAddresses = {
|
|
|
40
41
|
TESTNET: {
|
|
41
42
|
executionContract: "0xe8be24CF21341c9567664009a8a82C9Dc1eE90D6",
|
|
42
43
|
swapContract: "0xe510D5781C6C849284Fb25Dc20b1684cEC445C8B",
|
|
44
|
+
swapContractDeploymentHeight: 9368978,
|
|
43
45
|
btcRelayContract: "0x3887B02217726bB36958Dd595e57293fB63D5082",
|
|
44
46
|
btcRelayDeploymentHeight: 9368975,
|
|
45
47
|
spvVaultContract: "0x71Bc44F3F7203fC1279107D924e418F02b0d4029",
|
|
@@ -59,6 +61,7 @@ const GoatContractAddresses = {
|
|
|
59
61
|
TESTNET4: {
|
|
60
62
|
executionContract: "0x4f7d86C870F28ac30C8fa864Ee04264D7dD03847",
|
|
61
63
|
swapContract: "0x3FbbA0eb82cf1247cbf92B3D51641226310F0Ca5",
|
|
64
|
+
swapContractDeploymentHeight: 10240371,
|
|
62
65
|
btcRelayContract: "0xEeD58871C24d24C49554aF8B65Dd86eD8ed778D3",
|
|
63
66
|
btcRelayDeploymentHeight: 10240368,
|
|
64
67
|
spvVaultContract: "0x8a80A68f8bA1732015A821b5260fEF8040a844b7",
|
|
@@ -138,7 +141,7 @@ function initializeGoat(options, bitcoinRpc, network) {
|
|
|
138
141
|
...defaultContractAddresses.handlerContracts.claim,
|
|
139
142
|
...options?.handlerContracts?.claim
|
|
140
143
|
}
|
|
141
|
-
});
|
|
144
|
+
}, options.swapContractDeploymentHeight ?? defaultContractAddresses.swapContractDeploymentHeight);
|
|
142
145
|
const spvVaultContract = new EVMSpvVaultContract_1.EVMSpvVaultContract(chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract ?? defaultContractAddresses.spvVaultContract, options.spvVaultDeploymentHeight ?? defaultContractAddresses.spvVaultDeploymentHeight);
|
|
143
146
|
const chainEvents = new EVMChainEventsBrowser_1.EVMChainEventsBrowser(chainInterface, swapContract, spvVaultContract);
|
|
144
147
|
return {
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EVMContractEvents = void 0;
|
|
4
4
|
const EVMEvents_1 = require("../../chain/modules/EVMEvents");
|
|
5
|
+
function normalizeTopic(topic) {
|
|
6
|
+
if (topic.length !== 66) {
|
|
7
|
+
return "0x" + topic.substring(2).padStart(64, "0");
|
|
8
|
+
}
|
|
9
|
+
return topic;
|
|
10
|
+
}
|
|
5
11
|
class EVMContractEvents extends EVMEvents_1.EVMEvents {
|
|
6
12
|
constructor(chainInterface, contract) {
|
|
7
13
|
super(chainInterface);
|
|
@@ -17,7 +23,7 @@ class EVMContractEvents extends EVMEvents_1.EVMEvents {
|
|
|
17
23
|
return this.baseContract.getEvent(name).fragment.topicHash;
|
|
18
24
|
}));
|
|
19
25
|
if (keys != null)
|
|
20
|
-
keys.forEach(key => filterArray.push(key));
|
|
26
|
+
keys.forEach(key => filterArray.push(typeof (key) === "string" ? [normalizeTopic(key)] : Array.isArray(key) ? key.map(normalizeTopic) : key));
|
|
21
27
|
return filterArray;
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ChainEvents, ClaimEvent, EventListener, InitializeEvent, RefundEvent, SpvVaultClaimEvent, SpvVaultCloseEvent, SpvVaultDepositEvent, SpvVaultFrontEvent, SpvVaultOpenEvent } from "@atomiqlabs/base";
|
|
2
|
-
import { IClaimHandler } from "../swaps/handlers/claim/ClaimHandlers";
|
|
3
2
|
import { EVMSwapData } from "../swaps/EVMSwapData";
|
|
4
3
|
import { Block, JsonRpcApiProvider, EventFilter, Log } from "ethers";
|
|
5
4
|
import { EVMSwapContract } from "../swaps/EVMSwapContract";
|
|
@@ -8,7 +7,6 @@ import { EVMChainInterface } from "../chain/EVMChainInterface";
|
|
|
8
7
|
import { TypedEventLog } from "../typechain/common";
|
|
9
8
|
import { EscrowManager } from "../swaps/EscrowManagerTypechain";
|
|
10
9
|
import { SpvVaultManager } from "../spv_swap/SpvVaultContractTypechain";
|
|
11
|
-
import { EVMTxTrace } from "../chain/modules/EVMTransactions";
|
|
12
10
|
export type EVMEventListenerState = {
|
|
13
11
|
lastBlockNumber: number;
|
|
14
12
|
lastEvent?: {
|
|
@@ -45,7 +43,6 @@ export declare class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, E
|
|
|
45
43
|
constructor(chainInterface: EVMChainInterface, evmSwapContract: EVMSwapContract, evmSpvVaultContract: EVMSpvVaultContract<any>, pollIntervalSeconds?: number);
|
|
46
44
|
private addProcessedEvent;
|
|
47
45
|
private isEventProcessed;
|
|
48
|
-
findInitSwapData(call: EVMTxTrace, escrowHash: string, claimHandler: IClaimHandler<any, any>): EVMSwapData | null;
|
|
49
46
|
/**
|
|
50
47
|
* Returns async getter for fetching on-demand initialize event swap data
|
|
51
48
|
*
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EVMChainEventsBrowser = void 0;
|
|
4
4
|
const base_1 = require("@atomiqlabs/base");
|
|
5
|
-
const EVMSwapData_1 = require("../swaps/EVMSwapData");
|
|
6
|
-
const ethers_1 = require("ethers");
|
|
7
5
|
const Utils_1 = require("../../utils/Utils");
|
|
8
6
|
const EVMSpvVaultContract_1 = require("../spv_swap/EVMSpvVaultContract");
|
|
9
7
|
const LOGS_SLIDING_WINDOW_LENGTH = 60;
|
|
@@ -45,30 +43,6 @@ class EVMChainEventsBrowser {
|
|
|
45
43
|
isEventProcessed(event) {
|
|
46
44
|
return this.processedEvents.includes(event.transactionHash + ":" + event.index);
|
|
47
45
|
}
|
|
48
|
-
findInitSwapData(call, escrowHash, claimHandler) {
|
|
49
|
-
if (call.to.toLowerCase() === this.evmSwapContract.contractAddress.toLowerCase()) {
|
|
50
|
-
const _result = this.evmSwapContract.parseCalldata(call.input);
|
|
51
|
-
if (_result != null && _result.name === "initialize") {
|
|
52
|
-
const result = _result;
|
|
53
|
-
//Found, check correct escrow hash
|
|
54
|
-
const [escrowData, signature, timeout, extraData] = result.args;
|
|
55
|
-
const escrow = EVMSwapData_1.EVMSwapData.deserializeFromStruct(escrowData, claimHandler);
|
|
56
|
-
if ("0x" + escrow.getEscrowHash() === escrowHash) {
|
|
57
|
-
const extraDataHex = (0, ethers_1.hexlify)(extraData);
|
|
58
|
-
if (extraDataHex.length > 2) {
|
|
59
|
-
escrow.setExtraData(extraDataHex.substring(2));
|
|
60
|
-
}
|
|
61
|
-
return escrow;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
for (let _call of call.calls) {
|
|
66
|
-
const found = this.findInitSwapData(_call, escrowHash, claimHandler);
|
|
67
|
-
if (found != null)
|
|
68
|
-
return found;
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
46
|
/**
|
|
73
47
|
* Returns async getter for fetching on-demand initialize event swap data
|
|
74
48
|
*
|
|
@@ -82,7 +56,7 @@ class EVMChainEventsBrowser {
|
|
|
82
56
|
const trace = await this.chainInterface.Transactions.traceTransaction(event.transactionHash);
|
|
83
57
|
if (trace == null)
|
|
84
58
|
return null;
|
|
85
|
-
return this.findInitSwapData(trace, event.args.escrowHash, claimHandler);
|
|
59
|
+
return this.evmSwapContract.findInitSwapData(trace, event.args.escrowHash, claimHandler);
|
|
86
60
|
};
|
|
87
61
|
}
|
|
88
62
|
parseInitializeEvent(event) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
import { BitcoinRpc, BtcTx, RelaySynchronizer, SpvVaultContract, SpvVaultTokenData, SpvWithdrawalState, SpvWithdrawalTransactionData, TransactionConfirmationOptions } from "@atomiqlabs/base";
|
|
3
|
+
import { BitcoinRpc, BtcTx, RelaySynchronizer, SpvVaultContract, SpvVaultTokenData, SpvWithdrawalClaimedState, SpvWithdrawalFrontedState, SpvWithdrawalState, SpvWithdrawalTransactionData, TransactionConfirmationOptions } from "@atomiqlabs/base";
|
|
4
4
|
import { Buffer } from "buffer";
|
|
5
5
|
import { EVMTx } from "../chain/modules/EVMTransactions";
|
|
6
6
|
import { EVMContractBase } from "../contract/EVMContractBase";
|
|
@@ -112,6 +112,12 @@ export declare class EVMSpvVaultContract<ChainId extends string> extends EVMCont
|
|
|
112
112
|
}[]): Promise<{
|
|
113
113
|
[btcTxId: string]: SpvWithdrawalState;
|
|
114
114
|
}>;
|
|
115
|
+
getHistoricalWithdrawalStates(recipient: string, startBlockheight?: number): Promise<{
|
|
116
|
+
withdrawals: {
|
|
117
|
+
[btcTxId: string]: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState;
|
|
118
|
+
};
|
|
119
|
+
latestBlockheight?: number;
|
|
120
|
+
}>;
|
|
115
121
|
/**
|
|
116
122
|
* @inheritDoc
|
|
117
123
|
*/
|
|
@@ -264,32 +264,47 @@ class EVMSpvVaultContract extends EVMContractBase_1.EVMContractBase {
|
|
|
264
264
|
const [ownerFront, vaultIdFront] = unpackOwnerAndVaultId(frontedEvent.args.ownerAndVaultId);
|
|
265
265
|
return {
|
|
266
266
|
type: base_1.SpvWithdrawalStateType.FRONTED,
|
|
267
|
-
|
|
267
|
+
btcTxId: buffer_1.Buffer.from(frontedEvent.args.btcTxHash.substring(2), "hex").reverse().toString("hex"),
|
|
268
268
|
owner: ownerFront,
|
|
269
269
|
vaultId: vaultIdFront,
|
|
270
270
|
recipient: frontedEvent.args.recipient,
|
|
271
|
-
fronter: frontedEvent.args.caller
|
|
271
|
+
fronter: frontedEvent.args.caller,
|
|
272
|
+
txId: event.transactionHash,
|
|
273
|
+
getTxBlock: async () => ({
|
|
274
|
+
blockHeight: event.blockNumber,
|
|
275
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
276
|
+
})
|
|
272
277
|
};
|
|
273
278
|
case "Claimed":
|
|
274
279
|
const claimedEvent = event;
|
|
275
280
|
const [ownerClaim, vaultIdClaim] = unpackOwnerAndVaultId(claimedEvent.args.ownerAndVaultId);
|
|
276
281
|
return {
|
|
277
282
|
type: base_1.SpvWithdrawalStateType.CLAIMED,
|
|
278
|
-
|
|
283
|
+
btcTxId: buffer_1.Buffer.from(claimedEvent.args.btcTxHash.substring(2), "hex").reverse().toString("hex"),
|
|
279
284
|
owner: ownerClaim,
|
|
280
285
|
vaultId: vaultIdClaim,
|
|
281
286
|
recipient: claimedEvent.args.recipient,
|
|
282
287
|
claimer: claimedEvent.args.caller,
|
|
283
|
-
fronter: claimedEvent.args.frontingAddress
|
|
288
|
+
fronter: claimedEvent.args.frontingAddress,
|
|
289
|
+
txId: event.transactionHash,
|
|
290
|
+
getTxBlock: async () => ({
|
|
291
|
+
blockHeight: event.blockNumber,
|
|
292
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
293
|
+
})
|
|
284
294
|
};
|
|
285
295
|
case "Closed":
|
|
286
296
|
const closedEvent = event;
|
|
287
297
|
return {
|
|
288
298
|
type: base_1.SpvWithdrawalStateType.CLOSED,
|
|
289
|
-
|
|
299
|
+
btcTxId: buffer_1.Buffer.from(closedEvent.args.btcTxHash.substring(2), "hex").reverse().toString("hex"),
|
|
290
300
|
owner: closedEvent.args.owner,
|
|
291
301
|
vaultId: closedEvent.args.vaultId,
|
|
292
|
-
error: closedEvent.args.error
|
|
302
|
+
error: closedEvent.args.error,
|
|
303
|
+
txId: event.transactionHash,
|
|
304
|
+
getTxBlock: async () => ({
|
|
305
|
+
blockHeight: event.blockNumber,
|
|
306
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
307
|
+
})
|
|
293
308
|
};
|
|
294
309
|
default:
|
|
295
310
|
return null;
|
|
@@ -398,6 +413,20 @@ class EVMSpvVaultContract extends EVMContractBase_1.EVMContractBase {
|
|
|
398
413
|
}
|
|
399
414
|
return result;
|
|
400
415
|
}
|
|
416
|
+
async getHistoricalWithdrawalStates(recipient, startBlockheight) {
|
|
417
|
+
const { height: latestBlockheight } = await this.Chain.getFinalizedBlock();
|
|
418
|
+
const withdrawals = {};
|
|
419
|
+
await this.Events.findInContractEventsForward(["Claimed", "Fronted"], [null, recipient], async (_event) => {
|
|
420
|
+
const eventResult = this.parseWithdrawalEvent(_event);
|
|
421
|
+
if (eventResult == null || eventResult.type === base_1.SpvWithdrawalStateType.CLOSED)
|
|
422
|
+
return null;
|
|
423
|
+
withdrawals[eventResult.btcTxId] = eventResult;
|
|
424
|
+
}, startBlockheight);
|
|
425
|
+
return {
|
|
426
|
+
withdrawals,
|
|
427
|
+
latestBlockheight
|
|
428
|
+
};
|
|
429
|
+
}
|
|
401
430
|
/**
|
|
402
431
|
* @inheritDoc
|
|
403
432
|
*/
|
|
@@ -7,7 +7,7 @@ import { IHandler } from "./handlers/IHandler";
|
|
|
7
7
|
import { EVMContractBase } from "../contract/EVMContractBase";
|
|
8
8
|
import { EscrowManager } from "./EscrowManagerTypechain";
|
|
9
9
|
import { EVMSwapData } from "./EVMSwapData";
|
|
10
|
-
import { EVMTx } from "../chain/modules/EVMTransactions";
|
|
10
|
+
import { EVMTx, EVMTxTrace } from "../chain/modules/EVMTransactions";
|
|
11
11
|
import { EVMSigner } from "../wallet/EVMSigner";
|
|
12
12
|
import { EVMChainInterface } from "../chain/EVMChainInterface";
|
|
13
13
|
import { EVMBtcRelay } from "../btcrelay/EVMBtcRelay";
|
|
@@ -50,7 +50,7 @@ export declare class EVMSwapContract<ChainId extends string = string> extends EV
|
|
|
50
50
|
claim: {
|
|
51
51
|
[type in ChainSwapType]: string;
|
|
52
52
|
};
|
|
53
|
-
});
|
|
53
|
+
}, contractDeploymentHeight?: number);
|
|
54
54
|
/**
|
|
55
55
|
* @inheritDoc
|
|
56
56
|
*/
|
|
@@ -136,10 +136,27 @@ export declare class EVMSwapContract<ChainId extends string = string> extends EV
|
|
|
136
136
|
}[]): Promise<{
|
|
137
137
|
[p: string]: SwapCommitState;
|
|
138
138
|
}>;
|
|
139
|
+
getHistoricalSwaps(signer: string, startBlockheight?: number): Promise<{
|
|
140
|
+
swaps: {
|
|
141
|
+
[escrowHash: string]: {
|
|
142
|
+
init?: {
|
|
143
|
+
data: EVMSwapData;
|
|
144
|
+
getInitTxId: () => Promise<string>;
|
|
145
|
+
getTxBlock: () => Promise<{
|
|
146
|
+
blockTime: number;
|
|
147
|
+
blockHeight: number;
|
|
148
|
+
}>;
|
|
149
|
+
};
|
|
150
|
+
state: SwapCommitState;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
latestBlockheight?: number;
|
|
154
|
+
}>;
|
|
139
155
|
/**
|
|
140
156
|
* @inheritDoc
|
|
141
157
|
*/
|
|
142
158
|
createSwapData(type: ChainSwapType, offerer: string, claimer: string, token: string, amount: bigint, paymentHash: string, sequence: bigint, expiry: bigint, payIn: boolean, payOut: boolean, securityDeposit: bigint, claimerBounty: bigint, depositToken?: string): Promise<EVMSwapData>;
|
|
159
|
+
findInitSwapData(call: EVMTxTrace, escrowHash: string, claimHandler: IClaimHandler<any, any>): EVMSwapData | null;
|
|
143
160
|
/**
|
|
144
161
|
* @inheritDoc
|
|
145
162
|
*/
|
|
@@ -14,15 +14,17 @@ const EVMLpVault_1 = require("./modules/EVMLpVault");
|
|
|
14
14
|
const EVMSwapInit_1 = require("./modules/EVMSwapInit");
|
|
15
15
|
const EVMSwapRefund_1 = require("./modules/EVMSwapRefund");
|
|
16
16
|
const EVMSwapClaim_1 = require("./modules/EVMSwapClaim");
|
|
17
|
+
const Utils_1 = require("../../utils/Utils");
|
|
17
18
|
const ESCROW_STATE_COMMITTED = 1;
|
|
18
19
|
const ESCROW_STATE_CLAIMED = 2;
|
|
19
20
|
const ESCROW_STATE_REFUNDED = 3;
|
|
21
|
+
const logger = (0, Utils_1.getLogger)("EVMSwapContract: ");
|
|
20
22
|
/**
|
|
21
23
|
* @category Swaps
|
|
22
24
|
*/
|
|
23
25
|
class EVMSwapContract extends EVMContractBase_1.EVMContractBase {
|
|
24
|
-
constructor(chainInterface, btcRelay, contractAddress, handlerAddresses) {
|
|
25
|
-
super(chainInterface, contractAddress, EscrowManagerAbi_1.EscrowManagerAbi);
|
|
26
|
+
constructor(chainInterface, btcRelay, contractAddress, handlerAddresses, contractDeploymentHeight) {
|
|
27
|
+
super(chainInterface, contractAddress, EscrowManagerAbi_1.EscrowManagerAbi, contractDeploymentHeight);
|
|
26
28
|
this.supportsInitWithoutClaimer = true;
|
|
27
29
|
////////////////////////
|
|
28
30
|
//// Timeouts
|
|
@@ -299,6 +301,95 @@ class EVMSwapContract extends EVMContractBase_1.EVMContractBase {
|
|
|
299
301
|
await Promise.all(promises);
|
|
300
302
|
return result;
|
|
301
303
|
}
|
|
304
|
+
async getHistoricalSwaps(signer, startBlockheight) {
|
|
305
|
+
const { height: latestBlockheight } = await this.Chain.getFinalizedBlock();
|
|
306
|
+
const swapsOpened = {};
|
|
307
|
+
const resultingSwaps = {};
|
|
308
|
+
const processor = async (_event) => {
|
|
309
|
+
const escrowHash = _event.args.escrowHash.substring(2);
|
|
310
|
+
if (_event.eventName === "Initialize") {
|
|
311
|
+
const event = _event;
|
|
312
|
+
const claimHandlerHex = event.args.claimHandler;
|
|
313
|
+
const claimHandler = this.claimHandlersByAddress[claimHandlerHex.toLowerCase()];
|
|
314
|
+
if (claimHandler == null) {
|
|
315
|
+
logger.warn(`getHistoricalSwaps(): Unknown claim handler in tx ${event.transactionHash} with claim handler: ` + claimHandlerHex);
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
const txTrace = await this.Chain.Transactions.traceTransaction(event.transactionHash);
|
|
319
|
+
const data = this.findInitSwapData(txTrace, event.args.escrowHash, claimHandler);
|
|
320
|
+
if (data == null) {
|
|
321
|
+
logger.warn(`getHistoricalSwaps(): Cannot parse swap data from tx ${event.transactionHash} with escrow hash: ` + escrowHash);
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
swapsOpened[escrowHash] = {
|
|
325
|
+
data,
|
|
326
|
+
getInitTxId: () => Promise.resolve(event.transactionHash),
|
|
327
|
+
getTxBlock: async () => {
|
|
328
|
+
return {
|
|
329
|
+
blockHeight: event.blockNumber,
|
|
330
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
if (_event.eventName === "Claim") {
|
|
336
|
+
const event = _event;
|
|
337
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
338
|
+
delete swapsOpened[escrowHash];
|
|
339
|
+
resultingSwaps[escrowHash] = {
|
|
340
|
+
init: foundSwapData,
|
|
341
|
+
state: {
|
|
342
|
+
type: base_1.SwapCommitStateType.PAID,
|
|
343
|
+
getClaimTxId: () => Promise.resolve(event.transactionHash),
|
|
344
|
+
getClaimResult: () => Promise.resolve(event.args.witnessResult.substring(2)),
|
|
345
|
+
getTxBlock: async () => {
|
|
346
|
+
return {
|
|
347
|
+
blockHeight: event.blockNumber,
|
|
348
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
if (_event.eventName === "Refund") {
|
|
355
|
+
const event = _event;
|
|
356
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
357
|
+
delete swapsOpened[escrowHash];
|
|
358
|
+
const isExpired = foundSwapData != null && await this.isExpired(signer, foundSwapData.data);
|
|
359
|
+
resultingSwaps[escrowHash] = {
|
|
360
|
+
init: foundSwapData,
|
|
361
|
+
state: {
|
|
362
|
+
type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
|
|
363
|
+
getRefundTxId: () => Promise.resolve(event.transactionHash),
|
|
364
|
+
getTxBlock: async () => {
|
|
365
|
+
return {
|
|
366
|
+
blockHeight: event.blockNumber,
|
|
367
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
//We have to fetch separately the different directions
|
|
375
|
+
await this.Events.findInContractEventsForward(["Initialize", "Claim", "Refund"], [signer, null], processor, startBlockheight);
|
|
376
|
+
await this.Events.findInContractEventsForward(["Initialize", "Claim", "Refund"], [null, signer], processor, startBlockheight);
|
|
377
|
+
logger.debug(`getHistoricalSwaps(): Found ${Object.keys(resultingSwaps).length} settled swaps!`);
|
|
378
|
+
logger.debug(`getHistoricalSwaps(): Found ${Object.keys(swapsOpened).length} unsettled swaps!`);
|
|
379
|
+
for (let escrowHash in swapsOpened) {
|
|
380
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
381
|
+
resultingSwaps[escrowHash] = {
|
|
382
|
+
init: foundSwapData,
|
|
383
|
+
state: foundSwapData.data.isOfferer(signer) && await this.isExpired(signer, foundSwapData.data)
|
|
384
|
+
? { type: base_1.SwapCommitStateType.REFUNDABLE }
|
|
385
|
+
: { type: base_1.SwapCommitStateType.COMMITED }
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
swaps: resultingSwaps,
|
|
390
|
+
latestBlockheight: latestBlockheight ?? startBlockheight
|
|
391
|
+
};
|
|
392
|
+
}
|
|
302
393
|
////////////////////////////////////////////
|
|
303
394
|
//// Swap data initializer
|
|
304
395
|
/**
|
|
@@ -311,6 +402,30 @@ class EVMSwapContract extends EVMContractBase_1.EVMContractBase {
|
|
|
311
402
|
return Promise.resolve(new EVMSwapData_1.EVMSwapData(offerer, claimer, token, this.timelockRefundHandler.address, claimHandler.address, payOut, payIn, payIn, //For now track reputation for all payIn swaps
|
|
312
403
|
sequence, "0x" + paymentHash, (0, ethers_1.hexlify)(base_1.BigIntBufferUtils.toBuffer(expiry, "be", 32)), amount, depositToken, securityDeposit, claimerBounty, type));
|
|
313
404
|
}
|
|
405
|
+
findInitSwapData(call, escrowHash, claimHandler) {
|
|
406
|
+
if (call.to.toLowerCase() === this.contractAddress.toLowerCase()) {
|
|
407
|
+
const _result = this.parseCalldata(call.input);
|
|
408
|
+
if (_result != null && _result.name === "initialize") {
|
|
409
|
+
const result = _result;
|
|
410
|
+
//Found, check correct escrow hash
|
|
411
|
+
const [escrowData, signature, timeout, extraData] = result.args;
|
|
412
|
+
const escrow = EVMSwapData_1.EVMSwapData.deserializeFromStruct(escrowData, claimHandler);
|
|
413
|
+
if ("0x" + escrow.getEscrowHash() === escrowHash) {
|
|
414
|
+
const extraDataHex = (0, ethers_1.hexlify)(extraData);
|
|
415
|
+
if (extraDataHex.length > 2) {
|
|
416
|
+
escrow.setExtraData(extraDataHex.substring(2));
|
|
417
|
+
}
|
|
418
|
+
return escrow;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
for (let _call of call.calls) {
|
|
423
|
+
const found = this.findInitSwapData(_call, escrowHash, claimHandler);
|
|
424
|
+
if (found != null)
|
|
425
|
+
return found;
|
|
426
|
+
}
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
314
429
|
////////////////////////////////////////////
|
|
315
430
|
//// Utils
|
|
316
431
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomiqlabs/chain-evm",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.10",
|
|
4
4
|
"description": "EVM specific base implementation",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types:": "./dist/index.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"author": "adambor",
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@atomiqlabs/base": "^13.
|
|
28
|
+
"@atomiqlabs/base": "^13.1.9",
|
|
29
29
|
"@noble/hashes": "^1.8.0",
|
|
30
30
|
"@scure/btc-signer": "^1.6.0",
|
|
31
31
|
"buffer": "6.0.3",
|
|
@@ -21,6 +21,7 @@ const AlpenContractAddresses = {
|
|
|
21
21
|
MAINNET: {
|
|
22
22
|
executionContract: "",
|
|
23
23
|
swapContract: "",
|
|
24
|
+
swapContractDeploymentHeight: 0,
|
|
24
25
|
btcRelayContract: "",
|
|
25
26
|
btcRelayDeploymentHeight: 0,
|
|
26
27
|
spvVaultContract: "",
|
|
@@ -40,6 +41,7 @@ const AlpenContractAddresses = {
|
|
|
40
41
|
TESTNET: {
|
|
41
42
|
executionContract: "0x32EB4DbDdC31e19ba908fecc7cae03F0d04F01Fa",
|
|
42
43
|
swapContract: "0x2920EE496693A5027249a027A6FD3F643E743745",
|
|
44
|
+
swapContractDeploymentHeight: 532614,
|
|
43
45
|
btcRelayContract: "0x59A54378B6bA9C21ba66487C6A701D702baDEabE",
|
|
44
46
|
btcRelayDeploymentHeight: 532610,
|
|
45
47
|
spvVaultContract: "0xaB2D14745362B26a732dD8B7F95daAE3D2914bBF",
|
|
@@ -59,6 +61,7 @@ const AlpenContractAddresses = {
|
|
|
59
61
|
TESTNET4: {
|
|
60
62
|
executionContract: "0xa2698D2fBE3f7c74cCca428a5fd968411644C641",
|
|
61
63
|
swapContract: "0xb0226bAC3BD30179fb66A43cEA212AbBC988e004",
|
|
64
|
+
swapContractDeploymentHeight: 843614,
|
|
62
65
|
btcRelayContract: "0xfFA842529977a40A3fdb988cdDC9CB5c39bAcF26",
|
|
63
66
|
btcRelayDeploymentHeight: 843611,
|
|
64
67
|
spvVaultContract: "0x62a718348081F9CF9a8E3dF4B4EA6d6349991ad9",
|
|
@@ -111,6 +114,7 @@ export type AlpenOptions = {
|
|
|
111
114
|
chainType?: "MAINNET" | "TESTNET" | "TESTNET4",
|
|
112
115
|
|
|
113
116
|
swapContract?: string,
|
|
117
|
+
swapContractDeploymentHeight?: number,
|
|
114
118
|
btcRelayContract?: string,
|
|
115
119
|
btcRelayDeploymentHeight?: number,
|
|
116
120
|
spvVaultContract?: string,
|
|
@@ -126,7 +130,7 @@ export type AlpenOptions = {
|
|
|
126
130
|
|
|
127
131
|
fees?: EVMFees,
|
|
128
132
|
|
|
129
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
133
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
/**
|
|
@@ -180,7 +184,8 @@ export function initializeAlpen(
|
|
|
180
184
|
...defaultContractAddresses.handlerContracts.claim,
|
|
181
185
|
...options?.handlerContracts?.claim
|
|
182
186
|
}
|
|
183
|
-
}
|
|
187
|
+
},
|
|
188
|
+
options.swapContractDeploymentHeight ?? defaultContractAddresses.swapContractDeploymentHeight
|
|
184
189
|
);
|
|
185
190
|
|
|
186
191
|
const spvVaultContract = new EVMSpvVaultContract(
|
|
@@ -20,6 +20,7 @@ const BotanixContractAddresses = {
|
|
|
20
20
|
MAINNET: {
|
|
21
21
|
executionContract: "0x71Bc44F3F7203fC1279107D924e418F02b0d4029",
|
|
22
22
|
swapContract: "0x9a027B5Bf43382Cc4A5134d9EFD389f61ece27B9",
|
|
23
|
+
swapContractDeploymentHeight: 2320403,
|
|
23
24
|
btcRelayContract: "0xe8be24CF21341c9567664009a8a82C9Dc1eE90D6",
|
|
24
25
|
btcRelayDeploymentHeight: 2320400,
|
|
25
26
|
spvVaultContract: "0xe510D5781C6C849284Fb25Dc20b1684cEC445C8B",
|
|
@@ -39,6 +40,7 @@ const BotanixContractAddresses = {
|
|
|
39
40
|
TESTNET: {
|
|
40
41
|
executionContract: "0xe510D5781C6C849284Fb25Dc20b1684cEC445C8B",
|
|
41
42
|
swapContract: "0xfFA842529977a40A3fdb988cdDC9CB5c39bAcF26",
|
|
43
|
+
swapContractDeploymentHeight: 4173454,
|
|
42
44
|
btcRelayContract: "0xba7E78011909e3501027FBc226a04DCC837a555D",
|
|
43
45
|
btcRelayDeploymentHeight: 3462466,
|
|
44
46
|
spvVaultContract: "0x9a027B5Bf43382Cc4A5134d9EFD389f61ece27B9",
|
|
@@ -90,6 +92,7 @@ export type BotanixOptions = {
|
|
|
90
92
|
chainType?: "MAINNET" | "TESTNET",
|
|
91
93
|
|
|
92
94
|
swapContract?: string,
|
|
95
|
+
swapContractDeploymentHeight?: number,
|
|
93
96
|
btcRelayContract?: string,
|
|
94
97
|
btcRelayDeploymentHeight?: number,
|
|
95
98
|
spvVaultContract?: string,
|
|
@@ -105,7 +108,7 @@ export type BotanixOptions = {
|
|
|
105
108
|
|
|
106
109
|
fees?: EVMFees,
|
|
107
110
|
|
|
108
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
111
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
/**
|
|
@@ -163,7 +166,8 @@ export function initializeBotanix(
|
|
|
163
166
|
...defaultContractAddresses.handlerContracts.claim,
|
|
164
167
|
...options?.handlerContracts?.claim
|
|
165
168
|
}
|
|
166
|
-
}
|
|
169
|
+
},
|
|
170
|
+
options.swapContractDeploymentHeight ?? defaultContractAddresses.swapContractDeploymentHeight
|
|
167
171
|
);
|
|
168
172
|
|
|
169
173
|
const spvVaultContract = new EVMSpvVaultContract(
|
|
@@ -21,6 +21,7 @@ const CitreaContractAddresses = {
|
|
|
21
21
|
MAINNET: {
|
|
22
22
|
executionContract: "0x6a373b6Adad83964727bA0fa15E22Be05173fc12",
|
|
23
23
|
swapContract: "0xc98Ef084d3911C8447DBbE4dDa18bC2c9bB0584e",
|
|
24
|
+
swapContractDeploymentHeight: 2452632,
|
|
24
25
|
btcRelayContract: "0x11ac854A68830d61af975063c91602f878C36fA6",
|
|
25
26
|
btcRelayDeploymentHeight: 2452629,
|
|
26
27
|
spvVaultContract: "0x5bb0C725939cB825d1322A99a3FeB570097628c3",
|
|
@@ -40,6 +41,7 @@ const CitreaContractAddresses = {
|
|
|
40
41
|
TESTNET4: {
|
|
41
42
|
executionContract: "0x9e289512965A0842b342A6BB3F3c41F22a555Cfe",
|
|
42
43
|
swapContract: "0xBbf7755b674dD107d59F0650D1A3fA9C60bf6Fe6",
|
|
44
|
+
swapContractDeploymentHeight: 12346224,
|
|
43
45
|
btcRelayContract: "0x00D122E9f9766cd81a38D2dd44f9AFfb94c67Af7",
|
|
44
46
|
btcRelayDeploymentHeight: 12346223,
|
|
45
47
|
spvVaultContract: "0x9Bf990C6088F716279797a602b05941c40591533",
|
|
@@ -101,6 +103,7 @@ export type CitreaOptions = {
|
|
|
101
103
|
chainType?: "MAINNET" | "TESTNET4",
|
|
102
104
|
|
|
103
105
|
swapContract?: string,
|
|
106
|
+
swapContractDeploymentHeight?: number,
|
|
104
107
|
btcRelayContract?: string,
|
|
105
108
|
btcRelayDeploymentHeight?: number,
|
|
106
109
|
spvVaultContract?: string,
|
|
@@ -116,7 +119,7 @@ export type CitreaOptions = {
|
|
|
116
119
|
|
|
117
120
|
fees?: CitreaFees,
|
|
118
121
|
|
|
119
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
122
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
/**
|
|
@@ -172,7 +175,8 @@ export function initializeCitrea(
|
|
|
172
175
|
...defaultContractAddresses.handlerContracts.claim,
|
|
173
176
|
...options?.handlerContracts?.claim
|
|
174
177
|
}
|
|
175
|
-
}
|
|
178
|
+
},
|
|
179
|
+
options.swapContractDeploymentHeight ?? defaultContractAddresses.swapContractDeploymentHeight
|
|
176
180
|
);
|
|
177
181
|
|
|
178
182
|
const spvVaultContract = new CitreaSpvVaultContract(
|
|
@@ -21,6 +21,7 @@ const GoatContractAddresses = {
|
|
|
21
21
|
MAINNET: {
|
|
22
22
|
executionContract: "",
|
|
23
23
|
swapContract: "",
|
|
24
|
+
swapContractDeploymentHeight: 0,
|
|
24
25
|
btcRelayContract: "",
|
|
25
26
|
btcRelayDeploymentHeight: 0,
|
|
26
27
|
spvVaultContract: "",
|
|
@@ -40,6 +41,7 @@ const GoatContractAddresses = {
|
|
|
40
41
|
TESTNET: {
|
|
41
42
|
executionContract: "0xe8be24CF21341c9567664009a8a82C9Dc1eE90D6",
|
|
42
43
|
swapContract: "0xe510D5781C6C849284Fb25Dc20b1684cEC445C8B",
|
|
44
|
+
swapContractDeploymentHeight: 9368978,
|
|
43
45
|
btcRelayContract: "0x3887B02217726bB36958Dd595e57293fB63D5082",
|
|
44
46
|
btcRelayDeploymentHeight: 9368975,
|
|
45
47
|
spvVaultContract: "0x71Bc44F3F7203fC1279107D924e418F02b0d4029",
|
|
@@ -59,6 +61,7 @@ const GoatContractAddresses = {
|
|
|
59
61
|
TESTNET4: {
|
|
60
62
|
executionContract: "0x4f7d86C870F28ac30C8fa864Ee04264D7dD03847",
|
|
61
63
|
swapContract: "0x3FbbA0eb82cf1247cbf92B3D51641226310F0Ca5",
|
|
64
|
+
swapContractDeploymentHeight: 10240371,
|
|
62
65
|
btcRelayContract: "0xEeD58871C24d24C49554aF8B65Dd86eD8ed778D3",
|
|
63
66
|
btcRelayDeploymentHeight: 10240368,
|
|
64
67
|
spvVaultContract: "0x8a80A68f8bA1732015A821b5260fEF8040a844b7",
|
|
@@ -121,6 +124,7 @@ export type GoatOptions = {
|
|
|
121
124
|
chainType?: "MAINNET" | "TESTNET" | "TESTNET4",
|
|
122
125
|
|
|
123
126
|
swapContract?: string,
|
|
127
|
+
swapContractDeploymentHeight?: number,
|
|
124
128
|
btcRelayContract?: string,
|
|
125
129
|
btcRelayDeploymentHeight?: number,
|
|
126
130
|
spvVaultContract?: string,
|
|
@@ -136,7 +140,7 @@ export type GoatOptions = {
|
|
|
136
140
|
|
|
137
141
|
fees?: EVMFees,
|
|
138
142
|
|
|
139
|
-
evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"
|
|
143
|
+
evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
/**
|
|
@@ -190,7 +194,8 @@ export function initializeGoat(
|
|
|
190
194
|
...defaultContractAddresses.handlerContracts.claim,
|
|
191
195
|
...options?.handlerContracts?.claim
|
|
192
196
|
}
|
|
193
|
-
}
|
|
197
|
+
},
|
|
198
|
+
options.swapContractDeploymentHeight?? defaultContractAddresses.swapContractDeploymentHeight
|
|
194
199
|
);
|
|
195
200
|
|
|
196
201
|
const spvVaultContract = new EVMSpvVaultContract(
|
|
@@ -4,6 +4,14 @@ import {EVMContractBase} from "../EVMContractBase";
|
|
|
4
4
|
import {EVMChainInterface} from "../../chain/EVMChainInterface";
|
|
5
5
|
import {TypedEventLog} from "../../typechain/common";
|
|
6
6
|
|
|
7
|
+
function normalizeTopic(topic: string) {
|
|
8
|
+
if(topic.length!==66) {
|
|
9
|
+
return "0x"+topic.substring(2).padStart(64, "0");
|
|
10
|
+
}
|
|
11
|
+
return topic;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
7
15
|
export class EVMContractEvents<T extends BaseContract> extends EVMEvents {
|
|
8
16
|
|
|
9
17
|
readonly contract: EVMContractBase<T>;
|
|
@@ -22,12 +30,12 @@ export class EVMContractEvents<T extends BaseContract> extends EVMEvents {
|
|
|
22
30
|
private toFilter<TEventName extends keyof T["filters"]>(
|
|
23
31
|
events: TEventName[],
|
|
24
32
|
keys: null | (null | string | string[])[],
|
|
25
|
-
): (null | string
|
|
26
|
-
const filterArray: (null | string
|
|
33
|
+
): (null | string[])[] {
|
|
34
|
+
const filterArray: (null | string[])[] = [];
|
|
27
35
|
filterArray.push(events.map(name => {
|
|
28
36
|
return this.baseContract.getEvent(name as string).fragment.topicHash;
|
|
29
37
|
}));
|
|
30
|
-
if(keys!=null) keys.forEach(key => filterArray.push(key));
|
|
38
|
+
if(keys!=null) keys.forEach(key => filterArray.push(typeof(key)==="string" ? [normalizeTopic(key)] : Array.isArray(key) ? key.map(normalizeTopic) : key));
|
|
31
39
|
return filterArray;
|
|
32
40
|
}
|
|
33
41
|
|
|
@@ -93,33 +93,6 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
93
93
|
return this.processedEvents.includes(event.transactionHash+":"+event.index);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
findInitSwapData(call: EVMTxTrace, escrowHash: string, claimHandler: IClaimHandler<any, any>): EVMSwapData | null {
|
|
97
|
-
if(call.to.toLowerCase() === this.evmSwapContract.contractAddress.toLowerCase()) {
|
|
98
|
-
const _result = this.evmSwapContract.parseCalldata(call.input);
|
|
99
|
-
if(_result!=null && _result.name==="initialize") {
|
|
100
|
-
const result = _result as TypedFunctionCall<
|
|
101
|
-
// @ts-ignore
|
|
102
|
-
typeof this.evmSwapContract.contract.initialize
|
|
103
|
-
>;
|
|
104
|
-
//Found, check correct escrow hash
|
|
105
|
-
const [escrowData, signature, timeout, extraData] = result.args;
|
|
106
|
-
const escrow = EVMSwapData.deserializeFromStruct(escrowData, claimHandler);
|
|
107
|
-
if("0x"+escrow.getEscrowHash()===escrowHash) {
|
|
108
|
-
const extraDataHex = hexlify(extraData);
|
|
109
|
-
if(extraDataHex.length>2) {
|
|
110
|
-
escrow.setExtraData(extraDataHex.substring(2));
|
|
111
|
-
}
|
|
112
|
-
return escrow;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
for(let _call of call.calls) {
|
|
117
|
-
const found = this.findInitSwapData(_call, escrowHash, claimHandler);
|
|
118
|
-
if(found!=null) return found;
|
|
119
|
-
}
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
96
|
/**
|
|
124
97
|
* Returns async getter for fetching on-demand initialize event swap data
|
|
125
98
|
*
|
|
@@ -135,7 +108,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
135
108
|
return async () => {
|
|
136
109
|
const trace = await this.chainInterface.Transactions.traceTransaction(event.transactionHash);
|
|
137
110
|
if(trace==null) return null;
|
|
138
|
-
return this.findInitSwapData(trace, event.args.escrowHash, claimHandler);
|
|
111
|
+
return this.evmSwapContract.findInitSwapData(trace, event.args.escrowHash, claimHandler);
|
|
139
112
|
}
|
|
140
113
|
}
|
|
141
114
|
|
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
RelaySynchronizer,
|
|
6
6
|
SpvVaultContract,
|
|
7
7
|
SpvVaultTokenData,
|
|
8
|
+
SpvWithdrawalClaimedState,
|
|
9
|
+
SpvWithdrawalClosedState,
|
|
10
|
+
SpvWithdrawalFrontedState,
|
|
8
11
|
SpvWithdrawalState,
|
|
9
12
|
SpvWithdrawalStateType,
|
|
10
13
|
SpvWithdrawalTransactionData,
|
|
@@ -364,39 +367,56 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
364
367
|
return vaults;
|
|
365
368
|
}
|
|
366
369
|
|
|
367
|
-
private parseWithdrawalEvent(
|
|
370
|
+
private parseWithdrawalEvent(
|
|
371
|
+
event: TypedEventLog<SpvVaultManager["filters"][keyof SpvVaultManager["filters"]]>
|
|
372
|
+
): ((SpvWithdrawalFrontedState | SpvWithdrawalClaimedState | SpvWithdrawalClosedState) & {btcTxId: string}) | null {
|
|
368
373
|
switch(event.eventName) {
|
|
369
374
|
case "Fronted":
|
|
370
375
|
const frontedEvent = event as TypedEventLog<SpvVaultManager["filters"]["Fronted"]>;
|
|
371
376
|
const [ownerFront, vaultIdFront] = unpackOwnerAndVaultId(frontedEvent.args.ownerAndVaultId);
|
|
372
377
|
return {
|
|
373
378
|
type: SpvWithdrawalStateType.FRONTED,
|
|
374
|
-
|
|
379
|
+
btcTxId: Buffer.from(frontedEvent.args.btcTxHash.substring(2), "hex").reverse().toString("hex"),
|
|
375
380
|
owner: ownerFront,
|
|
376
381
|
vaultId: vaultIdFront,
|
|
377
382
|
recipient: frontedEvent.args.recipient,
|
|
378
|
-
fronter: frontedEvent.args.caller
|
|
383
|
+
fronter: frontedEvent.args.caller,
|
|
384
|
+
txId: event.transactionHash,
|
|
385
|
+
getTxBlock: async () => ({
|
|
386
|
+
blockHeight: event.blockNumber,
|
|
387
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
388
|
+
})
|
|
379
389
|
};
|
|
380
390
|
case "Claimed":
|
|
381
391
|
const claimedEvent = event as TypedEventLog<SpvVaultManager["filters"]["Claimed"]>;
|
|
382
392
|
const [ownerClaim, vaultIdClaim] = unpackOwnerAndVaultId(claimedEvent.args.ownerAndVaultId);
|
|
383
393
|
return {
|
|
384
394
|
type: SpvWithdrawalStateType.CLAIMED,
|
|
385
|
-
|
|
395
|
+
btcTxId: Buffer.from(claimedEvent.args.btcTxHash.substring(2), "hex").reverse().toString("hex"),
|
|
386
396
|
owner: ownerClaim,
|
|
387
397
|
vaultId: vaultIdClaim,
|
|
388
398
|
recipient: claimedEvent.args.recipient,
|
|
389
399
|
claimer: claimedEvent.args.caller,
|
|
390
|
-
fronter: claimedEvent.args.frontingAddress
|
|
400
|
+
fronter: claimedEvent.args.frontingAddress,
|
|
401
|
+
txId: event.transactionHash,
|
|
402
|
+
getTxBlock: async () => ({
|
|
403
|
+
blockHeight: event.blockNumber,
|
|
404
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
405
|
+
})
|
|
391
406
|
};
|
|
392
407
|
case "Closed":
|
|
393
408
|
const closedEvent = event as TypedEventLog<SpvVaultManager["filters"]["Closed"]>;
|
|
394
409
|
return {
|
|
395
410
|
type: SpvWithdrawalStateType.CLOSED,
|
|
396
|
-
|
|
411
|
+
btcTxId: Buffer.from(closedEvent.args.btcTxHash.substring(2), "hex").reverse().toString("hex"),
|
|
397
412
|
owner: closedEvent.args.owner,
|
|
398
413
|
vaultId: closedEvent.args.vaultId,
|
|
399
|
-
error: closedEvent.args.error
|
|
414
|
+
error: closedEvent.args.error,
|
|
415
|
+
txId: event.transactionHash,
|
|
416
|
+
getTxBlock: async () => ({
|
|
417
|
+
blockHeight: event.blockNumber,
|
|
418
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
419
|
+
})
|
|
400
420
|
};
|
|
401
421
|
default:
|
|
402
422
|
return null;
|
|
@@ -523,6 +543,30 @@ export class EVMSpvVaultContract<ChainId extends string>
|
|
|
523
543
|
return result;
|
|
524
544
|
}
|
|
525
545
|
|
|
546
|
+
async getHistoricalWithdrawalStates(recipient: string, startBlockheight?: number): Promise<{
|
|
547
|
+
withdrawals: { [btcTxId: string]: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState };
|
|
548
|
+
latestBlockheight?: number
|
|
549
|
+
}> {
|
|
550
|
+
const {height: latestBlockheight} = await this.Chain.getFinalizedBlock();
|
|
551
|
+
const withdrawals: { [btcTxId: string]: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState } = {};
|
|
552
|
+
|
|
553
|
+
await this.Events.findInContractEventsForward(
|
|
554
|
+
["Claimed", "Fronted"],
|
|
555
|
+
[null, recipient],
|
|
556
|
+
async (_event) => {
|
|
557
|
+
const eventResult = this.parseWithdrawalEvent(_event);
|
|
558
|
+
if(eventResult==null || eventResult.type===SpvWithdrawalStateType.CLOSED) return null;
|
|
559
|
+
withdrawals[eventResult.btcTxId] = eventResult;
|
|
560
|
+
},
|
|
561
|
+
startBlockheight
|
|
562
|
+
);
|
|
563
|
+
|
|
564
|
+
return {
|
|
565
|
+
withdrawals,
|
|
566
|
+
latestBlockheight
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
526
570
|
/**
|
|
527
571
|
* @inheritDoc
|
|
528
572
|
*/
|
|
@@ -12,10 +12,10 @@ import {TimelockRefundHandler} from "./handlers/refund/TimelockRefundHandler";
|
|
|
12
12
|
import {claimHandlersList, IClaimHandler} from "./handlers/claim/ClaimHandlers"
|
|
13
13
|
import {IHandler} from "./handlers/IHandler";
|
|
14
14
|
import {sha256} from "@noble/hashes/sha2";
|
|
15
|
-
import {
|
|
15
|
+
import {EVMContractBase, TypedFunctionCall} from "../contract/EVMContractBase";
|
|
16
16
|
import {EscrowManager} from "./EscrowManagerTypechain";
|
|
17
17
|
import { EVMSwapData } from "./EVMSwapData";
|
|
18
|
-
import {EVMTx} from "../chain/modules/EVMTransactions";
|
|
18
|
+
import {EVMTx, EVMTxTrace} from "../chain/modules/EVMTransactions";
|
|
19
19
|
import { EVMSigner } from "../wallet/EVMSigner";
|
|
20
20
|
import {EVMChainInterface} from "../chain/EVMChainInterface";
|
|
21
21
|
import { EVMBtcRelay } from "../btcrelay/EVMBtcRelay";
|
|
@@ -26,11 +26,15 @@ import {EVMLpVault} from "./modules/EVMLpVault";
|
|
|
26
26
|
import {EVMPreFetchVerification, EVMSwapInit} from "./modules/EVMSwapInit";
|
|
27
27
|
import { EVMSwapRefund } from "./modules/EVMSwapRefund";
|
|
28
28
|
import {EVMSwapClaim} from "./modules/EVMSwapClaim";
|
|
29
|
+
import {TypedEventLog} from "../typechain/common";
|
|
30
|
+
import {getLogger} from "../../utils/Utils";
|
|
29
31
|
|
|
30
32
|
const ESCROW_STATE_COMMITTED = 1;
|
|
31
33
|
const ESCROW_STATE_CLAIMED = 2;
|
|
32
34
|
const ESCROW_STATE_REFUNDED = 3;
|
|
33
35
|
|
|
36
|
+
const logger = getLogger("EVMSwapContract: ");
|
|
37
|
+
|
|
34
38
|
/**
|
|
35
39
|
* @category Swaps
|
|
36
40
|
*/
|
|
@@ -88,9 +92,10 @@ export class EVMSwapContract<ChainId extends string = string>
|
|
|
88
92
|
claim: {
|
|
89
93
|
[type in ChainSwapType]: string
|
|
90
94
|
}
|
|
91
|
-
}
|
|
95
|
+
},
|
|
96
|
+
contractDeploymentHeight?: number
|
|
92
97
|
) {
|
|
93
|
-
super(chainInterface, contractAddress, EscrowManagerAbi);
|
|
98
|
+
super(chainInterface, contractAddress, EscrowManagerAbi, contractDeploymentHeight);
|
|
94
99
|
this.chainId = chainInterface.chainId;
|
|
95
100
|
this.Init = new EVMSwapInit(chainInterface, this);
|
|
96
101
|
this.Refund = new EVMSwapRefund(chainInterface, this);
|
|
@@ -378,6 +383,145 @@ export class EVMSwapContract<ChainId extends string = string>
|
|
|
378
383
|
return result;
|
|
379
384
|
}
|
|
380
385
|
|
|
386
|
+
async getHistoricalSwaps(signer: string, startBlockheight?: number): Promise<{
|
|
387
|
+
swaps: {
|
|
388
|
+
[escrowHash: string]: {
|
|
389
|
+
init?: {
|
|
390
|
+
data: EVMSwapData;
|
|
391
|
+
getInitTxId: () => Promise<string>;
|
|
392
|
+
getTxBlock: () => Promise<{ blockTime: number; blockHeight: number }>
|
|
393
|
+
};
|
|
394
|
+
state: SwapCommitState
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
latestBlockheight?: number
|
|
398
|
+
}> {
|
|
399
|
+
const {height: latestBlockheight} = await this.Chain.getFinalizedBlock();
|
|
400
|
+
|
|
401
|
+
const swapsOpened: {
|
|
402
|
+
[escrowHash: string]: {
|
|
403
|
+
data: EVMSwapData,
|
|
404
|
+
getInitTxId: () => Promise<string>,
|
|
405
|
+
getTxBlock: () => Promise<{
|
|
406
|
+
blockTime: number,
|
|
407
|
+
blockHeight: number
|
|
408
|
+
}>
|
|
409
|
+
}
|
|
410
|
+
} = {};
|
|
411
|
+
const resultingSwaps: {
|
|
412
|
+
[escrowHash: string]: {
|
|
413
|
+
init?: {
|
|
414
|
+
data: EVMSwapData;
|
|
415
|
+
getInitTxId: () => Promise<string>;
|
|
416
|
+
getTxBlock: () => Promise<{ blockTime: number; blockHeight: number }>
|
|
417
|
+
};
|
|
418
|
+
state: SwapCommitState
|
|
419
|
+
}
|
|
420
|
+
} = {};
|
|
421
|
+
|
|
422
|
+
const processor = async (_event: TypedEventLog<EscrowManager["filters"]["Initialize" | "Claim" | "Refund"]>) => {
|
|
423
|
+
const escrowHash = _event.args.escrowHash.substring(2);
|
|
424
|
+
if(_event.eventName==="Initialize") {
|
|
425
|
+
const event = _event as TypedEventLog<EscrowManager["filters"]["Initialize"]>;
|
|
426
|
+
const claimHandlerHex = event.args.claimHandler;
|
|
427
|
+
|
|
428
|
+
const claimHandler = this.claimHandlersByAddress[claimHandlerHex.toLowerCase()];
|
|
429
|
+
if(claimHandler==null) {
|
|
430
|
+
logger.warn(`getHistoricalSwaps(): Unknown claim handler in tx ${event.transactionHash} with claim handler: `+claimHandlerHex);
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const txTrace = await this.Chain.Transactions.traceTransaction(event.transactionHash);
|
|
435
|
+
const data = this.findInitSwapData(txTrace, event.args.escrowHash, claimHandler);
|
|
436
|
+
if(data==null) {
|
|
437
|
+
logger.warn(`getHistoricalSwaps(): Cannot parse swap data from tx ${event.transactionHash} with escrow hash: `+escrowHash);
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
swapsOpened[escrowHash] = {
|
|
442
|
+
data,
|
|
443
|
+
getInitTxId: () => Promise.resolve(event.transactionHash),
|
|
444
|
+
getTxBlock: async () => {
|
|
445
|
+
return {
|
|
446
|
+
blockHeight: event.blockNumber,
|
|
447
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
if(_event.eventName==="Claim") {
|
|
453
|
+
const event = _event as TypedEventLog<EscrowManager["filters"]["Claim"]>;
|
|
454
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
455
|
+
delete swapsOpened[escrowHash];
|
|
456
|
+
resultingSwaps[escrowHash] = {
|
|
457
|
+
init: foundSwapData,
|
|
458
|
+
state: {
|
|
459
|
+
type: SwapCommitStateType.PAID,
|
|
460
|
+
getClaimTxId: () => Promise.resolve(event.transactionHash),
|
|
461
|
+
getClaimResult: () => Promise.resolve(event.args.witnessResult.substring(2)),
|
|
462
|
+
getTxBlock: async () => {
|
|
463
|
+
return {
|
|
464
|
+
blockHeight: event.blockNumber,
|
|
465
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if(_event.eventName==="Refund") {
|
|
472
|
+
const event = _event as TypedEventLog<EscrowManager["filters"]["Refund"]>;
|
|
473
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
474
|
+
delete swapsOpened[escrowHash];
|
|
475
|
+
const isExpired = foundSwapData!=null && await this.isExpired(signer, foundSwapData.data);
|
|
476
|
+
resultingSwaps[escrowHash] = {
|
|
477
|
+
init: foundSwapData,
|
|
478
|
+
state: {
|
|
479
|
+
type: isExpired ? SwapCommitStateType.EXPIRED : SwapCommitStateType.NOT_COMMITED,
|
|
480
|
+
getRefundTxId: () => Promise.resolve(event.transactionHash),
|
|
481
|
+
getTxBlock: async () => {
|
|
482
|
+
return {
|
|
483
|
+
blockHeight: event.blockNumber,
|
|
484
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber)
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
//We have to fetch separately the different directions
|
|
493
|
+
await this.Events.findInContractEventsForward(
|
|
494
|
+
["Initialize", "Claim", "Refund"],
|
|
495
|
+
[signer, null],
|
|
496
|
+
processor,
|
|
497
|
+
startBlockheight
|
|
498
|
+
);
|
|
499
|
+
await this.Events.findInContractEventsForward(
|
|
500
|
+
["Initialize", "Claim", "Refund"],
|
|
501
|
+
[null, signer],
|
|
502
|
+
processor,
|
|
503
|
+
startBlockheight
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
logger.debug(`getHistoricalSwaps(): Found ${Object.keys(resultingSwaps).length} settled swaps!`);
|
|
507
|
+
logger.debug(`getHistoricalSwaps(): Found ${Object.keys(swapsOpened).length} unsettled swaps!`);
|
|
508
|
+
|
|
509
|
+
for(let escrowHash in swapsOpened) {
|
|
510
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
511
|
+
resultingSwaps[escrowHash] = {
|
|
512
|
+
init: foundSwapData,
|
|
513
|
+
state: foundSwapData.data.isOfferer(signer) && await this.isExpired(signer, foundSwapData.data)
|
|
514
|
+
? {type: SwapCommitStateType.REFUNDABLE}
|
|
515
|
+
: {type: SwapCommitStateType.COMMITED}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return {
|
|
520
|
+
swaps: resultingSwaps,
|
|
521
|
+
latestBlockheight: latestBlockheight ?? startBlockheight
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
381
525
|
////////////////////////////////////////////
|
|
382
526
|
//// Swap data initializer
|
|
383
527
|
/**
|
|
@@ -421,6 +565,33 @@ export class EVMSwapContract<ChainId extends string = string>
|
|
|
421
565
|
));
|
|
422
566
|
}
|
|
423
567
|
|
|
568
|
+
findInitSwapData(call: EVMTxTrace, escrowHash: string, claimHandler: IClaimHandler<any, any>): EVMSwapData | null {
|
|
569
|
+
if(call.to.toLowerCase() === this.contractAddress.toLowerCase()) {
|
|
570
|
+
const _result = this.parseCalldata(call.input);
|
|
571
|
+
if(_result!=null && _result.name==="initialize") {
|
|
572
|
+
const result = _result as TypedFunctionCall<
|
|
573
|
+
// @ts-ignore
|
|
574
|
+
typeof this.evmSwapContract.contract.initialize
|
|
575
|
+
>;
|
|
576
|
+
//Found, check correct escrow hash
|
|
577
|
+
const [escrowData, signature, timeout, extraData] = result.args;
|
|
578
|
+
const escrow = EVMSwapData.deserializeFromStruct(escrowData, claimHandler);
|
|
579
|
+
if("0x"+escrow.getEscrowHash()===escrowHash) {
|
|
580
|
+
const extraDataHex = hexlify(extraData);
|
|
581
|
+
if(extraDataHex.length>2) {
|
|
582
|
+
escrow.setExtraData(extraDataHex.substring(2));
|
|
583
|
+
}
|
|
584
|
+
return escrow;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
for(let _call of call.calls) {
|
|
589
|
+
const found = this.findInitSwapData(_call, escrowHash, claimHandler);
|
|
590
|
+
if(found!=null) return found;
|
|
591
|
+
}
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
|
|
424
595
|
////////////////////////////////////////////
|
|
425
596
|
//// Utils
|
|
426
597
|
/**
|