@hyperlane-xyz/sdk 16.0.0 → 16.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/block-explorer/etherscan.d.ts +1 -12
- package/dist/block-explorer/etherscan.d.ts.map +1 -1
- package/dist/block-explorer/etherscan.js +14 -2
- package/dist/block-explorer/etherscan.js.map +1 -1
- package/dist/block-explorer/utils.d.ts +3 -0
- package/dist/block-explorer/utils.d.ts.map +1 -0
- package/dist/block-explorer/utils.js +16 -0
- package/dist/block-explorer/utils.js.map +1 -0
- package/dist/consts/testChains.d.ts +2 -0
- package/dist/consts/testChains.d.ts.map +1 -1
- package/dist/consts/testChains.js +36 -1
- package/dist/consts/testChains.js.map +1 -1
- package/dist/contracts/contracts.d.ts +9 -1
- package/dist/contracts/contracts.d.ts.map +1 -1
- package/dist/contracts/contracts.js +15 -1
- package/dist/contracts/contracts.js.map +1 -1
- package/dist/deploy/verify/ContractVerifier.d.ts.map +1 -1
- package/dist/deploy/verify/ContractVerifier.js +16 -5
- package/dist/deploy/verify/ContractVerifier.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/metadata/ChainMetadataManager.d.ts +10 -0
- package/dist/metadata/ChainMetadataManager.d.ts.map +1 -1
- package/dist/metadata/ChainMetadataManager.js +33 -2
- package/dist/metadata/ChainMetadataManager.js.map +1 -1
- package/dist/metadata/blockExplorer.d.ts.map +1 -1
- package/dist/metadata/blockExplorer.js +27 -1
- package/dist/metadata/blockExplorer.js.map +1 -1
- package/dist/metadata/blockExplorer.test.js +176 -1
- package/dist/metadata/blockExplorer.test.js.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5TimelockSubmitter.d.ts.map +1 -1
- package/dist/providers/transactions/submitter/ethersV5/EV5TimelockSubmitter.js +3 -3
- package/dist/providers/transactions/submitter/ethersV5/EV5TimelockSubmitter.js.map +1 -1
- package/dist/rpc/evm/EvmEventLogsReader.d.ts +79 -0
- package/dist/rpc/evm/EvmEventLogsReader.d.ts.map +1 -0
- package/dist/rpc/evm/EvmEventLogsReader.hardhat-test.d.ts +2 -0
- package/dist/rpc/evm/EvmEventLogsReader.hardhat-test.d.ts.map +1 -0
- package/dist/rpc/evm/EvmEventLogsReader.hardhat-test.js +279 -0
- package/dist/rpc/evm/EvmEventLogsReader.hardhat-test.js.map +1 -0
- package/dist/rpc/evm/EvmEventLogsReader.js +107 -0
- package/dist/rpc/evm/EvmEventLogsReader.js.map +1 -0
- package/dist/rpc/evm/types.d.ts +11 -0
- package/dist/rpc/evm/types.d.ts.map +1 -0
- package/dist/rpc/evm/types.js +2 -0
- package/dist/rpc/evm/types.js.map +1 -0
- package/dist/rpc/evm/utils.d.ts +18 -0
- package/dist/rpc/evm/utils.d.ts.map +1 -0
- package/dist/rpc/evm/utils.hardhat-test.d.ts +2 -0
- package/dist/rpc/evm/utils.hardhat-test.d.ts.map +1 -0
- package/dist/rpc/evm/utils.hardhat-test.js +144 -0
- package/dist/rpc/evm/utils.hardhat-test.js.map +1 -0
- package/dist/rpc/evm/utils.js +67 -0
- package/dist/rpc/evm/utils.js.map +1 -0
- package/dist/timelock/evm/EvmTimelockReader.d.ts +30 -0
- package/dist/timelock/evm/EvmTimelockReader.d.ts.map +1 -0
- package/dist/timelock/evm/EvmTimelockReader.hardhat-test.d.ts +2 -0
- package/dist/timelock/evm/EvmTimelockReader.hardhat-test.d.ts.map +1 -0
- package/dist/timelock/evm/EvmTimelockReader.hardhat-test.js +649 -0
- package/dist/timelock/evm/EvmTimelockReader.hardhat-test.js.map +1 -0
- package/dist/timelock/evm/EvmTimelockReader.js +173 -0
- package/dist/timelock/evm/EvmTimelockReader.js.map +1 -0
- package/dist/timelock/evm/utils.d.ts +4 -0
- package/dist/timelock/evm/utils.d.ts.map +1 -0
- package/dist/timelock/evm/utils.js +11 -0
- package/dist/timelock/evm/utils.js.map +1 -0
- package/dist/timelock/types.d.ts +11 -0
- package/dist/timelock/types.d.ts.map +1 -1
- package/dist/timelock/types.js.map +1 -1
- package/dist/token/checker.js +2 -2
- package/dist/token/checker.js.map +1 -1
- package/dist/token/types.d.ts +1 -1
- package/dist/token/xerc20.d.ts.map +1 -1
- package/dist/token/xerc20.js +3 -35
- package/dist/token/xerc20.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import chai, { expect } from 'chai';
|
|
2
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
3
|
+
import { ethers } from 'ethers';
|
|
4
|
+
import hre from 'hardhat';
|
|
5
|
+
import { ERC20Test__factory } from '@hyperlane-xyz/core';
|
|
6
|
+
import { assert } from '@hyperlane-xyz/utils';
|
|
7
|
+
import { KNOWN_BASE_TIMELOCK_CONTRACT, TestChainName, baseTestChain, } from '../../consts/testChains.js';
|
|
8
|
+
import { MultiProvider } from '../../providers/MultiProvider.js';
|
|
9
|
+
import { randomAddress, randomInt } from '../../test/testUtils.js';
|
|
10
|
+
import { EvmEtherscanLikeEventLogsReader, EvmEventLogsReader, EvmRpcEventLogsReader, } from './EvmEventLogsReader.js';
|
|
11
|
+
chai.use(chaiAsPromised);
|
|
12
|
+
describe('EvmEventLogsReader', () => {
|
|
13
|
+
let contractOwner;
|
|
14
|
+
let tokenRecipient1;
|
|
15
|
+
let tokenRecipient2;
|
|
16
|
+
let providerChainTest1;
|
|
17
|
+
let multiProvider;
|
|
18
|
+
let testContract;
|
|
19
|
+
let erc20Factory;
|
|
20
|
+
let deploymentBlockNumber;
|
|
21
|
+
const transferTopic = ethers.utils.id('Transfer(address,address,uint256)');
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
[contractOwner, tokenRecipient1, tokenRecipient2] =
|
|
24
|
+
await hre.ethers.getSigners();
|
|
25
|
+
assert(contractOwner.provider, 'Provider should be available');
|
|
26
|
+
// Initialize MultiProvider with test chain
|
|
27
|
+
multiProvider = MultiProvider.createTestMultiProvider({
|
|
28
|
+
signer: contractOwner,
|
|
29
|
+
provider: contractOwner.provider,
|
|
30
|
+
});
|
|
31
|
+
providerChainTest1 = contractOwner.provider;
|
|
32
|
+
// Get contract factory for ERC20Test
|
|
33
|
+
erc20Factory = new ERC20Test__factory(contractOwner);
|
|
34
|
+
});
|
|
35
|
+
async function deployTestErc20() {
|
|
36
|
+
testContract = await erc20Factory.deploy('TestToken', 'TST', ethers.utils.parseEther('1000000'), 18);
|
|
37
|
+
await testContract.deployed();
|
|
38
|
+
assert(testContract.deployTransaction.blockNumber, 'Expected the Contract deployment block number to be defined');
|
|
39
|
+
deploymentBlockNumber = testContract.deployTransaction.blockNumber;
|
|
40
|
+
}
|
|
41
|
+
async function mineRandomNumberOfBlocks() {
|
|
42
|
+
const blocksToMine = randomInt(5, 20);
|
|
43
|
+
for (let blockNum = 0; blockNum < blocksToMine; blockNum++) {
|
|
44
|
+
await providerChainTest1.send('evm_mine', []);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
describe('constructor', () => {
|
|
48
|
+
it('should initialize with BlockExplorer strategy when useRPC is false', async () => {
|
|
49
|
+
const readerWithRpc = EvmEventLogsReader.fromConfig({
|
|
50
|
+
chain: TestChainName.test1,
|
|
51
|
+
}, multiProvider);
|
|
52
|
+
// Access the private property indirectly
|
|
53
|
+
expect(readerWithRpc['logReaderStrategy']).to.be.instanceOf(EvmEtherscanLikeEventLogsReader);
|
|
54
|
+
});
|
|
55
|
+
it('should initialize with RPC strategy when useRPC is true', async () => {
|
|
56
|
+
const readerWithRpc = EvmEventLogsReader.fromConfig({
|
|
57
|
+
chain: TestChainName.test1,
|
|
58
|
+
useRPC: true,
|
|
59
|
+
}, multiProvider);
|
|
60
|
+
// Access the private property indirectly
|
|
61
|
+
expect(readerWithRpc['logReaderStrategy']).to.be.instanceOf(EvmRpcEventLogsReader);
|
|
62
|
+
});
|
|
63
|
+
it('should initialize with RPC strategy when no explorer is available', async () => {
|
|
64
|
+
const multiProviderNoExplorer = new MultiProvider({});
|
|
65
|
+
multiProviderNoExplorer.setSharedSigner(contractOwner);
|
|
66
|
+
const reader = EvmEventLogsReader.fromConfig({
|
|
67
|
+
chain: TestChainName.test1,
|
|
68
|
+
// Even when false, should use RPC if no explorer
|
|
69
|
+
useRPC: false,
|
|
70
|
+
}, multiProviderNoExplorer);
|
|
71
|
+
// Access the private property indirectly
|
|
72
|
+
expect(reader['logReaderStrategy']).to.be.instanceOf(EvmRpcEventLogsReader);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe(`${EvmEventLogsReader.prototype.getLogsByTopic.name} (rpc)`, () => {
|
|
76
|
+
let reader;
|
|
77
|
+
beforeEach(async () => {
|
|
78
|
+
await deployTestErc20();
|
|
79
|
+
reader = EvmEventLogsReader.fromConfig({
|
|
80
|
+
chain: TestChainName.test1,
|
|
81
|
+
useRPC: true,
|
|
82
|
+
paginationBlockRange: 1000,
|
|
83
|
+
}, multiProvider);
|
|
84
|
+
});
|
|
85
|
+
it('should retrieve logs for Transfer events emitted by the contract', async () => {
|
|
86
|
+
// Emit some Transfer events
|
|
87
|
+
const tx1 = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
88
|
+
await tx1.wait();
|
|
89
|
+
const tx2 = await testContract.transfer(tokenRecipient2.address, ethers.utils.parseEther('200'));
|
|
90
|
+
await tx2.wait();
|
|
91
|
+
const logs = await reader.getLogsByTopic({
|
|
92
|
+
eventTopic: transferTopic,
|
|
93
|
+
contractAddress: testContract.address,
|
|
94
|
+
fromBlock: deploymentBlockNumber,
|
|
95
|
+
});
|
|
96
|
+
// Should have 3 transfer events: 1 from constructor mint + 2 from transfers
|
|
97
|
+
expect(logs).to.have.length(3);
|
|
98
|
+
logs.forEach((log) => {
|
|
99
|
+
expect(log.address).to.equal(testContract.address);
|
|
100
|
+
expect(log.topics[0]).to.equal(transferTopic);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
it('should work when fromBlock is not specified (uses deployment block)', async () => {
|
|
104
|
+
// Emit Transfer event
|
|
105
|
+
const tx = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
106
|
+
await tx.wait();
|
|
107
|
+
const logs = await reader.getLogsByTopic({
|
|
108
|
+
eventTopic: transferTopic,
|
|
109
|
+
contractAddress: testContract.address,
|
|
110
|
+
});
|
|
111
|
+
// Should have 2 transfer events: 1 from constructor mint + 1 from transfer
|
|
112
|
+
expect(logs).to.have.length(2);
|
|
113
|
+
logs.forEach((log) => {
|
|
114
|
+
expect(log.address).to.equal(testContract.address);
|
|
115
|
+
expect(log.topics[0]).to.equal(transferTopic);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
it('should work when toBlock is not specified (uses current block)', async () => {
|
|
119
|
+
// Emit Transfer event
|
|
120
|
+
const tx = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
121
|
+
await tx.wait();
|
|
122
|
+
const logs = await reader.getLogsByTopic({
|
|
123
|
+
eventTopic: transferTopic,
|
|
124
|
+
contractAddress: testContract.address,
|
|
125
|
+
fromBlock: deploymentBlockNumber,
|
|
126
|
+
// No toBlock specified
|
|
127
|
+
});
|
|
128
|
+
// Should have 2 transfer events: 1 from constructor mint + 1 from transfer
|
|
129
|
+
expect(logs).to.have.length(2);
|
|
130
|
+
logs.forEach((log) => {
|
|
131
|
+
expect(log.address).to.equal(testContract.address);
|
|
132
|
+
expect(log.topics[0]).to.equal(transferTopic);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
it('should work when both fromBlock and toBlock are specified', async () => {
|
|
136
|
+
await mineRandomNumberOfBlocks();
|
|
137
|
+
const startBlock = await providerChainTest1.getBlockNumber();
|
|
138
|
+
// Emit event in first block
|
|
139
|
+
const tx1 = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
140
|
+
await tx1.wait();
|
|
141
|
+
const firstEventBlock = await providerChainTest1.getBlockNumber();
|
|
142
|
+
await mineRandomNumberOfBlocks();
|
|
143
|
+
// Emit event in later block
|
|
144
|
+
const tx2 = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('200'));
|
|
145
|
+
await tx2.wait();
|
|
146
|
+
// Query only the first event's block range
|
|
147
|
+
const logs = await reader.getLogsByTopic({
|
|
148
|
+
eventTopic: transferTopic,
|
|
149
|
+
contractAddress: testContract.address,
|
|
150
|
+
fromBlock: startBlock,
|
|
151
|
+
toBlock: firstEventBlock,
|
|
152
|
+
});
|
|
153
|
+
expect(logs).to.have.length(1);
|
|
154
|
+
expect(logs[0].blockNumber).to.equal(firstEventBlock);
|
|
155
|
+
expect(logs[0].address).to.equal(testContract.address);
|
|
156
|
+
expect(logs[0].topics[0]).to.equal(transferTopic);
|
|
157
|
+
});
|
|
158
|
+
it('should return empty array when no logs match the filter', async () => {
|
|
159
|
+
// Emit an event just to be sure that filtering works as expected
|
|
160
|
+
const tx = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
161
|
+
await tx.wait();
|
|
162
|
+
const nonExistentTopic = ethers.utils.id('NonExistentEvent(uint256)');
|
|
163
|
+
const logs = await reader.getLogsByTopic({
|
|
164
|
+
eventTopic: nonExistentTopic,
|
|
165
|
+
contractAddress: testContract.address,
|
|
166
|
+
fromBlock: deploymentBlockNumber,
|
|
167
|
+
});
|
|
168
|
+
expect(logs).to.have.length(0);
|
|
169
|
+
});
|
|
170
|
+
it('should handle multiple events across different blocks', async () => {
|
|
171
|
+
const numberOfEventsToEmit = randomInt(3, 10);
|
|
172
|
+
const eventBlocks = [];
|
|
173
|
+
for (let i = 0; i < numberOfEventsToEmit; i++) {
|
|
174
|
+
const tx = await testContract.mint(ethers.utils.parseEther(`${(i + 1) * 50}`));
|
|
175
|
+
await tx.wait();
|
|
176
|
+
eventBlocks.push(await providerChainTest1.getBlockNumber());
|
|
177
|
+
// Mine a few blocks between events
|
|
178
|
+
await mineRandomNumberOfBlocks();
|
|
179
|
+
}
|
|
180
|
+
// +1 because of the transfer event emitted on contract deployment
|
|
181
|
+
const expectedNumberOfEvents = numberOfEventsToEmit + 1;
|
|
182
|
+
const logs = await reader.getLogsByTopic({
|
|
183
|
+
eventTopic: transferTopic,
|
|
184
|
+
contractAddress: testContract.address,
|
|
185
|
+
fromBlock: deploymentBlockNumber,
|
|
186
|
+
});
|
|
187
|
+
expect(logs).to.have.length(expectedNumberOfEvents);
|
|
188
|
+
// Verify all logs are from the correct contract and have the right topic
|
|
189
|
+
logs.forEach((log) => {
|
|
190
|
+
expect(log.address).to.equal(testContract.address);
|
|
191
|
+
expect(log.topics[0]).to.equal(transferTopic);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
it('should work with small logPageSize (testing chunking)', async () => {
|
|
195
|
+
const readerWithSmallPageSize = EvmEventLogsReader.fromConfig({
|
|
196
|
+
chain: TestChainName.test1,
|
|
197
|
+
useRPC: true,
|
|
198
|
+
paginationBlockRange: 2,
|
|
199
|
+
}, multiProvider);
|
|
200
|
+
const numberOfEventsToEmit = 5;
|
|
201
|
+
for (let i = 0; i < numberOfEventsToEmit; i++) {
|
|
202
|
+
const tx = await testContract.mint(ethers.utils.parseEther(`${(i + 1) * 100}`));
|
|
203
|
+
await tx.wait();
|
|
204
|
+
}
|
|
205
|
+
// +1 because of the transfer event emitted on contract deployment
|
|
206
|
+
const expectedNumberOfEvents = numberOfEventsToEmit + 1;
|
|
207
|
+
const logs = await readerWithSmallPageSize.getLogsByTopic({
|
|
208
|
+
eventTopic: transferTopic,
|
|
209
|
+
contractAddress: testContract.address,
|
|
210
|
+
fromBlock: deploymentBlockNumber,
|
|
211
|
+
});
|
|
212
|
+
expect(logs).to.have.length(expectedNumberOfEvents);
|
|
213
|
+
});
|
|
214
|
+
it('should throw an error for non-existing contract address', async () => {
|
|
215
|
+
const nonExistentAddress = randomAddress();
|
|
216
|
+
await expect(reader.getLogsByTopic({
|
|
217
|
+
eventTopic: transferTopic,
|
|
218
|
+
contractAddress: nonExistentAddress,
|
|
219
|
+
fromBlock: deploymentBlockNumber,
|
|
220
|
+
})).to.be.rejected;
|
|
221
|
+
});
|
|
222
|
+
it('should handle edge case where fromBlock equals toBlock', async () => {
|
|
223
|
+
// Emit event
|
|
224
|
+
const tx = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
225
|
+
await tx.wait();
|
|
226
|
+
const eventBlock = await providerChainTest1.getBlockNumber();
|
|
227
|
+
const logs = await reader.getLogsByTopic({
|
|
228
|
+
eventTopic: transferTopic,
|
|
229
|
+
contractAddress: testContract.address,
|
|
230
|
+
fromBlock: eventBlock,
|
|
231
|
+
toBlock: eventBlock,
|
|
232
|
+
});
|
|
233
|
+
expect(logs).to.have.length(1);
|
|
234
|
+
expect(logs[0].blockNumber).to.equal(eventBlock);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
describe(`${EvmEventLogsReader.prototype.getLogsByTopic.name} (block explorer)`, () => {
|
|
238
|
+
let reader;
|
|
239
|
+
let multiProvider;
|
|
240
|
+
beforeEach(async () => {
|
|
241
|
+
await deployTestErc20();
|
|
242
|
+
multiProvider = new MultiProvider({
|
|
243
|
+
base: baseTestChain,
|
|
244
|
+
});
|
|
245
|
+
reader = EvmEventLogsReader.fromConfig({
|
|
246
|
+
chain: baseTestChain.name,
|
|
247
|
+
}, multiProvider);
|
|
248
|
+
});
|
|
249
|
+
it('should get the expected number of events when fromBlock is not provided', async () => {
|
|
250
|
+
const res = await reader.getLogsByTopic({
|
|
251
|
+
contractAddress: KNOWN_BASE_TIMELOCK_CONTRACT,
|
|
252
|
+
// CallExecuted signature
|
|
253
|
+
eventTopic: '0xc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58',
|
|
254
|
+
// Omitting from block to test getting contract deployment block from explorer
|
|
255
|
+
toBlock: 32986242,
|
|
256
|
+
});
|
|
257
|
+
expect(res.length).to.equal(5);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
describe('error handling', () => {
|
|
261
|
+
let reader;
|
|
262
|
+
beforeEach(async () => {
|
|
263
|
+
await deployTestErc20();
|
|
264
|
+
reader = EvmEventLogsReader.fromConfig({
|
|
265
|
+
chain: TestChainName.test1,
|
|
266
|
+
useRPC: true,
|
|
267
|
+
}, multiProvider);
|
|
268
|
+
});
|
|
269
|
+
it('should not allow invalid topic signatures', async () => {
|
|
270
|
+
const invalidTopic = 'invalid-topic';
|
|
271
|
+
expect(reader.getLogsByTopic({
|
|
272
|
+
eventTopic: invalidTopic,
|
|
273
|
+
contractAddress: testContract.address,
|
|
274
|
+
fromBlock: deploymentBlockNumber,
|
|
275
|
+
})).to.be.rejectedWith();
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
//# sourceMappingURL=EvmEventLogsReader.hardhat-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EvmEventLogsReader.hardhat-test.js","sourceRoot":"","sources":["../../../src/rpc/evm/EvmEventLogsReader.hardhat-test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { rootLogger } from '@hyperlane-xyz/utils';
|
|
3
|
+
import { getContractDeploymentTransaction, getLogsFromEtherscanLikeExplorerAPI, } from '../../block-explorer/etherscan.js';
|
|
4
|
+
import { assertIsContractAddress } from '../../contracts/contracts.js';
|
|
5
|
+
import { ZBytes32String, ZHash, ZUint } from '../../metadata/customZodTypes.js';
|
|
6
|
+
import { getContractCreationBlockFromRpc, getLogsFromRpc } from './utils.js';
|
|
7
|
+
export const GetLogByTopicOptionsSchema = z.object({
|
|
8
|
+
eventTopic: ZBytes32String,
|
|
9
|
+
contractAddress: ZHash,
|
|
10
|
+
fromBlock: ZUint.optional(),
|
|
11
|
+
toBlock: ZUint.optional(),
|
|
12
|
+
});
|
|
13
|
+
export const RequiredGetLogByTopicOptionsSchema = GetLogByTopicOptionsSchema.required();
|
|
14
|
+
export class EvmEtherscanLikeEventLogsReader {
|
|
15
|
+
chain;
|
|
16
|
+
config;
|
|
17
|
+
multiProvider;
|
|
18
|
+
constructor(chain, config, multiProvider) {
|
|
19
|
+
this.chain = chain;
|
|
20
|
+
this.config = config;
|
|
21
|
+
this.multiProvider = multiProvider;
|
|
22
|
+
}
|
|
23
|
+
async getContractDeploymentBlockNumber(address) {
|
|
24
|
+
const contractDeploymentTx = await getContractDeploymentTransaction({ apiUrl: this.config.apiUrl, apiKey: this.config.apiKey }, { contractAddress: address });
|
|
25
|
+
const deploymentTransactionReceipt = await this.multiProvider
|
|
26
|
+
.getProvider(this.chain)
|
|
27
|
+
.getTransactionReceipt(contractDeploymentTx.txHash);
|
|
28
|
+
return deploymentTransactionReceipt.blockNumber;
|
|
29
|
+
}
|
|
30
|
+
async getContractLogs(options) {
|
|
31
|
+
const parsedOptions = RequiredGetLogByTopicOptionsSchema.parse(options);
|
|
32
|
+
return getLogsFromEtherscanLikeExplorerAPI({
|
|
33
|
+
apiUrl: this.config.apiUrl,
|
|
34
|
+
apiKey: this.config.apiKey,
|
|
35
|
+
}, {
|
|
36
|
+
address: parsedOptions.contractAddress,
|
|
37
|
+
fromBlock: parsedOptions.fromBlock,
|
|
38
|
+
toBlock: parsedOptions.toBlock,
|
|
39
|
+
topic0: parsedOptions.eventTopic,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class EvmRpcEventLogsReader {
|
|
44
|
+
chain;
|
|
45
|
+
config;
|
|
46
|
+
multiProvider;
|
|
47
|
+
constructor(chain, config, multiProvider) {
|
|
48
|
+
this.chain = chain;
|
|
49
|
+
this.config = config;
|
|
50
|
+
this.multiProvider = multiProvider;
|
|
51
|
+
}
|
|
52
|
+
getContractDeploymentBlockNumber(address) {
|
|
53
|
+
return getContractCreationBlockFromRpc(this.chain, address, this.multiProvider);
|
|
54
|
+
}
|
|
55
|
+
getContractLogs(options) {
|
|
56
|
+
const parsedOptions = RequiredGetLogByTopicOptionsSchema.parse(options);
|
|
57
|
+
return getLogsFromRpc({
|
|
58
|
+
chain: this.chain,
|
|
59
|
+
contractAddress: parsedOptions.contractAddress,
|
|
60
|
+
topic: parsedOptions.eventTopic,
|
|
61
|
+
fromBlock: parsedOptions.fromBlock,
|
|
62
|
+
toBlock: parsedOptions.toBlock,
|
|
63
|
+
multiProvider: this.multiProvider,
|
|
64
|
+
range: this.config.paginationBlockRange,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export class EvmEventLogsReader {
|
|
69
|
+
config;
|
|
70
|
+
multiProvider;
|
|
71
|
+
logReaderStrategy;
|
|
72
|
+
logger;
|
|
73
|
+
constructor(config, multiProvider, logReaderStrategy, logger) {
|
|
74
|
+
this.config = config;
|
|
75
|
+
this.multiProvider = multiProvider;
|
|
76
|
+
this.logReaderStrategy = logReaderStrategy;
|
|
77
|
+
this.logger = logger;
|
|
78
|
+
}
|
|
79
|
+
static fromConfig(config, multiProvider, logger = rootLogger.child({
|
|
80
|
+
module: EvmEventLogsReader.name,
|
|
81
|
+
})) {
|
|
82
|
+
const explorer = multiProvider.tryGetEvmExplorerMetadata(config.chain);
|
|
83
|
+
let logReaderStrategy;
|
|
84
|
+
if (explorer && !config.useRPC) {
|
|
85
|
+
logReaderStrategy = new EvmEtherscanLikeEventLogsReader(config.chain, explorer, multiProvider);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
logReaderStrategy = new EvmRpcEventLogsReader(config.chain, { paginationBlockRange: config.paginationBlockRange }, multiProvider);
|
|
89
|
+
}
|
|
90
|
+
return new EvmEventLogsReader(config, multiProvider, logReaderStrategy, logger);
|
|
91
|
+
}
|
|
92
|
+
async getLogsByTopic(options) {
|
|
93
|
+
const parsedOptions = GetLogByTopicOptionsSchema.parse(options);
|
|
94
|
+
const provider = this.multiProvider.getProvider(this.config.chain);
|
|
95
|
+
await assertIsContractAddress(this.multiProvider, this.config.chain, options.contractAddress);
|
|
96
|
+
const fromBlock = parsedOptions.fromBlock ??
|
|
97
|
+
(await this.logReaderStrategy.getContractDeploymentBlockNumber(parsedOptions.contractAddress));
|
|
98
|
+
const toBlock = parsedOptions.toBlock ?? (await provider.getBlockNumber());
|
|
99
|
+
return this.logReaderStrategy.getContractLogs({
|
|
100
|
+
contractAddress: parsedOptions.contractAddress,
|
|
101
|
+
eventTopic: parsedOptions.eventTopic,
|
|
102
|
+
fromBlock,
|
|
103
|
+
toBlock,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=EvmEventLogsReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EvmEventLogsReader.js","sourceRoot":"","sources":["../../../src/rpc/evm/EvmEventLogsReader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Address, HexString } from '@hyperlane-xyz/utils';
|
|
2
|
+
export type GetEventLogsResponse = {
|
|
3
|
+
address: Address;
|
|
4
|
+
blockNumber: number;
|
|
5
|
+
data: HexString;
|
|
6
|
+
logIndex: number;
|
|
7
|
+
topics: ReadonlyArray<HexString>;
|
|
8
|
+
transactionHash: HexString;
|
|
9
|
+
transactionIndex: number;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/rpc/evm/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACjC,eAAe,EAAE,SAAS,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/rpc/evm/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Log } from 'viem';
|
|
2
|
+
import { Address } from '@hyperlane-xyz/utils';
|
|
3
|
+
import { MultiProvider } from '../../providers/MultiProvider.js';
|
|
4
|
+
import { ChainNameOrId } from '../../types.js';
|
|
5
|
+
import { GetEventLogsResponse } from './types.js';
|
|
6
|
+
export declare function getContractCreationBlockFromRpc(chain: ChainNameOrId, contractAddress: Address, multiProvider: MultiProvider): Promise<number>;
|
|
7
|
+
export type GetLogsFromRpcOptions = {
|
|
8
|
+
chain: ChainNameOrId;
|
|
9
|
+
contractAddress: Address;
|
|
10
|
+
multiProvider: MultiProvider;
|
|
11
|
+
fromBlock: number;
|
|
12
|
+
topic: string;
|
|
13
|
+
toBlock?: number;
|
|
14
|
+
range?: number;
|
|
15
|
+
};
|
|
16
|
+
export declare function getLogsFromRpc({ chain, contractAddress, multiProvider, fromBlock, topic, toBlock, range, }: GetLogsFromRpcOptions): Promise<GetEventLogsResponse[]>;
|
|
17
|
+
export declare function viemLogFromGetEventLogsResponse(log: GetEventLogsResponse): Log;
|
|
18
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/rpc/evm/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAM/C,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGlD,wBAAsB,+BAA+B,CACnD,KAAK,EAAE,aAAa,EACpB,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,cAAc,CAAC,EACnC,KAAK,EACL,eAAe,EACf,aAAa,EACb,SAAS,EACT,KAAK,EACL,OAAO,EACP,KAAW,GACZ,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAoCzD;AAED,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,oBAAoB,GACxB,GAAG,CAYL"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.hardhat-test.d.ts","sourceRoot":"","sources":["../../../src/rpc/evm/utils.hardhat-test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import chai, { expect } from 'chai';
|
|
2
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
3
|
+
import { ethers } from 'ethers';
|
|
4
|
+
import hre from 'hardhat';
|
|
5
|
+
import { ERC20Test__factory } from '@hyperlane-xyz/core';
|
|
6
|
+
import { assert } from '@hyperlane-xyz/utils';
|
|
7
|
+
import { TestChainName } from '../../consts/testChains.js';
|
|
8
|
+
import { MultiProvider } from '../../providers/MultiProvider.js';
|
|
9
|
+
import { randomAddress, randomInt } from '../../test/testUtils.js';
|
|
10
|
+
import { getContractCreationBlockFromRpc, getLogsFromRpc } from './utils.js';
|
|
11
|
+
chai.use(chaiAsPromised);
|
|
12
|
+
describe('RPC Utils', () => {
|
|
13
|
+
let contractOwner;
|
|
14
|
+
let tokenRecipient1;
|
|
15
|
+
let tokenRecipient2;
|
|
16
|
+
let providerChainTest1;
|
|
17
|
+
let multiProvider;
|
|
18
|
+
let testContract;
|
|
19
|
+
let erc20Factory;
|
|
20
|
+
let deploymentBlockNumber;
|
|
21
|
+
const transferTopic = ethers.utils.id('Transfer(address,address,uint256)');
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
[contractOwner, tokenRecipient1, tokenRecipient2] =
|
|
24
|
+
await hre.ethers.getSigners();
|
|
25
|
+
assert(contractOwner.provider, 'Expected provider to be defined on the signer');
|
|
26
|
+
// Initialize MultiProvider with test chain
|
|
27
|
+
multiProvider = MultiProvider.createTestMultiProvider({
|
|
28
|
+
signer: contractOwner,
|
|
29
|
+
provider: contractOwner.provider,
|
|
30
|
+
});
|
|
31
|
+
providerChainTest1 = contractOwner.provider;
|
|
32
|
+
// Get contract factory for ERC20Test
|
|
33
|
+
erc20Factory = new ERC20Test__factory(contractOwner);
|
|
34
|
+
});
|
|
35
|
+
async function deployTestErc20() {
|
|
36
|
+
testContract = await erc20Factory.deploy('TestToken', 'TST', ethers.utils.parseEther('1000000'), 18);
|
|
37
|
+
await testContract.deployed();
|
|
38
|
+
assert(testContract.deployTransaction.blockNumber, 'Expected the Contract deployment block number to be defined');
|
|
39
|
+
deploymentBlockNumber = testContract.deployTransaction.blockNumber;
|
|
40
|
+
}
|
|
41
|
+
async function mineRandomNumberOfBlocks() {
|
|
42
|
+
const blocksToMine = randomInt(69, 420);
|
|
43
|
+
for (let blockNum = 0; blockNum < blocksToMine; blockNum++) {
|
|
44
|
+
await providerChainTest1.send('evm_mine', []);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
describe(getContractCreationBlockFromRpc.name, () => {
|
|
48
|
+
it('should find the correct deployment block for a deployed contract', async () => {
|
|
49
|
+
await mineRandomNumberOfBlocks();
|
|
50
|
+
await deployTestErc20();
|
|
51
|
+
await mineRandomNumberOfBlocks();
|
|
52
|
+
const foundBlock = await getContractCreationBlockFromRpc(TestChainName.test1, testContract.address, multiProvider);
|
|
53
|
+
expect(foundBlock).to.equal(deploymentBlockNumber);
|
|
54
|
+
const contractCode = await providerChainTest1.getCode(testContract.address);
|
|
55
|
+
expect(contractCode).not.to.equal('0x');
|
|
56
|
+
});
|
|
57
|
+
it('should throw an error for non-existing contract address', async () => {
|
|
58
|
+
const nonExistentAddress = randomAddress();
|
|
59
|
+
await expect(getContractCreationBlockFromRpc(TestChainName.test1, nonExistentAddress, multiProvider)).to.be.rejectedWith(`Address "${nonExistentAddress}" on chain "${TestChainName.test1}" is not a contract`);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe(getLogsFromRpc.name, () => {
|
|
63
|
+
beforeEach(async () => {
|
|
64
|
+
await deployTestErc20();
|
|
65
|
+
});
|
|
66
|
+
it('should retrieve logs for Transfer events emitted by the contract', async () => {
|
|
67
|
+
// Emit some Transfer events
|
|
68
|
+
const tx1 = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
69
|
+
await tx1.wait();
|
|
70
|
+
const tx2 = await testContract.transfer(tokenRecipient2.address, ethers.utils.parseEther('200'));
|
|
71
|
+
await tx2.wait();
|
|
72
|
+
const logs = await getLogsFromRpc({
|
|
73
|
+
chain: TestChainName.test1,
|
|
74
|
+
contractAddress: testContract.address,
|
|
75
|
+
multiProvider,
|
|
76
|
+
fromBlock: deploymentBlockNumber,
|
|
77
|
+
topic: transferTopic,
|
|
78
|
+
});
|
|
79
|
+
// Should have 3 transfer events: 1 from constructor mint + 2 from transfers
|
|
80
|
+
expect(logs).to.have.length(3);
|
|
81
|
+
logs.forEach((log) => {
|
|
82
|
+
expect(log.address).to.equal(testContract.address);
|
|
83
|
+
expect(log.topics[0]).to.equal(transferTopic);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
it('should work when fromBlock and toBlock are provided', async () => {
|
|
87
|
+
await mineRandomNumberOfBlocks();
|
|
88
|
+
const startBlock = await providerChainTest1.getBlockNumber();
|
|
89
|
+
// Emit event in first block
|
|
90
|
+
const tx1 = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
91
|
+
await tx1.wait();
|
|
92
|
+
const firstEventBlock = await providerChainTest1.getBlockNumber();
|
|
93
|
+
await mineRandomNumberOfBlocks();
|
|
94
|
+
// Emit event in later block
|
|
95
|
+
const tx2 = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('200'));
|
|
96
|
+
await tx2.wait();
|
|
97
|
+
// Query only the first event's block range
|
|
98
|
+
const logs = await getLogsFromRpc({
|
|
99
|
+
chain: TestChainName.test1,
|
|
100
|
+
contractAddress: testContract.address,
|
|
101
|
+
multiProvider,
|
|
102
|
+
fromBlock: startBlock,
|
|
103
|
+
toBlock: firstEventBlock,
|
|
104
|
+
topic: transferTopic,
|
|
105
|
+
});
|
|
106
|
+
expect(logs).to.have.length(1);
|
|
107
|
+
expect(logs[0].blockNumber).to.equal(firstEventBlock);
|
|
108
|
+
});
|
|
109
|
+
it('should work when a custom range parameter is provided', async () => {
|
|
110
|
+
const numberOfEventsToEmit = randomInt(1, 47);
|
|
111
|
+
for (let i = 0; i < numberOfEventsToEmit; i++) {
|
|
112
|
+
const tx = await testContract.mint(ethers.utils.parseEther(`${(i + 1) * 100}`));
|
|
113
|
+
await tx.wait();
|
|
114
|
+
}
|
|
115
|
+
// +1 because of the transfer event emitted on contract deployment
|
|
116
|
+
const expectedNumberOfEvents = numberOfEventsToEmit + 1;
|
|
117
|
+
const logs = await getLogsFromRpc({
|
|
118
|
+
chain: TestChainName.test1,
|
|
119
|
+
contractAddress: testContract.address,
|
|
120
|
+
multiProvider,
|
|
121
|
+
fromBlock: deploymentBlockNumber,
|
|
122
|
+
topic: transferTopic,
|
|
123
|
+
// Small range to test chunking
|
|
124
|
+
range: 2,
|
|
125
|
+
});
|
|
126
|
+
expect(logs).to.have.length(expectedNumberOfEvents);
|
|
127
|
+
});
|
|
128
|
+
it('should return empty array when no logs match the criteria', async () => {
|
|
129
|
+
// Emitting an event just to be sure that filtering works as expected
|
|
130
|
+
const tx1 = await testContract.transfer(tokenRecipient1.address, ethers.utils.parseEther('100'));
|
|
131
|
+
await tx1.wait();
|
|
132
|
+
const nonExistentTopic = ethers.utils.id('NonExistentEvent(uint256)');
|
|
133
|
+
const logs = await getLogsFromRpc({
|
|
134
|
+
chain: TestChainName.test1,
|
|
135
|
+
contractAddress: testContract.address,
|
|
136
|
+
multiProvider,
|
|
137
|
+
fromBlock: deploymentBlockNumber,
|
|
138
|
+
topic: nonExistentTopic,
|
|
139
|
+
});
|
|
140
|
+
expect(logs).to.have.length(0);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=utils.hardhat-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.hardhat-test.js","sourceRoot":"","sources":["../../../src/rpc/evm/utils.hardhat-test.ts"],"names":[],"mappings":"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"}
|