Skip to content

Commit

Permalink
feat(core): add missing callbacks (#3585)
Browse files Browse the repository at this point in the history
* refactor: isolate notifications type for each channel

* refactor: update notification type enum

* feat: add missing callbacks

* fix: lint issues

* fix: notification type resolver
  • Loading branch information
dolcalmi authored Nov 27, 2023
1 parent 90b384b commit 8976cc5
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 28 deletions.
4 changes: 3 additions & 1 deletion core/api/dev/apollo-federation/supergraph.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,15 @@ type ApiKey
expired: Boolean!
lastUsedAt: Timestamp
expiresAt: Timestamp!
readOnly: Boolean!
}

input ApiKeyCreateInput
@join__type(graph: API_KEYS)
{
name: String!
expireInDays: Int
readOnly: Boolean! = false
}

type ApiKeyCreatePayload
Expand Down Expand Up @@ -1698,7 +1700,7 @@ enum TxNotificationType
{
IntraLedgerPayment @join__enumValue(graph: PUBLIC)
IntraLedgerReceipt @join__enumValue(graph: PUBLIC)
LnInvoicePaid @join__enumValue(graph: PUBLIC)
LigtningReceipt @join__enumValue(graph: PUBLIC)
OnchainPayment @join__enumValue(graph: PUBLIC)
OnchainReceipt @join__enumValue(graph: PUBLIC)
OnchainReceiptPending @join__enumValue(graph: PUBLIC)
Expand Down
48 changes: 40 additions & 8 deletions core/api/src/app/payments/send-intraledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,9 @@ const executePaymentViaIntraledger = async <
}))
}

const senderWalletDescriptor = paymentFlow.senderWalletDescriptor()
const recipientWalletDescriptor = paymentFlow.recipientWalletDescriptor()
if (recipientWalletDescriptor === undefined)
if (!senderWalletDescriptor || !recipientWalletDescriptor)
return new InvalidLightningPaymentFlowBuilderStateError()

const journal = await LedgerFacade.recordIntraledger({
Expand All @@ -332,7 +333,7 @@ const executePaymentViaIntraledger = async <
btc: paymentFlow.btcPaymentAmount,
usd: paymentFlow.usdPaymentAmount,
},
senderWalletDescriptor: paymentFlow.senderWalletDescriptor(),
senderWalletDescriptor,
recipientWalletDescriptor,
metadata,
additionalDebitMetadata,
Expand All @@ -344,13 +345,13 @@ const executePaymentViaIntraledger = async <
const recipientUser = await UsersRepository().findById(recipientAccount.kratosUserId)
if (recipientUser instanceof Error) return recipientUser

const walletTransaction = await getTransactionForWalletByJournalId({
const recipientWalletTransaction = await getTransactionForWalletByJournalId({
walletId: recipientWalletDescriptor.id,
journalId: journal.journalId,
})
if (walletTransaction instanceof Error) return walletTransaction
if (recipientWalletTransaction instanceof Error) return recipientWalletTransaction

const result = await NotificationsService().sendTransaction({
const recipientResult = await NotificationsService().sendTransaction({
recipient: {
accountId: recipientAccount.id,
walletId: recipientWalletDescriptor.id,
Expand All @@ -359,11 +360,42 @@ const executePaymentViaIntraledger = async <
notificationSettings: recipientAccount.notificationSettings,
level: recipientAccount.level,
},
transaction: walletTransaction,
transaction: recipientWalletTransaction,
})

if (result instanceof DeviceTokensNotRegisteredNotificationsServiceError) {
await removeDeviceTokens({ userId: recipientUser.id, deviceTokens: result.tokens })
if (recipientResult instanceof DeviceTokensNotRegisteredNotificationsServiceError) {
await removeDeviceTokens({
userId: recipientUser.id,
deviceTokens: recipientResult.tokens,
})
}

const senderUser = await UsersRepository().findById(senderAccount.kratosUserId)
if (senderUser instanceof Error) return senderUser

const senderWalletTransaction = await getTransactionForWalletByJournalId({
walletId: senderWalletDescriptor.id,
journalId: journal.journalId,
})
if (senderWalletTransaction instanceof Error) return senderWalletTransaction

const senderResult = await NotificationsService().sendTransaction({
recipient: {
accountId: senderAccount.id,
walletId: senderWalletDescriptor.id,
deviceTokens: senderUser.deviceTokens,
language: senderUser.language,
notificationSettings: senderAccount.notificationSettings,
level: senderAccount.level,
},
transaction: senderWalletTransaction,
})

if (senderResult instanceof DeviceTokensNotRegisteredNotificationsServiceError) {
await removeDeviceTokens({
userId: senderUser.id,
deviceTokens: senderResult.tokens,
})
}

return PaymentSendStatus.Success
Expand Down
29 changes: 29 additions & 0 deletions core/api/src/app/payments/send-lightning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export const payInvoiceByWalletId = async ({
decodedInvoice,
paymentFlow,
senderWallet,
senderAccount,
senderDisplayCurrency: senderAccount.displayCurrency,
memo,
})
Expand Down Expand Up @@ -159,6 +160,7 @@ const payNoAmountInvoiceByWalletId = async ({
decodedInvoice,
paymentFlow,
senderWallet,
senderAccount,
senderDisplayCurrency: senderAccount.displayCurrency,
memo,
})
Expand Down Expand Up @@ -560,12 +562,14 @@ const executePaymentViaLn = async ({
decodedInvoice,
paymentFlow,
senderWallet,
senderAccount,
senderDisplayCurrency,
memo,
}: {
decodedInvoice: LnInvoice
paymentFlow: PaymentFlow<WalletCurrency, WalletCurrency>
senderWallet: Wallet
senderAccount: Account
senderDisplayCurrency: DisplayCurrency
memo: string | null
}): Promise<PaymentSendStatus | ApplicationError> => {
Expand Down Expand Up @@ -742,6 +746,31 @@ const executePaymentViaLn = async ({
if (reimbursed instanceof Error) return reimbursed
}

const senderUser = await UsersRepository().findById(senderAccount.kratosUserId)
if (senderUser instanceof Error) return senderUser

const walletTransaction = await getTransactionForWalletByJournalId({
walletId: senderWallet.id,
journalId,
})
if (walletTransaction instanceof Error) return walletTransaction

const result = await NotificationsService().sendTransaction({
recipient: {
accountId: senderWallet.accountId,
walletId: senderWallet.id,
deviceTokens: senderUser.deviceTokens,
language: senderUser.language,
notificationSettings: senderAccount.notificationSettings,
level: senderAccount.level,
},
transaction: walletTransaction,
})

if (result instanceof DeviceTokensNotRegisteredNotificationsServiceError) {
await removeDeviceTokens({ userId: senderUser.id, deviceTokens: result.tokens })
}

return PaymentSendStatus.Success
})
}
40 changes: 40 additions & 0 deletions core/api/src/app/payments/update-pending-payments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { reimburseFailedUsdPayment } from "./reimburse-failed-usd"

import { PaymentFlowFromLedgerTransaction } from "./translations"

import { getTransactionForWalletByJournalId } from "@/app/wallets"
import { removeDeviceTokens } from "@/app/users/remove-device-tokens"

import { toSats } from "@/domain/bitcoin"
import { defaultTimeToExpiryInSeconds, PaymentStatus } from "@/domain/bitcoin/lightning"
import { InconsistentDataError } from "@/domain/errors"
Expand All @@ -16,6 +19,7 @@ import {
} from "@/domain/ledger"
import { MissingPropsInTransactionForPaymentFlowError } from "@/domain/payments"
import { setErrorCritical, WalletCurrency } from "@/domain/shared"
import { DeviceTokensNotRegisteredNotificationsServiceError } from "@/domain/notifications"

import { LedgerService, getNonEndUserWalletIds } from "@/services/ledger"
import * as LedgerFacade from "@/services/ledger/facade"
Expand All @@ -24,8 +28,10 @@ import { LockService } from "@/services/lock"
import {
AccountsRepository,
PaymentFlowStateRepository,
UsersRepository,
WalletsRepository,
} from "@/services/mongoose"
import { NotificationsService } from "@/services/notifications"
import { addAttributesToCurrentSpan, wrapAsyncToRunInSpan } from "@/services/tracing"
import { runInParallel } from "@/utils"

Expand Down Expand Up @@ -263,6 +269,40 @@ const updatePendingPayment = wrapAsyncToRunInSpan({
return new MissingExpectedDisplayAmountsForTransactionError()
}

const senderWallet = await WalletsRepository().findById(walletId)
if (senderWallet instanceof Error) return senderWallet

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

const senderUser = await UsersRepository().findById(senderAccount.kratosUserId)
if (senderUser instanceof Error) return senderUser

const walletTransaction = await getTransactionForWalletByJournalId({
walletId,
journalId: pendingPayment.journalId,
})
if (walletTransaction instanceof Error) return walletTransaction

const result = await NotificationsService().sendTransaction({
recipient: {
accountId: senderWallet.accountId,
walletId,
deviceTokens: senderUser.deviceTokens,
language: senderUser.language,
notificationSettings: senderAccount.notificationSettings,
level: senderAccount.level,
},
transaction: walletTransaction,
})

if (result instanceof DeviceTokensNotRegisteredNotificationsServiceError) {
await removeDeviceTokens({
userId: senderUser.id,
deviceTokens: result.tokens,
})
}

return reimburseFee({
paymentFlow,
senderDisplayAmount: displayAmount,
Expand Down
4 changes: 4 additions & 0 deletions core/api/src/domain/callback/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
export const CallbackEventType = {
SendIntraledger: "send.intraledger",
ReceiveIntraledger: "receive.intraledger",
SendLightning: "send.lightning",
ReceiveLightning: "receive.lightning",
SendOnchain: "send.onchain",
ReceiveOnchain: "receive.onchain",
} as const
3 changes: 2 additions & 1 deletion core/api/src/domain/notifications/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export const NotificationType = {
OnchainReceipt: "onchain_receipt",
OnchainReceiptPending: "onchain_receipt_pending",
OnchainPayment: "onchain_payment",
LnInvoicePaid: "paid-invoice",
LigtningReceipt: "paid-invoice",
LigtningPayment: "lightning_payment",
} as const

export const NotificationChannel = {
Expand Down
2 changes: 1 addition & 1 deletion core/api/src/graphql/public/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,7 @@ enum TxDirection {
enum TxNotificationType {
IntraLedgerPayment
IntraLedgerReceipt
LnInvoicePaid
LigtningReceipt
OnchainPayment
OnchainReceipt
OnchainReceiptPending
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const TxNotificationType = GT.Enum({
OnchainReceipt: { value: "onchain_receipt" },
OnchainReceiptPending: { value: "onchain_receipt_pending" },
OnchainPayment: { value: "onchain_payment" },
LnInvoicePaid: { value: "paid-invoice" },
LigtningReceipt: { value: "paid-invoice" },
IntraLedgerReceipt: { value: "intra_ledger_receipt" },
IntraLedgerPayment: { value: "intra_ledger_payment" },
},
Expand Down
29 changes: 23 additions & 6 deletions core/api/src/services/notifications/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const NotificationsService = (): INotificationsService => {
const type = getPubSubNotificationEventType(transaction)
if (!type) return

if (type === NotificationType.LnInvoicePaid) {
if (type === NotificationType.LigtningReceipt) {
const lnTx = transaction as WalletLnTransaction
const paymentHash = lnTx.initiationVia.paymentHash
// Notify public subscribers
Expand Down Expand Up @@ -379,7 +379,7 @@ const getPubSubNotificationEventType = (
): NotificationType | undefined => {
const type = translateToNotificationType(transaction)
switch (type) {
case NotificationType.LnInvoicePaid:
case NotificationType.LigtningReceipt:
case NotificationType.IntraLedgerReceipt:
case NotificationType.OnchainReceiptPending:
case NotificationType.OnchainPayment:
Expand All @@ -402,7 +402,7 @@ const getPushNotificationEventType = (
): NotificationType | undefined => {
const type = translateToNotificationType(transaction)
switch (type) {
case NotificationType.LnInvoicePaid:
case NotificationType.LigtningReceipt:
case NotificationType.IntraLedgerReceipt:
case NotificationType.OnchainReceiptPending:
case NotificationType.OnchainPayment:
Expand All @@ -425,10 +425,25 @@ const getCallbackEventType = (
): CallbackEventType | undefined => {
const type = translateToNotificationType(transaction)
switch (type) {
case NotificationType.LnInvoicePaid:
case NotificationType.LigtningReceipt:
return CallbackEventType.ReceiveLightning

case NotificationType.LigtningPayment:
return CallbackEventType.SendLightning

case NotificationType.IntraLedgerReceipt:
return CallbackEventType.ReceiveIntraledger

case NotificationType.IntraLedgerPayment:
return CallbackEventType.SendIntraledger

case NotificationType.OnchainReceiptPending:
case NotificationType.OnchainReceipt:
return CallbackEventType.ReceiveOnchain

case NotificationType.OnchainPayment:
return CallbackEventType.SendOnchain

default:
return undefined
}
Expand All @@ -440,11 +455,13 @@ const translateToNotificationType = (
const type = transaction.initiationVia.type
const isReceive = transaction.settlementAmount > 0
if (type === "lightning") {
return isReceive ? NotificationType.LnInvoicePaid : undefined
return isReceive ? NotificationType.LigtningReceipt : NotificationType.LigtningPayment
}

if (type === "intraledger") {
return isReceive ? NotificationType.IntraLedgerReceipt : undefined
return isReceive
? NotificationType.IntraLedgerReceipt
: NotificationType.IntraLedgerPayment
}

if (type === "onchain") {
Expand Down
Loading

0 comments on commit 8976cc5

Please sign in to comment.