diff --git a/localenv/cloud-nine-wallet/docker-compose.yml b/localenv/cloud-nine-wallet/docker-compose.yml index 93aec29a01..9595c89bc6 100644 --- a/localenv/cloud-nine-wallet/docker-compose.yml +++ b/localenv/cloud-nine-wallet/docker-compose.yml @@ -72,8 +72,9 @@ services: EXCHANGE_RATES_URL: http://cloud-nine-wallet/rates REDIS_URL: redis://shared-redis:6379/0 WALLET_ADDRESS_URL: ${CLOUD_NINE_WALLET_ADDRESS_URL:-https://cloud-nine-wallet-backend/.well-known/pay} - ILP_CONNECTOR_ADDRESS: ${CLOUD_NINE_CONNECTOR_URL} - ENABLE_TELEMETRY: false + ILP_CONNECTOR_URL: ${CLOUD_NINE_CONNECTOR_URL} + ENABLE_TELEMETRY: true + KEY_ID: 7097F83B-CB84-469E-96C6-2141C72E22C0 depends_on: - shared-database - shared-redis diff --git a/localenv/happy-life-bank/docker-compose.yml b/localenv/happy-life-bank/docker-compose.yml index 4fb4bb0ef0..20f4e203b0 100644 --- a/localenv/happy-life-bank/docker-compose.yml +++ b/localenv/happy-life-bank/docker-compose.yml @@ -41,6 +41,7 @@ services: ports: - "4000:80" - "4001:3001" + - "4002:3002" - '9231:9229' networks: - rafiki @@ -58,6 +59,7 @@ services: AUTH_SERVER_GRANT_URL: ${HAPPY_LIFE_BANK_AUTH_SERVER_DOMAIN:-http://happy-life-bank-auth:3006} AUTH_SERVER_INTROSPECTION_URL: http://happy-life-bank-auth:3007 ILP_ADDRESS: test.happy-life-bank + ILP_CONNECTOR_URL: http://127.0.0.1:4002 STREAM_SECRET: BjPXtnd00G2mRQwP/8ZpwyZASOch5sUXT5o0iR5b5wU= API_SECRET: iyIgCprjb9uL8wFckR+pLEkJWMB7FJhgkvqhTQR/964= WEBHOOK_URL: http://happy-life-bank/webhooks @@ -65,7 +67,8 @@ services: EXCHANGE_RATES_URL: http://happy-life-bank/rates REDIS_URL: redis://shared-redis:6379/2 WALLET_ADDRESS_URL: ${HAPPY_LIFE_BANK_WALLET_ADDRESS_URL:-https://happy-life-bank-backend/.well-known/pay} - ENABLE_TELEMETRY: false + ENABLE_TELEMETRY: true + KEY_ID: 53f2d913-e98a-40b9-b270-372d0547f23d depends_on: - cloud-nine-backend happy-life-auth: diff --git a/packages/backend/jest.config.js b/packages/backend/jest.config.js index 8f933f9a4c..492a6e5e30 100644 --- a/packages/backend/jest.config.js +++ b/packages/backend/jest.config.js @@ -5,6 +5,17 @@ const baseConfig = require('../../jest.config.base.js') const packageName = require('./package.json').name process.env.LOG_LEVEL = 'silent' +process.env.INSTANCE_NAME = 'Rafiki' +process.env.KEY_ID = 'myKey' +process.env.OPEN_PAYMENTS_URL = 'http://127.0.0.1:3000' +process.env.ILP_CONNECTOR_URL = 'http://127.0.0.1:3002' +process.env.ILP_ADDRESS = 'test.rafiki' +process.env.AUTH_SERVER_GRANT_URL = 'http://127.0.0.1:3006' +process.env.AUTH_SERVER_INTROSPECTION_URL = 'http://127.0.0.1:3007/' +process.env.WEBHOOK_URL = 'http://127.0.0.1:4001/webhook' +process.env.STREAM_SECRET = '2/PxuRFV9PAp0yJlnAifJ+1OxujjjI16lN+DBnLNRLA=' +process.env.USE_TIGERBEETLE = false +process.env.ENABLE_TELEMETRY = false module.exports = { ...baseConfig, diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index a6a2c642c3..149da7190a 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -661,7 +661,7 @@ export class App { router.get( WALLET_ADDRESS_PATH, getWalletAddressUrlFromPath, - createSpspMiddleware(this.config.spspEnabled), + createSpspMiddleware(this.config.enableSpspPaymentPointers), createValidatorMiddleware( walletAddressServerSpec, { diff --git a/packages/backend/src/config/app.ts b/packages/backend/src/config/app.ts index ee2711c931..9e5659115c 100644 --- a/packages/backend/src/config/app.ts +++ b/packages/backend/src/config/app.ts @@ -1,12 +1,15 @@ import { loadOrGenerateKey } from '@interledger/http-signature-utils' -import * as crypto from 'crypto' import dotenv from 'dotenv' import * as fs from 'fs' import { ConnectionOptions } from 'tls' -function envString(name: string, value: string): string { +function envString(name: string, defaultValue?: string): string { const envValue = process.env[name] - return envValue == null ? value : envValue + + if (envValue) return envValue + if (defaultValue) return defaultValue + + throw new Error(`Environment variable ${name} must be set.`) } function envStringArray(name: string, value: string[]): string[] { @@ -35,9 +38,18 @@ dotenv.config({ path: process.env.ENV_FILE || '.env' }) +let privateKeyFileEnv +try { + privateKeyFileEnv = envString('PRIVATE_KEY_FILE') +} catch (err) { + /* empty */ +} + +const privateKeyFileValue = loadOrGenerateKey(privateKeyFileEnv) + export const Config = { logLevel: envString('LOG_LEVEL', 'info'), - enableTelemetry: envBool('ENABLE_TELEMETRY', true), + enableTelemetry: envBool('ENABLE_TELEMETRY', false), livenet: envBool('LIVENET', false), openTelemetryCollectors: envStringArray( 'OPEN_TELEMETRY_COLLECTOR_URLS', @@ -59,7 +71,7 @@ export const Config = { 86_400_000 ), adminPort: envInt('ADMIN_PORT', 3001), - openPaymentsUrl: envString('OPEN_PAYMENTS_URL', 'http://127.0.0.1:3000'), + openPaymentsUrl: envString('OPEN_PAYMENTS_URL'), openPaymentsPort: envInt('OPEN_PAYMENTS_PORT', 3003), connectorPort: envInt('CONNECTOR_PORT', 3002), autoPeeringServerPort: envInt('AUTO_PEERING_SERVER_PORT', 3005), @@ -80,21 +92,15 @@ export const Config = { trustProxy: envBool('TRUST_PROXY', false), redisUrl: envString('REDIS_URL', 'redis://127.0.0.1:6379'), redisTls: parseRedisTlsConfig( - envString('REDIS_TLS_CA_FILE_PATH', ''), - envString('REDIS_TLS_KEY_FILE_PATH', ''), - envString('REDIS_TLS_CERT_FILE_PATH', '') + process.env.REDIS_TLS_CA_FILE_PATH, + process.env.REDIS_TLS_KEY_FILE_PATH, + process.env.REDIS_TLS_CERT_FILE_PATH ), - ilpAddress: envString('ILP_ADDRESS', 'test.rafiki'), - ilpConnectorAddress: envString( - 'ILP_CONNECTOR_ADDRESS', - 'http://127.0.0.1:3002' - ), - instanceName: envString('INSTANCE_NAME', 'Rafiki'), - streamSecret: process.env.STREAM_SECRET - ? Buffer.from(process.env.STREAM_SECRET, 'base64') - : crypto.randomBytes(32), - - useTigerbeetle: envBool('USE_TIGERBEETLE', false), + ilpAddress: envString('ILP_ADDRESS'), + ilpConnectorUrl: envString('ILP_CONNECTOR_URL'), + instanceName: envString('INSTANCE_NAME'), + streamSecret: Buffer.from(process.env.STREAM_SECRET || '', 'base64'), + useTigerbeetle: envBool('USE_TIGERBEETLE', true), tigerbeetleClusterId: envInt('TIGERBEETLE_CLUSTER_ID', 0), tigerbeetleReplicaAddresses: process.env.TIGERBEETLE_REPLICA_ADDRESSES ? process.env.TIGERBEETLE_REPLICA_ADDRESSES.split(',') @@ -109,14 +115,8 @@ export const Config = { walletAddressWorkers: envInt('WALLET_ADDRESS_WORKERS', 1), walletAddressWorkerIdle: envInt('WALLET_ADDRESS_WORKER_IDLE', 200), // milliseconds - authServerGrantUrl: envString( - 'AUTH_SERVER_GRANT_URL', - 'http://127.0.0.1:3006' - ), - authServerIntrospectionUrl: envString( - 'AUTH_SERVER_INTROSPECTION_URL', - 'http://127.0.0.1:3007/' - ), + authServerGrantUrl: envString('AUTH_SERVER_GRANT_URL'), + authServerIntrospectionUrl: envString('AUTH_SERVER_INTROSPECTION_URL'), outgoingPaymentWorkers: envInt('OUTGOING_PAYMENT_WORKERS', 4), outgoingPaymentWorkerIdle: envInt('OUTGOING_PAYMENT_WORKER_IDLE', 200), // milliseconds @@ -126,7 +126,7 @@ export const Config = { webhookWorkers: envInt('WEBHOOK_WORKERS', 1), webhookWorkerIdle: envInt('WEBHOOK_WORKER_IDLE', 200), // milliseconds - webhookUrl: envString('WEBHOOK_URL', 'http://127.0.0.1:4001/webhook'), + webhookUrl: envString('WEBHOOK_URL'), webhookTimeout: envInt('WEBHOOK_TIMEOUT', 2000), // milliseconds webhookMaxRetry: envInt('WEBHOOK_MAX_RETRY', 10), @@ -142,8 +142,8 @@ export const Config = { adminApiSignatureVersion: envInt('API_SIGNATURE_VERSION', 1), adminApiSignatureTtl: envInt('ADMIN_API_SIGNATURE_TTL_SECONDS', 30), - keyId: envString('KEY_ID', 'rafiki'), - privateKey: loadOrGenerateKey(envString('PRIVATE_KEY_FILE', '')), + keyId: envString('KEY_ID'), + privateKey: privateKeyFileValue, graphQLIdempotencyKeyLockMs: envInt('GRAPHQL_IDEMPOTENCY_KEY_LOCK_MS', 2000), graphQLIdempotencyKeyTtlMs: envInt( @@ -166,27 +166,27 @@ export const Config = { 'INCOMING_PAYMENT_EXPIRY_MAX_MS', 2592000000 ), // 30 days - spspEnabled: envBool('ENABLE_SPSP', true) + enableSpspPaymentPointers: envBool('ENABLE_SPSP_PAYMENT_POINTERS', true) } function parseRedisTlsConfig( - caFile: string, - keyFile: string, - certFile: string + caFile?: string, + keyFile?: string, + certFile?: string ): ConnectionOptions | undefined { const options: ConnectionOptions = {} // self-signed certs. - if (caFile !== '') { + if (caFile) { options.ca = fs.readFileSync(caFile) options.rejectUnauthorized = false } - if (certFile !== '') { + if (certFile) { options.cert = fs.readFileSync(certFile) } - if (keyFile !== '') { + if (keyFile) { options.key = fs.readFileSync(keyFile) } diff --git a/packages/backend/src/graphql/resolvers/auto-peering.test.ts b/packages/backend/src/graphql/resolvers/auto-peering.test.ts index 86f0f0a0ad..3a073130d3 100644 --- a/packages/backend/src/graphql/resolvers/auto-peering.test.ts +++ b/packages/backend/src/graphql/resolvers/auto-peering.test.ts @@ -112,7 +112,7 @@ describe('Auto Peering Resolvers', (): void => { const peerDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', name: 'Test Peer', httpToken: 'httpToken' } @@ -137,7 +137,7 @@ describe('Auto Peering Resolvers', (): void => { outgoing: { __typename: 'HttpOutgoing', authToken: expect.any(String), - endpoint: peerDetails.ilpConnectorAddress + endpoint: peerDetails.ilpConnectorUrl } }, maxPacketAmount: input.maxPacketAmount?.toString(), @@ -153,7 +153,7 @@ describe('Auto Peering Resolvers', (): void => { const peerDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', name: 'Test Peer', httpToken: 'httpToken' } @@ -187,7 +187,7 @@ describe('Auto Peering Resolvers', (): void => { outgoing: { __typename: 'HttpOutgoing', authToken: expect.any(String), - endpoint: peerDetails.ilpConnectorAddress + endpoint: peerDetails.ilpConnectorUrl } }, maxPacketAmount: input.maxPacketAmount?.toString(), @@ -221,7 +221,7 @@ describe('Auto Peering Resolvers', (): void => { outgoing: { __typename: 'HttpOutgoing', authToken: expect.any(String), - endpoint: peerDetails.ilpConnectorAddress + endpoint: peerDetails.ilpConnectorUrl } }, maxPacketAmount: secondInput.maxPacketAmount?.toString(), diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 346e9bb277..bf7c82be33 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -511,9 +511,9 @@ export const gracefulShutdown = async ( await redis.quit() redis.disconnect() - const telemetry = await container.use('telemetry') - if (telemetry) { - await telemetry.shutdown() + if (config.enableTelemetry) { + const telemetry = await container.use('telemetry') + telemetry?.shutdown() } } diff --git a/packages/backend/src/payment-method/ilp/auto-peering/routes.test.ts b/packages/backend/src/payment-method/ilp/auto-peering/routes.test.ts index f3bc49b3a9..d861ec8841 100644 --- a/packages/backend/src/payment-method/ilp/auto-peering/routes.test.ts +++ b/packages/backend/src/payment-method/ilp/auto-peering/routes.test.ts @@ -39,7 +39,7 @@ describe('Auto Peering Routes', (): void => { url: `/`, body: { staticIlpAddress: 'test.rafiki-money', - ilpConnectorAddress: 'http://peer.rafiki.money', + ilpConnectorUrl: 'http://peer.rafiki.money', asset: { code: asset.code, scale: asset.scale }, httpToken: 'someHttpToken', maxPacketAmount: 1000, @@ -53,7 +53,7 @@ describe('Auto Peering Routes', (): void => { expect(ctx.status).toBe(200) expect(ctx.body).toEqual({ staticIlpAddress: config.ilpAddress, - ilpConnectorAddress: config.ilpConnectorAddress, + ilpConnectorUrl: config.ilpConnectorUrl, httpToken: expect.any(String), name: config.instanceName }) @@ -65,7 +65,7 @@ describe('Auto Peering Routes', (): void => { url: `/`, body: { staticIlpAddress: 'test.rafiki-money', - ilpConnectorAddress: 'http://peer.rafiki.money', + ilpConnectorUrl: 'http://peer.rafiki.money', asset: { code: 'ABC', scale: 2 }, httpToken: 'someHttpToken' } diff --git a/packages/backend/src/payment-method/ilp/auto-peering/routes.ts b/packages/backend/src/payment-method/ilp/auto-peering/routes.ts index c6dd9a9fb6..1ec0197eaf 100644 --- a/packages/backend/src/payment-method/ilp/auto-peering/routes.ts +++ b/packages/backend/src/payment-method/ilp/auto-peering/routes.ts @@ -5,7 +5,7 @@ import { AutoPeeringService } from './service' interface PeeringRequestArgs { staticIlpAddress: string - ilpConnectorAddress: string + ilpConnectorUrl: string asset: { code: string; scale: number } httpToken: string maxPacketAmount?: number diff --git a/packages/backend/src/payment-method/ilp/auto-peering/service.test.ts b/packages/backend/src/payment-method/ilp/auto-peering/service.test.ts index 7789d20101..af2c2e2282 100644 --- a/packages/backend/src/payment-method/ilp/auto-peering/service.test.ts +++ b/packages/backend/src/payment-method/ilp/auto-peering/service.test.ts @@ -51,7 +51,7 @@ describe('Auto Peering Service', (): void => { const args: PeeringRequestArgs = { staticIlpAddress: 'test.rafiki-money', - ilpConnectorAddress: 'http://peer.rafiki.money', + ilpConnectorUrl: 'http://peer.rafiki.money', asset: { code: asset.code, scale: asset.scale }, httpToken: 'someHttpToken', name: 'Rafiki Money', @@ -64,7 +64,7 @@ describe('Auto Peering Service', (): void => { autoPeeringService.acceptPeeringRequest(args) ).resolves.toEqual({ staticIlpAddress: config.ilpAddress, - ilpConnectorAddress: config.ilpConnectorAddress, + ilpConnectorUrl: config.ilpConnectorUrl, httpToken: expect.any(String), name: config.instanceName }) @@ -78,7 +78,7 @@ describe('Auto Peering Service', (): void => { incoming: { authTokens: [args.httpToken] }, outgoing: { authToken: expect.any(String), - endpoint: args.ilpConnectorAddress + endpoint: args.ilpConnectorUrl } } }) @@ -89,7 +89,7 @@ describe('Auto Peering Service', (): void => { const args: PeeringRequestArgs = { staticIlpAddress: 'test.rafiki-money', - ilpConnectorAddress: 'http://peer.rafiki.money', + ilpConnectorUrl: 'http://peer.rafiki.money', asset: { code: asset.code, scale: asset.scale }, httpToken: 'someHttpToken', name: 'Rafiki Money' @@ -101,7 +101,7 @@ describe('Auto Peering Service', (): void => { autoPeeringService.acceptPeeringRequest(args) ).resolves.toEqual({ staticIlpAddress: config.ilpAddress, - ilpConnectorAddress: config.ilpConnectorAddress, + ilpConnectorUrl: config.ilpConnectorUrl, httpToken: expect.any(String), name: config.instanceName }) @@ -111,7 +111,7 @@ describe('Auto Peering Service', (): void => { autoPeeringService.acceptPeeringRequest(args) ).resolves.toEqual({ staticIlpAddress: config.ilpAddress, - ilpConnectorAddress: config.ilpConnectorAddress, + ilpConnectorUrl: config.ilpConnectorUrl, httpToken: expect.any(String), name: config.instanceName }) @@ -122,7 +122,7 @@ describe('Auto Peering Service', (): void => { incoming: { authTokens: [args.httpToken] }, outgoing: { authToken: expect.any(String), - endpoint: args.ilpConnectorAddress + endpoint: args.ilpConnectorUrl } } }) @@ -132,7 +132,7 @@ describe('Auto Peering Service', (): void => { test('returns error if unknown asset', async (): Promise => { const args: PeeringRequestArgs = { staticIlpAddress: 'test.rafiki-money', - ilpConnectorAddress: 'http://peer.rafiki.money', + ilpConnectorUrl: 'http://peer.rafiki.money', asset: { code: 'USD', scale: 2 }, httpToken: 'someHttpToken' } @@ -147,7 +147,7 @@ describe('Auto Peering Service', (): void => { const args: PeeringRequestArgs = { staticIlpAddress: 'test.rafiki-money', - ilpConnectorAddress: 'invalid', + ilpConnectorUrl: 'invalid', asset: { code: asset.code, scale: asset.scale }, httpToken: 'someHttpToken' } @@ -162,7 +162,7 @@ describe('Auto Peering Service', (): void => { const args: PeeringRequestArgs = { staticIlpAddress: 'invalid', - ilpConnectorAddress: 'http://peer.rafiki.money', + ilpConnectorUrl: 'http://peer.rafiki.money', asset: { code: asset.code, scale: asset.scale }, httpToken: 'someHttpToken' } @@ -177,7 +177,7 @@ describe('Auto Peering Service', (): void => { const args: PeeringRequestArgs = { staticIlpAddress: 'test.rafiki-money', - ilpConnectorAddress: 'http://peer.rafiki.money', + ilpConnectorUrl: 'http://peer.rafiki.money', asset: { code: asset.code, scale: asset.scale }, httpToken: 'someHttpToken' } @@ -219,7 +219,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: 'peerHttpToken', name: 'Peer 2' } @@ -232,7 +232,7 @@ describe('Auto Peering Service', (): void => { scale: asset.scale }, httpToken: expect.any(String), - ilpConnectorAddress: config.ilpConnectorAddress, + ilpConnectorUrl: config.ilpConnectorUrl, maxPacketAmount: Number(args.maxPacketAmount), name: config.instanceName, staticIlpAddress: config.ilpAddress @@ -255,7 +255,7 @@ describe('Auto Peering Service', (): void => { authTokens: [peerDetails.httpToken] }, outgoing: { - endpoint: peerDetails.ilpConnectorAddress, + endpoint: peerDetails.ilpConnectorUrl, authToken: expect.any(String) } }, @@ -280,7 +280,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: 'peerHttpToken', name: 'Peer 2' } @@ -293,7 +293,7 @@ describe('Auto Peering Service', (): void => { scale: asset.scale }, httpToken: expect.any(String), - ilpConnectorAddress: config.ilpConnectorAddress, + ilpConnectorUrl: config.ilpConnectorUrl, maxPacketAmount: Number(args.maxPacketAmount), name: config.instanceName, staticIlpAddress: config.ilpAddress @@ -326,7 +326,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: 'peerHttpToken', name: 'Peer 2' } @@ -339,7 +339,7 @@ describe('Auto Peering Service', (): void => { scale: asset.scale }, httpToken: expect.any(String), - ilpConnectorAddress: config.ilpConnectorAddress, + ilpConnectorUrl: config.ilpConnectorUrl, maxPacketAmount: Number(args.maxPacketAmount), name: config.instanceName, staticIlpAddress: config.ilpAddress @@ -366,7 +366,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: 'peerHttpToken', name: 'Peer 2' } @@ -387,7 +387,7 @@ describe('Auto Peering Service', (): void => { authTokens: [peerDetails.httpToken] }, outgoing: { - endpoint: peerDetails.ilpConnectorAddress, + endpoint: peerDetails.ilpConnectorUrl, authToken: expect.any(String) } }, @@ -477,7 +477,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: '', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: 'peerHttpToken', name: 'Peer 2' } @@ -500,7 +500,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: '', + ilpConnectorUrl: '', httpToken: 'peerHttpToken', name: 'Peer 2' } @@ -523,7 +523,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: uuid(), name: 'Peer 2' } @@ -579,7 +579,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: uuid(), name: 'Peer 2' } @@ -617,7 +617,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: uuid(), name: 'Peer 2' } @@ -649,7 +649,7 @@ describe('Auto Peering Service', (): void => { const peerDetails: PeeringDetails = { staticIlpAddress: 'test.peer2', - ilpConnectorAddress: 'http://peer-two.com', + ilpConnectorUrl: 'http://peer-two.com', httpToken: 'peerHttpToken', name: 'Peer 2' } diff --git a/packages/backend/src/payment-method/ilp/auto-peering/service.ts b/packages/backend/src/payment-method/ilp/auto-peering/service.ts index ea9f77ba6b..31d1e60ea9 100644 --- a/packages/backend/src/payment-method/ilp/auto-peering/service.ts +++ b/packages/backend/src/payment-method/ilp/auto-peering/service.ts @@ -11,7 +11,7 @@ import { isTransferError } from '../../../accounting/errors' export interface PeeringDetails { staticIlpAddress: string - ilpConnectorAddress: string + ilpConnectorUrl: string httpToken: string name: string } @@ -27,7 +27,7 @@ export interface InitiatePeeringRequestArgs { export interface PeeringRequestArgs { staticIlpAddress: string - ilpConnectorAddress: string + ilpConnectorUrl: string asset: { code: string; scale: number } httpToken: string maxPacketAmount?: number @@ -36,7 +36,7 @@ export interface PeeringRequestArgs { interface UpdatePeerArgs { staticIlpAddress: string - ilpConnectorAddress: string + ilpConnectorUrl: string assetId: string incomingHttpToken: string outgoingHttpToken: string @@ -96,7 +96,7 @@ async function initiatePeeringRequest( const outgoingHttpToken = uuid() const peeringDetailsOrError = await sendPeeringRequest(deps, peerUrl, { - ilpConnectorAddress: deps.config.ilpConnectorAddress, + ilpConnectorUrl: deps.config.ilpConnectorUrl, staticIlpAddress: deps.config.ilpAddress, asset: { code: asset.code, scale: asset.scale }, httpToken: outgoingHttpToken, @@ -120,7 +120,7 @@ async function initiatePeeringRequest( }, outgoing: { authToken: outgoingHttpToken, - endpoint: peeringDetailsOrError.ilpConnectorAddress + endpoint: peeringDetailsOrError.ilpConnectorUrl } } }) @@ -139,7 +139,7 @@ async function initiatePeeringRequest( assetId: asset.id, outgoingHttpToken, incomingHttpToken: peeringDetailsOrError.httpToken, - ilpConnectorAddress: peeringDetailsOrError.ilpConnectorAddress + ilpConnectorUrl: peeringDetailsOrError.ilpConnectorUrl }) : createdPeerOrError @@ -243,7 +243,7 @@ async function acceptPeeringRequest( authTokens: [args.httpToken] }, outgoing: { - endpoint: args.ilpConnectorAddress, + endpoint: args.ilpConnectorUrl, authToken: outgoingHttpToken } }, @@ -262,7 +262,7 @@ async function acceptPeeringRequest( assetId: asset.id, outgoingHttpToken, incomingHttpToken: args.httpToken, - ilpConnectorAddress: args.ilpConnectorAddress + ilpConnectorUrl: args.ilpConnectorUrl }) : createdPeerOrError @@ -275,7 +275,7 @@ async function acceptPeeringRequest( } return { - ilpConnectorAddress: deps.config.ilpConnectorAddress, + ilpConnectorUrl: deps.config.ilpConnectorUrl, staticIlpAddress: deps.config.ilpAddress, httpToken: peerOrError.http.outgoing.authToken, name: deps.config.instanceName @@ -306,7 +306,7 @@ async function updatePeer( incoming: { authTokens: [args.incomingHttpToken] }, outgoing: { authToken: args.outgoingHttpToken, - endpoint: args.ilpConnectorAddress + endpoint: args.ilpConnectorUrl } } }) diff --git a/packages/backend/src/payment-method/ilp/spsp/middleware.test.ts b/packages/backend/src/payment-method/ilp/spsp/middleware.test.ts index 4a70a5fcd9..9a4705f9c6 100644 --- a/packages/backend/src/payment-method/ilp/spsp/middleware.test.ts +++ b/packages/backend/src/payment-method/ilp/spsp/middleware.test.ts @@ -56,24 +56,24 @@ describe('SPSP Middleware', (): void => { }) test.each` - header | spspEnabled | description - ${'application/json'} | ${true} | ${'calls next'} - ${'application/json'} | ${false} | ${'calls next'} - ${'application/spsp4+json'} | ${true} | ${'calls SPSP route'} - ${'application/spsp4+json'} | ${false} | ${'calls next'} - ${'*/*'} | ${true} | ${'calls next'} - ${'*/*'} | ${false} | ${'calls next'} + header | enableSpspPaymentPointers | description + ${'application/json'} | ${true} | ${'calls next'} + ${'application/json'} | ${false} | ${'calls next'} + ${'application/spsp4+json'} | ${true} | ${'calls SPSP route'} + ${'application/spsp4+json'} | ${false} | ${'calls next'} + ${'*/*'} | ${true} | ${'calls next'} + ${'*/*'} | ${false} | ${'calls next'} `( - '$description for accept header: $header and spspEnabled: $spspEnabled', - async ({ header, spspEnabled }): Promise => { + '$description for accept header: $header and enableSpspPaymentPointers: $enableSpspPaymentPointers', + async ({ header, enableSpspPaymentPointers }): Promise => { const spspSpy = jest .spyOn(spspRoutes, 'get') .mockResolvedValueOnce(undefined) ctx.headers['accept'] = header - const spspMiddleware = createSpspMiddleware(spspEnabled) + const spspMiddleware = createSpspMiddleware(enableSpspPaymentPointers) await expect(spspMiddleware(ctx, next)).resolves.toBeUndefined() - if (spspEnabled && header == 'application/spsp4+json') { + if (enableSpspPaymentPointers && header == 'application/spsp4+json') { expect(spspSpy).toHaveBeenCalledTimes(1) expect(next).not.toHaveBeenCalled() expect(ctx.paymentTag).toEqual(walletAddress.id) diff --git a/packages/documentation/src/content/docs/concepts/interledger-protocol/peering.md b/packages/documentation/src/content/docs/concepts/interledger-protocol/peering.md index 43fe14afd1..de7994149b 100644 --- a/packages/documentation/src/content/docs/concepts/interledger-protocol/peering.md +++ b/packages/documentation/src/content/docs/concepts/interledger-protocol/peering.md @@ -362,14 +362,14 @@ with the input being: } ``` -Calling this mutation will exchange ILP peering information (`staticIlpAddress` `ilpConnectorAddress`, auth tokens) automatically. The instance being peered with will issue a default amount of liquidity, and you can begin sending payments to wallet addresses at the other Rafiki instance. +Calling this mutation will exchange ILP peering information (`staticIlpAddress` `ilpConnectorUrl`, auth tokens) automatically. The instance being peered with will issue a default amount of liquidity, and you can begin sending payments to wallet addresses at the other Rafiki instance. ### Prerequisites Before making the `createOrUpdatePeerByUrl` request, a few `backend` environment variables about your Rafiki instance need to be configured: 1. `ILP_ADDRESS`: The static ILP address of your Rafiki instance. This should already be defined in order to support ILP payments. -2. `ILP_CONNECTOR_ADDRESS`: The full address of the ILP connector that will receive ILP packets. Locally and by default, it is on `0.0.0.0:3002`. +2. `ILP_CONNECTOR_URL`: The full address of the ILP connector that will receive ILP packets. Locally and by default, it is on `0.0.0.0:3002`. 3. `INSTANCE_NAME`: The name of your Rafiki instance. This is how your peer will identify you. ### How to enable auto-peering diff --git a/packages/documentation/src/content/docs/integration/deployment.md b/packages/documentation/src/content/docs/integration/deployment.md index cb032692f1..d1615e985c 100644 --- a/packages/documentation/src/content/docs/integration/deployment.md +++ b/packages/documentation/src/content/docs/integration/deployment.md @@ -55,28 +55,28 @@ Now, the Admin UI can be found on localhost:3010. | Variable | Helm Value Name | Default | Description | | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ADMIN_PORT` | backend.port.admin | `3001` | Admin API GraphQL Server port | -| `AUTH_SERVER_GRANT_URL` | | `http://127.0.0.1:3006` | endpoint on the Open Payments Auth Server to request a grant | -| `AUTH_SERVER_INTROSPECTION_URL` | | `http://127.0.0.1:3007` | endpoint on the Open Payments Auth Server to introspect an access token | +| `AUTH_SERVER_GRANT_URL` | | `undefined` | endpoint on the Open Payments Auth Server to request a grant | +| `AUTH_SERVER_INTROSPECTION_URL` | | `undefined` | endpoint on the Open Payments Auth Server to introspect an access token | | `AUTO_PEERING_SERVER_PORT` | | `3005` | If [auto-peering](/concepts/interledger-protocol/peering#auto-peering) is enabled, its server will use this port | | `CONNECTOR_PORT` | backend.port.connector | `3002` | port of the ILP connector for for sending packets over ILP over HTTP | | `DATABASE_URL` | backend.postgresql.host, backend.postgresql.port, backend.postgresql.username, backend.postgresql.database, backend.postgresql.password | `postgresql://postgres:password@localhost:5432/development` | Postgres database URL of database storing the resource data; For Helm, these components are provided individually. | | `ENABLE_AUTO_PEERING` | | `false` | Flag to enable auto peering. View [documentation](/concepts/interledger-protocol/peering#auto-peering). | -| `ENABLE_SPSP` | | `true` | enables [SPSP](/reference/glossary#simple-payments-setup-protocol-spsp) route | +| `ENABLE_SPSP_PAYMENT_POINTERS` | | `true` | enables [SPSP](/reference/glossary#simple-payments-setup-protocol-spsp) route | | `EXCHANGE_RATES_LIFETIME` | backend.lifetime.exchangeRate | `15_000` | time in milliseconds the exchange rates provided by the ASE via the EXCHANGE_RATES_URL are valid for | | `EXCHANGE_RATES_URL` | backend.serviceUrls.EXCHANGE_RATES_URL | `undefined` | endpoint on the Account Servicing Entity to request exchange rates | | `GRAPHQL_IDEMPOTENCY_KEY_TTL_MS` | backend.idempotencyTTL | `86400000` | TTL in milliseconds for idempotencyKey on GraphQL mutations (Admin API). Default: 24hrs | | `GRAPHQL_IDEMPOTENCY_KEY_LOCK_MS` | | `2000` | TTL in milliseconds for idempotencyKey concurrency lock on GraphQL mutations (Admin API) | -| `ILP_ADDRESS` | backend.ilp.address | `test.rafiki` | ILP address of this Rafiki instance | -| `ILP_CONNECTOR_ADDRESS` | | `http://127.0.0.1:3002` | The ILP connector address where ILP packets are received. Communicated during [auto-peering](/concepts/interledger-protocol/peering#auto-peering) | +| `ILP_ADDRESS` | backend.ilp.address | `undefined` | ILP address of this Rafiki instance | +| `ILP_CONNECTOR_URL` | | `undefined` | The ILP connector address where ILP packets are received. Communicated during [auto-peering](/concepts/interledger-protocol/peering#auto-peering) | | `INCOMING_PAYMENT_EXPIRY_MAX_MS` | | `2592000000` | Maximum milliseconds into the future incoming payments expiry can be set to on creation. Default: 30 days | | `INCOMING_PAYMENT_WORKERS` | backend.workers.incomingPayment | `1` | number of workers processing incoming payment requests | | `INCOMING_PAYMENT_WORKER_IDLE` | backend.workerIdle | `200` | time in milliseconds that INCOMING_PAYMENT_WORKERS will wait until they check an empty incoming payment request queue again | -| `INSTANCE_NAME` | | `Rafiki` | this Rafiki instance's name used to communicate for [auto-peering](/concepts/interledger-protocol/peering#auto-peering) | -| `KEY_ID` | backend.key.id | `rafiki` | this Rafiki instance's client key id | +| `INSTANCE_NAME` | | `undefined` | this Rafiki instance's name used to communicate for [auto-peering](/concepts/interledger-protocol/peering#auto-peering) | +| `KEY_ID` | backend.key.id | `undefined` | this Rafiki instance's client key id | | `LOG_LEVEL` | backend.logLevel | `info` | [Pino Log Level](https://getpino.io/#/docs/api?id=levels) | | `NODE_ENV` | backend.nodeEnv | `development` | node environment, `development`, `test`, or `production` | | `OPEN_PAYMENTS_PORT` | backend.port.openPayments | `3003` | port of the Open Payments resource server port | -| `OPEN_PAYMENTS_URL` | backend.serviceUrls.OPEN_PAYMENTS_URL | `http://127.0.0.1:3003` | public endpoint of this Open Payments Resource Server | +| `OPEN_PAYMENTS_URL` | backend.serviceUrls.OPEN_PAYMENTS_URL | `undefined` | public endpoint of this Open Payments Resource Server | | `OUTGOING_PAYMENT_WORKERS` | backend.workers.outgoingPayment | `4` | number of workers processing outgoing payment requests | | `OUTGOING_PAYMENT_WORKER_IDLE` | backend.workerIdle | `200` | time in milliseconds that OUTGOING_PAYMENT_WORKERS will wait until they check an empty outgoing payment request queue again | | `PRIVATE_KEY_FILE` | backend.key.file | `undefined` | the path to this Rafiki instance's client private key | @@ -88,11 +88,11 @@ Now, the Admin UI can be found on localhost:3010. | `SIGNATURE_SECRET` | backend.quoteSignatureSecret | `undefined` | secret to generate request header signatures for webhook event requests | | `SIGNATURE_VERSION` | | `1` | version number to generate request header signatures for webhook event requests | | `SLIPPAGE` | backend.ilp.slippage | `0.01` | accepted ILP rate fluctuation, default 1% | -| `STREAM_SECRET` | backend.ilp.streamSecret | 32 random bytes | seed secret to generate shared STREAM secrets | +| `STREAM_SECRET` | backend.ilp.streamSecret | undefined | seed secret to generate shared STREAM secrets | | `TIGERBEETLE_CLUSTER_ID` | | `0` | Tigerbeetle cluster ID picked by the system that starts the TigerBeetle cluster to create a [Tigerbeetle client](https://docs.tigerbeetle.com/clients/node#creating-a-client) | | `TIGERBEETLE_REPLICA_ADDRESSES` | | `3004` | Tigerbeetle replica addresses for all replicas in the cluster, which are comma separated IP addresses/ports, to create a [Tigerbeetle client](https://docs.tigerbeetle.com/clients/node#creating-a-client) | | `TRUST_PROXY` | | `false` | flag to use X-Forwarded-Proto header to determine if connections is secure | -| `USE_TIGERBEETLE` | | `false` | flag - use TigerBeetle or Postgres for accounting | +| `USE_TIGERBEETLE` | | `true` | flag - use TigerBeetle or Postgres for accounting | | `WALLET_ADDRESS_DEACTIVATION_PAYMENT_GRACE_PERIOD_MS` | | `86400000` | time in milliseconds into the future to set expiration of open incoming payments when deactivating wallet address. Default: 1 days | | `WALLET_ADDRESS_LOOKUP_TIMEOUT_MS` | | `1500` | time in milliseconds the ASE has to create a missing wallet address until timeout | | `WALLET_ADDRESS_POLLING_FREQUENCY_MS` | | `100` | frequency of polling while waiting for ASE to create a missing wallet address | @@ -101,7 +101,7 @@ Now, the Admin UI can be found on localhost:3010. | `WALLET_ADDRESS_WORKER_IDLE` | backend.workerIdle | `200` | time in milliseconds that WALLET_ADDRESS_WORKERS will wait until they check an empty wallet address request queue again | | `WEBHOOK_MAX_RETRY` | backend.webhookMaxRetry | `10` | maximum number of times Rafiki backend retries sending a certain webhook event to the configured WEBHOOK_URL | | `WEBHOOK_TIMEOUT` | backend.lifetime.webhook | `2000` | milliseconds | -| `WEBHOOK_URL` | backend.serviceUrls.WEBHOOK_URL | `http://127.0.0.1:4001/webhook` | endpoint on the Account Servicing Entity that consumes webhook events | +| `WEBHOOK_URL` | backend.serviceUrls.WEBHOOK_URL | `undefined` | endpoint on the Account Servicing Entity that consumes webhook events | | `WEBHOOK_WORKERS` | backend.workers.webhook | `1` | number of workers processing webhook events | | `WEBHOOK_WORKER_IDLE` | backend.workerIdle | `200` | time in milliseconds that WEBHOOK_WORKERS will wait until they check an empty webhook event queue again | | `WITHDRAWAL_THROTTLE_DELAY` | backend.withdrawalThrottleDelay | `undefined` | delay in liquidity withdrawal processing | diff --git a/test/integration/testenv/cloud-nine-wallet/docker-compose.yml b/test/integration/testenv/cloud-nine-wallet/docker-compose.yml index cd42756e39..090b75257e 100644 --- a/test/integration/testenv/cloud-nine-wallet/docker-compose.yml +++ b/test/integration/testenv/cloud-nine-wallet/docker-compose.yml @@ -19,6 +19,7 @@ services: environment: LOG_LEVEL: debug NODE_ENV: development + INSTANCE_NAME: 'Rafiki' CONNECTOR_PORT: 3102 ADMIN_PORT: 3101 OPEN_PAYMENTS_PORT: 3100 @@ -31,10 +32,12 @@ services: AUTH_SERVER_INTROSPECTION_URL: http://cloud-nine-wallet-test-auth:3107 AUTH_SERVER_GRANT_URL: http://cloud-nine-wallet-test-auth:3106 ILP_ADDRESS: test.cloud-nine-wallet-test + ILP_CONNECTOR_URL: http://127.0.0.1:3102 STREAM_SECRET: BjPXtnd00G2mRQwP/8ZpwyZASOch5sUXT5o0iR5b5wU= WEBHOOK_URL: http://host.docker.internal:8888/webhooks EXCHANGE_RATES_URL: http://host.docker.internal:8888/rates REDIS_URL: redis://shared-redis:6379/0 + USE_TIGERBEETLE: false volumes: - ../private-key.pem:/workspace/private-key.pem depends_on: diff --git a/test/integration/testenv/happy-life-bank/docker-compose.yml b/test/integration/testenv/happy-life-bank/docker-compose.yml index 09121fa9b2..91c84487c1 100644 --- a/test/integration/testenv/happy-life-bank/docker-compose.yml +++ b/test/integration/testenv/happy-life-bank/docker-compose.yml @@ -17,6 +17,7 @@ services: environment: NODE_ENV: development LOG_LEVEL: debug + INSTANCE_NAME: 'Happy Life Test' OPEN_PAYMENTS_URL: https://happy-life-bank-test-backend:4100 WALLET_ADDRESS_URL: https://happy-life-bank-test-backend:4100/.well-known/pay ADMIN_PORT: 4101 @@ -29,10 +30,12 @@ services: KEY_ID: keyid-97a3a431-8ee1-48fc-ac85-70e2f5eba8e5 PRIVATE_KEY_FILE: /workspace/private-key.pem ILP_ADDRESS: test.happy-life-bank-test + ILP_CONNECTOR_URL: http://127.0.0.1:4102 STREAM_SECRET: BjPXtnd00G2mRQwP/8ZpwyZASOch5sUXT5o0iR5b5wU= WEBHOOK_URL: http://host.docker.internal:8889/webhooks EXCHANGE_RATES_URL: http://host.docker.internal:8889/rates REDIS_URL: redis://shared-redis:6379/2 + USE_TIGERBEETLE: false volumes: - ../private-key.pem:/workspace/private-key.pem depends_on: