Skip to content

Commit

Permalink
Add order triggered notification and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
adamfraser committed Aug 19, 2024
1 parent e2b14ba commit 6b068bc
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 128 deletions.
15 changes: 0 additions & 15 deletions indexer/packages/notifications/__tests__/localization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,4 @@ describe('deriveLocalizedNotificationMessage', () => {
const result = deriveLocalizedNotificationMessage(notification);
expect(result).toEqual(expected);
});

test('should throw an error for unknown notification type', () => {
const unknownNotification = {
type: 'UNKNOWN_TYPE' as NotificationType,
titleKey: LocalizationKey.DEPOSIT_SUCCESS_TITLE,
bodyKey: LocalizationKey.DEPOSIT_SUCCESS_BODY,
deeplink: Deeplink.DEPOSIT,
dynamicValues: {
[NotificationDynamicFieldKey.AMOUNT]: '1000',
[NotificationDynamicFieldKey.MARKET]: 'USDT',
},
} as Notification;

expect(() => deriveLocalizedNotificationMessage(unknownNotification)).toThrowError('Unknown notification type');
});
});
37 changes: 12 additions & 25 deletions indexer/packages/notifications/src/localization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
LocalizationKey,
Notification,
NotificationMesage,
NotificationType,
} from './types';

function replacePlaceholders(template: string, variables: Record<string, string>): string {
Expand All @@ -16,30 +15,18 @@ export function deriveLocalizedNotificationMessage(notification: Notification):
[LocalizationKey.ORDER_FILLED_BODY]: 'Order Filled',
// eslint-disable-next-line no-template-curly-in-string
[LocalizationKey.ORDER_FILLED_TITLE]: 'Your order for {AMOUNT} {MARKET} was filled at ${AVERAGE_PRICE}',
// eslint-disable-next-line no-template-curly-in-string
[LocalizationKey.ORDER_TRIGGERED_BODY]: 'Your order for {AMOUNT} {MARKET} was triggered at ${PRICE}',
[LocalizationKey.ORDER_TRIGGERED_TITLE]: '{MARKET} Order Triggered',
};

switch (notification.type) {
case NotificationType.DEPOSIT_SUCCESS:
return {
title: replacePlaceholders(
tempLocalizationFields[notification.titleKey],
notification.dynamicValues),
body: replacePlaceholders(
tempLocalizationFields[notification.bodyKey],
notification.dynamicValues,
),
};
case NotificationType.ORDER_FILLED:
return {
title: replacePlaceholders(
tempLocalizationFields[notification.titleKey],
notification.dynamicValues),
body: replacePlaceholders(
tempLocalizationFields[notification.bodyKey],
notification.dynamicValues,
),
};
default:
throw new Error('Unknown notification type');
}
return {
title: replacePlaceholders(
tempLocalizationFields[notification.titleKey],
notification.dynamicValues),
body: replacePlaceholders(
tempLocalizationFields[notification.bodyKey],
notification.dynamicValues,
),
};
}
2 changes: 1 addition & 1 deletion indexer/packages/notifications/src/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export async function sendFirebaseMessage(

const tokens = await getUserRegistrationTokens(address);
if (tokens.length === 0) {
throw new Error('User has no registration tokens');
throw new Error(`User has no registration tokens: ${address}`);
}

const { title, body } = deriveLocalizedNotificationMessage(notification);
Expand Down
44 changes: 34 additions & 10 deletions indexer/packages/notifications/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
export enum NotificationType {
DEPOSIT_SUCCESS = 'DEPOSIT_SUCCESS',
FAST_WITHDRAW_SUCCESS = 'FAST_WITHDRAW_SUCCESS',
SLOW_WITHDRAWAL_PENDING = 'SLOW_WITHDRAWAL_PENDING',
SLOW_WITHDRAWAL_SUCCESS = 'SLOW_WITHDRAWAL_SUCCESS',
ORDER_CANCEL = 'ORDER_CANCEL',
ORDER_FILLED = 'ORDER_FILLED',
ORDER_PARTIAL_FILL = 'ORDER_PARTIAL_FILL',
ORDER_TRIGGERED = 'ORDER_TRIGGERED',
LIQUIDATION = 'LIQUIDATION',
VOLATILITY = 'VOLATILITY',
}

// Keys for the dynamic values that are used in the notification messages
// Each key corresponds to a placeholder in the localizable strings for each notification
export enum NotificationDynamicFieldKey {
AMOUNT = 'AMOUNT',
AVERAGE_PRICE = 'AVERAGE_PRICE',
PRICE = 'PRICE',
FILLED_AMOUNT = 'FILLED_AMOUNT',
MARKET = 'MARKET',
SIDE = 'SIDE',
Expand All @@ -28,12 +23,15 @@ export enum LocalizationKey {
DEPOSIT_SUCCESS_BODY = 'DEPOSIT_SUCCESS_BODY',
ORDER_FILLED_TITLE = 'ORDER_FILLED_TITLE',
ORDER_FILLED_BODY = 'ORDER_FILLED_BODY',
ORDER_TRIGGERED_TITLE = 'ORDER_TRIGGERED_TITLE',
ORDER_TRIGGERED_BODY = 'ORDER_TRIGGERED_BODY',
}

// Deeplinks for each notification
export enum Deeplink {
DEPOSIT = '/profile',
ORDER_FILLED = '/profile',
ORDER_TRIGGERED = '/profile',
}

export enum Topic {
Expand Down Expand Up @@ -79,20 +77,39 @@ interface OrderFilledNotification extends BaseNotification <{
};
}

interface OrderTriggeredNotification extends BaseNotification <{
[NotificationDynamicFieldKey.MARKET]: string;
[NotificationDynamicFieldKey.PRICE]: string;
}>{
type: NotificationType.ORDER_TRIGGERED;
titleKey: LocalizationKey.ORDER_TRIGGERED_TITLE;
bodyKey: LocalizationKey.ORDER_TRIGGERED_BODY;
topic: Topic.TRADING;
dynamicValues: {
[NotificationDynamicFieldKey.MARKET]: string;
[NotificationDynamicFieldKey.AMOUNT]: string;
[NotificationDynamicFieldKey.PRICE]: string;
};
}

export type NotificationMesage = {
title: string;
body: string;
};

export type Notification = DepositSuccessNotification | OrderFilledNotification;
export type Notification =
DepositSuccessNotification |
OrderFilledNotification |
OrderTriggeredNotification;

export function createNotification<T extends NotificationType>(
type: T,
dynamicValues: T extends NotificationType.DEPOSIT_SUCCESS
? DepositSuccessNotification['dynamicValues']
: T extends NotificationType.ORDER_FILLED
? OrderFilledNotification['dynamicValues']
: never,
: T extends NotificationType.ORDER_TRIGGERED
? OrderTriggeredNotification['dynamicValues'] : never,
): Notification {
switch (type) {
case NotificationType.DEPOSIT_SUCCESS:
Expand All @@ -104,7 +121,6 @@ export function createNotification<T extends NotificationType>(
deeplink: Deeplink.DEPOSIT,
dynamicValues: dynamicValues as DepositSuccessNotification['dynamicValues'],
};

case NotificationType.ORDER_FILLED:
return {
type: NotificationType.ORDER_FILLED,
Expand All @@ -114,9 +130,17 @@ export function createNotification<T extends NotificationType>(
deeplink: Deeplink.ORDER_FILLED,
dynamicValues: dynamicValues as OrderFilledNotification['dynamicValues'],
};
case NotificationType.ORDER_TRIGGERED:
return {
type: NotificationType.ORDER_TRIGGERED,
titleKey: LocalizationKey.ORDER_TRIGGERED_TITLE,
bodyKey: LocalizationKey.ORDER_TRIGGERED_BODY,
topic: Topic.TRADING,
deeplink: Deeplink.ORDER_TRIGGERED,
dynamicValues: dynamicValues as OrderTriggeredNotification['dynamicValues'],
};

// Add other cases for new notification types here

default:
throw new Error('Unknown notification type');
}
Expand Down
2 changes: 1 addition & 1 deletion indexer/packages/postgres/__tests__/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@ export const defaultLeaderboardPnlOneDayToUpsert: LeaderboardPnlCreateObject = {
// ============== Tokens =============

export const defaultToken = {
token: '01234ABCD',
token: 'DEFAULT_TOKEN',
address: defaultAddress,
updatedAt: createdDateTime.toISO(),
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as MarketTable from '../../src/stores/market-table';
import * as PerpetualMarketTable from '../../src/stores/perpetual-market-table';
import * as SubaccountTable from '../../src/stores/subaccount-table';
import * as TendermintEventTable from '../../src/stores/tendermint-event-table';
import * as TokenTable from '../../src/stores/token-table';
import * as WalletTable from '../../src/stores/wallet-table';
import {
defaultAsset,
Expand All @@ -26,6 +27,7 @@ import {
defaultTendermintEvent2,
defaultTendermintEvent3,
defaultTendermintEvent4,
defaultToken,
defaultWallet,
isolatedMarket,
isolatedMarket2,
Expand Down Expand Up @@ -78,4 +80,7 @@ export async function seedData() {
await Promise.all([
WalletTable.create(defaultWallet),
]);
await Promise.all([
TokenTable.create(defaultToken),
]);
}
Loading

0 comments on commit 6b068bc

Please sign in to comment.