Skip to content

Commit

Permalink
Adding CL Collect Fees aggregator event.
Browse files Browse the repository at this point in the history
  • Loading branch information
jfarid27 committed Oct 24, 2024
1 parent e524d02 commit fde5ad7
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 38 deletions.
142 changes: 104 additions & 38 deletions src/EventHandlers/CLPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,69 @@ import {
CLPool_SetFeeProtocol,
CLPool_Swap,
CLPoolAggregator,
Token,
} from "generated";
import { set_whitelisted_prices } from "../PriceOracle";
import { normalizeTokenAmountTo1e18 } from "../Helpers";
import { multiplyBase1e18, abs } from "../Maths";
import { updateCLPoolAggregator } from "../Aggregators/CLPoolAggregator";

/**
* Updates the fee amounts for a CLPoolAggregator based on event data.
*
* This function calculates the new total fees for both tokens in a liquidity pool
* and their equivalent value in USD. It normalizes the token amounts to a base of 1e18
* for consistent calculations and updates the total fees in the aggregator.
*
* @param clPoolAggregator - The current state of the CLPoolAggregator, containing existing fee data.
* @param event - The event data containing the fee amounts for token0 and token1.
* @param token0Instance - The instance of token0, containing its decimals and price per USD.
* @param token1Instance - The instance of token1, containing its decimals and price per USD.
*
* @returns An object containing the updated total fees for token0, token1, and their equivalent in USD.
*
* The returned object has the following structure:
* - `totalFees0`: The updated total fees for token0, normalized to 1e18.
* - `totalFees1`: The updated total fees for token1, normalized to 1e18.
* - `totalFeesUSD`: The updated total fees in USD, calculated using the normalized token fees and their prices.
*/
function updateCLPoolFees(
clPoolAggregator: CLPoolAggregator,
event: any,
token0Instance: Token | undefined,
token1Instance: Token | undefined
) {
let tokenUpdateData = {
totalFees0: clPoolAggregator.totalFees0,
totalFees1: clPoolAggregator.totalFees1,
totalFeesUSD: clPoolAggregator.totalFeesUSD,
};

if (token0Instance) {
tokenUpdateData.totalFees0 += normalizeTokenAmountTo1e18(
event.params.amount0,
Number(token0Instance.decimals)
);
tokenUpdateData.totalFeesUSD += multiplyBase1e18(
tokenUpdateData.totalFees0,
token0Instance.pricePerUSDNew
);
}

if (token1Instance) {
tokenUpdateData.totalFees1 += normalizeTokenAmountTo1e18(
event.params.amount1,
Number(token1Instance.decimals)
);
tokenUpdateData.totalFeesUSD += multiplyBase1e18(
tokenUpdateData.totalFees1,
token1Instance.pricePerUSDNew
);
}

return tokenUpdateData;
}

CLPool.Burn.handler(async ({ event, context }) => {
const entity: CLPool_Burn = {
id: `${event.chainId}_${event.block.number}_${event.logIndex}`,
Expand Down Expand Up @@ -74,33 +131,7 @@ CLPool.Collect.handlerWithLoader({
if (loaderReturn && loaderReturn.clPoolAggregator) {
const { clPoolAggregator, token0Instance, token1Instance } = loaderReturn;

let tokenUpdateData = {
totalFees0: clPoolAggregator.totalFees0,
totalFees1: clPoolAggregator.totalFees1,
totalFeesUSD: clPoolAggregator.totalFeesUSD,
};

if (token0Instance) {
tokenUpdateData.totalFees0 += normalizeTokenAmountTo1e18(
event.params.amount0,
Number(token0Instance.decimals)
);
tokenUpdateData.totalFeesUSD += multiplyBase1e18(
tokenUpdateData.totalFees0,
token0Instance.pricePerUSDNew
);
}

if (token1Instance) {
tokenUpdateData.totalFees1 += normalizeTokenAmountTo1e18(
event.params.amount1,
Number(token1Instance.decimals)
);
tokenUpdateData.totalFeesUSD += multiplyBase1e18(
tokenUpdateData.totalFees1,
token1Instance.pricePerUSDNew
);
}
const tokenUpdateData = updateCLPoolFees(clPoolAggregator, event, token0Instance, token1Instance);

updateCLPoolAggregator(
tokenUpdateData,
Expand All @@ -112,18 +143,53 @@ CLPool.Collect.handlerWithLoader({
},
});

CLPool.CollectFees.handler(async ({ event, context }) => {
const entity: CLPool_CollectFees = {
id: `${event.chainId}_${event.block.number}_${event.logIndex}`,
recipient: event.params.recipient,
amount0: event.params.amount0,
amount1: event.params.amount1,
sourceAddress: event.srcAddress,
timestamp: new Date(event.block.timestamp * 1000),
chainId: event.chainId,
};
CLPool.CollectFees.handlerWithLoader({
loader: async ({ event, context }) => {
const pool_id = event.srcAddress;
const pool_created = await context.CLFactory_PoolCreated.getWhere.pool.eq(
pool_id
);

if (!pool_created || pool_created.length === 0) {
context.log.error(`Pool ${pool_id} not found during collect`);
return null;
}

const [token0Instance, token1Instance, clPoolAggregator] =
await Promise.all([
context.Token.get(pool_created[0].token0),
context.Token.get(pool_created[0].token1),
context.CLPoolAggregator.get(pool_id),
]);

context.CLPool_CollectFees.set(entity);
return { clPoolAggregator, token0Instance, token1Instance };
},
handler: async ({ event, context, loaderReturn }) => {
const entity: CLPool_CollectFees = {
id: `${event.chainId}_${event.block.number}_${event.logIndex}`,
recipient: event.params.recipient,
amount0: event.params.amount0,
amount1: event.params.amount1,
sourceAddress: event.srcAddress,
timestamp: new Date(event.block.timestamp * 1000),
chainId: event.chainId,
};

context.CLPool_CollectFees.set(entity);

if (loaderReturn && loaderReturn.clPoolAggregator) {
const { clPoolAggregator, token0Instance, token1Instance } = loaderReturn;

const tokenUpdateData = updateCLPoolFees(clPoolAggregator, event, token0Instance, token1Instance);

updateCLPoolAggregator(
tokenUpdateData,
clPoolAggregator,
new Date(event.block.timestamp * 1000),
context
);
}
}
});

CLPool.Flash.handler(async ({ event, context }) => {
Expand Down
99 changes: 99 additions & 0 deletions test/EventHandlers/CLPool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,105 @@ describe("CLPool Event Handlers", () => {
});
});
});
describe("Collect Fees Event", () => {

let mockEvent: any;
const poolId = "0x1234567890123456789012345678901234567890";
const token0Id = "0x0000000000000000000000000000000000000001";
const token1Id = "0x0000000000000000000000000000000000000002";
let mockCLPoolAggregator: any;
let mockEventData: any;
let setupDB: any;
let mockToken0: Token;
let mockToken1: Token;

const eventFees = {
amount0: 100n * 10n ** 18n,
amount1: 200n * 10n ** 6n,
};

beforeEach(() => {
mockToken0 = {
id: token0Id,
decimals: 18n,
pricePerUSDNew: 1n * 10n ** 18n,
} as Token;

mockToken1 = {
id: token1Id,
decimals: 6n,
pricePerUSDNew: 1n * 10n ** 18n,
} as Token;


mockEventData = {
amount0: eventFees.amount0,
amount1: eventFees.amount1,
mockEventData: {
block: {
number: 123456,
timestamp: 1000000,
hash: "0xblockhash",
},
chainId: 1,
logIndex: 0,
srcAddress: poolId,
},
};

mockEvent = CLPool.CollectFees.createMockEvent(mockEventData);

mockCLPoolAggregator = {
id: poolId,
chainId: 1,
totalFees0: 100n * 10n ** 18n,
totalFees1: 200n * 10n ** 18n,
totalFeesUSD: 300n * 10n ** 18n,
} as CLPoolAggregator;
});

describe("when event is processed", () => {

beforeEach(async () => {
let updatedDB = mockDb.entities.CLFactory_PoolCreated.set({
id: `1_123456_0`,
token0: token0Id,
token1: token1Id,
pool: poolId,
} as CLFactory_PoolCreated);
updatedDB = updatedDB.entities.Token.set(mockToken0);
updatedDB = updatedDB.entities.Token.set(mockToken1);
updatedDB = updatedDB.entities.CLPoolAggregator.set(mockCLPoolAggregator);

setupDB = await CLPool.CollectFees.processEvent({
event: mockEvent,
mockDb: updatedDB,
});
});

it("should create a CLPool_CollectFees entity", async () => {
const expectedId = `${mockEvent.chainId}_${mockEvent.block.number}_${mockEvent.logIndex}`;
const collectEntity = setupDB.entities.CLPool_CollectFees.get(expectedId);
expect(collectEntity).to.not.be.undefined;
expect(collectEntity?.amount0).to.equal(100n * 10n ** 18n);
expect(collectEntity?.amount1).to.equal(200n * 10n ** 6n);
});

it("should update CLPoolAggregator", async () => {
expect(updateCLPoolAggregatorStub.calledOnce).to.be.true;
const [diff] = updateCLPoolAggregatorStub.firstCall.args;

expect(diff.totalFees0).to.equal(
mockCLPoolAggregator.totalFees0 + eventFees.amount0
);
expect(diff.totalFees1).to.equal(
mockCLPoolAggregator.totalFees1 + (
eventFees.amount1 * (10n ** 18n) / 10n ** 6n
)
, "It should normalize fees here");
});
});
});

describe("Swap Event", () => {
const poolId = "0x1234567890123456789012345678901234567890";
Expand Down

0 comments on commit fde5ad7

Please sign in to comment.