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 properties for quoting #275

Merged
merged 15 commits into from
Sep 6, 2023
5 changes: 5 additions & 0 deletions .changeset/tender-ravens-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@interledger/open-payments': major
---

Adding properties for new quoting mechanism
14 changes: 8 additions & 6 deletions openapi/auth-server.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.1.0
info:
title: Open Payments Authorization Server
version: '1.0'
version: '1.1'
license:
name: Apache 2.0
identifier: Apache-2.0
Expand Down Expand Up @@ -112,7 +112,7 @@ paths:
limits:
receiver: 'https://openpayments.guide/connections/45a0d0ee-26dc-4c66-89e0-01fbf93156f7'
interval: 'R12/2019-08-24T14:15:22Z/P1M'
sendAmount:
debitAmount:
value: '500'
assetCode: USD
assetScale: 2
Expand Down Expand Up @@ -180,7 +180,7 @@ paths:
limits:
receiver: 'https://openpayments.guide/bob/incoming-payments/48884225-b393-4872-90de-1b737e2491c2'
interval: 'R12/2019-08-24T14:15:22Z/P1M'
sendAmount:
debitAmount:
value: '500'
assetCode: USD
assetScale: 2
Expand Down Expand Up @@ -275,7 +275,7 @@ paths:
limits:
interval: 'R12/2019-08-24T14:15:22Z/P1M'
receiver: 'https://openpayments.guide/bob/incoming-payments/48884225-b393-4872-90de-1b737e2491c2'
sendAmount:
debitAmount:
value: '500'
assetCode: USD
assetScale: 2
Expand Down Expand Up @@ -515,9 +515,11 @@ components:
properties:
receiver:
$ref: './schemas.yaml#/components/schemas/receiver'
sendAmount:
debitAmount:
description: 'All amounts are maxima, i.e. multiple payments can be created under a grant as long as the total amounts of these payments do not exceed the maximum amount per interval as specified in the grant.'
$ref: './schemas.yaml#/components/schemas/amount'
receiveAmount:
description: 'All amounts are maxima, i.e. multiple payments can be created under a grant as long as the total amounts of these payments do not exceed the maximum amount per interval as specified in the grant.'
$ref: './schemas.yaml#/components/schemas/amount'
interval:
$ref: '#/components/schemas/interval'
Expand All @@ -526,7 +528,7 @@ components:
required:
- interval
- required:
- sendAmount
- debitAmount
- required:
- receiveAmount
securitySchemes:
Expand Down
199 changes: 88 additions & 111 deletions openapi/resource-server.yaml

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion openapi/schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ components:
amount:
title: amount
type: object
description: 'All amounts are maxima, i.e. multiple payments can be created under a grant as long as the total amounts of these payments do not exceed the maximum amount per interval as specified in the grant.'
properties:
value:
type: string
Expand Down
14 changes: 7 additions & 7 deletions packages/open-payments/src/client/outgoing-payment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('outgoing-payment', (): void => {

test('throws if outgoing payment does not pass validation', async (): Promise<void> => {
const outgoingPayment = mockOutgoingPayment({
sendAmount: {
debitAmount: {
assetCode: 'USD',
assetScale: 3,
value: '5'
Expand Down Expand Up @@ -194,7 +194,7 @@ describe('outgoing-payment', (): void => {

test('throws if an outgoing payment does not pass validation', async (): Promise<void> => {
const invalidOutgoingPayment = mockOutgoingPayment({
sendAmount: {
debitAmount: {
assetCode: 'CAD',
assetScale: 2,
value: '5'
Expand Down Expand Up @@ -291,7 +291,7 @@ describe('outgoing-payment', (): void => {

test('throws if outgoing payment does not pass validation', async (): Promise<void> => {
const outgoingPayment = mockOutgoingPayment({
sendAmount: {
debitAmount: {
assetCode: 'USD',
assetScale: 3,
value: '5'
Expand Down Expand Up @@ -361,7 +361,7 @@ describe('outgoing-payment', (): void => {

test('throws if send amount and sent amount asset scales are different', async (): Promise<void> => {
const outgoingPayment = mockOutgoingPayment({
sendAmount: {
debitAmount: {
assetCode: 'USD',
assetScale: 3,
value: '5'
Expand All @@ -380,7 +380,7 @@ describe('outgoing-payment', (): void => {

test('throws if send amount and sent amount asset codes are different', async (): Promise<void> => {
const outgoingPayment = mockOutgoingPayment({
sendAmount: {
debitAmount: {
assetCode: 'CAD',
assetScale: 2,
value: '5'
Expand All @@ -399,7 +399,7 @@ describe('outgoing-payment', (): void => {

test('throws if sent amount is larger than send amount', async (): Promise<void> => {
const outgoingPayment = mockOutgoingPayment({
sendAmount: {
debitAmount: {
assetCode: 'USD',
assetScale: 2,
value: '5'
Expand All @@ -418,7 +418,7 @@ describe('outgoing-payment', (): void => {

test('throws if sent amount equals send amount, but payment has failed', async (): Promise<void> => {
const outgoingPayment = mockOutgoingPayment({
sendAmount: {
debitAmount: {
assetCode: 'USD',
assetScale: 2,
value: '5'
Expand Down
10 changes: 5 additions & 5 deletions packages/open-payments/src/client/outgoing-payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,19 @@ export const listOutgoingPayments = async (
export const validateOutgoingPayment = (
payment: OutgoingPayment
): OutgoingPayment => {
const { sendAmount, sentAmount } = payment
const { debitAmount, sentAmount } = payment
if (
sendAmount.assetCode !== sentAmount.assetCode ||
sendAmount.assetScale !== sentAmount.assetScale
debitAmount.assetCode !== sentAmount.assetCode ||
debitAmount.assetScale !== sentAmount.assetScale
) {
throw new Error(
'Asset code or asset scale of sending amount does not match sent amount'
)
}
if (BigInt(sendAmount.value) < BigInt(sentAmount.value)) {
if (BigInt(debitAmount.value) < BigInt(sentAmount.value)) {
throw new Error('Amount sent is larger than maximum amount to send')
}
if (sendAmount.value === sentAmount.value && payment.failed) {
if (debitAmount.value === sentAmount.value && payment.failed) {
throw new Error('Amount to send matches sent amount but payment failed')
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ export interface components {
*/
"limits-outgoing": Partial<unknown> & {
receiver?: external["schemas.yaml"]["components"]["schemas"]["receiver"];
sendAmount?: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description All amounts are maxima, i.e. multiple payments can be created under a grant as long as the total amounts of these payments do not exceed the maximum amount per interval as specified in the grant. */
debitAmount?: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description All amounts are maxima, i.e. multiple payments can be created under a grant as long as the total amounts of these payments do not exceed the maximum amount per interval as specified in the grant. */
receiveAmount?: external["schemas.yaml"]["components"]["schemas"]["amount"];
interval?: components["schemas"]["interval"];
};
Expand Down Expand Up @@ -312,10 +314,7 @@ export interface external {
paths: {};
components: {
schemas: {
/**
* amount
* @description All amounts are maxima, i.e. multiple payments can be created under a grant as long as the total amounts of these payments do not exceed the maximum amount per interval as specified in the grant.
*/
/** amount */
amount: {
/**
* Format: uint64
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ export interface components {
receiver: external["schemas.yaml"]["components"]["schemas"]["receiver"];
/** @description The total amount that should be received by the receiver when this outgoing payment has been paid. */
receiveAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description The total amount that should be sent when this outgoing payment has been paid. */
sendAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description The total amount that should be deducted from the sender's account when this outgoing payment has been paid. */
debitAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description The total amount that has been sent under this outgoing payment. */
sentAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description Additional metadata associated with the outgoing payment. (Optional) */
Expand Down Expand Up @@ -277,10 +277,13 @@ export interface components {
* @description The URL of the payment pointer from which this quote's payment would be sent.
*/
paymentPointer: string;
/** @description The URL of the incoming payment or ILP STREAM Connection that the quote is created for. */
receiver: external["schemas.yaml"]["components"]["schemas"]["receiver"];
/** @description The total amount that should be received by the receiver when the corresponding outgoing payment has been paid. */
receiveAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
sendAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description The date and time when the calculated `sendAmount` is no longer valid. */
/** @description The total amount that should be deducted from the sender's account when the corresponding outgoing payment has been paid. */
debitAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
/** @description The date and time when the calculated `debitAmount` is no longer valid. */
expiresAt?: string;
/**
* Format: date-time
Expand Down Expand Up @@ -539,7 +542,7 @@ export interface operations {
/**
* A subset of the outgoing payments schema is accepted as input to create a new outgoing payment.
*
* The `sendAmount` must use the same `assetCode` and `assetScale` as the payment pointer.
* The `debitAmount` must use the same `assetCode` and `assetScale` as the payment pointer.
*/
requestBody: {
content: {
Expand Down Expand Up @@ -580,7 +583,7 @@ export interface operations {
/**
* A subset of the quotes schema is accepted as input to create a new quote.
*
* The quote must be created with a (`sendAmount` xor `receiveAmount`) unless the `receiver` is an Incoming Payment which has an `incomingAmount`.
* The quote must be created with a (`debitAmount` xor `receiveAmount`) unless the `receiver` is an Incoming Payment which has an `incomingAmount`.
*/
requestBody: {
content: {
Expand All @@ -596,7 +599,7 @@ export interface operations {
| {
receiver: external["schemas.yaml"]["components"]["schemas"]["receiver"];
/** @description The fixed amount that would be sent from the sending payment pointer given a successful outgoing payment. */
sendAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
debitAmount: external["schemas.yaml"]["components"]["schemas"]["amount"];
};
};
};
Expand Down Expand Up @@ -720,10 +723,7 @@ export interface external {
paths: {};
components: {
schemas: {
/**
* amount
* @description All amounts are maxima, i.e. multiple payments can be created under a grant as long as the total amounts of these payments do not exceed the maximum amount per interval as specified in the grant.
*/
/** amount */
amount: {
/**
* Format: uint64
Expand Down
4 changes: 2 additions & 2 deletions packages/open-payments/src/test/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export const mockOutgoingPayment = (
id: `https://example.com/.well-known/pay/outgoing-payments/${uuid()}`,
paymentPointer: 'https://example.com/.well-known/pay',
failed: false,
sendAmount: {
debitAmount: {
assetCode: 'USD',
assetScale: 2,
value: '10'
Expand Down Expand Up @@ -286,7 +286,7 @@ export const mockQuote = (overrides?: Partial<Quote>): Quote => ({
id: `https://example.com/.well-known/pay/quotes/${uuid()}`,
receiver: 'https://example.com/.well-known/peer',
paymentPointer: 'https://example.com/.well-known/pay',
sendAmount: {
debitAmount: {
value: '100',
assetCode: 'USD',
assetScale: 2
Expand Down
8 changes: 4 additions & 4 deletions packages/open-payments/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ export type Quote = RSComponents['schemas']['quote']
type QuoteArgsBase = {
receiver: RSOperations['create-quote']['requestBody']['content']['application/json']['receiver']
}
type QuoteArgsWithSendAmount = QuoteArgsBase & {
sendAmount?: RSComponents['schemas']['quote']['sendAmount']
type QuoteArgsWithDebitAmount = QuoteArgsBase & {
debitAmount?: RSComponents['schemas']['quote']['debitAmount']
receiveAmount?: never
}
type QuoteArgsWithReceiveAmount = QuoteArgsBase & {
sendAmount?: never
debitAmount?: never
receiveAmount?: RSComponents['schemas']['quote']['receiveAmount']
}
export type CreateQuoteArgs =
| QuoteArgsWithSendAmount
| QuoteArgsWithDebitAmount
| QuoteArgsWithReceiveAmount

export const getASPath = <P extends keyof ASPaths>(path: P): string =>
Expand Down