Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions src/app/bridge/send-deposit-notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { getI18nInstance } from "@config"
import { checkedToAccountId } from "@domain/accounts"
import { getLanguageOrDefault } from "@domain/locale"
import {
DeviceTokensNotRegisteredNotificationsServiceError,
FlashNotificationCategories,
NotificationsServiceError,
} from "@domain/notifications"
import { removeDeviceTokens } from "@app/users/remove-device-tokens"
import { baseLogger } from "@services/logger"
import { AccountsRepository } from "@services/mongoose/accounts"
import { UsersRepository } from "@services/mongoose/users"
import {
PushNotificationsService,
SendFilteredPushNotificationStatus,
} from "@services/notifications/push-notifications"

const i18n = getI18nInstance()

const formatDepositAmount = (amount: string, currency: string): string =>
`${amount} ${currency.toUpperCase()}`

export const sendBridgeDepositNotification = async ({
accountId: accountIdRaw,
amount,
currency,
}: {
accountId: string
amount: string
currency: string
}): Promise<true | ApplicationError> => {
const accountId = checkedToAccountId(accountIdRaw)
if (accountId instanceof Error) return accountId

const account = await AccountsRepository().findById(accountId)
if (account instanceof Error) return account

const user = await UsersRepository().findById(account.kratosUserId)
if (user instanceof Error) return user

const locale = getLanguageOrDefault(user.language)
const formattedAmount = formatDepositAmount(amount, currency)
const phraseBase = "notification.bridgeDeposit"

const title = i18n.__({ phrase: `${phraseBase}.title`, locale })
const body = i18n.__(
{ phrase: `${phraseBase}.body`, locale },
{ amount: formattedAmount },
)

const result = await PushNotificationsService().sendFilteredNotification({
deviceTokens: user.deviceTokens,
title,
body,
notificationCategory: FlashNotificationCategories.Payments,
notificationSettings: account.notificationSettings,
data: {
type: "bridge_deposit_completed",
amount,
currency: currency == "usdt" ? "USD" : currency.toUpperCase(),
},
})

if (result instanceof NotificationsServiceError) return result

if (result.status === SendFilteredPushNotificationStatus.Filtered) {
return true
}

return true
}

export const sendBridgeDepositNotificationBestEffort = async (
args: Parameters<typeof sendBridgeDepositNotification>[0],
): Promise<void> => {
const result = await sendBridgeDepositNotification(args)

if (result instanceof DeviceTokensNotRegisteredNotificationsServiceError) {
const accountId = checkedToAccountId(args.accountId)
if (accountId instanceof Error) return

const account = await AccountsRepository().findById(accountId)
if (account instanceof Error) return

await removeDeviceTokens({
userId: account.kratosUserId,
deviceTokens: result.tokens,
})
return
}

if (result instanceof Error) {
baseLogger.warn(
{ accountId: args.accountId, error: result },
"Failed to send Bridge deposit push notification",
)
}
}
4 changes: 4 additions & 0 deletions src/config/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"body": "Your cashout of {{amount}} has been deposited to your bank account.",
"title": "Cashout"
},
"bridgeDeposit": {
"body": "Your deposit of {{amount}} has been added to your account.",
"title": "Deposit received"
},
"bridgeWithdrawal": {
"completed": {
"body": "Your withdrawal of {{amount}} has been sent to your bank account.",
Expand Down
4 changes: 4 additions & 0 deletions src/config/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
"title": "Transacción {{walletCurrency}}"
}
},
"bridgeDeposit": {
"body": "Su depósito de {{amount}} se agregó a su cuenta.",
"title": "Depósito recibido"
},
"bridgeWithdrawal": {
"completed": {
"body": "Su retiro de {{amount}} se envió a su cuenta bancaria.",
Expand Down
7 changes: 7 additions & 0 deletions src/services/ibex/webhook-server/routes/crypto-receive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import express, { Request, Response } from "express"
import { AccountsRepository } from "@services/mongoose/accounts"
import { createIbexCryptoReceive } from "@services/mongoose/ibex-crypto-receive-log"
import { listWalletsByAccountId } from "@app/wallets"
import { sendBridgeDepositNotificationBestEffort } from "@app/bridge/send-deposit-notification"
import { WalletCurrency, USDTAmount } from "@domain/shared"
import { baseLogger } from "@services/logger"
import { LockService } from "@services/lock"
Expand Down Expand Up @@ -125,6 +126,12 @@ const cryptoReceiveHandler = async (req: Request, res: Response) => {
return { status: "error", code: "erpnext_audit_failed" } as CryptoReceiveResult
}

await sendBridgeDepositNotificationBestEffort({
accountId: account.id,
amount: String(usdtAmount.asNumber()),
currency: normalizedCurrency,
})

return { status: "success" } as CryptoReceiveResult
} catch (error) {
baseLogger.error({ error, tx_hash }, "Error processing crypto receive webhook")
Expand Down