diff --git a/packages/backend/src/payment-method/local/service.test.ts b/packages/backend/src/payment-method/local/service.test.ts index 30130790f0..417e1eee24 100644 --- a/packages/backend/src/payment-method/local/service.test.ts +++ b/packages/backend/src/payment-method/local/service.test.ts @@ -16,7 +16,10 @@ import { AccountingService } from '../../accounting/service' import { truncateTables } from '../../tests/tableManager' import { createOutgoingPaymentWithReceiver } from '../../tests/outgoingPayment' import { OutgoingPayment } from '../../open_payments/payment/outgoing/model' -import { IncomingPayment } from '../../open_payments/payment/incoming/model' +import { + IncomingPayment, + IncomingPaymentState +} from '../../open_payments/payment/incoming/model' import { IncomingPaymentService } from '../../open_payments/payment/incoming/service' import { errorToMessage, TransferError } from '../../accounting/errors' import { PaymentMethodHandlerError } from '../handler/errors' @@ -451,6 +454,45 @@ describe('LocalPaymentService', (): void => { } }) + test('throws error if incoming payment state is not pending', async (): Promise => { + const { receiver, outgoingPayment } = + await createOutgoingPaymentWithReceiver(deps, { + sendingWalletAddress: walletAddressMap['USD'], + receivingWalletAddress: walletAddressMap['USD'], + method: 'ilp', + quoteOptions: { + debitAmount: { + value: 100n, + assetScale: walletAddressMap['USD'].asset.scale, + assetCode: walletAddressMap['USD'].asset.code + } + } + }) + + jest.spyOn(incomingPaymentService, 'get').mockResolvedValueOnce({ + state: IncomingPaymentState.Processing + } as IncomingPayment) + + expect.assertions(4) + try { + await localPaymentService.pay({ + receiver, + outgoingPayment, + finalDebitAmount: 100n, + finalReceiveAmount: 100n + }) + } catch (err) { + expect(err).toBeInstanceOf(PaymentMethodHandlerError) + expect((err as PaymentMethodHandlerError).message).toBe( + 'Bad Incoming Payment State' + ) + expect((err as PaymentMethodHandlerError).description).toBe( + `Incoming Payment state should be ${IncomingPaymentState.Pending}` + ) + expect((err as PaymentMethodHandlerError).retryable).toBe(false) + } + }) + test('throws InsufficientBalance when balance is insufficient', async (): Promise => { const { receiver, outgoingPayment } = await createOutgoingPaymentWithReceiver(deps, { diff --git a/packages/backend/src/payment-method/local/service.ts b/packages/backend/src/payment-method/local/service.ts index 11ce3584a1..598a520000 100644 --- a/packages/backend/src/payment-method/local/service.ts +++ b/packages/backend/src/payment-method/local/service.ts @@ -217,29 +217,31 @@ async function pay( retryable: false }) } + if (incomingPayment.state !== IncomingPaymentState.Pending) { + throw new PaymentMethodHandlerError('Bad Incoming Payment State', { + description: `Incoming Payment state should be ${IncomingPaymentState.Pending}`, + retryable: false + }) + } - // TODO: remove incoming state check? perhaps only applies ilp account middleware where its checking many different things - if (incomingPayment.state === IncomingPaymentState.Pending) { - try { - await deps.accountingService.createLiquidityAccount( - incomingPayment, - LiquidityAccountType.INCOMING + try { + await deps.accountingService.createLiquidityAccount( + incomingPayment, + LiquidityAccountType.INCOMING + ) + } catch (err) { + if (!(err instanceof AccountAlreadyExistsError)) { + deps.logger.error( + { incomingPayment, err }, + 'Failed to create liquidity account for local incoming payment' + ) + throw new PaymentMethodHandlerError( + 'Received error during local payment', + { + description: 'Unknown error while trying to create liquidity account', + retryable: false + } ) - } catch (err) { - if (!(err instanceof AccountAlreadyExistsError)) { - deps.logger.error( - { incomingPayment, err }, - 'Failed to create liquidity account for local incoming payment' - ) - throw new PaymentMethodHandlerError( - 'Received error during local payment', - { - description: - 'Unknown error while trying to create liquidity account', - retryable: false - } - ) - } } }