Skip to content

Commit

Permalink
feat(open-payments): adding open-payments package (#669)
Browse files Browse the repository at this point in the history
* feat(open-payments-client): initial POC of open-payments-client

* feat(open-payments-client): cleanup

* feat(open-payments): remove open-payments-client folder

* feat(open-payments): make open-payments folder and use script for type generation

* feat(open-payments): fix rootDir

* feat(open-payments): downgrading generation lib, updating how script is ran

* feat(open-payments): update default config usage

* feat(open-payments): update pnpm-lock.yaml

* feat(open-payments): update pnpm-lock.yaml

* feat(open-payments): adding tests

* feat(open-payments): update pnpm-lock.yaml

* feat(open-payments): simplify test

* feat(open-payments): updating workflows

* feat(open-payments): pin the open api spec to the most recent commit

* feat(open-payments): use updated RS spec

* feat(open-payments): building open-api package during workflow

* Revert "feat(open-payments): building open-api package during workflow"

This reverts commit e11ec65.
  • Loading branch information
mkurapov authored and omertoast committed Oct 28, 2022
1 parent d7de2c4 commit c2364e1
Show file tree
Hide file tree
Showing 13 changed files with 1,214 additions and 25 deletions.
2 changes: 2 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
'pkg: auth': packages/auth/**/*
'pkg: openapi': packages/openapi/**/*
'pkg: map': packages/mock-account-provider/**/*
'pkg: open-payments': packages/open-payments/**/*

# Add 'type: documentation' label to any change to *.md files
'type: ci':
Expand All @@ -22,6 +23,7 @@
- packages/frontend/src/**/*
- packages/auth/src/**/*
- packages/openapi/src/**/*
- packages/open-payments/src/**/*

# Add 'type: tests' label to any change to *.test.ts files
'type: tests': packages/**/*.test.ts
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/lint_test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ jobs:
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter openapi test

open-payments:
runs-on: ubuntu-latest
needs: checkout
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter open-payments test

build:
runs-on: ubuntu-latest
timeout-minutes: 5
Expand All @@ -65,6 +74,7 @@ jobs:
- frontend
- auth
- openapi
- open-payments
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/rafiki/env-setup
Expand Down
17 changes: 17 additions & 0 deletions packages/open-payments/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const baseConfig = require('../../jest.config.base.js')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const packageName = require('./package.json').name

module.exports = {
...baseConfig,
clearMocks: true,
roots: [`<rootDir>/packages/${packageName}`],
testRegex: `(packages/${packageName}/.*/__tests__/.*|\\.(test|spec))\\.tsx?$`,
moduleDirectories: [`node_modules`, `packages/${packageName}/node_modules`],
modulePaths: [`<rootDir>/packages/${packageName}/src/`],
id: packageName,
displayName: packageName,
rootDir: '../..'
}
26 changes: 26 additions & 0 deletions packages/open-payments/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "open-payments",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist/**/*"
],
"scripts": {
"build": "pnpm clean && tsc --build tsconfig.json",
"clean": "rm -fr dist/",
"generate:types": "npx ts-node scripts/generate-types.ts",
"prepack": "pnpm build",
"test": "jest --passWithNoTests"
},
"devDependencies": {
"@types/node": "^18.7.12",
"nock": "^13.2.9",
"openapi-typescript": "^4.5.0",
"ts-node": "^10.7.0",
"typescript": "^4.3.0"
},
"dependencies": {
"axios": "^1.1.2"
}
}
19 changes: 19 additions & 0 deletions packages/open-payments/scripts/generate-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import fs from 'fs'
import openapiTS from 'openapi-typescript'
import config from '../src/config'
;(async () => {
try {
const output = await openapiTS(config.OPEN_PAYMENTS_OPEN_API_URL)
const fileName = 'src/generated/types.ts'

fs.writeFile(fileName, output, (error) => {
if (error) {
console.log(`Error when writing types to ${fileName}`, { error })
}
})
} catch (error) {
console.log('Error when generating types', {
error
})
}
})()
67 changes: 67 additions & 0 deletions packages/open-payments/src/client.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { createAxiosInstance, get } from './client'
import nock from 'nock'

describe('open-payments', (): void => {
describe('createAxiosInstance', (): void => {
test('sets timeout properly', async (): Promise<void> => {
expect(createAxiosInstance({ timeout: 1000 }).defaults.timeout).toBe(1000)
})
test('sets Content-Type header properly', async (): Promise<void> => {
expect(
createAxiosInstance().defaults.headers.common['Content-Type']
).toBe('application/json')
})
})

describe('get', (): void => {
const axiosInstance = createAxiosInstance()
const baseUrl = 'http://localhost:1000'

beforeEach(() => {
jest.spyOn(axiosInstance, 'get')
})

test('sets headers properly if accessToken provided', async (): Promise<void> => {
nock(baseUrl)
.get('/incoming-payment')
.reply(200, () => ({
validReceiver: 0
}))

await get(axiosInstance, {
url: `${baseUrl}/incoming-payment`,
accessToken: 'accessToken'
})

expect(axiosInstance.get).toHaveBeenCalledWith(
`${baseUrl}/incoming-payment`,
{
headers: {
Authorization: 'GNAP accessToken',
Signature: 'TODO',
'Signature-Input': 'TODO'
}
}
)
})

test('sets headers properly if accessToken is not provided', async (): Promise<void> => {
nock(baseUrl)
.get('/incoming-payment')
.reply(200, () => ({
validReceiver: 0
}))

await get(axiosInstance, {
url: `${baseUrl}/incoming-payment`
})

expect(axiosInstance.get).toHaveBeenCalledWith(
`${baseUrl}/incoming-payment`,
{
headers: {}
}
)
})
})
})
67 changes: 67 additions & 0 deletions packages/open-payments/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { ILPStreamConnection, IncomingPayment } from './types'
import axios, { AxiosInstance } from 'axios'
import config from './config'

interface CreateOpenPaymentClientArgs {
timeout?: number
}

interface GetArgs {
url: string
accessToken?: string
}

export interface OpenPaymentsClient {
incomingPayment: {
get(args: GetArgs): Promise<IncomingPayment>
}
ilpStreamConnection: {
get(args: GetArgs): Promise<ILPStreamConnection>
}
}

export const get = async <T>(
axios: AxiosInstance,
args: GetArgs
): Promise<T> => {
const { url, accessToken } = args

const { data } = await axios.get(url, {
headers: accessToken
? {
Authorization: `GNAP ${accessToken}`,
Signature: 'TODO',
'Signature-Input': 'TODO'
}
: {}
})

return data
}

export const createAxiosInstance = (
args?: CreateOpenPaymentClientArgs
): AxiosInstance => {
const axiosInstance = axios.create({
timeout: args?.timeout ?? config.DEFAULT_REQUEST_TIMEOUT
})

axiosInstance.defaults.headers.common['Content-Type'] = 'application/json'

return axiosInstance
}

export const createClient = (
args?: CreateOpenPaymentClientArgs
): OpenPaymentsClient => {
const axios = createAxiosInstance(args)

return {
incomingPayment: {
get: (args: GetArgs) => get<IncomingPayment>(axios, args)
},
ilpStreamConnection: {
get: (args: GetArgs) => get<ILPStreamConnection>(axios, args)
}
}
}
5 changes: 5 additions & 0 deletions packages/open-payments/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
OPEN_PAYMENTS_OPEN_API_URL:
'https://raw.githubusercontent.com/interledger/open-payments/7bb2e6a03d7dfe7ecb0553afb6c70741317bb489/openapi/RS/openapi.yaml',
DEFAULT_REQUEST_TIMEOUT: 3_000
}
Loading

0 comments on commit c2364e1

Please sign in to comment.