Skip to content

Commit

Permalink
feat(incoming-payment): poll incoming payment
Browse files Browse the repository at this point in the history
  • Loading branch information
golobitch committed Aug 8, 2024
1 parent 57b2526 commit c2ab248
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 7 deletions.
3 changes: 2 additions & 1 deletion packages/backend/src/graphql/errors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export enum GraphQLErrorCode {
Inactive = 'INACTIVE',
InternalServerError = 'INTERNAL_SERVER_ERROR',
NotFound = 'NOT_FOUND',
Conflict = 'CONFLICT'
Conflict = 'CONFLICT',
Timeout = 'TIMEOUT'
}
12 changes: 8 additions & 4 deletions packages/backend/src/open_payments/payment/incoming/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export enum IncomingPaymentError {
InvalidState = 'InvalidState',
InvalidExpiry = 'InvalidExpiry',
WrongState = 'WrongState',
InactiveWalletAddress = 'InactiveWalletAddress'
InactiveWalletAddress = 'InactiveWalletAddress',
ActionNotPerformed = 'ActionNotPerformed'
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
Expand All @@ -23,7 +24,8 @@ export const errorToHTTPCode: {
[IncomingPaymentError.InvalidState]: 400,
[IncomingPaymentError.InvalidExpiry]: 400,
[IncomingPaymentError.WrongState]: 409,
[IncomingPaymentError.InactiveWalletAddress]: 400
[IncomingPaymentError.InactiveWalletAddress]: 400,
[IncomingPaymentError.ActionNotPerformed]: 400
}

export const errorToCode: {
Expand All @@ -35,7 +37,8 @@ export const errorToCode: {
[IncomingPaymentError.InvalidState]: GraphQLErrorCode.BadUserInput,
[IncomingPaymentError.InvalidExpiry]: GraphQLErrorCode.BadUserInput,
[IncomingPaymentError.WrongState]: GraphQLErrorCode.Conflict,
[IncomingPaymentError.InactiveWalletAddress]: GraphQLErrorCode.Inactive
[IncomingPaymentError.InactiveWalletAddress]: GraphQLErrorCode.Inactive,
[IncomingPaymentError.ActionNotPerformed]: GraphQLErrorCode.Timeout,
}

export const errorToMessage: {
Expand All @@ -47,5 +50,6 @@ export const errorToMessage: {
[IncomingPaymentError.InvalidState]: 'invalid state',
[IncomingPaymentError.InvalidExpiry]: 'invalid expiresAt',
[IncomingPaymentError.WrongState]: 'wrong state',
[IncomingPaymentError.InactiveWalletAddress]: 'inactive wallet address'
[IncomingPaymentError.InactiveWalletAddress]: 'inactive wallet address',
[IncomingPaymentError.ActionNotPerformed]: 'action not performed'
}
33 changes: 31 additions & 2 deletions packages/backend/src/open_payments/payment/incoming/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { Amount } from '../../amount'
import { IncomingPaymentError } from './errors'
import { IAppConfig } from '../../../config/app'
import { poll } from '../../../shared/utils'

export const POSITIVE_SLIPPAGE = BigInt(1)
// First retry waits 10 seconds
Expand Down Expand Up @@ -120,7 +121,8 @@ async function createIncomingPayment(
return IncomingPaymentError.InvalidAmount
}
}
const incomingPayment = await IncomingPayment.query(trx || deps.knex)

let incomingPayment = await IncomingPayment.query(trx || deps.knex)
.insertAndFetch({
walletAddressId: walletAddressId,
client,
Expand All @@ -139,7 +141,34 @@ async function createIncomingPayment(
data: incomingPayment.toData(0n)
})

return await addReceivedAmount(deps, incomingPayment, BigInt(0))
incomingPayment = await addReceivedAmount(deps, incomingPayment, BigInt(0))
if (!deps.config.pollIncomingPaymentCreatedWebhook) {
return incomingPayment
}

try {
const response = await poll({
request: async () => getApprovedOrCanceledIncomingPayment(deps, { id: incomingPayment.id }),
pollingFrequencyMs: deps.config.incomingPaymentCreatedPollFrequency,
timeoutMs: deps.config.incomingPaymentCreatedPollTimeout
})

if (response) return response
return IncomingPaymentError.ActionNotPerformed
}catch(err) {
return IncomingPaymentError.ActionNotPerformed
}

}

async function getApprovedOrCanceledIncomingPayment(deps: ServiceDependencies, options: GetOptions) {
const incomingPayment = await getIncomingPayment(deps, { id: options.id })

if (incomingPayment?.approvedAt || incomingPayment?.cancelledAt) {
return incomingPayment
}

return undefined
}

// Fetch (and lock) an incoming payment for work.
Expand Down

0 comments on commit c2ab248

Please sign in to comment.