@atomiqlabs/chain-evm 2.1.12 → 2.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -0
- package/dist/chains/EVMOptions.d.ts +66 -0
- package/dist/chains/EVMOptions.js +2 -0
- package/dist/chains/alpen/AlpenInitializer.d.ts +3 -30
- package/dist/chains/alpen/AlpenInitializer.js +3 -3
- package/dist/chains/botanix/BotanixInitializer.d.ts +3 -30
- package/dist/chains/botanix/BotanixInitializer.js +3 -3
- package/dist/chains/citrea/CitreaBtcRelay.d.ts +5 -0
- package/dist/chains/citrea/CitreaBtcRelay.js +7 -2
- package/dist/chains/citrea/CitreaFees.d.ts +3 -5
- package/dist/chains/citrea/CitreaFees.js +3 -5
- package/dist/chains/citrea/CitreaInitializer.d.ts +3 -29
- package/dist/chains/citrea/CitreaInitializer.js +3 -3
- package/dist/chains/citrea/CitreaSpvVaultContract.d.ts +5 -0
- package/dist/chains/citrea/CitreaSpvVaultContract.js +7 -2
- package/dist/chains/citrea/CitreaSwapContract.d.ts +7 -2
- package/dist/chains/citrea/CitreaSwapContract.js +10 -5
- package/dist/chains/citrea/CitreaTokens.d.ts +5 -0
- package/dist/chains/citrea/CitreaTokens.js +5 -0
- package/dist/chains/goat/GoatInitializer.d.ts +3 -30
- package/dist/chains/goat/GoatInitializer.js +3 -3
- package/dist/evm/btcrelay/EVMBtcRelay.d.ts +41 -10
- package/dist/evm/btcrelay/EVMBtcRelay.js +50 -18
- package/dist/evm/btcrelay/headers/EVMBtcHeader.d.ts +53 -7
- package/dist/evm/btcrelay/headers/EVMBtcHeader.js +43 -5
- package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.d.ts +53 -8
- package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.js +41 -1
- package/dist/evm/chain/EVMChainInterface.d.ts +57 -2
- package/dist/evm/chain/EVMChainInterface.js +7 -7
- package/dist/evm/chain/EVMModule.d.ts +5 -0
- package/dist/evm/chain/EVMModule.js +6 -1
- package/dist/evm/chain/modules/EVMBlocks.d.ts +7 -0
- package/dist/evm/chain/modules/EVMBlocks.js +2 -0
- package/dist/evm/chain/modules/EVMEvents.js +19 -19
- package/dist/evm/chain/modules/EVMFees.d.ts +41 -5
- package/dist/evm/chain/modules/EVMFees.js +24 -5
- package/dist/evm/chain/modules/EVMTokens.d.ts +1 -1
- package/dist/evm/chain/modules/EVMTokens.js +1 -1
- package/dist/evm/chain/modules/EVMTransactions.d.ts +20 -2
- package/dist/evm/chain/modules/EVMTransactions.js +11 -8
- package/dist/evm/contract/EVMContractBase.d.ts +28 -10
- package/dist/evm/contract/EVMContractBase.js +9 -18
- package/dist/evm/contract/EVMContractModule.d.ts +5 -0
- package/dist/evm/contract/EVMContractModule.js +5 -0
- package/dist/evm/contract/modules/EVMContractEvents.d.ts +7 -1
- package/dist/evm/contract/modules/EVMContractEvents.js +23 -3
- package/dist/evm/events/EVMChainEvents.d.ts +8 -0
- package/dist/evm/events/EVMChainEvents.js +8 -0
- package/dist/evm/events/EVMChainEventsBrowser.d.ts +87 -19
- package/dist/evm/events/EVMChainEventsBrowser.js +53 -18
- package/dist/evm/providers/JsonRpcProviderWithRetries.d.ts +9 -0
- package/dist/evm/providers/JsonRpcProviderWithRetries.js +9 -0
- package/dist/evm/providers/ReconnectingWebSocketProvider.d.ts +5 -0
- package/dist/evm/providers/ReconnectingWebSocketProvider.js +5 -0
- package/dist/evm/providers/WebSocketProviderWithRetries.d.ts +9 -0
- package/dist/evm/providers/WebSocketProviderWithRetries.js +9 -0
- package/dist/evm/spv_swap/EVMSpvVaultContract.d.ts +46 -21
- package/dist/evm/spv_swap/EVMSpvVaultContract.js +61 -23
- package/dist/evm/spv_swap/EVMSpvVaultData.d.ts +57 -2
- package/dist/evm/spv_swap/EVMSpvVaultData.js +57 -2
- package/dist/evm/spv_swap/EVMSpvWithdrawalData.d.ts +12 -0
- package/dist/evm/spv_swap/EVMSpvWithdrawalData.js +12 -0
- package/dist/evm/swaps/EVMSwapContract.d.ts +58 -13
- package/dist/evm/swaps/EVMSwapContract.js +81 -54
- package/dist/evm/swaps/EVMSwapData.d.ts +27 -6
- package/dist/evm/swaps/EVMSwapData.js +26 -0
- package/dist/evm/swaps/EVMSwapModule.d.ts +5 -0
- package/dist/evm/swaps/EVMSwapModule.js +5 -0
- package/dist/evm/swaps/handlers/IHandler.d.ts +5 -0
- package/dist/evm/swaps/handlers/claim/ClaimHandlers.d.ts +15 -0
- package/dist/evm/swaps/handlers/claim/ClaimHandlers.js +5 -0
- package/dist/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +5 -0
- package/dist/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +10 -0
- package/dist/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +5 -0
- package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +15 -0
- package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +7 -2
- package/dist/evm/swaps/modules/EVMLpVault.d.ts +5 -0
- package/dist/evm/swaps/modules/EVMLpVault.js +9 -4
- package/dist/evm/swaps/modules/EVMSwapClaim.d.ts +7 -2
- package/dist/evm/swaps/modules/EVMSwapClaim.js +11 -6
- package/dist/evm/swaps/modules/EVMSwapInit.d.ts +10 -0
- package/dist/evm/swaps/modules/EVMSwapInit.js +11 -6
- package/dist/evm/swaps/modules/EVMSwapRefund.d.ts +5 -0
- package/dist/evm/swaps/modules/EVMSwapRefund.js +9 -4
- package/dist/evm/wallet/EVMBrowserSigner.d.ts +22 -2
- package/dist/evm/wallet/EVMBrowserSigner.js +40 -2
- package/dist/evm/wallet/EVMPersistentSigner.d.ts +13 -2
- package/dist/evm/wallet/EVMPersistentSigner.js +13 -1
- package/dist/evm/wallet/EVMSigner.d.ts +30 -1
- package/dist/evm/wallet/EVMSigner.js +34 -1
- package/dist/index.d.ts +71 -0
- package/dist/index.js +70 -0
- package/dist/node/index.d.ts +10 -0
- package/dist/node/index.js +15 -0
- package/dist/utils/Utils.d.ts +50 -0
- package/dist/utils/Utils.js +45 -0
- package/node/index.d.ts +1 -0
- package/node/index.js +3 -0
- package/package.json +4 -3
- package/src/chains/EVMOptions.ts +70 -0
- package/src/chains/alpen/AlpenInitializer.ts +5 -27
- package/src/chains/botanix/BotanixChainType.ts +5 -5
- package/src/chains/botanix/BotanixInitializer.ts +5 -27
- package/src/chains/citrea/CitreaBtcRelay.ts +8 -3
- package/src/chains/citrea/CitreaFees.ts +3 -6
- package/src/chains/citrea/CitreaInitializer.ts +5 -27
- package/src/chains/citrea/CitreaSpvVaultContract.ts +7 -2
- package/src/chains/citrea/CitreaSwapContract.ts +11 -6
- package/src/chains/citrea/CitreaTokens.ts +6 -1
- package/src/chains/goat/GoatChainType.ts +5 -5
- package/src/chains/goat/GoatInitializer.ts +3 -25
- package/src/evm/btcrelay/EVMBtcRelay.ts +54 -22
- package/src/evm/btcrelay/headers/EVMBtcHeader.ts +60 -13
- package/src/evm/btcrelay/headers/EVMBtcStoredHeader.ts +55 -10
- package/src/evm/chain/EVMChainInterface.ts +66 -14
- package/src/evm/chain/EVMModule.ts +6 -1
- package/src/evm/chain/modules/EVMBlocks.ts +7 -0
- package/src/evm/chain/modules/EVMEvents.ts +19 -19
- package/src/evm/chain/modules/EVMFees.ts +41 -5
- package/src/evm/chain/modules/EVMTokens.ts +1 -1
- package/src/evm/chain/modules/EVMTransactions.ts +27 -8
- package/src/evm/contract/EVMContractBase.ts +29 -24
- package/src/evm/contract/EVMContractModule.ts +5 -0
- package/src/evm/contract/modules/EVMContractEvents.ts +27 -8
- package/src/evm/events/EVMChainEvents.ts +8 -0
- package/src/evm/events/EVMChainEventsBrowser.ts +103 -29
- package/src/evm/providers/JsonRpcProviderWithRetries.ts +10 -1
- package/src/evm/providers/ReconnectingWebSocketProvider.ts +6 -1
- package/src/evm/providers/WebSocketProviderWithRetries.ts +10 -1
- package/src/evm/spv_swap/EVMSpvVaultContract.ts +72 -32
- package/src/evm/spv_swap/EVMSpvVaultData.ts +57 -2
- package/src/evm/spv_swap/EVMSpvWithdrawalData.ts +12 -0
- package/src/evm/swaps/EVMSwapContract.ts +108 -63
- package/src/evm/swaps/EVMSwapData.ts +27 -1
- package/src/evm/swaps/EVMSwapModule.ts +5 -0
- package/src/evm/swaps/handlers/IHandler.ts +5 -0
- package/src/evm/swaps/handlers/claim/ClaimHandlers.ts +15 -0
- package/src/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +5 -0
- package/src/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +10 -0
- package/src/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +5 -0
- package/src/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +17 -2
- package/src/evm/swaps/modules/EVMLpVault.ts +10 -5
- package/src/evm/swaps/modules/EVMSwapClaim.ts +12 -7
- package/src/evm/swaps/modules/EVMSwapInit.ts +17 -7
- package/src/evm/swaps/modules/EVMSwapRefund.ts +9 -4
- package/src/evm/wallet/EVMBrowserSigner.ts +44 -5
- package/src/evm/wallet/EVMPersistentSigner.ts +14 -2
- package/src/evm/wallet/EVMSigner.ts +37 -1
- package/src/index.ts +72 -0
- package/src/node/index.ts +10 -0
- package/src/utils/Utils.ts +50 -1
|
@@ -13,23 +13,39 @@ type KeysOfType<T, ValueType> = keyof {
|
|
|
13
13
|
[K in keyof T]: T[K] extends ValueType ? K : never;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Typed transaction call decoded from calldata for a specific contract method.
|
|
18
|
+
*
|
|
19
|
+
* @category Internal/Contracts
|
|
20
|
+
*/
|
|
16
21
|
export interface TypedFunctionCall<TCMethod extends TypedContractMethod>
|
|
17
22
|
extends Omit<TransactionDescription, "args"> {
|
|
18
23
|
args: __TypechainOutputObject<TCMethod>;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
/**
|
|
22
|
-
* Base
|
|
27
|
+
* Base contract wrapper providing typed event and calldata parsing helpers.
|
|
28
|
+
*
|
|
29
|
+
* @category Internal/Contracts
|
|
23
30
|
*/
|
|
24
31
|
export class EVMContractBase<T extends BaseContract> {
|
|
25
32
|
|
|
26
|
-
contract: T;
|
|
33
|
+
readonly contract: T;
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
readonly _Events: EVMContractEvents<T>;
|
|
39
|
+
protected readonly Chain: EVMChainInterface<any>;
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
readonly _contractAddress: string;
|
|
45
|
+
/**
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
readonly _contractDeploymentHeight?: number;
|
|
33
49
|
|
|
34
50
|
constructor(
|
|
35
51
|
chainInterface: EVMChainInterface<any>,
|
|
@@ -39,26 +55,15 @@ export class EVMContractBase<T extends BaseContract> {
|
|
|
39
55
|
) {
|
|
40
56
|
this.Chain = chainInterface;
|
|
41
57
|
this.contract = new Contract(contractAddress, contractAbi, chainInterface.provider) as unknown as T;
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
44
|
-
this.
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
toTypedEvent<TEventName extends keyof T["filters"] = keyof T["filters"]>(log: Log): TypedEventLog<T["filters"][TEventName]> | null {
|
|
48
|
-
let foundFragment: EventFragment | null = null;
|
|
49
|
-
try {
|
|
50
|
-
foundFragment = this.contract.interface.getEvent(log.topics[0]);
|
|
51
|
-
} catch (error) { }
|
|
52
|
-
if(!foundFragment) return null;
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
return new EventLog(log, this.contract.interface, foundFragment) as unknown as TypedEventLog<T["filters"][TEventName]>;
|
|
56
|
-
} catch (error: any) { }
|
|
57
|
-
|
|
58
|
-
return null;
|
|
58
|
+
this._Events = new EVMContractEvents<T>(chainInterface, this);
|
|
59
|
+
this._contractAddress = contractAddress;
|
|
60
|
+
this._contractDeploymentHeight = contractDeploymentHeight;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
/**
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
protected parseCalldata<TMethod extends TypedContractMethod>(calldata: string): TypedFunctionCall<TMethod> {
|
|
62
67
|
return this.contract.interface.parseTransaction({data: calldata}) as unknown as TypedFunctionCall<TMethod>;
|
|
63
68
|
}
|
|
64
69
|
|
|
@@ -4,6 +4,11 @@ import {EVMChainInterface} from "../chain/EVMChainInterface";
|
|
|
4
4
|
import {EVMContractBase} from "./EVMContractBase";
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Base module class for EVM components tied to a specific contract wrapper.
|
|
9
|
+
*
|
|
10
|
+
* @category Internal/Contracts
|
|
11
|
+
*/
|
|
7
12
|
export class EVMContractModule<T extends BaseContract, C extends EVMContractBase<T> = EVMContractBase<T>> extends EVMModule<any> {
|
|
8
13
|
|
|
9
14
|
readonly contract: C;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {BaseContract, Log} from "ethers";
|
|
1
|
+
import {BaseContract, EventFragment, EventLog, Log} from "ethers";
|
|
2
2
|
import {EVMEvents} from "../../chain/modules/EVMEvents";
|
|
3
|
-
import {EVMContractBase} from "../EVMContractBase";
|
|
3
|
+
import {EVMContractBase, TypedFunctionCall} from "../EVMContractBase";
|
|
4
4
|
import {EVMChainInterface} from "../../chain/EVMChainInterface";
|
|
5
|
-
import {TypedEventLog} from "../../typechain/common";
|
|
5
|
+
import {TypedContractMethod, TypedEventLog} from "../../typechain/common";
|
|
6
6
|
|
|
7
7
|
function normalizeTopic(topic: string) {
|
|
8
8
|
if(topic.length!==66) {
|
|
@@ -12,9 +12,14 @@ function normalizeTopic(topic: string) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Typed contract event utilities built on top of generic EVM log querying helpers.
|
|
17
|
+
*
|
|
18
|
+
* @category Internal/Contracts
|
|
19
|
+
*/
|
|
15
20
|
export class EVMContractEvents<T extends BaseContract> extends EVMEvents {
|
|
16
21
|
|
|
17
|
-
readonly contract: EVMContractBase<T>;
|
|
22
|
+
private readonly contract: EVMContractBase<T>;
|
|
18
23
|
readonly baseContract: T;
|
|
19
24
|
|
|
20
25
|
constructor(chainInterface: EVMChainInterface<any>, contract: EVMContractBase<T>) {
|
|
@@ -23,8 +28,22 @@ export class EVMContractEvents<T extends BaseContract> extends EVMEvents {
|
|
|
23
28
|
this.baseContract = contract.contract;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
private toTypedEvent<TEventName extends keyof T["filters"] = keyof T["filters"]>(log: Log): TypedEventLog<T["filters"][TEventName]> | null {
|
|
32
|
+
let foundFragment: EventFragment | null = null;
|
|
33
|
+
try {
|
|
34
|
+
foundFragment = this.baseContract.interface.getEvent(log.topics[0]);
|
|
35
|
+
} catch (error) { }
|
|
36
|
+
if(!foundFragment) return null;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
return new EventLog(log, this.baseContract.interface, foundFragment) as unknown as TypedEventLog<T["filters"][TEventName]>;
|
|
40
|
+
} catch (error: any) { }
|
|
41
|
+
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
toTypedEvents<TEventName extends keyof T["filters"]>(blockEvents: Log[]): (TypedEventLog<T["filters"][TEventName]> | null)[] {
|
|
46
|
+
return blockEvents.map(log => this.toTypedEvent<TEventName>(log));
|
|
28
47
|
}
|
|
29
48
|
|
|
30
49
|
private toFilter<TEventName extends keyof T["filters"]>(
|
|
@@ -83,7 +102,7 @@ export class EVMContractEvents<T extends BaseContract> extends EVMEvents {
|
|
|
83
102
|
if(result!=null) return result;
|
|
84
103
|
}
|
|
85
104
|
return null;
|
|
86
|
-
}, abortSignal, this.contract.
|
|
105
|
+
}, abortSignal, this.contract._contractDeploymentHeight);
|
|
87
106
|
}
|
|
88
107
|
|
|
89
108
|
/**
|
|
@@ -111,7 +130,7 @@ export class EVMContractEvents<T extends BaseContract> extends EVMEvents {
|
|
|
111
130
|
if(result!=null) return result;
|
|
112
131
|
}
|
|
113
132
|
return null;
|
|
114
|
-
}, abortSignal, Math.max(this.contract.
|
|
133
|
+
}, abortSignal, Math.max(this.contract._contractDeploymentHeight ?? 0, startHeight ?? 0));
|
|
115
134
|
}
|
|
116
135
|
|
|
117
136
|
}
|
|
@@ -6,6 +6,11 @@ import {EVMSwapContract} from "../swaps/EVMSwapContract";
|
|
|
6
6
|
import {EVMSpvVaultContract} from "../spv_swap/EVMSpvVaultContract";
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Backend event listener with persisted polling cursor stored on filesystem.
|
|
11
|
+
*
|
|
12
|
+
* @category Events
|
|
13
|
+
*/
|
|
9
14
|
export class EVMChainEvents extends EVMChainEventsBrowser {
|
|
10
15
|
|
|
11
16
|
private readonly directory: string;
|
|
@@ -77,6 +82,9 @@ export class EVMChainEvents extends EVMChainEventsBrowser {
|
|
|
77
82
|
}).join(";"));
|
|
78
83
|
}
|
|
79
84
|
|
|
85
|
+
/**
|
|
86
|
+
* @inheritDoc
|
|
87
|
+
*/
|
|
80
88
|
async init(noAutomaticPoll?: boolean): Promise<void> {
|
|
81
89
|
if(noAutomaticPoll) return Promise.resolve();
|
|
82
90
|
this.stopped = false;
|
|
@@ -24,6 +24,12 @@ const LOGS_SLIDING_WINDOW_LENGTH = 60;
|
|
|
24
24
|
|
|
25
25
|
const PROCESSED_EVENTS_BACKLOG = 1000;
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Current state of the EVM event listener, containing the last processed block number
|
|
29
|
+
* and event position.
|
|
30
|
+
*
|
|
31
|
+
* @category Events
|
|
32
|
+
*/
|
|
27
33
|
export type EVMEventListenerState = {lastBlockNumber: number, lastEvent?: {blockHash: string, logIndex: number}} | null;
|
|
28
34
|
|
|
29
35
|
type AtomiqTypedEvent = (
|
|
@@ -35,6 +41,8 @@ type AtomiqTypedEvent = (
|
|
|
35
41
|
* EVM on-chain event handler for front-end systems without access to fs, uses WS or long-polling to subscribe, might lose
|
|
36
42
|
* out on some events if the network is unreliable, front-end systems should take this into consideration and not
|
|
37
43
|
* rely purely on events
|
|
44
|
+
*
|
|
45
|
+
* @category Events
|
|
38
46
|
*/
|
|
39
47
|
export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventListenerState[]> {
|
|
40
48
|
|
|
@@ -44,23 +52,59 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
44
52
|
private processedEvents: string[] = [];
|
|
45
53
|
private processedEventsIndex: number = 0;
|
|
46
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
47
58
|
protected readonly listeners: EventListener<EVMSwapData>[] = [];
|
|
59
|
+
/**
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
48
62
|
protected readonly provider: JsonRpcApiProvider;
|
|
63
|
+
/**
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
49
66
|
protected readonly chainInterface: EVMChainInterface;
|
|
67
|
+
/**
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
50
70
|
protected readonly evmSwapContract: EVMSwapContract;
|
|
71
|
+
/**
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
51
74
|
protected readonly evmSpvVaultContract: EVMSpvVaultContract<any>;
|
|
75
|
+
/**
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
52
78
|
protected readonly logger = getLogger("EVMChainEventsBrowser: ");
|
|
53
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
54
83
|
protected stopped: boolean = true;
|
|
84
|
+
/**
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
55
87
|
protected pollIntervalSeconds: number;
|
|
56
88
|
|
|
57
89
|
private timeout?: any;
|
|
58
90
|
|
|
59
91
|
//Websocket
|
|
92
|
+
/**
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
60
95
|
protected readonly spvVaultContractLogFilter: EventFilter;
|
|
96
|
+
/**
|
|
97
|
+
* @internal
|
|
98
|
+
*/
|
|
61
99
|
protected readonly swapContractLogFilter: EventFilter;
|
|
62
100
|
|
|
101
|
+
/**
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
63
104
|
protected unconfirmedEventQueue: AtomiqTypedEvent[] = [];
|
|
105
|
+
/**
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
64
108
|
protected confirmedEventQueue: {event: AtomiqTypedEvent, block: Block}[] = [];
|
|
65
109
|
|
|
66
110
|
constructor(
|
|
@@ -76,10 +120,10 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
76
120
|
this.pollIntervalSeconds = pollIntervalSeconds;
|
|
77
121
|
|
|
78
122
|
this.spvVaultContractLogFilter = {
|
|
79
|
-
address: this.evmSpvVaultContract.
|
|
123
|
+
address: this.evmSpvVaultContract._contractAddress
|
|
80
124
|
};
|
|
81
125
|
this.swapContractLogFilter = {
|
|
82
|
-
address: this.evmSwapContract.
|
|
126
|
+
address: this.evmSwapContract._contractAddress
|
|
83
127
|
};
|
|
84
128
|
}
|
|
85
129
|
|
|
@@ -112,12 +156,12 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
112
156
|
}
|
|
113
157
|
}
|
|
114
158
|
|
|
115
|
-
|
|
159
|
+
private parseInitializeEvent(
|
|
116
160
|
event: TypedEventLog<EscrowManager["filters"]["Initialize"]>
|
|
117
161
|
): InitializeEvent<EVMSwapData> | null {
|
|
118
162
|
const escrowHash = event.args.escrowHash.substring(2);
|
|
119
163
|
const claimHandlerHex = event.args.claimHandler;
|
|
120
|
-
const claimHandler = this.evmSwapContract.
|
|
164
|
+
const claimHandler = this.evmSwapContract._claimHandlersByAddress[claimHandlerHex.toLowerCase()];
|
|
121
165
|
if(claimHandler==null) {
|
|
122
166
|
this.logger.warn("parseInitializeEvent("+escrowHash+"): Unknown claim handler with claim: "+claimHandlerHex);
|
|
123
167
|
return null;
|
|
@@ -132,7 +176,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
132
176
|
);
|
|
133
177
|
}
|
|
134
178
|
|
|
135
|
-
|
|
179
|
+
private parseRefundEvent(
|
|
136
180
|
event: TypedEventLog<EscrowManager["filters"]["Refund"]>
|
|
137
181
|
): RefundEvent<EVMSwapData> {
|
|
138
182
|
const escrowHash = event.args.escrowHash.substring(2);
|
|
@@ -140,12 +184,12 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
140
184
|
return new RefundEvent<EVMSwapData>(escrowHash);
|
|
141
185
|
}
|
|
142
186
|
|
|
143
|
-
|
|
187
|
+
private parseClaimEvent(
|
|
144
188
|
event: TypedEventLog<EscrowManager["filters"]["Claim"]>
|
|
145
189
|
): ClaimEvent<EVMSwapData> | null {
|
|
146
190
|
const escrowHash = event.args.escrowHash.substring(2);
|
|
147
191
|
const claimHandlerHex = event.args.claimHandler;
|
|
148
|
-
const claimHandler = this.evmSwapContract.
|
|
192
|
+
const claimHandler = this.evmSwapContract._claimHandlersByAddress[claimHandlerHex.toLowerCase()];
|
|
149
193
|
if(claimHandler==null) {
|
|
150
194
|
this.logger.warn("parseClaimEvent("+escrowHash+"): Unknown claim handler with claim: "+claimHandlerHex);
|
|
151
195
|
return null;
|
|
@@ -155,7 +199,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
155
199
|
return new ClaimEvent<EVMSwapData>(escrowHash, witnessResult);
|
|
156
200
|
}
|
|
157
201
|
|
|
158
|
-
|
|
202
|
+
private parseSpvOpenEvent(
|
|
159
203
|
event: TypedEventLog<SpvVaultManager["filters"]["Opened"]>
|
|
160
204
|
): SpvVaultOpenEvent {
|
|
161
205
|
const owner = event.args.owner;
|
|
@@ -167,7 +211,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
167
211
|
return new SpvVaultOpenEvent(owner, vaultId, btcTxId, vout);
|
|
168
212
|
}
|
|
169
213
|
|
|
170
|
-
|
|
214
|
+
private parseSpvDepositEvent(
|
|
171
215
|
event: TypedEventLog<SpvVaultManager["filters"]["Deposited"]>
|
|
172
216
|
): SpvVaultDepositEvent {
|
|
173
217
|
const [owner, vaultId] = unpackOwnerAndVaultId(event.args.ownerAndVaultId);
|
|
@@ -178,7 +222,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
178
222
|
return new SpvVaultDepositEvent(owner, vaultId, amounts, depositCount);
|
|
179
223
|
}
|
|
180
224
|
|
|
181
|
-
|
|
225
|
+
private parseSpvFrontEvent(
|
|
182
226
|
event: TypedEventLog<SpvVaultManager["filters"]["Fronted"]>
|
|
183
227
|
): SpvVaultFrontEvent {
|
|
184
228
|
const [owner, vaultId] = unpackOwnerAndVaultId(event.args.ownerAndVaultId);
|
|
@@ -193,7 +237,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
193
237
|
return new SpvVaultFrontEvent(owner, vaultId, btcTxId, recipient, executionHash, amounts, frontingAddress);
|
|
194
238
|
}
|
|
195
239
|
|
|
196
|
-
|
|
240
|
+
private parseSpvClaimEvent(
|
|
197
241
|
event: TypedEventLog<SpvVaultManager["filters"]["Claimed"]>
|
|
198
242
|
): SpvVaultClaimEvent {
|
|
199
243
|
const [owner, vaultId] = unpackOwnerAndVaultId(event.args.ownerAndVaultId);
|
|
@@ -211,7 +255,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
211
255
|
return new SpvVaultClaimEvent(owner, vaultId, btcTxId, recipient, executionHash, amounts, caller, frontingAddress, withdrawCount);
|
|
212
256
|
}
|
|
213
257
|
|
|
214
|
-
|
|
258
|
+
private parseSpvCloseEvent(
|
|
215
259
|
event: TypedEventLog<SpvVaultManager["filters"]["Closed"]>
|
|
216
260
|
): SpvVaultCloseEvent {
|
|
217
261
|
const btcTxId = Buffer.from(event.args.btcTxHash.substring(2), "hex").reverse().toString("hex");
|
|
@@ -226,7 +270,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
226
270
|
* @param currentBlock
|
|
227
271
|
* @protected
|
|
228
272
|
*/
|
|
229
|
-
|
|
273
|
+
private async processEvents(
|
|
230
274
|
events : (
|
|
231
275
|
TypedEventLog<EscrowManager["filters"]["Initialize" | "Refund" | "Claim"]> |
|
|
232
276
|
TypedEventLog<SpvVaultManager["filters"]["Opened" | "Deposited" | "Fronted" | "Claimed" | "Closed"]>
|
|
@@ -300,7 +344,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
300
344
|
}
|
|
301
345
|
}
|
|
302
346
|
|
|
303
|
-
|
|
347
|
+
private async checkEventsEcrowManager(
|
|
304
348
|
currentBlock: Block,
|
|
305
349
|
lastEvent?: {blockHash: string, logIndex: number},
|
|
306
350
|
lastBlockNumber?: number
|
|
@@ -311,7 +355,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
311
355
|
return {lastEvent, lastBlockNumber};
|
|
312
356
|
}
|
|
313
357
|
// this.logger.debug(`checkEvents(EscrowManager): Requesting logs: ${lastBlockNumber}...${currentBlock.number}`);
|
|
314
|
-
let events = await this.evmSwapContract.
|
|
358
|
+
let events = await this.evmSwapContract._Events.getContractBlockEvents(
|
|
315
359
|
["Initialize", "Claim", "Refund"],
|
|
316
360
|
[],
|
|
317
361
|
lastBlockNumber,
|
|
@@ -341,7 +385,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
341
385
|
return {lastEvent, lastBlockNumber};
|
|
342
386
|
}
|
|
343
387
|
|
|
344
|
-
|
|
388
|
+
private async checkEventsSpvVaults(
|
|
345
389
|
currentBlock: Block,
|
|
346
390
|
lastEvent?: {blockHash: string, logIndex: number},
|
|
347
391
|
lastBlockNumber?: number
|
|
@@ -352,7 +396,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
352
396
|
return {lastEvent, lastBlockNumber};
|
|
353
397
|
}
|
|
354
398
|
// this.logger.debug(`checkEvents(SpvVaults): Requesting logs: ${lastBlockNumber}...${currentBlock.number}`);
|
|
355
|
-
let events = await this.evmSpvVaultContract.
|
|
399
|
+
let events = await this.evmSpvVaultContract._Events.getContractBlockEvents(
|
|
356
400
|
["Opened", "Deposited", "Closed", "Fronted", "Claimed"],
|
|
357
401
|
[],
|
|
358
402
|
lastBlockNumber,
|
|
@@ -388,8 +432,8 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
388
432
|
async poll(lastState?: EVMEventListenerState[]): Promise<EVMEventListenerState[]> {
|
|
389
433
|
lastState ??= [];
|
|
390
434
|
|
|
391
|
-
const currentBlock = await this.provider.getBlock(this.chainInterface.
|
|
392
|
-
if(currentBlock==null) throw new Error(`Cannot fetch '${this.chainInterface.
|
|
435
|
+
const currentBlock = await this.provider.getBlock(this.chainInterface._config.safeBlockTag, false);
|
|
436
|
+
if(currentBlock==null) throw new Error(`Cannot fetch '${this.chainInterface._config.safeBlockTag}' block!`);
|
|
393
437
|
|
|
394
438
|
const resultEscrow = await this.checkEventsEcrowManager(currentBlock, lastState?.[0]?.lastEvent, lastState?.[0]?.lastBlockNumber);
|
|
395
439
|
const resultSpvVault = await this.checkEventsSpvVaults(currentBlock, lastState?.[1]?.lastEvent, lastState?.[1]?.lastBlockNumber);
|
|
@@ -405,7 +449,7 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
405
449
|
/**
|
|
406
450
|
* Sets up event handlers listening for swap events over websocket
|
|
407
451
|
*
|
|
408
|
-
* @
|
|
452
|
+
* @internal
|
|
409
453
|
*/
|
|
410
454
|
protected async setupPoll(
|
|
411
455
|
lastState?: EVMEventListenerState[],
|
|
@@ -428,26 +472,47 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
428
472
|
|
|
429
473
|
//Websocket
|
|
430
474
|
|
|
475
|
+
/**
|
|
476
|
+
* @internal
|
|
477
|
+
*/
|
|
431
478
|
protected handleWsEvent(
|
|
432
479
|
event: AtomiqTypedEvent
|
|
433
480
|
): Promise<void> {
|
|
434
|
-
if(this.chainInterface.
|
|
481
|
+
if(this.chainInterface._config.safeBlockTag==="latest" || this.chainInterface._config.safeBlockTag==="pending") {
|
|
435
482
|
return this.processEvents([event]);
|
|
436
483
|
}
|
|
437
484
|
this.unconfirmedEventQueue.push(event);
|
|
438
485
|
return this.addOrRemoveBlockListener();
|
|
439
486
|
}
|
|
440
487
|
|
|
488
|
+
/**
|
|
489
|
+
* @internal
|
|
490
|
+
*/
|
|
441
491
|
protected spvVaultContractListener?: (log: Log) => void;
|
|
492
|
+
/**
|
|
493
|
+
* @internal
|
|
494
|
+
*/
|
|
442
495
|
protected swapContractListener?: (log: Log) => void;
|
|
496
|
+
/**
|
|
497
|
+
* @internal
|
|
498
|
+
*/
|
|
443
499
|
protected blockListener?: (blockNumber: number) => Promise<void>;
|
|
500
|
+
/**
|
|
501
|
+
* @internal
|
|
502
|
+
*/
|
|
444
503
|
protected finalityCheckTimer: any;
|
|
504
|
+
/**
|
|
505
|
+
* @internal
|
|
506
|
+
*/
|
|
445
507
|
protected wsStarted: boolean = false;
|
|
446
508
|
|
|
509
|
+
/**
|
|
510
|
+
* @internal
|
|
511
|
+
*/
|
|
447
512
|
protected async checkUnconfirmedEventsFinality() {
|
|
448
513
|
if(this.unconfirmedEventQueue.length>0) {
|
|
449
|
-
const latestSafeBlock = await this.provider.getBlock(this.chainInterface.
|
|
450
|
-
if(latestSafeBlock==null) throw new Error(`Failed to fetch '${this.chainInterface.
|
|
514
|
+
const latestSafeBlock = await this.provider.getBlock(this.chainInterface._config.safeBlockTag);
|
|
515
|
+
if(latestSafeBlock==null) throw new Error(`Failed to fetch '${this.chainInterface._config.safeBlockTag}' block!`);
|
|
451
516
|
|
|
452
517
|
const events = this.unconfirmedEventQueue.filter(event => {
|
|
453
518
|
return event.blockNumber <= latestSafeBlock.number;
|
|
@@ -473,8 +538,11 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
473
538
|
}
|
|
474
539
|
}
|
|
475
540
|
|
|
541
|
+
/**
|
|
542
|
+
* @internal
|
|
543
|
+
*/
|
|
476
544
|
protected async addOrRemoveBlockListener() {
|
|
477
|
-
if(this.chainInterface.
|
|
545
|
+
if(this.chainInterface._config.finalityCheckStrategy?.type!=="blocks") return;
|
|
478
546
|
if(this.unconfirmedEventQueue.length>0 || this.confirmedEventQueue.length>0) {
|
|
479
547
|
this.logger.debug(`addOrRemoveBlockListener(): Adding block listener, unconfirmed/confirmed event count: ${this.unconfirmedEventQueue.length + this.confirmedEventQueue.length}`);
|
|
480
548
|
await this.provider.on("block", this.blockListener!);
|
|
@@ -484,6 +552,9 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
484
552
|
}
|
|
485
553
|
}
|
|
486
554
|
|
|
555
|
+
/**
|
|
556
|
+
* @internal
|
|
557
|
+
*/
|
|
487
558
|
protected async startFinalityCheckTimer() {
|
|
488
559
|
let check: () => Promise<void>;
|
|
489
560
|
check = async () => {
|
|
@@ -496,11 +567,14 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
496
567
|
}
|
|
497
568
|
}
|
|
498
569
|
if(!this.wsStarted) return;
|
|
499
|
-
this.finalityCheckTimer = setTimeout(check, this.chainInterface.
|
|
570
|
+
this.finalityCheckTimer = setTimeout(check, this.chainInterface._config.finalityCheckStrategy?.delayMs ?? 5*1000);
|
|
500
571
|
};
|
|
501
572
|
await check();
|
|
502
573
|
}
|
|
503
574
|
|
|
575
|
+
/**
|
|
576
|
+
* @internal
|
|
577
|
+
*/
|
|
504
578
|
protected async setupWebsocket() {
|
|
505
579
|
this.wsStarted = true;
|
|
506
580
|
|
|
@@ -518,18 +592,18 @@ export class EVMChainEventsBrowser implements ChainEvents<EVMSwapData, EVMEventL
|
|
|
518
592
|
await this.addOrRemoveBlockListener();
|
|
519
593
|
}
|
|
520
594
|
|
|
521
|
-
if(this.chainInterface.
|
|
522
|
-
if(this.chainInterface.
|
|
595
|
+
if(this.chainInterface._config.safeBlockTag==="safe" || this.chainInterface._config.safeBlockTag==="finalized") {
|
|
596
|
+
if(this.chainInterface._config.finalityCheckStrategy?.type==="timer") this.startFinalityCheckTimer();
|
|
523
597
|
}
|
|
524
598
|
|
|
525
599
|
await this.provider.on(this.spvVaultContractLogFilter, this.spvVaultContractListener = (log) => {
|
|
526
|
-
let [event] = this.evmSpvVaultContract.
|
|
600
|
+
let [event] = this.evmSpvVaultContract._Events.toTypedEvents([log]);
|
|
527
601
|
if(event==null || event.removed) return;
|
|
528
602
|
this.handleWsEvent(event);
|
|
529
603
|
});
|
|
530
604
|
|
|
531
605
|
await this.provider.on(this.swapContractLogFilter, this.swapContractListener = (log) => {
|
|
532
|
-
let [event] = this.evmSwapContract.
|
|
606
|
+
let [event] = this.evmSwapContract._Events.toTypedEvents([log]);
|
|
533
607
|
if(event==null || event.removed) return;
|
|
534
608
|
if(event.eventName!=="Initialize" && event.eventName!=="Refund" && event.eventName!=="Claim") return;
|
|
535
609
|
this.handleWsEvent(event);
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
} from "../../utils/Utils";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
+
* JSON-RPC provider with built-in retry functionality for transient RPC failures.
|
|
12
|
+
*
|
|
11
13
|
* @category Providers
|
|
12
14
|
*/
|
|
13
15
|
export class JsonRpcProviderWithRetries extends JsonRpcProvider {
|
|
@@ -16,6 +18,13 @@ export class JsonRpcProviderWithRetries extends JsonRpcProvider {
|
|
|
16
18
|
maxRetries?: number, delay?: number, exponential?: boolean
|
|
17
19
|
};
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new JSON-RPC provider which retries RPC calls based on the provided policy.
|
|
23
|
+
*
|
|
24
|
+
* @param url
|
|
25
|
+
* @param network
|
|
26
|
+
* @param options
|
|
27
|
+
*/
|
|
19
28
|
constructor(url: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions & {
|
|
20
29
|
maxRetries?: number, delay?: number, exponential?: boolean, timeout?: number
|
|
21
30
|
}) {
|
|
@@ -34,4 +43,4 @@ export class JsonRpcProviderWithRetries extends JsonRpcProvider {
|
|
|
34
43
|
});
|
|
35
44
|
}
|
|
36
45
|
|
|
37
|
-
}
|
|
46
|
+
}
|
|
@@ -5,6 +5,11 @@ import {getLogger} from "../../utils/Utils";
|
|
|
5
5
|
|
|
6
6
|
const logger = getLogger("ReconnectingWebSocketProvider: ");
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* WebSocket RPC provider with automatic reconnect, heartbeat ping and connection timeout handling.
|
|
10
|
+
*
|
|
11
|
+
* @category Providers
|
|
12
|
+
*/
|
|
8
13
|
export class ReconnectingWebSocketProvider extends SocketProvider {
|
|
9
14
|
|
|
10
15
|
requestTimeoutSeconds: number = 10;
|
|
@@ -105,4 +110,4 @@ export class ReconnectingWebSocketProvider extends SocketProvider {
|
|
|
105
110
|
super.destroy();
|
|
106
111
|
}
|
|
107
112
|
|
|
108
|
-
}
|
|
113
|
+
}
|
|
@@ -10,6 +10,8 @@ import {ReconnectingWebSocketProvider} from "./ReconnectingWebSocketProvider";
|
|
|
10
10
|
import type {WebSocketLike} from "ethers/lib.esm";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
+
* WebSocket RPC provider with reconnect support and retry logic for transient RPC failures.
|
|
14
|
+
*
|
|
13
15
|
* @category Providers
|
|
14
16
|
*/
|
|
15
17
|
export class WebSocketProviderWithRetries extends ReconnectingWebSocketProvider {
|
|
@@ -18,6 +20,13 @@ export class WebSocketProviderWithRetries extends ReconnectingWebSocketProvider
|
|
|
18
20
|
maxRetries?: number, delay?: number, exponential?: boolean
|
|
19
21
|
};
|
|
20
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new WebSocket provider which retries RPC calls based on the provided policy.
|
|
25
|
+
*
|
|
26
|
+
* @param url
|
|
27
|
+
* @param network
|
|
28
|
+
* @param options
|
|
29
|
+
*/
|
|
21
30
|
constructor(url: string | (() => WebSocketLike), network?: Networkish, options?: JsonRpcApiProviderOptions & {
|
|
22
31
|
maxRetries?: number, delay?: number, exponential?: boolean
|
|
23
32
|
}) {
|
|
@@ -34,4 +43,4 @@ export class WebSocketProviderWithRetries extends ReconnectingWebSocketProvider
|
|
|
34
43
|
});
|
|
35
44
|
}
|
|
36
45
|
|
|
37
|
-
}
|
|
46
|
+
}
|