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

WIP: copy indexer deposits data to scraper db #506

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

melisaguevara
Copy link

@melisaguevara melisaguevara commented Dec 31, 2024

Configuration steps to use both databases from the indexer can be found here: https://linear.app/uma/issue/ACX-3496/copy-indexer-deposits-data-to-scraper-db

Copy link

linear bot commented Dec 31, 2024

Comment on lines +3 to +6
networks:
test-network:
external: true

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This network can be renamed.
I still have to check that both the indexer and scraper work fine using this network.
Indexer draft PR configuring the network: across-protocol/indexer#142

@@ -27,21 +33,26 @@ services:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE_NAME}
PG_DATA: /var/lib/postgresql/data
command: ["postgres", "-c", "log_statement=all"]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just to debug the auth issue I am having. Can be deleted after

ports:
- 5432:5432
- 5433:5432
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to avoid port collisions between indexer and scraper

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mainly a copy of the precious service but adapted to the new deposits and rewards table structures.

Comment on lines +47 to +88
public async getEarnedRewards(userAddress: string) {
userAddress = assertValidAddress(userAddress);

const baseQuery = this.buildBaseQuery(this.rewardRepository.createQueryBuilder("r"), userAddress);
const { opRewards } = await baseQuery
.select("SUM(CAST(r.amount as DECIMAL))", "opRewards")
.where("r.isClaimed = :isClaimed", { isClaimed: true })
.getRawOne<{ opRewards: string }>();

return opRewards;
}

public async getOpRebatesSummary(userAddress: string) {
userAddress = assertValidAddress(userAddress);

const baseQuery = this.buildBaseQuery(this.rewardRepository.createQueryBuilder("r"), userAddress);
baseQuery.andWhere("r.isClaimed = :isClaimed", { isClaimed: false });
const [{ depositsCount }, { unclaimedRewards }, { volumeUsd }] = await Promise.all([
baseQuery.select("COUNT(DISTINCT r.depositPrimaryKey)", "depositsCount").getRawOne<{
depositsCount: string;
}>(),
baseQuery.select("SUM(CAST(r.amount as DECIMAL))", "unclaimedRewards").getRawOne<{
unclaimedRewards: number;
}>(),
baseQuery
.leftJoinAndSelect("r.deposit", "d")
.leftJoinAndSelect("d.token", "t")
.leftJoinAndSelect("d.price", "p")
.select(`COALESCE(SUM(d.amount / power(10, t.decimals) * p.usd), 0)`, "volumeUsd")
.getRawOne<{
volumeUsd: number;
}>(),
// TODO: add claimable rewards
]);

return {
depositsCount: parseInt(depositsCount),
unclaimedRewards,
volumeUsd,
claimableRewards: "0",
};
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested this functions still work as expected.

Comment on lines +90 to +117
// public async getOpRebateRewards(query: GetRewardsQuery) {
// const limit = parseInt(query.limit ?? "10");
// const offset = parseInt(query.offset ?? "0");
// const userAddress = assertValidAddress(query.userAddress);

// const baseQuery = this.buildBaseQuery(this.rewardRepository.createQueryBuilder("r"), userAddress);

// const rewardsQuery = baseQuery.orderBy("r.depositDate", "DESC").limit(limit).offset(offset);
// const [rewards, total] = await rewardsQuery.getManyAndCount();

// // JOIN instead of query deposits separately
// const depositPrimaryKeys = rewards.map((reward) => reward.depositPrimaryKey);
// const deposits = await this.depositRepository.find({
// where: { id: In(depositPrimaryKeys) },
// });

// return {
// rewards: rewards.map((reward) => ({
// ...reward,
// deposit: deposits.find((deposit) => deposit.id === reward.depositPrimaryKey),
// })),
// pagination: {
// limit,
// offset,
// total,
// },
// };
// }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be rewritten to use JOIN instead of separate queries now that the FK between rewards and deposits is a composite key (depositId, originChainId).

Comment on lines +29 to +34
@OneToOne(() => RewardedDeposit)
@JoinColumn([
{ name: "depositId", referencedColumnName: "depositId", foreignKeyConstraintName: "FK_op_reward_deposit" },
{ name: "originChainId", referencedColumnName: "originChainId", foreignKeyConstraintName: "FK_op_reward_deposit" },
])
deposit: RewardedDeposit;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This relation used to be ManyToOne, but I think it's ok to set it to OneToOne.

// We use the `from` address of the deposit transaction as the reward receiver
// to also take into accounts deposits routed through the SpokePoolVerifier contract.
const provider = this.ethProvidersService.getProvider(deposit.originChainId);
const depositTransaction = await provider.getTransaction(deposit.depositTxHash); // This could also be part of the indexer data
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could fetch this in the indexer as we are already retrieving the transaction.

Comment on lines +280 to +281
const inputToken = await this.ethProvidersService.getCachedToken(deposit.originChainId, deposit.inputToken);
const outputToken = await this.ethProvidersService.getCachedToken(deposit.originChainId, deposit.outputToken);
Copy link
Author

@melisaguevara melisaguevara Dec 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we no longer have the token relation, we have to get token details using the addresses.
This is erroring locally for me with some chains though. It fails with:
Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="symbol()", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)

const inputToken = await this.ethProvidersService.getCachedToken(deposit.originChainId, deposit.inputToken);
const outputToken = await this.ethProvidersService.getCachedToken(deposit.originChainId, deposit.outputToken);

const inputTokenPrice = await this.getInputTokenPrice(deposit, inputToken, outputToken); // This could also be part of the indexer data
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also be part of the indexer data, but for now I'm fetching it here too.
This is needed to calculate the MAX reward amount for each deposit.

Comment on lines +82 to +87
WHERE
indexer_rhi."status" = 'filled'
AND indexer_deposit_events.finalised is true
AND indexer_fills.finalised is true
AND indexer_rhi."destinationChainId" in (${eligibleDestinationChains})
LIMIT 5000
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also add a condition here to fetch only deposits starting from 2025.

Comment on lines +96 to +99
performance.mark("query-start");
const newFilledDeposits = await this.dataSource.query(newFilledDepositsQuery) as RewardedDeposit[];
performance.mark("query-end");
performance.measure("query", "query-start", "query-end");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance marks can be deleted before merging

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant