From d7d7c496e4e827f10d285ab4d3e6644a06fd9cc2 Mon Sep 17 00:00:00 2001 From: heyolaniran Date: Fri, 27 Feb 2026 21:26:29 +0100 Subject: [PATCH 1/2] feat: handling push notification on onchain payment receive --- .../ibex/webhook-server/routes/on-receive.ts | 82 +++++++++++++++---- 1 file changed, 65 insertions(+), 17 deletions(-) diff --git a/src/services/ibex/webhook-server/routes/on-receive.ts b/src/services/ibex/webhook-server/routes/on-receive.ts index 7a7ad2b5d..1dfc3bbb1 100644 --- a/src/services/ibex/webhook-server/routes/on-receive.ts +++ b/src/services/ibex/webhook-server/routes/on-receive.ts @@ -78,9 +78,10 @@ const sendLightningNotification = async ( recipientAccountId: recipientAccount.id, recipientWalletId: receiverWallet.id, paymentAmount: toPaymentAmount(receiverWallet.currency)(transaction.amount), - displayPaymentAmount: await toDisplayAmount(recipientAccount.displayCurrency)( - receivedSat, - ), + displayPaymentAmount: await toDisplayAmount( + recipientAccount.displayCurrency, + WalletCurrency.Btc, + )(receivedSat), paymentHash: transaction.invoice.hash, recipientDeviceTokens: recipientUser.deviceTokens, recipientNotificationSettings: recipientAccount.notificationSettings, @@ -96,6 +97,40 @@ const sendLightningNotification = async ( next() } +const sendOnchainNotification = async ( + req: PaymentRequest, + res: Response, + next: NextFunction +) => { + if (!req.paymentContext) return next() + + const { transaction } = req.body; + + const { receiverWallet, recipientAccount, recipientUser } = req.paymentContext; + + const nResp = await NotificationsService().onChainTxReceived({ + recipientAccountId: recipientAccount.id, + recipientWalletId: receiverWallet.id, + paymentAmount: toPaymentAmount(receiverWallet.currency)(transaction.amount), + displayPaymentAmount: await toDisplayAmount( + recipientAccount.displayCurrency, + receiverWallet.currency as WalletCurrency, + )(transaction.amount), + recipientDeviceTokens: recipientUser.deviceTokens, + recipientNotificationSettings: recipientAccount.notificationSettings, + recipientLanguage: recipientUser.language, + txHash: transaction.hash, + }) + + if (nResp instanceof DeviceTokensNotRegisteredNotificationsServiceError) { + await removeDeviceTokens({ userId: recipientUser.id, deviceTokens: nResp.tokens }) + } else if (nResp instanceof NotificationsServiceError) { + logger.error(nResp) + } + + next() +} + const sendZapReceipt = async ( req: PaymentRequest, _resp: Response, @@ -169,25 +204,38 @@ router.post(paths.cashout, authenticate, logRequest, (_req, resp) => { resp.status(200).end() }) -router.post(paths.onchain, authenticate, logRequest, (_req, resp) => { - baseLogger.info("Received onchain payment (not implemented).") +router.post(paths.onchain, authenticate, logRequest, fetchPaymentContext, sendOnchainNotification, (_req, resp) => { + baseLogger.info("Received onchain payment.") resp.status(200).end() }) export { paths, router } // --- Helper functions --- -const toPaymentAmount = (currency: WalletCurrency) => (dollarAmount: number) => { - let amount - if (currency === WalletCurrency.Usd) amount = (dollarAmount * 100) as any - return { amount, currency } -} - -const toDisplayAmount = (currency: DisplayCurrency) => async (sats: number) => { - const displayCurrencyPrice = await getCurrentPriceAsDisplayPriceRatio({ currency }) - if (displayCurrencyPrice instanceof Error) { - logger.warn(displayCurrencyPrice, "displayCurrencyPrice") - return undefined +const toPaymentAmount = (currency: WalletCurrency) => (amount: number) => { + let paymentAmount: bigint + if (currency === WalletCurrency.Usd) { + paymentAmount = BigInt(Math.round(amount * 100)) + } else if (currency === WalletCurrency.Btc) { + paymentAmount = BigInt(Math.round(amount * 100_000_000)) + } else { + paymentAmount = BigInt(Math.round(amount)) } - return displayCurrencyPrice.convertFromWallet({ amount: BigInt(sats), currency: "BTC" }) + return { amount: paymentAmount, currency } } + +const toDisplayAmount = + (displayCurrency: DisplayCurrency, walletCurrency: WalletCurrency) => + async (amount: number) => { + const displayCurrencyPrice = await getCurrentPriceAsDisplayPriceRatio({ + currency: displayCurrency, + walletCurrency, + }) + if (displayCurrencyPrice instanceof Error) { + logger.warn(displayCurrencyPrice, "displayCurrencyPrice") + return undefined + } + return displayCurrencyPrice.convertFromWallet( + toPaymentAmount(walletCurrency)(amount), + ) + } From 6b31fc8613530ecee213c1feb31f67229223fb4d Mon Sep 17 00:00:00 2001 From: heyolaniran Date: Fri, 27 Feb 2026 21:26:58 +0100 Subject: [PATCH 2/2] feat: handling push notification on onchain payment receive --- .../ibex/webhook-server/routes/on-receive.ts | 51 +++++++------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/src/services/ibex/webhook-server/routes/on-receive.ts b/src/services/ibex/webhook-server/routes/on-receive.ts index 1dfc3bbb1..63a8c4e9d 100644 --- a/src/services/ibex/webhook-server/routes/on-receive.ts +++ b/src/services/ibex/webhook-server/routes/on-receive.ts @@ -78,10 +78,9 @@ const sendLightningNotification = async ( recipientAccountId: recipientAccount.id, recipientWalletId: receiverWallet.id, paymentAmount: toPaymentAmount(receiverWallet.currency)(transaction.amount), - displayPaymentAmount: await toDisplayAmount( - recipientAccount.displayCurrency, - WalletCurrency.Btc, - )(receivedSat), + displayPaymentAmount: await toDisplayAmount(recipientAccount.displayCurrency)( + receivedSat, + ), paymentHash: transaction.invoice.hash, recipientDeviceTokens: recipientUser.deviceTokens, recipientNotificationSettings: recipientAccount.notificationSettings, @@ -112,14 +111,11 @@ const sendOnchainNotification = async ( recipientAccountId: recipientAccount.id, recipientWalletId: receiverWallet.id, paymentAmount: toPaymentAmount(receiverWallet.currency)(transaction.amount), - displayPaymentAmount: await toDisplayAmount( - recipientAccount.displayCurrency, - receiverWallet.currency as WalletCurrency, - )(transaction.amount), + displayPaymentAmount: await toDisplayAmount(recipientAccount.displayCurrency)(transaction.amount), recipientDeviceTokens: recipientUser.deviceTokens, recipientNotificationSettings: recipientAccount.notificationSettings, recipientLanguage: recipientUser.language, - txHash: transaction.hash, + txHash: transaction.hash }) if (nResp instanceof DeviceTokensNotRegisteredNotificationsServiceError) { @@ -212,30 +208,17 @@ router.post(paths.onchain, authenticate, logRequest, fetchPaymentContext, sendOn export { paths, router } // --- Helper functions --- -const toPaymentAmount = (currency: WalletCurrency) => (amount: number) => { - let paymentAmount: bigint - if (currency === WalletCurrency.Usd) { - paymentAmount = BigInt(Math.round(amount * 100)) - } else if (currency === WalletCurrency.Btc) { - paymentAmount = BigInt(Math.round(amount * 100_000_000)) - } else { - paymentAmount = BigInt(Math.round(amount)) - } - return { amount: paymentAmount, currency } +const toPaymentAmount = (currency: WalletCurrency) => (dollarAmount: number) => { + let amount + if (currency === WalletCurrency.Usd) amount = (dollarAmount * 100) as any + return { amount, currency } } -const toDisplayAmount = - (displayCurrency: DisplayCurrency, walletCurrency: WalletCurrency) => - async (amount: number) => { - const displayCurrencyPrice = await getCurrentPriceAsDisplayPriceRatio({ - currency: displayCurrency, - walletCurrency, - }) - if (displayCurrencyPrice instanceof Error) { - logger.warn(displayCurrencyPrice, "displayCurrencyPrice") - return undefined - } - return displayCurrencyPrice.convertFromWallet( - toPaymentAmount(walletCurrency)(amount), - ) - } +const toDisplayAmount = (currency: DisplayCurrency) => async (sats: number) => { + const displayCurrencyPrice = await getCurrentPriceAsDisplayPriceRatio({ currency }) + if (displayCurrencyPrice instanceof Error) { + logger.warn(displayCurrencyPrice, "displayCurrencyPrice") + return undefined + } + return displayCurrencyPrice.convertFromWallet({ amount: BigInt(sats), currency: "BTC" }) +}