diff --git a/backend/src/apis/dltConnector/DltConnectorClient.test.ts b/backend/src/apis/dltConnector/DltConnectorClient.test.ts index 00b15348d..0e2043a09 100644 --- a/backend/src/apis/dltConnector/DltConnectorClient.test.ts +++ b/backend/src/apis/dltConnector/DltConnectorClient.test.ts @@ -1,46 +1,7 @@ -import { Transaction as DbTransaction } from 'database' -import { Decimal } from 'decimal.js-light' -import { DataSource } from 'typeorm' - -import { cleanDB, testEnvironment } from '@test/helpers' - import { CONFIG } from '@/config' -import { LogError } from '@/server/LogError' import { DltConnectorClient } from './DltConnectorClient' -let con: DataSource - -let testEnv: { - con: DataSource -} - -// Mock the GraphQLClient -jest.mock('graphql-request', () => { - const originalModule = jest.requireActual('graphql-request') - - return { - __esModule: true, - ...originalModule, - GraphQLClient: jest.fn().mockImplementation((url: string) => { - if (url === 'invalid') { - throw new Error('invalid url') - } - return { - // why not using mockResolvedValueOnce or mockReturnValueOnce? - // I have tried, but it didn't work and return every time the first value - request: jest.fn().mockImplementation(() => { - return Promise.resolve({ - transmitTransaction: { - succeed: true, - }, - }) - }), - } - }), - } -}) - describe('undefined DltConnectorClient', () => { it('invalid url', () => { CONFIG.DLT_CONNECTOR_URL = 'invalid' @@ -58,90 +19,4 @@ describe('undefined DltConnectorClient', () => { }) }) -/* -describe.skip('transmitTransaction, without db connection', () => { - const transaction = new DbTransaction() - transaction.typeId = 2 // Example transaction type ID - transaction.amount = new Decimal('10.00') // Example amount - transaction.balanceDate = new Date() // Example creation date - transaction.id = 1 // Example transaction ID - it('cannot query for transaction id', async () => { - const result = await DltConnectorClient.getInstance()?.transmitTransaction(transaction) - expect(result).toBe(false) - }) -}) -*/ - -describe('transmitTransaction', () => { - beforeAll(async () => { - testEnv = await testEnvironment() - con = testEnv.con - await cleanDB() - }) - - afterAll(async () => { - await cleanDB() - await con.destroy() - }) - - const transaction = new DbTransaction() - transaction.typeId = 2 // Example transaction type ID - transaction.amount = new Decimal('10.00') // Example amount - transaction.balanceDate = new Date() // Example creation date - transaction.id = 1 // Example transaction ID - - // data needed to let save succeed - transaction.memo = "I'm a dummy memo" - transaction.userId = 1 - transaction.userGradidoID = 'dummy gradido id' - - /* - it.skip('cannot find transaction in db', async () => { - const result = await DltConnectorClient.getInstance()?.transmitTransaction(transaction) - expect(result).toBe(false) - }) - */ - - it('invalid transaction type', async () => { - const localTransaction = new DbTransaction() - localTransaction.typeId = 12 - try { - await DltConnectorClient.getInstance()?.transmitTransaction(localTransaction) - } catch (e) { - expect(e).toMatchObject( - new LogError(`invalid transaction type id: ${localTransaction.typeId.toString()}`), - ) - } - }) - - /* - it.skip('should transmit the transaction and update the dltTransactionId in the database', async () => { - await transaction.save() - - const result = await DltConnectorClient.getInstance()?.transmitTransaction(transaction) - expect(result).toBe(true) - }) - - it.skip('invalid dltTransactionId (maximal 32 Bytes in Binary)', async () => { - await transaction.save() - - const result = await DltConnectorClient.getInstance()?.transmitTransaction(transaction) - expect(result).toBe(false) - }) - */ -}) - -/* -describe.skip('try transmitTransaction but graphql request failed', () => { - it('graphql request should throw', async () => { - const transaction = new DbTransaction() - transaction.typeId = 2 // Example transaction type ID - transaction.amount = new Decimal('10.00') // Example amount - transaction.balanceDate = new Date() // Example creation date - transaction.id = 1 // Example transaction ID - const result = await DltConnectorClient.getInstance()?.transmitTransaction(transaction) - expect(result).toBe(false) - }) -}) -*/ diff --git a/backend/src/apis/dltConnector/DltConnectorClient.ts b/backend/src/apis/dltConnector/DltConnectorClient.ts index 4fef742ed..16c74ab0c 100644 --- a/backend/src/apis/dltConnector/DltConnectorClient.ts +++ b/backend/src/apis/dltConnector/DltConnectorClient.ts @@ -3,29 +3,10 @@ import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getLogger } from 'log4js' import { TransactionDraft } from './model/TransactionDraft' -import { TransactionResult } from './model/TransactionResult' -import { GraphQLClient } from 'graphql-request' -import { gql } from 'graphql-request' +import { IRestResponse, RestClient } from 'typed-rest-client' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.apis.dltConnector`) -const sendTransaction = gql` - mutation ($input: TransactionDraft!) { - sendTransaction(data: $input) { - error { - message - name - } - succeed - recipe { - createdAt - type - messageIdHex - } - } - } -` - // Source: https://refactoring.guru/design-patterns/singleton/typescript/example // and ../federation/client/FederationClientFactory.ts /** @@ -35,7 +16,7 @@ const sendTransaction = gql` export class DltConnectorClient { private static instance: DltConnectorClient - client: GraphQLClient + client: RestClient /** * The Singleton's constructor should always be private to prevent direct * construction calls with the `new` operator. @@ -59,16 +40,12 @@ export class DltConnectorClient { } if (!DltConnectorClient.instance.client) { try { - DltConnectorClient.instance.client = new GraphQLClient(CONFIG.DLT_CONNECTOR_URL, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - jsonSerializer: { - parse: JSON.parse, - stringify: JSON.stringify, - }, - }) + DltConnectorClient.instance.client = new RestClient( + 'gradido-backend', + CONFIG.DLT_CONNECTOR_URL, + undefined, + { keepAlive: true } + ) } catch (e) { logger.error("couldn't connect to dlt-connector: ", e) return @@ -78,16 +55,11 @@ export class DltConnectorClient { } /** - * transmit transaction via dlt-connector to iota - * and update dltTransactionId of transaction in db with iota message id + * transmit transaction via dlt-connector to hiero + * and update dltTransactionId of transaction in db with hiero transaction id */ - public async sendTransaction(input: TransactionDraft): Promise { + public async sendTransaction(input: TransactionDraft): Promise> { logger.debug('transmit transaction or user to dlt connector', input) - const { - data: { sendTransaction: result }, - } = await this.client.rawRequest<{ sendTransaction: TransactionResult }>(sendTransaction, { - input, - }) - return result + return await this.client.create('/sendTransaction', input) } } diff --git a/backend/src/apis/dltConnector/__mocks__/DltConnectorClient.ts b/backend/src/apis/dltConnector/__mocks__/DltConnectorClient.ts new file mode 100644 index 000000000..81a7c5398 --- /dev/null +++ b/backend/src/apis/dltConnector/__mocks__/DltConnectorClient.ts @@ -0,0 +1,55 @@ +import { CONFIG } from '@/config' +import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { getLogger } from 'log4js' + +import { TransactionDraft } from '@/apis/dltConnector/model/TransactionDraft' +import { IRestResponse } from 'typed-rest-client' + +const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.apis.dltConnector`) + +// Source: https://refactoring.guru/design-patterns/singleton/typescript/example +// and ../federation/client/FederationClientFactory.ts +/** + * A Singleton class defines the `getInstance` method that lets clients access + * the unique singleton instance. + */ + +export class DltConnectorClient { + private static instance: DltConnectorClient + /** + * The Singleton's constructor should always be private to prevent direct + * construction calls with the `new` operator. + */ + + private constructor() {} + + /** + * The static method that controls the access to the singleton instance. + * + * This implementation let you subclass the Singleton class while keeping + * just one instance of each subclass around. + */ + public static getInstance(): DltConnectorClient | undefined { + if (!CONFIG.DLT_CONNECTOR || !CONFIG.DLT_CONNECTOR_URL) { + logger.info(`dlt-connector are disabled via config...`) + return + } + if (!DltConnectorClient.instance) { + DltConnectorClient.instance = new DltConnectorClient() + } + return DltConnectorClient.instance + } + + /** + * transmit transaction via dlt-connector to hiero + * and update dltTransactionId of transaction in db with hiero transaction id + */ + public async sendTransaction(input: TransactionDraft): Promise> { + logger.debug('transmit transaction or user to dlt connector', input) + return Promise.resolve({ + statusCode: 200, + result: 'test', + headers: {}, + }) + } +} diff --git a/backend/src/apis/dltConnector/interaction/transactionToDlt/AbstractTransactionToDlt.role.ts b/backend/src/apis/dltConnector/interaction/transactionToDlt/AbstractTransactionToDlt.role.ts index 5e756fb7d..22f7104b2 100644 --- a/backend/src/apis/dltConnector/interaction/transactionToDlt/AbstractTransactionToDlt.role.ts +++ b/backend/src/apis/dltConnector/interaction/transactionToDlt/AbstractTransactionToDlt.role.ts @@ -3,8 +3,7 @@ import { ObjectLiteral, OrderByCondition, SelectQueryBuilder } from 'typeorm' import { DltTransaction } from 'database' import { TransactionDraft } from '@dltConnector/model/TransactionDraft' -import { getLogger, Logger } from 'log4js' -import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { Logger } from 'log4js' export abstract class AbstractTransactionToDltRole { protected self: T | null diff --git a/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkDeleteToDlt.role.ts b/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkDeleteToDlt.role.ts index b8eaa633a..d4964a9f8 100644 --- a/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkDeleteToDlt.role.ts +++ b/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkDeleteToDlt.role.ts @@ -2,14 +2,14 @@ import { DltTransaction, TransactionLink } from 'database' import { DltTransactionType } from '@dltConnector/enum/DltTransactionType' import { TransactionType } from '@dltConnector/enum/TransactionType' -import { CommunityUser } from '@dltConnector/model/CommunityUser' import { IdentifierSeed } from '@dltConnector/model/IdentifierSeed' import { TransactionDraft } from '@dltConnector/model/TransactionDraft' -import { UserIdentifier } from '@dltConnector/model/UserIdentifier' +import { AccountIdentifier } from '@dltConnector/model/AccountIdentifier' import { LogError } from '@/server/LogError' import { AbstractTransactionToDltRole } from './AbstractTransactionToDlt.role' +import { CommunityAccountIdentifier } from '@dltConnector/model/CommunityAccountIdentifier' /** * redeem deferred transfer transaction by creator, so "deleting" it @@ -17,7 +17,10 @@ import { AbstractTransactionToDltRole } from './AbstractTransactionToDlt.role' export class TransactionLinkDeleteToDltRole extends AbstractTransactionToDltRole { async initWithLast(): Promise { const queryBuilder = this.createQueryForPendingItems( - TransactionLink.createQueryBuilder().leftJoinAndSelect('TransactionLink.user', 'user'), + TransactionLink + .createQueryBuilder() + .leftJoinAndSelect('TransactionLink.user', 'user') + .leftJoinAndSelect('user.community', 'community'), 'TransactionLink.id = dltTransaction.transactionLinkId and dltTransaction.type_id <> 4', // eslint-disable-next-line camelcase { TransactionLink_deletedAt: 'ASC', User_id: 'ASC' }, @@ -67,8 +70,15 @@ export class TransactionLinkDeleteToDltRole extends AbstractTransactionToDltRole const draft = new TransactionDraft() draft.amount = this.self.amount.abs().toString() const user = this.self.user - draft.user = new UserIdentifier(user.communityUuid, new IdentifierSeed(this.self.code)) - draft.linkedUser = new UserIdentifier(user.communityUuid, new CommunityUser(user.gradidoID, 1)) + if (!user.community) { + throw new LogError(`missing community for user ${user.id}`) + } + const topicId = user.community.hieroTopicId + if (!topicId) { + throw new LogError(`missing topicId for community ${user.community.id}`) + } + draft.user = new AccountIdentifier(topicId, new IdentifierSeed(this.self.code)) + draft.linkedUser = new AccountIdentifier(topicId, new CommunityAccountIdentifier(user.gradidoID)) draft.createdAt = this.self.deletedAt.toISOString() draft.type = TransactionType.GRADIDO_REDEEM_DEFERRED_TRANSFER return draft diff --git a/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkToDlt.role.ts b/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkToDlt.role.ts index 3d2717301..05f9d319e 100644 --- a/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkToDlt.role.ts +++ b/backend/src/apis/dltConnector/interaction/transactionToDlt/TransactionLinkToDlt.role.ts @@ -2,14 +2,14 @@ import { DltTransaction, TransactionLink } from 'database' import { DltTransactionType } from '@dltConnector/enum/DltTransactionType' import { TransactionType } from '@dltConnector/enum/TransactionType' -import { CommunityUser } from '@dltConnector/model/CommunityUser' import { IdentifierSeed } from '@dltConnector/model/IdentifierSeed' import { TransactionDraft } from '@dltConnector/model/TransactionDraft' -import { UserIdentifier } from '@dltConnector/model/UserIdentifier' +import { AccountIdentifier } from '@dltConnector/model/AccountIdentifier' import { LogError } from '@/server/LogError' import { AbstractTransactionToDltRole } from './AbstractTransactionToDlt.role' +import { CommunityAccountIdentifier } from '../../model/CommunityAccountIdentifier' /** * send transactionLink as Deferred Transfers @@ -17,7 +17,10 @@ import { AbstractTransactionToDltRole } from './AbstractTransactionToDlt.role' export class TransactionLinkToDltRole extends AbstractTransactionToDltRole { async initWithLast(): Promise { this.self = await this.createQueryForPendingItems( - TransactionLink.createQueryBuilder().leftJoinAndSelect('TransactionLink.user', 'user'), + TransactionLink + .createQueryBuilder() + .leftJoinAndSelect('TransactionLink.user', 'user') + .leftJoinAndSelect('user.community', 'community'), 'TransactionLink.id = dltTransaction.transactionLinkId', // eslint-disable-next-line camelcase { TransactionLink_createdAt: 'ASC', User_id: 'ASC' }, @@ -39,8 +42,15 @@ export class TransactionLinkToDltRole extends AbstractTransactionToDltRole { async initWithLast(): Promise { this.self = await this.createQueryForPendingItems( - User.createQueryBuilder(), + User.createQueryBuilder().leftJoinAndSelect('User.community', 'community'), 'User.id = dltTransaction.userId', // eslint-disable-next-line camelcase { User_created_at: 'ASC', User_id: 'ASC' }, @@ -36,8 +36,15 @@ export class UserToDltRole extends AbstractTransactionToDltRole { if (!this.self) { throw new LogError('try to create dlt entry for empty transaction') } + if (!this.self.community) { + throw new LogError(`missing community for user ${this.self.id}`) + } + const topicId = this.self.community.hieroTopicId + if (!topicId) { + throw new LogError(`missing topicId for community ${this.self.community.id}`) + } const draft = new TransactionDraft() - draft.user = new UserIdentifier(this.self.communityUuid, new CommunityUser(this.self.gradidoID)) + draft.user = new AccountIdentifier(topicId, new CommunityAccountIdentifier(this.self.gradidoID)) draft.createdAt = this.self.createdAt.toISOString() draft.accountType = AccountType.COMMUNITY_HUMAN draft.type = TransactionType.REGISTER_ADDRESS diff --git a/backend/src/apis/dltConnector/interaction/transactionToDlt/transactionToDlt.context.ts b/backend/src/apis/dltConnector/interaction/transactionToDlt/transactionToDlt.context.ts index b03bd5300..cb1d8cca2 100644 --- a/backend/src/apis/dltConnector/interaction/transactionToDlt/transactionToDlt.context.ts +++ b/backend/src/apis/dltConnector/interaction/transactionToDlt/transactionToDlt.context.ts @@ -1,14 +1,13 @@ import { Transaction, TransactionLink, User } from 'database' import { DltConnectorClient } from '@/apis/dltConnector/DltConnectorClient' -import { TransactionResult } from '@/apis/dltConnector/model/TransactionResult' import { AbstractTransactionToDltRole } from './AbstractTransactionToDlt.role' import { TransactionLinkDeleteToDltRole } from './TransactionLinkDeleteToDlt.role' import { TransactionLinkToDltRole } from './TransactionLinkToDlt.role' import { TransactionToDltRole } from './TransactionToDlt.role' import { UserToDltRole } from './UserToDlt.role' -import { getLogger } from 'log4js' +import { getLogger, Logger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' /** @@ -16,10 +15,9 @@ import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' * Context for sending transactions to dlt connector, always the oldest not sended transaction first */ export async function transactionToDlt(dltConnector: DltConnectorClient): Promise { - async function findNextPendingTransaction(): Promise< + async function findNextPendingTransaction(logger: Logger): Promise< AbstractTransactionToDltRole > { - const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}/apis/dltConnector/interaction/transactionToDlt`) // collect each oldest not sended entity from db and choose oldest const results = await Promise.all([ new TransactionToDltRole(logger).initWithLast(), @@ -34,18 +32,28 @@ export async function transactionToDlt(dltConnector: DltConnectorClient): Promis }) return results[0] } + + const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.apis.dltConnector.interaction.transactionToDlt`) while (true) { - const pendingTransactionRole = await findNextPendingTransaction() + const pendingTransactionRole = await findNextPendingTransaction(logger) const pendingTransaction = pendingTransactionRole.getEntity() if (!pendingTransaction) { break } let messageId = '' let error: string | null = null - let result: TransactionResult | undefined try { - result = await dltConnector.sendTransaction(pendingTransactionRole.convertToGraphqlInput()) + const result = await dltConnector.sendTransaction( + pendingTransactionRole.convertToGraphqlInput() + ) + if (result.statusCode === 200 && result.result) { + messageId = result.result + } else { + error = `empty result with status code ${result.statusCode}` + logger.error('error from dlt-connector', result) + } } catch (e) { + logger.debug(e) if (e instanceof Error) { error = e.message } else if (typeof e === 'string') { @@ -54,13 +62,6 @@ export async function transactionToDlt(dltConnector: DltConnectorClient): Promis throw e } } - if (result?.succeed && result.recipe) { - messageId = result.recipe.messageIdHex - } else if (result?.error) { - error = result.error.message - logger.error('error from dlt-connector', result.error) - } - await pendingTransactionRole.saveTransactionResult(messageId, error) } } diff --git a/backend/src/apis/dltConnector/model/AccountIdentifier.ts b/backend/src/apis/dltConnector/model/AccountIdentifier.ts new file mode 100644 index 000000000..ed1d61e51 --- /dev/null +++ b/backend/src/apis/dltConnector/model/AccountIdentifier.ts @@ -0,0 +1,17 @@ +import { CommunityAccountIdentifier } from './CommunityAccountIdentifier' +import { IdentifierSeed } from './IdentifierSeed' + +export class AccountIdentifier { + communityTopicId: string + account?: CommunityAccountIdentifier + seed?: IdentifierSeed // used for deferred transfers + + constructor(communityTopicId: string, input: CommunityAccountIdentifier | IdentifierSeed) { + if (input instanceof CommunityAccountIdentifier) { + this.account = input + } else if (input instanceof IdentifierSeed) { + this.seed = input + } + this.communityTopicId = communityTopicId + } +} diff --git a/backend/src/apis/dltConnector/model/CommunityAccountIdentifier.ts b/backend/src/apis/dltConnector/model/CommunityAccountIdentifier.ts new file mode 100644 index 000000000..1e8b6a64f --- /dev/null +++ b/backend/src/apis/dltConnector/model/CommunityAccountIdentifier.ts @@ -0,0 +1,10 @@ +export class CommunityAccountIdentifier { + // for community user, uuid and communityUuid used + userUuid: string + accountNr?: number + + constructor(userUuid: string, accountNr?: number) { + this.userUuid = userUuid + this.accountNr = accountNr + } +} diff --git a/backend/src/apis/dltConnector/model/CommunityUser.ts b/backend/src/apis/dltConnector/model/CommunityUser.ts deleted file mode 100644 index 0a4eadebf..000000000 --- a/backend/src/apis/dltConnector/model/CommunityUser.ts +++ /dev/null @@ -1,10 +0,0 @@ -export class CommunityUser { - // for community user, uuid and communityUuid used - uuid: string - accountNr?: number - - constructor(uuid: string, accountNr?: number) { - this.uuid = uuid - this.accountNr = accountNr - } -} diff --git a/backend/src/apis/dltConnector/model/TransactionDraft.ts b/backend/src/apis/dltConnector/model/TransactionDraft.ts index d197fe629..8dba79bdc 100755 --- a/backend/src/apis/dltConnector/model/TransactionDraft.ts +++ b/backend/src/apis/dltConnector/model/TransactionDraft.ts @@ -2,12 +2,12 @@ import { AccountType } from '@dltConnector/enum/AccountType' import { TransactionType } from '@dltConnector/enum/TransactionType' -import { UserIdentifier } from './UserIdentifier' +import { AccountIdentifier } from './AccountIdentifier' export class TransactionDraft { - user: UserIdentifier + user: AccountIdentifier // not used for simply register address - linkedUser?: UserIdentifier + linkedUser?: AccountIdentifier // not used for register address amount?: string memo?: string diff --git a/backend/src/apis/dltConnector/model/TransactionError.ts b/backend/src/apis/dltConnector/model/TransactionError.ts deleted file mode 100644 index a2b1348a5..000000000 --- a/backend/src/apis/dltConnector/model/TransactionError.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { TransactionErrorType } from '@dltConnector/enum/TransactionErrorType' - -export interface TransactionError { - type: TransactionErrorType - message: string - name: string -} diff --git a/backend/src/apis/dltConnector/model/TransactionRecipe.ts b/backend/src/apis/dltConnector/model/TransactionRecipe.ts deleted file mode 100644 index 504ff2044..000000000 --- a/backend/src/apis/dltConnector/model/TransactionRecipe.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { TransactionType } from '@dltConnector/enum/TransactionType' - -export interface TransactionRecipe { - createdAt: string - type: TransactionType - messageIdHex: string -} diff --git a/backend/src/apis/dltConnector/model/TransactionResult.ts b/backend/src/apis/dltConnector/model/TransactionResult.ts deleted file mode 100644 index 510907429..000000000 --- a/backend/src/apis/dltConnector/model/TransactionResult.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { TransactionError } from './TransactionError' -import { TransactionRecipe } from './TransactionRecipe' - -export interface TransactionResult { - error?: TransactionError - recipe?: TransactionRecipe - succeed: boolean -} diff --git a/backend/src/apis/dltConnector/model/UserIdentifier.ts b/backend/src/apis/dltConnector/model/UserIdentifier.ts deleted file mode 100644 index 059405bd0..000000000 --- a/backend/src/apis/dltConnector/model/UserIdentifier.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { CommunityUser } from './CommunityUser' -import { IdentifierSeed } from './IdentifierSeed' - -export class UserIdentifier { - communityUuid: string - communityUser?: CommunityUser - seed?: IdentifierSeed // used for deferred transfers - - constructor(communityUuid: string, input: CommunityUser | IdentifierSeed) { - if (input instanceof CommunityUser) { - this.communityUser = input - } else if (input instanceof IdentifierSeed) { - this.seed = input - } - this.communityUuid = communityUuid - } -} diff --git a/backend/src/apis/dltConnector/sendTransactionsToDltConnector.test.ts b/backend/src/apis/dltConnector/sendTransactionsToDltConnector.test.ts index b5ec0a08a..50af15e9a 100644 --- a/backend/src/apis/dltConnector/sendTransactionsToDltConnector.test.ts +++ b/backend/src/apis/dltConnector/sendTransactionsToDltConnector.test.ts @@ -1,9 +1,5 @@ -import { ApolloServerTestClient } from 'apollo-server-testing' import { Community, DltTransaction, Transaction } from 'database' import { Decimal } from 'decimal.js-light' -// import { GraphQLClient } from 'graphql-request' -// import { Response } from 'graphql-request/dist/types' -import { GraphQLClient } from 'graphql-request' import { Response } from 'graphql-request/dist/types' import { DataSource } from 'typeorm' import { v4 as uuidv4 } from 'uuid' @@ -15,11 +11,11 @@ import { CONFIG } from '@/config' import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId' import { creations } from '@/seeds/creation' import { creationFactory } from '@/seeds/factory/creation' -import { userFactory } from '@/seeds/factory/user' -import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' -import { bobBaumeister } from '@/seeds/users/bob-baumeister' -import { peterLustig } from '@/seeds/users/peter-lustig' -import { raeuberHotzenplotz } from '@/seeds/users/raeuber-hotzenplotz' +import { userFactory } from 'database/src/seeds/factory/user' +import { bibiBloxberg } from 'database/src/seeds/users/bibi-bloxberg' +import { bobBaumeister } from 'database/src/seeds/users/bob-baumeister' +import { peterLustig } from 'database/src/seeds/users/peter-lustig' +import { raeuberHotzenplotz } from 'database/src/seeds/users/raeuber-hotzenplotz' import { getLogger } from 'config-schema/test/testSetup' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' @@ -31,63 +27,6 @@ const logger = getLogger( `${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.sendTransactionsToDltConnector`, ) -/* -// Mock the GraphQLClient -jest.mock('graphql-request', () => { - const originalModule = jest.requireActual('graphql-request') - - let testCursor = 0 - - return { - __esModule: true, - ...originalModule, - GraphQLClient: jest.fn().mockImplementation((url: string) => { - if (url === 'invalid') { - throw new Error('invalid url') - } - return { - // why not using mockResolvedValueOnce or mockReturnValueOnce? - // I have tried, but it didn't work and return every time the first value - request: jest.fn().mockImplementation(() => { - testCursor++ - if (testCursor === 4) { - return Promise.resolve( - // invalid, is 33 Bytes long as binary - { - transmitTransaction: { - dltTransactionIdHex: - '723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc516212A', - }, - }, - ) - } else if (testCursor === 5) { - throw Error('Connection error') - } else { - return Promise.resolve( - // valid, is 32 Bytes long as binary - { - transmitTransaction: { - dltTransactionIdHex: - '723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621', - }, - }, - ) - } - }), - } - }), - } -}) -let mutate: ApolloServerTestClient['mutate'], - query: ApolloServerTestClient['query'], - con: Connection -let testEnv: { - mutate: ApolloServerTestClient['mutate'] - query: ApolloServerTestClient['query'] - con: Connection -} -*/ - async function createHomeCommunity(): Promise { const homeCommunity = Community.create() homeCommunity.foreign = false @@ -336,8 +275,6 @@ async function createTxReceive1FromSend3(verified: boolean): Promise { CONFIG.DLT_CONNECTOR = true - jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => { - return { - data: { - sendTransaction: { succeed: true }, - }, - } as Response - }) - await sendTransactionsToDltConnector() expect(logger.info).toBeCalledWith('sendTransactionsToDltConnector...') diff --git a/backend/src/apis/dltConnector/sendTransactionsToDltConnector.ts b/backend/src/apis/dltConnector/sendTransactionsToDltConnector.ts index 3b0bfbc27..ef58ed606 100644 --- a/backend/src/apis/dltConnector/sendTransactionsToDltConnector.ts +++ b/backend/src/apis/dltConnector/sendTransactionsToDltConnector.ts @@ -16,7 +16,7 @@ import { transactionToDlt } from './interaction/transactionToDlt/transactionToDl import { getLogger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}/apis/dltConnector/sendTransactionsToDltConnector`) +const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.apis.dltConnector.sendTransactionsToDltConnector`) let isLoopRunning = true diff --git a/bun.lock b/bun.lock index b49609f5c..532b20dc6 100644 --- a/bun.lock +++ b/bun.lock @@ -113,10 +113,10 @@ "await-semaphore": "^0.1.3", "axios": "^0.21.1", "class-validator": "^0.13.1", - "config-schema": "workspace:*", - "core": "workspace:*", + "config-schema": "*", + "core": "*", "cors": "^2.8.5", - "database": "workspace:*", + "database": "*", "decimal.js-light": "^2.5.1", "dotenv": "^10.0.0", "esbuild": "^0.25.2", @@ -146,7 +146,7 @@ "random-bigint": "^0.0.1", "reflect-metadata": "^0.1.13", "regenerator-runtime": "^0.14.1", - "shared": "workspace:*", + "shared": "*", "source-map-support": "^0.5.21", "ts-jest": "29.4.0", "ts-node": "^10.9.2", diff --git a/database/entity/0088-add_dlt_users_table/DltTransaction.ts b/database/entity/0088-add_dlt_users_table/DltTransaction.ts deleted file mode 100644 index 653077bac..000000000 --- a/database/entity/0088-add_dlt_users_table/DltTransaction.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm' -import { Transaction } from '../Transaction' - -@Entity('dlt_transactions', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) -export class DltTransaction extends BaseEntity { - @PrimaryGeneratedColumn('increment', { unsigned: true }) - id: number - - @Column({ name: 'transaction_id', type: 'int', unsigned: true, nullable: false }) - transactionId: number - - @Column({ - name: 'message_id', - length: 64, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - messageId: string - - @Column({ name: 'verified', type: 'bool', nullable: false, default: false }) - verified: boolean - - @Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP(3)', nullable: false }) - createdAt: Date - - @Column({ name: 'verified_at', nullable: true, default: null, type: 'datetime' }) - verifiedAt: Date | null - - @Column({ name: 'error', type: 'text', nullable: true }) - error: string | null - - @OneToOne(() => Transaction, (transaction) => transaction.dltTransaction) - @JoinColumn({ name: 'transaction_id' }) - transaction?: Transaction | null -} diff --git a/database/entity/0088-add_dlt_users_table/DltUser.ts b/database/entity/0088-add_dlt_users_table/DltUser.ts deleted file mode 100644 index 2b9dccb3f..000000000 --- a/database/entity/0088-add_dlt_users_table/DltUser.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm' -// this Entity was removed in current code and isn't any longer compatible with user -import { User } from './User' - -@Entity('dlt_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) -export class DltUser extends BaseEntity { - @PrimaryGeneratedColumn('increment', { unsigned: true }) - id: number - - @Column({ name: 'user_id', type: 'int', unsigned: true, nullable: false }) - userId: number - - @Column({ - name: 'message_id', - length: 64, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - messageId: string - - @Column({ name: 'verified', type: 'bool', nullable: false, default: false }) - verified: boolean - - @Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP(3)', nullable: false }) - createdAt: Date - - @Column({ name: 'verified_at', nullable: true, default: null, type: 'datetime' }) - verifiedAt: Date | null - - @Column({ name: 'error', type: 'text', nullable: true }) - error: string | null - - @OneToOne(() => User, (user) => user.dltUser) - @JoinColumn({ name: 'user_id' }) - user?: User | null -} diff --git a/database/entity/0088-add_dlt_users_table/User.ts b/database/entity/0088-add_dlt_users_table/User.ts deleted file mode 100644 index f9b079a04..000000000 --- a/database/entity/0088-add_dlt_users_table/User.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { - BaseEntity, - Entity, - PrimaryGeneratedColumn, - Column, - DeleteDateColumn, - OneToMany, - JoinColumn, - OneToOne, - Geometry, - ManyToOne, -} from 'typeorm' -import { Contribution } from '../Contribution' -import { ContributionMessage } from '../ContributionMessage' -import { UserContact } from '../UserContact' -import { UserRole } from '../UserRole' -import { GeometryTransformer } from '../../src/typeorm/GeometryTransformer' -import { Community } from '../Community' -// removed in current version -import { DltUser } from './DltUser' - -@Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) -export class User extends BaseEntity { - @PrimaryGeneratedColumn('increment', { unsigned: true }) - id: number - - @Column({ type: 'bool', default: false }) - foreign: boolean - - @Column({ - name: 'gradido_id', - length: 36, - nullable: false, - collation: 'utf8mb4_unicode_ci', - }) - gradidoID: string - - @Column({ - name: 'community_uuid', - type: 'char', - length: 36, - nullable: true, - collation: 'utf8mb4_unicode_ci', - }) - communityUuid: string - - @ManyToOne(() => Community, (community) => community.users) - @JoinColumn({ name: 'community_uuid', referencedColumnName: 'communityUuid' }) - community: Community | null - - @Column({ - name: 'alias', - length: 20, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - alias: string - - @OneToOne(() => UserContact, (emailContact: UserContact) => emailContact.user) - @JoinColumn({ name: 'email_id' }) - emailContact: UserContact - - @Column({ name: 'email_id', type: 'int', unsigned: true, nullable: true, default: null }) - emailId: number | null - - @Column({ - name: 'first_name', - length: 255, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - firstName: string - - @Column({ - name: 'last_name', - length: 255, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - lastName: string - - @Column({ name: 'gms_publish_name', type: 'int', unsigned: true, nullable: false, default: 0 }) - gmsPublishName: number - - @Column({ name: 'humhub_publish_name', type: 'int', unsigned: true, nullable: false, default: 0 }) - humhubPublishName: number - - @Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP(3)', nullable: false }) - createdAt: Date - - @DeleteDateColumn({ name: 'deleted_at', nullable: true }) - deletedAt: Date | null - - @Column({ type: 'bigint', default: 0, unsigned: true }) - password: BigInt - - @Column({ - name: 'password_encryption_type', - type: 'int', - unsigned: true, - nullable: false, - default: 0, - }) - passwordEncryptionType: number - - @Column({ length: 4, default: 'de', collation: 'utf8mb4_unicode_ci', nullable: false }) - language: string - - @Column({ type: 'bool', default: false }) - hideAmountGDD: boolean - - @Column({ type: 'bool', default: false }) - hideAmountGDT: boolean - - @OneToMany(() => UserRole, (userRole) => userRole.user) - @JoinColumn({ name: 'user_id' }) - userRoles: UserRole[] - - @Column({ name: 'referrer_id', type: 'int', unsigned: true, nullable: true, default: null }) - referrerId?: number | null - - @Column({ - name: 'contribution_link_id', - type: 'int', - unsigned: true, - nullable: true, - default: null, - }) - contributionLinkId?: number | null - - @Column({ name: 'publisher_id', default: 0 }) - publisherId: number - - @Column({ name: 'gms_allowed', type: 'bool', default: true }) - gmsAllowed: boolean - - @Column({ - name: 'location', - type: 'geometry', - default: null, - nullable: true, - transformer: GeometryTransformer, - }) - location: Geometry | null - - @Column({ - name: 'gms_publish_location', - type: 'int', - unsigned: true, - nullable: false, - default: 2, - }) - gmsPublishLocation: number - - @Column({ name: 'gms_registered', type: 'bool', default: false }) - gmsRegistered: boolean - - @Column({ name: 'gms_registered_at', type: 'datetime', default: null, nullable: true }) - gmsRegisteredAt: Date | null - - @Column({ name: 'humhub_allowed', type: 'bool', default: false }) - humhubAllowed: boolean - - @OneToMany(() => Contribution, (contribution) => contribution.user) - @JoinColumn({ name: 'user_id' }) - contributions?: Contribution[] - - @OneToMany(() => ContributionMessage, (message) => message.user) - @JoinColumn({ name: 'user_id' }) - messages?: ContributionMessage[] - - @OneToMany(() => UserContact, (userContact: UserContact) => userContact.user) - @JoinColumn({ name: 'user_id' }) - userContacts?: UserContact[] - - @OneToOne(() => DltUser, (dlt) => dlt.userId) - @JoinColumn({ name: 'id', referencedColumnName: 'userId' }) - dltUser?: DltUser | null -} diff --git a/database/entity/0089-merge_dlt_tables/DltTransaction.ts b/database/entity/0089-merge_dlt_tables/DltTransaction.ts deleted file mode 100644 index 012bddf0b..000000000 --- a/database/entity/0089-merge_dlt_tables/DltTransaction.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm' -import { Transaction } from '../Transaction' -import { User } from '../User' -import { TransactionLink } from '../TransactionLink' - -@Entity('dlt_transactions', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) -export class DltTransaction extends BaseEntity { - @PrimaryGeneratedColumn('increment', { unsigned: true }) - id: number - - @Column({ name: 'transaction_id', type: 'int', unsigned: true, nullable: true }) - transactionId?: number | null - - @Column({ name: 'user_id', type: 'int', unsigned: true, nullable: true }) - userId?: number | null - - @Column({ name: 'transaction_link_id', type: 'int', unsigned: true, nullable: true }) - transactionLinkId?: number | null - - @Column({ name: 'type_id', unsigned: true, nullable: false }) - typeId: number - - @Column({ - name: 'message_id', - length: 64, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - messageId: string - - @Column({ name: 'verified', type: 'bool', nullable: false, default: false }) - verified: boolean - - @Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP(3)', nullable: false }) - createdAt: Date - - @Column({ name: 'verified_at', nullable: true, default: null, type: 'datetime' }) - verifiedAt: Date | null - - @Column({ name: 'error', type: 'text', nullable: true }) - error: string | null - - @OneToOne(() => Transaction, (transaction) => transaction.dltTransaction) - @JoinColumn({ name: 'transaction_id' }) - transaction?: Transaction | null - - @OneToOne(() => User, (user) => user.dltTransaction) - @JoinColumn({ name: 'user_id' }) - user?: User | null - - @OneToOne(() => TransactionLink, (transactionLink) => transactionLink.dltTransaction) - @JoinColumn({ name: 'transaction_link_id' }) - transactionLink?: TransactionLink | null -} diff --git a/database/entity/0089-merge_dlt_tables/Transaction.ts b/database/entity/0089-merge_dlt_tables/Transaction.ts deleted file mode 100644 index 8eec4e1a9..000000000 --- a/database/entity/0089-merge_dlt_tables/Transaction.ts +++ /dev/null @@ -1,176 +0,0 @@ -/* eslint-disable no-use-before-define */ -import { Decimal } from 'decimal.js-light' -import { - BaseEntity, - Entity, - PrimaryGeneratedColumn, - Column, - OneToOne, - JoinColumn, - ManyToOne, -} from 'typeorm' -import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' -import { Contribution } from '../Contribution' -import { DltTransaction } from '../DltTransaction' -import { TransactionLink } from '../TransactionLink' - -@Entity('transactions') -export class Transaction extends BaseEntity { - @PrimaryGeneratedColumn('increment', { unsigned: true }) - id: number - - @Column({ type: 'int', unsigned: true, unique: true, nullable: true, default: null }) - previous: number | null - - @Column({ name: 'type_id', unsigned: true, nullable: false }) - typeId: number - - @Column({ - name: 'transaction_link_id', - type: 'int', - unsigned: true, - nullable: true, - default: null, - }) - transactionLinkId?: number | null - - @Column({ - type: 'decimal', - precision: 40, - scale: 20, - nullable: false, - transformer: DecimalTransformer, - }) - amount: Decimal - - @Column({ - type: 'decimal', - precision: 40, - scale: 20, - nullable: false, - transformer: DecimalTransformer, - }) - balance: Decimal - - @Column({ - name: 'balance_date', - type: 'datetime', - default: () => 'CURRENT_TIMESTAMP', - nullable: false, - }) - balanceDate: Date - - @Column({ - type: 'decimal', - precision: 40, - scale: 20, - nullable: false, - transformer: DecimalTransformer, - }) - decay: Decimal - - @Column({ - name: 'decay_start', - type: 'datetime', - nullable: true, - default: null, - }) - decayStart: Date | null - - @Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) - memo: string - - @Column({ name: 'creation_date', type: 'datetime', nullable: true, default: null }) - creationDate: Date | null - - @Column({ name: 'user_id', unsigned: true, nullable: false }) - userId: number - - @Column({ - name: 'user_community_uuid', - type: 'varchar', - length: 36, - nullable: true, - collation: 'utf8mb4_unicode_ci', - }) - userCommunityUuid: string | null - - @Column({ - name: 'user_gradido_id', - type: 'varchar', - length: 36, - nullable: false, - collation: 'utf8mb4_unicode_ci', - }) - userGradidoID: string - - @Column({ - name: 'user_name', - type: 'varchar', - length: 512, - nullable: true, - collation: 'utf8mb4_unicode_ci', - }) - userName: string | null - - @Column({ - name: 'linked_user_id', - type: 'int', - unsigned: true, - nullable: true, - default: null, - }) - linkedUserId?: number | null - - @Column({ - name: 'linked_user_community_uuid', - type: 'varchar', - length: 36, - nullable: true, - collation: 'utf8mb4_unicode_ci', - }) - linkedUserCommunityUuid: string | null - - @Column({ - name: 'linked_user_gradido_id', - type: 'varchar', - length: 36, - nullable: true, - collation: 'utf8mb4_unicode_ci', - }) - linkedUserGradidoID: string | null - - @Column({ - name: 'linked_user_name', - type: 'varchar', - length: 512, - nullable: true, - collation: 'utf8mb4_unicode_ci', - }) - linkedUserName: string | null - - @Column({ - name: 'linked_transaction_id', - type: 'int', - unsigned: true, - nullable: true, - default: null, - }) - linkedTransactionId?: number | null - - @OneToOne(() => Contribution, (contribution) => contribution.transaction) - @JoinColumn({ name: 'id', referencedColumnName: 'transactionId' }) - contribution?: Contribution | null - - @OneToOne(() => DltTransaction, (dlt) => dlt.transactionId) - @JoinColumn({ name: 'id', referencedColumnName: 'transactionId' }) - dltTransaction?: DltTransaction | null - - @OneToOne(() => Transaction) - @JoinColumn({ name: 'previous' }) - previousTransaction?: Transaction | null - - @ManyToOne(() => TransactionLink, (transactionLink) => transactionLink.transactions) - @JoinColumn({ name: 'transaction_link_id' }) - transactionLink?: TransactionLink | null -} diff --git a/database/entity/0089-merge_dlt_tables/TransactionLink.ts b/database/entity/0089-merge_dlt_tables/TransactionLink.ts deleted file mode 100644 index 18bcf9892..000000000 --- a/database/entity/0089-merge_dlt_tables/TransactionLink.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Decimal } from 'decimal.js-light' -import { - BaseEntity, - Entity, - PrimaryGeneratedColumn, - Column, - DeleteDateColumn, - OneToOne, - JoinColumn, - OneToMany, -} from 'typeorm' -import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' -import { DltTransaction } from '../DltTransaction' -import { User } from '../User' -import { Transaction } from '../Transaction' - -@Entity('transaction_links') -export class TransactionLink extends BaseEntity { - @PrimaryGeneratedColumn('increment', { unsigned: true }) - id: number - - @Column({ unsigned: true, nullable: false }) - userId: number - - @Column({ - type: 'decimal', - precision: 40, - scale: 20, - nullable: false, - transformer: DecimalTransformer, - }) - amount: Decimal - - @Column({ - type: 'decimal', - name: 'hold_available_amount', - precision: 40, - scale: 20, - nullable: false, - transformer: DecimalTransformer, - }) - holdAvailableAmount: Decimal - - @Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) - memo: string - - @Column({ length: 24, nullable: false, collation: 'utf8mb4_unicode_ci' }) - code: string - - @Column({ - type: 'datetime', - nullable: false, - }) - createdAt: Date - - @DeleteDateColumn() - deletedAt: Date | null - - @Column({ - type: 'datetime', - nullable: false, - }) - validUntil: Date - - @Column({ - type: 'datetime', - nullable: true, - }) - redeemedAt: Date | null - - @Column({ type: 'int', unsigned: true, nullable: true }) - redeemedBy: number | null - - @OneToOne(() => DltTransaction, (dlt) => dlt.transactionLinkId) - @JoinColumn({ name: 'id', referencedColumnName: 'transactionLinkId' }) - dltTransaction?: DltTransaction | null - - @OneToOne(() => User, (user) => user.transactionLink) - @JoinColumn({ name: 'userId' }) - user: User - - @OneToMany(() => Transaction, (transaction) => transaction.transactionLink) - @JoinColumn({ referencedColumnName: 'transaction_link_id' }) - transactions: Transaction[] -} diff --git a/database/entity/0089-merge_dlt_tables/User.ts b/database/entity/0089-merge_dlt_tables/User.ts deleted file mode 100644 index 64a6261ab..000000000 --- a/database/entity/0089-merge_dlt_tables/User.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { - BaseEntity, - Entity, - PrimaryGeneratedColumn, - Column, - DeleteDateColumn, - OneToMany, - JoinColumn, - OneToOne, - Geometry, - ManyToOne, -} from 'typeorm' -import { Contribution } from '../Contribution' -import { ContributionMessage } from '../ContributionMessage' -import { UserContact } from '../UserContact' -import { UserRole } from '../UserRole' -import { GeometryTransformer } from '../../src/typeorm/GeometryTransformer' -import { Community } from '../Community' -import { DltTransaction } from '../DltTransaction' -import { TransactionLink } from './TransactionLink' - -@Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) -export class User extends BaseEntity { - @PrimaryGeneratedColumn('increment', { unsigned: true }) - id: number - - @Column({ type: 'bool', default: false }) - foreign: boolean - - @Column({ - name: 'gradido_id', - length: 36, - nullable: false, - collation: 'utf8mb4_unicode_ci', - }) - gradidoID: string - - @Column({ - name: 'community_uuid', - type: 'char', - length: 36, - nullable: true, - collation: 'utf8mb4_unicode_ci', - }) - communityUuid: string - - @ManyToOne(() => Community, (community) => community.users) - @JoinColumn({ name: 'community_uuid', referencedColumnName: 'communityUuid' }) - community: Community | null - - @Column({ - name: 'alias', - length: 20, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - alias: string - - @OneToOne(() => UserContact, (emailContact: UserContact) => emailContact.user) - @JoinColumn({ name: 'email_id' }) - emailContact: UserContact - - @Column({ name: 'email_id', type: 'int', unsigned: true, nullable: true, default: null }) - emailId: number | null - - @Column({ - name: 'first_name', - length: 255, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - firstName: string - - @Column({ - name: 'last_name', - length: 255, - nullable: true, - default: null, - collation: 'utf8mb4_unicode_ci', - }) - lastName: string - - @Column({ name: 'gms_publish_name', type: 'int', unsigned: true, nullable: false, default: 0 }) - gmsPublishName: number - - @Column({ name: 'humhub_publish_name', type: 'int', unsigned: true, nullable: false, default: 0 }) - humhubPublishName: number - - @Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP(3)', nullable: false }) - createdAt: Date - - @DeleteDateColumn({ name: 'deleted_at', nullable: true }) - deletedAt: Date | null - - @Column({ type: 'bigint', default: 0, unsigned: true }) - password: BigInt - - @Column({ - name: 'password_encryption_type', - type: 'int', - unsigned: true, - nullable: false, - default: 0, - }) - passwordEncryptionType: number - - @Column({ length: 4, default: 'de', collation: 'utf8mb4_unicode_ci', nullable: false }) - language: string - - @Column({ type: 'bool', default: false }) - hideAmountGDD: boolean - - @Column({ type: 'bool', default: false }) - hideAmountGDT: boolean - - @OneToMany(() => UserRole, (userRole) => userRole.user) - @JoinColumn({ name: 'user_id' }) - userRoles: UserRole[] - - @Column({ name: 'referrer_id', type: 'int', unsigned: true, nullable: true, default: null }) - referrerId?: number | null - - @Column({ - name: 'contribution_link_id', - type: 'int', - unsigned: true, - nullable: true, - default: null, - }) - contributionLinkId?: number | null - - @Column({ name: 'publisher_id', default: 0 }) - publisherId: number - - @Column({ name: 'gms_allowed', type: 'bool', default: true }) - gmsAllowed: boolean - - @Column({ - name: 'location', - type: 'geometry', - default: null, - nullable: true, - transformer: GeometryTransformer, - }) - location: Geometry | null - - @Column({ - name: 'gms_publish_location', - type: 'int', - unsigned: true, - nullable: false, - default: 2, - }) - gmsPublishLocation: number - - @Column({ name: 'gms_registered', type: 'bool', default: false }) - gmsRegistered: boolean - - @Column({ name: 'gms_registered_at', type: 'datetime', default: null, nullable: true }) - gmsRegisteredAt: Date | null - - @Column({ name: 'humhub_allowed', type: 'bool', default: false }) - humhubAllowed: boolean - - @OneToMany(() => Contribution, (contribution) => contribution.user) - @JoinColumn({ name: 'user_id' }) - contributions?: Contribution[] - - @OneToMany(() => ContributionMessage, (message) => message.user) - @JoinColumn({ name: 'user_id' }) - messages?: ContributionMessage[] - - @OneToMany(() => UserContact, (userContact: UserContact) => userContact.user) - @JoinColumn({ name: 'user_id' }) - userContacts?: UserContact[] - - @OneToOne(() => DltTransaction, (dlt) => dlt.userId) - @JoinColumn({ name: 'id', referencedColumnName: 'userId' }) - dltTransaction?: DltTransaction | null - - @OneToOne(() => TransactionLink, (transactionLink) => transactionLink.userId) - @JoinColumn({ name: 'id', referencedColumnName: 'userId' }) - transactionLink?: TransactionLink | null -} diff --git a/database/entity/DltTransaction.ts b/database/entity/DltTransaction.ts deleted file mode 100644 index bc3244dc0..000000000 --- a/database/entity/DltTransaction.ts +++ /dev/null @@ -1 +0,0 @@ -export { DltTransaction } from './0089-merge_dlt_tables/DltTransaction' diff --git a/database/entity/Transaction.ts b/database/entity/Transaction.ts deleted file mode 100644 index 2f4b2ccfc..000000000 --- a/database/entity/Transaction.ts +++ /dev/null @@ -1 +0,0 @@ -export { Transaction } from './0089-merge_dlt_tables/Transaction' diff --git a/database/entity/TransactionLink.ts b/database/entity/TransactionLink.ts deleted file mode 100644 index fa8af166d..000000000 --- a/database/entity/TransactionLink.ts +++ /dev/null @@ -1 +0,0 @@ -export { TransactionLink } from './0089-merge_dlt_tables/TransactionLink' diff --git a/database/entity/User.ts b/database/entity/User.ts deleted file mode 100644 index 92b529cb1..000000000 --- a/database/entity/User.ts +++ /dev/null @@ -1 +0,0 @@ -export { User } from './0089-merge_dlt_tables/User' diff --git a/dlt-connector/src/client/hiero/HieroClient.ts b/dlt-connector/src/client/hiero/HieroClient.ts index c06eedf8b..9c48800d8 100644 --- a/dlt-connector/src/client/hiero/HieroClient.ts +++ b/dlt-connector/src/client/hiero/HieroClient.ts @@ -75,6 +75,8 @@ export class HieroClient { this.logger.info( `message sent to topic ${topicId}, status: ${sendReceipt.status.toString()}, transaction id: ${sendResponse.transactionId.toString()}`, ) + const record = await sendResponse.getRecordWithSigner(this.wallet) + this.logger.info(`message sent, cost: ${record.transactionFee.toString()}`) return { receipt: sendReceipt, response: sendResponse } } @@ -120,6 +122,8 @@ export class HieroClient { const createReceipt = await createResponse.getReceiptWithSigner(this.wallet) this.logger.debug(createReceipt.toString()) this.logger.addContext('topicId', createReceipt.topicId?.toString()) + const record = await createResponse.getRecordWithSigner(this.wallet) + this.logger.info(`topic created, cost: ${record.transactionFee.toString()}`) return parse(hieroIdSchema, createReceipt.topicId?.toString()) } @@ -133,5 +137,7 @@ export class HieroClient { const updateResponse = await transaction.executeWithSigner(this.wallet) const updateReceipt = await updateResponse.getReceiptWithSigner(this.wallet) this.logger.debug(updateReceipt.toString()) + const record = await updateResponse.getRecordWithSigner(this.wallet) + this.logger.info(`topic updated, cost: ${record.transactionFee.toString()}`) } } diff --git a/dlt-connector/src/index.ts b/dlt-connector/src/index.ts index cafd1a006..e2eb30a8a 100644 --- a/dlt-connector/src/index.ts +++ b/dlt-connector/src/index.ts @@ -87,7 +87,8 @@ async function homeCommunitySetup({ backend, hiero }: Clients, logger: Logger): } else { // if topic exist, check if we need to update it let topicInfo = await hiero.getTopicInfo(homeCommunity.hieroTopicId) - if ( + console.log(`topicInfo: ${JSON.stringify(topicInfo, null, 2)}`) + /*if ( topicInfo.expirationTime.getTime() - new Date().getTime() < MIN_TOPIC_EXPIRE_MILLISECONDS_FOR_UPDATE ) { @@ -96,7 +97,7 @@ async function homeCommunitySetup({ backend, hiero }: Clients, logger: Logger): logger.info( `updated topic info, new expiration time: ${topicInfo.expirationTime.toLocaleDateString()}`, ) - } + }*/ } if (!homeCommunity.hieroTopicId) { throw new Error('still no topic id, after creating topic and update community in backend.') diff --git a/dlt-connector/src/interactions/sendToHiero/SendToHiero.context.ts b/dlt-connector/src/interactions/sendToHiero/SendToHiero.context.ts index c363ad263..996be0d10 100644 --- a/dlt-connector/src/interactions/sendToHiero/SendToHiero.context.ts +++ b/dlt-connector/src/interactions/sendToHiero/SendToHiero.context.ts @@ -88,19 +88,19 @@ export async function SendToHieroContext( if (builder.isCrossCommunityTransaction()) { const outboundTransaction = builder.buildOutbound() validate(outboundTransaction) - const outboundIotaMessageId = await sendViaHiero( + const outboundHieroTransactionId = await sendViaHiero( outboundTransaction, role.getSenderCommunityTopicId(), ) - builder.setParentMessageId(MemoryBlock.createPtr(new MemoryBlock(outboundIotaMessageId))) + builder.setParentMessageId(MemoryBlock.createPtr(new MemoryBlock(outboundHieroTransactionId))) const inboundTransaction = builder.buildInbound() validate(inboundTransaction) await sendViaHiero(inboundTransaction, role.getRecipientCommunityTopicId()) - return parse(hieroTransactionIdSchema, outboundIotaMessageId) + return parse(hieroTransactionIdSchema, outboundHieroTransactionId) } else { const transaction = builder.build() validate(transaction) - const iotaMessageId = await sendViaHiero(transaction, role.getSenderCommunityTopicId()) - return parse(hieroTransactionIdSchema, iotaMessageId) + const hieroTransactionId = await sendViaHiero(transaction, role.getSenderCommunityTopicId()) + return parse(hieroTransactionIdSchema, hieroTransactionId) } } diff --git a/dlt-connector/src/server/index.ts b/dlt-connector/src/server/index.ts index c3a00d4e3..3aa13dcac 100644 --- a/dlt-connector/src/server/index.ts +++ b/dlt-connector/src/server/index.ts @@ -1,4 +1,5 @@ import { TypeBoxFromValibot } from '@sinclair/typemap' +import { Type } from '@sinclair/typebox' import { Elysia, status } from 'elysia' import { AddressType_NONE } from 'gradido-blockchain-js' import { getLogger } from 'log4js' @@ -46,11 +47,30 @@ export const appRoutes = new Elysia() ) .post( '/sendTransaction', - async ({ body }) => await SendToHieroContext(parse(transactionSchema, body)), + async ({ body }) => { + console.log("sendTransaction was called") + return "0.0.123" + console.log(body) + console.log(parse(transactionSchema, body)) + const transaction = parse(transactionSchema, body) + return await SendToHieroContext(transaction) + }, // validation schemas { - body: TypeBoxFromValibot(transactionSchema), - response: TypeBoxFromValibot(hieroTransactionIdSchema), + // body: TypeBoxFromValibot(transactionSchema), + body: Type.Object({ + user: Type.Object({ + communityUser: Type.Object({ + uuid: Type.String({ format: 'uuid' }), + accountNr: Type.Optional(Type.String()), // optional/undefined + }), + communityUuid: Type.String({ format: 'uuid' }), + }), + createdAt: Type.String({ format: 'date-time' }), + accountType: Type.Literal('COMMUNITY_HUMAN'), + type: Type.Literal('REGISTER_ADDRESS'), + }) + // response: TypeBoxFromValibot(hieroTransactionIdSchema), }, ) @@ -76,3 +96,4 @@ async function isAccountExist(identifierAccount: IdentifierAccount): Promise