Skip to content

Commit

Permalink
common: test by mocking escrow acocunt response
Browse files Browse the repository at this point in the history
Signed-off-by: Gustavo Inacio <[email protected]>
  • Loading branch information
gusinacio committed Oct 9, 2024
1 parent 600608f commit 34abfce
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 47 deletions.
32 changes: 32 additions & 0 deletions packages/indexer-common/src/allocations/__tests__/tap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import {
defineQueryFeeModels,
GraphNode,
Network,
EscrowAccounts,
QueryFeeModels,
TapSubgraphResponse,
TapCollector,
Allocation,
} from '@graphprotocol/indexer-common'
import {
Address,
Expand Down Expand Up @@ -499,6 +501,36 @@ describe('TAP', () => {
},
timeout,
)

test('test `submitRAVs` with escrow account lower on balance', async () => {
// mock redeemRav to not call the blockchain
const redeemRavFunc = jest
.spyOn(tapCollector, 'redeemRav')
.mockImplementation(jest.fn())

// mock fromResponse to return the correct escrow account
// eslint-disable-next-line @typescript-eslint/no-unused-vars
jest.spyOn(EscrowAccounts, 'fromResponse').mockImplementation((_) => {
const balances = new Map<Address, bigint>()
balances.set(SENDER_ADDRESS_1, 40000000000000n)
return new EscrowAccounts(balances)
})

const [first] = await queryFeeModels.receiptAggregateVouchers.findAll()
const rav = first.getSignedRAV()

const ravWithAllocation = {
rav,
allocation: {} as Allocation,
sender: first.senderAddress,
}
const ravs = [ravWithAllocation, ravWithAllocation, ravWithAllocation]
// submit 3 ravs
await tapCollector['submitRAVs'](ravs)
// expect to be able to redeem only 2 of them
// because of the balance
expect(redeemRavFunc).toBeCalledTimes(2)
})
})

function createLastNonFinalRav(
Expand Down
1 change: 1 addition & 0 deletions packages/indexer-common/src/allocations/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './escrow-accounts'
export * from './keys'
export * from './query-fees'
export * from './tap-collector'
Expand Down
106 changes: 59 additions & 47 deletions packages/indexer-common/src/allocations/tap-collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ interface ValidRavs {
eligible: RavWithAllocation[]
}

interface RavWithAllocation {
export interface RavWithAllocation {
rav: SignedRAV
allocation: Allocation
sender: Address
Expand Down Expand Up @@ -450,7 +450,6 @@ export class TapCollector {
)
return
}
const escrow = this.tapContracts

logger.info(`Redeem last RAVs on chain individually`, {
signedRavs,
Expand Down Expand Up @@ -481,54 +480,10 @@ export class TapCollector {
allocation: rav.allocationId,
})
try {
const proof = await tapAllocationIdProof(
allocationSigner(this.transactionManager.wallet, allocation),
parseInt(this.protocolNetwork.split(':')[1]),
sender,
toAddress(rav.allocationId),
toAddress(escrow.escrow.address),
)
this.logger.debug(`Computed allocationIdProof`, {
allocationId: rav.allocationId,
proof,
})
// Submit the signed RAV on chain
const txReceipt = await this.transactionManager.executeTransaction(
() => escrow.escrow.estimateGas.redeem(signedRav, proof),
(gasLimit) =>
escrow.escrow.redeem(signedRav, proof, {
gasLimit,
}),
logger.child({ function: 'redeem' }),
)

// get tx receipt and post process
if (txReceipt === 'paused' || txReceipt === 'unauthorized') {
this.metrics.ravRedeemsInvalid.inc({ allocation: rav.allocationId })
return
}
await this.redeemRav(logger, allocation, sender, signedRav)
// subtract from the escrow account
// THIS IS A MUT OPERATION
escrowAccounts.subtractSenderBalance(sender, ravValue)

this.metrics.ravCollectedFees.set(
{ allocation: rav.allocationId },
parseFloat(rav.valueAggregate.toString()),
)

try {
await this.markRavAsRedeemed(toAddress(rav.allocationId), sender)
logger.info(
`Updated receipt aggregate vouchers table with redeemed_at for allocation ${rav.allocationId} and sender ${sender}`,
)
} catch (err) {
logger.warn(
`Failed to update receipt aggregate voucher table with redeemed_at for allocation ${rav.allocationId}`,
{
err,
},
)
}
} catch (err) {
this.metrics.ravRedeemsFailed.inc({ allocation: rav.allocationId })
logger.error(`Failed to redeem RAV`, {
Expand Down Expand Up @@ -571,6 +526,63 @@ export class TapCollector {
)
}

public async redeemRav(
logger: Logger,
allocation: Allocation,
sender: Address,
signedRav: SignedRAV,
) {
const { rav } = signedRav

const escrow = this.tapContracts

const proof = await tapAllocationIdProof(
allocationSigner(this.transactionManager.wallet, allocation),
parseInt(this.protocolNetwork.split(':')[1]),
sender,
toAddress(rav.allocationId),
toAddress(escrow.escrow.address),
)
this.logger.debug(`Computed allocationIdProof`, {
allocationId: rav.allocationId,
proof,
})
// Submit the signed RAV on chain
const txReceipt = await this.transactionManager.executeTransaction(
() => escrow.escrow.estimateGas.redeem(signedRav, proof),
(gasLimit) =>
escrow.escrow.redeem(signedRav, proof, {
gasLimit,
}),
logger.child({ function: 'redeem' }),
)

// get tx receipt and post process
if (txReceipt === 'paused' || txReceipt === 'unauthorized') {
this.metrics.ravRedeemsInvalid.inc({ allocation: rav.allocationId })
return
}

this.metrics.ravCollectedFees.set(
{ allocation: rav.allocationId },
parseFloat(rav.valueAggregate.toString()),
)

try {
await this.markRavAsRedeemed(toAddress(rav.allocationId), sender)
logger.info(
`Updated receipt aggregate vouchers table with redeemed_at for allocation ${rav.allocationId} and sender ${sender}`,
)
} catch (err) {
logger.warn(
`Failed to update receipt aggregate voucher table with redeemed_at for allocation ${rav.allocationId}`,
{
err,
},
)
}
}

private async markRavAsRedeemed(
allocationId: Address,
senderAddress: Address,
Expand Down

0 comments on commit 34abfce

Please sign in to comment.