Skip to content

Commit 3e5b87c

Browse files
authored
fix: fall back on ENS batch call exceptions (#478)
* fix: fall back on ENS batch call exceptions Fixes #475 * test: cover ENS batch error capture --------- Co-authored-by: chai3-bot <chai3-bot@users.noreply.github.com>
1 parent a8b5f3a commit 3e5b87c

2 files changed

Lines changed: 43 additions & 6 deletions

File tree

src/addressResolvers/ens.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,17 @@ export async function lookupAddresses(addresses: Address[]): Promise<Record<Addr
3535
if (normalizedAddresses.length === 0) return {};
3636

3737
try {
38-
const reverseRecords = await snapshot.utils.call(
39-
provider,
40-
abi,
41-
['0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C', 'getNames', [normalizedAddresses]],
42-
{ blockTag: 'latest' }
43-
);
38+
let reverseRecords: string[] = [];
39+
try {
40+
reverseRecords = await snapshot.utils.call(
41+
provider,
42+
abi,
43+
['0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C', 'getNames', [normalizedAddresses]],
44+
{ blockTag: 'latest' }
45+
);
46+
} catch (err: any) {
47+
if (err?.code !== 'CALL_EXCEPTION') throw err;
48+
}
4449
const validNames = normalizeEns(reverseRecords);
4550

4651
// The batch contract only reads on-chain reverse records. Names served by

test/integration/addressResolvers/ens.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
import { capture } from '@snapshot-labs/snapshot-sentry';
2+
import snapshot from '@snapshot-labs/snapshot.js';
13
import testAddressResolver from './helper';
24
import { lookupAddresses, resolveNames } from '../../../src/addressResolvers/ens';
5+
import { FetchError } from '../../../src/addressResolvers/utils';
6+
7+
jest.mock('@snapshot-labs/snapshot-sentry', () => ({
8+
capture: jest.fn()
9+
}));
310

411
testAddressResolver({
512
name: 'ENS',
@@ -21,4 +28,29 @@ describe('ENS address resolver: CCIP-Read fallback', () => {
2128
[address]: 'avsa.eth'
2229
});
2330
}, 15e3);
31+
32+
it('falls back to per-address lookups when the batch reverse call reverts', async () => {
33+
const ccipAddress = '0x3a872f8FED4421E7d5BE5c98Ab5Ea0e0245169A0';
34+
const goodAddress = '0xE6D0Dd18C6C3a9Af8C2FaB57d6e6A38E29d513cC';
35+
36+
await expect(lookupAddresses([ccipAddress])).resolves.toEqual({});
37+
await expect(lookupAddresses([ccipAddress, goodAddress])).resolves.toEqual({
38+
[goodAddress]: 'sdntestens.eth'
39+
});
40+
}, 20e3);
41+
42+
it('still surfaces non-CALL_EXCEPTION batch errors', async () => {
43+
const error = Object.assign(new Error('boom'), {
44+
code: 'SERVER_ERROR'
45+
});
46+
const callSpy = jest.spyOn(snapshot.utils, 'call').mockRejectedValueOnce(error);
47+
const address = '0xE6D0Dd18C6C3a9Af8C2FaB57d6e6A38E29d513cC';
48+
49+
try {
50+
await expect(lookupAddresses([address])).rejects.toBeInstanceOf(FetchError);
51+
expect(capture).toHaveBeenCalledWith(error, { input: { addresses: [address] } });
52+
} finally {
53+
callSpy.mockRestore();
54+
}
55+
});
2456
});

0 commit comments

Comments
 (0)