update with hiero changes and other changes

This commit is contained in:
einhornimmond 2025-09-16 07:13:02 +02:00
parent 832f2f6ce5
commit eb3bf5e904
36 changed files with 208 additions and 1100 deletions

View File

@ -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)
})
})
*/

View File

@ -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<TransactionResult | undefined> {
public async sendTransaction(input: TransactionDraft): Promise<IRestResponse<string>> {
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<string>('/sendTransaction', input)
}
}

View File

@ -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<IRestResponse<string>> {
logger.debug('transmit transaction or user to dlt connector', input)
return Promise.resolve({
statusCode: 200,
result: 'test',
headers: {},
})
}
}

View File

@ -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<T extends ObjectLiteral> {
protected self: T | null

View File

@ -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<TransactionLink> {
async initWithLast(): Promise<this> {
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

View File

@ -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<TransactionLink> {
async initWithLast(): Promise<this> {
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<Trans
const draft = new TransactionDraft()
draft.amount = this.self.amount.abs().toString()
const user = this.self.user
draft.user = new UserIdentifier(user.communityUuid, new CommunityUser(user.gradidoID, 1))
draft.linkedUser = new UserIdentifier(user.communityUuid, new IdentifierSeed(this.self.code))
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 CommunityAccountIdentifier(user.gradidoID, 1))
draft.linkedUser = new AccountIdentifier(topicId, new IdentifierSeed(this.self.code))
draft.createdAt = this.self.createdAt.toISOString()
draft.timeoutDuration = (this.self.validUntil.getTime() - this.self.createdAt.getTime()) / 1000
draft.memo = this.self.memo

View File

@ -5,7 +5,7 @@ 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 { UserIdentifier } from '@/apis/dltConnector/model/AccountIdentifier'
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
import { LogError } from '@/server/LogError'

View File

@ -3,13 +3,13 @@ import { DltTransaction, User } from 'database'
import { AccountType } from '@dltConnector/enum/AccountType'
import { DltTransactionType } from '@dltConnector/enum/DltTransactionType'
import { TransactionType } from '@dltConnector/enum/TransactionType'
import { CommunityUser } from '@dltConnector/model/CommunityUser'
import { TransactionDraft } from '@dltConnector/model/TransactionDraft'
import { UserIdentifier } from '@dltConnector/model/UserIdentifier'
import { AccountIdentifier } from '@/apis/dltConnector/model/AccountIdentifier'
import { LogError } from '@/server/LogError'
import { AbstractTransactionToDltRole } from './AbstractTransactionToDlt.role'
import { CommunityAccountIdentifier } from '../../model/CommunityAccountIdentifier'
/**
* send new user to dlt connector, will be made to RegisterAddress Transaction
@ -17,7 +17,7 @@ import { AbstractTransactionToDltRole } from './AbstractTransactionToDlt.role'
export class UserToDltRole extends AbstractTransactionToDltRole<User> {
async initWithLast(): Promise<this> {
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<User> {
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

View File

@ -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<void> {
async function findNextPendingTransaction(): Promise<
async function findNextPendingTransaction(logger: Logger): Promise<
AbstractTransactionToDltRole<Transaction | User | TransactionLink>
> {
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)
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -1,7 +0,0 @@
import { TransactionErrorType } from '@dltConnector/enum/TransactionErrorType'
export interface TransactionError {
type: TransactionErrorType
message: string
name: string
}

View File

@ -1,7 +0,0 @@
import { TransactionType } from '@dltConnector/enum/TransactionType'
export interface TransactionRecipe {
createdAt: string
type: TransactionType
messageIdHex: string
}

View File

@ -1,8 +0,0 @@
import { TransactionError } from './TransactionError'
import { TransactionRecipe } from './TransactionRecipe'
export interface TransactionResult {
error?: TransactionError
recipe?: TransactionRecipe
succeed: boolean
}

View File

@ -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
}
}

View File

@ -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<Community> {
const homeCommunity = Community.create()
homeCommunity.foreign = false
@ -336,8 +275,6 @@ async function createTxReceive1FromSend3(verified: boolean): Promise<Transaction
let con: DataSource
let testEnv: {
mutate: ApolloServerTestClient['mutate']
query: ApolloServerTestClient['query']
con: DataSource
}
@ -446,14 +383,6 @@ describe('create and send Transactions to DltConnector', () => {
CONFIG.DLT_CONNECTOR = true
jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => {
return {
data: {
sendTransaction: { succeed: true },
},
} as Response<unknown>
})
await sendTransactionsToDltConnector()
expect(logger.info).toBeCalledWith('sendTransactionsToDltConnector...')

View File

@ -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

View File

@ -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",

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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[]
}

View File

@ -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
}

View File

@ -1 +0,0 @@
export { DltTransaction } from './0089-merge_dlt_tables/DltTransaction'

View File

@ -1 +0,0 @@
export { Transaction } from './0089-merge_dlt_tables/Transaction'

View File

@ -1 +0,0 @@
export { TransactionLink } from './0089-merge_dlt_tables/TransactionLink'

View File

@ -1 +0,0 @@
export { User } from './0089-merge_dlt_tables/User'

View File

@ -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()}`)
}
}

View File

@ -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.')

View File

@ -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)
}
}

View File

@ -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<boo
}
return addressType !== AddressType_NONE
}
export type DltRoutes = typeof appRoutes

View File

@ -2667,6 +2667,11 @@
resolved "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz"
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
"@types/node@^14.11.2":
version "14.18.63"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b"
integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==
"@types/node@^17.0.21", "@types/node@^17.0.45":
version "17.0.45"
resolved "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz"