Skip to content

Commit

Permalink
chore(lint): cancel outgoing payment code
Browse files Browse the repository at this point in the history
  • Loading branch information
golobitch committed May 2, 2024
1 parent 7adeae6 commit 4920165
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 55 deletions.
39 changes: 18 additions & 21 deletions localenv/mock-account-servicing-entity/app/lib/webhooks.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,29 @@ export async function handleOutgoingPaymentCreated(wh: Webhook) {

const amt = parseAmount(payment['debitAmount'] as AmountJSON)
const accBalance = BigInt(acc.creditsPosted) - BigInt(acc.debitsPosted)

// check if account has enough balance. If not, cancel outgoing payment
if (accBalance < amt.value) {
//cancel outgoing payment
const mutationResponse = await apolloClient
.mutate({
mutation: gql`
mutation CancelOutgoingPayment(
$input: CancelOutgoingPaymentInput!
) {
cancelOutgoingPayment(input: $input) {
code
success
message
error
}
}
`,
variables: {
input: {
outgoingPaymentId: payment.id,
reason: "Account does not have enough balance."
await apolloClient.mutate({
mutation: gql`
mutation CancelOutgoingPayment($input: CancelOutgoingPaymentInput!) {
cancelOutgoingPayment(input: $input) {
code
success
message
error
}
}
})
return
`,
variables: {
input: {
outgoingPaymentId: payment.id,
reason: 'Account does not have enough balance.'
}
}
})
return
}

await mockAccounts.pendingDebit(acc.id, amt.value)
Expand Down
30 changes: 21 additions & 9 deletions packages/backend/src/graphql/resolvers/outgoing_payment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,11 +549,22 @@ describe('OutgoingPayment Resolvers', (): void => {
payment = await createPayment({ walletAddressId })
})

const states: [string, OutgoingPaymentError | null][] =
Object.values(OutgoingPaymentState).flatMap((state) => [
["Not enough balance", state == OutgoingPaymentState.Funding ? null : OutgoingPaymentError.WrongState],
["Missing KYC", state == OutgoingPaymentState.Funding ? null : OutgoingPaymentError.WrongState],
])
const states: [string, OutgoingPaymentError | null][] = Object.values(
OutgoingPaymentState
).flatMap((state) => [
[
'Not enough balance',
state == OutgoingPaymentState.Funding
? null
: OutgoingPaymentError.WrongState
],
[
'Missing KYC',
state == OutgoingPaymentState.Funding
? null
: OutgoingPaymentError.WrongState
]
])
test.each(states)(
'200 - %s, error: %s',
async (reason, error): Promise<void> => {
Expand All @@ -576,7 +587,9 @@ describe('OutgoingPayment Resolvers', (): void => {
const response = await appContainer.apolloClient
.mutate({
mutation: gql`
mutation cancelOutgoingPayment($input: CancelOutgoingPaymentInput!) {
mutation cancelOutgoingPayment(
$input: CancelOutgoingPaymentInput!
) {
cancelOutgoingPayment(input: $input) {
code
success
Expand All @@ -602,13 +615,12 @@ describe('OutgoingPayment Resolvers', (): void => {
throw new Error('Data was empty')
})


expect(response.success).toBe(!error)
expect(response.code).toEqual(error ? '409' : '200')

if (!error) {
expect(response.payment).toEqual({
__typename: "OutgoingPayment",
__typename: 'OutgoingPayment',
id: payment.id,
walletAddressId: payment.walletAddressId,
state: OutgoingPaymentState.Cancelled,
Expand All @@ -618,7 +630,7 @@ describe('OutgoingPayment Resolvers', (): void => {
})
} else {
expect(response.message).toEqual('wrong state')
expect(response.payment).toBeNull();
expect(response.payment).toBeNull()
}
}
)
Expand Down
29 changes: 18 additions & 11 deletions packages/backend/src/graphql/resolvers/outgoing_payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,31 @@ export const getOutgoingPayment: QueryResolvers<ApolloContext>['outgoingPayment'
}

export const cancelOutgoingPayment: MutationResolvers<ApolloContext>['cancelOutgoingPayment'] =
async (parent, args, ctx): Promise<ResolversTypes['OutgoingPaymentResponse']> => {
const outgoingPaymentService = await ctx.container.use('outgoingPaymentService')
async (
parent,
args,
ctx
): Promise<ResolversTypes['OutgoingPaymentResponse']> => {
const outgoingPaymentService = await ctx.container.use(
'outgoingPaymentService'
)

return outgoingPaymentService
.cancel(args.input)
.then((paymentOrError: OutgoingPayment | OutgoingPaymentError) =>
isOutgoingPaymentError(paymentOrError)
? {
code: errorToCode[paymentOrError].toString(),
success: false,
message: errorToMessage[paymentOrError]
}
code: errorToCode[paymentOrError].toString(),
success: false,
message: errorToMessage[paymentOrError]
}
: {
code: '200',
success: true,
payment: paymentToGraphql(paymentOrError)
}
).catch(() => ({
code: '200',
success: true,
payment: paymentToGraphql(paymentOrError)
}
)
.catch(() => ({
code: '500',
success: false,
message: 'Error trying to cancel outgoing payment'
Expand Down
7 changes: 5 additions & 2 deletions packages/backend/src/open_payments/payment/outgoing/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ export class OutgoingPayment
}

public get failed(): boolean {
return [OutgoingPaymentState.Cancelled, OutgoingPaymentState.Failed].includes(this.state)
return [
OutgoingPaymentState.Cancelled,
OutgoingPaymentState.Failed
].includes(this.state)
}

// Outgoing peer
Expand Down Expand Up @@ -186,7 +189,7 @@ export enum OutgoingPaymentState {
// Successful completion.
Completed = 'COMPLETED',
// Transaction has been cancelled by ASE
Cancelled = "CANCELLED"
Cancelled = 'CANCELLED'
}

export enum OutgoingPaymentDepositType {
Expand Down
25 changes: 13 additions & 12 deletions packages/backend/src/open_payments/payment/outgoing/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ export interface CreateFromIncomingPayment extends BaseOptions {
}

export type CancelOutgoingPaymentOptions = {
id: string;
reason: string;
id: string
reason: string
}

export type CreateOutgoingPaymentOptions =
Expand All @@ -134,22 +134,23 @@ async function cancelOutgoingPayment(
const { id } = options

return deps.knex.transaction(async (trx) => {
let payment = await OutgoingPayment.query(trx)
.findById(id)
.forUpdate()
let payment = await OutgoingPayment.query(trx).findById(id).forUpdate()

if (!payment) return OutgoingPaymentError.UnknownPayment
if (payment.state !== OutgoingPaymentState.Funding) {
return OutgoingPaymentError.WrongState
}

payment = await payment.$query(trx).patchAndFetch({
state: OutgoingPaymentState.Cancelled,
metadata: {
...payment.metadata,
cancellationReason: options.reason
}
}).withGraphFetched('[quote.asset, walletAddress]')
payment = await payment
.$query(trx)
.patchAndFetch({
state: OutgoingPaymentState.Cancelled,
metadata: {
...payment.metadata,
cancellationReason: options.reason
}
})
.withGraphFetched('[quote.asset, walletAddress]')

return addSentAmount(deps, payment)
})
Expand Down

0 comments on commit 4920165

Please sign in to comment.