diff --git a/db/migrations/1714034652645-Data.js b/db/migrations/1717086042133-Data.js similarity index 89% rename from db/migrations/1714034652645-Data.js rename to db/migrations/1717086042133-Data.js index 232eacfc..c179d05d 100644 --- a/db/migrations/1714034652645-Data.js +++ b/db/migrations/1717086042133-Data.js @@ -1,5 +1,5 @@ -module.exports = class Data1714034652645 { - name = 'Data1714034652645' +module.exports = class Data1717086042133 { + name = 'Data1717086042133' async up(db) { await db.query( @@ -326,6 +326,42 @@ module.exports = class Data1714034652645 { await db.query( `CREATE TABLE "router" ("id" character varying NOT NULL, "paused" boolean NOT NULL, CONSTRAINT "PK_510c864aa88ac8eb3a306789801" PRIMARY KEY ("id"))` ) + await db.query( + `CREATE TABLE "nabla_swap" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "sender" text NOT NULL, "amount_in" numeric NOT NULL, "amount_out" numeric NOT NULL, "to" text NOT NULL, "token_in_id" character varying, "token_out_id" character varying, "swap_fee_id" character varying, CONSTRAINT "PK_6274610b518e1a9e61b1c6f03bb" PRIMARY KEY ("id"))` + ) + await db.query( + `CREATE INDEX "IDX_78ad17aaf8e256aada35d50c95" ON "nabla_swap" ("token_in_id") ` + ) + await db.query( + `CREATE INDEX "IDX_3ddf0d667a8f06da7f6ab50004" ON "nabla_swap" ("token_out_id") ` + ) + await db.query( + `CREATE INDEX "IDX_dd24afed240ad46290bfcf0603" ON "nabla_swap" ("swap_fee_id") ` + ) + await db.query( + `CREATE TABLE "nabla_backstop_liquidity_deposit" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "sender" text NOT NULL, "pool_shares_minted" numeric NOT NULL, "amount_pool_tokens_deposited" numeric NOT NULL, "backstop_pool_id" character varying, CONSTRAINT "PK_6a7b952f6ac801d591360e47743" PRIMARY KEY ("id"))` + ) + await db.query( + `CREATE INDEX "IDX_a3ce6e5ba78f5987919e7ee346" ON "nabla_backstop_liquidity_deposit" ("backstop_pool_id") ` + ) + await db.query( + `CREATE TABLE "nabla_swap_liquidity_deposit" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "sender" text NOT NULL, "pool_shares_minted" numeric NOT NULL, "amount_pool_tokens_deposited" numeric NOT NULL, "swap_pool_id" character varying, CONSTRAINT "PK_4788b03472eec9547df44a82c48" PRIMARY KEY ("id"))` + ) + await db.query( + `CREATE INDEX "IDX_e0480f777845618674d1bbc3b1" ON "nabla_swap_liquidity_deposit" ("swap_pool_id") ` + ) + await db.query( + `CREATE TABLE "nabla_backstop_liquidity_withdrawal" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "sender" text NOT NULL, "pool_shares_burned" numeric NOT NULL, "amount_pool_tokens_withdrawn" numeric NOT NULL, "backstop_pool_id" character varying, CONSTRAINT "PK_9fca1665db21118d0b318e1f828" PRIMARY KEY ("id"))` + ) + await db.query( + `CREATE INDEX "IDX_33f15234263ac9c6d07fe5441f" ON "nabla_backstop_liquidity_withdrawal" ("backstop_pool_id") ` + ) + await db.query( + `CREATE TABLE "nabla_swap_liquidity_withdrawal" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "sender" text NOT NULL, "pool_shares_burned" numeric NOT NULL, "amount_pool_tokens_withdrawn" numeric NOT NULL, "swap_pool_id" character varying, CONSTRAINT "PK_38c9ff7047fcf36ccbd4b7cb521" PRIMARY KEY ("id"))` + ) + await db.query( + `CREATE INDEX "IDX_ec313e0ceb8429cb76aa63ed74" ON "nabla_swap_liquidity_withdrawal" ("swap_pool_id") ` + ) await db.query( `CREATE TABLE "event" ("id" character varying NOT NULL, "index" integer NOT NULL, "phase" text NOT NULL, "pallet" text NOT NULL, "name" text NOT NULL, "args" jsonb, "args_str" text array, "block_id" character varying, "extrinsic_id" character varying, "call_id" character varying, CONSTRAINT "PK_30c2f3bbaf6d34a55f8ae6e4614" PRIMARY KEY ("id"))` ) @@ -554,6 +590,27 @@ module.exports = class Data1714034652645 { await db.query( `ALTER TABLE "swap_pool" ADD CONSTRAINT "FK_b66a5cc8d2ce7bba1b48fd8c1ab" FOREIGN KEY ("token_id") REFERENCES "nabla_token"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` ) + await db.query( + `ALTER TABLE "nabla_swap" ADD CONSTRAINT "FK_78ad17aaf8e256aada35d50c95a" FOREIGN KEY ("token_in_id") REFERENCES "nabla_token"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` + ) + await db.query( + `ALTER TABLE "nabla_swap" ADD CONSTRAINT "FK_3ddf0d667a8f06da7f6ab50004f" FOREIGN KEY ("token_out_id") REFERENCES "nabla_token"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` + ) + await db.query( + `ALTER TABLE "nabla_swap" ADD CONSTRAINT "FK_dd24afed240ad46290bfcf0603b" FOREIGN KEY ("swap_fee_id") REFERENCES "nabla_swap_fee"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` + ) + await db.query( + `ALTER TABLE "nabla_backstop_liquidity_deposit" ADD CONSTRAINT "FK_a3ce6e5ba78f5987919e7ee3467" FOREIGN KEY ("backstop_pool_id") REFERENCES "backstop_pool"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` + ) + await db.query( + `ALTER TABLE "nabla_swap_liquidity_deposit" ADD CONSTRAINT "FK_e0480f777845618674d1bbc3b18" FOREIGN KEY ("swap_pool_id") REFERENCES "swap_pool"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` + ) + await db.query( + `ALTER TABLE "nabla_backstop_liquidity_withdrawal" ADD CONSTRAINT "FK_33f15234263ac9c6d07fe5441f0" FOREIGN KEY ("backstop_pool_id") REFERENCES "backstop_pool"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` + ) + await db.query( + `ALTER TABLE "nabla_swap_liquidity_withdrawal" ADD CONSTRAINT "FK_ec313e0ceb8429cb76aa63ed746" FOREIGN KEY ("swap_pool_id") REFERENCES "swap_pool"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` + ) await db.query( `ALTER TABLE "event" ADD CONSTRAINT "FK_2b0d35d675c4f99751855c45021" FOREIGN KEY ("block_id") REFERENCES "block"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` ) @@ -689,6 +746,18 @@ module.exports = class Data1714034652645 { await db.query(`DROP INDEX "public"."IDX_5c3209a88e41d53bdc450605b3"`) await db.query(`DROP INDEX "public"."IDX_b66a5cc8d2ce7bba1b48fd8c1a"`) await db.query(`DROP TABLE "router"`) + await db.query(`DROP TABLE "nabla_swap"`) + await db.query(`DROP INDEX "public"."IDX_78ad17aaf8e256aada35d50c95"`) + await db.query(`DROP INDEX "public"."IDX_3ddf0d667a8f06da7f6ab50004"`) + await db.query(`DROP INDEX "public"."IDX_dd24afed240ad46290bfcf0603"`) + await db.query(`DROP TABLE "nabla_backstop_liquidity_deposit"`) + await db.query(`DROP INDEX "public"."IDX_a3ce6e5ba78f5987919e7ee346"`) + await db.query(`DROP TABLE "nabla_swap_liquidity_deposit"`) + await db.query(`DROP INDEX "public"."IDX_e0480f777845618674d1bbc3b1"`) + await db.query(`DROP TABLE "nabla_backstop_liquidity_withdrawal"`) + await db.query(`DROP INDEX "public"."IDX_33f15234263ac9c6d07fe5441f"`) + await db.query(`DROP TABLE "nabla_swap_liquidity_withdrawal"`) + await db.query(`DROP INDEX "public"."IDX_ec313e0ceb8429cb76aa63ed74"`) await db.query(`DROP TABLE "event"`) await db.query(`DROP INDEX "public"."IDX_2b0d35d675c4f99751855c4502"`) await db.query(`DROP INDEX "public"."IDX_129efedcb305c80256db2d57a5"`) @@ -857,6 +926,27 @@ module.exports = class Data1714034652645 { await db.query( `ALTER TABLE "swap_pool" DROP CONSTRAINT "FK_b66a5cc8d2ce7bba1b48fd8c1ab"` ) + await db.query( + `ALTER TABLE "nabla_swap" DROP CONSTRAINT "FK_78ad17aaf8e256aada35d50c95a"` + ) + await db.query( + `ALTER TABLE "nabla_swap" DROP CONSTRAINT "FK_3ddf0d667a8f06da7f6ab50004f"` + ) + await db.query( + `ALTER TABLE "nabla_swap" DROP CONSTRAINT "FK_dd24afed240ad46290bfcf0603b"` + ) + await db.query( + `ALTER TABLE "nabla_backstop_liquidity_deposit" DROP CONSTRAINT "FK_a3ce6e5ba78f5987919e7ee3467"` + ) + await db.query( + `ALTER TABLE "nabla_swap_liquidity_deposit" DROP CONSTRAINT "FK_e0480f777845618674d1bbc3b18"` + ) + await db.query( + `ALTER TABLE "nabla_backstop_liquidity_withdrawal" DROP CONSTRAINT "FK_33f15234263ac9c6d07fe5441f0"` + ) + await db.query( + `ALTER TABLE "nabla_swap_liquidity_withdrawal" DROP CONSTRAINT "FK_ec313e0ceb8429cb76aa63ed746"` + ) await db.query( `ALTER TABLE "event" DROP CONSTRAINT "FK_2b0d35d675c4f99751855c45021"` ) diff --git a/schema.graphql b/schema.graphql index faf13b30..3ebee84d 100644 --- a/schema.graphql +++ b/schema.graphql @@ -791,7 +791,7 @@ type BackstopPool @entity { } type NablaSwapFee @entity { - id: ID! # id is address of the swap pool contract + timestamp + id: ID! # # calculated from blockNumber - extrinsicIndex lpFees: BigInt! # LP fee in `asset` backstopFees: BigInt! # backstop fee in `asset` protocolFees: BigInt! # protocol fee in `asset` @@ -800,6 +800,59 @@ type NablaSwapFee @entity { backstopPool: BackstopPool # link to the BackstopPool entity } +type NablaSwap @entity { + id: ID! # calculated from blockNumber - extrinsicIndex + timestamp: DateTime! # need this to pull recent txns for specific token or pair + # from router Swap event + sender: String! + amountIn: BigInt! + amountOut: BigInt! + tokenIn: NablaToken! + tokenOut: NablaToken! + to: String! + swapFee: NablaSwapFee +} + +type NablaBackstopLiquidityDeposit @entity { + id: ID! # calculated from blockNumber - extrinsicIndex + timestamp: DateTime! + # from backstop Mint event + sender: String! + poolSharesMinted: BigInt! + amountPoolTokensDeposited: BigInt! + backstopPool: BackstopPool! +} + +type NablaSwapLiquidityDeposit @entity { + id: ID! # calculated from blockNumber - extrinsicIndex + timestamp: DateTime! + # from swap Mint event + sender: String! + poolSharesMinted: BigInt! + amountPoolTokensDeposited: BigInt! + swapPool: SwapPool! +} + +type NablaBackstopLiquidityWithdrawal @entity { + id: ID! # calculated from blockNumber - extrinsicIndex + timestamp: DateTime! + # from backstop Burn event + sender: String! + poolSharesBurned: BigInt! + amountPoolTokensWithdrawn: BigInt! + backstopPool: BackstopPool! +} + +type NablaSwapLiquidityWithdrawal @entity { + id: ID! # calculated from blockNumber - extrinsicIndex + timestamp: DateTime! + # from swap Burn event + sender: String! + poolSharesBurned: BigInt! + amountPoolTokensWithdrawn: BigInt! + swapPool: SwapPool! +} + type Block @entity { "BlockHeight-blockHash - e.g. 0001812319-0001c" id: ID! diff --git a/squid-amplitude.yaml b/squid-amplitude.yaml index 596f7bb3..b581bd9e 100644 --- a/squid-amplitude.yaml +++ b/squid-amplitude.yaml @@ -1,6 +1,6 @@ manifestVersion: subsquid.io/v0.1 name: amplitude-squid -version: 21 +version: 22 description: 'Amplitude Kusama Squid' build: deploy: diff --git a/squid-foucoco.yaml b/squid-foucoco.yaml index 4c47c8ce..34ef6b60 100644 --- a/squid-foucoco.yaml +++ b/squid-foucoco.yaml @@ -1,6 +1,6 @@ manifestVersion: subsquid.io/v0.1 name: foucoco-squid -version: 21 +version: 22 description: 'Foucoco Squid' build: deploy: diff --git a/squid-pendulum.yaml b/squid-pendulum.yaml index 70f23760..9f4aa55a 100644 --- a/squid-pendulum.yaml +++ b/squid-pendulum.yaml @@ -1,6 +1,6 @@ manifestVersion: subsquid.io/v0.1 name: pendulum-squid -version: 21 +version: 22 description: 'Pendulum Squid' build: deploy: diff --git a/src/config.ts b/src/config.ts index ce80be75..4a8d05f5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -74,7 +74,6 @@ export const config: ProcessorConfig = console.log('Using ProcessorConfig: ', config) // Fetch max height from the archive and export it as a promise - export const maxHeightPromise = isLocalExecution ? Promise.resolve(0) : axios @@ -91,3 +90,11 @@ export const maxHeightPromise = isLocalExecution ) return Number.MAX_SAFE_INTEGER }) + +// Derive ids from block number and extrinsic index of the event +export function generateId( + blockNumber: number, + extrinsicIndex?: number +): string { + return `${blockNumber}-${extrinsicIndex ?? ''}` +} diff --git a/src/mappings/nabla/backstopPoolEventHandler.ts b/src/mappings/nabla/backstopPoolEventHandler.ts index e4c7a7f1..21674b34 100644 --- a/src/mappings/nabla/backstopPoolEventHandler.ts +++ b/src/mappings/nabla/backstopPoolEventHandler.ts @@ -7,10 +7,16 @@ import { Event_WithdrawSwapLiquidity, Contract as BackstopPoolContract, Event_InsuranceFeeSet, + Event_Burn, + Event_Mint, } from '../../abi/backstop' import { Contract as Erc20Contract } from '../../abi/erc20' import { hexToSs58, ss58ToHex } from './addresses' -import { getSwapPool } from './creation' +import { + createNablaBackstopLiquidityDeposit, + createNablaBackstopLiquidityWithdrawal, + getSwapPool, +} from './creation' import { updateSwapPoolCoverageAndSupply } from './swapPoolEventHandler' export async function handleBackstopPoolEvent( @@ -25,7 +31,7 @@ export async function handleBackstopPoolEvent( break case 'Burn': - await handleBurn(ctx, backstopPool) + await handleBurn(ctx, event, backstopPool) break case 'CoverSwapWithdrawal': @@ -37,7 +43,7 @@ export async function handleBackstopPoolEvent( break case 'Mint': - await handleMint(ctx, backstopPool) + await handleMint(ctx, event, backstopPool) break case 'OwnershipTransferred': @@ -69,8 +75,19 @@ export async function handleBackstopPoolEvent( export async function handleBurn( ctx: EventHandlerContext, + event: Event_Burn, backstopPool: BackstopPool ) { + await createNablaBackstopLiquidityWithdrawal( + ctx, + ctx.event.block.height, + ctx.event.extrinsicIndex, + ctx.event.block.timestamp, + hexToSs58(event.sender), + event.poolSharesBurned, + event.amountPrincipleWithdrawn, + backstopPool + ) await updateBackstopCoverageAndSupply(ctx, backstopPool) await ctx.store.save(backstopPool) } @@ -112,9 +129,20 @@ export async function handleInsuranceFeeSet( export async function handleMint( ctx: EventHandlerContext, + event: Event_Mint, backstopPool: BackstopPool ) { await updateBackstopCoverageAndSupply(ctx, backstopPool) + await createNablaBackstopLiquidityDeposit( + ctx, + ctx.event.block.height, + ctx.event.extrinsicIndex, + ctx.event.block.timestamp, + hexToSs58(event.sender), + event.poolSharesMinted, + event.amountPrincipleDeposited, + backstopPool + ) await ctx.store.save(backstopPool) } diff --git a/src/mappings/nabla/creation.ts b/src/mappings/nabla/creation.ts index e09ed19b..bea026b4 100644 --- a/src/mappings/nabla/creation.ts +++ b/src/mappings/nabla/creation.ts @@ -5,11 +5,17 @@ import { NablaToken, SwapPool, NablaSwapFee, + NablaSwap, + NablaBackstopLiquidityDeposit, + NablaSwapLiquidityDeposit, + NablaBackstopLiquidityWithdrawal, + NablaSwapLiquidityWithdrawal, } from '../../model' import * as backstopPoolAbi from '../../abi/backstop' import * as erc20Abi from '../../abi/erc20' import * as swapPoolAbi from '../../abi/swap' import { hexToSs58 } from './addresses' +import { generateId } from '../../config' export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000000000000000000000000000' @@ -40,6 +46,17 @@ export async function getSwapPool( }) } +export async function getSwapFee( + ctx: EventHandlerContext, + blockNumber: number, + extrinsicIndex: number | undefined +) { + return await ctx.store.get( + NablaSwapFee, + generateId(blockNumber, extrinsicIndex) + ) +} + export async function getSwapPoolsOfRouterForToken( ctx: EventHandlerContext, routerSs58Address: string, @@ -211,7 +228,7 @@ export async function createSwapFee( swapPool: SwapPool, backstopPool: BackstopPool | undefined ): Promise { - const swapFeeId = `${blockNumber}-${extrinsicIndex ?? ''}` + const swapFeeId = generateId(blockNumber, extrinsicIndex) const swapFee = new NablaSwapFee({ id: swapFeeId, lpFees, @@ -225,3 +242,129 @@ export async function createSwapFee( await ctx.store.save(swapFee) return swapFee } + +export async function createNablaSwap( + ctx: EventHandlerContext, + blockNumber: number, + extrinsicIndex: number | undefined, + timestamp: number | undefined, + sender: string, + amountIn: bigint, + amountOut: bigint, + tokenIn: NablaToken, + tokenOut: NablaToken, + to: string, + swapFee: NablaSwapFee | undefined +): Promise { + const nablaSwapId = generateId(blockNumber, extrinsicIndex) + const nablaSwap = new NablaSwap({ + id: nablaSwapId, + timestamp: new Date(timestamp ?? 0), + sender, + amountIn, + amountOut, + tokenIn, + tokenOut, + to, + swapFee, + }) + + await ctx.store.save(nablaSwap) + return nablaSwap +} + +export async function createNablaBackstopLiquidityDeposit( + ctx: EventHandlerContext, + blockNumber: number, + extrinsicIndex: number | undefined, + timestamp: number | undefined, + sender: string, + poolSharesMinted: bigint, + amountPoolTokensDeposited: bigint, + backstopPool: BackstopPool +): Promise { + const backstopDepositId = generateId(blockNumber, extrinsicIndex) + const backstopDeposit = new NablaBackstopLiquidityDeposit({ + id: backstopDepositId, + timestamp: new Date(timestamp ?? 0), + sender, + poolSharesMinted, + amountPoolTokensDeposited, + backstopPool, + }) + + await ctx.store.save(backstopDeposit) + return backstopDeposit +} + +export async function createNablaSwapLiquidityDeposit( + ctx: EventHandlerContext, + blockNumber: number, + extrinsicIndex: number | undefined, + timestamp: number | undefined, + sender: string, + poolSharesMinted: bigint, + amountPoolTokensDeposited: bigint, + swapPool: SwapPool +): Promise { + const swapDepositId = generateId(blockNumber, extrinsicIndex) + const swapDeposit = new NablaSwapLiquidityDeposit({ + id: swapDepositId, + timestamp: new Date(timestamp ?? 0), + sender, + poolSharesMinted, + amountPoolTokensDeposited, + swapPool, + }) + + await ctx.store.save(swapDeposit) + return swapDeposit +} + +export async function createNablaBackstopLiquidityWithdrawal( + ctx: EventHandlerContext, + blockNumber: number, + extrinsicIndex: number | undefined, + timestamp: number | undefined, + sender: string, + poolSharesBurned: bigint, + amountPoolTokensWithdrawn: bigint, + backstopPool: BackstopPool +): Promise { + const backstopWithdrawalId = generateId(blockNumber, extrinsicIndex) + const backstopWithdrawal = new NablaBackstopLiquidityWithdrawal({ + id: backstopWithdrawalId, + timestamp: new Date(timestamp ?? 0), + sender, + poolSharesBurned, + amountPoolTokensWithdrawn, + backstopPool, + }) + + await ctx.store.save(backstopWithdrawal) + return backstopWithdrawal +} + +export async function createNablaSwapLiquidityWithdrawal( + ctx: EventHandlerContext, + blockNumber: number, + extrinsicIndex: number | undefined, + timestamp: number | undefined, + sender: string, + poolSharesBurned: bigint, + amountPoolTokensWithdrawn: bigint, + swapPool: SwapPool +): Promise { + const swapWithdrawalId = generateId(blockNumber, extrinsicIndex) + const swapWithdrawal = new NablaSwapLiquidityWithdrawal({ + id: swapWithdrawalId, + timestamp: new Date(timestamp ?? 0), + sender, + poolSharesBurned, + amountPoolTokensWithdrawn, + swapPool, + }) + + await ctx.store.save(swapWithdrawal) + return swapWithdrawal +} diff --git a/src/mappings/nabla/routerEventHandler.ts b/src/mappings/nabla/routerEventHandler.ts index c5f8c606..49e0bd5f 100644 --- a/src/mappings/nabla/routerEventHandler.ts +++ b/src/mappings/nabla/routerEventHandler.ts @@ -11,6 +11,8 @@ import { getSwapPoolsOfRouterForToken, getOrCreateNablaToken, getSwapPool, + createNablaSwap, + getSwapFee, } from './creation' import { updateSwapPoolCoverageAndSupply } from './swapPoolEventHandler' import { hexToSs58, ss58ToHex } from './addresses' @@ -89,6 +91,26 @@ export async function handleSwap( await updateSwapPoolCoverageAndSupply(ctx, swapPoolOut) await ctx.store.save(swapPoolOut) } + + const swapFee = await getSwapFee( + ctx, + ctx.event.block.height, + ctx.event.extrinsicIndex + ) + + await createNablaSwap( + ctx, + ctx.event.block.height, + ctx.event.extrinsicIndex, + ctx.event.block.timestamp!, + hexToSs58(event.sender), + event.amountIn, + event.amountOut, + tokenIn, + tokenOut, + hexToSs58(event.to), + swapFee + ) } export async function handleSwapPoolRegistered( diff --git a/src/mappings/nabla/swapPoolEventHandler.ts b/src/mappings/nabla/swapPoolEventHandler.ts index 8e2e9e01..81175bc0 100644 --- a/src/mappings/nabla/swapPoolEventHandler.ts +++ b/src/mappings/nabla/swapPoolEventHandler.ts @@ -1,16 +1,20 @@ import { EventHandlerContext } from '../../processor' import { ZERO_ADDRESS, + createNablaSwapLiquidityDeposit, + createNablaSwapLiquidityWithdrawal, createSwapFee, getBackstopPool, getSwapPool, } from './creation' -import { NablaSwapFee, SwapPool } from '../../model' +import { NablaSwap, NablaSwapFee, SwapPool } from '../../model' import { decodeEvent, Contract as SwapPoolContract, Event_ChargedSwapFees, Event_ProtocolTreasuryChanged, + Event_Mint, + Event_Burn, } from '../../abi/swap' import { Contract as BackstopPoolContract } from '../../abi/backstop' import { hexToSs58, ss58ToHex } from './addresses' @@ -34,7 +38,7 @@ export async function handleSwapPoolEvent( break case 'Burn': - await handleBurn(ctx, swapPool) + await handleBurn(ctx, event, swapPool) break case 'ChargedSwapFees': @@ -42,7 +46,7 @@ export async function handleSwapPoolEvent( break case 'Mint': - await handleMint(ctx, swapPool) + await handleMint(ctx, event, swapPool) break case 'OwnershipTransferred': @@ -82,8 +86,23 @@ export async function handleBackstopDrain( } } -export async function handleBurn(ctx: EventHandlerContext, swapPool: SwapPool) { +export async function handleBurn( + ctx: EventHandlerContext, + event: Event_Burn, + swapPool: SwapPool +) { await updateSwapPoolCoverageAndSupply(ctx, swapPool) + await createNablaSwapLiquidityWithdrawal( + ctx, + ctx.event.block.height, + ctx.event.extrinsicIndex, + ctx.event.block.timestamp, + hexToSs58(event.sender), + event.poolSharesBurned, + event.amountPrincipleWithdrawn, + swapPool + ) + await ctx.store.save(swapPool) } @@ -111,8 +130,23 @@ export async function handleChargedSwapFees( await updateAprAfterSwap(ctx, swapPool, swapFee) } -export async function handleMint(ctx: EventHandlerContext, swapPool: SwapPool) { +export async function handleMint( + ctx: EventHandlerContext, + event: Event_Mint, + swapPool: SwapPool +) { await updateSwapPoolCoverageAndSupply(ctx, swapPool) + await createNablaSwapLiquidityDeposit( + ctx, + ctx.event.block.height, + ctx.event.extrinsicIndex, + ctx.event.block.timestamp, + hexToSs58(event.sender), + event.poolSharesMinted, + event.amountPrincipleDeposited, + swapPool + ) + await ctx.store.save(swapPool) } @@ -178,6 +212,16 @@ async function filterSwapFeeHistory( ) { for (const swapFee of feesHistory) { if (swapFee.timestamp < pastPeriodInSeconds) { + // Check for references in the NablaSwap table + const swapReference = await ctx.store.findOne(NablaSwap, { + where: { swapFee: { id: swapFee.id } }, + }) + if (swapReference) { + swapReference.swapFee = null + await ctx.store.save(swapReference) + } + + // Now it should be safe to remove the swap fee await ctx.store.remove(swapFee) } } diff --git a/src/model/generated/index.ts b/src/model/generated/index.ts index 5721586f..7fe778ed 100644 --- a/src/model/generated/index.ts +++ b/src/model/generated/index.ts @@ -50,6 +50,11 @@ export * from './nablaToken.model' export * from './swapPool.model' export * from './backstopPool.model' export * from './nablaSwapFee.model' +export * from './nablaSwap.model' +export * from './nablaBackstopLiquidityDeposit.model' +export * from './nablaSwapLiquidityDeposit.model' +export * from './nablaBackstopLiquidityWithdrawal.model' +export * from './nablaSwapLiquidityWithdrawal.model' export * from './block.model' export * from './extrinsic.model' export * from './_extrinsicSignature' diff --git a/src/model/generated/nablaBackstopLiquidityDeposit.model.ts b/src/model/generated/nablaBackstopLiquidityDeposit.model.ts new file mode 100644 index 00000000..f1428aa0 --- /dev/null +++ b/src/model/generated/nablaBackstopLiquidityDeposit.model.ts @@ -0,0 +1,41 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm' +import * as marshal from './marshal' +import { BackstopPool } from './backstopPool.model' + +@Entity_() +export class NablaBackstopLiquidityDeposit { + constructor(props?: Partial) { + Object.assign(this, props) + } + + @PrimaryColumn_() + id!: string + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date + + @Column_('text', { nullable: false }) + sender!: string + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + poolSharesMinted!: bigint + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + amountPoolTokensDeposited!: bigint + + @Index_() + @ManyToOne_(() => BackstopPool, { nullable: true }) + backstopPool!: BackstopPool +} diff --git a/src/model/generated/nablaBackstopLiquidityWithdrawal.model.ts b/src/model/generated/nablaBackstopLiquidityWithdrawal.model.ts new file mode 100644 index 00000000..de65dd7e --- /dev/null +++ b/src/model/generated/nablaBackstopLiquidityWithdrawal.model.ts @@ -0,0 +1,41 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm' +import * as marshal from './marshal' +import { BackstopPool } from './backstopPool.model' + +@Entity_() +export class NablaBackstopLiquidityWithdrawal { + constructor(props?: Partial) { + Object.assign(this, props) + } + + @PrimaryColumn_() + id!: string + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date + + @Column_('text', { nullable: false }) + sender!: string + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + poolSharesBurned!: bigint + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + amountPoolTokensWithdrawn!: bigint + + @Index_() + @ManyToOne_(() => BackstopPool, { nullable: true }) + backstopPool!: BackstopPool +} diff --git a/src/model/generated/nablaSwap.model.ts b/src/model/generated/nablaSwap.model.ts new file mode 100644 index 00000000..e52aedbe --- /dev/null +++ b/src/model/generated/nablaSwap.model.ts @@ -0,0 +1,53 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm' +import * as marshal from './marshal' +import { NablaToken } from './nablaToken.model' +import { NablaSwapFee } from './nablaSwapFee.model' + +@Entity_() +export class NablaSwap { + constructor(props?: Partial) { + Object.assign(this, props) + } + + @PrimaryColumn_() + id!: string + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date + + @Column_('text', { nullable: false }) + sender!: string + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + amountIn!: bigint + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + amountOut!: bigint + + @Index_() + @ManyToOne_(() => NablaToken, { nullable: true }) + tokenIn!: NablaToken + + @Index_() + @ManyToOne_(() => NablaToken, { nullable: true }) + tokenOut!: NablaToken + + @Column_('text', { nullable: false }) + to!: string + + @Index_() + @ManyToOne_(() => NablaSwapFee, { nullable: true }) + swapFee!: NablaSwapFee | undefined | null +} diff --git a/src/model/generated/nablaSwapLiquidityDeposit.model.ts b/src/model/generated/nablaSwapLiquidityDeposit.model.ts new file mode 100644 index 00000000..e3d4ab65 --- /dev/null +++ b/src/model/generated/nablaSwapLiquidityDeposit.model.ts @@ -0,0 +1,41 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm' +import * as marshal from './marshal' +import { SwapPool } from './swapPool.model' + +@Entity_() +export class NablaSwapLiquidityDeposit { + constructor(props?: Partial) { + Object.assign(this, props) + } + + @PrimaryColumn_() + id!: string + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date + + @Column_('text', { nullable: false }) + sender!: string + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + poolSharesMinted!: bigint + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + amountPoolTokensDeposited!: bigint + + @Index_() + @ManyToOne_(() => SwapPool, { nullable: true }) + swapPool!: SwapPool +} diff --git a/src/model/generated/nablaSwapLiquidityWithdrawal.model.ts b/src/model/generated/nablaSwapLiquidityWithdrawal.model.ts new file mode 100644 index 00000000..d4092a75 --- /dev/null +++ b/src/model/generated/nablaSwapLiquidityWithdrawal.model.ts @@ -0,0 +1,41 @@ +import { + Entity as Entity_, + Column as Column_, + PrimaryColumn as PrimaryColumn_, + ManyToOne as ManyToOne_, + Index as Index_, +} from 'typeorm' +import * as marshal from './marshal' +import { SwapPool } from './swapPool.model' + +@Entity_() +export class NablaSwapLiquidityWithdrawal { + constructor(props?: Partial) { + Object.assign(this, props) + } + + @PrimaryColumn_() + id!: string + + @Column_('timestamp with time zone', { nullable: false }) + timestamp!: Date + + @Column_('text', { nullable: false }) + sender!: string + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + poolSharesBurned!: bigint + + @Column_('numeric', { + transformer: marshal.bigintTransformer, + nullable: false, + }) + amountPoolTokensWithdrawn!: bigint + + @Index_() + @ManyToOne_(() => SwapPool, { nullable: true }) + swapPool!: SwapPool +}