From 6cea6baff36a935f9cf02dd53c910d5b7bba4ddc Mon Sep 17 00:00:00 2001 From: Teddy Ding Date: Wed, 20 Nov 2024 11:16:15 -0500 Subject: [PATCH] exclude liquidation fees in referred fee calculation --- .../stores/affiliate-info-table.test.ts | 96 +++++++++++++++---- .../src/stores/affiliate-info-table.ts | 12 ++- 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/indexer/packages/postgres/__tests__/stores/affiliate-info-table.test.ts b/indexer/packages/postgres/__tests__/stores/affiliate-info-table.test.ts index 9c9eddc6eb..dccf4e1ece 100644 --- a/indexer/packages/postgres/__tests__/stores/affiliate-info-table.test.ts +++ b/indexer/packages/postgres/__tests__/stores/affiliate-info-table.test.ts @@ -1,5 +1,5 @@ import { - AffiliateInfoFromDatabase, Liquidity, + AffiliateInfoFromDatabase, Liquidity, FillType, } from '../../src/types'; import { clearData, migrate, teardown } from '../../src/helpers/db-helpers'; import { @@ -138,15 +138,15 @@ describe('Affiliate info store', () => { ); const expectedAffiliateInfo1: AffiliateInfoFromDatabase = { address: defaultWallet2.address, - affiliateEarnings: '1000', - referredMakerTrades: 2, - referredTakerTrades: 0, - totalReferredMakerFees: '2000', + affiliateEarnings: '1005', + referredMakerTrades: 3, + referredTakerTrades: 1, + totalReferredMakerFees: '2100', totalReferredTakerFees: '0', totalReferredMakerRebates: '0', totalReferredUsers: 1, firstReferralBlockHeight: '1', - referredTotalVolume: '2', + referredTotalVolume: '4', }; expect(updatedInfo1).toEqual(expectedAffiliateInfo1); @@ -161,15 +161,15 @@ describe('Affiliate info store', () => { ); const expectedAffiliateInfo2: AffiliateInfoFromDatabase = { address: defaultWallet2.address, - affiliateEarnings: '2000', - referredMakerTrades: 3, - referredTakerTrades: 1, - totalReferredMakerFees: '2000', + affiliateEarnings: '2005', + referredMakerTrades: 4, + referredTakerTrades: 2, + totalReferredMakerFees: '2100', totalReferredTakerFees: '1000', totalReferredMakerRebates: '-1000', totalReferredUsers: 1, firstReferralBlockHeight: '1', - referredTotalVolume: '4', + referredTotalVolume: '6', }; expect(updatedInfo2).toEqual(expectedAffiliateInfo2); @@ -188,15 +188,15 @@ describe('Affiliate info store', () => { ); const expectedAffiliateInfo3: AffiliateInfoFromDatabase = { address: defaultWallet2.address, - affiliateEarnings: '2000', - referredMakerTrades: 3, - referredTakerTrades: 1, - totalReferredMakerFees: '2000', + affiliateEarnings: '2005', + referredMakerTrades: 4, + referredTakerTrades: 2, + totalReferredMakerFees: '2100', totalReferredTakerFees: '1000', totalReferredMakerRebates: '-1000', totalReferredUsers: 2, firstReferralBlockHeight: '1', - referredTotalVolume: '4', + referredTotalVolume: '6', }; expect(updatedInfo3).toEqual(expectedAffiliateInfo3); }); @@ -303,7 +303,7 @@ describe('Affiliate info store', () => { })); }); - it('Successfully uses offset and limit', async () => { + it('Successfully uses offset (default to sorted) and limit', async () => { const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable .paginatedFindWithAddressFilter( [], @@ -315,13 +315,15 @@ describe('Affiliate info store', () => { expect(infos!.length).toEqual(2); expect(infos![0]).toEqual(expect.objectContaining({ ...defaultAffiliateInfo, - address: 'address_5', - affiliateEarnings: '5', + address: 'address_4', + // affiliateEarnings in DB: 9, 8, 7, 6, 5, 4, ... + // so we get 4 with offset = 5. + affiliateEarnings: '4', })); expect(infos![1]).toEqual(expect.objectContaining({ ...defaultAffiliateInfo, - address: 'address_6', - affiliateEarnings: '6', + address: 'address_3', + affiliateEarnings: '3', })); }); @@ -358,6 +360,34 @@ describe('Affiliate info store', () => { expect(infos).toBeDefined(); expect(infos!.length).toEqual(0); }); + + it('Successfully use sorted - equal earnings between affiliates', async () => { + await AffiliateInfoTable.create({ + ...defaultAffiliateInfo, + address: 'address_10', + affiliateEarnings: '9', // same as address_9 + }); + const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable + .paginatedFindWithAddressFilter( + [], + 0, + 100, + true, + ); + expect(infos).toBeDefined(); + expect(infos!.length).toEqual(11); + expect(infos![0]).toEqual(expect.objectContaining({ + ...defaultAffiliateInfo, + address: 'address_10', // '10' < '9' in lexicographical order + affiliateEarnings: '9', + })); + expect(infos![1]).toEqual(expect.objectContaining({ + ...defaultAffiliateInfo, + address: 'address_9', + affiliateEarnings: '9', + })); + }); + }); }); @@ -421,6 +451,30 @@ async function populateFillsAndReferrals(): Promise { fee: '1000', affiliateRevShare: '500', }), + FillTable.create({ + ...defaultFill, + liquidity: Liquidity.TAKER, + subaccountId: defaultOrder.subaccountId, + createdAt: referenceDt.minus({ minutes: 2 }).toISO(), + eventId: defaultTendermintEventId4, + price: '1', + size: '1', + fee: '1000', + affiliateRevShare: '0', + type: FillType.LIQUIDATED, + }), + FillTable.create({ + ...defaultFill, + liquidity: Liquidity.MAKER, + subaccountId: defaultOrder.subaccountId, + createdAt: referenceDt.minus({ minutes: 2 }).toISO(), + eventId: defaultTendermintEventId, + price: '1', + size: '1', + fee: '100', + affiliateRevShare: '5', + type: FillType.LIQUIDATION, + }), ]); return referenceDt; diff --git a/indexer/packages/postgres/src/stores/affiliate-info-table.ts b/indexer/packages/postgres/src/stores/affiliate-info-table.ts index d661a01d70..5ea785bc70 100644 --- a/indexer/packages/postgres/src/stores/affiliate-info-table.ts +++ b/indexer/packages/postgres/src/stores/affiliate-info-table.ts @@ -16,6 +16,7 @@ import { AffiliateInfoFromDatabase, AffiliateInfoQueryConfig, Liquidity, + FillType, } from '../types'; export async function findAll( @@ -156,7 +157,8 @@ filtered_fills AS ( fills."affiliateRevShare", fills."createdAtHeight", fills."price", - fills."size" + fills."size", + fills."type" FROM fills WHERE @@ -174,6 +176,7 @@ affiliate_fills AS ( filtered_fills."affiliateRevShare", filtered_fills."price", filtered_fills."size", + filtered_fills."type", affiliate_referred_subaccounts."affiliateAddress", affiliate_referred_subaccounts."referredAtBlock" FROM @@ -193,7 +196,7 @@ affiliate_stats AS ( SUM(affiliate_fills."fee") AS "totalReferredFees", SUM(affiliate_fills."affiliateRevShare") AS "affiliateEarnings", SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.MAKER}' AND affiliate_fills."fee" > 0 THEN affiliate_fills."fee" ELSE 0 END) AS "totalReferredMakerFees", - SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.TAKER}' THEN affiliate_fills."fee" ELSE 0 END) AS "totalReferredTakerFees", + SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.TAKER}' AND affiliate_fills."type" = '${FillType.LIMIT}' THEN affiliate_fills."fee" ELSE 0 END) AS "totalReferredTakerFees", SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.MAKER}' AND affiliate_fills."fee" < 0 THEN affiliate_fills."fee" ELSE 0 END) AS "totalReferredMakerRebates", COUNT(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.MAKER}' THEN 1 END) AS "referredMakerTrades", COUNT(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.TAKER}' THEN 1 END) AS "referredTakerTrades", @@ -301,8 +304,9 @@ export async function paginatedFindWithAddressFilter( } // Sorting by affiliate earnings or default sorting by address - if (sortByAffiliateEarning) { - baseQuery = baseQuery.orderBy(AffiliateInfoColumns.affiliateEarnings, Ordering.DESC); + if (sortByAffiliateEarning || offset !== 0) { + baseQuery = baseQuery.orderBy(AffiliateInfoColumns.affiliateEarnings, Ordering.DESC) + .orderBy(AffiliateInfoColumns.address, Ordering.ASC); } // Apply pagination using offset and limit