Skip to content
This repository was archived by the owner on Jul 9, 2024. It is now read-only.

Commit e1aa4af

Browse files
committed
Adds unit tests
1 parent 8ac3c66 commit e1aa4af

File tree

2 files changed

+147
-7
lines changed

2 files changed

+147
-7
lines changed

src/update-data-feeds.test.ts

+140
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,146 @@ describe('updateDataFeedsInLoop', () => {
300300
});
301301
});
302302

303+
describe('updateBeacons', () => {
304+
it('calls updateBeaconWithSignedData in Api3ServerV1 contract for single beacon', async () => {
305+
state.updateState((currentState) => ({
306+
...currentState,
307+
beaconValues: {
308+
'0x2ba0526238b0f2671b7981fd7a263730619c8e849a528088fd4a92350a8c2f2c': validSignedData,
309+
'0xa5ddf304a7dcec62fa55449b7fe66b33339fd8b249db06c18423d5b0da7716c2': undefined as any,
310+
'0x8fa9d00cb8f2d95b1299623d97a97696ed03d0e3350e4ea638f469beabcdabcd': validSignedData,
311+
},
312+
}));
313+
314+
const txCountSpy = jest.spyOn(ethers.providers.StaticJsonRpcProvider.prototype, 'getTransactionCount');
315+
txCountSpy.mockResolvedValueOnce(212);
316+
317+
const timestamp = 1649664085;
318+
319+
const updateBeaconWithSignedDataMock = jest
320+
.fn()
321+
.mockReturnValueOnce({ hash: ethers.utils.hexlify(ethers.utils.randomBytes(32)) });
322+
const callStaticTryMulticallMock = jest.fn().mockReturnValueOnce({
323+
successes: [true, true],
324+
returndata: [
325+
ethers.utils.defaultAbiCoder.encode(['int224', 'uint32'], [ethers.BigNumber.from(41000000000), timestamp - 30]),
326+
ethers.utils.defaultAbiCoder.encode(['int224', 'uint32'], [ethers.BigNumber.from(40000000000), timestamp]),
327+
],
328+
});
329+
jest.spyOn(Api3ServerV1Factory, 'connect').mockImplementation(
330+
(_dapiServerAddress, _provider) =>
331+
({
332+
connect(_signerOrProvider: ethers.Signer | ethers.providers.Provider | string) {
333+
return this;
334+
},
335+
updateBeaconWithSignedData: updateBeaconWithSignedDataMock,
336+
interface: {
337+
encodeFunctionData: (functionFragment: string, values: [any]): string => {
338+
if (functionFragment === 'dataFeeds')
339+
return '0x67a7cfb741c3d6e0ee82ae3d33356c4dceb84e98d1a0b361db0f51081fc5a2541ae51683';
340+
341+
if (functionFragment === 'readDataFeedWithId') {
342+
switch (values[0]) {
343+
case '0x2ba0526238b0f2671b7981fd7a263730619c8e849a528088fd4a92350a8c2f2c':
344+
return '0xa5fc076f2ba0526238b0f2671b7981fd7a263730619c8e849a528088fd4a92350a8c2f2c';
345+
case '0xa5ddf304a7dcec62fa55449b7fe66b33339fd8b249db06c18423d5b0da7716c2':
346+
return '0xa5fc076fa5ddf304a7dcec62fa55449b7fe66b33339fd8b249db06c18423d5b0da7716c2';
347+
case '0x8fa9d00cb8f2d95b1299623d97a97696ed03d0e3350e4ea638f469beabcdabcd':
348+
return '0xa5fc076f8fa9d00cb8f2d95b1299623d97a97696ed03d0e3350e4ea638f469beabcdabcd';
349+
}
350+
}
351+
352+
if (functionFragment === 'updateBeaconWithSignedData')
353+
return '0x1a0a0b3e0000000000000000000000005656d3a378b1aadfddcf4196ea364a9d786172909ec34b00a5019442dcd05a4860ff2bf015164b368cb83fcb756088fcabcdabcd000000000000000000000000000000000000000000000000000000006253e05500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000009dc41b78000000000000000000000000000000000000000000000000000000000000000418aace553ec28f53cc976c8a2469d50f16de121d248495117aca36feb4950957827570e0648f82bdbc0afa6cb69dd9fe37dc7f9d58ae3aa06450e627e06c1b8031b00000000000000000000000000000000000000000000000000000000000000';
354+
355+
if (functionFragment === 'updateBeaconSetWithBeacons')
356+
return '0x00aae33f00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002924b5d4cb3ec6366ae4302a1ca6aec035594ea3ea48a102d160b50b0c43ebfb5bf7ce55d109fd196de2a8bf1515d166c56c9decbe9cb473656bbca30d5743990';
357+
358+
return '';
359+
},
360+
},
361+
callStatic: { tryMulticall: callStaticTryMulticallMock },
362+
} as any)
363+
);
364+
365+
const groups = api.groupDataFeedsByProviderSponsor();
366+
367+
await api.updateBeacons(groups[0], Date.now());
368+
369+
expect(callStaticTryMulticallMock).toHaveBeenCalledTimes(1);
370+
expect(updateBeaconWithSignedDataMock).toHaveBeenCalledTimes(1);
371+
});
372+
373+
it('calls tryMulticall in Api3ServerV1 contract for multiple beacon updates', async () => {
374+
state.updateState((currentState) => ({
375+
...currentState,
376+
beaconValues: {
377+
'0x2ba0526238b0f2671b7981fd7a263730619c8e849a528088fd4a92350a8c2f2c': validSignedData,
378+
'0xa5ddf304a7dcec62fa55449b7fe66b33339fd8b249db06c18423d5b0da7716c2': validSignedData,
379+
'0x8fa9d00cb8f2d95b1299623d97a97696ed03d0e3350e4ea638f469beabcdabcd': validSignedData,
380+
},
381+
}));
382+
383+
const txCountSpy = jest.spyOn(ethers.providers.StaticJsonRpcProvider.prototype, 'getTransactionCount');
384+
txCountSpy.mockResolvedValueOnce(212);
385+
386+
const timestamp = 1649664085;
387+
388+
const tryMulticallMock = jest
389+
.fn()
390+
.mockReturnValueOnce({ hash: ethers.utils.hexlify(ethers.utils.randomBytes(32)) });
391+
const callStaticTryMulticallMock = jest.fn().mockReturnValueOnce({
392+
successes: [true, true],
393+
returndata: [
394+
ethers.utils.defaultAbiCoder.encode(['int224', 'uint32'], [ethers.BigNumber.from(41000000000), timestamp - 30]),
395+
ethers.utils.defaultAbiCoder.encode(['int224', 'uint32'], [ethers.BigNumber.from(39000000000), timestamp - 30]),
396+
],
397+
});
398+
jest.spyOn(Api3ServerV1Factory, 'connect').mockImplementation(
399+
(_dapiServerAddress, _provider) =>
400+
({
401+
connect(_signerOrProvider: ethers.Signer | ethers.providers.Provider | string) {
402+
return this;
403+
},
404+
tryMulticall: tryMulticallMock,
405+
interface: {
406+
encodeFunctionData: (functionFragment: string, values: [any]): string => {
407+
if (functionFragment === 'dataFeeds')
408+
return '0x67a7cfb741c3d6e0ee82ae3d33356c4dceb84e98d1a0b361db0f51081fc5a2541ae51683';
409+
410+
if (functionFragment === 'readDataFeedWithId') {
411+
switch (values[0]) {
412+
case '0x2ba0526238b0f2671b7981fd7a263730619c8e849a528088fd4a92350a8c2f2c':
413+
return '0xa5fc076f2ba0526238b0f2671b7981fd7a263730619c8e849a528088fd4a92350a8c2f2c';
414+
case '0xa5ddf304a7dcec62fa55449b7fe66b33339fd8b249db06c18423d5b0da7716c2':
415+
return '0xa5fc076fa5ddf304a7dcec62fa55449b7fe66b33339fd8b249db06c18423d5b0da7716c2';
416+
case '0x8fa9d00cb8f2d95b1299623d97a97696ed03d0e3350e4ea638f469beabcdabcd':
417+
return '0xa5fc076f8fa9d00cb8f2d95b1299623d97a97696ed03d0e3350e4ea638f469beabcdabcd';
418+
}
419+
}
420+
421+
if (functionFragment === 'updateBeaconWithSignedData')
422+
return '0x1a0a0b3e0000000000000000000000005656d3a378b1aadfddcf4196ea364a9d786172909ec34b00a5019442dcd05a4860ff2bf015164b368cb83fcb756088fcabcdabcd000000000000000000000000000000000000000000000000000000006253e05500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000009dc41b78000000000000000000000000000000000000000000000000000000000000000418aace553ec28f53cc976c8a2469d50f16de121d248495117aca36feb4950957827570e0648f82bdbc0afa6cb69dd9fe37dc7f9d58ae3aa06450e627e06c1b8031b00000000000000000000000000000000000000000000000000000000000000';
423+
424+
if (functionFragment === 'updateBeaconSetWithBeacons')
425+
return '0x00aae33f00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002924b5d4cb3ec6366ae4302a1ca6aec035594ea3ea48a102d160b50b0c43ebfb5bf7ce55d109fd196de2a8bf1515d166c56c9decbe9cb473656bbca30d5743990';
426+
427+
return '';
428+
},
429+
},
430+
callStatic: { tryMulticall: callStaticTryMulticallMock },
431+
} as any)
432+
);
433+
434+
const groups = api.groupDataFeedsByProviderSponsor();
435+
436+
await api.updateBeacons(groups[0], Date.now());
437+
438+
expect(callStaticTryMulticallMock).toHaveBeenCalledTimes(1);
439+
expect(tryMulticallMock).toHaveBeenCalledTimes(1);
440+
});
441+
});
442+
303443
describe('updateBeaconSets', () => {
304444
it('calls updateBeaconSetWithBeacons in Api3ServerV1 contract', async () => {
305445
state.updateState((currentState) => ({

src/update-data-feeds.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -238,18 +238,18 @@ export const updateBeacons = async (providerSponsorDataFeeds: ProviderSponsorDat
238238
for (const readBatch of chunk(beaconUpdates, DATAFEED_READ_BATCH_SIZE)) {
239239
// Read beacon batch onchain values
240240
const goDatafeedsTryMulticall = await go(
241-
() => {
242-
const calldatas = readBatch.map((beaconUpdate) => beaconUpdate.dataFeedsCalldata);
243-
return contract.connect(voidSigner).callStatic.tryMulticall(calldatas);
244-
},
241+
() =>
242+
contract
243+
.connect(voidSigner)
244+
.callStatic.tryMulticall(readBatch.map((beaconUpdate) => beaconUpdate.dataFeedsCalldata)),
245245
{
246246
...prepareGoOptions(startTime, totalTimeout),
247247
onAttemptError: (goError) =>
248-
logger.warn(`Failed attempt to read beacon data using multicall. Error ${goError.error}`, logOptions),
248+
logger.warn(`Attempt to read beacon data using tryMulticall has failed. Error ${goError.error}`, logOptions),
249249
}
250250
);
251251
if (!goDatafeedsTryMulticall.success) {
252-
logger.warn(`Unable to read beacon data using multicall. Error: ${goDatafeedsTryMulticall.error}`, logOptions);
252+
logger.warn(`Unable to read beacon data using tryMulticall. Error: ${goDatafeedsTryMulticall.error}`, logOptions);
253253
continue;
254254
}
255255

@@ -337,7 +337,7 @@ export const updateBeacons = async (providerSponsorDataFeeds: ProviderSponsorDat
337337
...prepareGoOptions(startTime, totalTimeout),
338338
onAttemptError: (goError) =>
339339
logger.warn(
340-
`Attempt to send transaction to update ${updateBatch.length} beacon(s) failed. Error ${goError.error}`,
340+
`Attempt to send transaction to update ${updateBatch.length} beacon(s) has failed. Error ${goError.error}`,
341341
logOptions
342342
),
343343
}

0 commit comments

Comments
 (0)