check version of gradido node, fix lint

This commit is contained in:
einhornimmond 2026-03-10 10:48:50 +01:00
parent 5bae90a236
commit 757139c3ca
15 changed files with 100 additions and 47 deletions

View File

@ -35,11 +35,18 @@ export async function checkHieroAccount(logger: Logger, clients: AppContextClien
export async function checkHomeCommunity(
appContext: AppContext,
logger: Logger,
): Promise<Community> {
): Promise<Community | undefined> {
const { backend, hiero } = appContext.clients
// wait for backend server
await isPortOpenRetry(backend.url)
try {
logger.info(`Waiting for backend server to become available at ${backend.url}`)
await isPortOpenRetry(backend.url)
} catch (e) {
logger.error(`Backend server at ${backend.url} is not reachable`)
return
}
// ask backend for home community
let homeCommunity = await backend.getHomeCommunityDraft()
// on missing topicId, create one
@ -58,7 +65,7 @@ export async function checkHomeCommunity(
await hiero.updateTopic(homeCommunity.hieroTopicId)
topicInfo = await hiero.getTopicInfo(homeCommunity.hieroTopicId)
logger.info(
`updated topic info, new expiration time: ${topicInfo.expirationTime.toLocaleDateString()}`,
`Topic expiration extended. New expiration time: ${topicInfo.expirationTime.toLocaleDateString()}`,
)
}
}
@ -66,9 +73,10 @@ export async function checkHomeCommunity(
throw new Error('still no topic id, after creating topic and update community in backend.')
}
appContext.cache.setHomeCommunityTopicId(homeCommunity.hieroTopicId)
logger.info(`home community topic: ${homeCommunity.hieroTopicId}`)
logger.info(`gradido node server: ${appContext.clients.gradidoNode.url}`)
logger.info(`gradido backend server: ${appContext.clients.backend.url}`)
logger.info(`Home community topic id: ${homeCommunity.hieroTopicId}`)
logger.info(`Gradido node server: ${appContext.clients.gradidoNode.url}`)
logger.info(`Gradido backend server: ${appContext.clients.backend.url}`)
await ResolveKeyPair(
new KeyPairIdentifierLogic({
communityTopicId: homeCommunity.hieroTopicId,

View File

@ -53,11 +53,24 @@ async function exportHederaAddressbooks(
async function ensureGradidoNodeRuntimeAvailable(runtimeFileName: string): Promise<void> {
const runtimeFolder = path.dirname(runtimeFileName)
const wantedVersion = `v${CONFIG.DLT_GRADIDO_NODE_SERVER_VERSION}`
checkPathExist(runtimeFolder, true)
if (!checkFileExist(runtimeFileName)) {
let versionMatch = false
const isFileExist = checkFileExist(runtimeFileName)
if (isFileExist) {
const foundVersion = await GradidoNodeProcess.checkRuntimeVersion()
if (wantedVersion !== foundVersion) {
logger.info(
`GradidoNode version detected: ${foundVersion}, required: ${wantedVersion}`
)
} else {
versionMatch = true
}
}
if (!isFileExist || !versionMatch) {
const runtimeArchiveFilename = createGradidoNodeRuntimeArchiveFilename()
const downloadUrl = new URL(
`https://github.com/gradido/gradido_node/releases/download/v${CONFIG.DLT_GRADIDO_NODE_SERVER_VERSION}/${runtimeArchiveFilename}`,
`https://github.com/gradido/gradido_node/releases/download/${wantedVersion}/${runtimeArchiveFilename}`,
)
logger.debug(`download GradidoNode Runtime from ${downloadUrl}`)
const archive = await fetch(downloadUrl)

View File

@ -1,13 +1,12 @@
import path from 'node:path'
import { Mutex } from 'async-mutex'
import { Subprocess, spawn } from 'bun'
import { $, Subprocess, spawn } from 'bun'
import { getLogger, Logger } from 'log4js'
import { CONFIG } from '../../config'
import {
GRADIDO_NODE_KILL_TIMEOUT_MILLISECONDS,
GRADIDO_NODE_MIN_RUNTIME_BEFORE_EXIT_MILLISECONDS,
GRADIDO_NODE_MIN_RUNTIME_BEFORE_RESTART_MILLISECONDS,
GRADIDO_NODE_RUNTIME_PATH,
LOG4JS_BASE_CATEGORY,
} from '../../config/const'
import { delay } from '../../utils/time'
@ -51,6 +50,10 @@ export class GradidoNodeProcess {
return path.join(CONFIG.DLT_GRADIDO_NODE_SERVER_HOME_FOLDER, 'bin', binaryName)
}
public static async checkRuntimeVersion(): Promise<string> {
return (await $`${GradidoNodeProcess.getRuntimePathFileName()} --version`.text()).trim()
}
public start() {
if (this.proc) {
this.logger.warn('GradidoNodeProcess already running.')

View File

@ -82,9 +82,9 @@ export const configSchema = v.object({
DLT_GRADIDO_NODE_SERVER_VERSION: v.optional(
v.pipe(
v.string('The version of the DLT node server, for example: 0.9.0'),
v.regex(/^\d+\.\d+\.\d+$/),
v.regex(/^\d+\.\d+\.\d+(.\d+)?$/),
),
'0.9.4',
'0.9.6.10',
),
DLT_GRADIDO_NODE_SERVER_HOME_FOLDER: v.optional(
v.string('The home folder for the gradido dlt node server'),

View File

@ -21,6 +21,9 @@ async function main() {
// get home community, create topic if not exist, or check topic expiration and update it if needed
const homeCommunity = await checkHomeCommunity(appContext, logger)
if (!homeCommunity) {
process.exit(1)
}
// ask gradido node if community blockchain was created
// if not exist, create community root transaction

View File

@ -103,11 +103,15 @@ export class Balance {
}
toString(): string {
return JSON.stringify({
balance: this.balance.toString(),
date: this.date,
publicKey: this.publicKey.convertToHex(),
communityId: this.communityId
}, null, 2)
return JSON.stringify(
{
balance: this.balance.toString(),
date: this.date,
publicKey: this.publicKey.convertToHex(),
communityId: this.communityId,
},
null,
2,
)
}
}

View File

@ -14,6 +14,7 @@ import {
TransferAmount,
} from 'gradido-blockchain-js'
import * as v from 'valibot'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
import { addToBlockchain } from '../../blockchain'
import { Context } from '../../Context'
import { ContributionStatus } from '../../data/ContributionStatus'
@ -26,7 +27,6 @@ import {
creationTransactionDbSchema,
} from '../../valibot.schema'
import { AbstractSyncRole, IndexType } from './AbstractSync.role'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
export class CreationsSyncRole extends AbstractSyncRole<CreationTransactionDb> {
constructor(context: Context) {
@ -38,7 +38,7 @@ export class CreationsSyncRole extends AbstractSyncRole<CreationTransactionDb> {
return this.peek().confirmedAt
}
getCommunityUuids(): Uuidv4[] {
return [ this.peek().user.communityUuid ]
return [this.peek().user.communityUuid]
}
getLastIndex(): IndexType {

View File

@ -14,6 +14,7 @@ import {
} from 'gradido-blockchain-js'
import * as v from 'valibot'
import { deriveFromCode } from '../../../../data/deriveKeyPair'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
import { addToBlockchain } from '../../blockchain'
import { Context } from '../../Context'
import { Balance } from '../../data/Balance'
@ -26,7 +27,6 @@ import {
deletedTransactionLinKDbSchema,
} from '../../valibot.schema'
import { AbstractSyncRole, IndexType } from './AbstractSync.role'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
export class DeletedTransactionLinksSyncRole extends AbstractSyncRole<DeletedTransactionLinkDb> {
constructor(context: Context) {

View File

@ -11,6 +11,7 @@ import {
TransferAmount,
} from 'gradido-blockchain-js'
import * as v from 'valibot'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
import { addToBlockchain } from '../../blockchain'
import { Context } from '../../Context'
import { TransactionTypeId } from '../../data/TransactionTypeId'
@ -24,7 +25,6 @@ import {
import { toMysqlDateTime } from '../../utils'
import { CommunityContext, TransactionDb, transactionDbSchema } from '../../valibot.schema'
import { AbstractSyncRole, IndexType } from './AbstractSync.role'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
export class LocalTransactionsSyncRole extends AbstractSyncRole<TransactionDb> {
constructor(context: Context) {

View File

@ -17,6 +17,7 @@ import {
} from 'gradido-blockchain-js'
import * as v from 'valibot'
import { deriveFromCode } from '../../../../data/deriveKeyPair'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
import { addToBlockchain } from '../../blockchain'
import { Context } from '../../Context'
import { transactionLinksTable, usersTable } from '../../drizzle.schema'
@ -28,7 +29,6 @@ import {
redeemedTransactionLinkDbSchema,
} from '../../valibot.schema'
import { AbstractSyncRole, IndexType } from './AbstractSync.role'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
export class RedeemTransactionLinksSyncRole extends AbstractSyncRole<RedeemedTransactionLinkDb> {
constructor(context: Context) {

View File

@ -14,6 +14,7 @@ import {
TransferAmount,
} from 'gradido-blockchain-js'
import * as v from 'valibot'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
import { addToBlockchain } from '../../blockchain'
import { Context } from '../../Context'
import { TransactionTypeId } from '../../data/TransactionTypeId'
@ -27,7 +28,6 @@ import {
import { toMysqlDateTime } from '../../utils'
import { CommunityContext, TransactionDb, transactionDbSchema, UserDb } from '../../valibot.schema'
import { AbstractSyncRole, IndexType } from './AbstractSync.role'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
export class RemoteTransactionsSyncRole extends AbstractSyncRole<TransactionDb> {
constructor(context: Context) {
@ -41,7 +41,7 @@ export class RemoteTransactionsSyncRole extends AbstractSyncRole<TransactionDb>
getCommunityUuids(): Uuidv4[] {
const currentItem = this.peek()
return [ currentItem.user.communityUuid, currentItem.linkedUser.communityUuid ]
return [currentItem.user.communityUuid, currentItem.linkedUser.communityUuid]
}
getLastIndex(): IndexType {

View File

@ -14,11 +14,12 @@ import {
LedgerAnchor,
MemoryBlockPtr,
SearchDirection_DESC,
transactionTypeToString,
TransferAmount,
transactionTypeToString,
} from 'gradido-blockchain-js'
import * as v from 'valibot'
import { deriveFromCode } from '../../../../data/deriveKeyPair'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
import { addToBlockchain } from '../../blockchain'
import { Context } from '../../Context'
import { transactionLinksTable, usersTable } from '../../drizzle.schema'
@ -26,7 +27,6 @@ import { BlockchainError, DatabaseError, NegativeBalanceError } from '../../erro
import { reverseLegacyDecay, toMysqlDateTime } from '../../utils'
import { CommunityContext, TransactionLinkDb, transactionLinkDbSchema } from '../../valibot.schema'
import { AbstractSyncRole, IndexType } from './AbstractSync.role'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
export class TransactionLinkFundingsSyncRole extends AbstractSyncRole<TransactionLinkDb> {
constructor(context: Context) {
@ -119,7 +119,6 @@ export class TransactionLinkFundingsSyncRole extends AbstractSyncRole<Transactio
senderPublicKey: MemoryBlockPtr,
recipientPublicKey: MemoryBlockPtr,
): AccountBalances {
this.accountBalances.clear()
const senderLastBalance = this.getLastBalanceForUser(
senderPublicKey,

View File

@ -12,6 +12,7 @@ import {
import * as v from 'valibot'
import { deriveFromKeyPairAndUuid } from '../../../../data/deriveKeyPair'
import { Uuidv4Hash } from '../../../../data/Uuidv4Hash'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
import { addToBlockchain } from '../../blockchain'
import { Context } from '../../Context'
import { usersTable } from '../../drizzle.schema'
@ -19,7 +20,6 @@ import { BlockchainError, DatabaseError } from '../../errors'
import { toMysqlDateTime } from '../../utils'
import { CommunityContext, UserDb, userDbSchema } from '../../valibot.schema'
import { AbstractSyncRole, IndexType } from './AbstractSync.role'
import { Uuidv4 } from '../../../../schemas/typeGuard.schema'
export class UsersSyncRole extends AbstractSyncRole<UserDb> {
constructor(context: Context) {

View File

@ -1,6 +1,15 @@
import { Filter, Profiler, Timestamp, InteractionCreateTransactionByEvent, LedgerAnchor, Abstract } from 'gradido-blockchain-js'
import {
Abstract,
Filter,
InteractionCreateTransactionByEvent,
LedgerAnchor,
Profiler,
Timestamp,
} from 'gradido-blockchain-js'
import { Logger } from 'log4js'
import { callTime } from '../../blockchain'
import { Context } from '../../Context'
import { CommunityContext } from '../../valibot.schema'
import { nanosBalanceForUser } from './AbstractSync.role'
import { ContributionLinkTransactionSyncRole } from './ContributionLinkTransactionSync.role'
import { CreationsSyncRole } from './CreationsSync.role'
@ -10,24 +19,25 @@ import { RedeemTransactionLinksSyncRole } from './RedeemTransactionLinksSync.rol
import { RemoteTransactionsSyncRole } from './RemoteTransactionsSync.role'
import { TransactionLinkFundingsSyncRole } from './TransactionLinkFundingsSync.role'
import { UsersSyncRole } from './UsersSync.role'
import { CommunityContext } from '../../valibot.schema'
import { Logger } from 'log4js'
function processTransactionTrigger(context: CommunityContext, endDate: Date, logger: Logger) {
while(true) {
while (true) {
const lastTx = context.blockchain.findOne(Filter.LAST_TRANSACTION)
let confirmedAt: Timestamp | undefined = undefined
let confirmedAt: Timestamp | undefined
if (!lastTx) {
// no transaction, no triggers
return
} else {
const confirmedTx = lastTx.getConfirmedTransaction()
if (!confirmedTx) {
throw new Error("missing confirmed tx in transaction entry")
throw new Error('missing confirmed tx in transaction entry')
}
confirmedAt = confirmedTx.getConfirmedAt()
}
const triggerEvent = context.blockchain.findNextTransactionTriggerEventInRange(confirmedAt, new Timestamp(endDate))
const triggerEvent = context.blockchain.findNextTransactionTriggerEventInRange(
confirmedAt,
new Timestamp(endDate),
)
if (!triggerEvent) {
// no trigger, we can exit here
return
@ -35,17 +45,26 @@ function processTransactionTrigger(context: CommunityContext, endDate: Date, log
context.blockchain.removeTransactionTriggerEvent(triggerEvent)
try {
// InMemoryBlockchain extend Abstract, but between C++ -> Swig -> TypeScript it seems the info is gone, so I need to cheat a bit here
const createTransactionByEvent = new InteractionCreateTransactionByEvent(context.blockchain as unknown as Abstract)
if (!context.blockchain.createAndAddConfirmedTransaction(
createTransactionByEvent.run(triggerEvent),
new LedgerAnchor(triggerEvent.getLinkedTransactionId(), LedgerAnchor.Type_NODE_TRIGGER_TRANSACTION_ID),
triggerEvent.getTargetDate()
)) {
const createTransactionByEvent = new InteractionCreateTransactionByEvent(
context.blockchain as unknown as Abstract,
)
if (
!context.blockchain.createAndAddConfirmedTransaction(
createTransactionByEvent.run(triggerEvent),
new LedgerAnchor(
triggerEvent.getLinkedTransactionId(),
LedgerAnchor.Type_NODE_TRIGGER_TRANSACTION_ID,
),
triggerEvent.getTargetDate(),
)
) {
throw new Error('Adding trigger created Transaction Failed')
}
} catch(e) {
} catch (e) {
context.blockchain.addTransactionTriggerEvent(triggerEvent)
logger.error(`Error processing transaction trigger event for transaction: ${triggerEvent.getLinkedTransactionId()}`)
logger.error(
`Error processing transaction trigger event for transaction: ${triggerEvent.getLinkedTransactionId()}`,
)
throw e
}
}
@ -95,9 +114,13 @@ export async function syncDbWithBlockchainContext(context: Context, batchSize: n
}
const communityUuids = available[0].getCommunityUuids()
for (let i = 0; i < communityUuids.length; ++i) {
processTransactionTrigger(context.getCommunityContextByUuid(communityUuids[i]), available[0].getDate(), context.logger)
processTransactionTrigger(
context.getCommunityContextByUuid(communityUuids[i]),
available[0].getDate(),
context.logger,
)
}
available[0].toBlockchain()
transactionsCount++
if (isDebug) {

View File

@ -29,7 +29,7 @@ export async function isPortOpen(
socket.destroy()
const logger = getLogger(`${LOG4JS_BASE_CATEGORY}.network.isPortOpen`)
logger.addContext('url', url)
logger.error(`${err.message}: ${err.code}`)
logger.debug(`${err.message}: ${err.code}`)
resolve(false)
})
})