From fe392069e6a040104a9a46b8a464058de63a49f3 Mon Sep 17 00:00:00 2001 From: Chris Jacobs Date: Mon, 28 Oct 2024 12:32:41 -0700 Subject: [PATCH] Add `TraderateChanged` for ARM --- ...97704620-Data.js => 1730140167059-Data.js} | 16 +++++- schema.graphql | 11 ++++ schema/arm.graphql | 11 ++++ src/model/generated/index.ts | 1 + src/model/generated/traderateChanged.model.ts | 37 +++++++++++++ src/oeth/processors/strategies.ts | 4 -- src/templates/events/createEventProcessor.ts | 5 +- src/templates/origin-arm/origin-arm.ts | 55 +++++++++++-------- 8 files changed, 108 insertions(+), 32 deletions(-) rename db/migrations/{1729897704620-Data.js => 1730140167059-Data.js} (99%) create mode 100644 src/model/generated/traderateChanged.model.ts diff --git a/db/migrations/1729897704620-Data.js b/db/migrations/1730140167059-Data.js similarity index 99% rename from db/migrations/1729897704620-Data.js rename to db/migrations/1730140167059-Data.js index 6d99b21..e4786c8 100644 --- a/db/migrations/1729897704620-Data.js +++ b/db/migrations/1730140167059-Data.js @@ -1,5 +1,5 @@ -module.exports = class Data1729897704620 { - name = 'Data1729897704620' +module.exports = class Data1730140167059 { + name = 'Data1730140167059' async up(db) { await db.query(`CREATE TABLE "aero_cl_gauge_claim_fees" ("id" character varying NOT NULL, "chain_id" integer NOT NULL, "block_number" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "address" text NOT NULL, "from" text NOT NULL, "claimed0" numeric NOT NULL, "claimed1" numeric NOT NULL, CONSTRAINT "PK_324db7f817fe71a6a8dfc04701a" PRIMARY KEY ("id"))`) @@ -372,6 +372,12 @@ module.exports = class Data1729897704620 { await db.query(`CREATE INDEX "IDX_f19a1f1ecd4b69d3def526cf6d" ON "arm_withdrawal_request" ("block_number") `) await db.query(`CREATE INDEX "IDX_a66956c5f52400d8800132b21f" ON "arm_withdrawal_request" ("address") `) await db.query(`CREATE INDEX "IDX_87f6fbcd7e96024c7d413e0496" ON "arm_withdrawal_request" ("account") `) + await db.query(`CREATE TABLE "traderate_changed" ("id" character varying NOT NULL, "chain_id" integer NOT NULL, "tx_hash" text NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "address" text NOT NULL, "traderate0" numeric NOT NULL, "traderate1" numeric NOT NULL, CONSTRAINT "PK_479a7665a7814427a59d0acf7b9" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_d556cdea4a5d7c1bbe68af5540" ON "traderate_changed" ("chain_id") `) + await db.query(`CREATE INDEX "IDX_705910a32dde2d3bb5afe3baaf" ON "traderate_changed" ("tx_hash") `) + await db.query(`CREATE INDEX "IDX_ee5733a47926aa5d45d925e427" ON "traderate_changed" ("timestamp") `) + await db.query(`CREATE INDEX "IDX_8ba4cfdcc71cd663da41d5c683" ON "traderate_changed" ("block_number") `) + await db.query(`CREATE INDEX "IDX_767274005ca866b0c3a89956e1" ON "traderate_changed" ("address") `) await db.query(`CREATE TABLE "coin_gecko_coin_data" ("id" character varying NOT NULL, "product" text NOT NULL, "date" text NOT NULL, "vs_currency" text NOT NULL, "price" numeric NOT NULL, "market_cap" numeric NOT NULL, "trading_volume" numeric NOT NULL, CONSTRAINT "PK_abb8340f8d830c27b3288a1083c" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_55f8b56cad28caa22a995dfb83" ON "coin_gecko_coin_data" ("product") `) await db.query(`CREATE INDEX "IDX_821542437abc5d0d6aa7959131" ON "coin_gecko_coin_data" ("date") `) @@ -1120,6 +1126,12 @@ module.exports = class Data1729897704620 { await db.query(`DROP INDEX "public"."IDX_f19a1f1ecd4b69d3def526cf6d"`) await db.query(`DROP INDEX "public"."IDX_a66956c5f52400d8800132b21f"`) await db.query(`DROP INDEX "public"."IDX_87f6fbcd7e96024c7d413e0496"`) + await db.query(`DROP TABLE "traderate_changed"`) + await db.query(`DROP INDEX "public"."IDX_d556cdea4a5d7c1bbe68af5540"`) + await db.query(`DROP INDEX "public"."IDX_705910a32dde2d3bb5afe3baaf"`) + await db.query(`DROP INDEX "public"."IDX_ee5733a47926aa5d45d925e427"`) + await db.query(`DROP INDEX "public"."IDX_8ba4cfdcc71cd663da41d5c683"`) + await db.query(`DROP INDEX "public"."IDX_767274005ca866b0c3a89956e1"`) await db.query(`DROP TABLE "coin_gecko_coin_data"`) await db.query(`DROP INDEX "public"."IDX_55f8b56cad28caa22a995dfb83"`) await db.query(`DROP INDEX "public"."IDX_821542437abc5d0d6aa7959131"`) diff --git a/schema.graphql b/schema.graphql index 4822da9..2cbf7a3 100644 --- a/schema.graphql +++ b/schema.graphql @@ -824,6 +824,17 @@ type ArmWithdrawalRequest @entity { queued: BigInt! claimed: Boolean! } + +type TraderateChanged @entity { + id: ID! + chainId: Int! @index + txHash: String! @index + timestamp: DateTime! @index + blockNumber: Int! @index + address: String! @index + traderate0: BigInt! + traderate1: BigInt! +} type CoinGeckoCoinData @entity { id: ID! product: String! @index diff --git a/schema/arm.graphql b/schema/arm.graphql index 6756dfa..5fa2d94 100644 --- a/schema/arm.graphql +++ b/schema/arm.graphql @@ -75,3 +75,14 @@ type ArmWithdrawalRequest @entity { queued: BigInt! claimed: Boolean! } + +type TraderateChanged @entity { + id: ID! + chainId: Int! @index + txHash: String! @index + timestamp: DateTime! @index + blockNumber: Int! @index + address: String! @index + traderate0: BigInt! + traderate1: BigInt! +} diff --git a/src/model/generated/index.ts b/src/model/generated/index.ts index 56ba09e..ed4a857 100644 --- a/src/model/generated/index.ts +++ b/src/model/generated/index.ts @@ -57,6 +57,7 @@ export * from "./arm.model" export * from "./armState.model" export * from "./armDailyStat.model" export * from "./armWithdrawalRequest.model" +export * from "./traderateChanged.model" export * from "./coinGeckoCoinData.model" export * from "./esToken.model" export * from "./esAccount.model" diff --git a/src/model/generated/traderateChanged.model.ts b/src/model/generated/traderateChanged.model.ts new file mode 100644 index 0000000..0e50d07 --- /dev/null +++ b/src/model/generated/traderateChanged.model.ts @@ -0,0 +1,37 @@ +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, IntColumn as IntColumn_, Index as Index_, StringColumn as StringColumn_, DateTimeColumn as DateTimeColumn_, BigIntColumn as BigIntColumn_} from "@subsquid/typeorm-store" + +@Entity_() +export class TraderateChanged { + constructor(props?: Partial) { + Object.assign(this, props) + } + + @PrimaryColumn_() + id!: string + + @Index_() + @IntColumn_({nullable: false}) + chainId!: number + + @Index_() + @StringColumn_({nullable: false}) + txHash!: string + + @Index_() + @DateTimeColumn_({nullable: false}) + timestamp!: Date + + @Index_() + @IntColumn_({nullable: false}) + blockNumber!: number + + @Index_() + @StringColumn_({nullable: false}) + address!: string + + @BigIntColumn_({nullable: false}) + traderate0!: bigint + + @BigIntColumn_({nullable: false}) + traderate1!: bigint +} diff --git a/src/oeth/processors/strategies.ts b/src/oeth/processors/strategies.ts index a3cb8cd..47fa709 100644 --- a/src/oeth/processors/strategies.ts +++ b/src/oeth/processors/strategies.ts @@ -171,10 +171,8 @@ const eventProcessors = [ ...OETH_NATIVE_STRATEGY_ADDRESSES.map((address) => createEventProcessor({ address, - eventName: 'AccountingConsensusRewards', event: nativeStakingAbi.events.AccountingConsensusRewards, from: 20046251, - Entity: AccountingConsensusRewards, mapEntity: (ctx, block, log, decoded) => new AccountingConsensusRewards({ id: `${ctx.chain.id}:${log.id}`, @@ -188,10 +186,8 @@ const eventProcessors = [ ), createEventProcessor({ address: addresses.oeth.nativeStakingFeeAccumulator, - eventName: 'ExecutionRewardsCollected', event: feeAccumulatorAbi.events.ExecutionRewardsCollected, from: 20046238, - Entity: ExecutionRewardsCollected, mapEntity: (ctx, block, log, decoded) => new ExecutionRewardsCollected({ id: `${ctx.chain.id}:${log.id}`, diff --git a/src/templates/events/createEventProcessor.ts b/src/templates/events/createEventProcessor.ts index 8515cff..9da03c5 100644 --- a/src/templates/events/createEventProcessor.ts +++ b/src/templates/events/createEventProcessor.ts @@ -5,14 +5,11 @@ import { DecodedStruct, Struct } from '@subsquid/evm-codec' import { EvmBatchProcessor } from '@subsquid/evm-processor' import { Entity } from '@subsquid/typeorm-store/lib/store' import { logFilter } from '@utils/logFilter' -import { EntityClassT } from '@utils/type' export const createEventProcessor = (params: { - eventName: string event: ReturnType> address: string from: number - Entity: EntityClassT mapEntity: (ctx: Context, block: Block, log: Log, decoded: DecodedStruct>) => EventEntity extraFilterArgs?: { topic1?: string[] @@ -35,7 +32,7 @@ export const createEventProcessor = { + return new TraderateChanged({ + id: `${ctx.chain.id}:${log.id}`, + chainId: ctx.chain.id, + txHash: log.transactionHash, + timestamp: new Date(block.header.timestamp), + blockNumber: block.header.height, + address: armAddress, + traderate0: decoded.traderate0, + traderate1: decoded.traderate1, + }) + }, + }) const tracker = blockFrequencyTracker({ from }) let armEntity: Arm let initialized = false @@ -92,6 +110,7 @@ export const createOriginARMProcessors = ({ p.addLog(depositFilter.value) p.addLog(withdrawalFilter.value) p.addLog(feeCollectedFilter.value) + tradeRateProcessor.setup(p) }, initialize, process: async (ctx: Context) => { @@ -103,7 +122,7 @@ export const createOriginARMProcessors = ({ const dailyStatsMap = new Map() const redemptionMap = new Map() const getStateId = (block: Block) => `${ctx.chain.id}:${block.header.height}:${armAddress}` - const getPreviousState = async (block: Block) => { + const getPreviousState = async () => { return ( last(states) ?? (await ctx.store.findOne(ArmState, { @@ -117,28 +136,19 @@ export const createOriginARMProcessors = ({ if (states[states.length - 1]?.id === stateId) { return states[states.length - 1] } - const previousState = await getPreviousState(block) + const previousState = await getPreviousState() const armContract = new originLidoArmAbi.Contract(ctx, block.header, armAddress) const controllerContract = new originLidoArmCapManagerAbi.Contract(ctx, block.header, capManagerAddress) - const [ - assets0, - assets1, - outstandingAssets1, - totalAssets, - totalAssetsCap, - totalSupply, - assetsPerShare, - feesAccrued, - ] = await Promise.all([ - new erc20Abi.Contract(ctx, block.header, armEntity.token0).balanceOf(armAddress), - new erc20Abi.Contract(ctx, block.header, armEntity.token1).balanceOf(armAddress), - armContract.lidoWithdrawalQueueAmount(), - armContract.totalAssets(), - controllerContract.totalAssetsCap(), - armContract.totalSupply(), - armContract.previewRedeem(10n ** 18n), - armContract.feesAccrued(), - ]) + const [assets0, assets1, outstandingAssets1, totalAssets, totalAssetsCap, totalSupply, assetsPerShare] = + await Promise.all([ + new erc20Abi.Contract(ctx, block.header, armEntity.token0).balanceOf(armAddress), + new erc20Abi.Contract(ctx, block.header, armEntity.token1).balanceOf(armAddress), + armContract.lidoWithdrawalQueueAmount(), + armContract.totalAssets(), + controllerContract.totalAssetsCap(), + armContract.totalSupply(), + armContract.previewRedeem(10n ** 18n), + ]) const date = new Date(block.header.timestamp) const armStateEntity = new ArmState({ id: stateId, @@ -259,6 +269,7 @@ export const createOriginARMProcessors = ({ await ctx.store.insert(states) await ctx.store.upsert([...dailyStatsMap.values()]) await ctx.store.upsert([...redemptionMap.values()]) + await tradeRateProcessor.process(ctx) }, }, // The ARM is an ERC20, so we can use the ERC20SimpleTracker to track holder balances