Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(backend): swap connection for methods #2054

Merged
merged 40 commits into from
Oct 20, 2023

Conversation

BlairCurrey
Copy link
Contributor

@BlairCurrey BlairCurrey commented Oct 18, 2023

Changes proposed in this pull request

  • updates to latest open-payments openapi spec (5.2.2)
  • refactors to remove connection and replace with methods
  • connection service was reduced to just get the stream credentials and has been renamed to streamCredentialService

Context

This branch is does not build yet, and not all tests pass, which is expected. This is due to other unimplemented changes. I fixed all build errors related to these change and the test failures I see locally appear related to pagination (possibly due to bug in our down migration in our dev branch at the moment?).

Checklist

  • Related issues linked using fixes #number
  • Tests added/updated
  • Documentation added
  • Make sure that all checks pass
  • Postman collection updated

BlairCurrey and others added 19 commits October 18, 2023 13:26
* feat(backend): mount resource server routes explicitly

* chore: formatting

* feat(backend): wip unauthenticated incoming payment get

* fix(backend): token introspection middleware

* chore(backend): cleanup

* chore(backend): cleanup

* test(backend): update incoming payment tests

* test(backend): add tests for new option

* feat(backend): add unauthed incoming payment

* fix: accidentally removed postman request

* refactor(backend): optional sig params

* fix(backend): typo

* fix(backend): unused args

---------

Co-authored-by: Nathan Lie <nathanlie@Nathans-MacBook-Pro.local>
@github-actions github-actions bot added type: tests Testing related pkg: backend Changes in the backend package. type: source Changes business logic labels Oct 18, 2023
@BlairCurrey BlairCurrey changed the title Bc/1962/swap connection for methods refactor(backend): swap connection for methods Oct 18, 2023
Comment on lines +156 to +159
public get method(): 'ilp' {
return 'ilp'
}

Copy link
Contributor Author

@BlairCurrey BlairCurrey Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkurapov wasn't quite sure what our intention is for modeling payment methods.

The new openapi spec requires the method on the POST /quote body but I didn't actually add it to the create path (quoteRoutes.create, quoteService.create, createQuote test util etc) since its not stored anywhere and I'm not sure how we want to do that (method column on Quote? fkey column on Quote point to Methods table?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like having the idea of a PaymentMethods table that determines what types of payment methods are active or inactive, but for the sake of time this (hard-coding ilp) works well

@BlairCurrey
Copy link
Contributor Author

the ilp payment method is hardcoded a number of places. I'm not against abstracting it a bit to handle multiple methods where it's clear and simple but I wanted to keep the scope to what is necessary to maintain functionality of ilp payment methods. In additional to maximizing the amount of time we have to update testnet, I think the right way to handle multiple methods will probably be more clear when we actually add the next method.

Comment on lines 68 to 70
// TODO: ensure these are the right assetCode/Scales
this.assetCode = incomingPayment.receivedAmount.assetCode
this.assetScale = incomingPayment.receivedAmount.assetScale
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will address this TODO before merging. Previously we were getting these off the connection and I wasn't sure where we should get it now - Max suggested this and I believe it is correct. Tests seem to back it up but any more common-sense checks would be welcome

expect(receiver).toEqual({
assetCode: incomingPayment.asset.code,
assetScale: incomingPayment.asset.scale,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than fetching the walletAddress asset, I don't think there is really any other option that we have

Copy link
Contributor

@mkurapov mkurapov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

): string | undefined {
if (!payment.connectionId) {
return undefined
return {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can probably get away with the if (!payment.connectionId) check, and remove connectionid altogether from the incoming payment model

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the connectionId from IncomingPayment. I kept this check to return undefined when payment is completed or expired to maintain the behavior tested here:

test.each`
state
${IncomingPaymentState.Completed}
${IncomingPaymentState.Expired}
`(
`returns undefined for $state incoming payment`,
async ({ state }): Promise<void> => {
await incomingPayment.$query(knex).patch({
state,
expiresAt:
state === IncomingPaymentState.Expired ? new Date() : undefined
})
expect(connectionService.get(incomingPayment)).toBeUndefined()
}
)

A beforeInsert hook ensured the connectionId was always set, and then it would be set to null in a beforeUpdate hook when the state was completed or expired. So it seems this was basically a roundabout way to check if the payment was expired or complete.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this mean that the Open Payments GET /incoming-payment/ fails if the payment is expired or completed since we won't be returning the methods array?

Copy link
Contributor

@mkurapov mkurapov Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, if there is no ilpStreamConnection passed into the incomingPayment.toOpenPaymentsType (here), we can just return an empty methods array

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this mean that the Open Payments GET /incoming-payment/ fails if the payment is expired or completed since we won't be returning the methods array?

I think you're right but I dont think we can just add an empty methods array to toOpenPaymentsType when no connections are passed in. Sometimes it should return the payment without methods to satisfy the base incoming-payment openapi type. I guess we could make a seperate toOpenPaymentsTypeWithMethods (not overloaded) and call as appropriate. But should the method really be empty when the payment is expired/complete? Do we not want the actual payment method with credentials?

I'm thinking your original suggestion makes the most sense now. If we dont return undefined for completed or expired payments then we can handle completed/expired where its called if we want, and do nothing otherwise (such as GET /incoming-payment/{id}). I implemented that in this new commit 8396970

Copy link
Contributor Author

@BlairCurrey BlairCurrey Oct 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will need to revise this to ensure methods is an empty array when the result should match the incoming-payment-with-methods type and the state is completed or expired.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated. The caller of toOpenPaymentsType has to distinguish between which type (with methods or without) so that we ensure we're returning the right object with respect to the methods field. We can no longer use the presence of the ilpStreamCredentials to determine it alone. An undefined ilpStreamCredentials should sometimes return no methods, and sometimes [] depending on where its called.

As such I removed the overloading (rather than perhaps adding an additional withMethods boolean) since it makes the internal function logic much simpler and the caller already has to differentiate between which type it wants anyways.

Comment on lines +156 to +159
public get method(): 'ilp' {
return 'ilp'
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like having the idea of a PaymentMethods table that determines what types of payment methods are active or inactive, but for the sake of time this (hard-coding ilp) works well

Comment on lines 68 to 70
// TODO: ensure these are the right assetCode/Scales
this.assetCode = incomingPayment.receivedAmount.assetCode
this.assetScale = incomingPayment.receivedAmount.assetScale
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than fetching the walletAddress asset, I don't think there is really any other option that we have

@BlairCurrey
Copy link
Contributor Author

Almost makes me think we can just pass in the streamServer into incomingPaymentService and remove connectionService altogether, thoughts? @sabineschaller @BlairCurrey

I had a similar thought but I'm unsure if incomignPayment makes the most sense for this since it's ilp specific. As discussed elsewhere, I will change the service name to streamCredentials and move to the payment-method/ilp.

@@ -20,7 +20,8 @@ export class Quote extends WalletAddressSubresource {
'receiveAmount',
'minExchangeRate',
'lowEstimatedExchangeRate',
'highEstimatedExchangeRate'
'highEstimatedExchangeRate',
'method'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also be able to expect the method field as an argument to quote creation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I fully understand so please clarify if I have something wrong. Given that this is an objection model, these quotes objects are created from inserting and querying the database. Rather than doing something like new Quote({..., method: 'ilp'}). So I cant pass it in to the quote creation because it doesnt exist in the database and I think we agreed that the database changes didn't need to be in this PR. And if its defined as a real class attribute, it will try to write ilp to a non-existant method column where ever we insert a quote.

At face value I think it would be appropriate to include all of that here (add to quoteService.create, adjust everywhere that's called, add migration). However I think we're sacrificing debugging of nl-open-payments-updates at this point to do so, and it's functional as-is. I can capture this improvement in a task if we like, and work on that if we have extra time, otherwise do it after the code-freeze.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what Max meant was adding method to the arguments of quoteService.create.

Copy link
Contributor Author

@BlairCurrey BlairCurrey Oct 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, but it will be unused until we make the db changes.

edit: im adding it to the create paths

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added 6f3e16e

@BlairCurrey BlairCurrey requested a review from mkurapov October 19, 2023 19:43
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we talked about this during our call:
We should test that expired and completed incoming payments include an empty methods array.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, we should check that no stream credentials are created

Copy link
Contributor Author

@BlairCurrey BlairCurrey Oct 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

credentials were never being generated in the incoming payment service. so I think thats a non-factor here unless Im missing something. I dont see anywhere I could add such a check in the service (I am adding one to the incoming/model.test.ts in addition to incoming/routes.test.ts).

Copy link
Contributor Author

@BlairCurrey BlairCurrey Oct 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im also going to restore the original behavior to streamCredentials.get where it returned undefined when the incoming payment was complete or expired (maybe this was your point here).


public toOpenPaymentsType(
walletAddress: WalletAddress,
ilpStreamConnection?: Connection | string
ilpStreamCredentials?: IlpStreamCredentials
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To spitball a future idea for this, maybe this parameter could be genericized into method which has a type that all payment methods implement and can call a .toOpenPayments() function.

Copy link
Contributor Author

@BlairCurrey BlairCurrey Oct 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure if I'm following but wanted to note there have been some recent changes that might affect this suggestion: #2054 (comment)

@@ -1654,12 +1620,10 @@
}
],
"url": {
"raw": "http://localhost:4000/incoming-payments/{{incomingPaymentId}}",
"protocol": "http",
"raw": "{{pfryWalletAddress}}/incoming-payments/{{incomingPaymentId}}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the postman collection needs to be updated again - looks like it swallowed the "remove wallet address from url" changes.

@njlie
Copy link
Contributor

njlie commented Oct 20, 2023

@mkurapov @sabineschaller If there's any other feedback you'd like to give in this PR feel free to make comment on pertinent lines as usual, but in the interest of keeping things moving I'd also like for you to create an issue so we can address it in a subsequent PR on the nl-open-payments feature branch.

@njlie njlie merged commit b941a72 into nl-open-payments-updates Oct 20, 2023
@njlie njlie deleted the bc/1962/swap-connection-for-methods branch October 20, 2023 22:12
njlie added a commit that referenced this pull request Oct 23, 2023
Co-authored-by: Nathan Lie <lie4nathan@gmail.com>
sabineschaller added a commit that referenced this pull request Oct 26, 2023
* feat(backend): rename "payment pointer" tables & columns to use "wallet address" (#1937)

Co-authored-by: Nathan Lie <nathanlie@Nathans-MacBook-Pro.local>

* feat(backend, mock-ase): rename payment pointer to wallet address in rafiki code (#2029)

* fix(backend): rename paymentPointerId column in combinedPaymentsView to walletAddressId (#2043)

* docs: replace payment pointer with wallet address (#1951)

* feat(backend): remove connections route (#1940) (#2051)

Co-authored-by: Ömer Talha Özdemir <omer@fynbos.dev>

* feat(backend): unauthenticated get incoming payment (#1952) (#2052)

Co-authored-by: Ömer Talha Özdemir <omer@fynbos.dev>
Co-authored-by: Blair Currey <12960453+BlairCurrey@users.noreply.github.com>

* feat(auth): fix auth tests for access tokens (#2053)

* feat(backend): remove payment pointer from url, retrieve it from request query or body (#2042)

* refactor(backend): swap connection for methods (#2054)

Co-authored-by: Nathan Lie <lie4nathan@gmail.com>

* fix(backend): resolve breaking build after main rebase (#2085)

* fix(backend): combined_payment, ilp service tests (#2094)

* fix(backend): combined_payment, ilp service tests

* chore(backend): format

* fix(backend): bad test refactor

* fix(postman): invalid json (#2096)

* fix: fetch walletAddress graph in quote and outgoing payment service (#2099)

* fix(postman): env var usage (#2107)

* feat(backend): add quotes route to exceptions in wallet address middleware (#2108)

* chore: formatting

* fix(backend): fix GET /incoming-payments (#2111)

* fix(backend): remove wallet address from OP response id and fix receiver service (#2115)

* fix: remove wallet address from op resource urls

* feat: return auth server url in public incoming payment and fix receiver service

* fix: quote issue

* fix: walletAddress middleware

* chore: update postman

* fix: listing

* chore: remove console.log

* fix: progress towards making listing work

* fix(backend): fix create remote incoming payment (#2121)

* fix(postman): misc postman fixes

* fix(postman): complete incoming payment (#2126)

* fix: file name correction (#2127)

* fix: GET resource lists, use op client (#2122)

* fix(postman): update list urls

* fix(openapi): rm defaults for first, last

* refactor(postman): query param order for readability

* fix(backend): update to new open-payments pkgs

* fix(backend): use op client to get authServer

* fix(backend): rm old code

* fix(backend): receiver tests

* chore: cleanup

* feat: make list query parameter configurable

* chore: update OP package and fix types

---------

Co-authored-by: Sabine Schaller <sabine@interledger.org>

* fix(postman): additional fixes

* fix: wallet address on the fly creation (#2129)

* chore: update postman environments

* Postman: update description for P2P example

* Postman: Remove finalizationReason from getGrants API + fix createWalletAddress

* chore: bump open-payments package in auth

* chore: update last few remaining mentions of payment pointers

* chore(postman): remove references to payment pointer

* chore: update another reference to pp

---------

Co-authored-by: Nathan Lie <nathanlie@Nathans-MacBook-Pro.local>
Co-authored-by: Ömer Talha Özdemir <omer@fynbos.dev>
Co-authored-by: Blair Currey <12960453+BlairCurrey@users.noreply.github.com>
Co-authored-by: Sabine Schaller <sabine@interledger.org>
Co-authored-by: Sarah Jones <sarah38186@gmail.com>
Co-authored-by: Max Kurapov <maxkurapov@gmail.com>
Co-authored-by: Max Kurapov <max@interledger.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: backend Changes in the backend package. type: source Changes business logic type: tests Testing related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants