From 4a8b94c8699a0966f2fb4be87a39724eda96587a Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Mon, 16 Oct 2023 16:14:23 -0700 Subject: [PATCH 1/6] feat(backend): remove payment pointer from url, retrieve it from query or body --- ...918113102_rename_payment_pointer_tables.js | 6 +-- packages/backend/package.json | 2 +- packages/backend/src/app.ts | 32 ++++++++------- .../open_payments/payment/incoming/routes.ts | 1 + .../open_payments/payment/outgoing/routes.ts | 1 + .../payment_pointer/middleware.ts | 39 +++++++++++++++++++ packages/backend/src/shared/pagination.ts | 4 +- pnpm-lock.yaml | 19 ++++++++- 8 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 packages/backend/src/open_payments/payment_pointer/middleware.ts diff --git a/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js b/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js index 7e4ebf8582..d0b1516f73 100644 --- a/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js +++ b/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js @@ -113,7 +113,7 @@ exports.down = function (knex) { 'ALTER INDEX "walletAddresses_pkey" RENAME TO "paymentPointers_pkey"' ), knex.raw( - 'ALTER INDEX "walletAddresses_url_index" RENAME TO "paymentPointers_url_index"' + 'ALTER INDEX "walletaddresses_url_index" RENAME TO "paymentpointers_url_index"' ), knex.raw( 'ALTER INDEX "walletaddresses_processat_index" RENAME TO "paymentpointers_processat_index"' @@ -122,7 +122,7 @@ exports.down = function (knex) { 'ALTER TABLE "paymentPointers" DROP CONSTRAINT "walletaddresses_url_unique"' ), knex.raw( - 'ALTER TABLE "paymentPointers" DROP CONSTRAINT "walletaddreses_assetid_foreign"' + 'ALTER TABLE "paymentPointers" DROP CONSTRAINT "walletaddresses_assetid_foreign"' ), knex.schema.renameTable('walletAddressKeys', 'paymentPointerKeys'), knex.schema.alterTable('paymentPointerKeys', function (table) { @@ -134,7 +134,7 @@ exports.down = function (knex) { 'ALTER INDEX "walletAddressKeys_pkey" RENAME TO "paymentPointerKeys_pkey"' ), knex.raw( - 'ALTER TABLE "paymentpointerKeys" DROP CONSTRAINT "walletaddresskeys_paymentpointerid_foreign"' + 'ALTER TABLE "paymentPointerKeys" DROP CONSTRAINT "walletaddresskeys_walletaddressid_foreign"' ), knex.schema.alterTable('quotes', function (table) { table.dropForeign(['walletAddressId']) diff --git a/packages/backend/package.json b/packages/backend/package.json index a88d18e432..638b99ecc7 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -53,7 +53,7 @@ "@graphql-tools/load": "^8.0.0", "@graphql-tools/schema": "^10.0.0", "@interledger/http-signature-utils": "1.1.0", - "@interledger/open-payments": "5.0.0", + "@interledger/open-payments": "5.2.0", "@interledger/openapi": "1.0.3", "@interledger/pay": "0.4.0-alpha.9", "@interledger/stream-receiver": "^0.3.3-alpha.3", diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index 8b02ec391b..c67b02198e 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -132,10 +132,14 @@ export type HttpSigContext = AppContext & { client: string } -// Wallet address subresources export type HttpSigWithAuthenticatedStatusContext = HttpSigContext & AuthenticatedStatusContext +// Wallet address subresources +interface GetCollectionQuery { + 'wallet-address': string +} + type CollectionRequest = Omit< WalletAddressContext['request'], 'body' @@ -371,7 +375,7 @@ export class App { // POST /incoming-payments // Create incoming payment router.post>( - WALLET_ADDRESS_PATH + '/incoming-payments', + '/incoming-payments', createWalletAddressMiddleware(), createValidatorMiddleware< ContextType> @@ -389,10 +393,10 @@ export class App { // GET /incoming-payments // List incoming payments - router.get( - WALLET_ADDRESS_PATH + '/incoming-payments', + router.get>( + '/incoming-payments', createWalletAddressMiddleware(), - createValidatorMiddleware>( + createValidatorMiddleware>>( resourceServerSpec, { path: '/incoming-payments', @@ -410,7 +414,7 @@ export class App { // POST /outgoing-payment // Create outgoing payment router.post>( - WALLET_ADDRESS_PATH + '/outgoing-payments', + '/outgoing-payments', createWalletAddressMiddleware(), createValidatorMiddleware< ContextType> @@ -428,10 +432,10 @@ export class App { // GET /outgoing-payment // List outgoing payments - router.get( - WALLET_ADDRESS_PATH + '/outgoing-payments', + router.get>( + '/outgoing-payments', createWalletAddressMiddleware(), - createValidatorMiddleware>( + createValidatorMiddleware>>( resourceServerSpec, { path: '/outgoing-payments', @@ -449,7 +453,7 @@ export class App { // POST /quotes // Create quote router.post>( - WALLET_ADDRESS_PATH + '/quotes', + '/quotes', createWalletAddressMiddleware(), createValidatorMiddleware< ContextType> @@ -468,7 +472,7 @@ export class App { // GET /incoming-payments/{id} // Read incoming payment router.get( - WALLET_ADDRESS_PATH + '/incoming-payments/:id', + '/incoming-payments/:id', createWalletAddressMiddleware(), createValidatorMiddleware< ContextType @@ -488,7 +492,7 @@ export class App { // POST /incoming-payments/{id}/complete // Complete incoming payment router.post( - WALLET_ADDRESS_PATH + '/incoming-payments/:id/complete', + '/incoming-payments/:id/complete', createWalletAddressMiddleware(), createValidatorMiddleware>( resourceServerSpec, @@ -508,7 +512,7 @@ export class App { // GET /outgoing-payments/{id} // Read outgoing payment router.get( - WALLET_ADDRESS_PATH + '/outgoing-payments/:id', + '/outgoing-payments/:id', createWalletAddressMiddleware(), createValidatorMiddleware>( resourceServerSpec, @@ -528,7 +532,7 @@ export class App { // GET /quotes/{id} // Read quote router.get( - WALLET_ADDRESS_PATH + '/quotes/:id', + '/quotes/:id', createWalletAddressMiddleware(), createValidatorMiddleware>( resourceServerSpec, diff --git a/packages/backend/src/open_payments/payment/incoming/routes.ts b/packages/backend/src/open_payments/payment/incoming/routes.ts index 188afae0af..e3d62ff4bf 100644 --- a/packages/backend/src/open_payments/payment/incoming/routes.ts +++ b/packages/backend/src/open_payments/payment/incoming/routes.ts @@ -115,6 +115,7 @@ async function getIncomingPaymentPrivate( } export type CreateBody = { + walletAddress: string expiresAt?: string incomingAmount?: AmountJSON metadata?: Record diff --git a/packages/backend/src/open_payments/payment/outgoing/routes.ts b/packages/backend/src/open_payments/payment/outgoing/routes.ts index 62be310455..821da996e0 100644 --- a/packages/backend/src/open_payments/payment/outgoing/routes.ts +++ b/packages/backend/src/open_payments/payment/outgoing/routes.ts @@ -58,6 +58,7 @@ async function getOutgoingPayment( } export type CreateBody = { + walletAddress: string quoteId: string metadata?: Record } diff --git a/packages/backend/src/open_payments/payment_pointer/middleware.ts b/packages/backend/src/open_payments/payment_pointer/middleware.ts new file mode 100644 index 0000000000..a7c487adc6 --- /dev/null +++ b/packages/backend/src/open_payments/payment_pointer/middleware.ts @@ -0,0 +1,39 @@ +import { AppContext } from '../../app' +import { CreateBody as IncomingCreateBody } from '../../open_payments/payment/incoming/routes' +import { CreateBody as OutgoingCreateBody } from '../../open_payments/payment/outgoing/routes' + +type CreateBody = IncomingCreateBody | OutgoingCreateBody + +export function createPaymentPointerMiddleware() { + return async ( + ctx: AppContext, + next: () => Promise + ): Promise => { + if (ctx.path === '/incoming-payments' || ctx.path === '/outgoing-payments') { + if (ctx.method === 'GET') { + ctx.paymentPointerUrl = ctx.query['wallet-address'] as string + } else if (ctx.method === 'POST') { + ctx.paymentPointerUrl = (ctx.request.body as CreateBody).walletAddress + } else { + ctx.throw(401) + } + } else { + ctx.paymentPointerUrl = `https://${ctx.request.host}/${ctx.params.paymentPointerPath}` + } + const config = await ctx.container.use('config') + if (ctx.paymentPointerUrl !== config.paymentPointerUrl) { + const paymentPointerService = await ctx.container.use( + 'paymentPointerService' + ) + const paymentPointer = await paymentPointerService.getOrPollByUrl( + ctx.paymentPointerUrl + ) + + if (!paymentPointer?.isActive) { + ctx.throw(404) + } + ctx.paymentPointer = paymentPointer + } + await next() + } +} diff --git a/packages/backend/src/shared/pagination.ts b/packages/backend/src/shared/pagination.ts index 8af77ea58e..205afb523f 100644 --- a/packages/backend/src/shared/pagination.ts +++ b/packages/backend/src/shared/pagination.ts @@ -1,7 +1,9 @@ -import { PaginationArgs } from '@interledger/open-payments' +import { PaginationArgs as OpenPaymentsPaginationArgs } from '@interledger/open-payments' import { BaseModel, PageInfo, Pagination } from './baseModel' +type PaginationArgs = Omit + export function parsePaginationQueryParameters({ first, last, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d286819948..a5913a954c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -303,8 +303,8 @@ importers: specifier: 1.1.0 version: 1.1.0 '@interledger/open-payments': - specifier: 5.0.0 - version: 5.0.0 + specifier: 5.2.0 + version: 5.2.0 '@interledger/openapi': specifier: 1.0.3 version: 1.0.3 @@ -4415,6 +4415,21 @@ packages: - supports-color dev: false + /@interledger/open-payments@5.2.0: + resolution: {integrity: sha512-Rt1ypzDkEimLky2QoJ1cTPkjr0esxGwzoj7rTLwNiT9B5SY30O+dVXhw3AYa3dK4FDwGgDQOQHJlPEHwzrXZng==} + dependencies: + '@interledger/http-signature-utils': 1.1.0 + '@interledger/openapi': 1.2.0 + axios: 1.5.1 + base64url: 3.0.1 + http-message-signatures: 0.1.2 + pino: 8.16.0 + uuid: 9.0.1 + transitivePeerDependencies: + - debug + - supports-color + dev: false + /@interledger/openapi@1.0.3: resolution: {integrity: sha512-Xx/Me2tj8DhHpQR9cVjioX/DAUmQnaXWjt8hEVPIru4pDSMHCGG0RmpU2dV+aIiVmkDM2OvJUfKoLGsPVStqrA==} dependencies: From 650092bbca9664eeeae3373536c54b40ef281162 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 17 Oct 2023 10:21:03 -0700 Subject: [PATCH 2/6] chore: remove payemnt pointer middleware after rebase --- .../payment_pointer/middleware.ts | 39 ------------------- .../wallet_address/middleware.ts | 16 +++++++- 2 files changed, 15 insertions(+), 40 deletions(-) delete mode 100644 packages/backend/src/open_payments/payment_pointer/middleware.ts diff --git a/packages/backend/src/open_payments/payment_pointer/middleware.ts b/packages/backend/src/open_payments/payment_pointer/middleware.ts deleted file mode 100644 index a7c487adc6..0000000000 --- a/packages/backend/src/open_payments/payment_pointer/middleware.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { AppContext } from '../../app' -import { CreateBody as IncomingCreateBody } from '../../open_payments/payment/incoming/routes' -import { CreateBody as OutgoingCreateBody } from '../../open_payments/payment/outgoing/routes' - -type CreateBody = IncomingCreateBody | OutgoingCreateBody - -export function createPaymentPointerMiddleware() { - return async ( - ctx: AppContext, - next: () => Promise - ): Promise => { - if (ctx.path === '/incoming-payments' || ctx.path === '/outgoing-payments') { - if (ctx.method === 'GET') { - ctx.paymentPointerUrl = ctx.query['wallet-address'] as string - } else if (ctx.method === 'POST') { - ctx.paymentPointerUrl = (ctx.request.body as CreateBody).walletAddress - } else { - ctx.throw(401) - } - } else { - ctx.paymentPointerUrl = `https://${ctx.request.host}/${ctx.params.paymentPointerPath}` - } - const config = await ctx.container.use('config') - if (ctx.paymentPointerUrl !== config.paymentPointerUrl) { - const paymentPointerService = await ctx.container.use( - 'paymentPointerService' - ) - const paymentPointer = await paymentPointerService.getOrPollByUrl( - ctx.paymentPointerUrl - ) - - if (!paymentPointer?.isActive) { - ctx.throw(404) - } - ctx.paymentPointer = paymentPointer - } - await next() - } -} diff --git a/packages/backend/src/open_payments/wallet_address/middleware.ts b/packages/backend/src/open_payments/wallet_address/middleware.ts index c7ac829d36..b1cd20ef28 100644 --- a/packages/backend/src/open_payments/wallet_address/middleware.ts +++ b/packages/backend/src/open_payments/wallet_address/middleware.ts @@ -1,11 +1,25 @@ import { AppContext } from '../../app' +import { CreateBody as IncomingCreateBody } from '../../open_payments/payment/incoming/routes' +import { CreateBody as OutgoingCreateBody } from '../../open_payments/payment/outgoing/routes' + +type CreateBody = IncomingCreateBody | OutgoingCreateBody export function createWalletAddressMiddleware() { return async ( ctx: AppContext, next: () => Promise ): Promise => { - ctx.walletAddressUrl = `https://${ctx.request.host}/${ctx.params.walletAddressPath}` + if (ctx.path === '/incoming-payments' || ctx.path === '/outgoing-payments') { + if (ctx.method === 'GET') { + ctx.walletAddressUrl = ctx.query['wallet-address'] as string + } else if (ctx.method === 'POST') { + ctx.walletAddressUrl = (ctx.request.body as CreateBody).walletAddress + } else { + ctx.throw(401) + } + } else { + ctx.walletAddressUrl = `https://${ctx.request.host}/${ctx.params.paymentPointerPath}` + } const config = await ctx.container.use('config') if (ctx.walletAddressUrl !== config.walletAddressUrl) { const walletAddressService = await ctx.container.use( From 646d1dc8ac0e7aa72046718afc30f06d4f422280 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 17 Oct 2023 12:14:45 -0700 Subject: [PATCH 3/6] feat: re-add post-rebase changes, remove middleware from GET subresource requests --- packages/backend/src/app.ts | 38 ++++++++++--------- .../open_payments/payment/incoming/routes.ts | 4 +- .../payment/incoming_remote/service.ts | 3 +- .../open_payments/payment/outgoing/routes.ts | 10 +++-- .../backend/src/open_payments/quote/routes.ts | 7 ++-- .../wallet_address/middleware.ts | 7 +++- 6 files changed, 38 insertions(+), 31 deletions(-) diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index c67b02198e..8d11e94939 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -393,16 +393,18 @@ export class App { // GET /incoming-payments // List incoming payments - router.get>( + router.get< + DefaultState, + SignedCollectionContext + >( '/incoming-payments', createWalletAddressMiddleware(), - createValidatorMiddleware>>( - resourceServerSpec, - { - path: '/incoming-payments', - method: HttpMethod.GET - } - ), + createValidatorMiddleware< + ContextType> + >(resourceServerSpec, { + path: '/incoming-payments', + method: HttpMethod.GET + }), createTokenIntrospectionMiddleware({ requestType: AccessType.IncomingPayment, requestAction: RequestAction.List @@ -432,16 +434,18 @@ export class App { // GET /outgoing-payment // List outgoing payments - router.get>( + router.get< + DefaultState, + SignedCollectionContext + >( '/outgoing-payments', createWalletAddressMiddleware(), - createValidatorMiddleware>>( - resourceServerSpec, - { - path: '/outgoing-payments', - method: HttpMethod.GET - } - ), + createValidatorMiddleware< + ContextType> + >(resourceServerSpec, { + path: '/outgoing-payments', + method: HttpMethod.GET + }), createTokenIntrospectionMiddleware({ requestType: AccessType.OutgoingPayment, requestAction: RequestAction.List @@ -473,7 +477,6 @@ export class App { // Read incoming payment router.get( '/incoming-payments/:id', - createWalletAddressMiddleware(), createValidatorMiddleware< ContextType >(resourceServerSpec, { @@ -513,7 +516,6 @@ export class App { // Read outgoing payment router.get( '/outgoing-payments/:id', - createWalletAddressMiddleware(), createValidatorMiddleware>( resourceServerSpec, { diff --git a/packages/backend/src/open_payments/payment/incoming/routes.ts b/packages/backend/src/open_payments/payment/incoming/routes.ts index e3d62ff4bf..8702a081bd 100644 --- a/packages/backend/src/open_payments/payment/incoming/routes.ts +++ b/packages/backend/src/open_payments/payment/incoming/routes.ts @@ -105,10 +105,10 @@ async function getIncomingPaymentPrivate( } catch (err) { ctx.throw(500, 'Error trying to get incoming payment') } - if (!incomingPayment) return ctx.throw(404) + if (!incomingPayment || !incomingPayment.walletAddress) return ctx.throw(404) const connection = deps.connectionService.get(incomingPayment) ctx.body = incomingPaymentToBody( - ctx.walletAddress, + incomingPayment.walletAddress, incomingPayment, connection ) diff --git a/packages/backend/src/open_payments/payment/incoming_remote/service.ts b/packages/backend/src/open_payments/payment/incoming_remote/service.ts index 4d38be5c0f..1eabea33a7 100644 --- a/packages/backend/src/open_payments/payment/incoming_remote/service.ts +++ b/packages/backend/src/open_payments/payment/incoming_remote/service.ts @@ -66,10 +66,11 @@ async function create( try { return await deps.openPaymentsClient.incomingPayment.create( { - walletAddress: walletAddressUrl, + url: walletAddressUrl, accessToken: grantOrError.accessToken }, { + walletAddress: walletAddressUrl, incomingAmount: args.incomingAmount ? serializeAmount(args.incomingAmount) : undefined, diff --git a/packages/backend/src/open_payments/payment/outgoing/routes.ts b/packages/backend/src/open_payments/payment/outgoing/routes.ts index 821da996e0..51ac82a9b8 100644 --- a/packages/backend/src/open_payments/payment/outgoing/routes.ts +++ b/packages/backend/src/open_payments/payment/outgoing/routes.ts @@ -47,14 +47,16 @@ async function getOutgoingPayment( try { outgoingPayment = await deps.outgoingPaymentService.get({ id: ctx.params.id, - client: ctx.accessAction === AccessAction.Read ? ctx.client : undefined, - walletAddressId: ctx.walletAddress.id + client: ctx.accessAction === AccessAction.Read ? ctx.client : undefined }) } catch (_) { ctx.throw(500, 'Error trying to get outgoing payment') } - if (!outgoingPayment) return ctx.throw(404) - ctx.body = outgoingPaymentToBody(ctx.walletAddress, outgoingPayment) + if (!outgoingPayment || !outgoingPayment.walletAddress) return ctx.throw(404) + ctx.body = outgoingPaymentToBody( + outgoingPayment.walletAddress, + outgoingPayment + ) } export type CreateBody = { diff --git a/packages/backend/src/open_payments/quote/routes.ts b/packages/backend/src/open_payments/quote/routes.ts index 816b415a72..46c23941ae 100644 --- a/packages/backend/src/open_payments/quote/routes.ts +++ b/packages/backend/src/open_payments/quote/routes.ts @@ -37,11 +37,10 @@ async function getQuote( ): Promise { const quote = await deps.quoteService.get({ id: ctx.params.id, - client: ctx.accessAction === AccessAction.Read ? ctx.client : undefined, - walletAddressId: ctx.walletAddress.id + client: ctx.accessAction === AccessAction.Read ? ctx.client : undefined }) - if (!quote) return ctx.throw(404) - ctx.body = quoteToBody(ctx.walletAddress, quote) + if (!quote || !quote.walletAddress) return ctx.throw(404) + ctx.body = quoteToBody(quote.walletAddress, quote) } interface CreateBodyBase { diff --git a/packages/backend/src/open_payments/wallet_address/middleware.ts b/packages/backend/src/open_payments/wallet_address/middleware.ts index b1cd20ef28..5a2ee882c0 100644 --- a/packages/backend/src/open_payments/wallet_address/middleware.ts +++ b/packages/backend/src/open_payments/wallet_address/middleware.ts @@ -9,11 +9,14 @@ export function createWalletAddressMiddleware() { ctx: AppContext, next: () => Promise ): Promise => { - if (ctx.path === '/incoming-payments' || ctx.path === '/outgoing-payments') { + if ( + ctx.path === '/incoming-payments' || + ctx.path === '/outgoing-payments' + ) { if (ctx.method === 'GET') { ctx.walletAddressUrl = ctx.query['wallet-address'] as string } else if (ctx.method === 'POST') { - ctx.walletAddressUrl = (ctx.request.body as CreateBody).walletAddress + ctx.walletAddressUrl = (ctx.request.body as CreateBody).walletAddress } else { ctx.throw(401) } From 3ebbdc0473f76766ab071fe5eb8faed38565b71c Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Thu, 19 Oct 2023 09:47:48 -0700 Subject: [PATCH 4/6] docs: update postman --- postman/collections/Interledger.json | 87 ++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/postman/collections/Interledger.json b/postman/collections/Interledger.json index 1ff5e31e5a..5cbb3338e2 100644 --- a/postman/collections/Interledger.json +++ b/postman/collections/Interledger.json @@ -1530,7 +1530,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"incomingAmount\": {\n \"value\": \"2000\",\n \"assetCode\": \"USD\",\n \"assetScale\": 2\n },\n \"expiresAt\": \"{{tomorrow}}\",\n \"metadata\": {\n \"description\": \"Incoming Payment on Own Account\",\n \"externalRef\": \"INV-001\"\n }\n}", + "raw": "{\n \"walletAddress\": {{pfryWalletAddress}},\n \"incomingAmount\": {\n \"value\": \"2000\",\n \"assetCode\": \"USD\",\n \"assetScale\": 2\n },\n \"expiresAt\": \"{{tomorrow}}\",\n \"metadata\": {\n \"description\": \"Incoming Payment on Own Account\",\n \"externalRef\": \"INV-001\"\n }\n}", "options": { "raw": { "language": "json" @@ -1538,10 +1538,12 @@ } }, "url": { - "raw": "{{pfryWalletAddress}}/incoming-payments", + "raw": "http://localhost:4000/incoming-payments", + "protocol": "http", "host": [ - "{{pfryWalletAddress}}" + "localhost" ], + "port": "4000", "path": [ "incoming-payments" ] @@ -1593,10 +1595,12 @@ } ], "url": { - "raw": "{{pfryWalletAddress}}/incoming-payments/{{incomingPaymentId}}", + "raw": "http://localhost:4000/incoming-payments/{{incomingPaymentId}}", + "protocol": "http", "host": [ - "{{pfryWalletAddress}}" + "localhost" ], + "port": "4000", "path": [ "incoming-payments", "{{incomingPaymentId}}" @@ -1650,10 +1654,12 @@ } ], "url": { - "raw": "{{pfryPaymentPointer}}/incoming-payments/{{incomingPaymentId}}", + "raw": "http://localhost:4000/incoming-payments/{{incomingPaymentId}}", + "protocol": "http", "host": [ - "{{pfryPaymentPointer}}" + "localhost" ], + "port": "4000", "path": [ "incoming-payments", "{{incomingPaymentId}}" @@ -1706,22 +1712,28 @@ } ], "url": { - "raw": "{{pfryWalletAddress}}/incoming-payments?first=10", + "raw": "http://localhost:4000/incoming-payments?first=10&wallet-address={{pfryWalletAddress}}", + "protocol": "http", "host": [ - "{{pfryWalletAddress}}" + "localhost" ], + "port": "4000", "path": [ "incoming-payments" ], "query": [ + { + "key": "first", + "value": "10" + }, { "key": "cursor", "value": "ea3bf38f-2719-4473-a0f7-4ba967d1d81b", "disabled": true }, { - "key": "first", - "value": "10" + "key": "wallet-address", + "value": "{{pfryWalletAddress}}" } ] } @@ -1758,11 +1770,22 @@ "value": "happy-life-bank-backend" } ], + "body": { + "mode": "raw", + "raw": "{\n \"walletAddress\": {{pfryWalletAddress}}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{pfryWalletAddress}}/incoming-payments/{{incomingPaymentId}}/complete", + "raw": "http://localhost:4000/incoming-payments/{{incomingPaymentId}}/complete", + "protocol": "http", "host": [ - "{{pfryWalletAddress}}" + "localhost" ], + "port": "4000", "path": [ "incoming-payments", "{{incomingPaymentId}}", @@ -1826,7 +1849,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"receiver\": \"https://happy-life-bank-backend/accounts/pfry/incoming-payments/{{incomingPaymentId}}\",\n \"debitAmount\": {\n \"value\": \"1000\",\n \"assetCode\": \"USD\",\n \"assetScale\": 2\n }\n}", + "raw": "{\n \"walletAddress\": {{gfranklinWalletAddress}},\n \"receiver\": \"https://happy-life-bank-backend/accounts/pfry/incoming-payments/{{incomingPaymentId}}\",\n \"debitAmount\": {\n \"value\": \"1000\",\n \"assetCode\": \"USD\",\n \"assetScale\": 2\n }\n}", "options": { "raw": { "language": "json" @@ -1834,10 +1857,12 @@ } }, "url": { - "raw": "{{gfranklinWalletAddress}}/quotes", + "raw": "http://localhost:3000/quotes", + "protocol": "http", "host": [ - "{{gfranklinWalletAddress}}" + "localhost" ], + "port": "3000", "path": [ "quotes" ] @@ -1889,10 +1914,12 @@ } ], "url": { - "raw": "{{gfranklinWalletAddress}}/quotes/{{quoteId}}", + "raw": "http://localhost:3000/quotes/{{quoteId}}", + "protocol": "http", "host": [ - "{{gfranklinWalletAddress}}" + "localhost" ], + "port": "3000", "path": [ "quotes", "{{quoteId}}" @@ -1955,7 +1982,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"quoteId\": \"{{gfranklinWalletAddress}}/quotes/{{quoteId}}\",\n \"description\": \"yolo\",\n \"externalRef\": \"INV-001\"\n}", + "raw": "{\n \"walletAddress\": {{gfranklinWalletAddress}},\n \"quoteId\": \"{{gfranklinWalletAddress}}/quotes/{{quoteId}}\",\n \"description\": \"yolo\",\n \"externalRef\": \"INV-001\"\n}", "options": { "raw": { "language": "json" @@ -1963,10 +1990,12 @@ } }, "url": { - "raw": "{{gfranklinWalletAddress}}/outgoing-payments", + "raw": "http://localhost:3000/outgoing-payments", + "protocol": "http", "host": [ - "{{gfranklinWalletAddress}}" + "localhost" ], + "port": "3000", "path": [ "outgoing-payments" ] @@ -2018,10 +2047,12 @@ } ], "url": { - "raw": "{{gfranklinWalletAddress}}/outgoing-payments/{{outgoingPaymentId}}", + "raw": "http://localhost:3000/outgoing-payments/{{outgoingPaymentId}}", + "protocol": "http", "host": [ - "{{gfranklinWalletAddress}}" + "localhost" ], + "port": "3000", "path": [ "outgoing-payments", "{{outgoingPaymentId}}" @@ -2074,10 +2105,12 @@ } ], "url": { - "raw": "{{gfranklinWalletAddress}}/outgoing-payments?first=2", + "raw": "http://localhost:3000/outgoing-payments?first=2&wallet-address={{gfranklinWalletAddress}}", + "protocol": "http", "host": [ - "{{gfranklinWalletAddress}}" + "localhost" ], + "port": "3000", "path": [ "outgoing-payments" ], @@ -2090,6 +2123,10 @@ "key": "cursor", "value": "ea3bf38f-2719-4473-a0f7-4ba967d1d81b", "disabled": true + }, + { + "key": "wallet-address", + "value": "{{gfranklinWalletAddress}}" } ] } From 4ad3cdb7fc954ea616f53b30053945a4c48babe4 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Thu, 19 Oct 2023 10:39:42 -0700 Subject: [PATCH 5/6] feat: remove walletAddress from complete incoming payment context --- packages/backend/src/app.ts | 1 - .../open_payments/payment/incoming/routes.test.ts | 4 ++-- .../src/open_payments/payment/incoming/routes.ts | 15 ++++++++++++--- .../open_payments/wallet_address/middleware.ts | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index 8d11e94939..f8425c5d6c 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -496,7 +496,6 @@ export class App { // Complete incoming payment router.post( '/incoming-payments/:id/complete', - createWalletAddressMiddleware(), createValidatorMiddleware>( resourceServerSpec, { diff --git a/packages/backend/src/open_payments/payment/incoming/routes.test.ts b/packages/backend/src/open_payments/payment/incoming/routes.test.ts index 455cc259f0..3e536fa136 100644 --- a/packages/backend/src/open_payments/payment/incoming/routes.test.ts +++ b/packages/backend/src/open_payments/payment/incoming/routes.test.ts @@ -297,7 +297,7 @@ describe('Incoming Payment Routes', (): void => { describe('get unauthenticated incoming payment', (): void => { test('Can get incoming payment with public fields', async (): Promise => { const incomingPayment = await createIncomingPayment(deps, { - paymentPointerId: paymentPointer.id, + walletAddressId: walletAddress.id, expiresAt, incomingAmount, metadata @@ -312,7 +312,7 @@ describe('Incoming Payment Routes', (): void => { params: { id: incomingPayment.id }, - paymentPointer + walletAddress }) ctx.authenticated = false diff --git a/packages/backend/src/open_payments/payment/incoming/routes.ts b/packages/backend/src/open_payments/payment/incoming/routes.ts index 8702a081bd..895843d5cb 100644 --- a/packages/backend/src/open_payments/payment/incoming/routes.ts +++ b/packages/backend/src/open_payments/payment/incoming/routes.ts @@ -81,7 +81,7 @@ async function getIncomingPaymentPublic( const incomingPayment = await deps.incomingPaymentService.get({ id: ctx.params.id, client: ctx.accessAction === AccessAction.Read ? ctx.client : undefined, - paymentPointerId: ctx.paymentPointer.id + walletAddressId: ctx.walletAddress.id }) ctx.body = incomingPayment?.toPublicOpenPaymentsType() } catch (err) { @@ -147,10 +147,14 @@ async function createIncomingPayment( ) } + if (!incomingPaymentOrError.walletAddress) { + ctx.throw(404) + } + ctx.status = 201 const connection = deps.connectionService.get(incomingPaymentOrError) ctx.body = incomingPaymentToBody( - ctx.walletAddress, + incomingPaymentOrError.walletAddress, incomingPaymentOrError, connection ) @@ -175,7 +179,12 @@ async function completeIncomingPayment( errorToMessage[incomingPaymentOrError] ) } - ctx.body = incomingPaymentToBody(ctx.walletAddress, incomingPaymentOrError) + + if (!incomingPaymentOrError.walletAddress) { + ctx.throw(404) + } + + ctx.body = incomingPaymentToBody(incomingPaymentOrError.walletAddress, incomingPaymentOrError) } async function listIncomingPayments( diff --git a/packages/backend/src/open_payments/wallet_address/middleware.ts b/packages/backend/src/open_payments/wallet_address/middleware.ts index 5a2ee882c0..c9db313b96 100644 --- a/packages/backend/src/open_payments/wallet_address/middleware.ts +++ b/packages/backend/src/open_payments/wallet_address/middleware.ts @@ -21,7 +21,7 @@ export function createWalletAddressMiddleware() { ctx.throw(401) } } else { - ctx.walletAddressUrl = `https://${ctx.request.host}/${ctx.params.paymentPointerPath}` + ctx.walletAddressUrl = `https://${ctx.request.host}/${ctx.params.walletAddressPath}` } const config = await ctx.container.use('config') if (ctx.walletAddressUrl !== config.walletAddressUrl) { From 5113efd6f5bfc1d716ce2b5f376deff03f4d19c8 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Thu, 19 Oct 2023 14:20:21 -0700 Subject: [PATCH 6/6] fix: migration typos --- .../20230918113102_rename_payment_pointer_tables.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js b/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js index d0b1516f73..2a305dbd05 100644 --- a/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js +++ b/packages/backend/migrations/20230918113102_rename_payment_pointer_tables.js @@ -40,27 +40,21 @@ exports.up = function (knex) { table.dropIndex(['paymentPointerId', 'createdAt', 'id']) table.renameColumn('paymentPointerId', 'walletAddressId') table.foreign('walletAddressId').references('walletAddresses.id') - table.index(['walletAddressId']) - table.index(['createdAt']) - table.index(['id']) + table.index(['walletAddressId', 'createdAt', 'id']) }), knex.schema.alterTable('incomingPayments', function (table) { table.dropForeign(['paymentPointerId']) table.dropIndex(['paymentPointerId', 'createdAt', 'id']) table.renameColumn('paymentPointerId', 'walletAddressId') table.foreign('walletAddressId').references('walletAddresses.id') - table.index(['walletAddressId']) - table.index(['createdAt']) - table.index(['id']) + table.index(['walletAddressId', 'createdAt', 'id']) }), knex.schema.alterTable('outgoingPayments', function (table) { table.dropForeign(['paymentPointerId']) table.dropIndex(['paymentPointerId', 'createdAt', 'id']) table.renameColumn('paymentPointerId', 'walletAddressId') table.foreign('walletAddressId').references('walletAddresses.id') - table.index(['walletAddressId']) - table.index(['createdAt']) - table.index(['id']) + table.index(['walletAddressId', 'createdAt', 'id']) }), knex('webhookEvents') .update({ @@ -126,7 +120,6 @@ exports.down = function (knex) { ), knex.schema.renameTable('walletAddressKeys', 'paymentPointerKeys'), knex.schema.alterTable('paymentPointerKeys', function (table) { - table.dropForeign(['walletAddressId']) table.renameColumn('walletAddressId', 'paymentPointerId') table.foreign('paymentPointerId').references('paymentPointers.id') }),