Skip to content

Commit

Permalink
refactor(backend): add optional quoteId to getQuote args
Browse files Browse the repository at this point in the history
- add runtime check to ilp payment method implementation requireing it
  • Loading branch information
BlairCurrey committed Nov 1, 2024
1 parent 3fc6924 commit 6634b8f
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 0 deletions.
19 changes: 19 additions & 0 deletions packages/backend/src/open_payments/quote/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
PaymentMethodHandlerError,
PaymentMethodHandlerErrorCode
} from '../../payment-method/handler/errors'
import { v4 as uuid } from 'uuid'

const MAX_INT64 = BigInt('9223372036854775807')

Expand Down Expand Up @@ -80,6 +81,22 @@ export type CreateQuoteOptions =
| QuoteOptionsWithDebitAmount
| QuoteOptionsWithReceiveAmount

// TODO: refactor
// - re-model
// - [ ] remove IlpQuoteDetails.quoteId FK relation so i can insert that first
// - [ ] remove relationship on Quote objection model (and ilp quote details?)
// - quote service
// - [X] make id for quote
// - [X] pass id into getQuote
// - [X] use id for quote create
// ... make payment method service changes
// - [ ] dont do anything with additionalFields
// - payment method service
// - [ ] take quoteId
// - [ ] insert ilpQuoteDetails at end of method and use the given quoteId
// - [ ] remove additionalFields if unused
// - new tests (in addition to updating tests based on above)
// - [ ] ilpQuoteDetails should be checked in payment method getQuote tests. not quote create, as currently
async function createQuote(
deps: ServiceDependencies,
options: CreateQuoteOptions
Expand Down Expand Up @@ -114,9 +131,11 @@ async function createQuote(
try {
const receiver = await resolveReceiver(deps, options)
const paymentMethod = receiver.isLocal ? 'LOCAL' : 'ILP'
const quoteId = uuid()
const quote = await deps.paymentMethodHandlerService.getQuote(
paymentMethod,
{
quoteId,
walletAddress,
receiver,
receiveAmount: options.receiveAmount,
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/payment-method/handler/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { IlpPaymentService } from '../ilp/service'
import { truncateTables } from '../../tests/tableManager'
import { createOutgoingPaymentWithReceiver } from '../../tests/outgoingPayment'
import { LocalPaymentService } from '../local/service'
import { v4 as uuid } from 'uuid'

describe('PaymentMethodHandlerService', (): void => {
let deps: IocContract<AppServices>
Expand Down Expand Up @@ -50,6 +51,7 @@ describe('PaymentMethodHandlerService', (): void => {
})

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress,
receiver: await createReceiver(deps, walletAddress),
debitAmount: {
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/payment-method/handler/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IlpPaymentService } from '../ilp/service'
import { LocalPaymentService } from '../local/service'

export interface StartQuoteOptions {
quoteId?: string
walletAddress: WalletAddress
debitAmount?: Amount
receiveAmount?: Amount
Expand Down
37 changes: 37 additions & 0 deletions packages/backend/src/payment-method/ilp/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { AccountingService } from '../../accounting/service'
import { IncomingPayment } from '../../open_payments/payment/incoming/model'
import { truncateTables } from '../../tests/tableManager'
import { createOutgoingPaymentWithReceiver } from '../../tests/outgoingPayment'
import { v4 as uuid } from 'uuid'

const nock = (global as unknown as { nock: typeof import('nock') }).nock

Expand Down Expand Up @@ -90,6 +91,7 @@ describe('IlpPaymentService', (): void => {
const ratesScope = mockRatesApi(exchangeRatesUrl, () => ({}))

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD']),
debitAmount: {
Expand All @@ -108,6 +110,32 @@ describe('IlpPaymentService', (): void => {
ratesScope.done()
})

test('Throws if quoteId is not provided', async (): Promise<void> => {
const options: StartQuoteOptions = {
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD']),
debitAmount: {
assetCode: 'USD',
assetScale: 2,
value: 100n
}
}

expect.assertions(4)
try {
await ilpPaymentService.getQuote(options)
} catch (error) {
expect(error).toBeInstanceOf(PaymentMethodHandlerError)
expect((error as PaymentMethodHandlerError).message).toBe(
'Received error during ILP quoting'
)
expect((error as PaymentMethodHandlerError).description).toBe(
'quoteId is required for ILP quotes'
)
expect((error as PaymentMethodHandlerError).retryable).toBe(false)
}
})

test('fails on rate service error', async (): Promise<void> => {
const ratesService = await deps.use('ratesService')
jest
Expand All @@ -117,6 +145,7 @@ describe('IlpPaymentService', (): void => {
expect.assertions(4)
try {
await ilpPaymentService.getQuote({
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD']),
debitAmount: {
Expand All @@ -141,6 +170,7 @@ describe('IlpPaymentService', (): void => {
const ratesScope = mockRatesApi(exchangeRatesUrl, () => ({}))

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD']),
debitAmount: {
Expand Down Expand Up @@ -184,6 +214,7 @@ describe('IlpPaymentService', (): void => {
}

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD'], {
incomingAmount
Expand Down Expand Up @@ -218,6 +249,7 @@ describe('IlpPaymentService', (): void => {
expect.assertions(4)
try {
await ilpPaymentService.getQuote({
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD']),
debitAmount: {
Expand All @@ -243,6 +275,7 @@ describe('IlpPaymentService', (): void => {
const ratesScope = mockRatesApi(exchangeRatesUrl, () => ({}))

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD'])
}
Expand Down Expand Up @@ -272,6 +305,7 @@ describe('IlpPaymentService', (): void => {
const ratesScope = mockRatesApi(exchangeRatesUrl, () => ({}))

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD'], {
incomingAmount: {
Expand Down Expand Up @@ -311,6 +345,7 @@ describe('IlpPaymentService', (): void => {
const ratesScope = mockRatesApi(exchangeRatesUrl, () => ({}))

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: walletAddressMap['USD'],
receiver: await createReceiver(deps, walletAddressMap['USD'])
}
Expand Down Expand Up @@ -371,6 +406,7 @@ describe('IlpPaymentService', (): void => {
const sendingWalletAddress = walletAddressMap[debitAssetCode]

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: sendingWalletAddress,
receiver: await createReceiver(deps, receivingWalletAddress),
receiveAmount: {
Expand Down Expand Up @@ -430,6 +466,7 @@ describe('IlpPaymentService', (): void => {
const sendingWalletAddress = walletAddressMap[debitAssetCode]

const options: StartQuoteOptions = {
quoteId: uuid(),
walletAddress: sendingWalletAddress,
receiver: await createReceiver(deps, receivingWalletAddress),
debitAmount: {
Expand Down
7 changes: 7 additions & 0 deletions packages/backend/src/payment-method/ilp/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ async function getQuote(
deps: ServiceDependencies,
options: StartQuoteOptions
): Promise<PaymentQuote> {
if (!options.quoteId) {
throw new PaymentMethodHandlerError('Received error during ILP quoting', {
description: 'quoteId is required for ILP quotes',
retryable: false
})
}

const rates = await deps.ratesService
.rates(options.walletAddress.asset.code)
.catch((_err: Error) => {
Expand Down

0 comments on commit 6634b8f

Please sign in to comment.