From 6a51fd9e48be912956c7497b075e49dec2749800 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Fri, 19 Sep 2025 13:55:55 +0200 Subject: [PATCH 01/11] feat(backend): update CardDetailsInput GraphQL type --- .../generated/graphql.ts | 5 +-- .../src/graphql/generated/graphql.schema.json | 36 +++++++++++++++++-- .../backend/src/graphql/generated/graphql.ts | 5 +-- packages/backend/src/graphql/schema.graphql | 5 +-- .../src/graphql/generated/graphql.ts | 5 +-- packages/frontend/app/generated/graphql.ts | 5 +-- .../src/generated/graphql.ts | 5 +-- .../src/graphql/generated/graphql.ts | 5 +-- test/test-lib/src/generated/graphql.ts | 5 +-- 9 files changed, 58 insertions(+), 18 deletions(-) diff --git a/localenv/mock-account-servicing-entity/generated/graphql.ts b/localenv/mock-account-servicing-entity/generated/graphql.ts index 2ce732b831..ae53531638 100644 --- a/localenv/mock-account-servicing-entity/generated/graphql.ts +++ b/localenv/mock-account-servicing-entity/generated/graphql.ts @@ -192,8 +192,9 @@ export type CancelOutgoingPaymentInput = { }; export type CardDetailsInput = { - /** Signature */ - signature: Scalars['String']['input']; + data: Scalars['JSONObject']['input']; + initiatedAt: Scalars['String']['input']; + requestId: Scalars['String']['input']; }; export type CreateAssetInput = { diff --git a/packages/backend/src/graphql/generated/graphql.schema.json b/packages/backend/src/graphql/generated/graphql.schema.json index 6a24d91def..339b386496 100644 --- a/packages/backend/src/graphql/generated/graphql.schema.json +++ b/packages/backend/src/graphql/generated/graphql.schema.json @@ -1100,8 +1100,40 @@ "fields": null, "inputFields": [ { - "name": "signature", - "description": "Signature", + "name": "data", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "JSONObject", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "initiatedAt", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "requestId", + "description": null, "type": { "kind": "NON_NULL", "name": null, diff --git a/packages/backend/src/graphql/generated/graphql.ts b/packages/backend/src/graphql/generated/graphql.ts index 2ce732b831..ae53531638 100644 --- a/packages/backend/src/graphql/generated/graphql.ts +++ b/packages/backend/src/graphql/generated/graphql.ts @@ -192,8 +192,9 @@ export type CancelOutgoingPaymentInput = { }; export type CardDetailsInput = { - /** Signature */ - signature: Scalars['String']['input']; + data: Scalars['JSONObject']['input']; + initiatedAt: Scalars['String']['input']; + requestId: Scalars['String']['input']; }; export type CreateAssetInput = { diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index 24d01e55d9..cfaa301bc9 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -1248,8 +1248,9 @@ input CreateOutgoingPaymentInput { } input CardDetailsInput { - "Signature" - signature: String! + data: JSONObject! + requestId: String! + initiatedAt: String! } input CancelOutgoingPaymentInput { diff --git a/packages/card-service/src/graphql/generated/graphql.ts b/packages/card-service/src/graphql/generated/graphql.ts index 550165c896..834a16bf39 100644 --- a/packages/card-service/src/graphql/generated/graphql.ts +++ b/packages/card-service/src/graphql/generated/graphql.ts @@ -192,8 +192,9 @@ export type CancelOutgoingPaymentInput = { }; export type CardDetailsInput = { - /** Signature */ - signature: Scalars['String']['input']; + data: Scalars['JSONObject']['input']; + initiatedAt: Scalars['String']['input']; + requestId: Scalars['String']['input']; }; export type CreateAssetInput = { diff --git a/packages/frontend/app/generated/graphql.ts b/packages/frontend/app/generated/graphql.ts index a19673cc32..5cb0ece1bc 100644 --- a/packages/frontend/app/generated/graphql.ts +++ b/packages/frontend/app/generated/graphql.ts @@ -192,8 +192,9 @@ export type CancelOutgoingPaymentInput = { }; export type CardDetailsInput = { - /** Signature */ - signature: Scalars['String']['input']; + data: Scalars['JSONObject']['input']; + initiatedAt: Scalars['String']['input']; + requestId: Scalars['String']['input']; }; export type CreateAssetInput = { diff --git a/packages/mock-account-service-lib/src/generated/graphql.ts b/packages/mock-account-service-lib/src/generated/graphql.ts index 2ce732b831..ae53531638 100644 --- a/packages/mock-account-service-lib/src/generated/graphql.ts +++ b/packages/mock-account-service-lib/src/generated/graphql.ts @@ -192,8 +192,9 @@ export type CancelOutgoingPaymentInput = { }; export type CardDetailsInput = { - /** Signature */ - signature: Scalars['String']['input']; + data: Scalars['JSONObject']['input']; + initiatedAt: Scalars['String']['input']; + requestId: Scalars['String']['input']; }; export type CreateAssetInput = { diff --git a/packages/point-of-sale/src/graphql/generated/graphql.ts b/packages/point-of-sale/src/graphql/generated/graphql.ts index dc9f2c24b3..331d472897 100644 --- a/packages/point-of-sale/src/graphql/generated/graphql.ts +++ b/packages/point-of-sale/src/graphql/generated/graphql.ts @@ -192,8 +192,9 @@ export type CancelOutgoingPaymentInput = { }; export type CardDetailsInput = { - /** Signature */ - signature: Scalars['String']['input']; + data: Scalars['JSONObject']['input']; + initiatedAt: Scalars['String']['input']; + requestId: Scalars['String']['input']; }; export type CreateAssetInput = { diff --git a/test/test-lib/src/generated/graphql.ts b/test/test-lib/src/generated/graphql.ts index 2ce732b831..ae53531638 100644 --- a/test/test-lib/src/generated/graphql.ts +++ b/test/test-lib/src/generated/graphql.ts @@ -192,8 +192,9 @@ export type CancelOutgoingPaymentInput = { }; export type CardDetailsInput = { - /** Signature */ - signature: Scalars['String']['input']; + data: Scalars['JSONObject']['input']; + initiatedAt: Scalars['String']['input']; + requestId: Scalars['String']['input']; }; export type CreateAssetInput = { From ccc939f216e9c5bab8b205efe2c56b0e9371d2a6 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Fri, 19 Sep 2025 13:57:31 +0200 Subject: [PATCH 02/11] feat(backend): update OutgoingPaymentCardDetails model --- ...date_outgoing_payment_card_details_data.js | 29 +++++++++++++++++++ .../payment/outgoing/card/model.ts | 10 ++++--- .../payment/outgoing/service.test.ts | 25 +++++++++++----- .../open_payments/payment/outgoing/service.ts | 21 +++++--------- 4 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js diff --git a/packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js b/packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js new file mode 100644 index 0000000000..98c3851f02 --- /dev/null +++ b/packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js @@ -0,0 +1,29 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function (knex) { + return knex.schema.alterTable('outgoingPaymentCardDetails', function (table) { + table.dropColumn('expiry') + table.dropColumn('signature') + + table.uuid('requestId').notNullable() + table.jsonb('data').notNullable() + table.timestamp('initiatedAt').notNullable() + }) +} + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function (knex) { + return knex.schema.alterTable('outgoingPaymentCardDetails', function (table) { + table.dropColumn('requestId') + table.dropColumn('data') + table.dropColumn('initiatedAt') + + table.string('signature').notNullable() + table.string('expiry').notNullable() + }) +} diff --git a/packages/backend/src/open_payments/payment/outgoing/card/model.ts b/packages/backend/src/open_payments/payment/outgoing/card/model.ts index faf6750d7e..2018cdf505 100644 --- a/packages/backend/src/open_payments/payment/outgoing/card/model.ts +++ b/packages/backend/src/open_payments/payment/outgoing/card/model.ts @@ -8,8 +8,9 @@ export const outgoingPaymentCardDetailsRelation: OutgoingPaymentIdRelation = 'outgoingPaymentCardDetails.outgoingPaymentId' type OutgoingPaymentCardDetailsType = { - expiry: string - signature: string + requestId: string + data: Record + initiatedAt: Date } & { [key in OutgoingPaymentIdColumnName]: string } @@ -22,7 +23,8 @@ export class OutgoingPaymentCardDetails return 'outgoingPaymentCardDetails' } - public expiry!: string public readonly outgoingPaymentId!: string - public signature!: string + public requestId!: string + public data!: Record + public initiatedAt!: Date } diff --git a/packages/backend/src/open_payments/payment/outgoing/service.test.ts b/packages/backend/src/open_payments/payment/outgoing/service.test.ts index 1d12dbad4b..9278bdaab1 100644 --- a/packages/backend/src/open_payments/payment/outgoing/service.test.ts +++ b/packages/backend/src/open_payments/payment/outgoing/service.test.ts @@ -67,6 +67,7 @@ import { } from '../../../tests/tenantSettings' import { OpenPaymentsPaymentMethod } from '../../../payment-method/provider/service' import { IlpAddress } from 'ilp-packet' +import { OutgoingPaymentCardDetails } from './card/model' describe('OutgoingPaymentService', (): void => { let deps: IocContract @@ -1493,7 +1494,8 @@ describe('OutgoingPaymentService', (): void => { } ) }) - test('failed to create when expiry is not valid', async () => { + + test('stores card details when card payment', async () => { const paymentMethods: OpenPaymentsPaymentMethod[] = [ { type: 'ilp', @@ -1512,19 +1514,28 @@ describe('OutgoingPaymentService', (): void => { incomingPayment: incomingPayment.toOpenPaymentsTypeWithMethods( config.openPaymentsUrl, receiverWalletAddress, - paymentMethods ).id, tenantId, cardDetails: { - expiry: 'invalid', - signature: 'test' + requestId: crypto.randomUUID(), + initiatedAt: new Date(), + data: { + signature: 'signature', + payload: 'payload' + } } } - const payment = await outgoingPaymentService.create(options) - expect(isOutgoingPaymentError(payment)).toBeTruthy() - expect(payment).toBe(OutgoingPaymentError.InvalidCardExpiry) + const outgoingPayment = await outgoingPaymentService.create(options) + + assert(outgoingPayment instanceof OutgoingPayment) + + const cardDetails = await OutgoingPaymentCardDetails.query(knex).where({ + outgoingPaymentId: outgoingPayment.id + }) + + expect(cardDetails).toHaveLength(1) }) }) diff --git a/packages/backend/src/open_payments/payment/outgoing/service.ts b/packages/backend/src/open_payments/payment/outgoing/service.ts index 21d8b7f738..d0ea0f3026 100644 --- a/packages/backend/src/open_payments/payment/outgoing/service.ts +++ b/packages/backend/src/open_payments/payment/outgoing/service.ts @@ -202,8 +202,9 @@ export interface CreateFromIncomingPayment extends BaseOptions { export interface CreateFromCardPayment extends CreateFromIncomingPayment { cardDetails: { - expiry: string - signature: string + requestId: string + data: Record + initiatedAt: Date } } @@ -221,11 +222,7 @@ export type CreateOutgoingPaymentOptions = export function isCreateFromCardPayment( options: CreateOutgoingPaymentOptions ): options is CreateFromCardPayment { - return ( - 'cardDetails' in options && - 'expiry' in options.cardDetails && - 'signature' in options.cardDetails - ) + return 'cardDetails' in options && 'requestId' in options.cardDetails } export function isCreateFromIncomingPayment( @@ -399,17 +396,15 @@ async function createOutgoingPayment( }) if (isCreateFromCardPayment(options)) { - const { expiry, signature } = options.cardDetails - - if (!isExpiryFormat(expiry)) - throw OutgoingPaymentError.InvalidCardExpiry + const { data, requestId, initiatedAt } = options.cardDetails payment.cardDetails = await OutgoingPaymentCardDetails.query( trx ).insertAndFetch({ outgoingPaymentId: payment.id, - expiry, - signature + requestId, + data, + initiatedAt }) } From 6a3e4212bf17e40f9d25908f77de60af3cb52b21 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Fri, 19 Sep 2025 13:59:00 +0200 Subject: [PATCH 03/11] feat(backend): start publishing cardDetails in outgoing_payment.created webhook --- .../src/open_payments/payment/outgoing/model.ts | 11 +++++++++++ packages/backend/src/openapi/specs/webhooks.yaml | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/packages/backend/src/open_payments/payment/outgoing/model.ts b/packages/backend/src/open_payments/payment/outgoing/model.ts index 6228cd4615..2191869cf2 100644 --- a/packages/backend/src/open_payments/payment/outgoing/model.ts +++ b/packages/backend/src/open_payments/payment/outgoing/model.ts @@ -209,6 +209,13 @@ export class OutgoingPayment if (this.grantId) { data.grantId = this.grantId } + if (this.cardDetails) { + data.cardDetails = { + requestId: this.cardDetails.requestId, + data: this.cardDetails.data, + initiatedAt: this.cardDetails.initiatedAt + } + } return data } @@ -296,6 +303,10 @@ export type PaymentData = Omit & { stateAttempts: number balance: string grantId?: string + cardDetails?: Pick< + OutgoingPaymentCardDetails, + 'requestId' | 'data' | 'initiatedAt' + > } export const isOutgoingPaymentEventType = ( diff --git a/packages/backend/src/openapi/specs/webhooks.yaml b/packages/backend/src/openapi/specs/webhooks.yaml index fd1f4a8034..d9e5236784 100644 --- a/packages/backend/src/openapi/specs/webhooks.yaml +++ b/packages/backend/src/openapi/specs/webhooks.yaml @@ -242,6 +242,16 @@ components: grantId: type: string format: uuid + cardDetails: + type: object + properties: + data: + type: object + requestId: + type: string + initiatedAt: + type: string + format: date-time additionalProperties: false walletAddressNotFound: required: From bd47c19c888f9135a34c9bd165fd2d1b988f26b2 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Fri, 19 Sep 2025 14:05:05 +0200 Subject: [PATCH 04/11] chore(backend): remove old expiry check --- .../backend/src/open_payments/payment/outgoing/service.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/backend/src/open_payments/payment/outgoing/service.ts b/packages/backend/src/open_payments/payment/outgoing/service.ts index d0ea0f3026..ae78bc9ca5 100644 --- a/packages/backend/src/open_payments/payment/outgoing/service.ts +++ b/packages/backend/src/open_payments/payment/outgoing/service.ts @@ -818,7 +818,3 @@ function validateSentAmount( ) throw new Error(errorMessage) } - -function isExpiryFormat(expiry: string): boolean { - return !!expiry.match(/^(0[1-9]|1[0-2])\/(\d{2})$/) -} From 812b734a899b7eaa60d56aa59be07e5a9749d3a1 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Mon, 22 Sep 2025 12:40:11 +0200 Subject: [PATCH 05/11] test(backend): update outgoing payment resolver test --- .../backend/src/graphql/resolvers/outgoing_payment.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts b/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts index 3f9009007e..77755adaf6 100644 --- a/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts +++ b/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts @@ -916,7 +916,12 @@ describe('OutgoingPayment Resolvers', (): void => { walletAddressId: payment.walletAddressId, quoteId: payment.quote.id, cardDetails: { - signature: 'test-signature' + data: { + signature: 'test-signature', + payload: 'payload' + }, + requestId: crypto.randomUUID(), + initiatedAt: new Date().toISOString() } } From 8d15c216676250a7b3bc7cd269389c4937b55271 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Tue, 23 Sep 2025 12:38:47 +0200 Subject: [PATCH 06/11] chore(backend): remove unused cardDetails from GraphQL API --- .../generated/graphql.ts | 30 +---- .../src/graphql/generated/graphql.schema.json | 127 ------------------ .../backend/src/graphql/generated/graphql.ts | 30 +---- .../src/graphql/resolvers/outgoing_payment.ts | 21 +-- packages/backend/src/graphql/schema.graphql | 12 -- .../src/graphql/generated/graphql.ts | 30 +---- packages/frontend/app/generated/graphql.ts | 30 +---- .../src/generated/graphql.ts | 30 +---- .../src/graphql/generated/graphql.ts | 30 +---- test/test-lib/src/generated/graphql.ts | 30 +---- 10 files changed, 16 insertions(+), 354 deletions(-) diff --git a/localenv/mock-account-servicing-entity/generated/graphql.ts b/localenv/mock-account-servicing-entity/generated/graphql.ts index ae53531638..47ec55a71e 100644 --- a/localenv/mock-account-servicing-entity/generated/graphql.ts +++ b/localenv/mock-account-servicing-entity/generated/graphql.ts @@ -288,8 +288,6 @@ export type CreateOutgoingPaymentFromIncomingPaymentInput = { }; export type CreateOutgoingPaymentInput = { - /** Used for the card service to provide the card signature */ - cardDetails?: InputMaybe; /** Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency). */ idempotencyKey?: InputMaybe; /** Additional metadata associated with the outgoing payment. */ @@ -1022,8 +1020,6 @@ export type MutationWithdrawEventLiquidityArgs = { export type OutgoingPayment = BasePayment & Model & { __typename?: 'OutgoingPayment'; - /** Used for the card service to provide the card expiry and signature */ - cardDetails?: Maybe; /** Information about the wallet address of the Open Payments client that created the outgoing payment. */ client?: Maybe; /** The date and time that the outgoing payment was created. */ @@ -1058,15 +1054,6 @@ export type OutgoingPayment = BasePayment & Model & { walletAddressId: Scalars['ID']['output']; }; -export type OutgoingPaymentCardDetails = Model & { - __typename?: 'OutgoingPaymentCardDetails'; - createdAt: Scalars['String']['output']; - id: Scalars['ID']['output']; - outgoingPaymentId: Scalars['ID']['output']; - signature: Scalars['String']['output']; - updatedAt: Scalars['String']['output']; -}; - export type OutgoingPaymentConnection = { __typename?: 'OutgoingPaymentConnection'; /** A list of outgoing payment edges, containing outgoing payment nodes and cursors for pagination. */ @@ -1934,7 +1921,7 @@ export type DirectiveResolverFn> = { BasePayment: ( Partial ) | ( Partial ) | ( Partial ); - Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); + Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); }; /** Mapping between all available schema types and the resolvers types */ @@ -2019,7 +2006,6 @@ export type ResolversTypes = { Model: ResolverTypeWrapper['Model']>; Mutation: ResolverTypeWrapper<{}>; OutgoingPayment: ResolverTypeWrapper>; - OutgoingPaymentCardDetails: ResolverTypeWrapper>; OutgoingPaymentConnection: ResolverTypeWrapper>; OutgoingPaymentEdge: ResolverTypeWrapper>; OutgoingPaymentFilter: ResolverTypeWrapper>; @@ -2161,7 +2147,6 @@ export type ResolversParentTypes = { Model: ResolversInterfaceTypes['Model']; Mutation: {}; OutgoingPayment: Partial; - OutgoingPaymentCardDetails: Partial; OutgoingPaymentConnection: Partial; OutgoingPaymentEdge: Partial; OutgoingPaymentFilter: Partial; @@ -2434,7 +2419,7 @@ export type LiquidityMutationResponseResolvers = { - __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'OutgoingPaymentCardDetails' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; + __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; createdAt?: Resolver; id?: Resolver; }; @@ -2481,7 +2466,6 @@ export type MutationResolvers = { - cardDetails?: Resolver, ParentType, ContextType>; client?: Resolver, ParentType, ContextType>; createdAt?: Resolver; debitAmount?: Resolver; @@ -2501,15 +2485,6 @@ export type OutgoingPaymentResolvers; }; -export type OutgoingPaymentCardDetailsResolvers = { - createdAt?: Resolver; - id?: Resolver; - outgoingPaymentId?: Resolver; - signature?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type OutgoingPaymentConnectionResolvers = { edges?: Resolver, ParentType, ContextType>; pageInfo?: Resolver; @@ -2844,7 +2819,6 @@ export type Resolvers = { Model?: ModelResolvers; Mutation?: MutationResolvers; OutgoingPayment?: OutgoingPaymentResolvers; - OutgoingPaymentCardDetails?: OutgoingPaymentCardDetailsResolvers; OutgoingPaymentConnection?: OutgoingPaymentConnectionResolvers; OutgoingPaymentEdge?: OutgoingPaymentEdgeResolvers; OutgoingPaymentResponse?: OutgoingPaymentResponseResolvers; diff --git a/packages/backend/src/graphql/generated/graphql.schema.json b/packages/backend/src/graphql/generated/graphql.schema.json index 339b386496..5d711093e5 100644 --- a/packages/backend/src/graphql/generated/graphql.schema.json +++ b/packages/backend/src/graphql/generated/graphql.schema.json @@ -1711,18 +1711,6 @@ "isOneOf": false, "fields": null, "inputFields": [ - { - "name": "cardDetails", - "description": "Used for the card service to provide the card signature", - "type": { - "kind": "INPUT_OBJECT", - "name": "CardDetailsInput", - "ofType": null - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "idempotencyKey", "description": "Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency).", @@ -4427,11 +4415,6 @@ "name": "OutgoingPayment", "ofType": null }, - { - "kind": "OBJECT", - "name": "OutgoingPaymentCardDetails", - "ofType": null - }, { "kind": "OBJECT", "name": "Payment", @@ -5676,18 +5659,6 @@ "description": null, "isOneOf": null, "fields": [ - { - "name": "cardDetails", - "description": "Used for the card service to provide the card expiry and signature", - "args": [], - "type": { - "kind": "OBJECT", - "name": "OutgoingPaymentCardDetails", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "client", "description": "Information about the wallet address of the Open Payments client that created the outgoing payment.", @@ -5933,104 +5904,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "OutgoingPaymentCardDetails", - "description": null, - "isOneOf": null, - "fields": [ - { - "name": "createdAt", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "outgoingPaymentId", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "signature", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "updatedAt", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - { - "kind": "INTERFACE", - "name": "Model", - "ofType": null - } - ], - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", "name": "OutgoingPaymentConnection", diff --git a/packages/backend/src/graphql/generated/graphql.ts b/packages/backend/src/graphql/generated/graphql.ts index ae53531638..47ec55a71e 100644 --- a/packages/backend/src/graphql/generated/graphql.ts +++ b/packages/backend/src/graphql/generated/graphql.ts @@ -288,8 +288,6 @@ export type CreateOutgoingPaymentFromIncomingPaymentInput = { }; export type CreateOutgoingPaymentInput = { - /** Used for the card service to provide the card signature */ - cardDetails?: InputMaybe; /** Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency). */ idempotencyKey?: InputMaybe; /** Additional metadata associated with the outgoing payment. */ @@ -1022,8 +1020,6 @@ export type MutationWithdrawEventLiquidityArgs = { export type OutgoingPayment = BasePayment & Model & { __typename?: 'OutgoingPayment'; - /** Used for the card service to provide the card expiry and signature */ - cardDetails?: Maybe; /** Information about the wallet address of the Open Payments client that created the outgoing payment. */ client?: Maybe; /** The date and time that the outgoing payment was created. */ @@ -1058,15 +1054,6 @@ export type OutgoingPayment = BasePayment & Model & { walletAddressId: Scalars['ID']['output']; }; -export type OutgoingPaymentCardDetails = Model & { - __typename?: 'OutgoingPaymentCardDetails'; - createdAt: Scalars['String']['output']; - id: Scalars['ID']['output']; - outgoingPaymentId: Scalars['ID']['output']; - signature: Scalars['String']['output']; - updatedAt: Scalars['String']['output']; -}; - export type OutgoingPaymentConnection = { __typename?: 'OutgoingPaymentConnection'; /** A list of outgoing payment edges, containing outgoing payment nodes and cursors for pagination. */ @@ -1934,7 +1921,7 @@ export type DirectiveResolverFn> = { BasePayment: ( Partial ) | ( Partial ) | ( Partial ); - Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); + Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); }; /** Mapping between all available schema types and the resolvers types */ @@ -2019,7 +2006,6 @@ export type ResolversTypes = { Model: ResolverTypeWrapper['Model']>; Mutation: ResolverTypeWrapper<{}>; OutgoingPayment: ResolverTypeWrapper>; - OutgoingPaymentCardDetails: ResolverTypeWrapper>; OutgoingPaymentConnection: ResolverTypeWrapper>; OutgoingPaymentEdge: ResolverTypeWrapper>; OutgoingPaymentFilter: ResolverTypeWrapper>; @@ -2161,7 +2147,6 @@ export type ResolversParentTypes = { Model: ResolversInterfaceTypes['Model']; Mutation: {}; OutgoingPayment: Partial; - OutgoingPaymentCardDetails: Partial; OutgoingPaymentConnection: Partial; OutgoingPaymentEdge: Partial; OutgoingPaymentFilter: Partial; @@ -2434,7 +2419,7 @@ export type LiquidityMutationResponseResolvers = { - __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'OutgoingPaymentCardDetails' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; + __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; createdAt?: Resolver; id?: Resolver; }; @@ -2481,7 +2466,6 @@ export type MutationResolvers = { - cardDetails?: Resolver, ParentType, ContextType>; client?: Resolver, ParentType, ContextType>; createdAt?: Resolver; debitAmount?: Resolver; @@ -2501,15 +2485,6 @@ export type OutgoingPaymentResolvers; }; -export type OutgoingPaymentCardDetailsResolvers = { - createdAt?: Resolver; - id?: Resolver; - outgoingPaymentId?: Resolver; - signature?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type OutgoingPaymentConnectionResolvers = { edges?: Resolver, ParentType, ContextType>; pageInfo?: Resolver; @@ -2844,7 +2819,6 @@ export type Resolvers = { Model?: ModelResolvers; Mutation?: MutationResolvers; OutgoingPayment?: OutgoingPaymentResolvers; - OutgoingPaymentCardDetails?: OutgoingPaymentCardDetailsResolvers; OutgoingPaymentConnection?: OutgoingPaymentConnectionResolvers; OutgoingPaymentEdge?: OutgoingPaymentEdgeResolvers; OutgoingPaymentResponse?: OutgoingPaymentResponseResolvers; diff --git a/packages/backend/src/graphql/resolvers/outgoing_payment.ts b/packages/backend/src/graphql/resolvers/outgoing_payment.ts index ed052a4266..7eb85b86ee 100644 --- a/packages/backend/src/graphql/resolvers/outgoing_payment.ts +++ b/packages/backend/src/graphql/resolvers/outgoing_payment.ts @@ -4,8 +4,7 @@ import { OutgoingPayment as SchemaOutgoingPayment, WalletAddressResolvers, QueryResolvers, - ResolversTypes, - OutgoingPaymentCardDetails as SchemaOutgoingPaymentCardDetails + ResolversTypes } from '../generated/graphql' import { isOutgoingPaymentError, @@ -18,7 +17,6 @@ import { getPageInfo } from '../../shared/pagination' import { Pagination, SortOrder } from '../../shared/baseModel' import { GraphQLError } from 'graphql' import { GraphQLErrorCode } from '../errors' -import { OutgoingPaymentCardDetails } from '../../open_payments/payment/outgoing/card/model' export const getOutgoingPayment: QueryResolvers['outgoingPayment'] = async (parent, args, ctx): Promise => { @@ -250,21 +248,6 @@ export function paymentToGraphql( createdAt: new Date(+payment.createdAt).toISOString(), quote: quoteToGraphql(payment.quote), grantId: payment.grantId, - tenantId: payment.tenantId, - cardDetails: payment.cardDetails - ? cardDetailsToGraphql(payment.cardDetails) - : undefined - } -} -function cardDetailsToGraphql( - cardDetails: OutgoingPaymentCardDetails -): SchemaOutgoingPaymentCardDetails | undefined { - if (!cardDetails) return undefined - return { - id: cardDetails.id, - outgoingPaymentId: cardDetails.outgoingPaymentId, - signature: cardDetails.signature, - createdAt: new Date(+cardDetails.createdAt).toISOString(), - updatedAt: new Date(+cardDetails.updatedAt).toISOString() + tenantId: payment.tenantId } } diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index cfaa301bc9..fa0cf0abae 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -1056,16 +1056,6 @@ type OutgoingPayment implements BasePayment & Model { grantId: String "Tenant ID of the outgoing payment." tenantId: String - "Used for the card service to provide the card expiry and signature" - cardDetails: OutgoingPaymentCardDetails -} - -type OutgoingPaymentCardDetails implements Model { - id: ID! - outgoingPaymentId: ID! - signature: String! - createdAt: String! - updatedAt: String! } enum OutgoingPaymentState { @@ -1243,8 +1233,6 @@ input CreateOutgoingPaymentInput { metadata: JSONObject "Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency)." idempotencyKey: String - "Used for the card service to provide the card signature" - cardDetails: CardDetailsInput } input CardDetailsInput { diff --git a/packages/card-service/src/graphql/generated/graphql.ts b/packages/card-service/src/graphql/generated/graphql.ts index 834a16bf39..5573066035 100644 --- a/packages/card-service/src/graphql/generated/graphql.ts +++ b/packages/card-service/src/graphql/generated/graphql.ts @@ -288,8 +288,6 @@ export type CreateOutgoingPaymentFromIncomingPaymentInput = { }; export type CreateOutgoingPaymentInput = { - /** Used for the card service to provide the card signature */ - cardDetails?: InputMaybe; /** Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency). */ idempotencyKey?: InputMaybe; /** Additional metadata associated with the outgoing payment. */ @@ -1022,8 +1020,6 @@ export type MutationWithdrawEventLiquidityArgs = { export type OutgoingPayment = BasePayment & Model & { __typename?: 'OutgoingPayment'; - /** Used for the card service to provide the card expiry and signature */ - cardDetails?: Maybe; /** Information about the wallet address of the Open Payments client that created the outgoing payment. */ client?: Maybe; /** The date and time that the outgoing payment was created. */ @@ -1058,15 +1054,6 @@ export type OutgoingPayment = BasePayment & Model & { walletAddressId: Scalars['ID']['output']; }; -export type OutgoingPaymentCardDetails = Model & { - __typename?: 'OutgoingPaymentCardDetails'; - createdAt: Scalars['String']['output']; - id: Scalars['ID']['output']; - outgoingPaymentId: Scalars['ID']['output']; - signature: Scalars['String']['output']; - updatedAt: Scalars['String']['output']; -}; - export type OutgoingPaymentConnection = { __typename?: 'OutgoingPaymentConnection'; /** A list of outgoing payment edges, containing outgoing payment nodes and cursors for pagination. */ @@ -1934,7 +1921,7 @@ export type DirectiveResolverFn> = { BasePayment: ( Partial ) | ( Partial ) | ( Partial ); - Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); + Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); }; /** Mapping between all available schema types and the resolvers types */ @@ -2019,7 +2006,6 @@ export type ResolversTypes = { Model: ResolverTypeWrapper['Model']>; Mutation: ResolverTypeWrapper<{}>; OutgoingPayment: ResolverTypeWrapper>; - OutgoingPaymentCardDetails: ResolverTypeWrapper>; OutgoingPaymentConnection: ResolverTypeWrapper>; OutgoingPaymentEdge: ResolverTypeWrapper>; OutgoingPaymentFilter: ResolverTypeWrapper>; @@ -2161,7 +2147,6 @@ export type ResolversParentTypes = { Model: ResolversInterfaceTypes['Model']; Mutation: {}; OutgoingPayment: Partial; - OutgoingPaymentCardDetails: Partial; OutgoingPaymentConnection: Partial; OutgoingPaymentEdge: Partial; OutgoingPaymentFilter: Partial; @@ -2434,7 +2419,7 @@ export type LiquidityMutationResponseResolvers = { - __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'OutgoingPaymentCardDetails' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; + __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; createdAt?: Resolver; id?: Resolver; }; @@ -2481,7 +2466,6 @@ export type MutationResolvers = { - cardDetails?: Resolver, ParentType, ContextType>; client?: Resolver, ParentType, ContextType>; createdAt?: Resolver; debitAmount?: Resolver; @@ -2501,15 +2485,6 @@ export type OutgoingPaymentResolvers; }; -export type OutgoingPaymentCardDetailsResolvers = { - createdAt?: Resolver; - id?: Resolver; - outgoingPaymentId?: Resolver; - signature?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type OutgoingPaymentConnectionResolvers = { edges?: Resolver, ParentType, ContextType>; pageInfo?: Resolver; @@ -2844,7 +2819,6 @@ export type Resolvers = { Model?: ModelResolvers; Mutation?: MutationResolvers; OutgoingPayment?: OutgoingPaymentResolvers; - OutgoingPaymentCardDetails?: OutgoingPaymentCardDetailsResolvers; OutgoingPaymentConnection?: OutgoingPaymentConnectionResolvers; OutgoingPaymentEdge?: OutgoingPaymentEdgeResolvers; OutgoingPaymentResponse?: OutgoingPaymentResponseResolvers; diff --git a/packages/frontend/app/generated/graphql.ts b/packages/frontend/app/generated/graphql.ts index 5cb0ece1bc..2f5fc9ea2d 100644 --- a/packages/frontend/app/generated/graphql.ts +++ b/packages/frontend/app/generated/graphql.ts @@ -288,8 +288,6 @@ export type CreateOutgoingPaymentFromIncomingPaymentInput = { }; export type CreateOutgoingPaymentInput = { - /** Used for the card service to provide the card signature */ - cardDetails?: InputMaybe; /** Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency). */ idempotencyKey?: InputMaybe; /** Additional metadata associated with the outgoing payment. */ @@ -1022,8 +1020,6 @@ export type MutationWithdrawEventLiquidityArgs = { export type OutgoingPayment = BasePayment & Model & { __typename?: 'OutgoingPayment'; - /** Used for the card service to provide the card expiry and signature */ - cardDetails?: Maybe; /** Information about the wallet address of the Open Payments client that created the outgoing payment. */ client?: Maybe; /** The date and time that the outgoing payment was created. */ @@ -1058,15 +1054,6 @@ export type OutgoingPayment = BasePayment & Model & { walletAddressId: Scalars['ID']['output']; }; -export type OutgoingPaymentCardDetails = Model & { - __typename?: 'OutgoingPaymentCardDetails'; - createdAt: Scalars['String']['output']; - id: Scalars['ID']['output']; - outgoingPaymentId: Scalars['ID']['output']; - signature: Scalars['String']['output']; - updatedAt: Scalars['String']['output']; -}; - export type OutgoingPaymentConnection = { __typename?: 'OutgoingPaymentConnection'; /** A list of outgoing payment edges, containing outgoing payment nodes and cursors for pagination. */ @@ -1934,7 +1921,7 @@ export type DirectiveResolverFn> = { BasePayment: ( Partial ) | ( Partial ) | ( Partial ); - Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); + Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); }; /** Mapping between all available schema types and the resolvers types */ @@ -2019,7 +2006,6 @@ export type ResolversTypes = { Model: ResolverTypeWrapper['Model']>; Mutation: ResolverTypeWrapper<{}>; OutgoingPayment: ResolverTypeWrapper>; - OutgoingPaymentCardDetails: ResolverTypeWrapper>; OutgoingPaymentConnection: ResolverTypeWrapper>; OutgoingPaymentEdge: ResolverTypeWrapper>; OutgoingPaymentFilter: ResolverTypeWrapper>; @@ -2161,7 +2147,6 @@ export type ResolversParentTypes = { Model: ResolversInterfaceTypes['Model']; Mutation: {}; OutgoingPayment: Partial; - OutgoingPaymentCardDetails: Partial; OutgoingPaymentConnection: Partial; OutgoingPaymentEdge: Partial; OutgoingPaymentFilter: Partial; @@ -2434,7 +2419,7 @@ export type LiquidityMutationResponseResolvers = { - __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'OutgoingPaymentCardDetails' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; + __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; createdAt?: Resolver; id?: Resolver; }; @@ -2481,7 +2466,6 @@ export type MutationResolvers = { - cardDetails?: Resolver, ParentType, ContextType>; client?: Resolver, ParentType, ContextType>; createdAt?: Resolver; debitAmount?: Resolver; @@ -2501,15 +2485,6 @@ export type OutgoingPaymentResolvers; }; -export type OutgoingPaymentCardDetailsResolvers = { - createdAt?: Resolver; - id?: Resolver; - outgoingPaymentId?: Resolver; - signature?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type OutgoingPaymentConnectionResolvers = { edges?: Resolver, ParentType, ContextType>; pageInfo?: Resolver; @@ -2844,7 +2819,6 @@ export type Resolvers = { Model?: ModelResolvers; Mutation?: MutationResolvers; OutgoingPayment?: OutgoingPaymentResolvers; - OutgoingPaymentCardDetails?: OutgoingPaymentCardDetailsResolvers; OutgoingPaymentConnection?: OutgoingPaymentConnectionResolvers; OutgoingPaymentEdge?: OutgoingPaymentEdgeResolvers; OutgoingPaymentResponse?: OutgoingPaymentResponseResolvers; diff --git a/packages/mock-account-service-lib/src/generated/graphql.ts b/packages/mock-account-service-lib/src/generated/graphql.ts index ae53531638..47ec55a71e 100644 --- a/packages/mock-account-service-lib/src/generated/graphql.ts +++ b/packages/mock-account-service-lib/src/generated/graphql.ts @@ -288,8 +288,6 @@ export type CreateOutgoingPaymentFromIncomingPaymentInput = { }; export type CreateOutgoingPaymentInput = { - /** Used for the card service to provide the card signature */ - cardDetails?: InputMaybe; /** Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency). */ idempotencyKey?: InputMaybe; /** Additional metadata associated with the outgoing payment. */ @@ -1022,8 +1020,6 @@ export type MutationWithdrawEventLiquidityArgs = { export type OutgoingPayment = BasePayment & Model & { __typename?: 'OutgoingPayment'; - /** Used for the card service to provide the card expiry and signature */ - cardDetails?: Maybe; /** Information about the wallet address of the Open Payments client that created the outgoing payment. */ client?: Maybe; /** The date and time that the outgoing payment was created. */ @@ -1058,15 +1054,6 @@ export type OutgoingPayment = BasePayment & Model & { walletAddressId: Scalars['ID']['output']; }; -export type OutgoingPaymentCardDetails = Model & { - __typename?: 'OutgoingPaymentCardDetails'; - createdAt: Scalars['String']['output']; - id: Scalars['ID']['output']; - outgoingPaymentId: Scalars['ID']['output']; - signature: Scalars['String']['output']; - updatedAt: Scalars['String']['output']; -}; - export type OutgoingPaymentConnection = { __typename?: 'OutgoingPaymentConnection'; /** A list of outgoing payment edges, containing outgoing payment nodes and cursors for pagination. */ @@ -1934,7 +1921,7 @@ export type DirectiveResolverFn> = { BasePayment: ( Partial ) | ( Partial ) | ( Partial ); - Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); + Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); }; /** Mapping between all available schema types and the resolvers types */ @@ -2019,7 +2006,6 @@ export type ResolversTypes = { Model: ResolverTypeWrapper['Model']>; Mutation: ResolverTypeWrapper<{}>; OutgoingPayment: ResolverTypeWrapper>; - OutgoingPaymentCardDetails: ResolverTypeWrapper>; OutgoingPaymentConnection: ResolverTypeWrapper>; OutgoingPaymentEdge: ResolverTypeWrapper>; OutgoingPaymentFilter: ResolverTypeWrapper>; @@ -2161,7 +2147,6 @@ export type ResolversParentTypes = { Model: ResolversInterfaceTypes['Model']; Mutation: {}; OutgoingPayment: Partial; - OutgoingPaymentCardDetails: Partial; OutgoingPaymentConnection: Partial; OutgoingPaymentEdge: Partial; OutgoingPaymentFilter: Partial; @@ -2434,7 +2419,7 @@ export type LiquidityMutationResponseResolvers = { - __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'OutgoingPaymentCardDetails' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; + __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; createdAt?: Resolver; id?: Resolver; }; @@ -2481,7 +2466,6 @@ export type MutationResolvers = { - cardDetails?: Resolver, ParentType, ContextType>; client?: Resolver, ParentType, ContextType>; createdAt?: Resolver; debitAmount?: Resolver; @@ -2501,15 +2485,6 @@ export type OutgoingPaymentResolvers; }; -export type OutgoingPaymentCardDetailsResolvers = { - createdAt?: Resolver; - id?: Resolver; - outgoingPaymentId?: Resolver; - signature?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type OutgoingPaymentConnectionResolvers = { edges?: Resolver, ParentType, ContextType>; pageInfo?: Resolver; @@ -2844,7 +2819,6 @@ export type Resolvers = { Model?: ModelResolvers; Mutation?: MutationResolvers; OutgoingPayment?: OutgoingPaymentResolvers; - OutgoingPaymentCardDetails?: OutgoingPaymentCardDetailsResolvers; OutgoingPaymentConnection?: OutgoingPaymentConnectionResolvers; OutgoingPaymentEdge?: OutgoingPaymentEdgeResolvers; OutgoingPaymentResponse?: OutgoingPaymentResponseResolvers; diff --git a/packages/point-of-sale/src/graphql/generated/graphql.ts b/packages/point-of-sale/src/graphql/generated/graphql.ts index 331d472897..91045bf26d 100644 --- a/packages/point-of-sale/src/graphql/generated/graphql.ts +++ b/packages/point-of-sale/src/graphql/generated/graphql.ts @@ -288,8 +288,6 @@ export type CreateOutgoingPaymentFromIncomingPaymentInput = { }; export type CreateOutgoingPaymentInput = { - /** Used for the card service to provide the card signature */ - cardDetails?: InputMaybe; /** Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency). */ idempotencyKey?: InputMaybe; /** Additional metadata associated with the outgoing payment. */ @@ -1022,8 +1020,6 @@ export type MutationWithdrawEventLiquidityArgs = { export type OutgoingPayment = BasePayment & Model & { __typename?: 'OutgoingPayment'; - /** Used for the card service to provide the card expiry and signature */ - cardDetails?: Maybe; /** Information about the wallet address of the Open Payments client that created the outgoing payment. */ client?: Maybe; /** The date and time that the outgoing payment was created. */ @@ -1058,15 +1054,6 @@ export type OutgoingPayment = BasePayment & Model & { walletAddressId: Scalars['ID']['output']; }; -export type OutgoingPaymentCardDetails = Model & { - __typename?: 'OutgoingPaymentCardDetails'; - createdAt: Scalars['String']['output']; - id: Scalars['ID']['output']; - outgoingPaymentId: Scalars['ID']['output']; - signature: Scalars['String']['output']; - updatedAt: Scalars['String']['output']; -}; - export type OutgoingPaymentConnection = { __typename?: 'OutgoingPaymentConnection'; /** A list of outgoing payment edges, containing outgoing payment nodes and cursors for pagination. */ @@ -1934,7 +1921,7 @@ export type DirectiveResolverFn> = { BasePayment: ( Partial ) | ( Partial ) | ( Partial ); - Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); + Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); }; /** Mapping between all available schema types and the resolvers types */ @@ -2019,7 +2006,6 @@ export type ResolversTypes = { Model: ResolverTypeWrapper['Model']>; Mutation: ResolverTypeWrapper<{}>; OutgoingPayment: ResolverTypeWrapper>; - OutgoingPaymentCardDetails: ResolverTypeWrapper>; OutgoingPaymentConnection: ResolverTypeWrapper>; OutgoingPaymentEdge: ResolverTypeWrapper>; OutgoingPaymentFilter: ResolverTypeWrapper>; @@ -2161,7 +2147,6 @@ export type ResolversParentTypes = { Model: ResolversInterfaceTypes['Model']; Mutation: {}; OutgoingPayment: Partial; - OutgoingPaymentCardDetails: Partial; OutgoingPaymentConnection: Partial; OutgoingPaymentEdge: Partial; OutgoingPaymentFilter: Partial; @@ -2434,7 +2419,7 @@ export type LiquidityMutationResponseResolvers = { - __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'OutgoingPaymentCardDetails' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; + __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; createdAt?: Resolver; id?: Resolver; }; @@ -2481,7 +2466,6 @@ export type MutationResolvers = { - cardDetails?: Resolver, ParentType, ContextType>; client?: Resolver, ParentType, ContextType>; createdAt?: Resolver; debitAmount?: Resolver; @@ -2501,15 +2485,6 @@ export type OutgoingPaymentResolvers; }; -export type OutgoingPaymentCardDetailsResolvers = { - createdAt?: Resolver; - id?: Resolver; - outgoingPaymentId?: Resolver; - signature?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type OutgoingPaymentConnectionResolvers = { edges?: Resolver, ParentType, ContextType>; pageInfo?: Resolver; @@ -2844,7 +2819,6 @@ export type Resolvers = { Model?: ModelResolvers; Mutation?: MutationResolvers; OutgoingPayment?: OutgoingPaymentResolvers; - OutgoingPaymentCardDetails?: OutgoingPaymentCardDetailsResolvers; OutgoingPaymentConnection?: OutgoingPaymentConnectionResolvers; OutgoingPaymentEdge?: OutgoingPaymentEdgeResolvers; OutgoingPaymentResponse?: OutgoingPaymentResponseResolvers; diff --git a/test/test-lib/src/generated/graphql.ts b/test/test-lib/src/generated/graphql.ts index ae53531638..47ec55a71e 100644 --- a/test/test-lib/src/generated/graphql.ts +++ b/test/test-lib/src/generated/graphql.ts @@ -288,8 +288,6 @@ export type CreateOutgoingPaymentFromIncomingPaymentInput = { }; export type CreateOutgoingPaymentInput = { - /** Used for the card service to provide the card signature */ - cardDetails?: InputMaybe; /** Unique key to ensure duplicate or retried requests are processed only once. For more information, refer to [idempotency](https://rafiki.dev/apis/graphql/admin-api-overview/#idempotency). */ idempotencyKey?: InputMaybe; /** Additional metadata associated with the outgoing payment. */ @@ -1022,8 +1020,6 @@ export type MutationWithdrawEventLiquidityArgs = { export type OutgoingPayment = BasePayment & Model & { __typename?: 'OutgoingPayment'; - /** Used for the card service to provide the card expiry and signature */ - cardDetails?: Maybe; /** Information about the wallet address of the Open Payments client that created the outgoing payment. */ client?: Maybe; /** The date and time that the outgoing payment was created. */ @@ -1058,15 +1054,6 @@ export type OutgoingPayment = BasePayment & Model & { walletAddressId: Scalars['ID']['output']; }; -export type OutgoingPaymentCardDetails = Model & { - __typename?: 'OutgoingPaymentCardDetails'; - createdAt: Scalars['String']['output']; - id: Scalars['ID']['output']; - outgoingPaymentId: Scalars['ID']['output']; - signature: Scalars['String']['output']; - updatedAt: Scalars['String']['output']; -}; - export type OutgoingPaymentConnection = { __typename?: 'OutgoingPaymentConnection'; /** A list of outgoing payment edges, containing outgoing payment nodes and cursors for pagination. */ @@ -1934,7 +1921,7 @@ export type DirectiveResolverFn> = { BasePayment: ( Partial ) | ( Partial ) | ( Partial ); - Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); + Model: ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ) | ( Partial ); }; /** Mapping between all available schema types and the resolvers types */ @@ -2019,7 +2006,6 @@ export type ResolversTypes = { Model: ResolverTypeWrapper['Model']>; Mutation: ResolverTypeWrapper<{}>; OutgoingPayment: ResolverTypeWrapper>; - OutgoingPaymentCardDetails: ResolverTypeWrapper>; OutgoingPaymentConnection: ResolverTypeWrapper>; OutgoingPaymentEdge: ResolverTypeWrapper>; OutgoingPaymentFilter: ResolverTypeWrapper>; @@ -2161,7 +2147,6 @@ export type ResolversParentTypes = { Model: ResolversInterfaceTypes['Model']; Mutation: {}; OutgoingPayment: Partial; - OutgoingPaymentCardDetails: Partial; OutgoingPaymentConnection: Partial; OutgoingPaymentEdge: Partial; OutgoingPaymentFilter: Partial; @@ -2434,7 +2419,7 @@ export type LiquidityMutationResponseResolvers = { - __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'OutgoingPaymentCardDetails' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; + __resolveType: TypeResolveFn<'AccountingTransfer' | 'Asset' | 'Fee' | 'IncomingPayment' | 'OutgoingPayment' | 'Payment' | 'Peer' | 'Tenant' | 'WalletAddress' | 'WalletAddressKey' | 'WebhookEvent', ParentType, ContextType>; createdAt?: Resolver; id?: Resolver; }; @@ -2481,7 +2466,6 @@ export type MutationResolvers = { - cardDetails?: Resolver, ParentType, ContextType>; client?: Resolver, ParentType, ContextType>; createdAt?: Resolver; debitAmount?: Resolver; @@ -2501,15 +2485,6 @@ export type OutgoingPaymentResolvers; }; -export type OutgoingPaymentCardDetailsResolvers = { - createdAt?: Resolver; - id?: Resolver; - outgoingPaymentId?: Resolver; - signature?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type OutgoingPaymentConnectionResolvers = { edges?: Resolver, ParentType, ContextType>; pageInfo?: Resolver; @@ -2844,7 +2819,6 @@ export type Resolvers = { Model?: ModelResolvers; Mutation?: MutationResolvers; OutgoingPayment?: OutgoingPaymentResolvers; - OutgoingPaymentCardDetails?: OutgoingPaymentCardDetailsResolvers; OutgoingPaymentConnection?: OutgoingPaymentConnectionResolvers; OutgoingPaymentEdge?: OutgoingPaymentEdgeResolvers; OutgoingPaymentResponse?: OutgoingPaymentResponseResolvers; From f8cf3382859fb5decba8c90c560e423cde7c96c0 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Tue, 23 Sep 2025 13:19:30 +0200 Subject: [PATCH 07/11] test(backend): update outgoing payment resolver test --- .../resolvers/outgoing_payment.test.ts | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts b/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts index 77755adaf6..036d248012 100644 --- a/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts +++ b/packages/backend/src/graphql/resolvers/outgoing_payment.test.ts @@ -897,15 +897,24 @@ describe('OutgoingPayment Resolvers', (): void => { } expect(createSpy).toHaveBeenCalledWith({ ...input, tenantId }) }) + }) - test('works with card details', async (): Promise => { - const { id: walletAddressId } = await createWalletAddress(deps, { + describe('Mutation.createOutgoingPaymentFromIncomingPayment', (): void => { + let tenantId: string + const mockIncomingPaymentUrl = `https://${faker.internet.domainName()}/incoming-payments/${uuid()}` + + beforeEach(async (): Promise => { + tenantId = Config.operatorTenantId + }) + + test('create', async (): Promise => { + const walletAddress = await createWalletAddress(deps, { tenantId, assetId: asset.id }) const payment = await createPayment({ tenantId, - walletAddressId + walletAddressId: walletAddress.id }) const createSpy = jest @@ -914,24 +923,21 @@ describe('OutgoingPayment Resolvers', (): void => { const input = { walletAddressId: payment.walletAddressId, - quoteId: payment.quote.id, - cardDetails: { - data: { - signature: 'test-signature', - payload: 'payload' - }, - requestId: crypto.randomUUID(), - initiatedAt: new Date().toISOString() + incomingPayment: mockIncomingPaymentUrl, + debitAmount: { + value: BigInt(56), + assetCode: asset.code, + assetScale: asset.scale } } - const query = await appContainer.apolloClient - .query({ - query: gql` - mutation CreateOutgoingPayment( - $input: CreateOutgoingPaymentInput! + const mutation = await appContainer.apolloClient + .mutate({ + mutation: gql` + mutation CreateOutgoingPaymentFromIncomingPayment( + $input: CreateOutgoingPaymentFromIncomingPaymentInput! ) { - createOutgoingPayment(input: $input) { + createOutgoingPaymentFromIncomingPayment(input: $input) { payment { id state @@ -942,21 +948,12 @@ describe('OutgoingPayment Resolvers', (): void => { variables: { input } }) .then( - (query): OutgoingPaymentResponse => query.data?.createOutgoingPayment + (response) => response.data?.createOutgoingPaymentFromIncomingPayment ) expect(createSpy).toHaveBeenCalledWith({ ...input, tenantId }) - expect(query.payment?.id).toBe(payment.id) - expect(query.payment?.state).toBe(SchemaPaymentState.Funding) - }) - }) - - describe('Mutation.createOutgoingPaymentFromIncomingPayment', (): void => { - let tenantId: string - const mockIncomingPaymentUrl = `https://${faker.internet.domainName()}/incoming-payments/${uuid()}` - - beforeEach(async (): Promise => { - tenantId = Config.operatorTenantId + expect(mutation.payment?.id).toBe(payment.id) + expect(mutation.payment?.state).toBe(SchemaPaymentState.Funding) }) test('create', async (): Promise => { @@ -980,12 +977,20 @@ describe('OutgoingPayment Resolvers', (): void => { value: BigInt(56), assetCode: asset.code, assetScale: asset.scale + }, + cardDetails: { + data: { + signature: 'test-signature', + payload: 'payload' + }, + requestId: crypto.randomUUID(), + initiatedAt: new Date().toISOString() } } - const query = await appContainer.apolloClient - .query({ - query: gql` + const mutation = await appContainer.apolloClient + .mutate({ + mutation: gql` mutation CreateOutgoingPaymentFromIncomingPayment( $input: CreateOutgoingPaymentFromIncomingPaymentInput! ) { @@ -1000,13 +1005,12 @@ describe('OutgoingPayment Resolvers', (): void => { variables: { input } }) .then( - (query): OutgoingPaymentResponse => - query.data?.createOutgoingPaymentFromIncomingPayment + (response) => response.data?.createOutgoingPaymentFromIncomingPayment ) expect(createSpy).toHaveBeenCalledWith({ ...input, tenantId }) - expect(query.payment?.id).toBe(payment.id) - expect(query.payment?.state).toBe(SchemaPaymentState.Funding) + expect(mutation.payment?.id).toBe(payment.id) + expect(mutation.payment?.state).toBe(SchemaPaymentState.Funding) }) test('unknown wallet address', async (): Promise => { From ff1028439b0eaca12b943f5693adf5d8cd871598 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Tue, 23 Sep 2025 17:12:06 +0200 Subject: [PATCH 08/11] chore(backend): update migration to not add already included requestId --- .../20250919105030_update_outgoing_payment_card_details_data.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js b/packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js index 98c3851f02..3260bd2a5a 100644 --- a/packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js +++ b/packages/backend/migrations/20250919105030_update_outgoing_payment_card_details_data.js @@ -7,7 +7,6 @@ exports.up = function (knex) { table.dropColumn('expiry') table.dropColumn('signature') - table.uuid('requestId').notNullable() table.jsonb('data').notNullable() table.timestamp('initiatedAt').notNullable() }) @@ -19,7 +18,6 @@ exports.up = function (knex) { */ exports.down = function (knex) { return knex.schema.alterTable('outgoingPaymentCardDetails', function (table) { - table.dropColumn('requestId') table.dropColumn('data') table.dropColumn('initiatedAt') From 9abb1f7dcef90ae0eeebd2252c8efdba57e6305c Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Tue, 23 Sep 2025 18:12:36 +0200 Subject: [PATCH 09/11] chore(backend): update outgoing payment test --- .../payment/outgoing/service.test.ts | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/packages/backend/src/open_payments/payment/outgoing/service.test.ts b/packages/backend/src/open_payments/payment/outgoing/service.test.ts index 5a94c38eeb..40906d7983 100644 --- a/packages/backend/src/open_payments/payment/outgoing/service.test.ts +++ b/packages/backend/src/open_payments/payment/outgoing/service.test.ts @@ -1536,44 +1536,7 @@ describe('OutgoingPaymentService', (): void => { }) expect(cardDetails).toHaveLength(1) - }) - - test('persists requestId in cardDetails and includes in webhook data', async () => { - const paymentMethods: OpenPaymentsPaymentMethod[] = [ - { - type: 'ilp', - ilpAddress: 'test.ilp' as IlpAddress, - sharedSecret: '' - } - ] - const debitAmount = { - value: BigInt(123), - assetCode: receiverWalletAddress.asset.code, - assetScale: receiverWalletAddress.asset.scale - } - const requestId = 'req-123' - const options: CreateFromCardPayment = { - walletAddressId: receiverWalletAddress.id, - debitAmount, - incomingPayment: incomingPayment.toOpenPaymentsTypeWithMethods( - config.openPaymentsUrl, - receiverWalletAddress, - paymentMethods - ).id, - tenantId, - cardDetails: { - expiry: '12/30', - signature: 'sig', - requestId - } - } - const created = await outgoingPaymentService.create(options) - assert.ok(!isOutgoingPaymentError(created)) - const fetched = await OutgoingPayment.query(knex) - .findById(created.id) - .withGraphFetched('cardDetails') - assert.ok(fetched?.cardDetails) - expect(fetched.cardDetails.requestId).toBe(requestId) + expect(cardDetails[0].requestId).toBe(options.cardDetails.requestId) }) }) From c9c185e38c90780c790a71ea790eb5cc007d4df9 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Tue, 23 Sep 2025 18:16:43 +0200 Subject: [PATCH 10/11] feat(card-service): update outgoing payment creation with new payload --- packages/card-service/src/payment/service.test.ts | 7 ++++++- packages/card-service/src/payment/service.ts | 12 ++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/card-service/src/payment/service.test.ts b/packages/card-service/src/payment/service.test.ts index 7736ded5ab..b659f2f6e0 100644 --- a/packages/card-service/src/payment/service.test.ts +++ b/packages/card-service/src/payment/service.test.ts @@ -109,7 +109,12 @@ describe('PaymentService', () => { walletAddressId: expect.any(String), incomingPayment: paymentFixture.incomingPaymentUrl, cardDetails: { - signature: paymentFixture.signature + requestId: paymentFixture.requestId, + initiatedAt: new Date(paymentFixture.timestamp).toISOString(), + data: { + signature: paymentFixture.signature, + payload: paymentFixture.payload + } } } } diff --git a/packages/card-service/src/payment/service.ts b/packages/card-service/src/payment/service.ts index b6267d231c..f514b7ac97 100644 --- a/packages/card-service/src/payment/service.ts +++ b/packages/card-service/src/payment/service.ts @@ -79,13 +79,21 @@ async function handleCreatePayment( walletAddressId, incomingPayment: payment.incomingPaymentUrl, cardDetails: { - signature: payment.signature + requestId: payment.requestId, + initiatedAt: new Date(payment.timestamp).toISOString(), + data: { + signature: payment.signature, + payload: payment.payload + } } } } }) - if (!outgoingPaymentFromIncomingPayment?.data) + if ( + !outgoingPaymentFromIncomingPayment?.data + ?.createOutgoingPaymentFromIncomingPayment.payment + ) throw new PaymentCreationFailedError() const result = await waitForPaymentEvent(deps.config, deferred) From 38ba95d14fe1f00c687f014b50259001e9a95476 Mon Sep 17 00:00:00 2001 From: Max Kurapov Date: Tue, 23 Sep 2025 18:31:30 +0200 Subject: [PATCH 11/11] test(backend): update outgoing payment test --- .../payment/outgoing/service.test.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/open_payments/payment/outgoing/service.test.ts b/packages/backend/src/open_payments/payment/outgoing/service.test.ts index 40906d7983..9442db34d0 100644 --- a/packages/backend/src/open_payments/payment/outgoing/service.test.ts +++ b/packages/backend/src/open_payments/payment/outgoing/service.test.ts @@ -2086,8 +2086,16 @@ describe('OutgoingPaymentService', (): void => { debitAmount, incomingPayment: cardIncomingPayment.getUrl(config.openPaymentsUrl), tenantId, - cardDetails: { expiry: '12/30', signature: 'sig', requestId: 'req-1' } + cardDetails: { + requestId: crypto.randomUUID(), + data: { + signature: 'sig', + payload: 'payload' + }, + initiatedAt: new Date() + } } + const cardOutgoingPayment = await outgoingPaymentService.create(cardOptions) assert.ok(!isOutgoingPaymentError(cardOutgoingPayment)) @@ -2140,7 +2148,14 @@ describe('OutgoingPaymentService', (): void => { debitAmount, incomingPayment: cardIncomingPayment.getUrl(config.openPaymentsUrl), tenantId, - cardDetails: { expiry: '12/30', signature: 'sig', requestId: 'req-2' } + cardDetails: { + requestId: crypto.randomUUID(), + data: { + signature: 'sig', + payload: 'payload' + }, + initiatedAt: new Date() + } } const cardOutgoingPayment = await outgoingPaymentService.create(cardOptions)