From 2bf2b9538d819569627e83a62ddebca266942a40 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sat, 9 Nov 2024 10:58:54 +0330 Subject: [PATCH 1/4] feat: add relay service --- .changeset/tender-buckets-agree.md | 2 + package-lock.json | 45 +++++++++++++++++++ package.json | 1 + .../rosenet-node/lib/createRoseNetNode.ts | 2 +- .../rosenet-relay/lib/createRoseNetRelay.ts | 2 +- services/relay/.eslintignore | 1 + services/relay/README.md | 9 ++++ services/relay/config/default.yml | 14 ++++++ services/relay/package.json | 36 +++++++++++++++ services/relay/src/bootstrap.ts | 7 +++ services/relay/src/configs/index.ts | 14 ++++++ services/relay/src/index.ts | 17 +++++++ services/relay/src/relay.ts | 38 ++++++++++++++++ services/relay/ts-node-esm-loader.js | 15 +++++++ services/relay/tsconfig.json | 19 ++++++++ 15 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 .changeset/tender-buckets-agree.md create mode 100644 services/relay/.eslintignore create mode 100644 services/relay/README.md create mode 100644 services/relay/config/default.yml create mode 100644 services/relay/package.json create mode 100644 services/relay/src/bootstrap.ts create mode 100644 services/relay/src/configs/index.ts create mode 100644 services/relay/src/index.ts create mode 100644 services/relay/src/relay.ts create mode 100644 services/relay/ts-node-esm-loader.js create mode 100644 services/relay/tsconfig.json diff --git a/.changeset/tender-buckets-agree.md b/.changeset/tender-buckets-agree.md new file mode 100644 index 0000000..a845151 --- /dev/null +++ b/.changeset/tender-buckets-agree.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/package-lock.json b/package-lock.json index fd5dec0..dc34531 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ }, "workspaces": { "packages": [ + "services/*", "tests/*", "packages/*" ] @@ -2710,6 +2711,10 @@ "integrity": "sha512-t9SVq4IXZwoykIxQT1EBnAGTpXW4xNrg1jfC+gM754IiIaGXBp9FMRrh3+zFvk7BfsGrmkS3wFUsYN7kKIIxYQ==", "deprecated": "@rosen-bridge/logger-interface has been renamed to @rosen-bridge/abstract-logger and will no longer get new updates." }, + "node_modules/@rosen-bridge/relay-service": { + "resolved": "services/relay", + "link": true + }, "node_modules/@rosen-bridge/rosenet-node": { "resolved": "packages/rosenet-node", "link": true @@ -2814,6 +2819,12 @@ "@types/node": "*" } }, + "node_modules/@types/config": { + "version": "0.0.41", + "resolved": "https://registry.npmjs.org/@types/config/-/config-0.0.41.tgz", + "integrity": "sha512-HjXUmIld0gwvyG8MU/17QtLzOyuMX4jbGuijmS9sWsob5xxgZ/hY9cbRCaHIHqTQ3HMLhwS3F8uXq3Bt9zgzHA==", + "dev": true + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -4092,6 +4103,17 @@ "dev": true, "license": "MIT" }, + "node_modules/config": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.12.tgz", + "integrity": "sha512-Vmx389R/QVM3foxqBzXO8t2tUikYZP64Q6vQxGrsMpREeJc/aWRnPRERXWsYzOHAumx/AOoILWe6nU3ZJL+6Sw==", + "dependencies": { + "json5": "^2.2.3" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -10789,6 +10811,29 @@ "node": ">=20.11.0" } }, + "services/relay": { + "name": "@rosen-bridge/relay-service", + "version": "0.1.0", + "license": "GPL-3.0", + "dependencies": { + "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/winston-logger": "^1.0.2", + "config": "^3.3.7" + }, + "devDependencies": { + "@types/config": "^0.0.41", + "@types/node": "^20.11.9", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "extensionless": "^1.9.6", + "prettier": "^3.2.4", + "ts-node": "^10.7.0", + "tsconfig-paths": "^4.1.2", + "typescript": "^5.3.3" + } + }, "tests/basic-messaging": { "name": "@rosenet-tests/basic-messaging", "version": "0.0.0", diff --git a/package.json b/package.json index 7c2d7bc..d81c740 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "type": "module", "workspaces": { "packages": [ + "services/*", "tests/*", "packages/*" ] diff --git a/packages/rosenet-node/lib/createRoseNetNode.ts b/packages/rosenet-node/lib/createRoseNetNode.ts index 78093e2..2c509c1 100644 --- a/packages/rosenet-node/lib/createRoseNetNode.ts +++ b/packages/rosenet-node/lib/createRoseNetNode.ts @@ -33,7 +33,7 @@ import sample from './utils/sample'; import RoseNetNodeError from './errors/RoseNetNodeError'; -import packageJson from '../package.json' with { type: 'json' }; +import packageJson from '../package.json' assert { type: 'json' }; import { PartialRoseNetNodeConfig } from './types'; diff --git a/packages/rosenet-relay/lib/createRoseNetRelay.ts b/packages/rosenet-relay/lib/createRoseNetRelay.ts index d44b3a6..0f06a57 100644 --- a/packages/rosenet-relay/lib/createRoseNetRelay.ts +++ b/packages/rosenet-relay/lib/createRoseNetRelay.ts @@ -25,7 +25,7 @@ import { RESERVATION_DURATION_LIMIT, } from './constants'; -import packageJson from '../package.json' with { type: 'json' }; +import packageJson from '../package.json' assert { type: 'json' }; import { RoseNetRelayConfig } from './types'; diff --git a/services/relay/.eslintignore b/services/relay/.eslintignore new file mode 100644 index 0000000..1521c8b --- /dev/null +++ b/services/relay/.eslintignore @@ -0,0 +1 @@ +dist diff --git a/services/relay/README.md b/services/relay/README.md new file mode 100644 index 0000000..405821e --- /dev/null +++ b/services/relay/README.md @@ -0,0 +1,9 @@ +# @rosen-bridge/relay-service + +## Table of contents + +- [Introduction](#introduction) + +## Introduction + +Rosen Bridge relay service diff --git a/services/relay/config/default.yml b/services/relay/config/default.yml new file mode 100644 index 0000000..30f68d3 --- /dev/null +++ b/services/relay/config/default.yml @@ -0,0 +1,14 @@ +logs: + - type: 'file' + path: './logs/' + maxSize: '10m' + maxFiles: '14d' + level: 'info' + - type: 'console' + level: 'info' +listen: + host: 0.0.0.0 + port: 44123 +whitelist: [] +pubsubTopics: [] +privateKeyFilePath: './rosenet-pk' diff --git a/services/relay/package.json b/services/relay/package.json new file mode 100644 index 0000000..aba2613 --- /dev/null +++ b/services/relay/package.json @@ -0,0 +1,36 @@ +{ + "name": "@rosen-bridge/relay-service", + "version": "0.1.0", + "description": "Rosen Bridge relay service", + "repository": "", + "license": "GPL-3.0", + "author": "Rosen Team", + "type": "module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "lint": "eslint --fix . && npm run prettify", + "prettify": "prettier --write . --ignore-path ./.gitignore", + "start": "node --watch --loader ./ts-node-esm-loader.js --loader extensionless ./src/index.ts", + "start:prod": "node --loader extensionless ./dist/index.js", + "type-check": "tsc --noEmit" + }, + "dependencies": { + "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/winston-logger": "^1.0.2", + "config": "^3.3.7" + }, + "devDependencies": { + "@types/config": "^0.0.41", + "@types/node": "^20.11.9", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "extensionless": "^1.9.6", + "prettier": "^3.2.4", + "ts-node": "^10.7.0", + "tsconfig-paths": "^4.1.2", + "typescript": "^5.3.3" + } +} diff --git a/services/relay/src/bootstrap.ts b/services/relay/src/bootstrap.ts new file mode 100644 index 0000000..bf065cd --- /dev/null +++ b/services/relay/src/bootstrap.ts @@ -0,0 +1,7 @@ +import { DefaultLoggerFactory } from '@rosen-bridge/abstract-logger'; +import WinstonLogger from '@rosen-bridge/winston-logger'; + +import { logs } from './configs'; + +const winston = new WinstonLogger(logs); +DefaultLoggerFactory.init(winston); diff --git a/services/relay/src/configs/index.ts b/services/relay/src/configs/index.ts new file mode 100644 index 0000000..470f023 --- /dev/null +++ b/services/relay/src/configs/index.ts @@ -0,0 +1,14 @@ +import { TransportOptions } from '@rosen-bridge/winston-logger'; +import config from 'config'; + +export const host = config.get('listen.host') ?? '0.0.0.0'; +export const port = config.get('listen.port') ?? 44123; + +export const whitelist = config.get('whitelist') ?? []; + +export const pubsubTopics = config.get('pubsubTopics') ?? []; + +export const logs = config.get('logs') ?? []; + +export const privateKeyFilePath = + config.get('privateKeyFilePath') ?? './rosenet-pk'; diff --git a/services/relay/src/index.ts b/services/relay/src/index.ts new file mode 100644 index 0000000..7f411ef --- /dev/null +++ b/services/relay/src/index.ts @@ -0,0 +1,17 @@ +import './bootstrap'; + +import { DefaultLoggerFactory } from '@rosen-bridge/abstract-logger'; + +import { startRelay } from './relay'; + +const logger = DefaultLoggerFactory.getInstance().getLogger(import.meta.url); + +try { + await startRelay(); +} catch (error) { + if (error instanceof Error) { + logger.error(`An error occurred while starting relay: [${error.message}]`); + } else { + logger.error(`An unknown error occurred while starting relay`); + } +} diff --git a/services/relay/src/relay.ts b/services/relay/src/relay.ts new file mode 100644 index 0000000..ba386cb --- /dev/null +++ b/services/relay/src/relay.ts @@ -0,0 +1,38 @@ +import { DefaultLoggerFactory } from '@rosen-bridge/abstract-logger'; +import { createRoseNetRelay } from '@rosen-bridge/rosenet-relay'; +import { readPrivateKeyFromFile } from '@rosen-bridge/rosenet-utils'; + +import { + host, + port, + privateKeyFilePath, + pubsubTopics, + whitelist, +} from './configs'; + +const logger = DefaultLoggerFactory.getInstance().getLogger(import.meta.url); +const rosenetLogger = DefaultLoggerFactory.getInstance().getLogger('rosenet'); + +/** + * Start relay service + */ +const startRelay = async () => { + const privateKey = await readPrivateKeyFromFile(privateKeyFilePath); + const node = await createRoseNetRelay({ + privateKey, + listen: { + host, + port, + }, + whitelist, + logger: rosenetLogger, + }); + + await node.start(); + + pubsubTopics.forEach((topic) => node.subscribe(topic, () => {})); + + logger.info('RoseNet relay started'); +}; + +export { startRelay }; diff --git a/services/relay/ts-node-esm-loader.js b/services/relay/ts-node-esm-loader.js new file mode 100644 index 0000000..6a27e30 --- /dev/null +++ b/services/relay/ts-node-esm-loader.js @@ -0,0 +1,15 @@ +import { resolve as resolveTs } from 'ts-node/esm'; +import * as tsConfigPaths from 'tsconfig-paths'; +import { pathToFileURL } from 'url'; + +const { absoluteBaseUrl, paths } = tsConfigPaths.loadConfig(); +const matchPath = tsConfigPaths.createMatchPath(absoluteBaseUrl, paths); + +export function resolve(specifier, ctx, defaultResolve) { + const match = matchPath(specifier); + return match + ? resolveTs(pathToFileURL(`${match}`).href, ctx, defaultResolve) + : resolveTs(specifier, ctx, defaultResolve); +} + +export { load, transformSource } from 'ts-node/esm'; diff --git a/services/relay/tsconfig.json b/services/relay/tsconfig.json new file mode 100644 index 0000000..822df1a --- /dev/null +++ b/services/relay/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "baseUrl": ".", + }, + "include": ["src"], + "ts-node": { + "esm": true, + }, + "references": [ + { + "path": "../../packages/rosenet-relay", + }, + { + "path": "../../packages/utils", + }, + ], +} From 9b3491486f998c65074959efce5a7995204c1250 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Sat, 9 Nov 2024 14:26:01 +0330 Subject: [PATCH 2/4] chore(relay-service): update default rosenet secret file name --- services/relay/config/default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/relay/config/default.yml b/services/relay/config/default.yml index 30f68d3..39b4932 100644 --- a/services/relay/config/default.yml +++ b/services/relay/config/default.yml @@ -11,4 +11,4 @@ listen: port: 44123 whitelist: [] pubsubTopics: [] -privateKeyFilePath: './rosenet-pk' +privateKeyFilePath: './rosenet-secret.json' From d239f1060786b722cfdaa8b75fd953cf83b59d91 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Mon, 11 Nov 2024 15:17:18 +0330 Subject: [PATCH 3/4] fix(relay-service): add missing dependencies --- package-lock.json | 2 ++ services/relay/package.json | 2 ++ 2 files changed, 4 insertions(+) diff --git a/package-lock.json b/package-lock.json index dc34531..6bdbf20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10817,6 +10817,8 @@ "license": "GPL-3.0", "dependencies": { "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/rosenet-relay": "^0.1.1", + "@rosen-bridge/rosenet-utils": "^0.2.0", "@rosen-bridge/winston-logger": "^1.0.2", "config": "^3.3.7" }, diff --git a/services/relay/package.json b/services/relay/package.json index aba2613..c0739cd 100644 --- a/services/relay/package.json +++ b/services/relay/package.json @@ -17,6 +17,8 @@ }, "dependencies": { "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/rosenet-relay": "^0.1.1", + "@rosen-bridge/rosenet-utils": "^0.2.0", "@rosen-bridge/winston-logger": "^1.0.2", "config": "^3.3.7" }, From f68a8c0573fea43259bcb40b6d02f2f5617998d2 Mon Sep 17 00:00:00 2001 From: Mohammad Kermani Date: Mon, 11 Nov 2024 15:17:51 +0330 Subject: [PATCH 4/4] chore(relay-service): fix default value in config --- services/relay/src/configs/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/relay/src/configs/index.ts b/services/relay/src/configs/index.ts index 470f023..7b42b9a 100644 --- a/services/relay/src/configs/index.ts +++ b/services/relay/src/configs/index.ts @@ -11,4 +11,4 @@ export const pubsubTopics = config.get('pubsubTopics') ?? []; export const logs = config.get('logs') ?? []; export const privateKeyFilePath = - config.get('privateKeyFilePath') ?? './rosenet-pk'; + config.get('privateKeyFilePath') ?? './rosenet-secret.json';