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

663/mk/use open payments client #706

Merged
merged 69 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
d3470c4
feat(open-payments-client): initial POC of open-payments-client
mkurapov Oct 12, 2022
7f968c3
feat(open-payments-client): cleanup
mkurapov Oct 12, 2022
79e7cd7
feat(open-payments): remove open-payments-client folder
mkurapov Oct 13, 2022
32e2a31
feat(open-payments): make open-payments folder and use script for typ…
mkurapov Oct 13, 2022
050ebef
feat(open-payments): fix rootDir
mkurapov Oct 13, 2022
9893029
feat(open-payments): downgrading generation lib, updating how script …
mkurapov Oct 14, 2022
c15fdbc
feat(open-payments): update default config usage
mkurapov Oct 14, 2022
130e310
feat(open-payments): update pnpm-lock.yaml
mkurapov Oct 14, 2022
e067011
feat(open-payments): update pnpm-lock.yaml
mkurapov Oct 14, 2022
dc28878
feat(open-payments): adding tests
mkurapov Oct 14, 2022
39b561b
feat(open-payments): update pnpm-lock.yaml
mkurapov Oct 14, 2022
9393e47
feat(open-payments): simplify test
mkurapov Oct 14, 2022
3c3a0b7
feat(open-payments): updating workflows
mkurapov Oct 14, 2022
120dcae
feat(open-payments): pin the open api spec to the most recent commit
mkurapov Oct 14, 2022
80d9856
feat(open-payments): adding openapi validation
mkurapov Oct 18, 2022
218f1f0
feat(open-payments): adding openapi validation
mkurapov Oct 18, 2022
d7c203c
feat(open-payments): adding tests
mkurapov Oct 18, 2022
dfc07cb
feat(open-payments): correcting test
mkurapov Oct 18, 2022
d59c2ea
Merge branch 'main' into 663/mk/open-payments-validate
mkurapov Oct 21, 2022
bc0ea85
feat(backend): import open-payments package
mkurapov Oct 21, 2022
43335f6
feat(open-payments): use updated RS spec
mkurapov Oct 21, 2022
723de2f
Merge branch '663/mk/op-client-1' into 663/mk/open-payments-validate
mkurapov Oct 21, 2022
02b8f9f
Merge branch 'main' into 663/mk/open-payments-validate
mkurapov Oct 24, 2022
c111b4c
Merge branch 'main' into 663/mk/use-open-payments-client
mkurapov Oct 24, 2022
b7e1282
feat(open-payments): build open api package on build step
mkurapov Oct 24, 2022
f8c1846
feat(open-payments): build open api package on build step
mkurapov Oct 24, 2022
f560c79
Merge branch 'main' into 663/mk/op-client-1
mkurapov Oct 24, 2022
e11ec65
feat(open-payments): building open-api package during workflow
mkurapov Oct 24, 2022
0dad54d
Revert "feat(open-payments): building open-api package during workflow"
mkurapov Oct 24, 2022
000fc9b
Merge branch '663/mk/op-client-1' into 663/mk/open-payments-validate
mkurapov Oct 24, 2022
25d2617
feat(open-payments): building open-api package during workflow
mkurapov Oct 24, 2022
f734dff
Merge branch 'main' into 663/mk/open-payments-validate
mkurapov Oct 24, 2022
4552188
feat(open-payments): update naming
mkurapov Oct 24, 2022
85db136
feat(open-payments): instantiate validator functions once
mkurapov Oct 25, 2022
dc4aa0f
chore(openapi): add docs for usage
mkurapov Oct 25, 2022
c927291
chore(openapi): update docs
mkurapov Oct 25, 2022
3ed946b
chore(openapi): prettify docs
mkurapov Oct 25, 2022
347075a
chore(openapi): update docs
mkurapov Oct 25, 2022
90bc6b0
feat(open-payments): adding logger as dependency
mkurapov Oct 25, 2022
3129f2a
feat(open-payments): updating logging & error logic
mkurapov Oct 25, 2022
05b6cfb
feat(open-payments): remove unnecessary imports
mkurapov Oct 25, 2022
f1d2412
Merge branch 'main' into 663/mk/open-payments-validate
mkurapov Oct 25, 2022
f6eb6a8
feat(open-payments): update error handling & test
mkurapov Oct 25, 2022
f18cc2d
Merge branch '663/mk/open-payments-validate' into 663/mk/use-open-pay…
mkurapov Oct 25, 2022
9b3de72
Merge branch 'main' into 663/mk/use-open-payments-client
mkurapov Oct 25, 2022
3306129
feat(backend): wip receiver service
mkurapov Oct 26, 2022
9535ee2
feat(backend): adding open-payments as a build dependency
mkurapov Oct 26, 2022
bcda9c8
feat(backend): organizing models, and adding receiver service logic
mkurapov Oct 26, 2022
ad74758
feat(backend): start using receiver service
mkurapov Oct 26, 2022
df3bcf4
feat(backend): start using receiver service
mkurapov Oct 26, 2022
d950377
Merge branch 'main' into 663/mk/use-open-payments-client
mkurapov Oct 28, 2022
eaa4e87
feat(backend): add open-payments build as a test workflow step
mkurapov Oct 28, 2022
6c65e96
feat(backend): add initial test for receiver service
mkurapov Oct 28, 2022
d997e79
feat(backend): update ilpStreamConnection fetch
mkurapov Oct 28, 2022
9d726d9
Merge branch 'main' into 663/mk/use-open-payments-client
mkurapov Oct 31, 2022
2a8cbe9
feat(backend): removing incoming payment validation from receiver ser…
mkurapov Nov 1, 2022
6ea7205
feat(backend): start of receiver service tests
mkurapov Nov 1, 2022
042c8fd
feat(backend): adding logs in service
mkurapov Nov 2, 2022
08c2708
feat(backend): adding tests for service
mkurapov Nov 2, 2022
691a95e
feat(backend): updating methods for models
mkurapov Nov 2, 2022
581d7f7
feat(backend): updating logic for receiver model, adding tests
mkurapov Nov 2, 2022
acba42e
feat(backend): remove log from test
mkurapov Nov 2, 2022
fbdcb48
Merge branch 'main' into 663/mk/use-open-payments-client
mkurapov Nov 2, 2022
e9b41c4
feat(backend): remove type assertion in model
mkurapov Nov 2, 2022
39ebc2b
feat(backend): remove openPaymentsClientService
mkurapov Nov 2, 2022
1bebc31
feat(backend): merge in expiresAt addition
mkurapov Nov 2, 2022
d277827
chore(backend): update order of tsc building
mkurapov Nov 2, 2022
d51d3d2
feat(backend): remove jest-koa-mocks package
mkurapov Nov 4, 2022
f3558d8
feat(backend): address feedback, add tests
mkurapov Nov 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/lint_test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter openapi build
- run: pnpm --filter auth build
- run: pnpm --filter open-payments build
- run: pnpm --filter backend test

frontend:
Expand Down
3 changes: 2 additions & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"test": "jest --passWithNoTests --maxWorkers=50%",
"knex": "knex",
"generate": "graphql-codegen --config codegen.yml",
"build:deps": "pnpm --filter openapi build && pnpm --filter auth build",
"build:deps": "pnpm --filter openapi build && pnpm --filter auth build && pnpm --filter open-payments build",
"build": "pnpm build:deps && tsc --build tsconfig.json && pnpm copy-files",
"clean": "rm -fr dist/",
"copy-files": "cp src/graphql/schema.graphql dist/graphql/",
Expand Down Expand Up @@ -82,6 +82,7 @@
"objection-db-errors": "^1.1.2",
"oer-utils": "5.1.3-alpha.1",
"openapi": "workspace:../openapi",
"open-payments": "workspace:../open-payments",
"pg": "^8.6.0",
"pino": "^8.4.2",
"pino-pretty": "^9.0.1",
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { createValidatorMiddleware, HttpMethod, isHttpMethod } from 'openapi'
import { ClientKeysService } from './clientKeys/service'
import { ClientService } from './clients/service'
import { GrantReferenceService } from './open_payments/grantReference/service'
import { OpenPaymentsClient } from 'open-payments'

export interface AppContextData {
logger: Logger
Expand Down Expand Up @@ -154,6 +155,7 @@ export interface AppServices {
clientService: Promise<ClientService>
clientKeysService: Promise<ClientKeysService>
grantReferenceService: Promise<GrantReferenceService>
openPaymentsClient: Promise<OpenPaymentsClient>
}

export type AppContainer = IocContract<AppServices>
Expand Down
23 changes: 21 additions & 2 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ import { createConnectorService } from './connector'
import { createSessionService } from './session/service'
import { createApiKeyService } from './apiKey/service'
import { createOpenAPI } from 'openapi'
import { createClient as createOpenPaymentsClient } from 'open-payments'
import { createConnectionService } from './open_payments/connection/service'
import { createConnectionRoutes } from './open_payments/connection/routes'
import { createClientKeysService } from './clientKeys/service'
import { createClientService } from './clients/service'
import { createGrantReferenceService } from './open_payments/grantReference/service'
import { createReceiverService } from './open_payments/receiver/service'

BigInt.prototype.toJSON = function () {
return this.toString()
Expand Down Expand Up @@ -113,6 +115,10 @@ export function initIocContainer(
const config = await deps.use('config')
return await createOpenAPI(config.authServerSpec)
})
container.singleton('openPaymentsClient', async (deps) => {
const logger = await deps.use('logger')
return createOpenPaymentsClient({ logger })
Copy link
Contributor

Choose a reason for hiding this comment

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

Depending on how #722 shapes up, this might also take config.privateKey + a key id

})

/**
* Add services to the container.
Expand Down Expand Up @@ -229,6 +235,19 @@ export function initIocContainer(
connectionService: await deps.use('connectionService')
})
})
container.singleton('receiverService', async (deps) => {
const config = await deps.use('config')
return await createReceiverService({
logger: await deps.use('logger'),
// TODO: https://github.com/interledger/rafiki/issues/583
accessToken: config.devAccessToken,
connectionService: await deps.use('connectionService'),
incomingPaymentService: await deps.use('incomingPaymentService'),
openPaymentsUrl: config.openPaymentsUrl,
paymentPointerService: await deps.use('paymentPointerService'),
openPaymentsClient: await deps.use('openPaymentsClient')
})
})
container.singleton('openPaymentsClientService', async (deps) => {
const config = await deps.use('config')
return await createOpenPaymentsClientService({
Expand Down Expand Up @@ -288,7 +307,7 @@ export function initIocContainer(
logger: await deps.use('logger'),
knex: await deps.use('knex'),
makeIlpPlugin: await deps.use('makeIlpPlugin'),
clientService: await deps.use('openPaymentsClientService'),
receiverService: await deps.use('receiverService'),
paymentPointerService: await deps.use('paymentPointerService'),
ratesService: await deps.use('ratesService')
})
Expand All @@ -308,7 +327,7 @@ export function initIocContainer(
logger: await deps.use('logger'),
knex: await deps.use('knex'),
accountingService: await deps.use('accountingService'),
clientService: await deps.use('openPaymentsClientService'),
receiverService: await deps.use('receiverService'),
grantReferenceService: await deps.use('grantReferenceService'),
makeIlpPlugin: await deps.use('makeIlpPlugin'),
peerService: await deps.use('peerService')
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/open_payments/client/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { URL } from 'url'

import { Amount, parseAmount } from '../amount'
import { ConnectionRoutes } from '../connection/routes'
import { ConnectionBase, ConnectionJSON } from '../connection/service'
import { ConnectionBase, ConnectionJSON } from '../connection/model'
import { IncomingPaymentJSON } from '../payment/incoming/model'
import { IncomingPaymentRoutes } from '../payment/incoming/routes'
import { PaymentPointerService } from '../payment_pointer/service'
Expand Down
74 changes: 74 additions & 0 deletions packages/backend/src/open_payments/connection/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { StreamCredentials } from '@interledger/stream-receiver'
import base64url from 'base64url'
import { IlpAddress } from 'ilp-packet'
import { ILPStreamConnection } from 'open-payments'
import { IncomingPayment } from '../payment/incoming/model'

export type ConnectionJSON = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this still needed because of the IlpAddress type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is still used in the connection routes

Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't necessarily have to happen in this pr, but I think the routes should use generated types from open-payments

id: string
ilpAddress: IlpAddress
sharedSecret: string
assetCode: string
assetScale: number
}

export abstract class ConnectionBase {
protected constructor(
public readonly ilpAddress: IlpAddress,
public readonly sharedSecret: Buffer,
public readonly assetCode: string,
public readonly assetScale: number
) {}
}

export class Connection extends ConnectionBase {
static fromPayment(options: {
payment: IncomingPayment
credentials: StreamCredentials
openPaymentsUrl: string
}): Connection {
return new this(
options.payment.connectionId,
options.openPaymentsUrl,
options.credentials.ilpAddress,
options.credentials.sharedSecret,
options.payment.asset.code,
options.payment.asset.scale
)
}

private constructor(
public readonly id: string,
private readonly openPaymentsUrl: string,
ilpAddress: IlpAddress,
sharedSecret: Buffer,
assetCode: string,
assetScale: number
) {
super(ilpAddress, sharedSecret, assetCode, assetScale)
}

public get url(): string {
return `${this.openPaymentsUrl}/connections/${this.id}`
}

public toJSON(): ConnectionJSON {
return {
id: this.url,
ilpAddress: this.ilpAddress,
sharedSecret: base64url(this.sharedSecret),
assetCode: this.assetCode,
assetScale: this.assetScale
}
}

public toOpenPaymentsType(): ILPStreamConnection {
return {
id: this.url,
ilpAddress: this.ilpAddress,
sharedSecret: base64url(this.sharedSecret),
assetCode: this.assetCode,
assetScale: this.assetScale
}
}
}
64 changes: 2 additions & 62 deletions packages/backend/src/open_payments/connection/service.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,8 @@
import base64url from 'base64url'
import { IlpAddress } from 'ilp-packet'
import { StreamCredentials, StreamServer } from '@interledger/stream-receiver'
import { StreamServer } from '@interledger/stream-receiver'

import { BaseService } from '../../shared/baseService'
import { IncomingPayment } from '../payment/incoming/model'

export type ConnectionJSON = {
id: string
ilpAddress: IlpAddress
sharedSecret: string
assetCode: string
assetScale: number
}

export abstract class ConnectionBase {
protected constructor(
public readonly ilpAddress: IlpAddress,
public readonly sharedSecret: Buffer,
public readonly assetCode: string,
public readonly assetScale: number
) {}
}

export class Connection extends ConnectionBase {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to its own model.ts file

static fromPayment(options: {
payment: IncomingPayment
credentials: StreamCredentials
openPaymentsUrl: string
}): Connection {
return new this(
options.payment.connectionId,
options.openPaymentsUrl,
options.credentials.ilpAddress,
options.credentials.sharedSecret,
options.payment.asset.code,
options.payment.asset.scale
)
}

private constructor(
public readonly id: string,
private readonly openPaymentsUrl: string,
ilpAddress: IlpAddress,
sharedSecret: Buffer,
assetCode: string,
assetScale: number
) {
super(ilpAddress, sharedSecret, assetCode, assetScale)
}

public get url(): string {
return `${this.openPaymentsUrl}/connections/${this.id}`
}

public toJSON(): ConnectionJSON {
return {
id: this.url,
ilpAddress: this.ilpAddress,
sharedSecret: base64url(this.sharedSecret),
assetCode: this.assetCode,
assetScale: this.assetScale
}
}
}
import { Connection } from './model'

export interface ConnectionService {
get(payment: IncomingPayment): Connection | undefined
Expand Down
27 changes: 26 additions & 1 deletion packages/backend/src/open_payments/payment/incoming/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Model, ModelOptions, Pojo, QueryContext } from 'objection'
import { v4 as uuid } from 'uuid'

import { Amount, AmountJSON } from '../../amount'
import { ConnectionJSON } from '../../connection/service'
import { Connection, ConnectionJSON } from '../../connection/model'
import {
PaymentPointer,
PaymentPointerSubresource
Expand All @@ -11,6 +11,7 @@ import { Asset } from '../../../asset/model'
import { LiquidityAccount, OnCreditOptions } from '../../../accounting/service'
import { ConnectorAccount } from '../../../connector/core/rafiki'
import { WebhookEvent } from '../../../webhook/model'
import { IncomingPayment as OpenPaymentsIncomingPayment } from 'open-payments'

export enum IncomingPaymentEventType {
IncomingPaymentExpired = 'incoming_payment.expired',
Expand Down Expand Up @@ -237,6 +238,30 @@ export class IncomingPayment
}
return payment
}

public toOpenPaymentsType({
Copy link
Contributor

Choose a reason for hiding this comment

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

I expect this can replace a number of existing toJSON calls, especially in routes.ts files.

ilpStreamConnection
}: {
ilpStreamConnection: Connection
}): OpenPaymentsIncomingPayment {
return {
id: this.id,
paymentPointer: this.paymentPointer.url,
incomingAmount: {
...this.incomingAmount,
value: this.incomingAmount.value.toString()
},
receivedAmount: {
...this.receivedAmount,
value: this.receivedAmount.value.toString()
},
completed: this.completed,
createdAt: this.createdAt.toISOString(),
updatedAt: this.updatedAt.toISOString(),
expiresAt: this.expiresAt.toISOString(),
ilpStreamConnection: ilpStreamConnection.toOpenPaymentsType()
}
}
}

// TODO: disallow undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import {
} from './errors'
import { AmountJSON, parseAmount } from '../../amount'
import { listSubresource } from '../../payment_pointer/routes'
import { ConnectionJSON, ConnectionService } from '../../connection/service'
import { ConnectionJSON } from '../../connection/model'
import { ConnectionService } from '../../connection/service'

// Don't allow creating an incoming payment too far out. Incoming payments with no payments before they expire are cleaned up, since incoming payments creation is unauthenticated.
// TODO what is a good default value for this?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
PaymentEventType
} from './model'
import { ServiceDependencies } from './service'
import { Receiver } from '../../client/service'
import { Receiver } from '../../receiver/model'
import { IlpPlugin } from '../../../shared/ilp_plugin'

// "payment" is locked by the "deps.knex" transaction.
Expand All @@ -19,7 +19,7 @@ export async function handleSending(
): Promise<void> {
if (!payment.quote) throw LifecycleError.MissingQuote

const receiver = await deps.clientService.receiver.get(payment.receiver)
const receiver = await deps.receiverService.get(payment.receiver)

// TODO: Query Tigerbeetle transfers by code to distinguish sending debits from withdrawals
const amountSent = await deps.accountingService.getTotalSent(payment.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { AccountingService } from '../../../accounting/service'
import { PeerService } from '../../../peer/service'
import { Grant, AccessLimits, getInterval } from '../../auth/grant'
import { OpenPaymentsClientService } from '../../client/service'
import { ReceiverService } from '../../receiver/service'
import { GetOptions, ListOptions } from '../../payment_pointer/model'
import { PaymentPointerSubresourceService } from '../../payment_pointer/service'
import { IlpPlugin, IlpPluginOptions } from '../../../shared/ilp_plugin'
Expand Down Expand Up @@ -43,7 +43,7 @@ export interface OutgoingPaymentService
export interface ServiceDependencies extends BaseService {
knex: TransactionOrKnex
accountingService: AccountingService
clientService: OpenPaymentsClientService
receiverService: ReceiverService
peerService: PeerService
grantReferenceService: GrantReferenceService
makeIlpPlugin: (options: IlpPluginOptions) => IlpPlugin
Expand Down Expand Up @@ -126,7 +126,7 @@ async function createOutgoingPayment(
throw OutgoingPaymentError.InsufficientGrant
}
}
const receiver = await deps.clientService.receiver.get(payment.receiver)
const receiver = await deps.receiverService.get(payment.receiver)
if (!receiver) {
throw OutgoingPaymentError.InvalidQuote
}
Expand Down
7 changes: 4 additions & 3 deletions packages/backend/src/open_payments/quote/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { BaseService } from '../../shared/baseService'
import { QuoteError, isQuoteError } from './errors'
import { Quote } from './model'
import { Amount, parseAmount } from '../amount'
import { OpenPaymentsClientService, Receiver } from '../client/service'
import { ReceiverService } from '../receiver/service'
import { Receiver } from '../receiver/model'
import {
PaymentPointer,
GetOptions,
Expand All @@ -34,7 +35,7 @@ export interface ServiceDependencies extends BaseService {
quoteLifespan: number // milliseconds
signatureSecret?: string
signatureVersion: number
clientService: OpenPaymentsClientService
receiverService: ReceiverService
paymentPointerService: PaymentPointerService
ratesService: RatesService
makeIlpPlugin: (options: IlpPluginOptions) => IlpPlugin
Expand Down Expand Up @@ -167,7 +168,7 @@ export async function resolveReceiver(
deps: ServiceDependencies,
options: CreateQuoteOptions
): Promise<Receiver> {
const receiver = await deps.clientService.receiver.get(options.receiver)
const receiver = await deps.receiverService.get(options.receiver)
if (!receiver) {
throw QuoteError.InvalidReceiver
}
Expand Down
Loading