Merge pull request #3118 from gradido/iota4_extra_module_hello_world

feat(other): iota-tangle-connector mit Hello World Message als separates Modul
This commit is contained in:
einhornimmond 2023-07-07 12:16:51 +02:00 committed by GitHub
commit 61063424bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 6951 additions and 0 deletions

View File

@ -36,6 +36,9 @@ backend: &backend
dht_node: &dht_node
- 'dht-node/**/*'
dlt_connector: &dlt_connector
- 'dlt-connector/**/*'
docker-compose: &docker-compose
- 'docker-compose.*'

View File

@ -30,6 +30,7 @@ jobs:
release
federation
dht
dlt
workflow
docker
other

View File

@ -0,0 +1,74 @@
name: Gradido DLT Connector Test CI
on: push
jobs:
files-changed:
name: Detect File Changes - DLT Connector
runs-on: ubuntu-latest
outputs:
dlt_connector: ${{ steps.changes.outputs.dlt_connector }}
docker-compose: ${{ steps.changes.outputs.docker-compose }}
steps:
- uses: actions/checkout@v3.3.0
- name: Check for frontend file changes
uses: dorny/paths-filter@v2.11.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
build:
name: Docker Build Test - DLT Connector
if: needs.files-changed.outputs.dlt_connector == 'true'
needs: files-changed
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Build 'test' image
run: |
docker build --target test -t "gradido/dlt-connector:test" -f dlt-connector/Dockerfile .
docker save "gradido/dlt-connector:test" > /tmp/dlt-connector.tar
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: docker-dlt-connector-test
path: /tmp/dlt-connector.tar
lint:
name: Lint - DLT Connector
if: needs.files-changed.outputs.dlt_connector == 'true'
needs: files-changed
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Lint
run: cd dlt-connector && yarn && yarn run lint
unit_test:
name: Unit Tests - DLT Connector
if: needs.files-changed.outputs.dlt_connector == 'true' || needs.files-changed.outputs.docker-compose == 'true'
needs: [files-changed, build]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Download Docker Image
uses: actions/download-artifact@v3
with:
name: docker-dlt-connector-test
path: /tmp
- name: Load Docker Image
run: docker load < /tmp/dlt-connector.tar
- name: Unit tests
run: docker run --env NODE_ENV=test --rm gradido/dlt-connector:test yarn run test

9
dlt-connector/.env.dist Normal file
View File

@ -0,0 +1,9 @@
CONFIG_VERSION=v1.2023-07-04
# SET LOG LEVEL AS NEEDED IN YOUR .ENV
# POSSIBLE VALUES: all | trace | debug | info | warn | error | fatal
# LOG_LEVEL=info
# IOTA
IOTA_API_URL=https://chrysalis-nodes.iota.org
IOTA_COMMUNITY_ALIAS=GRADIDO: TestHelloWelt2

View File

@ -0,0 +1,5 @@
CONFIG_VERSION=$DLT_CONNECTOR_CONFIG_VERSION
#IOTA
IOTA_API_URL=$IOTA_API_URL
IOTA_COMMUNITY_ALIAS=$IOTA_COMMUNITY_ALIAS

View File

@ -0,0 +1,4 @@
node_modules
**/*.min.js
build
coverage

205
dlt-connector/.eslintrc.js Normal file
View File

@ -0,0 +1,205 @@
// eslint-disable-next-line import/no-commonjs, import/unambiguous
module.exports = {
root: true,
env: {
node: true,
},
parser: '@typescript-eslint/parser',
plugins: ['prettier', '@typescript-eslint', 'import', 'n', 'promise'],
extends: [
'standard',
'eslint:recommended',
'plugin:prettier/recommended',
// 'plugin:import/recommended',
// 'plugin:import/typescript',
// 'plugin:security/recommended',
'plugin:@eslint-community/eslint-comments/recommended',
],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
project: ['./tsconfig.json'],
},
node: true,
},
},
rules: {
'no-console': 'error',
camelcase: 'error',
'no-debugger': 'error',
'prettier/prettier': [
'error',
{
htmlWhitespaceSensitivity: 'ignore',
},
],
// import
// 'import/export': 'error',
// 'import/no-deprecated': 'error',
// 'import/no-empty-named-blocks': 'error',
// 'import/no-extraneous-dependencies': 'error',
// 'import/no-mutable-exports': 'error',
// 'import/no-unused-modules': 'error',
// 'import/no-named-as-default': 'error',
// 'import/no-named-as-default-member': 'error',
// 'import/no-amd': 'error',
// 'import/no-commonjs': 'error',
// 'import/no-import-module-exports': 'error',
// 'import/no-nodejs-modules': 'off',
// 'import/unambiguous': 'error',
// 'import/default': 'error',
// 'import/named': 'error',
// 'import/namespace': 'error',
// 'import/no-absolute-path': 'error',
// 'import/no-cycle': 'error',
// 'import/no-dynamic-require': 'error',
// 'import/no-internal-modules': 'off',
// 'import/no-relative-packages': 'error',
// 'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }],
// 'import/no-self-import': 'error',
// 'import/no-unresolved': 'error',
// 'import/no-useless-path-segments': 'error',
// 'import/no-webpack-loader-syntax': 'error',
// 'import/consistent-type-specifier-style': 'error',
// 'import/exports-last': 'off',
// 'import/extensions': 'error',
// 'import/first': 'error',
// 'import/group-exports': 'off',
// 'import/newline-after-import': 'error',
// 'import/no-anonymous-default-export': 'error',
// 'import/no-default-export': 'error',
// 'import/no-duplicates': 'error',
// 'import/no-named-default': 'error',
// 'import/no-namespace': 'error',
// 'import/no-unassigned-import': 'error',
// 'import/order': [
// 'error',
// {
// groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
// 'newlines-between': 'always',
// pathGroups: [
// {
// pattern: '@?*/**',
// group: 'external',
// position: 'after',
// },
// {
// pattern: '@/**',
// group: 'external',
// position: 'after',
// },
// ],
// alphabetize: {
// order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */,
// caseInsensitive: true /* ignore case. Options: [true, false] */,
// },
// distinctGroup: true,
// },
// ],
// 'import/prefer-default-export': 'off',
// n
'n/handle-callback-err': 'error',
'n/no-callback-literal': 'error',
'n/no-exports-assign': 'error',
'n/no-extraneous-import': 'error',
'n/no-extraneous-require': 'error',
'n/no-hide-core-modules': 'error',
'n/no-missing-import': 'off', // not compatible with typescript
'n/no-missing-require': 'error',
'n/no-new-require': 'error',
'n/no-path-concat': 'error',
'n/no-process-exit': 'error',
'n/no-unpublished-bin': 'error',
'n/no-unpublished-import': 'off', // TODO need to exclude seeds
'n/no-unpublished-require': 'error',
'n/no-unsupported-features': ['error', { ignores: ['modules'] }],
'n/no-unsupported-features/es-builtins': 'error',
'n/no-unsupported-features/es-syntax': 'error',
'n/no-unsupported-features/node-builtins': 'error',
'n/process-exit-as-throw': 'error',
'n/shebang': 'error',
'n/callback-return': 'error',
'n/exports-style': 'error',
'n/file-extension-in-import': 'off',
'n/global-require': 'error',
'n/no-mixed-requires': 'error',
'n/no-process-env': 'error',
'n/no-restricted-import': 'error',
'n/no-restricted-require': 'error',
'n/no-sync': 'error',
'n/prefer-global/buffer': 'error',
'n/prefer-global/console': 'error',
'n/prefer-global/process': 'error',
'n/prefer-global/text-decoder': 'error',
'n/prefer-global/text-encoder': 'error',
'n/prefer-global/url': 'error',
'n/prefer-global/url-search-params': 'error',
'n/prefer-promises/dns': 'error',
'n/prefer-promises/fs': 'error',
// promise
// 'promise/catch-or-return': 'error',
// 'promise/no-return-wrap': 'error',
// 'promise/param-names': 'error',
// 'promise/always-return': 'error',
// 'promise/no-native': 'off',
// 'promise/no-nesting': 'warn',
// 'promise/no-promise-in-callback': 'warn',
// 'promise/no-callback-in-promise': 'warn',
// 'promise/avoid-new': 'warn',
// 'promise/no-new-statics': 'error',
// 'promise/no-return-in-finally': 'warn',
// 'promise/valid-params': 'warn',
// 'promise/prefer-await-to-callbacks': 'error',
// 'promise/no-multiple-resolved': 'error',
// eslint comments
'@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
'@eslint-community/eslint-comments/no-restricted-disable': 'error',
'@eslint-community/eslint-comments/no-use': 'off',
'@eslint-community/eslint-comments/require-description': 'off',
},
overrides: [
// only for ts files
{
files: ['*.ts', '*.tsx'],
extends: [
'plugin:@typescript-eslint/recommended',
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
// 'plugin:@typescript-eslint/strict',
],
rules: {
// allow explicitly defined dangling promises
// '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
'no-void': ['error', { allowAsStatement: true }],
// ignore prefer-regexp-exec rule to allow string.match(regex)
'@typescript-eslint/prefer-regexp-exec': 'off',
// this should not run on ts files: https://github.com/import-js/eslint-plugin-import/issues/2215#issuecomment-911245486
'import/unambiguous': 'off',
// this is not compatible with typeorm, due to joined tables can be null, but are not defined as nullable
'@typescript-eslint/no-unnecessary-condition': 'off',
},
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
// this is to properly reference the referenced project database without requirement of compiling it
// eslint-disable-next-line camelcase
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true,
},
},
{
files: ['*.test.ts'],
plugins: ['jest'],
rules: {
'jest/no-disabled-tests': 'error',
'jest/no-focused-tests': 'error',
'jest/no-identical-title': 'error',
'jest/prefer-to-have-length': 'error',
'jest/valid-expect': 'error',
'@typescript-eslint/unbound-method': 'off',
'jest/unbound-method': 'error',
},
},
],
}

8
dlt-connector/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
/node_modules/
/.env
/.env.bak
/build/
package-json.lock
coverage
# emacs
*~

View File

@ -0,0 +1,9 @@
module.exports = {
semi: false,
printWidth: 100,
singleQuote: true,
trailingComma: "all",
tabWidth: 2,
bracketSpacing: true,
endOfLine: "auto",
};

109
dlt-connector/Dockerfile Normal file
View File

@ -0,0 +1,109 @@
##################################################################################
# BASE ###########################################################################
##################################################################################
FROM node:19.5.0-alpine3.17 as base
#FROM ubuntu:latest as base
# ENVs (available in production aswell, can be overwritten by commandline or env file)
## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame
ENV DOCKER_WORKDIR="/app"
## We Cannot do `$(date -u +'%Y-%m-%dT%H:%M:%SZ')` here so we use unix timestamp=0
ENV BUILD_DATE="1970-01-01T00:00:00.00Z"
## We cannot do $(npm run version).${BUILD_NUMBER} here so we default to 0.0.0.0
ENV BUILD_VERSION="0.0.0.0"
## We cannot do `$(git rev-parse --short HEAD)` here so we default to 0000000
ENV BUILD_COMMIT="0000000"
## SET NODE_ENV
ENV NODE_ENV="production"
## App relevant Envs
ENV PORT="6000"
# Labels
LABEL org.label-schema.build-date="${BUILD_DATE}"
LABEL org.label-schema.name="gradido:dlt-connector"
LABEL org.label-schema.description="Gradido dlt-connector"
LABEL org.label-schema.usage="https://github.com/gradido/gradido/blob/master/README.md"
LABEL org.label-schema.url="https://gradido.net"
LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido/tree/master/dlt-connector"
LABEL org.label-schema.vcs-ref="${BUILD_COMMIT}"
LABEL org.label-schema.vendor="Gradido Community"
LABEL org.label-schema.version="${BUILD_VERSION}"
LABEL org.label-schema.schema-version="1.0"
LABEL maintainer="support@gradido.net"
# Install Additional Software
## install: @iota/client requirements
# Install Build Tool for Rust for @iota/client
RUN apk add --no-cache rust cargo python3 make g++
# Settings
## Expose Container Port
EXPOSE ${PORT}
## Workdir
RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
##################################################################################
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
##################################################################################
FROM base as development
# We don't need to copy or build anything since we gonna bind to the
# local filesystem which will need a rebuild anyway
# Run command
# (for development we need to execute yarn install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "cd /app && yarn install && yarn run dev"
##################################################################################
# BUILD (Does contain all files and is therefore bloated) ########################
##################################################################################
FROM base as build
# Copy everything from dlt-connector
COPY ./dlt-connector/ ./
# yarn install dlt-connector
RUN yarn install --production=false --frozen-lockfile --non-interactive
# yarn build
RUN yarn run build
##################################################################################
# TEST ###########################################################################
##################################################################################
FROM build as test
# Run command
CMD /bin/sh -c "yarn run start"
##################################################################################
# PRODUCTION (Does contain only "binary"- and static-files to reduce image size) #
##################################################################################
FROM base as production
# remove iota build tools to have production docker image smaller
RUN apk del rust cargo python3 make g++
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/build ./build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
# Copy static files
# COPY --from=build ${DOCKER_WORKDIR}/public ./public
# Copy package.json for script definitions (lock file should not be needed)
COPY --from=build ${DOCKER_WORKDIR}/package.json ./package.json
# Copy tsconfig.json to provide alias path definitions
COPY --from=build ${DOCKER_WORKDIR}/tsconfig.json ./tsconfig.json
# Copy log4js-config.json to provide log configuration
COPY --from=build ${DOCKER_WORKDIR}/log4js-config.json ./log4js-config.json
# Copy run scripts run/
# COPY --from=build ${DOCKER_WORKDIR}/run ./run
# Run command
CMD /bin/sh -c "yarn run start"

View File

@ -0,0 +1,29 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
verbose: true,
preset: 'ts-jest',
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
coverageThreshold: {
global: {
lines: 52,
},
},
setupFiles: ['<rootDir>/test/testSetup.ts'],
setupFilesAfterEnv: [],
modulePathIgnorePatterns: ['<rootDir>/build/'],
moduleNameMapper: {
'@/(.*)': '<rootDir>/src/$1',
'@test/(.*)': '<rootDir>/test/$1',
'@entity/(.*)':
// eslint-disable-next-line n/no-process-env
process.env.NODE_ENV === 'development'
? '<rootDir>/../database/entity/$1'
: '<rootDir>/../database/build/entity/$1',
'@dbTools/(.*)':
// eslint-disable-next-line n/no-process-env
process.env.NODE_ENV === 'development'
? '<rootDir>/../database/src/$1'
: '<rootDir>/../database/build/src/$1',
},
}

View File

@ -0,0 +1,69 @@
{
"appenders":
{
"dlt":
{
"type": "dateFile",
"filename": "../logs/dlt-connector/apiversion-%v.log",
"pattern": "yyyy-MM-dd",
"layout":
{
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{user}] [%f : %l] - %m"
},
"keepFileExt" : true,
"fileNameSep" : "_",
"numBackups" : 30
},
"errorFile":
{
"type": "dateFile",
"filename": "../logs/dlt-connector/errors.log",
"pattern": "yyyy-MM-dd",
"layout":
{
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{user}] [%f : %l] - %m"
},
"keepFileExt" : true,
"fileNameSep" : "_",
"numBackups" : 30
},
"errors":
{
"type": "logLevelFilter",
"level": "error",
"appender": "errorFile"
},
"out":
{
"type": "stdout",
"layout":
{
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{user}] [%f : %l] - %m"
}
}
},
"categories":
{
"default":
{
"appenders":
[
"out",
"errors"
],
"level": "debug",
"enableCallStack": true
},
"dlt":
{
"appenders":
[
"dlt",
"out",
"errors"
],
"level": "debug",
"enableCallStack": true
}
}
}

View File

@ -0,0 +1,57 @@
{
"name": "gradido-dlt-connector",
"version": "1.22.0",
"description": "Gradido DLT-Connector",
"main": "src/index.ts",
"repository": "https://github.com/gradido/gradido/",
"author": "Dario Rekowski",
"license": "Apache-2.0",
"private": false,
"scripts": {
"build": "tsc --build",
"clean": "tsc --build --clean",
"start": "cross-env TZ=UTC TS_NODE_BASEURL=./build node -r tsconfig-paths/register build/src/index.js",
"dev": "cross-env TZ=UTC nodemon -w src --ext ts --exec ts-node -r dotenv/config -r tsconfig-paths/register src/index.ts",
"lint": "eslint --max-warnings=0 --ext .js,.ts .",
"test": "cross-env TZ=UTC NODE_ENV=development jest --runInBand --forceExit --detectOpenHandles"
},
"dependencies": {
"@apollo/server": "^4.7.5",
"@iota/client": "^2.2.4",
"class-validator": "^0.14.0",
"cross-env": "^7.0.3",
"dotenv": "10.0.0",
"express": "4.17.1",
"graphql": "^16.7.1",
"log4js": "^6.7.1",
"nodemon": "^2.0.20",
"tsconfig-paths": "^4.1.2",
"type-graphql": "^2.0.0-beta.2"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "^3.2.1",
"@types/jest": "^27.0.2",
"@types/node": "^18.11.18",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"eslint": "^8.37.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-standard": "^17.0.0",
"eslint-import-resolver-typescript": "^3.5.4",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-n": "^15.7.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-security": "^1.7.1",
"jest": "^27.2.4",
"prettier": "^2.8.7",
"ts-jest": "^27.0.5",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
},
"engines": {
"node": ">=14"
}
}

View File

@ -0,0 +1,71 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { sendMessage, receiveMessage } from '@/client/IotaClient'
jest.mock('@iota/client', () => {
const mockMessageSender = jest.fn().mockImplementation(() => {
return {
index: jest.fn().mockReturnThis(),
data: jest.fn().mockReturnThis(),
submit: jest
.fn()
.mockReturnValue('5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710'),
}
})
const mockMessageFinder = jest.fn().mockImplementation(() => {
return {
data: jest.fn().mockReturnValue({
message: {
networkId: '1454675179895816119',
parentMessageIds: [
'5f30efecca59fdfef7c103e85ef691b2b1dc474e9eae9056888a6d58605083e7',
'77cef2fb405daedcd7469e009bb87a6d9a4840e618cdb599cd21a30a9fec88dc',
'7d2cfb39f40585ba568a29ad7e85c1478b2584496eb736d4001ac344f6a6cacf',
'c66da602874220dfa26925f6be540d37c0084d37cd04726fcc5be9d80b36f850',
],
payload: {
type: 2,
index: '4752414449444f3a205465737448656c6c6f57656c7431',
data: '48656c6c6f20576f726c64202d20546875204a756e20303820323032332031343a35393a343520474d542b3030303020284b6f6f7264696e69657274652057656c747a65697429',
},
nonce: '13835058055282465157',
},
messageId: '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710',
}),
}
})
const mockClient = {
message: mockMessageSender,
getMessage: mockMessageFinder,
}
const mockClientBuilder = {
node: jest.fn().mockReturnThis(),
build: jest.fn(() => mockClient),
}
return {
ClientBuilder: jest.fn(() => mockClientBuilder),
}
})
describe('Iota Tests', () => {
it('test mocked sendDataMessage', async () => {
const result = await sendMessage('Test Message')
expect(result).toBe('5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710')
})
it('should mock getMessage', async () => {
const result = await receiveMessage(
'5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710',
)
expect(result).toMatchObject({
message: {
payload: {
data: '48656c6c6f20576f726c64202d20546875204a756e20303820323032332031343a35393a343520474d542b3030303020284b6f6f7264696e69657274652057656c747a65697429',
index: '4752414449444f3a205465737448656c6c6f57656c7431',
},
},
messageId: '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710',
})
})
})

View File

@ -0,0 +1,51 @@
import { ClientBuilder } from '@iota/client'
import { MessageWrapper } from '@iota/client/lib/types'
import { CONFIG } from '@/config'
const client = new ClientBuilder().node(CONFIG.IOTA_API_URL).build()
/**
* send data message onto iota tangle
* use CONFIG.IOTA_COMMUNITY_ALIAS for index
* @param {string} message - the message as utf based string, will be converted to hex automatically from @iota/client
* @return {Promise<MessageWrapper>} the iota message typed
*/
function sendMessage(message: string): Promise<MessageWrapper> {
return client.message().index(CONFIG.IOTA_COMMUNITY_ALIAS).data(message).submit()
}
/**
* receive message for known message id from iota tangle
* @param {string} messageId - as hex string
* @return {Promise<MessageWrapper>} the iota message typed
*/
function receiveMessage(messageId: string): Promise<MessageWrapper> {
return client.getMessage().data(messageId)
}
export { sendMessage, receiveMessage }
/**
* example for message:
```json
{
message: {
networkId: '1454675179895816119',
parentMessageIds: [
'5f30efecca59fdfef7c103e85ef691b2b1dc474e9eae9056888a6d58605083e7',
'77cef2fb405daedcd7469e009bb87a6d9a4840e618cdb599cd21a30a9fec88dc',
'7d2cfb39f40585ba568a29ad7e85c1478b2584496eb736d4001ac344f6a6cacf',
'c66da602874220dfa26925f6be540d37c0084d37cd04726fcc5be9d80b36f850'
],
payload: {
type: 2,
index: '4752414449444f3a205465737448656c6c6f57656c7431',
data: '48656c6c6f20576f726c64202d20546875204a756e20303820323032332031343a35393a343520474d542b3030303020284b6f6f7264696e69657274652057656c747a65697429'
},
nonce: '13835058055282465157'
},
messageId: '5498130bc3918e1a7143969ce05805502417e3e1bd596d3c44d6a0adeea22710'
}
```
*/

View File

@ -0,0 +1,41 @@
/* eslint-disable n/no-process-env */
import dotenv from 'dotenv'
dotenv.config()
const constants = {
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v1.2023-07-04',
CURRENT: '',
},
}
const server = {
PRODUCTION: process.env.NODE_ENV === 'production' || false,
}
const iota = {
IOTA_API_URL: process.env.IOTA_API_URL ?? 'https://chrysalis-nodes.iota.org',
IOTA_COMMUNITY_ALIAS: process.env.IOTA_COMMUNITY_ALIAS ?? 'GRADIDO: TestHelloWelt2',
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,
)
) {
throw new Error(
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
)
}
export const CONFIG = {
...constants,
...server,
...iota,
}

View File

@ -0,0 +1,39 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
sendMessage as iotaSendMessage,
receiveMessage as iotaReceiveMessage,
} from '@/client/IotaClient'
import { CONFIG } from '@/config'
import { IndexationPayload } from '@iota/client/lib/types'
import { logger } from './server/logger'
async function main() {
const now = new Date()
const messageString = 'Hello World - ' + now.toString()
const messageHexString = Buffer.from(messageString, 'utf8').toString('hex')
const indexHexString = Buffer.from(CONFIG.IOTA_COMMUNITY_ALIAS, 'utf8').toString('hex')
const iotaSendedMessage = await iotaSendMessage(messageString)
if (iotaSendedMessage && iotaSendedMessage.messageId) {
logger.info('Hello World Message send to iota, get messageId: %s', iotaSendedMessage.messageId)
const iotaReceivedMessage = await iotaReceiveMessage(iotaSendedMessage.messageId)
const indexationPayload = iotaReceivedMessage.message.payload as IndexationPayload
if (
indexationPayload.index.toString() === indexHexString ||
indexationPayload.data.toString() === messageHexString
) {
logger.info('Hello World Message received unchanged from Iota')
} else {
logger.error('Hello World Message changed on Tangle!!!')
}
}
}
main().catch((e) => {
// eslint-disable-next-line no-console
console.error(e)
// eslint-disable-next-line n/no-process-exit
process.exit(1)
})

View File

@ -0,0 +1,11 @@
import log4js from 'log4js'
import { CONFIG } from '@/config'
import { readFileSync } from 'fs'
const options = JSON.parse(readFileSync(CONFIG.LOG4JS_CONFIG, 'utf-8'))
log4js.configure(options)
const logger = log4js.getLogger('dlt')
export { logger }

View File

@ -0,0 +1,22 @@
import { logger } from '@/server/logger'
jest.setTimeout(1000000)
jest.mock('@/server/logger', () => {
const originalModule = jest.requireActual('@/server/logger')
return {
__esModule: true,
...originalModule,
logger: {
addContext: jest.fn(),
trace: jest.fn(),
debug: jest.fn(),
warn: jest.fn(),
info: jest.fn(),
error: jest.fn(),
fatal: jest.fn(),
},
}
})
export { logger }

View File

@ -0,0 +1,76 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./build", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
"strictPropertyInitialization": false, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
"paths": { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
"@/*": ["src/*"],
"@test/*": ["test/*"],
/* external */
},
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
"typeRoots": ["node_modules/@types"], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
}

5993
dlt-connector/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -84,6 +84,26 @@ services:
- ./dht-node:/app
- ./database:/database
########################################################
# DLT-CONNECTOR ########################################
########################################################
dlt-connector:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: gradido/dlt-connector:local-development
build:
target: development
networks:
- external-net
- internal-net
environment:
- NODE_ENV="development"
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- dlt_connector_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./dlt-connector:/app
########################################################
# FEDERATION ###########################################
########################################################

View File

@ -51,6 +51,20 @@ services:
- NODE_ENV="test"
- DB_HOST=mariadb
########################################################
# DLT-CONNECTOR ########################################
########################################################
dlt-connector:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: gradido/dlt-connector:test
build:
target: test
networks:
- external-net
- internal-net
environment:
- NODE_ENV="test"
########################################################
# DATABASE #############################################
########################################################

View File

@ -147,6 +147,37 @@ services:
# <host_machine_directory>:<container_directory> mirror bidirectional path in local context with path in Docker container
- ./logs/dht-node:/logs/dht-node
########################################################
# DLT-Connector ########################################
########################################################
dlt-connector:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: gradido/dlt-connector:local-production
build:
# since we have to include the entities from ./database we cannot define the context as ./backend
# this might blow build image size to the moon ?!
context: ./dlt-connector
dockerfile: ./Dockerfile
target: production
networks:
- internal-net
- external-net
ports:
- 6000:6000
restart: always
environment:
# Envs used in Dockerfile
# - DOCKER_WORKDIR="/app"
- PORT=6000
- BUILD_DATE
- BUILD_VERSION
- BUILD_COMMIT
- NODE_ENV="production"
# Application only envs
volumes:
# <host_machine_directory>:<container_directory> mirror bidirectional path in local context with path in Docker container
- ./logs/dlt-connector:/logs/dlt-connector
########################################################
# FEDERATION ###########################################
########################################################