Skip to content

Commit

Permalink
[OTE-762] replace comlink affiliate snapshot endpoint stub with real …
Browse files Browse the repository at this point in the history
…logic
  • Loading branch information
jerryfan01234 authored Sep 17, 2024
1 parent 9c38c1e commit 3cb2978
Show file tree
Hide file tree
Showing 15 changed files with 537 additions and 73 deletions.
56 changes: 46 additions & 10 deletions indexer/packages/postgres/__tests__/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const blockedAddress: string = 'dydx1f9k5qldwmqrnwy8hcgp4fw6heuvszt35egvt
export const vaultAddress: string = 'dydx1c0m5x87llaunl5sgv3q5vd7j5uha26d2q2r2q0';

// ============== Subaccounts ==============
export const defaultWalletAddress: string = 'defaultWalletAddress';

export const defaultSubaccount: SubaccountCreateObject = {
address: defaultAddress,
Expand All @@ -99,6 +100,14 @@ export const defaultSubaccount3: SubaccountCreateObject = {
updatedAtHeight: createdHeight,
};

// defaultWalletAddress belongs to defaultWallet2 and is different from defaultAddress
export const defaultSubaccountDefaultWalletAddress: SubaccountCreateObject = {
address: defaultWalletAddress,
subaccountNumber: 0,
updatedAt: createdDateTime.toISO(),
updatedAtHeight: createdHeight,
};

export const defaultSubaccountWithAlternateAddress: SubaccountCreateObject = {
address: defaultAddress2,
subaccountNumber: 0,
Expand Down Expand Up @@ -127,8 +136,6 @@ export const isolatedSubaccount2: SubaccountCreateObject = {
updatedAtHeight: createdHeight,
};

export const defaultWalletAddress: string = 'defaultWalletAddress';

export const defaultSubaccountId: string = SubaccountTable.uuid(
defaultAddress,
defaultSubaccount.subaccountNumber,
Expand All @@ -141,6 +148,10 @@ export const defaultSubaccountId3: string = SubaccountTable.uuid(
defaultAddress,
defaultSubaccount3.subaccountNumber,
);
export const defaultSubaccountIdDefaultWalletAddress: string = SubaccountTable.uuid(
defaultWalletAddress,
defaultSubaccountDefaultWalletAddress.subaccountNumber,
);
export const defaultSubaccountIdWithAlternateAddress: string = SubaccountTable.uuid(
defaultAddress2,
defaultSubaccountWithAlternateAddress.subaccountNumber,
Expand Down Expand Up @@ -908,6 +919,17 @@ export const duplicatedSubaccountUsername: SubaccountUsernamesCreateObject = {
subaccountId: defaultSubaccountId3,
};

// defaultWalletAddress belongs to defaultWallet2 and is different from defaultAddress
export const subaccountUsernameWithDefaultWalletAddress: SubaccountUsernamesCreateObject = {
username: 'EvilRaisin11',
subaccountId: defaultSubaccountIdDefaultWalletAddress,
};

export const subaccountUsernameWithAlternativeAddress: SubaccountUsernamesCreateObject = {
username: 'HonestRaisin32',
subaccountId: defaultSubaccountIdWithAlternateAddress,
};

// ============== Leaderboard pnl Data ==============

export const defaultLeaderboardPnlOneDay: LeaderboardPnlCreateObject = {
Expand Down Expand Up @@ -965,24 +987,38 @@ export const defaultKV2: PersistentCacheCreateObject = {

export const defaultAffiliateInfo: AffiliateInfoCreateObject = {
address: defaultAddress,
affiliateEarnings: '10.00',
affiliateEarnings: '10',
referredMakerTrades: 10,
referredTakerTrades: 20,
totalReferredFees: '10.00',
totalReferredFees: '10',
totalReferredUsers: 5,
referredNetProtocolEarnings: '20.00',
referredNetProtocolEarnings: '20',
firstReferralBlockHeight: '1',
referredTotalVolume: '1000',
};

export const defaultAffiliateInfo1: AffiliateInfoCreateObject = {
address: defaultAddress2,
affiliateEarnings: '11.00',
export const defaultAffiliateInfo2: AffiliateInfoCreateObject = {
address: defaultWalletAddress,
affiliateEarnings: '11',
referredMakerTrades: 11,
referredTakerTrades: 21,
totalReferredFees: '11.00',
totalReferredFees: '11',
totalReferredUsers: 5,
referredNetProtocolEarnings: '21.00',
referredNetProtocolEarnings: '21',
firstReferralBlockHeight: '11',
referredTotalVolume: '1000',
};

export const defaultAffiliateInfo3: AffiliateInfoCreateObject = {
address: defaultAddress2,
affiliateEarnings: '12',
referredMakerTrades: 12,
referredTakerTrades: 22,
totalReferredFees: '12',
totalReferredUsers: 10,
referredNetProtocolEarnings: '22',
firstReferralBlockHeight: '12',
referredTotalVolume: '1111111',
};

// ============== Tokens =============
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AffiliateInfoFromDatabase } from '../../src/types';
import { clearData, migrate, teardown } from '../../src/helpers/db-helpers';
import { defaultAffiliateInfo, defaultAffiliateInfo1 } from '../helpers/constants';
import { defaultAffiliateInfo, defaultAffiliateInfo2 } from '../helpers/constants';
import * as AffiliateInfoTable from '../../src/stores/affiliate-info-table';

describe('Affiliate info store', () => {
Expand All @@ -27,20 +27,20 @@ describe('Affiliate info store', () => {

it('Can upsert affiliate info multiple times', async () => {
await AffiliateInfoTable.upsert(defaultAffiliateInfo);
let info: AffiliateInfoFromDatabase | undefined = await AffiliateInfoTable.findById(
let info: AffiliateInfoFromDatabase = await AffiliateInfoTable.findById(
defaultAffiliateInfo.address,
);
expect(info).toEqual(expect.objectContaining(defaultAffiliateInfo));

await AffiliateInfoTable.upsert(defaultAffiliateInfo1);
info = await AffiliateInfoTable.findById(defaultAffiliateInfo1.address);
expect(info).toEqual(expect.objectContaining(defaultAffiliateInfo1));
await AffiliateInfoTable.upsert(defaultAffiliateInfo2);
info = await AffiliateInfoTable.findById(defaultAffiliateInfo2.address);
expect(info).toEqual(expect.objectContaining(defaultAffiliateInfo2));
});

it('Successfully finds all affiliate infos', async () => {
await Promise.all([
AffiliateInfoTable.create(defaultAffiliateInfo),
AffiliateInfoTable.create(defaultAffiliateInfo1),
AffiliateInfoTable.create(defaultAffiliateInfo2),
]);

const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable.findAll(
Expand All @@ -52,17 +52,126 @@ describe('Affiliate info store', () => {
expect(infos.length).toEqual(2);
expect(infos).toEqual(expect.arrayContaining([
expect.objectContaining(defaultAffiliateInfo),
expect.objectContaining(defaultAffiliateInfo1),
expect.objectContaining(defaultAffiliateInfo2),
]));
});

it('Successfully finds an affiliate info', async () => {
await AffiliateInfoTable.create(defaultAffiliateInfo);

const info: AffiliateInfoFromDatabase | undefined = await AffiliateInfoTable.findById(
const info: AffiliateInfoFromDatabase = await AffiliateInfoTable.findById(
defaultAffiliateInfo.address,
);

expect(info).toEqual(expect.objectContaining(defaultAffiliateInfo));
});

describe('paginatedFindWithAddressFilter', () => {
beforeEach(async () => {
await migrate();
await Promise.all(
Array.from({ length: 10 }, (_, i) => AffiliateInfoTable.create({
...defaultAffiliateInfo,
address: `address_${i}`,
affiliateEarnings: i.toString(),
}),
),
);
});

it('Successfully filters by address', async () => {
const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable
.paginatedFindWithAddressFilter(
['address_0'],
0,
10,
false,
);
expect(infos).toBeDefined();
expect(infos!.length).toEqual(1);
expect(infos![0]).toEqual(expect.objectContaining({
...defaultAffiliateInfo,
address: 'address_0',
affiliateEarnings: '0',
}));
});

it('Successfully sorts by affiliate earning', async () => {
const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable
.paginatedFindWithAddressFilter(
[],
0,
10,
true,
);
expect(infos).toBeDefined();
expect(infos!.length).toEqual(10);
expect(infos![0]).toEqual(expect.objectContaining({
...defaultAffiliateInfo,
address: 'address_9',
affiliateEarnings: '9',
}));
expect(infos![9]).toEqual(expect.objectContaining({
...defaultAffiliateInfo,
address: 'address_0',
affiliateEarnings: '0',
}));
});

it('Successfully uses offset and limit', async () => {
const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable
.paginatedFindWithAddressFilter(
[],
5,
2,
false,
);
expect(infos).toBeDefined();
expect(infos!.length).toEqual(2);
expect(infos![0]).toEqual(expect.objectContaining({
...defaultAffiliateInfo,
address: 'address_5',
affiliateEarnings: '5',
}));
expect(infos![1]).toEqual(expect.objectContaining({
...defaultAffiliateInfo,
address: 'address_6',
affiliateEarnings: '6',
}));
});

it('Successfully filters, sorts, offsets, and limits', async () => {
const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable
.paginatedFindWithAddressFilter(
[],
3,
2,
true,
);
expect(infos).toBeDefined();
expect(infos!.length).toEqual(2);
expect(infos![0]).toEqual(expect.objectContaining({
...defaultAffiliateInfo,
address: 'address_6',
affiliateEarnings: '6',
}));
expect(infos![1]).toEqual(expect.objectContaining({
...defaultAffiliateInfo,
address: 'address_5',
affiliateEarnings: '5',
}));
});

it('Returns empty array if no results', async () => {
const infos: AffiliateInfoFromDatabase[] = await AffiliateInfoTable
.paginatedFindWithAddressFilter(
['address_11'],
0,
10,
false,
);
expect(infos).toBeDefined();
expect(infos!.length).toEqual(0);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { SubaccountFromDatabase, SubaccountUsernamesFromDatabase, SubaccountsWithoutUsernamesResult } from '../../src/types';
import * as SubaccountUsernamesTable from '../../src/stores/subaccount-usernames-table';
import * as WalletTable from '../../src/stores/wallet-table';
import * as SubaccountsTable from '../../src/stores/subaccount-table';
import { clearData, migrate, teardown } from '../../src/helpers/db-helpers';
import {
defaultSubaccountUsername,
defaultSubaccountUsername2,
defaultSubaccountWithAlternateAddress,
defaultWallet,
defaultWallet2,
duplicatedSubaccountUsername,
subaccountUsernameWithAlternativeAddress,
} from '../helpers/constants';
import { seedData } from '../helpers/mock-generators';

Expand Down Expand Up @@ -80,4 +85,24 @@ describe('SubaccountUsernames store', () => {
SubaccountUsernamesTable.getSubaccountsWithoutUsernames();
expect(subaccountIds.length).toEqual(subaccountLength - 1);
});

it('Get username using address', async () => {
await Promise.all([
// Add two usernames for defaultWallet
SubaccountUsernamesTable.create(defaultSubaccountUsername),
SubaccountUsernamesTable.create(defaultSubaccountUsername2),
// Add one username for alternativeWallet
WalletTable.create(defaultWallet2),
SubaccountsTable.create(defaultSubaccountWithAlternateAddress),
SubaccountUsernamesTable.create(subaccountUsernameWithAlternativeAddress),
]);

// Should only get username for defaultWallet's subaccount 0
const usernames = await SubaccountUsernamesTable.findByAddress([defaultWallet.address]);
expect(usernames.length).toEqual(1);
expect(usernames[0]).toEqual(expect.objectContaining({
address: defaultWallet.address,
username: defaultSubaccountUsername.username,
}));
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as Knex from 'knex';

export async function up(knex: Knex): Promise<void> {
return knex.schema.alterTable('affiliate_info', (table) => {
// null indicates variable precision whereas not specifying will result in 8,2 precision,scale
table.decimal('affiliateEarnings', null).alter();
table.decimal('totalReferredFees', null).alter();
table.decimal('referredNetProtocolEarnings', null).alter();

table.decimal('referredTotalVolume', null).notNullable();
});
}

export async function down(knex: Knex): Promise<void> {
return knex.schema.alterTable('affiliate_info', (table) => {
table.decimal('affiliateEarnings').alter();
table.decimal('totalReferredFees').alter();
table.decimal('referredNetProtocolEarnings').alter();

table.dropColumn('referredTotalVolume');
});
}
2 changes: 2 additions & 0 deletions indexer/packages/postgres/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { default as SubaccountUsernamesModel } from './models/subaccount-usernam
export { default as LeaderboardPnlModel } from './models/leaderboard-pnl-model';
export { default as PersistentCacheModel } from './models/persistent-cache-model';
export { default as AffiliateReferredUsersModel } from './models/affiliate-referred-users-model';
export { default as AffiliateInfoModel } from './models/affiliate-info-model';

export * as AssetTable from './stores/asset-table';
export * as AssetPositionTable from './stores/asset-position-table';
Expand Down Expand Up @@ -48,6 +49,7 @@ export * as SubaccountUsernamesTable from './stores/subaccount-usernames-table';
export * as PersistentCacheTable from './stores/persistent-cache-table';
export * as AffiliateReferredUsersTable from './stores/affiliate-referred-users-table';
export * as FirebaseNotificationTokenTable from './stores/firebase-notification-token-table';
export * as AffiliateInfoTable from './stores/affiliate-info-table';
export * as VaultTable from './stores/vault-table';

export * as perpetualMarketRefresher from './loops/perpetual-market-refresher';
Expand Down
5 changes: 5 additions & 0 deletions indexer/packages/postgres/src/models/affiliate-info-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default class AffiliateInfoModel extends BaseModel {
'totalReferredUsers',
'referredNetProtocolEarnings',
'firstReferralBlockHeight',
'referredTotalVolume',
],
properties: {
address: { type: 'string' },
Expand All @@ -33,6 +34,7 @@ export default class AffiliateInfoModel extends BaseModel {
totalReferredUsers: { type: 'int' },
referredNetProtocolEarnings: { type: 'string', pattern: NonNegativeNumericPattern },
firstReferralBlockHeight: { type: 'string', pattern: NonNegativeNumericPattern },
referredTotalVolume: { type: 'string', pattern: NonNegativeNumericPattern },
},
};
}
Expand All @@ -53,6 +55,7 @@ export default class AffiliateInfoModel extends BaseModel {
totalReferredUsers: 'int',
referredNetProtocolEarnings: 'string',
firstReferralBlockHeight: 'string',
referredTotalVolume: 'string',
};
}

Expand All @@ -73,4 +76,6 @@ export default class AffiliateInfoModel extends BaseModel {
referredNetProtocolEarnings!: string;

firstReferralBlockHeight!: string;

referredTotalVolume!: string;
}
Loading

0 comments on commit 3cb2978

Please sign in to comment.