diff --git a/migrations/1669984610620-DepositsMv.ts b/migrations/1669984610620-DepositsMv.ts new file mode 100644 index 00000000..71e57bfa --- /dev/null +++ b/migrations/1669984610620-DepositsMv.ts @@ -0,0 +1,81 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class DepositsMv1669984610620 implements MigrationInterface { + name = "DepositsMv1669984610620"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP MATERIALIZED VIEW IF EXISTS "deposits_mv"`); + await queryRunner.query(`DROP VIEW IF EXISTS "deposits_filtered_referrals"`); + await queryRunner.query(`CREATE VIEW "deposits_filtered_referrals" AS + SELECT + d.id, + d."depositorAddr", + d."stickyReferralAddress", + d."depositDate", + d."priceId", + d."tokenId", + d.amount, + d."rewardsWindowIndex", + case when d."rewardsWindowIndex" = c."windowIndex" then d."rewardsWindowIndex" else -1 end as "referralClaimedWindowIndex", + hmp."usd", + t.decimals + FROM deposit d + JOIN historic_market_price hmp on d."priceId" = hmp.id + JOIN token t on d."tokenId" = t.id + LEFT JOIN claim c on d."rewardsWindowIndex" = c."windowIndex" and d."stickyReferralAddress" = c."account" + WHERE "stickyReferralAddress" is not null + AND "depositDate" is not null + AND "tokenId" is not null + AND "priceId" is not null + AND status = 'filled' + AND d."acxUsdPrice" is not null; + `); + + await queryRunner.query(`CREATE MATERIALIZED VIEW "deposits_mv" AS + SELECT + d.id, + d."depositId", + d."depositTxHash", + d."sourceChainId", + d."destinationChainId", + d.amount, + t.symbol, + t.decimals, + d."depositorAddr", + d."rewardsWindowIndex", + case when d."rewardsWindowIndex" = c."windowIndex" and d."depositorAddr" = c.account then d."rewardsWindowIndex" else -1 end as "depositorClaimedWindowIndex", + d1."referralClaimedWindowIndex", + d."stickyReferralAddress" AS "referralAddress", + d."depositDate", + hmp.usd AS "tokenUsdPrice", + (d."realizedLpFeePctCapped" / power(10, 18)) * (d.amount / power(10, t.decimals)) * hmp.usd AS "realizedLpFeeUsd", + (d."bridgeFeePct" / power(10, 18)) * (d.amount / power(10, t.decimals)) * hmp.usd AS "bridgeFeeUsd", + d."acxUsdPrice", + CASE + WHEN d1."referralCount" >= 20 OR d1."referralVolume" >= 500000 THEN 0.8 + WHEN d1."referralCount" >= 10 OR d1."referralVolume" >= 250000 THEN 0.7 + WHEN d1."referralCount" >= 5 OR d1."referralVolume" >= 100000 THEN 0.6 + WHEN d1."referralCount" >= 3 OR d1."referralVolume" >= 50000 THEN 0.5 + ELSE 0.4 + END AS "referralRate", + CASE + WHEN d."depositDate" < '2022-07-22 17:00:00' THEN 3 + ELSE 2 + END AS multiplier + FROM deposit d + JOIN "deposit_referral_stat" d1 ON d."id" = d1."depositId" + JOIN token t ON d."tokenId" = t.id + JOIN historic_market_price hmp ON d."priceId" = hmp.id + LEFT JOIN claim c on d."rewardsWindowIndex" = c."windowIndex" and c.account = d."depositorAddr" + ORDER BY d."depositDate" desc; + `); + await queryRunner.query( + `CREATE UNIQUE INDEX "UK_deposits_mv_depositId_sourceChainId" ON deposits_mv ("depositId", "sourceChainId");`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP MATERIALIZED VIEW "deposits_mv"`); + await queryRunner.query(`DROP VIEW "deposits_filtered_referrals"`); + } +} diff --git a/src/modules/configuration/index.ts b/src/modules/configuration/index.ts index 6b098f26..06860ade 100644 --- a/src/modules/configuration/index.ts +++ b/src/modules/configuration/index.ts @@ -73,7 +73,6 @@ export const configValues = () => ({ address: process.env.ACX_ADDRESS || "0x40153DdFAd90C49dbE3F5c9F96f2a5B25ec67461", // TODO: replace with mainnet, }, }, - acxUsdPrice: 0.1, enableSpokePoolsEventsProcessing: process.env.ENABLE_SPOKE_POOLS_EVENTS_PROCESSING === "true", enableMerkleDistributorEventsProcessing: process.env.ENABLE_MERKLE_DISTRIBUTOR_EVENTS_PROCESSING === "true", enableReferralsMaterializedViewRefresh: process.env.ENABLE_REFERRALS_MATERIALIZED_VIEW_REFRESH === "true", diff --git a/src/modules/deposit/model/DepositsMv.entity.ts b/src/modules/deposit/model/DepositsMv.entity.ts index e8d61f5f..79b25c3a 100644 --- a/src/modules/deposit/model/DepositsMv.entity.ts +++ b/src/modules/deposit/model/DepositsMv.entity.ts @@ -24,6 +24,7 @@ import { DepositReferralStats } from "../../referral/model/DepositReferralStats. hmp.usd AS "tokenUsdPrice", (d."realizedLpFeePctCapped" / power(10, 18)) * (d.amount / power(10, t.decimals)) * hmp.usd AS "realizedLpFeeUsd", (d."bridgeFeePct" / power(10, 18)) * (d.amount / power(10, t.decimals)) * hmp.usd AS "bridgeFeeUsd", + d."acxUsdPrice", CASE WHEN d1."referralCount" >= 20 OR d1."referralVolume" >= 500000 THEN 0.8 WHEN d1."referralCount" >= 10 OR d1."referralVolume" >= 250000 THEN 0.7 @@ -101,4 +102,7 @@ export class DepositsMv { @ViewColumn() bridgeFeeUsd: string; + + @ViewColumn() + acxUsdPrice: string; } diff --git a/src/modules/referral/model/DepositsFilteredReferrals.entity.ts b/src/modules/referral/model/DepositsFilteredReferrals.entity.ts index be5f370f..697cf05b 100644 --- a/src/modules/referral/model/DepositsFilteredReferrals.entity.ts +++ b/src/modules/referral/model/DepositsFilteredReferrals.entity.ts @@ -22,7 +22,8 @@ import { ViewEntity, ViewColumn } from "typeorm"; AND "depositDate" is not null AND "tokenId" is not null AND "priceId" is not null - AND status = 'filled'; + AND status = 'filled' + AND d."acxUsdPrice" is not null; `, }) export class DepositsFilteredReferrals { diff --git a/src/modules/referral/services/queries.ts b/src/modules/referral/services/queries.ts index 83e365a3..b85df3fc 100644 --- a/src/modules/referral/services/queries.ts +++ b/src/modules/referral/services/queries.ts @@ -4,17 +4,17 @@ export const getReferralsQuery = () => { *, case when d."depositorAddr" = $1 and d."referralAddress" = $1 - then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / $2 * power(10, 18) * d.multiplier as decimal)) + then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / d."acxUsdPrice" * power(10, 18) * d.multiplier as decimal)) when d."depositorAddr" = $1 - then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / $2 * 0.25 * power(10, 18) * d.multiplier as decimal)) - else trunc(cast(d."bridgeFeeUsd" * d."referralRate" / $2 * 0.75 * power(10, 18) * d.multiplier as decimal)) + then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / d."acxUsdPrice" * 0.25 * power(10, 18) * d.multiplier as decimal)) + else trunc(cast(d."bridgeFeeUsd" * d."referralRate" / d."acxUsdPrice" * 0.75 * power(10, 18) * d.multiplier as decimal)) end as "acxRewards" from deposits_mv as d where d."referralAddress" = $1 or (d."depositorAddr" = $1 and d."referralAddress" is not null) order by d."depositDate" DESC - limit $3 - offset $4; + limit $2 + offset $3; `; }; @@ -33,10 +33,10 @@ export const getTotalReferralRewardsQuery = () => { sum( case when d."depositorAddr" = $1 and d."referralAddress" = $1 - then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / $2 * power(10, 18) * d.multiplier as decimal)) + then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / d."acxUsdPrice" * power(10, 18) * d.multiplier as decimal)) when d."depositorAddr" = $1 - then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / $2 * 0.25 * power(10, 18) * d.multiplier as decimal)) - else trunc(cast(d."bridgeFeeUsd" * d."referralRate" / $2 * 0.75 * power(10, 18) * d.multiplier as decimal)) + then trunc(cast(d."bridgeFeeUsd" * d."referralRate" / d."acxUsdPrice" * 0.25 * power(10, 18) * d.multiplier as decimal)) + else trunc(cast(d."bridgeFeeUsd" * d."referralRate" / d."acxUsdPrice" * 0.75 * power(10, 18) * d.multiplier as decimal)) end ) as "acxRewards" from deposits_mv as d diff --git a/src/modules/referral/services/service.ts b/src/modules/referral/services/service.ts index 3be66da2..de6b1cf8 100644 --- a/src/modules/referral/services/service.ts +++ b/src/modules/referral/services/service.ts @@ -60,7 +60,7 @@ export class ReferralService { this.depositRepository.query(referreeWalletsQuery, [address]), this.depositRepository.query(referralTransfersQuery, [address]), this.depositRepository.query(referralVolumeQuery, [address]), - this.depositRepository.query(totalReferralRewardsQuery, [address, this.appConfig.values.acxUsdPrice]), + this.depositRepository.query(totalReferralRewardsQuery, [address]), this.depositRepository.query(activeRefereesCountQuery, [address]), ]); @@ -89,7 +89,7 @@ export class ReferralService { const query = getReferralsQuery(); const totalQuery = getReferralsTotalQuery(); const [result, totalResult] = await Promise.all([ - this.depositRepository.manager.query(query, [address, this.appConfig.values.acxUsdPrice, limit, offset]), + this.depositRepository.manager.query(query, [address, limit, offset]), this.depositRepository.query(totalQuery, [address]), ]); const total = parseInt(totalResult[0].count); @@ -242,7 +242,7 @@ export class ReferralService { .multipliedBy(feePct) .multipliedBy(d.multiplier) .multipliedBy(new BigNumber(10).pow(18)) - .dividedBy(this.appConfig.values.acxUsdPrice) + .dividedBy(d.acxUsdPrice) .toFixed(0); return sum.plus(rewards); }, new BigNumber(0));