Skip to content

Commit 63a5a5f

Browse files
Open eden tbill change latest answer retrieval (#3886)
* add latestRoundData * add Changeset * fix redundancy * change redundancy * Fixing test cases * fix test cases * fix integration test * review re-work * fix test * review re-work * Delete .changeset/giant-parrots-tell.md * Delete .changeset/thick-mirrors-play.md * Restore latestAnswer mock behavior in fixture --------- Co-authored-by: David de Kloet <david.dekloet@smartcontract.com>
1 parent 2ebd02b commit 63a5a5f

File tree

7 files changed

+105
-57
lines changed

7 files changed

+105
-57
lines changed

.changeset/breezy-pots-juggle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@chainlink/token-balance-adapter': minor
3+
---
4+
5+
Switch from using latestAnswer to latestRoundData

packages/sources/token-balance/src/transport/tbill.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export class TbillTransport extends SubscriptionTransport<BaseEndpointTypes> {
164164
)
165165

166166
const [sharePriceUSD, sharesDecimals, queueLength, balanceResponse] = await Promise.all([
167-
priceOracleContract.getRate(),
167+
priceOracleContract.getRateFromLatestRoundData(),
168168
contract.decimals(),
169169
contract.getWithdrawalQueueLength(),
170170
Promise.all(address.wallets.map((wallet) => contract.balanceOf(wallet))),

packages/sources/token-balance/src/transport/utils.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ export class GroupedPriceOracleContract {
7575
return this.runner.run(() => this.contract.decimals())
7676
}
7777

78-
async latestAnswer(): Promise<bigint> {
79-
return this.runner.run(() => this.contract.latestAnswer())
78+
async latestRoundData(): Promise<bigint[]> {
79+
return this.runner.run(() => this.contract.latestRoundData())
8080
}
8181

82-
async getRate(): Promise<SharePriceType> {
83-
const [value, decimal] = await Promise.all([this.latestAnswer(), this.decimals()])
82+
async getRateFromLatestRoundData(): Promise<SharePriceType> {
83+
const [[_, answer], decimal] = await Promise.all([this.latestRoundData(), this.decimals()])
8484
return {
85-
value,
85+
value: answer,
8686
decimal: Number(decimal),
8787
}
8888
}

packages/sources/token-balance/test/integration/__snapshots__/tbill.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ exports[`execute tbill endpoint should return success 1`] = `
44
{
55
"data": {
66
"decimals": 18,
7-
"result": "39273843706330946296200000",
7+
"result": "39580028506378570397100000",
88
},
9-
"result": "39273843706330946296200000",
9+
"result": "39580028506378570397100000",
1010
"statusCode": 200,
1111
"timestamps": {
1212
"providerDataReceivedUnixMs": 978347471111,

packages/sources/token-balance/test/integration/fixtures.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,17 @@ export const mockETHContractCallResponseSuccess = (): nock.Scope =>
211211
id: request.id,
212212
result: '0x0000000000000000000000000000000000000000000000000000000006882052',
213213
}
214+
} else if (
215+
request.method === 'eth_call' &&
216+
request.params[0].to === '0xce9a6626eb99eaea829d7fa613d5d0a2eae45f40' &&
217+
request.params[0].data === '0xfeaf968c' // latestRoundData()
218+
) {
219+
return {
220+
jsonrpc: '2.0',
221+
id: request.id,
222+
result:
223+
'0x00000000000000000000000000000000000000000000000000000000000002f6000000000000000000000000000000000000000000000000000000000695299300000000000000000000000000000000000000000000000000000000683720cf00000000000000000000000000000000000000000000000000000000683720cf00000000000000000000000000000000000000000000000000000000000002f6',
224+
}
214225
} else {
215226
// Default response for unsupported calls
216227
return {

packages/sources/token-balance/test/unit/tbill.test.ts

Lines changed: 67 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ const BASE_TBILL_PRICE_ORACLE_ADDRESS = 'unknown'
2020

2121
const RESULT_DECIMALS = 18
2222

23+
const createRoundData = ({ price, priceDecimals }: { price: number; priceDecimals: number }) => {
24+
const now = BigInt(Math.floor(Date.now() / 1000))
25+
return [
26+
1n, // roundId
27+
BigInt(price * 10 ** priceDecimals), // answer
28+
now, // startedAt
29+
now, // updatedAt
30+
1n, // answeredInRound
31+
]
32+
}
33+
2334
const createMockTokenContract = () => ({
2435
decimals: jest.fn(),
2536
getWithdrawalQueueLength: jest.fn(),
@@ -29,7 +40,7 @@ const createMockTokenContract = () => ({
2940

3041
const createMockPriceContract = () => ({
3142
decimals: jest.fn(),
32-
latestAnswer: jest.fn(),
43+
latestRoundData: jest.fn(),
3344
})
3445

3546
const ethTbillContract = createMockTokenContract()
@@ -131,7 +142,9 @@ describe('TbillTransport', () => {
131142
ethTbillContract.decimals.mockResolvedValue(balanceDecimals)
132143
ethTbillContract.balanceOf.mockResolvedValue(BigInt(balance * 10 ** balanceDecimals))
133144
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
134-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
145+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
146+
createRoundData({ price, priceDecimals }),
147+
)
135148

136149
const param = {
137150
addresses: [
@@ -149,10 +162,10 @@ describe('TbillTransport', () => {
149162

150163
expect(ethTbillContract.balanceOf).toBeCalledWith(walletAddress)
151164
expect(ethTbillContract.balanceOf).toBeCalledTimes(1)
152-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(1)
165+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(1)
153166

154167
expect(arbTbillContract.balanceOf).toBeCalledTimes(0)
155-
expect(arbTbillPriceContract.latestAnswer).toBeCalledTimes(0)
168+
expect(arbTbillPriceContract.latestRoundData).toBeCalledTimes(0)
156169

157170
expect(responseCache.write).toBeCalledWith(transportName, [
158171
{
@@ -185,7 +198,9 @@ describe('TbillTransport', () => {
185198
arbTbillContract.decimals.mockResolvedValue(balanceDecimals)
186199
arbTbillContract.balanceOf.mockResolvedValue(BigInt(balance * 10 ** balanceDecimals))
187200
arbTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
188-
arbTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
201+
arbTbillPriceContract.latestRoundData.mockResolvedValue(
202+
createRoundData({ price, priceDecimals }),
203+
)
189204

190205
const param = {
191206
addresses: [
@@ -203,10 +218,10 @@ describe('TbillTransport', () => {
203218

204219
expect(arbTbillContract.balanceOf).toBeCalledWith(walletAddress)
205220
expect(arbTbillContract.balanceOf).toBeCalledTimes(1)
206-
expect(arbTbillPriceContract.latestAnswer).toBeCalledTimes(1)
221+
expect(arbTbillPriceContract.latestRoundData).toBeCalledTimes(1)
207222

208223
expect(ethTbillContract.balanceOf).toBeCalledTimes(0)
209-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(0)
224+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(0)
210225

211226
expect(responseCache.write).toBeCalledWith(transportName, [
212227
{
@@ -265,8 +280,8 @@ describe('TbillTransport', () => {
265280
BigInt(ethTbillBalance2 * 10 ** ethTbillBalanceDecimals),
266281
)
267282
ethTbillPriceContract.decimals.mockResolvedValue(ethTbillPriceDecimals)
268-
ethTbillPriceContract.latestAnswer.mockResolvedValue(
269-
BigInt(ethTbillPrice * 10 ** ethTbillPriceDecimals),
283+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
284+
createRoundData({ price: ethTbillPrice, priceDecimals: ethTbillPriceDecimals }),
270285
)
271286

272287
arbTbillContract.decimals.mockResolvedValue(arbTbillBalanceDecimals)
@@ -277,8 +292,8 @@ describe('TbillTransport', () => {
277292
BigInt(arbTbillBalance2 * 10 ** arbTbillBalanceDecimals),
278293
)
279294
arbTbillPriceContract.decimals.mockResolvedValue(arbTbillPriceDecimals)
280-
arbTbillPriceContract.latestAnswer.mockResolvedValue(
281-
BigInt(arbTbillPrice * 10 ** arbTbillPriceDecimals),
295+
arbTbillPriceContract.latestRoundData.mockResolvedValue(
296+
createRoundData({ price: arbTbillPrice, priceDecimals: arbTbillPriceDecimals }),
282297
)
283298

284299
const param = {
@@ -317,13 +332,13 @@ describe('TbillTransport', () => {
317332
expect(ethTbillContract.balanceOf).toHaveBeenNthCalledWith(2, ethWalletAddress2)
318333
expect(ethTbillContract.balanceOf).toBeCalledTimes(2)
319334
// TODO: Do we really need 2 calls to the price contract?
320-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(2)
335+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(2)
321336

322337
expect(arbTbillContract.balanceOf).toHaveBeenNthCalledWith(1, arbWalletAddress1)
323338
expect(arbTbillContract.balanceOf).toHaveBeenNthCalledWith(2, arbWalletAddress2)
324339
expect(arbTbillContract.balanceOf).toBeCalledTimes(2)
325340
// TODO: Do we really need 2 calls to the price contract?
326-
expect(arbTbillPriceContract.latestAnswer).toBeCalledTimes(2)
341+
expect(arbTbillPriceContract.latestRoundData).toBeCalledTimes(2)
327342

328343
expect(responseCache.write).toBeCalledWith(transportName, [
329344
{
@@ -358,7 +373,9 @@ describe('TbillTransport', () => {
358373
ethTbillContract.decimals.mockResolvedValue(decimalsPromise)
359374
ethTbillContract.balanceOf.mockResolvedValue(BigInt(balance * 10 ** balanceDecimals))
360375
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
361-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
376+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
377+
createRoundData({ price, priceDecimals }),
378+
)
362379

363380
const param = {
364381
addresses: [
@@ -411,7 +428,9 @@ describe('TbillTransport', () => {
411428
ethTbillContract.decimals.mockRejectedValue(new Error('test error'))
412429
ethTbillContract.balanceOf.mockResolvedValue(BigInt(balance * 10 ** balanceDecimals))
413430
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
414-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
431+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
432+
createRoundData({ price, priceDecimals }),
433+
)
415434

416435
const param = {
417436
addresses: [
@@ -457,7 +476,9 @@ describe('TbillTransport', () => {
457476
ethTbillContract.decimals.mockResolvedValue(balanceDecimals)
458477
ethTbillContract.balanceOf.mockResolvedValue(BigInt(balance * 10 ** balanceDecimals))
459478
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
460-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
479+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
480+
createRoundData({ price, priceDecimals }),
481+
)
461482

462483
const param = {
463484
addresses: [
@@ -481,10 +502,10 @@ describe('TbillTransport', () => {
481502

482503
expect(ethTbillContract.balanceOf).toBeCalledWith(walletAddress)
483504
expect(ethTbillContract.balanceOf).toBeCalledTimes(1)
484-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(1)
505+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(1)
485506

486507
expect(arbTbillContract.balanceOf).toBeCalledTimes(0)
487-
expect(arbTbillPriceContract.latestAnswer).toBeCalledTimes(0)
508+
expect(arbTbillPriceContract.latestRoundData).toBeCalledTimes(0)
488509

489510
expect(responseCache.write).toBeCalledWith(transportName, [
490511
{
@@ -534,7 +555,9 @@ describe('TbillTransport', () => {
534555
})
535556

536557
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
537-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
558+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
559+
createRoundData({ price, priceDecimals }),
560+
)
538561

539562
const param: RequestParams = {
540563
addresses: [
@@ -607,7 +630,9 @@ describe('TbillTransport', () => {
607630
})
608631

609632
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
610-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
633+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
634+
createRoundData({ price, priceDecimals }),
635+
)
611636

612637
const param: RequestParams = {
613638
addresses: [
@@ -687,7 +712,9 @@ describe('TbillTransport', () => {
687712
)
688713

689714
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
690-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
715+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
716+
createRoundData({ price, priceDecimals }),
717+
)
691718

692719
const param: RequestParams = {
693720
addresses: [walletAddress1, walletAddress2].map((walletAddress) => ({
@@ -768,7 +795,9 @@ describe('TbillTransport', () => {
768795
)
769796

770797
ethTbillPriceContract.decimals.mockResolvedValue(priceDecimals)
771-
ethTbillPriceContract.latestAnswer.mockResolvedValue(BigInt(price * 10 ** priceDecimals))
798+
ethTbillPriceContract.latestRoundData.mockResolvedValue(
799+
createRoundData({ price, priceDecimals }),
800+
)
772801

773802
const param: RequestParams = {
774803
addresses: [
@@ -834,8 +863,8 @@ describe('TbillTransport', () => {
834863
deferred(BigInt(balance * 10 ** balanceDecimals)),
835864
)
836865
ethTbillPriceContract.decimals.mockImplementation(deferred(priceDecimals))
837-
ethTbillPriceContract.latestAnswer.mockImplementation(
838-
deferred(BigInt(price * 10 ** priceDecimals)),
866+
ethTbillPriceContract.latestRoundData.mockImplementation(
867+
deferred(createRoundData({ price, priceDecimals })),
839868
)
840869
ethTbillContract.getWithdrawalQueueLength.mockImplementation(deferred(0))
841870

@@ -855,7 +884,7 @@ describe('TbillTransport', () => {
855884
// 2. ethTbillContract.balanceOf
856885
// 5. ethTbillContract.getWithdrawalQueueLength
857886
// 3. ethTbillPriceContract.decimals
858-
// 4. ethTbillPriceContract.latestAnswer
887+
// 4. ethTbillPriceContract.latestRoundData
859888
//
860889
// So for 2 addresses we expect 10 RPCs. With a group size of 3, we
861890
// should have 4 batches of sizes 3, 3, 3, and 1.
@@ -876,7 +905,7 @@ describe('TbillTransport', () => {
876905
expect(ethTbillContract.decimals).toBeCalledTimes(2)
877906
expect(ethTbillContract.getWithdrawalQueueLength).toBeCalledTimes(2)
878907
expect(ethTbillPriceContract.decimals).toBeCalledTimes(2)
879-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(2)
908+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(2)
880909
})
881910

882911
it('should limit concurrent RPCs per provider', async () => {
@@ -904,8 +933,8 @@ describe('TbillTransport', () => {
904933
deferred(BigInt(balance * 10 ** balanceDecimals)),
905934
)
906935
ethTbillPriceContract.decimals.mockImplementation(deferred(priceDecimals))
907-
ethTbillPriceContract.latestAnswer.mockImplementation(
908-
deferred(BigInt(price * 10 ** priceDecimals)),
936+
ethTbillPriceContract.latestRoundData.mockImplementation(
937+
deferred(createRoundData({ price, priceDecimals })),
909938
)
910939
ethTbillContract.getWithdrawalQueueLength.mockImplementation(deferred(0))
911940

@@ -914,8 +943,8 @@ describe('TbillTransport', () => {
914943
deferred(BigInt(balance * 10 ** balanceDecimals)),
915944
)
916945
arbTbillPriceContract.decimals.mockImplementation(deferred(priceDecimals))
917-
arbTbillPriceContract.latestAnswer.mockImplementation(
918-
deferred(BigInt(price * 10 ** priceDecimals)),
946+
arbTbillPriceContract.latestRoundData.mockImplementation(
947+
deferred(createRoundData({ price, priceDecimals })),
919948
)
920949
arbTbillContract.getWithdrawalQueueLength.mockImplementation(deferred(0))
921950

@@ -943,7 +972,7 @@ describe('TbillTransport', () => {
943972
// 2. ethTbillContract.balanceOf
944973
// 5. ethTbillContract.getWithdrawalQueueLength
945974
// 3. ethTbillPriceContract.decimals
946-
// 4. ethTbillPriceContract.latestAnswer
975+
// 4. ethTbillPriceContract.latestRoundData
947976
//
948977
// So for 4 addresses we expect 20 RPCs. With a group size of 3 but a
949978
// separate group size per provider, we should have 4 batches of sizes 6,
@@ -965,13 +994,13 @@ describe('TbillTransport', () => {
965994
expect(ethTbillContract.decimals).toBeCalledTimes(2)
966995
expect(ethTbillContract.getWithdrawalQueueLength).toBeCalledTimes(2)
967996
expect(ethTbillPriceContract.decimals).toBeCalledTimes(2)
968-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(2)
997+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(2)
969998

970999
expect(arbTbillContract.balanceOf).toBeCalledTimes(2)
9711000
expect(arbTbillContract.decimals).toBeCalledTimes(2)
9721001
expect(arbTbillContract.getWithdrawalQueueLength).toBeCalledTimes(2)
9731002
expect(arbTbillPriceContract.decimals).toBeCalledTimes(2)
974-
expect(arbTbillPriceContract.latestAnswer).toBeCalledTimes(2)
1003+
expect(arbTbillPriceContract.latestRoundData).toBeCalledTimes(2)
9751004
})
9761005

9771006
it('should reset RPC grouping for a new request', async () => {
@@ -999,8 +1028,8 @@ describe('TbillTransport', () => {
9991028
deferred(BigInt(balance * 10 ** balanceDecimals)),
10001029
)
10011030
ethTbillPriceContract.decimals.mockImplementation(deferred(priceDecimals))
1002-
ethTbillPriceContract.latestAnswer.mockImplementation(
1003-
deferred(BigInt(price * 10 ** priceDecimals)),
1031+
ethTbillPriceContract.latestRoundData.mockImplementation(
1032+
deferred(createRoundData({ price, priceDecimals })),
10041033
)
10051034
ethTbillContract.getWithdrawalQueueLength.mockImplementation(deferred(0))
10061035

@@ -1020,7 +1049,7 @@ describe('TbillTransport', () => {
10201049
// 2. ethTbillContract.balanceOf
10211050
// 5. ethTbillContract.getWithdrawalQueueLength
10221051
// 3. ethTbillPriceContract.decimals
1023-
// 4. ethTbillPriceContract.latestAnswer
1052+
// 4. ethTbillPriceContract.latestARoundData
10241053
//
10251054
// So for 2 addresses we expect 10 RPCs. With a group size of 3, we
10261055
// should have 4 batches of sizes 3, 3, 3, and 1.
@@ -1041,7 +1070,7 @@ describe('TbillTransport', () => {
10411070
expect(ethTbillContract.decimals).toBeCalledTimes(2)
10421071
expect(ethTbillContract.getWithdrawalQueueLength).toBeCalledTimes(2)
10431072
expect(ethTbillPriceContract.decimals).toBeCalledTimes(2)
1044-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(2)
1073+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(2)
10451074

10461075
// When we make a new request, it should start with another group of 3,
10471076
// rather than just 2, which might happen if we reuse the same
@@ -1058,7 +1087,7 @@ describe('TbillTransport', () => {
10581087
expect(ethTbillContract.decimals).toBeCalledTimes(4)
10591088
expect(ethTbillContract.getWithdrawalQueueLength).toBeCalledTimes(4)
10601089
expect(ethTbillPriceContract.decimals).toBeCalledTimes(4)
1061-
expect(ethTbillPriceContract.latestAnswer).toBeCalledTimes(4)
1090+
expect(ethTbillPriceContract.latestRoundData).toBeCalledTimes(4)
10621091
})
10631092
})
10641093

0 commit comments

Comments
 (0)