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

feat: add spent amounts to POST /outgoing-payment #2753

Merged
merged 26 commits into from
Jun 20, 2024

Conversation

BlairCurrey
Copy link
Contributor

@BlairCurrey BlairCurrey commented May 29, 2024

Changes proposed in this pull request

  • adds grantSpentDebitAmount and grantSpentReceiveAmount to outgoing payment create response
  • adds "Web Monetization" example to Bruno collection

Context

#2678

Checklist

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

@github-actions github-actions bot added pkg: backend Changes in the backend package. type: source Changes business logic labels May 29, 2024
Copy link

netlify bot commented May 29, 2024

Deploy Preview for brilliant-pasca-3e80ec canceled.

Name Link
🔨 Latest commit d43dfb0
🔍 Latest deploy log https://app.netlify.com/sites/brilliant-pasca-3e80ec/deploys/667240100a841a0008de9375

@BlairCurrey BlairCurrey changed the title Bc/2678/add spent amounts feat: add spent amounts to POST /outgoing-payment May 29, 2024
@github-actions github-actions bot added the type: tests Testing related label May 29, 2024
Comment on lines 542 to 545
expect(payment.grantSpentReceiveAmount.value).toBe(
// Must account for interledger/pay off-by-one issue (even with 0 slippage/fees)
BigInt((debitAmount.value - BigInt(1)) * BigInt(i))
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

didn't see an issue for this quirk identified in the comment (not sure where we left it) but figured id note why receive amount should be 1 less than the debit amount here

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a feature, not a bug 😆

Copy link
Contributor Author

@BlairCurrey BlairCurrey Jun 4, 2024

Choose a reason for hiding this comment

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

I guess with the consent interaction after this step it's not exactly what the web monetization flow will look like. Otherwise I think it's similar? Not sure if there is a better name for this example but I felt like there were enough changes compared to the Open Payments flow to warrant including this new set of requests.

@github-actions github-actions bot added the pkg: auth Changes in the GNAP auth package. label Jun 4, 2024
workaround for error:
"TypeError: A dynamic import callback was invoked without --experimental-vm-modules"
introduced by new op version
@github-actions github-actions bot removed the pkg: auth Changes in the GNAP auth package. label Jun 6, 2024
@BlairCurrey BlairCurrey marked this pull request as ready for review June 6, 2024 02:05
njlie
njlie previously approved these changes Jun 11, 2024
@@ -16,7 +16,7 @@
"devDependencies": {
"@apollo/client": "^3.10.4",
"@interledger/http-signature-utils": "2.0.2",
"@interledger/open-payments": "^6.11.1",
"@interledger/open-payments": "6.11.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

pinning it just in case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As I recall I did this in the middle of fixing the open payments issue we saw related to the ESM import. I noticed the others were pinned as well so I changed this one but at this point it may not matter.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, they were always pinned. I guess it's ok.

Comment on lines 405 to 406
assetCode: payment.asset.code,
assetScale: payment.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.

I think the received amount should be the asset of the receiver itself, ie. it can be a different asset than the payment. In this case, we should use grant.limits to get this asset information instead.

I think debitAmount should always be the outgoing payment asset, however.

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: fc4adba

I used the paymentLimits (comes from grant.limits) and added some typeguards. Otherwise its a bit tedious to check which of the amounts are defined.

@@ -170,6 +170,7 @@ export async function resolveReceiver(
): Promise<Receiver> {
const receiver = await deps.receiverService.get(options.receiver)
if (!receiver) {
deps.logger.info({ receiver: options.receiver }, 'Receiver not found')
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can add something like "could not create quote" in the log message

Comment on lines 538 to 546
assert.ok(!isOutgoingPaymentError(payment))
expect(payment.grantSpentDebitAmount.value).toBe(
BigInt(debitAmount.value * BigInt(i))
)
expect(payment.grantSpentReceiveAmount.value).toBe(
// Must account for interledger/pay off-by-one issue (even with 0 slippage/fees)
BigInt((debitAmount.value - BigInt(1)) * BigInt(i))
)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe it makes sense to split the test for grantSpentDebitAmount and grantSpentReceiveAmount, since we want to allow a grant to have either or only, not both:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah that does make sense. split

Comment on lines 85 to 86
assetCode: this.asset.code,
assetScale: this.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.

same comment as in the service file. The asset code may be different than the payment itself.

Copy link
Contributor Author

@BlairCurrey BlairCurrey Jun 14, 2024

Choose a reason for hiding this comment

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

I guess this means we dont have any sort of default for the grantSpentReceiveAmount since this depends on being created with a grant limit. So we simply cant return grantSpentReceiveAmount for outgoing payments created in this case.

Maybe that's fine... it just seems incongruent with the grantSpentDebitAmount, which we can return a default value for (0 with outgoing payment's assetCode and assetScale). I guess maybe that's OK, but it seems non-obvious from the caller's perspective.

I guess we could:

  • just leave as-is
  • not return any defualt/null version of grantSpentDebitAmount either
  • return something like {value: 0, assetCode: "", assetScale: -1 } for grantSpentReceiveAmount as a default (and maybe grantSpentDebitAmount as well)

Copy link
Contributor Author

@BlairCurrey BlairCurrey Jun 14, 2024

Choose a reason for hiding this comment

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

or maybe we can get the asset from somewhere other than grant.limits so that we can form it without grant limits...

It's kinda edge-casey so maybe we shouldn't worry about it too much. Im just trying to envision what the most intuitive way to handle it would be. Is it going to be confusing when someone creates an outgoing payment for the first time and sees grantSpentDebitAmount of {0, asset: 'XYZ', scale: '2' } and no grantSpentReceiveAmount?

Copy link
Contributor

Choose a reason for hiding this comment

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

What if instead of storing grantSpentReceiveAmountValue: bigint and grantSpentDebitAmountValue: bigint, we just allow setting the whole Amount? Otherwise if not set, it just gets returned as undefined?

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've changed it set the whole amount locally already so in full agreement there.

After sitting on this for a bit, I think undefined and then not returning them in the /POST /outgoing-payment seems fine. I guess my default expectation is to not include/exclude properties when they're in a sort of null state but in this case I think it may be the most straightforward.

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 to above ^ 710897d

@@ -0,0 +1,33 @@
meta {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm trying to think whether we need a separate folder for this. Technically, we can get a large grant, and then keep re-running the same "Create Outgoing Payment" request. Maybe it's good to have, however, just thinking out loud

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 trying to think whether we need a separate folder for this

In other words, maybe not adding this new "Web Monetization" example?

I mentioned my reasoning a bit in this comment (while questioning the name) #2753 (comment). Basically I didn't find it trivial to alter the existing Open Payments one to do this. It took me some time to put together and I dont even remember all the changes off the top of my head (I would not want to have to re-figure it out). Feel like it could save myself and other some time.

Comment on lines 379 to 385
if (hasDebitAmount(paymentLimits)) {
paymentLimitAmount = paymentLimits.debitAmount
} else if (hasReceiveAmount(paymentLimits)) {
paymentLimitAmount = paymentLimits.receiveAmount
} else {
return { isValid: true }
}
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 we can only do this once

is merged? Since now, we can have both

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 renamed paymentLimit to amountForReceivedAmount but the logic should be the same as it was before. I think the paymentLimit was misleading - it was only being used to get the asset code/scale (per your request to get it from grant limits). I also removed the typeguards (had bigger plans for them originally, but doing nothing compared to paymentLimit.debitAmount etc. checks now).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, looking at it, we can actually do something easier: I think we can use payment.receiveAmount -> that will have the asset code & scale of the receiver (since it uses the quote.receiveAmount) under the hood for it

debitAmount: options.debitAmount,
incomingAmount: receiver.incomingAmount
},
'debitAmount or incomingAmount required'
Copy link
Contributor

Choose a reason for hiding this comment

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

Same thing with "could not create quote"

@@ -16,7 +16,7 @@
"devDependencies": {
"@apollo/client": "^3.10.4",
"@interledger/http-signature-utils": "2.0.2",
"@interledger/open-payments": "^6.11.1",
"@interledger/open-payments": "6.11.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

I see, they were always pinned. I guess it's ok.

Comment on lines 542 to 545
expect(payment.grantSpentReceiveAmount.value).toBe(
// Must account for interledger/pay off-by-one issue (even with 0 slippage/fees)
BigInt((debitAmount.value - BigInt(1)) * BigInt(i))
)
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a feature, not a bug 😆

@mkurapov mkurapov merged commit 2b6f171 into main Jun 20, 2024
42 checks passed
@mkurapov mkurapov deleted the bc/2678/add-spent-amounts branch June 20, 2024 10:27
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.

Return amount spent on the outgoing payment grant during outgoing payment creation
3 participants