Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redeem test #835

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions packages/indexer-common/src/__tests__/redeem-rav-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { AllocationReceiptCollector } from './../allocations/query-fees'
import { AllocationStatus, SubgraphDeployment } from '@graphprotocol/indexer-common'
import {
Logger,
Metrics,
Eventual,
SubgraphDeploymentID,
EventualValue,
} from '@graphprotocol/common-ts'
import { BigNumber, Contract, providers, Wallet } from 'ethers'
import {
Gateway,
IndexerOptions,
TransactionMonitoring,
} from './../network-specification'
import {
NetworkContracts as EscrowContracts,
connectContracts,
} from '@semiotic-labs/tap-contracts-bindings'
import { toAddress } from '@graphprotocol/common-ts'
import { Allocation, QueryFeeModels, TransactionManager, specification as spec } from '..'
function createAllocation(id: string, indexer: string): Allocation {
const subgraphDeploymentID = new SubgraphDeploymentID('mock-deployment-id')
const mockSubgraphDeployment: SubgraphDeployment = {
id: subgraphDeploymentID,
deniedAt: Date.now(),
stakedTokens: BigNumber.from('1000'),
signalledTokens: BigNumber.from('500'),
queryFeesAmount: BigNumber.from('200'),
protocolNetwork: 'mainnet',
}
return {
id: toAddress(`0x${id}`),
status: AllocationStatus.ACTIVE,
subgraphDeployment: mockSubgraphDeployment,
indexer: toAddress(`0x${indexer}`),
allocatedTokens: BigNumber.from(1000),
createdAtEpoch: 1,
createdAtBlockHash: '',
closedAtEpoch: 1,
closedAtEpochStartBlockHash: '',
previousEpochStartBlockHash: '',
closedAtBlockHash: '',
poi: '',
queryFeeRebates: BigNumber.from(1000),
queryFeesCollected: BigNumber.from(1000),
}
}
// const histogramConfig = {
// name: 'test_histogram',
// help: 'Histogram for testing purposes',
// labelNames: ['label1', 'label2'],
// buckets: [0.1, 5, 15, 50, 100, 500],
// }
//const mockHistogram = new Histogram<string>(histogramConfig)

describe('AllocationReceiptCollector', () => {
let mockLogger: Logger
let mockMetrics: Metrics
let transactionManager: TransactionManager
let escrowContracts: EscrowContracts
let paused: Eventual<boolean>
let isOperator: Eventual<boolean>
let mockModel: QueryFeeModels
let allocation: Allocation
let mockAllocationExchange: Contract
let networkSpecification: spec.NetworkSpecification
let allocations: Eventual<Allocation[]>
const TAPVerifierAddress = '0x995629b19667Ae71483DC812c1B5a35fCaaAF4B8'
const escrowAddress = '0x94dFeceb91678ec912ef8f14c72721c102ed2Df7'
const indexerAddress = '0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b' //<--receiver
//const gatewayAddress = '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1'
const allocationID = '0x3fD652C93dFA333979ad762Cf581Df89BaBa6795'
const allocationIDTrkrAddress = '0x25AF99b922857C37282f578F428CB7f34335B379'
const rpc_url = 'localhost:8545'
const chainId = 1337

beforeEach(async () => {
const provider = new providers.JsonRpcProvider()

const { allocationIDTracker, escrow, tapVerifier } = await connectContracts(
provider,
chainId,
{
[chainId]: {
TAPVerifier: TAPVerifierAddress,
AllocationIDTracker: allocationIDTrkrAddress,
Escrow: escrowAddress,
},
},
)

allocation = createAllocation(allocationID, indexerAddress)
const specification: TransactionMonitoring = {
gasIncreaseTimeout: 240,
gasIncreaseFactor: 1.2,
gasPriceMax: 50000,
maxTransactionAttempts: 3,
}
const existingAllocations: Allocation[] = [allocation]

allocations = new EventualValue(existingAllocations)

networkSpecification.networkIdentifier = '' // <-- Whats this
networkSpecification.gateway = Gateway.parse({
url: rpc_url, // <-- Url is it rpc url too?
})
networkSpecification.indexerOptions = IndexerOptions.parse({
mnemonic:
'myth like bonus scare over problem client lizard pioneer submit female collect',
url: rpc_url, // <-- Url is it rpc url too?
})

const wallet = new Wallet(
'6370fd033278c143179d81c5526140625662b8daa446c22ee2d73db3707e620c', // <--
provider,
) // <-- Is this the Gateway PK?

mockLogger = {
error: jest.fn(),
info: jest.fn(),
debug: jest.fn(),
child: jest.fn(),
} as unknown as Logger

mockMetrics = {
ravsRedeemDuration: {
startTimer: jest.fn(() => jest.fn()),
},
invalidRavRedeems: {
inc: jest.fn(),
},
ravCollectedFees: {
set: jest.fn(),
},
failedRavRedeems: {
inc: jest.fn(),
},
} as unknown as Metrics

transactionManager = new TransactionManager(
provider,
wallet,
paused,
isOperator,
specification,
)
// const collectorOptions = {
// logger: mockLogger,
// metrics: mockMetrics,
// transactionManager: transactionManager,
// models: mockModel,
// allocationExchange: mockAllocationExchange,
// escrowContracts: escrowContracts,
// allocations: allocations,
// networkSpecification: specification,
// }
})

it('should log an error if escrow contracts are undefined', async () => {
const signedRavs = [
{
message: {
allocationId: allocationID,
timestampNs: 123,
valueAggregate: 5,
},
signature: '',
},
]
try {
const collector = await AllocationReceiptCollector.create({
logger: mockLogger,
metrics: mockMetrics,
transactionManager: transactionManager,
models: mockModel,
allocationExchange: mockAllocationExchange,
escrowContracts: escrowContracts,
allocations: allocations,
networkSpecification: networkSpecification,
})

await (collector as any).submitRAVs(signedRavs)
} catch (error) {
console.error('Error creating AllocationReceiptCollector:', error)
}

// Check if the error logging method was called
expect(mockLogger.error).toHaveBeenCalled()
expect(mockLogger.error).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({ signedRavs }),
)
})

// ... other test cases
})
37 changes: 1 addition & 36 deletions packages/indexer-common/src/allocations/query-fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export class AllocationReceiptCollector implements ReceiptCollector {
collector.startReceiptCollecting()
collector.startVoucherProcessing()
if (collector.escrowContracts) {
collector.logger.info(`RAV processing is initiated`);
collector.logger.info(`RAV processing is initiated`)
collector.startRAVProcessing()
}
await collector.queuePendingReceiptsFromDatabase()
Expand Down Expand Up @@ -801,41 +801,6 @@ export class AllocationReceiptCollector implements ReceiptCollector {
stopTimer()
}

// Postprocess obsolete RAVs from the database
logger.info(`Successfully redeemed RAV, delete local copy`)
try {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await this.models.allocationSummaries.sequelize!.transaction(
async (transaction) => {
for (const signedRav of signedRavs) {
const [summary] = await ensureAllocationSummary(
this.models,
toAddress(signedRav.rav.allocationId),
transaction,
this.protocolNetwork,
)
summary.withdrawnFees = BigNumber.from(summary.withdrawnFees)
.add(signedRav.rav.valueAggregate)
.toString()
await summary.save({ transaction })
}
},
)

await this.models.receiptAggregateVouchers.destroy({
where: {
allocation_id: signedRavs.map((signedRav) => signedRav.rav.allocationId),
},
})
signedRavs.map((signedRav) =>
this.metrics.successRavRedeems.inc({ allocation: signedRav.rav.allocationId }),
)
logger.info(`Successfully deleted local RAV copy`)
} catch (err) {
logger.warn(`Failed to delete local RAV copy, will try again later`, {
err,
})
}
}

public async queuePendingReceiptsFromDatabase(): Promise<void> {
Expand Down
14 changes: 7 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@

"@graphprotocol/[email protected]":
version "0.1.16"
resolved "https://registry.npmjs.org/@graphprotocol/cost-model/-/cost-model-0.1.16.tgz"
resolved "https://registry.yarnpkg.com/@graphprotocol/cost-model/-/cost-model-0.1.16.tgz#42e6889a23934f293f119db9ac23159be019df0c"
integrity sha512-oDBhXH4sdKLduw0PgcK6rWPrzqJ4eFH9BTWz81c2iMIdTrm3n92eixCrhTwB3Nd1JpM1y0Bz9sMIvRGvC6htoA==
dependencies:
"@mapbox/node-pre-gyp" "1.0.9"
Expand Down Expand Up @@ -2066,7 +2066,7 @@

"@mapbox/[email protected]":
version "1.0.9"
resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz"
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz#09a8781a3a036151cdebbe8719d6f8b25d4058bc"
integrity sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==
dependencies:
detect-libc "^2.0.0"
Expand Down Expand Up @@ -2677,10 +2677,10 @@
"@noble/hashes" "~1.3.0"
"@scure/base" "~1.1.0"

"@semiotic-labs/tap-contracts-bindings@^1.1.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@semiotic-labs/tap-contracts-bindings/-/tap-contracts-bindings-1.1.0.tgz#94c18951eb4dbec1008f1e3b27134544981904d5"
integrity sha512-oVLx50mmhtypfORe6orchkmtKS6V09RJ0q9IkxG/ObVSQKZ/xCrdOwGIVJYUajhi6QdEt0Xh27b8rQVCtPKvsA==
"@semiotic-labs/tap-contracts-bindings@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@semiotic-labs/tap-contracts-bindings/-/tap-contracts-bindings-1.2.0.tgz#83835487dbfdae54f7dde2954389faf8cd12a559"
integrity sha512-bJfZAXug551h/vTYmo4XJh0BxV5XEe7FzZRXhdH2Hza+QZEp/pkx+JRppJjlvCpfqVglgzwLfp2X3CXlDvJm9A==
dependencies:
"@typechain/ethers-v5" "^11.1.2"
abitype "^0.10.3"
Expand Down Expand Up @@ -4291,7 +4291,7 @@ caniuse-lite@^1.0.30001517:

[email protected]:
version "0.1.6"
resolved "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz"
resolved "https://registry.yarnpkg.com/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz#df1bc9dad036ae0f4230639a869182e1d5850f89"
integrity sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==

[email protected]:
Expand Down