From 23e70c5f1c42e9a9f4b2413adf2409a8c09ba60d Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 6 Aug 2025 16:42:19 +0200 Subject: [PATCH 01/48] only for save current work --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 9 ++++++--- shared/src/jwt/payloadtypes/DisburseJwtPayloadType.ts | 5 ++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 32464cc82..65c2d5df6 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -39,7 +39,7 @@ import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' import { TRANSACTION_LINK_LOCK } from '@/util/TRANSACTION_LINK_LOCK' import { fullName } from '@/util/utilities' import { calculateBalance } from '@/util/validate' -import { calculateDecay, decode, DisburseJwtPayloadType, encode, RedeemJwtPayloadType, verify } from 'shared' +import { calculateDecay, decode, DisburseJwtPayloadType, encode, encryptAndSign, RedeemJwtPayloadType, verify } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getLogger, Logger } from 'log4js' @@ -655,6 +655,7 @@ export class TransactionLinkResolver { } async createDisburseJwt( + handshakeId: string, senderCommunityUuid: string, senderGradidoId: string, recipientCommunityUuid: string, @@ -670,6 +671,7 @@ export class TransactionLinkResolver { const logger = createLogger() logger.addContext('code', code.substring(0, 6)) logger.debug('TransactionLinkResolver.createDisburseJwt... args=', { + handshakeId, senderCommunityUuid, senderGradidoId, recipientCommunityUuid, @@ -683,7 +685,8 @@ export class TransactionLinkResolver { recipientAlias, }) - const disburseJwtPayloadType = new DisburseJwtPayloadType( + const disburseJwtPayload = new DisburseJwtPayloadType( + handshakeId, senderCommunityUuid, senderGradidoId, recipientCommunityUuid, @@ -696,8 +699,8 @@ export class TransactionLinkResolver { validUntil, recipientAlias, ) + const disburseJwt = await encryptAndSign(disburseJwtPayload, homeComB.privateJwtKey!, authCom.publicJwtKey!) // TODO:encode/sign the jwt normally with the private key of the recipient community, but interims with uuid - const disburseJwt = await encode(disburseJwtPayloadType, recipientCommunityUuid) logger.debug('TransactionLinkResolver.createDisburseJwt... disburseJwt=', disburseJwt) // TODO: encrypt the payload with the public key of the target/sender community return disburseJwt diff --git a/shared/src/jwt/payloadtypes/DisburseJwtPayloadType.ts b/shared/src/jwt/payloadtypes/DisburseJwtPayloadType.ts index 2940161df..426e3f58a 100644 --- a/shared/src/jwt/payloadtypes/DisburseJwtPayloadType.ts +++ b/shared/src/jwt/payloadtypes/DisburseJwtPayloadType.ts @@ -17,6 +17,7 @@ export class DisburseJwtPayloadType extends JwtPayloadType { recipientalias: string constructor( + handshakeID: string, senderCommunityUuid: string, senderGradidoId: string, recipientCommunityUuid: string, @@ -29,9 +30,7 @@ export class DisburseJwtPayloadType extends JwtPayloadType { validUntil: string, recipientAlias: string, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - super('handshakeID') - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + super(handshakeID) this.tokentype = DisburseJwtPayloadType.DISBURSE_ACTIVATION_TYPE this.sendercommunityuuid = senderCommunityUuid this.sendergradidoid = senderGradidoId From 6e5fb223d655d22bd9bedaa41518ee002f17ed76 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 20 Aug 2025 16:26:02 +0200 Subject: [PATCH 02/48] safe current work --- .../apis/dltConnector/DltConnectorClient.ts | 2 +- .../src/federation/authenticateCommunities.ts | 2 +- .../client/1_0/DisbursementClient.ts | 48 ++++ .../federation/client/1_0/FederationClient.ts | 2 +- .../processDisburseJwtOnSenderCommunity.ts | 7 + .../client/1_1/DisbursementClient.ts | 3 + .../federation/client/1_1/SendCoinsClient.ts | 3 - .../client/AuthenticationClientFactory.ts | 2 +- .../client/DisbursementClientFactory.ts | 58 +++++ .../client/FederationClientFactory.ts | 4 +- backend/src/federation/validateCommunities.ts | 2 +- backend/src/graphql/model/Transaction.ts | 2 +- .../graphql/resolver/ContributionResolver.ts | 4 +- .../resolver/TransactionLinkResolver.ts | 205 +++++++++--------- .../resolver/TransactionResolver.test.ts | 6 +- .../graphql/resolver/TransactionResolver.ts | 18 +- .../sendTransactionsToDltConnector.test.ts | 2 +- .../graphql/resolver/util/storeForeignUser.ts | 2 +- backend/src/util/virtualTransactions.ts | 2 +- bun.lock | 1 + core/package.json | 1 + .../federation/client/1_0/SendCoinsClient.ts | 9 +- .../1_0/logging/SendCoinsArgsLogging.view.ts | 2 +- .../logging/SendCoinsResultLogging.view.ts | 2 +- .../client/1_0/model/SendCoinsArgs.ts | 0 .../client/1_0/model/SendCoinsResult.ts | 0 .../client/1_0/query/revertSendCoins.ts | 0 .../1_0/query/revertSettledSendCoins.ts | 0 .../client/1_0/query/settleSendCoins.ts | 0 .../client/1_0/query/voteForSendCoins.ts | 0 .../federation/client/1_1/SendCoinsClient.ts | 3 + .../client/SendCoinsClientFactory.ts | 7 +- .../src/federation/enum/apiVersionType.ts | 0 .../src/graphql/enum/TransactionTypeId.ts | 0 .../graphql/logic}/processXComSendCoins.ts | 25 +-- core/src/index.ts | 16 +- {backend => core}/src/util/utilities.test.ts | 0 {backend => core}/src/util/utilities.ts | 0 core/tsconfig.json | 11 +- .../src/client/AuthenticationClientFactory.ts | 2 +- federation/src/client/enum/ApiVersionType.ts | 4 - .../api/1_0/resolver/DisbursementResolver.ts | 33 +++ 42 files changed, 322 insertions(+), 168 deletions(-) create mode 100644 backend/src/federation/client/1_0/DisbursementClient.ts create mode 100644 backend/src/federation/client/1_0/query/processDisburseJwtOnSenderCommunity.ts create mode 100644 backend/src/federation/client/1_1/DisbursementClient.ts delete mode 100644 backend/src/federation/client/1_1/SendCoinsClient.ts create mode 100644 backend/src/federation/client/DisbursementClientFactory.ts rename {backend => core}/src/federation/client/1_0/SendCoinsClient.ts (92%) rename {backend => core}/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts (89%) rename {backend => core}/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts (85%) rename {backend => core}/src/federation/client/1_0/model/SendCoinsArgs.ts (100%) rename {backend => core}/src/federation/client/1_0/model/SendCoinsResult.ts (100%) rename {backend => core}/src/federation/client/1_0/query/revertSendCoins.ts (100%) rename {backend => core}/src/federation/client/1_0/query/revertSettledSendCoins.ts (100%) rename {backend => core}/src/federation/client/1_0/query/settleSendCoins.ts (100%) rename {backend => core}/src/federation/client/1_0/query/voteForSendCoins.ts (100%) create mode 100644 core/src/federation/client/1_1/SendCoinsClient.ts rename {backend => core}/src/federation/client/SendCoinsClientFactory.ts (85%) rename {backend => core}/src/federation/enum/apiVersionType.ts (100%) rename {backend => core}/src/graphql/enum/TransactionTypeId.ts (100%) rename {backend/src/graphql/resolver/util => core/src/graphql/logic}/processXComSendCoins.ts (93%) rename {backend => core}/src/util/utilities.test.ts (100%) rename {backend => core}/src/util/utilities.ts (100%) delete mode 100644 federation/src/client/enum/ApiVersionType.ts create mode 100644 federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts diff --git a/backend/src/apis/dltConnector/DltConnectorClient.ts b/backend/src/apis/dltConnector/DltConnectorClient.ts index 6f5b437de..bec2990d0 100644 --- a/backend/src/apis/dltConnector/DltConnectorClient.ts +++ b/backend/src/apis/dltConnector/DltConnectorClient.ts @@ -3,7 +3,7 @@ import { GraphQLClient, gql } from 'graphql-request' import { CONFIG } from '@/config' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId' +import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' import { LogError } from '@/server/LogError' import { getLogger } from 'log4js' diff --git a/backend/src/federation/authenticateCommunities.ts b/backend/src/federation/authenticateCommunities.ts index d8946eb47..179c7e996 100644 --- a/backend/src/federation/authenticateCommunities.ts +++ b/backend/src/federation/authenticateCommunities.ts @@ -4,7 +4,7 @@ import { randombytes_random } from 'sodium-native' import { CONFIG } from '@/config' import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ensureUrlEndsWithSlash } from 'core' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { encryptAndSign, OpenConnectionJwtPayloadType } from 'shared' diff --git a/backend/src/federation/client/1_0/DisbursementClient.ts b/backend/src/federation/client/1_0/DisbursementClient.ts new file mode 100644 index 000000000..bf466feef --- /dev/null +++ b/backend/src/federation/client/1_0/DisbursementClient.ts @@ -0,0 +1,48 @@ +import { FederatedCommunity as DbFederatedCommunity } from 'database' +import { GraphQLClient } from 'graphql-request' + +import { LogError } from '@/server/LogError' +import { ensureUrlEndsWithSlash } from 'core/src/util/utilities' +import { getLogger } from 'log4js' + +import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { EncryptedTransferArgs } from 'core' +import { processDisburseJwtOnSenderCommunity as processDisburseJwtOnSenderCommunityQuery } from './query/processDisburseJwtOnSenderCommunity' + +const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.client.1_0.DisbursementClient`) + +export class DisbursementClient { + dbCom: DbFederatedCommunity + endpoint: string + client: GraphQLClient + + constructor(dbCom: DbFederatedCommunity) { + this.dbCom = dbCom + this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion).concat('/') + this.client = new GraphQLClient(this.endpoint, { + method: 'POST', + jsonSerializer: { + parse: JSON.parse, + stringify: JSON.stringify, + }, + }) + } + + async sendDisburseJwtToSenderCommunity(args: EncryptedTransferArgs): Promise { + logger.debug('sendDisburseJwtToSenderCommunity against endpoint=', this.endpoint) + try { + const { data } = await this.client.rawRequest<{ processDisburseJwtOnSenderCommunity: string }>(processDisburseJwtOnSenderCommunityQuery, { args }) + const responseJwt = data?.processDisburseJwtOnSenderCommunity + if (responseJwt) { + logger.debug('received response jwt', responseJwt) + return responseJwt + } + } catch (err) { + const errmsg = `sendDisburseJwtToSenderCommunity failed for endpoint=${this.endpoint}, err=${err}` + logger.error(errmsg) + throw new Error(errmsg) + } + return null + } + +} diff --git a/backend/src/federation/client/1_0/FederationClient.ts b/backend/src/federation/client/1_0/FederationClient.ts index df1140f9c..525765803 100644 --- a/backend/src/federation/client/1_0/FederationClient.ts +++ b/backend/src/federation/client/1_0/FederationClient.ts @@ -4,7 +4,7 @@ import { GraphQLClient } from 'graphql-request' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getPublicCommunityInfo } from '@/federation/client/1_0/query/getPublicCommunityInfo' import { getPublicKey } from '@/federation/client/1_0/query/getPublicKey' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ensureUrlEndsWithSlash } from 'core/src/util/utilities' import { getLogger } from 'log4js' import { PublicCommunityInfoLoggingView } from './logging/PublicCommunityInfoLogging.view' diff --git a/backend/src/federation/client/1_0/query/processDisburseJwtOnSenderCommunity.ts b/backend/src/federation/client/1_0/query/processDisburseJwtOnSenderCommunity.ts new file mode 100644 index 000000000..e2d0f49d9 --- /dev/null +++ b/backend/src/federation/client/1_0/query/processDisburseJwtOnSenderCommunity.ts @@ -0,0 +1,7 @@ +import { gql } from 'graphql-request' + +export const processDisburseJwtOnSenderCommunity = gql` + mutation ($args: EncryptedTransferArgs!) { + processDisburseJwtOnSenderCommunity(data: $args) + } +` diff --git a/backend/src/federation/client/1_1/DisbursementClient.ts b/backend/src/federation/client/1_1/DisbursementClient.ts new file mode 100644 index 000000000..411befe19 --- /dev/null +++ b/backend/src/federation/client/1_1/DisbursementClient.ts @@ -0,0 +1,3 @@ +import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient' + +export class DisbursementClient extends V1_0_DisbursementClient {} diff --git a/backend/src/federation/client/1_1/SendCoinsClient.ts b/backend/src/federation/client/1_1/SendCoinsClient.ts deleted file mode 100644 index cc804d0dc..000000000 --- a/backend/src/federation/client/1_1/SendCoinsClient.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient' - -export class SendCoinsClient extends V1_0_SendCoinsClient {} diff --git a/backend/src/federation/client/AuthenticationClientFactory.ts b/backend/src/federation/client/AuthenticationClientFactory.ts index 0ae0cd1b8..344753a48 100644 --- a/backend/src/federation/client/AuthenticationClientFactory.ts +++ b/backend/src/federation/client/AuthenticationClientFactory.ts @@ -3,7 +3,7 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient' import { AuthenticationClient as V1_1_AuthenticationClient } from '@/federation/client/1_1/AuthenticationClient' -import { ApiVersionType } from '@/federation/enum/apiVersionType' +import { ApiVersionType } from 'core' type AuthenticationClient = V1_0_AuthenticationClient | V1_1_AuthenticationClient diff --git a/backend/src/federation/client/DisbursementClientFactory.ts b/backend/src/federation/client/DisbursementClientFactory.ts new file mode 100644 index 000000000..01c911e92 --- /dev/null +++ b/backend/src/federation/client/DisbursementClientFactory.ts @@ -0,0 +1,58 @@ +import { FederatedCommunity as DbFederatedCommunity } from 'database' + +import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient' +import { DisbursementClient as V1_1_DisbursementClient } from '@/federation/client/1_1/DisbursementClient' +import { ApiVersionType } from 'core' + +type DisbursementClient = V1_0_DisbursementClient | V1_1_DisbursementClient + +interface DisbursementClientInstance { + id: number + + client: DisbursementClient +} + +export class DisbursementClientFactory { + private static instanceArray: DisbursementClientInstance[] = [] + + /** + * The Singleton's constructor should always be private to prevent direct + * construction calls with the `new` operator. + */ + + private constructor() {} + + private static createDisbursementClient = (dbCom: DbFederatedCommunity) => { + switch (dbCom.apiVersion) { + case ApiVersionType.V1_0: + return new V1_0_DisbursementClient(dbCom) + case ApiVersionType.V1_1: + return new V1_1_DisbursementClient(dbCom) + default: + return null + } + } + + /** + * 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(dbCom: DbFederatedCommunity): DisbursementClient | null { + const instance = DisbursementClientFactory.instanceArray.find( + (instance) => instance.id === dbCom.id, + ) + if (instance) { + return instance.client + } + const client = DisbursementClientFactory.createDisbursementClient(dbCom) + if (client) { + DisbursementClientFactory.instanceArray.push({ + id: dbCom.id, + client, + } as DisbursementClientInstance) + } + return client + } +} diff --git a/backend/src/federation/client/FederationClientFactory.ts b/backend/src/federation/client/FederationClientFactory.ts index 3660934f4..926c3c180 100644 --- a/backend/src/federation/client/FederationClientFactory.ts +++ b/backend/src/federation/client/FederationClientFactory.ts @@ -1,10 +1,8 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { FederationClient as V1_0_FederationClient } from '@/federation/client/1_0/FederationClient' - import { FederationClient as V1_1_FederationClient } from '@/federation/client/1_1/FederationClient' -import { ApiVersionType } from '@/federation/enum/apiVersionType' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ApiVersionType, ensureUrlEndsWithSlash } from 'core' type FederationClient = V1_0_FederationClient | V1_1_FederationClient diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index 478261386..36c9985c9 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -15,7 +15,7 @@ import { createKeyPair } from 'shared' import { getLogger } from 'log4js' import { startCommunityAuthentication } from './authenticateCommunities' import { PublicCommunityInfoLoggingView } from './client/1_0/logging/PublicCommunityInfoLogging.view' -import { ApiVersionType } from './enum/apiVersionType' +import { ApiVersionType } from 'core' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.validateCommunities`) diff --git a/backend/src/graphql/model/Transaction.ts b/backend/src/graphql/model/Transaction.ts index dc0849a53..ee7250271 100644 --- a/backend/src/graphql/model/Transaction.ts +++ b/backend/src/graphql/model/Transaction.ts @@ -2,7 +2,7 @@ import { Transaction as dbTransaction } from 'database' import { Decimal } from 'decimal.js-light' import { Field, Int, ObjectType } from 'type-graphql' -import { TransactionTypeId } from '@enum/TransactionTypeId' +import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' import { Decay } from './Decay' import { User } from './User' diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index c6f7b33c1..6e2a302ba 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -16,11 +16,11 @@ import { Paginated } from '@arg/Paginated' import { SearchContributionsFilterArgs } from '@arg/SearchContributionsFilterArgs' import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionType } from '@enum/ContributionType' -import { TransactionTypeId } from '@enum/TransactionTypeId' import { AdminUpdateContribution } from '@model/AdminUpdateContribution' import { Contribution, ContributionListResult } from '@model/Contribution' import { OpenCreation } from '@model/OpenCreation' import { UnconfirmedContribution } from '@model/UnconfirmedContribution' +import { TransactionTypeId } from 'core' import { RIGHTS } from '@/auth/RIGHTS' import { @@ -43,8 +43,8 @@ import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUncon import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' +import { fullName } from 'core' import { calculateDecay, Decay } from 'shared' -import { fullName } from '@/util/utilities' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { ContributionMessageType } from '@enum/ContributionMessageType' diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 65c2d5df6..546d11124 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -6,22 +6,19 @@ import { TransactionLinkFilters } from '@arg/TransactionLinkFilters' import { ContributionCycleType } from '@enum/ContributionCycleType' import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionType } from '@enum/ContributionType' -import { TransactionTypeId } from '@enum/TransactionTypeId' -import { Community } from '@model/Community' import { ContributionLink } from '@model/ContributionLink' import { Decay } from '@model/Decay' import { RedeemJwtLink } from '@model/RedeemJwtLink' import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink' import { User } from '@model/User' import { QueryLinkResult } from '@union/QueryLinkResult' +import { TransactionTypeId } from 'core' import { - AppDatabase, - Contribution as DbContribution, - ContributionLink as DbContributionLink, - Transaction as DbTransaction, + AppDatabase, Community as DbCommunity, Contribution as DbContribution, + ContributionLink as DbContributionLink, FederatedCommunity as DbFederatedCommunity, Transaction as DbTransaction, TransactionLink as DbTransactionLink, User as DbUser, - getHomeCommunity, + getHomeCommunity } from 'database' import { Decimal } from 'decimal.js-light' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' @@ -37,12 +34,16 @@ import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' import { TRANSACTION_LINK_LOCK } from '@/util/TRANSACTION_LINK_LOCK' -import { fullName } from '@/util/utilities' import { calculateBalance } from '@/util/validate' +import { fullName } from 'core' import { calculateDecay, decode, DisburseJwtPayloadType, encode, encryptAndSign, RedeemJwtPayloadType, verify } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient' +import { DisbursementClientFactory } from '@/federation/client/DisbursementClientFactory' +import { EncryptedTransferArgs } from 'core' import { getLogger, Logger } from 'log4js' +import { randombytes_random } from 'sodium-native' import { executeTransaction } from './TransactionResolver' import { getAuthenticatedCommunities, @@ -53,7 +54,7 @@ import { getLastTransaction } from './util/getLastTransaction' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' import { transactionLinkList } from './util/transactionLinkList' -const createLogger = () => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.TransactionLinkResolver`) +const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.TransactionLinkResolver.${method}`) // TODO: do not export, test it inside the resolver export const transactionLinkCode = (date: Date): string => { @@ -148,9 +149,9 @@ export class TransactionLinkResolver { @Authorized([RIGHTS.QUERY_TRANSACTION_LINK]) @Query(() => QueryLinkResult) async queryTransactionLink(@Arg('code') code: string): Promise { - const logger = createLogger() - logger.addContext('code', code.substring(0, 6)) - logger.debug('TransactionLinkResolver.queryTransactionLink...') + const methodLogger = createLogger('queryTransactionLink') + methodLogger.addContext('code', code.substring(0, 6)) + methodLogger.debug('queryTransactionLink...') if (code.match(/^CL-/)) { const contributionLink = await DbContributionLink.findOneOrFail({ where: { code: code.replace('CL-', '') }, @@ -171,7 +172,7 @@ export class TransactionLinkResolver { } // normal redeem code if (txLinkFound) { - logger.debug( + methodLogger.debug( 'TransactionLinkResolver.queryTransactionLink... normal redeem code found=', txLinkFound, ) @@ -186,7 +187,7 @@ export class TransactionLinkResolver { return new TransactionLink(dbTransactionLink, new User(user), redeemedBy, communities) } else { // redeem jwt-token - return await this.queryRedeemJwtLink(code, logger) + return await this.queryRedeemJwtLink(code, methodLogger) } } } @@ -197,8 +198,8 @@ export class TransactionLinkResolver { @Arg('code', () => String) code: string, @Ctx() context: Context, ): Promise { - const logger = createLogger() - logger.addContext('code', code.substring(0, 6)) + const methodLogger = createLogger('redeemTransactionLink') + methodLogger.addContext('code', code.substring(0, 6)) const clientTimezoneOffset = getClientTimezoneOffset(context) // const homeCom = await DbCommunity.findOneOrFail({ where: { foreign: false } }) const user = getUser(context) @@ -206,7 +207,7 @@ export class TransactionLinkResolver { // acquire lock const releaseLock = await TRANSACTIONS_LOCK.acquire() try { - logger.info('redeem contribution link...') + methodLogger.info('redeem contribution link...') const now = new Date() const queryRunner = db.getDataSource().createQueryRunner() await queryRunner.connect() @@ -221,7 +222,7 @@ export class TransactionLinkResolver { if (!contributionLink) { throw new LogError('No contribution link found to given code', code) } - logger.info('...contribution link found with id', contributionLink.id) + methodLogger.info('...contribution link found with id', contributionLink.id) if (new Date(contributionLink.validFrom).getTime() > now.getTime()) { throw new LogError('Contribution link is not valid yet', contributionLink.validFrom) } @@ -278,7 +279,7 @@ export class TransactionLinkResolver { } const creations = await getUserCreation(user.id, clientTimezoneOffset) - logger.info('open creations', creations) + methodLogger.info('open creations', creations) validateContribution(creations, contributionLink.amount, now, clientTimezoneOffset) const contribution = new DbContribution() contribution.userId = user.id @@ -383,7 +384,7 @@ export class TransactionLinkResolver { transactionLink.memo, linkedUser, user, - logger, + methodLogger, transactionLink, ) await EVENT_TRANSACTION_LINK_REDEEM( @@ -413,9 +414,9 @@ export class TransactionLinkResolver { @Arg('alias', { nullable: true }) alias?: string, @Arg('validUntil', { nullable: true }) validUntil?: string, ): Promise { - const logger = createLogger() - logger.addContext('code', code.substring(0, 6)) - logger.debug('TransactionLinkResolver.queryRedeemJwt... args=', { + const methodLogger = createLogger('createRedeemJwt') + methodLogger.addContext('code', code.substring(0, 6)) + methodLogger.debug('args=', { gradidoId, senderCommunityUuid, senderCommunityName, @@ -466,40 +467,80 @@ export class TransactionLinkResolver { @Arg('validUntil', { nullable: true }) validUntil?: string, @Arg('recipientAlias', { nullable: true }) recipientAlias?: string, ): Promise { - const logger = createLogger() - logger.addContext('code', code.substring(0, 6)) - logger.debug('TransactionLinkResolver.disburseTransactionLink... args=', { - senderGradidoId, - senderCommunityUuid, - recipientCommunityUuid, - recipientCommunityName, - recipientGradidoId, - recipientFirstName, - code, - amount, - memo, - validUntil, + const handshakeID = randombytes_random().toString() + const methodLogger = createLogger(`disburseTransactionLink`) + methodLogger.addContext('handshakeID', handshakeID) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('args=', { + senderGradidoId, + senderCommunityUuid, + recipientCommunityUuid, + recipientCommunityName, + recipientGradidoId, + recipientFirstName, + code, + amount, + memo, + validUntil, recipientAlias, - }) - const disburseJwt = await this.createDisburseJwt( - senderCommunityUuid, - senderGradidoId, - recipientCommunityUuid, - recipientCommunityName, - recipientGradidoId, - recipientFirstName, - code, - amount, - memo, - validUntil ?? '', - recipientAlias ?? '', - ) - try { - logger.debug('TransactionLinkResolver.disburseTransactionLink... disburseJwt=', disburseJwt) - // now send the disburseJwt to the sender community to invoke a x-community-tx to disbures the redeemLink - // await sendDisburseJwtToSenderCommunity(context, disburseJwt) - } catch (e) { - throw new LogError('Disburse JWT was not sent successfully', e) + }) + } + const senderCom = await DbCommunity.findOneBy({ communityUuid: senderCommunityUuid }) + if (!senderCom) { + const errmsg = `Sender community not found with uuid=${senderCommunityUuid}` + methodLogger.error(errmsg) + throw new LogError(errmsg) + } + const senderFedCom = await DbFederatedCommunity.findOneBy({ publicKey: senderCom.publicKey }) + if (!senderFedCom) { + const errmsg = `Sender federated community not found with publicKey=${senderCom.publicKey}` + methodLogger.error(errmsg) + throw new LogError(errmsg) + } + const recipientCom = await DbCommunity.findOneBy({ communityUuid: recipientCommunityUuid }) + if (!recipientCom) { + const errmsg = `Recipient community not found with uuid=${recipientCommunityUuid}` + methodLogger.error(errmsg) + throw new LogError(errmsg) + } + const client = DisbursementClientFactory.getInstance(senderFedCom) + if (client instanceof V1_0_DisbursementClient) { + const disburseJwtPayload = new DisburseJwtPayloadType( + handshakeID, + senderCommunityUuid, + senderGradidoId, + recipientCommunityUuid, + recipientCommunityName, + recipientGradidoId, + recipientFirstName, + code, + amount, + memo, + validUntil!, + recipientAlias!, + ) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('disburseJwtPayload=', disburseJwtPayload) + } + const jws = await encryptAndSign(disburseJwtPayload, recipientCom.privateJwtKey!, senderCom.publicJwtKey!) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('jws=', jws) + } + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = handshakeID + try { + // now send the disburseJwt to the sender community to invoke a x-community-tx to disbures the redeemLink + const result = await client.sendDisburseJwtToSenderCommunity(args) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('Disburse JWT was sent successfully with result=', result) + } + } catch (e) { + const errmsg = `Disburse JWT was not sent successfully with error=${e}` + methodLogger.error(errmsg) + throw new Error(errmsg) + } } return true } @@ -653,56 +694,4 @@ export class TransactionLinkResolver { ) } } - - async createDisburseJwt( - handshakeId: string, - senderCommunityUuid: string, - senderGradidoId: string, - recipientCommunityUuid: string, - recipientCommunityName: string, - recipientGradidoId: string, - recipientFirstName: string, - code: string, - amount: string, - memo: string, - validUntil: string, - recipientAlias: string, - ): Promise { - const logger = createLogger() - logger.addContext('code', code.substring(0, 6)) - logger.debug('TransactionLinkResolver.createDisburseJwt... args=', { - handshakeId, - senderCommunityUuid, - senderGradidoId, - recipientCommunityUuid, - recipientCommunityName, - recipientGradidoId, - recipientFirstName, - code, - amount, - memo, - validUntil, - recipientAlias, - }) - - const disburseJwtPayload = new DisburseJwtPayloadType( - handshakeId, - senderCommunityUuid, - senderGradidoId, - recipientCommunityUuid, - recipientCommunityName, - recipientGradidoId, - recipientFirstName, - code, - amount, - memo, - validUntil, - recipientAlias, - ) - const disburseJwt = await encryptAndSign(disburseJwtPayload, homeComB.privateJwtKey!, authCom.publicJwtKey!) - // TODO:encode/sign the jwt normally with the private key of the recipient community, but interims with uuid - logger.debug('TransactionLinkResolver.createDisburseJwt... disburseJwt=', disburseJwt) - // TODO: encrypt the payload with the public key of the target/sender community - return disburseJwt - } } diff --git a/backend/src/graphql/resolver/TransactionResolver.test.ts b/backend/src/graphql/resolver/TransactionResolver.test.ts index 275ae77fd..e39fcefc4 100644 --- a/backend/src/graphql/resolver/TransactionResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionResolver.test.ts @@ -16,9 +16,9 @@ import { cleanDB, testEnvironment } from '@test/helpers' import { CONFIG } from '@/config' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { EventType } from '@/event/Events' -import { SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient' -import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs' -import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult' +import { SendCoinsClient } from 'core/src/federation/client/1_0/SendCoinsClient' +import { SendCoinsArgs } from 'core/src/federation/client/1_0/model/SendCoinsArgs' +import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult' import { userFactory } from '@/seeds/factory/user' import { confirmContribution, diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 06ddf6bbf..5ceef0836 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -2,7 +2,6 @@ import { AppDatabase, countOpenPendingTransactions, Community as DbCommunity, - PendingTransaction as DbPendingTransaction, Transaction as dbTransaction, TransactionLink as dbTransactionLink, User as dbUser, @@ -15,11 +14,11 @@ import { In, IsNull } from 'typeorm' import { Paginated } from '@arg/Paginated' import { TransactionSendArgs } from '@arg/TransactionSendArgs' import { Order } from '@enum/Order' -import { PendingTransactionState, SendCoinsResponseJwtPayloadType } from 'shared' -import { TransactionTypeId } from '@enum/TransactionTypeId' import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' import { User } from '@model/User' +import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' +import { SendCoinsResponseJwtPayloadType } from 'shared' import { RIGHTS } from '@/auth/RIGHTS' import { CONFIG } from '@/config' @@ -28,26 +27,25 @@ import { sendTransactionReceivedEmail, } from '@/emails/sendEmailVariants' import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Events' -import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult' import { LogError } from '@/server/LogError' import { Context, getUser } from '@/server/context' import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' import { communityUser } from '@/util/communityUser' -import { fullName } from '@/util/utilities' import { calculateBalance } from '@/util/validate' import { virtualDecayTransaction, virtualLinkTransaction } from '@/util/virtualTransactions' +import { fullName, SendCoinsResult } from 'core' -import { Logger, getLogger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { + processXComCommittingSendCoins, + processXComPendingSendCoins, +} from 'core' +import { getLogger, Logger } from 'log4js' import { BalanceResolver } from './BalanceResolver' import { GdtResolver } from './GdtResolver' import { getCommunityByIdentifier, getCommunityName, isHomeCommunity } from './util/communities' import { getLastTransaction } from './util/getLastTransaction' import { getTransactionList } from './util/getTransactionList' -import { - processXComCommittingSendCoins, - processXComPendingSendCoins, -} from './util/processXComSendCoins' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' import { storeForeignUser } from './util/storeForeignUser' import { transactionLinkSummary } from './util/transactionLinkSummary' diff --git a/backend/src/graphql/resolver/util/sendTransactionsToDltConnector.test.ts b/backend/src/graphql/resolver/util/sendTransactionsToDltConnector.test.ts index b5ec0a08a..769730544 100644 --- a/backend/src/graphql/resolver/util/sendTransactionsToDltConnector.test.ts +++ b/backend/src/graphql/resolver/util/sendTransactionsToDltConnector.test.ts @@ -12,7 +12,7 @@ import { cleanDB, testEnvironment } from '@test/helpers' import { i18n as localization } from '@test/testSetup' import { CONFIG } from '@/config' -import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId' +import { TransactionTypeId } from 'core' import { creations } from '@/seeds/creation' import { creationFactory } from '@/seeds/factory/creation' import { userFactory } from '@/seeds/factory/user' diff --git a/backend/src/graphql/resolver/util/storeForeignUser.ts b/backend/src/graphql/resolver/util/storeForeignUser.ts index adceb155e..8c33c8923 100644 --- a/backend/src/graphql/resolver/util/storeForeignUser.ts +++ b/backend/src/graphql/resolver/util/storeForeignUser.ts @@ -1,6 +1,6 @@ import { Community as DbCommunity, User as DbUser } from 'database' -import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult' +import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getLogger } from 'log4js' diff --git a/backend/src/util/virtualTransactions.ts b/backend/src/util/virtualTransactions.ts index dabaee264..0811eaf1b 100644 --- a/backend/src/util/virtualTransactions.ts +++ b/backend/src/util/virtualTransactions.ts @@ -2,7 +2,7 @@ import { Transaction as dbTransaction } from 'database' import { Decimal } from 'decimal.js-light' import { RemoveOptions, SaveOptions } from 'typeorm' -import { TransactionTypeId } from '@enum/TransactionTypeId' +import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' import { Transaction } from '@model/Transaction' import { User } from '@model/User' diff --git a/bun.lock b/bun.lock index b49609f5c..30a87f9af 100644 --- a/bun.lock +++ b/bun.lock @@ -192,6 +192,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", + "jest": "27.2.4", "type-graphql": "^1.1.1", "typescript": "^4.9.5", }, diff --git a/core/package.json b/core/package.json index a1f7a5603..0044d263f 100644 --- a/core/package.json +++ b/core/package.json @@ -27,6 +27,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", + "jest": "27.2.4", "type-graphql": "^1.1.1", "typescript": "^4.9.5" }, diff --git a/backend/src/federation/client/1_0/SendCoinsClient.ts b/core/src/federation/client/1_0/SendCoinsClient.ts similarity index 92% rename from backend/src/federation/client/1_0/SendCoinsClient.ts rename to core/src/federation/client/1_0/SendCoinsClient.ts index 13c2b8697..f4b6d49d8 100644 --- a/backend/src/federation/client/1_0/SendCoinsClient.ts +++ b/core/src/federation/client/1_0/SendCoinsClient.ts @@ -1,7 +1,6 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { GraphQLClient } from 'graphql-request' -import { LogError } from '@/server/LogError' import { ensureUrlEndsWithSlash } from '@/util/utilities' import { getLogger } from 'log4js' @@ -83,7 +82,9 @@ export class SendCoinsClient { logger.debug(`settleSendCoins successful from endpoint=${this.endpoint}`) return true } catch (err) { - throw new LogError(`settleSendCoins failed for endpoint=${this.endpoint}`, err) + const errmsg = `settleSendCoins failed for endpoint=${this.endpoint}, err=${err}` + logger.error(errmsg) + throw new Error(errmsg) } } @@ -103,7 +104,9 @@ export class SendCoinsClient { logger.debug(`revertSettledSendCoins successful from endpoint=${this.endpoint}`) return true } catch (err) { - throw new LogError(`revertSettledSendCoins failed for endpoint=${this.endpoint}`, err) + const errmsg = `revertSettledSendCoins failed for endpoint=${this.endpoint}, err=${err}` + logger.error(errmsg) + throw new Error(errmsg) } } } diff --git a/backend/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts b/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts similarity index 89% rename from backend/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts rename to core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts index 9bd8fee69..4057a2971 100644 --- a/backend/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts +++ b/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs' +import { SendCoinsArgs } from 'core/src/federation/client/1_0/model/SendCoinsArgs' export class SendCoinsArgsLoggingView extends AbstractLoggingView { public constructor(private self: SendCoinsArgs) { diff --git a/backend/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts b/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts similarity index 85% rename from backend/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts rename to core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts index 2f2ec355e..a83e211e8 100644 --- a/backend/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts +++ b/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult' +import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult' export class SendCoinsResultLoggingView extends AbstractLoggingView { public constructor(private self: SendCoinsResult) { diff --git a/backend/src/federation/client/1_0/model/SendCoinsArgs.ts b/core/src/federation/client/1_0/model/SendCoinsArgs.ts similarity index 100% rename from backend/src/federation/client/1_0/model/SendCoinsArgs.ts rename to core/src/federation/client/1_0/model/SendCoinsArgs.ts diff --git a/backend/src/federation/client/1_0/model/SendCoinsResult.ts b/core/src/federation/client/1_0/model/SendCoinsResult.ts similarity index 100% rename from backend/src/federation/client/1_0/model/SendCoinsResult.ts rename to core/src/federation/client/1_0/model/SendCoinsResult.ts diff --git a/backend/src/federation/client/1_0/query/revertSendCoins.ts b/core/src/federation/client/1_0/query/revertSendCoins.ts similarity index 100% rename from backend/src/federation/client/1_0/query/revertSendCoins.ts rename to core/src/federation/client/1_0/query/revertSendCoins.ts diff --git a/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts b/core/src/federation/client/1_0/query/revertSettledSendCoins.ts similarity index 100% rename from backend/src/federation/client/1_0/query/revertSettledSendCoins.ts rename to core/src/federation/client/1_0/query/revertSettledSendCoins.ts diff --git a/backend/src/federation/client/1_0/query/settleSendCoins.ts b/core/src/federation/client/1_0/query/settleSendCoins.ts similarity index 100% rename from backend/src/federation/client/1_0/query/settleSendCoins.ts rename to core/src/federation/client/1_0/query/settleSendCoins.ts diff --git a/backend/src/federation/client/1_0/query/voteForSendCoins.ts b/core/src/federation/client/1_0/query/voteForSendCoins.ts similarity index 100% rename from backend/src/federation/client/1_0/query/voteForSendCoins.ts rename to core/src/federation/client/1_0/query/voteForSendCoins.ts diff --git a/core/src/federation/client/1_1/SendCoinsClient.ts b/core/src/federation/client/1_1/SendCoinsClient.ts new file mode 100644 index 000000000..b37f08b29 --- /dev/null +++ b/core/src/federation/client/1_1/SendCoinsClient.ts @@ -0,0 +1,3 @@ +import { SendCoinsClient as V1_0_SendCoinsClient } from 'core/src/federation/client/1_0/SendCoinsClient' + +export class SendCoinsClient extends V1_0_SendCoinsClient {} diff --git a/backend/src/federation/client/SendCoinsClientFactory.ts b/core/src/federation/client/SendCoinsClientFactory.ts similarity index 85% rename from backend/src/federation/client/SendCoinsClientFactory.ts rename to core/src/federation/client/SendCoinsClientFactory.ts index 2fd15f739..8251da3cb 100644 --- a/backend/src/federation/client/SendCoinsClientFactory.ts +++ b/core/src/federation/client/SendCoinsClientFactory.ts @@ -1,9 +1,8 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' -import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient' - -import { SendCoinsClient as V1_1_SendCoinsClient } from '@/federation/client/1_1/SendCoinsClient' -import { ApiVersionType } from '@/federation/enum/apiVersionType' +import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' +import { SendCoinsClient as V1_1_SendCoinsClient } from '@federation/client/1_1/SendCoinsClient' +import { ApiVersionType } from '@federation/enum/apiVersionType' type SendCoinsClient = V1_0_SendCoinsClient | V1_1_SendCoinsClient diff --git a/backend/src/federation/enum/apiVersionType.ts b/core/src/federation/enum/apiVersionType.ts similarity index 100% rename from backend/src/federation/enum/apiVersionType.ts rename to core/src/federation/enum/apiVersionType.ts diff --git a/backend/src/graphql/enum/TransactionTypeId.ts b/core/src/graphql/enum/TransactionTypeId.ts similarity index 100% rename from backend/src/graphql/enum/TransactionTypeId.ts rename to core/src/graphql/enum/TransactionTypeId.ts diff --git a/backend/src/graphql/resolver/util/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts similarity index 93% rename from backend/src/graphql/resolver/util/processXComSendCoins.ts rename to core/src/graphql/logic/processXComSendCoins.ts index 91eb61a1e..3b17939d5 100644 --- a/backend/src/graphql/resolver/util/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -10,23 +10,22 @@ import { } from 'database' import { Decimal } from 'decimal.js-light' -import { CONFIG } from '@/config' +import { LOG4JS_BASE_CATEGORY_NAME } from '@config/const' -import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient' -import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs' -import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult' -import { SendCoinsClientFactory } from '@/federation/client/SendCoinsClientFactory' +import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' +import { SendCoinsArgs } from '@federation/client/1_0/model/SendCoinsArgs' +import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' +import { SendCoinsClientFactory } from '@federation/client/SendCoinsClientFactory' import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' -import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId' -import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { LogError } from '@/server/LogError' -import { calculateSenderBalance } from '@/util/calculateSenderBalance' -import { fullName } from '@/util/utilities' +import { TransactionTypeId } from '@graphql/enum/TransactionTypeId' +import { LogError } from '@server/LogError' +import { calculateSenderBalance } from '@util/calculateSenderBalance' +import { fullName } from '@util/utilities' import { getLogger } from 'log4js' -import { settlePendingSenderTransaction } from './settlePendingSenderTransaction' -import { SendCoinsArgsLoggingView } from '@/federation/client/1_0/logging/SendCoinsArgsLogging.view' -import { SendCoinsResultLoggingView } from '@/federation/client/1_0/logging/SendCoinsResultLogging.view' +import { settlePendingSenderTransaction } from '@graphql/resolver/util/settlePendingSenderTransaction' +import { SendCoinsArgsLoggingView } from '@federation/client/1_0/logging/SendCoinsArgsLogging.view' +import { SendCoinsResultLoggingView } from '@federation/client/1_0/logging/SendCoinsResultLogging.view' import { EncryptedTransferArgs } from 'core' import { randombytes_random } from 'sodium-native' diff --git a/core/src/index.ts b/core/src/index.ts index 28aae758a..3aa4a63d8 100644 --- a/core/src/index.ts +++ b/core/src/index.ts @@ -1,3 +1,17 @@ -export * from './validation/user' +export * from './federation/client/1_0/logging/SendCoinsArgsLogging.view' +export * from './federation/client/1_0/logging/SendCoinsResultLogging.view' +export * from './federation/client/1_0/model/SendCoinsArgs' +export * from './federation/client/1_0/model/SendCoinsResult' +export * from './federation/client/1_0/query/revertSendCoins' +export * from './federation/client/1_0/query/revertSettledSendCoins' +export * from './federation/client/1_0/query/settleSendCoins' +export * from './federation/client/1_0/query/voteForSendCoins' +export * from './federation/client/SendCoinsClientFactory' +export * from './federation/enum/apiVersionType' +export * from './graphql/enum/TransactionTypeId' export * from './graphql/logic/interpretEncryptedTransferArgs' +export * from './graphql/logic/processXComSendCoins' export * from './graphql/model/EncryptedTransferArgs' +export * from './util/utilities' +export * from './validation/user' + diff --git a/backend/src/util/utilities.test.ts b/core/src/util/utilities.test.ts similarity index 100% rename from backend/src/util/utilities.test.ts rename to core/src/util/utilities.test.ts diff --git a/backend/src/util/utilities.ts b/core/src/util/utilities.ts similarity index 100% rename from backend/src/util/utilities.ts rename to core/src/util/utilities.ts diff --git a/core/tsconfig.json b/core/tsconfig.json index 75b686340..660381127 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -44,8 +44,15 @@ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": ".", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + "baseUrl": ".", /* Base directory to resolve non-absolute module names. */ + "paths": { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + "@/*": ["src/*"], + "@config/*": ["src/config/*"], + "@federation/*": ["src/federation/*"], + "@graphql/*": ["src/graphql/*"], + "@util/*": ["src/util/*"], + "@validation/*": ["src/validation/*"], + }, // "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": ["bun-types"], /* Type declaration files to be included in compilation. */ diff --git a/federation/src/client/AuthenticationClientFactory.ts b/federation/src/client/AuthenticationClientFactory.ts index 29e55279d..94a74581a 100644 --- a/federation/src/client/AuthenticationClientFactory.ts +++ b/federation/src/client/AuthenticationClientFactory.ts @@ -3,7 +3,7 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { AuthenticationClient as V1_0_AuthenticationClient } from './1_0/AuthenticationClient' import { AuthenticationClient as V1_1_AuthenticationClient } from './1_1/AuthenticationClient' -import { ApiVersionType } from './enum/ApiVersionType' +import { ApiVersionType } from 'core' type AuthenticationClient = V1_0_AuthenticationClient | V1_1_AuthenticationClient diff --git a/federation/src/client/enum/ApiVersionType.ts b/federation/src/client/enum/ApiVersionType.ts deleted file mode 100644 index 60da9de57..000000000 --- a/federation/src/client/enum/ApiVersionType.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum ApiVersionType { - V1_0 = '1_0', - V1_1 = '1_1', -} diff --git a/federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts b/federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts new file mode 100644 index 000000000..629da9e54 --- /dev/null +++ b/federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts @@ -0,0 +1,33 @@ +import { getLogger } from "log4js" +import { Arg, Mutation, Resolver } from "type-graphql" + +import { LOG4JS_BASE_CATEGORY_NAME } from "@/config/const" +import { interpretEncryptedTransferArgs } from "core" +import { EncryptedTransferArgs } from "core" +import { DisburseJwtPayloadType } from "shared" + +const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.api.1_0.resolver.DisbursementResolver.${method}`) + +@Resolver() +export class DisbursementResolver { + @Mutation(() => String) + async processDisburseJwtOnSenderCommunity( + @Arg('data') + args: EncryptedTransferArgs, + ): Promise { + const methodLogger = createLogger(`processDisburseJwtOnSenderCommunity`) + methodLogger.addContext('handshakeID', args.handshakeID) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`processDisburseJwtOnSenderCommunity() via apiVersion=1_0 ...`, args) + } + const authArgs = await interpretEncryptedTransferArgs(args) as DisburseJwtPayloadType + if (!authArgs) { + const errmsg = `invalid disbursement payload of requesting community with publicKey` + args.publicKey + methodLogger.error(errmsg) + throw new Error(errmsg) + } + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`processDisburseJwtOnSenderCommunity() via apiVersion=1_0 ...`, authArgs) + } + } +} \ No newline at end of file From 0c6d8b4ba18aa3cdbaa139931e6712956253f3f2 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 20 Aug 2025 19:01:56 +0200 Subject: [PATCH 03/48] save current work --- .../client/1_0/AuthenticationClient.ts | 4 +- .../client/1_0/DisbursementClient.ts | 3 +- .../federation/client/1_0/FederationClient.ts | 2 +- backend/src/graphql/model/Transaction.ts | 3 +- .../src/graphql/resolver/BalanceResolver.ts | 4 +- .../graphql/resolver/ContributionResolver.ts | 4 +- .../resolver/TransactionLinkResolver.test.ts | 2 +- .../resolver/TransactionLinkResolver.ts | 8 +- .../resolver/TransactionResolver.test.ts | 8 +- .../graphql/resolver/TransactionResolver.ts | 6 +- backend/src/util/validate.ts | 4 +- .../federation/client/1_0/SendCoinsClient.ts | 2 +- .../1_0/logging/SendCoinsArgsLogging.view.ts | 2 +- .../logging/SendCoinsResultLogging.view.ts | 2 +- .../client/1_0/query/voteForSendCoins.ts | 11 +- .../federation/client/1_1/SendCoinsClient.ts | 2 +- .../src/graphql}/logging/DecayLogging.view.ts | 2 +- .../src/graphql/logic/processXComSendCoins.ts | 235 +++++++++++++++++- .../logic}/settlePendingSenderTransaction.ts | 28 ++- {backend => core}/src/graphql/model/Decay.ts | 0 core/src/index.ts | 5 + .../src/util/calculateSenderBalance.ts | 4 +- database/package.json | 1 + database/src/index.ts | 1 + database/src/queries/index.ts | 1 + .../src/queries/transactions.ts | 0 .../src/util/TRANSACTIONS_LOCK.ts | 0 .../src/util/TRANSACTION_LINK_LOCK.ts | 0 database/src/util/index.ts | 2 + .../src/client/1_0/AuthenticationClient.ts | 2 +- 30 files changed, 289 insertions(+), 59 deletions(-) rename {backend/src => core/src/graphql}/logging/DecayLogging.view.ts (92%) rename {backend/src/graphql/resolver/util => core/src/graphql/logic}/settlePendingSenderTransaction.ts (85%) rename {backend => core}/src/graphql/model/Decay.ts (100%) rename {backend => core}/src/util/calculateSenderBalance.ts (83%) rename backend/src/graphql/resolver/util/getLastTransaction.ts => database/src/queries/transactions.ts (100%) rename {backend => database}/src/util/TRANSACTIONS_LOCK.ts (100%) rename {backend => database}/src/util/TRANSACTION_LINK_LOCK.ts (100%) create mode 100644 database/src/util/index.ts diff --git a/backend/src/federation/client/1_0/AuthenticationClient.ts b/backend/src/federation/client/1_0/AuthenticationClient.ts index b504c0030..5d897093e 100644 --- a/backend/src/federation/client/1_0/AuthenticationClient.ts +++ b/backend/src/federation/client/1_0/AuthenticationClient.ts @@ -1,11 +1,11 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { GraphQLClient } from 'graphql-request' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ensureUrlEndsWithSlash } from 'core' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { EncryptedTransferArgs } from 'core' import { getLogger } from 'log4js' -import { EncryptedTransferArgs } from 'core/src/graphql/model/EncryptedTransferArgs' import { openConnection } from './query/openConnection' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.client.1_0.AuthenticationClient`) diff --git a/backend/src/federation/client/1_0/DisbursementClient.ts b/backend/src/federation/client/1_0/DisbursementClient.ts index bf466feef..abaf1818b 100644 --- a/backend/src/federation/client/1_0/DisbursementClient.ts +++ b/backend/src/federation/client/1_0/DisbursementClient.ts @@ -1,8 +1,7 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { GraphQLClient } from 'graphql-request' -import { LogError } from '@/server/LogError' -import { ensureUrlEndsWithSlash } from 'core/src/util/utilities' +import { ensureUrlEndsWithSlash } from 'core' import { getLogger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' diff --git a/backend/src/federation/client/1_0/FederationClient.ts b/backend/src/federation/client/1_0/FederationClient.ts index 525765803..c437ad085 100644 --- a/backend/src/federation/client/1_0/FederationClient.ts +++ b/backend/src/federation/client/1_0/FederationClient.ts @@ -4,7 +4,7 @@ import { GraphQLClient } from 'graphql-request' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getPublicCommunityInfo } from '@/federation/client/1_0/query/getPublicCommunityInfo' import { getPublicKey } from '@/federation/client/1_0/query/getPublicKey' -import { ensureUrlEndsWithSlash } from 'core/src/util/utilities' +import { ensureUrlEndsWithSlash } from 'core' import { getLogger } from 'log4js' import { PublicCommunityInfoLoggingView } from './logging/PublicCommunityInfoLogging.view' diff --git a/backend/src/graphql/model/Transaction.ts b/backend/src/graphql/model/Transaction.ts index ee7250271..0560cef54 100644 --- a/backend/src/graphql/model/Transaction.ts +++ b/backend/src/graphql/model/Transaction.ts @@ -2,9 +2,8 @@ import { Transaction as dbTransaction } from 'database' import { Decimal } from 'decimal.js-light' import { Field, Int, ObjectType } from 'type-graphql' -import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' +import { Decay, TransactionTypeId } from 'core' -import { Decay } from './Decay' import { User } from './User' @ObjectType() diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index f7388c027..d49c73c39 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -7,14 +7,14 @@ import { Balance } from '@model/Balance' import { RIGHTS } from '@/auth/RIGHTS' import { BalanceLoggingView } from '@/logging/BalanceLogging.view' -import { DecayLoggingView } from '@/logging/DecayLogging.view' +import { DecayLoggingView } from 'core/src/graphql/logging/DecayLogging.view' import { Context, getUser } from '@/server/context' import { calculateDecay } from 'shared' import { getLogger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { GdtResolver } from './GdtResolver' -import { getLastTransaction } from './util/getLastTransaction' +import { getLastTransaction } from 'database' import { transactionLinkSummary } from './util/transactionLinkSummary' @Resolver() diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 6e2a302ba..263c5c4aa 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -42,7 +42,7 @@ import { import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUnconfirmedContribution/UpdateUnconfirmedContribution.context' import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' -import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' +import { TRANSACTIONS_LOCK } from 'database' import { fullName } from 'core' import { calculateDecay, Decay } from 'shared' @@ -58,7 +58,7 @@ import { import { getOpenCreations, getUserCreation, validateContribution } from './util/creations' import { extractGraphQLFields } from './util/extractGraphQLFields' import { findContributions } from './util/findContributions' -import { getLastTransaction } from './util/getLastTransaction' +import { getLastTransaction } from 'database' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' const db = AppDatabase.getInstance() diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 7862f71f0..658d74186 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -32,7 +32,7 @@ import { listTransactionLinksAdmin } from '@/seeds/graphql/queries' import { transactionLinks } from '@/seeds/transactionLink/index' import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' import { peterLustig } from '@/seeds/users/peter-lustig' -import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' +import { TRANSACTIONS_LOCK } from 'database' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getLogger } from 'config-schema/test/testSetup' diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 546d11124..cf601a300 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -7,12 +7,11 @@ import { ContributionCycleType } from '@enum/ContributionCycleType' import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionType } from '@enum/ContributionType' import { ContributionLink } from '@model/ContributionLink' -import { Decay } from '@model/Decay' import { RedeemJwtLink } from '@model/RedeemJwtLink' import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink' import { User } from '@model/User' import { QueryLinkResult } from '@union/QueryLinkResult' -import { TransactionTypeId } from 'core' +import { Decay, TransactionTypeId } from 'core' import { AppDatabase, Community as DbCommunity, Contribution as DbContribution, ContributionLink as DbContributionLink, FederatedCommunity as DbFederatedCommunity, Transaction as DbTransaction, @@ -32,16 +31,16 @@ import { } from '@/event/Events' import { LogError } from '@/server/LogError' import { Context, getClientTimezoneOffset, getUser } from '@/server/context' -import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' -import { TRANSACTION_LINK_LOCK } from '@/util/TRANSACTION_LINK_LOCK' import { calculateBalance } from '@/util/validate' import { fullName } from 'core' +import { TRANSACTION_LINK_LOCK, TRANSACTIONS_LOCK } from 'database' import { calculateDecay, decode, DisburseJwtPayloadType, encode, encryptAndSign, RedeemJwtPayloadType, verify } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient' import { DisbursementClientFactory } from '@/federation/client/DisbursementClientFactory' import { EncryptedTransferArgs } from 'core' +import { getLastTransaction } from 'database' import { getLogger, Logger } from 'log4js' import { randombytes_random } from 'sodium-native' import { executeTransaction } from './TransactionResolver' @@ -50,7 +49,6 @@ import { getCommunityByUuid, } from './util/communities' import { getUserCreation, validateContribution } from './util/creations' -import { getLastTransaction } from './util/getLastTransaction' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' import { transactionLinkList } from './util/transactionLinkList' diff --git a/backend/src/graphql/resolver/TransactionResolver.test.ts b/backend/src/graphql/resolver/TransactionResolver.test.ts index e39fcefc4..e844ed0a5 100644 --- a/backend/src/graphql/resolver/TransactionResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionResolver.test.ts @@ -13,12 +13,12 @@ import { v4 as uuidv4 } from 'uuid' import { cleanDB, testEnvironment } from '@test/helpers' -import { CONFIG } from '@/config' +// import { CONFIG } from '@/config' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { EventType } from '@/event/Events' -import { SendCoinsClient } from 'core/src/federation/client/1_0/SendCoinsClient' -import { SendCoinsArgs } from 'core/src/federation/client/1_0/model/SendCoinsArgs' -import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult' +// import { V1_0_SendCoinsClient } from 'core' +// import { SendCoinsArgs } from 'core' +// import { SendCoinsResult } from 'core' import { userFactory } from '@/seeds/factory/user' import { confirmContribution, diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 5ceef0836..23e9f415f 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -17,7 +17,7 @@ import { Order } from '@enum/Order' import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' import { User } from '@model/User' -import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' +import { TransactionTypeId } from 'core' import { SendCoinsResponseJwtPayloadType } from 'shared' import { RIGHTS } from '@/auth/RIGHTS' @@ -29,7 +29,7 @@ import { import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Events' import { LogError } from '@/server/LogError' import { Context, getUser } from '@/server/context' -import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' +import { TRANSACTIONS_LOCK } from 'database' import { communityUser } from '@/util/communityUser' import { calculateBalance } from '@/util/validate' import { virtualDecayTransaction, virtualLinkTransaction } from '@/util/virtualTransactions' @@ -44,7 +44,7 @@ import { getLogger, Logger } from 'log4js' import { BalanceResolver } from './BalanceResolver' import { GdtResolver } from './GdtResolver' import { getCommunityByIdentifier, getCommunityName, isHomeCommunity } from './util/communities' -import { getLastTransaction } from './util/getLastTransaction' +import { getLastTransaction } from 'database' import { getTransactionList } from './util/getTransactionList' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' import { storeForeignUser } from './util/storeForeignUser' diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 1dd8a4529..1190e32aa 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -2,9 +2,9 @@ import { TransactionLink as dbTransactionLink } from 'database' import { Decimal } from 'decimal.js-light' import { validate, version } from 'uuid' -import { Decay } from '@model/Decay' +import { Decay } from 'core' -import { getLastTransaction } from '@/graphql/resolver/util/getLastTransaction' +import { getLastTransaction } from 'database' import { transactionLinkSummary } from '@/graphql/resolver/util/transactionLinkSummary' import { calculateDecay } from 'shared' diff --git a/core/src/federation/client/1_0/SendCoinsClient.ts b/core/src/federation/client/1_0/SendCoinsClient.ts index f4b6d49d8..bb8d2c858 100644 --- a/core/src/federation/client/1_0/SendCoinsClient.ts +++ b/core/src/federation/client/1_0/SendCoinsClient.ts @@ -9,7 +9,7 @@ import { revertSendCoins as revertSendCoinsQuery } from './query/revertSendCoins import { revertSettledSendCoins as revertSettledSendCoinsQuery } from './query/revertSettledSendCoins' import { settleSendCoins as settleSendCoinsQuery } from './query/settleSendCoins' import { voteForSendCoins as voteForSendCoinsQuery } from './query/voteForSendCoins' -import { EncryptedTransferArgs } from 'core' +import { EncryptedTransferArgs } from '@graphql/model/EncryptedTransferArgs' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.client.1_0.SendCoinsClient`) diff --git a/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts b/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts index 4057a2971..1db8c2887 100644 --- a/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts +++ b/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { SendCoinsArgs } from 'core/src/federation/client/1_0/model/SendCoinsArgs' +import { SendCoinsArgs } from '@federation/client/1_0/model/SendCoinsArgs' export class SendCoinsArgsLoggingView extends AbstractLoggingView { public constructor(private self: SendCoinsArgs) { diff --git a/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts b/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts index a83e211e8..383f4fd37 100644 --- a/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts +++ b/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult' +import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' export class SendCoinsResultLoggingView extends AbstractLoggingView { public constructor(private self: SendCoinsResult) { diff --git a/core/src/federation/client/1_0/query/voteForSendCoins.ts b/core/src/federation/client/1_0/query/voteForSendCoins.ts index 6fc9a11ae..9b987657c 100644 --- a/core/src/federation/client/1_0/query/voteForSendCoins.ts +++ b/core/src/federation/client/1_0/query/voteForSendCoins.ts @@ -5,13 +5,4 @@ export const voteForSendCoins = gql` voteForSendCoins(data: $args) } ` -/* - { - vote - recipGradidoID - recipFirstName - recipLastName - recipAlias - } - } -*/ + diff --git a/core/src/federation/client/1_1/SendCoinsClient.ts b/core/src/federation/client/1_1/SendCoinsClient.ts index b37f08b29..8c7f9caec 100644 --- a/core/src/federation/client/1_1/SendCoinsClient.ts +++ b/core/src/federation/client/1_1/SendCoinsClient.ts @@ -1,3 +1,3 @@ -import { SendCoinsClient as V1_0_SendCoinsClient } from 'core/src/federation/client/1_0/SendCoinsClient' +import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' export class SendCoinsClient extends V1_0_SendCoinsClient {} diff --git a/backend/src/logging/DecayLogging.view.ts b/core/src/graphql/logging/DecayLogging.view.ts similarity index 92% rename from backend/src/logging/DecayLogging.view.ts rename to core/src/graphql/logging/DecayLogging.view.ts index 538beecd5..f4f20ab6f 100644 --- a/backend/src/logging/DecayLogging.view.ts +++ b/core/src/graphql/logging/DecayLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { Decay } from '@/graphql/model/Decay' +import { Decay } from '@graphql/model/Decay' import type { Decay as DecayInterface } from 'shared' export class DecayLoggingView extends AbstractLoggingView { diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index 3b17939d5..a50fa2f8d 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -18,19 +18,105 @@ import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' import { SendCoinsClientFactory } from '@federation/client/SendCoinsClientFactory' import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' import { TransactionTypeId } from '@graphql/enum/TransactionTypeId' -import { LogError } from '@server/LogError' +// import { LogError } from '@server/LogError' import { calculateSenderBalance } from '@util/calculateSenderBalance' import { fullName } from '@util/utilities' import { getLogger } from 'log4js' -import { settlePendingSenderTransaction } from '@graphql/resolver/util/settlePendingSenderTransaction' +import { settlePendingSenderTransaction } from './settlePendingSenderTransaction' import { SendCoinsArgsLoggingView } from '@federation/client/1_0/logging/SendCoinsArgsLogging.view' import { SendCoinsResultLoggingView } from '@federation/client/1_0/logging/SendCoinsResultLogging.view' -import { EncryptedTransferArgs } from 'core' +import { EncryptedTransferArgs } from '@graphql/model/EncryptedTransferArgs' import { randombytes_random } from 'sodium-native' const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.${method}`) +/* +export async function processXComTransaction( + receiverCom: DbCommunity, + senderCom: DbCommunity, + creationDate: Date, + amount: Decimal, + memo: string, + sender: dbUser, + recipientIdentifier: string, +): Promise { + const methodLogger = createLogger(`processXComTransaction`) + // processing a x-community sendCoins + methodLogger.info('X-Com: processing a x-community transaction...') + if (!CONFIG.FEDERATION_XCOM_SENDCOINS_ENABLED) { + throw new LogError('X-Community sendCoins disabled per configuration!') + } + const recipCom = await getCommunityByIdentifier(recipientCommunityIdentifier) + methodLogger.debug('recipient community: ', recipCom?.id) + if (recipCom === null) { + throw new LogError( + `no recipient community found for identifier: ${recipientCommunityIdentifier}`, + ) + } + if (recipCom !== null && recipCom.authenticatedAt === null) { + throw new LogError('recipient community is connected, but still not authenticated yet!') + } + let pendingResult: SendCoinsResponseJwtPayloadType | null = null + let committingResult: SendCoinsResult + const creationDate = new Date() + try { + pendingResult = await processXComPendingSendCoins( + recipCom, + homeCom, + creationDate, + amount, + memo, + senderUser, + recipientIdentifier, + ) + methodLogger.debug('processXComPendingSendCoins result: ', pendingResult) + if (pendingResult && pendingResult.vote && pendingResult.recipGradidoID) { + methodLogger.debug('vor processXComCommittingSendCoins... ') + committingResult = await processXComCommittingSendCoins( + recipCom, + homeCom, + creationDate, + amount, + memo, + senderUser, + pendingResult, + ) + methodLogger.debug('processXComCommittingSendCoins result: ', committingResult) + if (!committingResult.vote) { + methodLogger.fatal('FATAL ERROR: on processXComCommittingSendCoins for', committingResult) + throw new LogError( + 'FATAL ERROR: on processXComCommittingSendCoins with ', + recipientCommunityIdentifier, + recipientIdentifier, + amount.toString(), + memo, + ) + } + // after successful x-com-tx store the recipient as foreign user + methodLogger.debug('store recipient as foreign user...') + if (await storeForeignUser(recipCom, committingResult)) { + methodLogger.info( + 'X-Com: new foreign user inserted successfully...', + recipCom.communityUuid, + committingResult.recipGradidoID, + ) + } + } + } catch (err) { + const errmsg = `ERROR: on processXComCommittingSendCoins with ` + + recipientCommunityIdentifier + + recipientIdentifier + + amount.toString() + + memo + + err + methodLogger.error(errmsg) + throw new Error(errmsg) + } + return true +} +*/ +/* export async function processXComPendingSendCoins( receiverCom: DbCommunity, senderCom: DbCommunity, @@ -82,6 +168,149 @@ export async function processXComPendingSendCoins( }) const client = SendCoinsClientFactory.getInstance(receiverFCom) + if (client instanceof V1_0_SendCoinsClient) { + const payload = new SendCoinsJwtPayloadType(handshakeID, + receiverCom.communityUuid!, + recipientIdentifier, + creationDate.toISOString(), + amount, + memo, + senderCom.communityUuid!, + sender.gradidoID, + fullName(sender.firstName, sender.lastName), + sender.alias + ) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`ready for voteForSendCoins with payload=${payload}`) + } + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, receiverCom.publicJwtKey!) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('jws', jws) + } + // prepare the args for the client invocation + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = handshakeID + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('before client.voteForSendCoins() args:', args) + } + + const responseJwt = await client.voteForSendCoins(args) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`response of voteForSendCoins():`, responseJwt) + } + if (responseJwt !== null) { + voteResult = await verifyAndDecrypt(handshakeID, responseJwt, senderCom.privateJwtKey!, receiverCom.publicJwtKey!) as SendCoinsResponseJwtPayloadType + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`calculated voteResult = ${JSON.stringify(voteResult, null, 2)}`) + } + if (voteResult && voteResult.vote && voteResult.recipGradidoID) { + methodLogger.debug('vor processXComCommittingSendCoins... ') + const committingResult = await processXComCommittingSendCoins( + receiverCom, + senderCom, + creationDate, + amount, + memo, + sender, + voteResult, + ) + methodLogger.debug('processXComCommittingSendCoins result: ', committingResult) + if (!committingResult.vote) { + methodLogger.fatal('FATAL ERROR: on processXComCommittingSendCoins for', committingResult) + throw new LogError( + 'FATAL ERROR: on processXComCommittingSendCoins with ', + recipientCommunityIdentifier, + recipientIdentifier, + amount.toString(), + memo, + ) + } + // after successful x-com-tx store the recipient as foreign user + methodLogger.debug('store recipient as foreign user...') + if (await storeForeignUser(receiverCom, committingResult)) { + methodLogger.info( + 'X-Com: new foreign user inserted successfully...', + receiverCom.communityUuid, + committingResult.recipGradidoID, + ) + } + } + } + } else { + const errmsg = `Client is not instance of V1_0_SendCoinsClient` + methodLogger.error(errmsg) + throw new LogError(errmsg) + } + } catch (err) { + const errmsg = `ERROR: on processXComCommittingSendCoins with ` + + recipientCommunityIdentifier + + recipientIdentifier + + amount.toString() + + memo + + err + throw new LogError(errmsg) + } +} + memo, + err, + ) + } + } +} +*/ +export async function processXComPendingSendCoins( + receiverCom: DbCommunity, + senderCom: DbCommunity, + creationDate: Date, + amount: Decimal, + memo: string, + sender: dbUser, + recipientIdentifier: string, +): Promise { + let voteResult: SendCoinsResponseJwtPayloadType + const methodLogger = createLogger(`processXComPendingSendCoins`) + try { + // even if debug is not enabled, attributes are processed so we skip the entire call for performance reasons + if(methodLogger.isDebugEnabled()) { + methodLogger.debug( + 'XCom: processXComPendingSendCoins...', { + receiverCom: new CommunityLoggingView(receiverCom), + senderCom: new CommunityLoggingView(senderCom), + amount: amount.toString(), + memo: memo.substring(0, 5), + sender: new UserLoggingView(sender), + recipientIdentifier + } + ) + } + if (await countOpenPendingTransactions([sender.gradidoID, recipientIdentifier]) > 0) { + const errmsg = `There exist still ongoing 'Pending-Transactions' for the involved users on sender-side!` + methodLogger.error(errmsg) + throw new Error(errmsg) + } + const handshakeID = randombytes_random().toString() + methodLogger.addContext('handshakeID', handshakeID) + // first calculate the sender balance and check if the transaction is allowed + const senderBalance = await calculateSenderBalance(sender.id, amount.mul(-1), creationDate) + if (!senderBalance) { + const errmsg = `User has not enough GDD or amount is < 0` + methodLogger.error(errmsg) + throw new Error(errmsg) + } + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`calculated senderBalance = ${JSON.stringify(senderBalance, null, 2)}`) + } + + const receiverFCom = await DbFederatedCommunity.findOneOrFail({ + where: { + publicKey: Buffer.from(receiverCom.publicKey), + apiVersion: CONFIG.FEDERATION_BACKEND_SEND_ON_API, + }, + }) + const client = SendCoinsClientFactory.getInstance(receiverFCom) + if (client instanceof V1_0_SendCoinsClient) { const payload = new SendCoinsJwtPayloadType(handshakeID, receiverCom.communityUuid!, diff --git a/backend/src/graphql/resolver/util/settlePendingSenderTransaction.ts b/core/src/graphql/logic/settlePendingSenderTransaction.ts similarity index 85% rename from backend/src/graphql/resolver/util/settlePendingSenderTransaction.ts rename to core/src/graphql/logic/settlePendingSenderTransaction.ts index c528b0ca7..8abd511c1 100644 --- a/backend/src/graphql/resolver/util/settlePendingSenderTransaction.ts +++ b/core/src/graphql/logic/settlePendingSenderTransaction.ts @@ -10,17 +10,16 @@ import { } from 'database' import { Decimal } from 'decimal.js-light' -import { PendingTransactionState } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { LogError } from '@/server/LogError' -import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' -import { calculateSenderBalance } from '@/util/calculateSenderBalance' +import { PendingTransactionState } from 'shared' +// import { LogError } from '@/server/LogError' +import { calculateSenderBalance } from 'core' +import { TRANSACTIONS_LOCK, getLastTransaction } from 'database' import { getLogger } from 'log4js' -import { getLastTransaction } from './getLastTransaction' const db = AppDatabase.getInstance() const logger = getLogger( - `${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.settlePendingSenderTransaction`, + `${LOG4JS_BASE_CATEGORY_NAME}.graphql.logic.settlePendingSenderTransaction`, ) export async function settlePendingSenderTransaction( @@ -53,15 +52,17 @@ export async function settlePendingSenderTransaction( ], }) if (openSenderPendingTx > 1 || openReceiverPendingTx > 1) { - throw new LogError('There are more than 1 pending Transactions for Sender and/or Recipient') + const errmsg = `There are more than 1 pending Transactions for Sender and/or Recipient` + logger.error(errmsg) + throw new Error(errmsg) } const lastTransaction = await getLastTransaction(senderUser.id) if (lastTransaction?.id !== pendingTx.previous) { - throw new LogError( - `X-Com: missmatching transaction order! lastTransationId=${lastTransaction?.id} != pendingTx.previous=${pendingTx.previous}`, - ) + const errmsg = `X-Com: missmatching transaction order! lastTransationId=${lastTransaction?.id} != pendingTx.previous=${pendingTx.previous}` + logger.error(errmsg) + throw new Error(errmsg) } // transfer the pendingTx to the transactions table @@ -82,7 +83,9 @@ export async function settlePendingSenderTransaction( pendingTx.balanceDate, ) if (!sendBalance) { - throw new LogError(`Sender has not enough GDD or amount is < 0', sendBalance`) + const errmsg = 'Sender has not enough GDD or amount is < 0' + logger.error(errmsg) + throw new Error(errmsg) } transactionSend.balance = sendBalance?.balance ?? new Decimal(0) transactionSend.balanceDate = pendingTx.balanceDate @@ -114,7 +117,8 @@ export async function settlePendingSenderTransaction( // void sendTransactionsToDltConnector() } catch (e) { await queryRunner.rollbackTransaction() - throw new LogError('X-Com: send Transaction was not successful', e) + logger.error('X-Com: send Transaction was not successful', e) + throw new Error('X-Com: send Transaction was not successful') } finally { await queryRunner.release() releaseLock() diff --git a/backend/src/graphql/model/Decay.ts b/core/src/graphql/model/Decay.ts similarity index 100% rename from backend/src/graphql/model/Decay.ts rename to core/src/graphql/model/Decay.ts diff --git a/core/src/index.ts b/core/src/index.ts index 3aa4a63d8..9ee34cc19 100644 --- a/core/src/index.ts +++ b/core/src/index.ts @@ -1,3 +1,4 @@ +export {SendCoinsClient as V1_0_SendCoinsClient} from './federation/client/1_0/SendCoinsClient' export * from './federation/client/1_0/logging/SendCoinsArgsLogging.view' export * from './federation/client/1_0/logging/SendCoinsResultLogging.view' export * from './federation/client/1_0/model/SendCoinsArgs' @@ -6,12 +7,16 @@ export * from './federation/client/1_0/query/revertSendCoins' export * from './federation/client/1_0/query/revertSettledSendCoins' export * from './federation/client/1_0/query/settleSendCoins' export * from './federation/client/1_0/query/voteForSendCoins' +export {SendCoinsClient as V1_1_SendCoinsClient} from './federation/client/1_1/SendCoinsClient' export * from './federation/client/SendCoinsClientFactory' export * from './federation/enum/apiVersionType' export * from './graphql/enum/TransactionTypeId' +export * from './graphql/logging/DecayLogging.view' export * from './graphql/logic/interpretEncryptedTransferArgs' export * from './graphql/logic/processXComSendCoins' +export * from './graphql/model/Decay' export * from './graphql/model/EncryptedTransferArgs' +export * from './util/calculateSenderBalance' export * from './util/utilities' export * from './validation/user' diff --git a/backend/src/util/calculateSenderBalance.ts b/core/src/util/calculateSenderBalance.ts similarity index 83% rename from backend/src/util/calculateSenderBalance.ts rename to core/src/util/calculateSenderBalance.ts index a01b1f15e..ce7609895 100644 --- a/backend/src/util/calculateSenderBalance.ts +++ b/core/src/util/calculateSenderBalance.ts @@ -1,8 +1,8 @@ import { Decimal } from 'decimal.js-light' -import { Decay } from '@model/Decay' +import { Decay } from '@graphql/model/Decay' -import { getLastTransaction } from '@/graphql/resolver/util/getLastTransaction' +import { getLastTransaction } from 'database' import { calculateDecay } from 'shared' diff --git a/database/package.json b/database/package.json index 6a6240fa1..26aa6b9e1 100644 --- a/database/package.json +++ b/database/package.json @@ -41,6 +41,7 @@ "@types/geojson": "^7946.0.13", "@types/jest": "27.0.2", "@types/node": "^18.7.14", + "await-semaphore": "^0.1.3", "crypto-random-bigint": "^2.1.1", "jest": "27.2.4", "ts-jest": "27.0.5", diff --git a/database/src/index.ts b/database/src/index.ts index 3ff4efa17..56dec24ee 100644 --- a/database/src/index.ts +++ b/database/src/index.ts @@ -60,4 +60,5 @@ export const entities = [ export { latestDbVersion } export * from './logging' export * from './queries' +export * from './util' export { AppDatabase } from './AppDatabase' diff --git a/database/src/queries/index.ts b/database/src/queries/index.ts index 9acf80871..b8ca12b86 100644 --- a/database/src/queries/index.ts +++ b/database/src/queries/index.ts @@ -3,5 +3,6 @@ import { LOG4JS_BASE_CATEGORY_NAME } from '../config/const' export * from './user' export * from './communities' export * from './pendingTransactions' +export * from './transactions' export const LOG4JS_QUERIES_CATEGORY_NAME = `${LOG4JS_BASE_CATEGORY_NAME}.queries` diff --git a/backend/src/graphql/resolver/util/getLastTransaction.ts b/database/src/queries/transactions.ts similarity index 100% rename from backend/src/graphql/resolver/util/getLastTransaction.ts rename to database/src/queries/transactions.ts diff --git a/backend/src/util/TRANSACTIONS_LOCK.ts b/database/src/util/TRANSACTIONS_LOCK.ts similarity index 100% rename from backend/src/util/TRANSACTIONS_LOCK.ts rename to database/src/util/TRANSACTIONS_LOCK.ts diff --git a/backend/src/util/TRANSACTION_LINK_LOCK.ts b/database/src/util/TRANSACTION_LINK_LOCK.ts similarity index 100% rename from backend/src/util/TRANSACTION_LINK_LOCK.ts rename to database/src/util/TRANSACTION_LINK_LOCK.ts diff --git a/database/src/util/index.ts b/database/src/util/index.ts new file mode 100644 index 000000000..b16b20d19 --- /dev/null +++ b/database/src/util/index.ts @@ -0,0 +1,2 @@ +export * from './TRANSACTIONS_LOCK' +export * from './TRANSACTION_LINK_LOCK' \ No newline at end of file diff --git a/federation/src/client/1_0/AuthenticationClient.ts b/federation/src/client/1_0/AuthenticationClient.ts index 60a205aa7..ac14bcb84 100644 --- a/federation/src/client/1_0/AuthenticationClient.ts +++ b/federation/src/client/1_0/AuthenticationClient.ts @@ -3,7 +3,7 @@ import { GraphQLClient } from 'graphql-request' import { getLogger, Logger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { EncryptedTransferArgs } from 'core/src/graphql/model/EncryptedTransferArgs' +import { EncryptedTransferArgs } from 'core' import { authenticate } from './query/authenticate' import { openConnectionCallback } from './query/openConnectionCallback' From d4b2f5494c4961fb684a33ce54832371f02378a9 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 20 Aug 2025 23:58:29 +0200 Subject: [PATCH 04/48] correct imports after shifting code to core modul --- backend/src/apis/dltConnector/DltConnectorClient.ts | 2 +- backend/src/apis/gms/GmsClient.ts | 2 +- backend/src/emails/sendEmailVariants.ts | 2 +- backend/src/graphql/model/FederatedCommunity.ts | 2 +- backend/src/graphql/resolver/BalanceResolver.ts | 6 +++--- backend/src/graphql/resolver/UserResolver.ts | 2 +- .../graphql/resolver/util/authenticateGmsUserPlayground.ts | 2 +- backend/src/graphql/resolver/util/creations.ts | 2 +- backend/src/util/virtualTransactions.ts | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/apis/dltConnector/DltConnectorClient.ts b/backend/src/apis/dltConnector/DltConnectorClient.ts index bec2990d0..17d6a3a9d 100644 --- a/backend/src/apis/dltConnector/DltConnectorClient.ts +++ b/backend/src/apis/dltConnector/DltConnectorClient.ts @@ -3,7 +3,7 @@ import { GraphQLClient, gql } from 'graphql-request' import { CONFIG } from '@/config' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' +import { TransactionTypeId } from 'core' import { LogError } from '@/server/LogError' import { getLogger } from 'log4js' diff --git a/backend/src/apis/gms/GmsClient.ts b/backend/src/apis/gms/GmsClient.ts index bb4fce2e7..7ed1df89d 100644 --- a/backend/src/apis/gms/GmsClient.ts +++ b/backend/src/apis/gms/GmsClient.ts @@ -4,7 +4,7 @@ import { httpAgent, httpsAgent } from '@/apis/ConnectionAgents' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { CONFIG } from '@/config' import { LogError } from '@/server/LogError' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ensureUrlEndsWithSlash } from 'core' import { getLogger } from 'log4js' import { GmsUser } from './model/GmsUser' diff --git a/backend/src/emails/sendEmailVariants.ts b/backend/src/emails/sendEmailVariants.ts index 642f87387..aac726002 100644 --- a/backend/src/emails/sendEmailVariants.ts +++ b/backend/src/emails/sendEmailVariants.ts @@ -1,7 +1,7 @@ import { Decimal } from 'decimal.js-light' import { CONFIG } from '@/config' -import { decimalSeparatorByLanguage } from '@/util/utilities' +import { decimalSeparatorByLanguage } from 'core' import { sendEmailTranslated } from './sendEmailTranslated' diff --git a/backend/src/graphql/model/FederatedCommunity.ts b/backend/src/graphql/model/FederatedCommunity.ts index 7029013eb..cee430dba 100644 --- a/backend/src/graphql/model/FederatedCommunity.ts +++ b/backend/src/graphql/model/FederatedCommunity.ts @@ -1,7 +1,7 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { Field, Int, ObjectType } from 'type-graphql' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ensureUrlEndsWithSlash } from 'core' @ObjectType() export class FederatedCommunity { diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index d49c73c39..0e88382ff 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -7,14 +7,14 @@ import { Balance } from '@model/Balance' import { RIGHTS } from '@/auth/RIGHTS' import { BalanceLoggingView } from '@/logging/BalanceLogging.view' -import { DecayLoggingView } from 'core/src/graphql/logging/DecayLogging.view' import { Context, getUser } from '@/server/context' +import { DecayLoggingView } from 'core' import { calculateDecay } from 'shared' -import { getLogger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { GdtResolver } from './GdtResolver' import { getLastTransaction } from 'database' +import { getLogger } from 'log4js' +import { GdtResolver } from './GdtResolver' import { transactionLinkSummary } from './util/transactionLinkSummary' @Resolver() diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index dbfad91ef..045ca7756 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -85,7 +85,7 @@ import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { communityDbUser } from '@/util/communityUser' import { hasElopageBuys } from '@/util/hasElopageBuys' import { durationInMinutesFromDates, getTimeDurationObject, printTimeDuration } from '@/util/time' -import { delay } from '@/util/utilities' +import { delay } from 'core' import random from 'random-bigint' import { randombytes_random } from 'sodium-native' diff --git a/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts b/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts index 74593f1c7..dfa775bde 100644 --- a/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts +++ b/backend/src/graphql/resolver/util/authenticateGmsUserPlayground.ts @@ -4,7 +4,7 @@ import { verifyAuthToken } from '@/apis/gms/GmsClient' import { CONFIG } from '@/config' import { GmsUserAuthenticationResult } from '@/graphql/model/GmsUserAuthenticationResult' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ensureUrlEndsWithSlash } from 'core' import { getLogger } from 'log4js' const logger = getLogger( diff --git a/backend/src/graphql/resolver/util/creations.ts b/backend/src/graphql/resolver/util/creations.ts index a0c930579..486e7cc99 100644 --- a/backend/src/graphql/resolver/util/creations.ts +++ b/backend/src/graphql/resolver/util/creations.ts @@ -6,7 +6,7 @@ import { OpenCreation } from '@model/OpenCreation' import { FULL_CREATION_AVAILABLE, MAX_CREATION_AMOUNT } from '@/graphql/resolver/const/const' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { LogError } from '@/server/LogError' -import { getFirstDayOfPreviousNMonth } from '@/util/utilities' +import { getFirstDayOfPreviousNMonth } from 'core' import { AppDatabase } from 'database' import { getLogger } from 'log4js' diff --git a/backend/src/util/virtualTransactions.ts b/backend/src/util/virtualTransactions.ts index 0811eaf1b..a3bbbe042 100644 --- a/backend/src/util/virtualTransactions.ts +++ b/backend/src/util/virtualTransactions.ts @@ -2,7 +2,7 @@ import { Transaction as dbTransaction } from 'database' import { Decimal } from 'decimal.js-light' import { RemoveOptions, SaveOptions } from 'typeorm' -import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId' +import { TransactionTypeId } from 'core' import { Transaction } from '@model/Transaction' import { User } from '@model/User' From f6db4b633d78d983674bd63f956d75d5633a69be Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Thu, 21 Aug 2025 22:10:16 +0200 Subject: [PATCH 05/48] introduce config_core --- .../resolver/TransactionLinkResolver.ts | 6 +- .../graphql/resolver/TransactionResolver.ts | 26 +- core/package.json | 1 + core/src/config/index.ts | 27 ++ core/src/config/schema.ts | 29 ++ .../src/graphql/logic/processXComSendCoins.ts | 289 ++++++------------ .../src/graphql/logic}/storeForeignUser.ts | 14 +- core/src/index.ts | 3 +- database/src/queries/communities.ts | 8 +- database/src/queries/index.ts | 1 + database/src/queries/transactionLinks.ts | 8 + database/src/queries/user.ts | 9 + 12 files changed, 199 insertions(+), 222 deletions(-) create mode 100644 core/src/config/index.ts create mode 100644 core/src/config/schema.ts rename {backend/src/graphql/resolver/util => core/src/graphql/logic}/storeForeignUser.ts (83%) create mode 100644 database/src/queries/transactionLinks.ts diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index cf601a300..28375bcab 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -17,6 +17,7 @@ import { ContributionLink as DbContributionLink, FederatedCommunity as DbFederatedCommunity, Transaction as DbTransaction, TransactionLink as DbTransactionLink, User as DbUser, + findTransactionLinkByCode, getHomeCommunity } from 'database' import { Decimal } from 'decimal.js-light' @@ -160,10 +161,7 @@ export class TransactionLinkResolver { let txLinkFound = false let dbTransactionLink!: DbTransactionLink try { - dbTransactionLink = await DbTransactionLink.findOneOrFail({ - where: { code }, - withDeleted: true, - }) + dbTransactionLink = await findTransactionLinkByCode(code) txLinkFound = true } catch (_err) { txLinkFound = false diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 23e9f415f..2ef7b69ff 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -17,8 +17,7 @@ import { Order } from '@enum/Order' import { Transaction } from '@model/Transaction' import { TransactionList } from '@model/TransactionList' import { User } from '@model/User' -import { TransactionTypeId } from 'core' -import { SendCoinsResponseJwtPayloadType } from 'shared' +import { processXComCompleteTransaction, TransactionTypeId } from 'core' import { RIGHTS } from '@/auth/RIGHTS' import { CONFIG } from '@/config' @@ -29,25 +28,20 @@ import { import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Events' import { LogError } from '@/server/LogError' import { Context, getUser } from '@/server/context' -import { TRANSACTIONS_LOCK } from 'database' import { communityUser } from '@/util/communityUser' import { calculateBalance } from '@/util/validate' import { virtualDecayTransaction, virtualLinkTransaction } from '@/util/virtualTransactions' -import { fullName, SendCoinsResult } from 'core' +import { fullName } from 'core' +import { TRANSACTIONS_LOCK } from 'database' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { - processXComCommittingSendCoins, - processXComPendingSendCoins, -} from 'core' +import { getLastTransaction } from 'database' import { getLogger, Logger } from 'log4js' import { BalanceResolver } from './BalanceResolver' import { GdtResolver } from './GdtResolver' -import { getCommunityByIdentifier, getCommunityName, isHomeCommunity } from './util/communities' -import { getLastTransaction } from 'database' +import { getCommunityName, isHomeCommunity } from './util/communities' import { getTransactionList } from './util/getTransactionList' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' -import { storeForeignUser } from './util/storeForeignUser' import { transactionLinkSummary } from './util/transactionLinkSummary' const db = AppDatabase.getInstance() @@ -465,6 +459,15 @@ export class TransactionResolver { await executeTransaction(amount, memo, senderUser, recipientUser, logger) logger.info('successful executeTransaction') } else { + await processXComCompleteTransaction( + senderUser.communityUuid, + senderUser.gradidoID, + recipientCommunityIdentifier, + recipientIdentifier, + amount.valueOf(), + memo, + ) + /* // processing a x-community sendCoins logger.info('X-Com: processing a x-community transaction...') if (!CONFIG.FEDERATION_XCOM_SENDCOINS_ENABLED) { @@ -537,6 +540,7 @@ export class TransactionResolver { err, ) } + */ } return true } diff --git a/core/package.json b/core/package.json index 0044d263f..c85b5e504 100644 --- a/core/package.json +++ b/core/package.json @@ -27,6 +27,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", + "decimal.js-light": "^2.5.1", "jest": "27.2.4", "type-graphql": "^1.1.1", "typescript": "^4.9.5" diff --git a/core/src/config/index.ts b/core/src/config/index.ts new file mode 100644 index 000000000..31b8cf033 --- /dev/null +++ b/core/src/config/index.ts @@ -0,0 +1,27 @@ +// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env) + +import { LogLevel, validate } from 'config-schema' +import dotenv from 'dotenv' + +import { schema } from './schema' + +dotenv.config() + + +const federation = { + FEDERATION_BACKEND_SEND_ON_API: process.env.FEDERATION_BACKEND_SEND_ON_API ?? '1_0', + FEDERATION_XCOM_SENDCOINS_ENABLED: + process.env.FEDERATION_XCOM_SENDCOINS_ENABLED === 'true' || false, + // default value for community-uuid is equal uuid of stage-3 + FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID: + process.env.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID ?? '56a55482-909e-46a4-bfa2-cd025e894ebc', + FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: parseInt( + process.env.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS ?? '3', + ), +} + + +export const CONFIG = { + ...federation, +} +validate(schema, CONFIG) diff --git a/core/src/config/schema.ts b/core/src/config/schema.ts new file mode 100644 index 000000000..dbf6478de --- /dev/null +++ b/core/src/config/schema.ts @@ -0,0 +1,29 @@ +import Joi from 'joi' + +export const schema = Joi.object({ + FEDERATION_BACKEND_SEND_ON_API: Joi.string() + .pattern(/^\d+_\d+$/) + .default('1_0') + .description('API Version of sending requests to another communities, e.g., "1_0"') + .required(), + + FEDERATION_XCOM_SENDCOINS_ENABLED: Joi.boolean() + .default(false) + .description('Enable or disable the federation send coins feature') + .optional(), + + FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID: Joi.string() + .uuid() + .default('56a55482-909e-46a4-bfa2-cd025e894ebc') + .description( + 'UUID of the receiver community for federation cross-community transactions if the receiver is unknown', + ) + .required(), + + FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: Joi.number() + .integer() + .min(0) + .default(3) + .description('Maximum number of retries for reverting send coins transactions') + .required(), +}) diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index a50fa2f8d..6846ed143 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -3,14 +3,19 @@ import { FederatedCommunity as DbFederatedCommunity, PendingTransaction as DbPendingTransaction, User as dbUser, + TransactionLink as DbTransactionLink, PendingTransactionLoggingView, CommunityLoggingView, UserLoggingView, countOpenPendingTransactions, + getCommunityByUuid, + findUserByIdentifier, + findTransactionLinkByCode, } from 'database' import { Decimal } from 'decimal.js-light' import { LOG4JS_BASE_CATEGORY_NAME } from '@config/const' +import { CONFIG as CONFIG_CORE } from '@/config' import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' import { SendCoinsArgs } from '@federation/client/1_0/model/SendCoinsArgs' @@ -28,56 +33,93 @@ import { SendCoinsArgsLoggingView } from '@federation/client/1_0/logging/SendCoi import { SendCoinsResultLoggingView } from '@federation/client/1_0/logging/SendCoinsResultLogging.view' import { EncryptedTransferArgs } from '@graphql/model/EncryptedTransferArgs' import { randombytes_random } from 'sodium-native' +import { storeForeignUser } from './storeForeignUser' const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.${method}`) -/* -export async function processXComTransaction( - receiverCom: DbCommunity, - senderCom: DbCommunity, - creationDate: Date, - amount: Decimal, + +export async function processXComCompleteTransaction( + sendercommunityuuid: string, + sendergradidoid: string, + recipientcommunityuuid: string, + recipientgradidoid: string, + amount: string, memo: string, - sender: dbUser, - recipientIdentifier: string, + code?: string, + creationDate?: Date, + recipientfirstname?: string, + recipientalias?: string, ): Promise { - const methodLogger = createLogger(`processXComTransaction`) + const methodLogger = createLogger(`processXComCompleteTransaction`) // processing a x-community sendCoins - methodLogger.info('X-Com: processing a x-community transaction...') - if (!CONFIG.FEDERATION_XCOM_SENDCOINS_ENABLED) { - throw new LogError('X-Community sendCoins disabled per configuration!') + methodLogger.info('processing a x-community transaction...') + if (!CONFIG_CORE.FEDERATION_XCOM_SENDCOINS_ENABLED) { + const errmsg = 'X-Community sendCoins disabled per configuration!' + methodLogger.error(errmsg) + throw new Error(errmsg) } - const recipCom = await getCommunityByIdentifier(recipientCommunityIdentifier) - methodLogger.debug('recipient community: ', recipCom?.id) - if (recipCom === null) { - throw new LogError( - `no recipient community found for identifier: ${recipientCommunityIdentifier}`, - ) + const senderCom = await getCommunityByUuid(sendercommunityuuid) + methodLogger.debug('sender community: ', senderCom?.id) + if (senderCom === null) { + const errmsg = `no sender community found for identifier: ${sendercommunityuuid}` + methodLogger.error(errmsg) + throw new Error(errmsg) } - if (recipCom !== null && recipCom.authenticatedAt === null) { - throw new LogError('recipient community is connected, but still not authenticated yet!') + const senderUser = await findUserByIdentifier(sendergradidoid, sendercommunityuuid) + if (senderUser === null) { + const errmsg = `no sender user found for identifier: ${sendercommunityuuid}:${sendergradidoid}` + methodLogger.error(errmsg) + throw new Error(errmsg) + } + const recipientCom = await getCommunityByUuid(recipientcommunityuuid) + methodLogger.debug('recipient community: ', recipientCom?.id) + if (recipientCom === null) { + const errmsg = `no recipient community found for identifier: ${recipientcommunityuuid}` + methodLogger.error(errmsg) + throw new Error(errmsg) + } + if (recipientCom !== null && recipientCom.authenticatedAt === null) { + const errmsg = 'recipient community is connected, but still not authenticated yet!' + methodLogger.error(errmsg) + throw new Error(errmsg) + } + if(code !== undefined) { + try { + const dbTransactionLink = await findTransactionLinkByCode(code) + if (dbTransactionLink && dbTransactionLink.validUntil < new Date()) { + const errmsg = `TransactionLink ${code} is expired!` + methodLogger.error(errmsg) + throw new Error(errmsg) + } + } catch (_err) { + const errmsg = `TransactionLink ${code} not found any more!` + methodLogger.error(errmsg) + throw new Error(errmsg) + } + } + if(creationDate === undefined) { + creationDate = new Date() } let pendingResult: SendCoinsResponseJwtPayloadType | null = null let committingResult: SendCoinsResult - const creationDate = new Date() - + try { pendingResult = await processXComPendingSendCoins( - recipCom, - homeCom, + recipientCom, + senderCom, creationDate, - amount, + new Decimal(amount), memo, senderUser, - recipientIdentifier, + recipientgradidoid, ) methodLogger.debug('processXComPendingSendCoins result: ', pendingResult) if (pendingResult && pendingResult.vote && pendingResult.recipGradidoID) { methodLogger.debug('vor processXComCommittingSendCoins... ') committingResult = await processXComCommittingSendCoins( - recipCom, - homeCom, + recipientCom, + senderCom, creationDate, - amount, + new Decimal(amount), memo, senderUser, pendingResult, @@ -85,28 +127,28 @@ export async function processXComTransaction( methodLogger.debug('processXComCommittingSendCoins result: ', committingResult) if (!committingResult.vote) { methodLogger.fatal('FATAL ERROR: on processXComCommittingSendCoins for', committingResult) - throw new LogError( - 'FATAL ERROR: on processXComCommittingSendCoins with ', - recipientCommunityIdentifier, - recipientIdentifier, - amount.toString(), + throw new Error( + 'FATAL ERROR: on processXComCommittingSendCoins with ' + + recipientCom.communityUuid + + recipientgradidoid + + amount.toString() + memo, ) } // after successful x-com-tx store the recipient as foreign user methodLogger.debug('store recipient as foreign user...') - if (await storeForeignUser(recipCom, committingResult)) { + if (await storeForeignUser(recipientCom, committingResult)) { methodLogger.info( 'X-Com: new foreign user inserted successfully...', - recipCom.communityUuid, + recipientCom.communityUuid, committingResult.recipGradidoID, ) } } } catch (err) { const errmsg = `ERROR: on processXComCommittingSendCoins with ` + - recipientCommunityIdentifier + - recipientIdentifier + + recipientcommunityuuid + + recipientgradidoid + amount.toString() + memo + err @@ -115,151 +157,7 @@ export async function processXComTransaction( } return true } -*/ -/* -export async function processXComPendingSendCoins( - receiverCom: DbCommunity, - senderCom: DbCommunity, - creationDate: Date, - amount: Decimal, - memo: string, - sender: dbUser, - recipientIdentifier: string, -): Promise { - let voteResult: SendCoinsResponseJwtPayloadType - const methodLogger = createLogger(`processXComPendingSendCoins`) - try { - // even if debug is not enabled, attributes are processed so we skip the entire call for performance reasons - if(methodLogger.isDebugEnabled()) { - methodLogger.debug( - 'XCom: processXComPendingSendCoins...', { - receiverCom: new CommunityLoggingView(receiverCom), - senderCom: new CommunityLoggingView(senderCom), - amount: amount.toString(), - memo: memo.substring(0, 5), - sender: new UserLoggingView(sender), - recipientIdentifier - } - ) - } - if (await countOpenPendingTransactions([sender.gradidoID, recipientIdentifier]) > 0) { - const errmsg = `There exist still ongoing 'Pending-Transactions' for the involved users on sender-side!` - methodLogger.error(errmsg) - throw new LogError(errmsg) - } - const handshakeID = randombytes_random().toString() - methodLogger.addContext('handshakeID', handshakeID) - // first calculate the sender balance and check if the transaction is allowed - const senderBalance = await calculateSenderBalance(sender.id, amount.mul(-1), creationDate) - if (!senderBalance) { - const errmsg = `User has not enough GDD or amount is < 0` - methodLogger.error(errmsg) - throw new LogError(errmsg) - } - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`calculated senderBalance = ${JSON.stringify(senderBalance, null, 2)}`) - } - const receiverFCom = await DbFederatedCommunity.findOneOrFail({ - where: { - publicKey: Buffer.from(receiverCom.publicKey), - apiVersion: CONFIG.FEDERATION_BACKEND_SEND_ON_API, - }, - }) - const client = SendCoinsClientFactory.getInstance(receiverFCom) - - if (client instanceof V1_0_SendCoinsClient) { - const payload = new SendCoinsJwtPayloadType(handshakeID, - receiverCom.communityUuid!, - recipientIdentifier, - creationDate.toISOString(), - amount, - memo, - senderCom.communityUuid!, - sender.gradidoID, - fullName(sender.firstName, sender.lastName), - sender.alias - ) - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`ready for voteForSendCoins with payload=${payload}`) - } - const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, receiverCom.publicJwtKey!) - if(methodLogger.isDebugEnabled()) { - methodLogger.debug('jws', jws) - } - // prepare the args for the client invocation - const args = new EncryptedTransferArgs() - args.publicKey = senderCom.publicKey.toString('hex') - args.jwt = jws - args.handshakeID = handshakeID - if(methodLogger.isDebugEnabled()) { - methodLogger.debug('before client.voteForSendCoins() args:', args) - } - - const responseJwt = await client.voteForSendCoins(args) - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`response of voteForSendCoins():`, responseJwt) - } - if (responseJwt !== null) { - voteResult = await verifyAndDecrypt(handshakeID, responseJwt, senderCom.privateJwtKey!, receiverCom.publicJwtKey!) as SendCoinsResponseJwtPayloadType - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`calculated voteResult = ${JSON.stringify(voteResult, null, 2)}`) - } - if (voteResult && voteResult.vote && voteResult.recipGradidoID) { - methodLogger.debug('vor processXComCommittingSendCoins... ') - const committingResult = await processXComCommittingSendCoins( - receiverCom, - senderCom, - creationDate, - amount, - memo, - sender, - voteResult, - ) - methodLogger.debug('processXComCommittingSendCoins result: ', committingResult) - if (!committingResult.vote) { - methodLogger.fatal('FATAL ERROR: on processXComCommittingSendCoins for', committingResult) - throw new LogError( - 'FATAL ERROR: on processXComCommittingSendCoins with ', - recipientCommunityIdentifier, - recipientIdentifier, - amount.toString(), - memo, - ) - } - // after successful x-com-tx store the recipient as foreign user - methodLogger.debug('store recipient as foreign user...') - if (await storeForeignUser(receiverCom, committingResult)) { - methodLogger.info( - 'X-Com: new foreign user inserted successfully...', - receiverCom.communityUuid, - committingResult.recipGradidoID, - ) - } - } - } - } else { - const errmsg = `Client is not instance of V1_0_SendCoinsClient` - methodLogger.error(errmsg) - throw new LogError(errmsg) - } - } catch (err) { - const errmsg = `ERROR: on processXComCommittingSendCoins with ` + - recipientCommunityIdentifier + - recipientIdentifier + - amount.toString() + - memo + - err - throw new LogError(errmsg) - } -} - memo, - err, - ) - } - } -} -*/ export async function processXComPendingSendCoins( receiverCom: DbCommunity, senderCom: DbCommunity, @@ -306,7 +204,7 @@ export async function processXComPendingSendCoins( const receiverFCom = await DbFederatedCommunity.findOneOrFail({ where: { publicKey: Buffer.from(receiverCom.publicKey), - apiVersion: CONFIG.FEDERATION_BACKEND_SEND_ON_API, + apiVersion: CONFIG_CORE.FEDERATION_BACKEND_SEND_ON_API, }, }) const client = SendCoinsClientFactory.getInstance(receiverFCom) @@ -401,7 +299,7 @@ export async function processXComPendingSendCoins( methodLogger.error(errmsg) throw new Error(errmsg) } - } while (CONFIG.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS > revertCount++) + } while (CONFIG_CORE.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS > revertCount++) const errmsg = `Error in reverting receiver pending transaction even after revertCount=${revertCount}` + JSON.stringify(err, null, 2) methodLogger.error(errmsg) throw new Error(errmsg) @@ -456,7 +354,7 @@ export async function processXComCommittingSendCoins( userGradidoID: sender.gradidoID, userName: fullName(sender.firstName, sender.lastName), linkedUserCommunityUuid: - receiverCom.communityUuid ?? CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID, + receiverCom.communityUuid ?? CONFIG_CORE.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID, linkedUserGradidoID: recipient.recipGradidoID ? recipient.recipGradidoID : undefined, typeId: TransactionTypeId.SEND, state: PendingTransactionState.NEW, @@ -470,7 +368,7 @@ export async function processXComCommittingSendCoins( const receiverFCom = await DbFederatedCommunity.findOneOrFail({ where: { publicKey: Buffer.from(receiverCom.publicKey), - apiVersion: CONFIG.FEDERATION_BACKEND_SEND_ON_API, + apiVersion: CONFIG_CORE.FEDERATION_BACKEND_SEND_ON_API, }, }) const client = SendCoinsClientFactory.getInstance(receiverFCom) @@ -480,7 +378,7 @@ export async function processXComCommittingSendCoins( handshakeID, pendingTx.linkedUserCommunityUuid ? pendingTx.linkedUserCommunityUuid - : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID, + : CONFIG_CORE.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID, pendingTx.linkedUserGradidoID!, pendingTx.balanceDate.toISOString(), pendingTx.amount.mul(-1), @@ -492,7 +390,7 @@ export async function processXComCommittingSendCoins( ) payload.recipientCommunityUuid = pendingTx.linkedUserCommunityUuid ? pendingTx.linkedUserCommunityUuid - : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID + : CONFIG_CORE.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID if (pendingTx.linkedUserGradidoID) { payload.recipientUserIdentifier = pendingTx.linkedUserGradidoID } @@ -533,20 +431,21 @@ export async function processXComCommittingSendCoins( methodLogger.error(`Error in writing sender pending transaction: ${JSON.stringify(err, null, 2)}`) // revert the existing pending transaction on receiver side let revertCount = 0 - methodLogger.debug('first try to revertSetteledSendCoins of receiver') + methodLogger.debug('first try to revertSettledSendCoins of receiver') do { if (await client.revertSettledSendCoins(args)) { methodLogger.debug( `revertSettledSendCoins()-1_0... successfull after revertCount=${revertCount}`, ) // treat revertingSettledSendCoins as an error of the whole sendCoins-process - throw new LogError('Error in settle sender pending transaction: ', err) + const errmsg = `Error in settle sender pending transaction: ${JSON.stringify(err, null, 2)}` + methodLogger.error(errmsg) + throw new Error(errmsg) } - } while (CONFIG.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS > revertCount++) - throw new LogError( - `Error in reverting receiver pending transaction even after revertCount=${revertCount}`, - err, - ) + } while (CONFIG_CORE.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS > revertCount++) + const errmsg = `Error in reverting receiver pending transaction even after revertCount=${revertCount}` + methodLogger.error(errmsg) + throw new Error(errmsg) } } } diff --git a/backend/src/graphql/resolver/util/storeForeignUser.ts b/core/src/graphql/logic/storeForeignUser.ts similarity index 83% rename from backend/src/graphql/resolver/util/storeForeignUser.ts rename to core/src/graphql/logic/storeForeignUser.ts index 8c33c8923..402a9a835 100644 --- a/backend/src/graphql/resolver/util/storeForeignUser.ts +++ b/core/src/graphql/logic/storeForeignUser.ts @@ -1,10 +1,10 @@ -import { Community as DbCommunity, User as DbUser } from 'database' +import { Community as DbCommunity, User as DbUser, findForeignUserByUuids } from 'database' -import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult' +import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getLogger } from 'log4js' -const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.storeForeignUser`) +const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.logic.storeForeignUser`) export async function storeForeignUser( recipCom: DbCommunity, @@ -12,13 +12,7 @@ export async function storeForeignUser( ): Promise { if (recipCom.communityUuid !== null && committingResult.recipGradidoID !== null) { try { - const user = await DbUser.findOne({ - where: { - foreign: true, - communityUuid: recipCom.communityUuid, - gradidoID: committingResult.recipGradidoID, - }, - }) + const user = await findForeignUserByUuids(recipCom.communityUuid, committingResult.recipGradidoID) if (!user) { logger.debug( 'no foreignUser found for:', diff --git a/core/src/index.ts b/core/src/index.ts index 9ee34cc19..85042ef0b 100644 --- a/core/src/index.ts +++ b/core/src/index.ts @@ -14,9 +14,10 @@ export * from './graphql/enum/TransactionTypeId' export * from './graphql/logging/DecayLogging.view' export * from './graphql/logic/interpretEncryptedTransferArgs' export * from './graphql/logic/processXComSendCoins' +export * from './graphql/logic/settlePendingSenderTransaction' +export * from './graphql/logic/storeForeignUser' export * from './graphql/model/Decay' export * from './graphql/model/EncryptedTransferArgs' export * from './util/calculateSenderBalance' export * from './util/utilities' export * from './validation/user' - diff --git a/database/src/queries/communities.ts b/database/src/queries/communities.ts index 868db42e8..3afdaf883 100644 --- a/database/src/queries/communities.ts +++ b/database/src/queries/communities.ts @@ -8,4 +8,10 @@ export async function getHomeCommunity(): Promise { return await DbCommunity.findOne({ where: { foreign: false }, }) -} \ No newline at end of file +} + +export async function getCommunityByUuid(communityUuid: string): Promise { + return await DbCommunity.findOne({ + where: [{ communityUuid }], + }) +} diff --git a/database/src/queries/index.ts b/database/src/queries/index.ts index b8ca12b86..1fec568bf 100644 --- a/database/src/queries/index.ts +++ b/database/src/queries/index.ts @@ -4,5 +4,6 @@ export * from './user' export * from './communities' export * from './pendingTransactions' export * from './transactions' +export * from './transactionLinks' export const LOG4JS_QUERIES_CATEGORY_NAME = `${LOG4JS_BASE_CATEGORY_NAME}.queries` diff --git a/database/src/queries/transactionLinks.ts b/database/src/queries/transactionLinks.ts new file mode 100644 index 000000000..9a4cda064 --- /dev/null +++ b/database/src/queries/transactionLinks.ts @@ -0,0 +1,8 @@ +import { TransactionLink as DbTransactionLink } from "../entity/TransactionLink" + +export async function findTransactionLinkByCode(code: string): Promise { + return await DbTransactionLink.findOneOrFail({ + where: { code }, + withDeleted: true, + }) +} diff --git a/database/src/queries/user.ts b/database/src/queries/user.ts index b968e9433..c4f0a023c 100644 --- a/database/src/queries/user.ts +++ b/database/src/queries/user.ts @@ -60,3 +60,12 @@ export const findUserByIdentifier = async ( getLogger(`${LOG4JS_QUERIES_CATEGORY_NAME}.user.findUserByIdentifier`).warn('Unknown identifier type', identifier) return null } + +export async function findForeignUserByUuids( + communityUuid: string, + gradidoID: string, +): Promise { + return DbUser.findOne({ + where: { foreign: true, communityUuid, gradidoID }, + }) +} From a02771b35d9b2f7d5f29a1f4026969b1aa929682 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Thu, 21 Aug 2025 22:39:49 +0200 Subject: [PATCH 06/48] add i18n --- core/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/core/package.json b/core/package.json index c85b5e504..bd7ce462f 100644 --- a/core/package.json +++ b/core/package.json @@ -28,6 +28,7 @@ "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", "decimal.js-light": "^2.5.1", + "i18n": "^0.15.1", "jest": "27.2.4", "type-graphql": "^1.1.1", "typescript": "^4.9.5" From 621b41cb05c8f8d5a638116183496e4acd5f3263 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 22 Aug 2025 00:12:24 +0200 Subject: [PATCH 07/48] correct package dependencies --- bun.lock | 5 +++++ core/package.json | 2 ++ 2 files changed, 7 insertions(+) diff --git a/bun.lock b/bun.lock index 30a87f9af..d524f7999 100644 --- a/bun.lock +++ b/bun.lock @@ -192,6 +192,10 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", + "config-schema": "*", + "decimal.js-light": "^2.5.1", + "graphql-request": "5.0.0", + "i18n": "^0.15.1", "jest": "27.2.4", "type-graphql": "^1.1.1", "typescript": "^4.9.5", @@ -229,6 +233,7 @@ "@types/geojson": "^7946.0.13", "@types/jest": "27.0.2", "@types/node": "^18.7.14", + "await-semaphore": "^0.1.3", "crypto-random-bigint": "^2.1.1", "jest": "27.2.4", "ts-jest": "27.0.5", diff --git a/core/package.json b/core/package.json index bd7ce462f..72687d629 100644 --- a/core/package.json +++ b/core/package.json @@ -27,7 +27,9 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", + "config-schema": "*", "decimal.js-light": "^2.5.1", + "graphql-request": "5.0.0", "i18n": "^0.15.1", "jest": "27.2.4", "type-graphql": "^1.1.1", From 21d05193eb7362991b8141518335323c1e802bd0 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 22 Aug 2025 00:20:48 +0200 Subject: [PATCH 08/48] correct dependencies --- core/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/core/package.json b/core/package.json index 72687d629..8317808e2 100644 --- a/core/package.json +++ b/core/package.json @@ -41,6 +41,7 @@ "jose": "^4.14.4", "log4js": "^6.9.1", "shared": "*", + "sodium-native": "^3.4.1", "zod": "^3.25.61" }, "engines": { From a0b0e58059462859170efb14adabd9e4413dfe36 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 22 Aug 2025 00:37:18 +0200 Subject: [PATCH 09/48] next try for changed dependencies --- core/package.json | 22 +++++++++---------- .../src/graphql/logic/processXComSendCoins.ts | 21 ++++++++---------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/core/package.json b/core/package.json index 8317808e2..092b4ff00 100644 --- a/core/package.json +++ b/core/package.json @@ -24,26 +24,26 @@ "lint:fix": "biome check --error-on-warnings . --write", "clear": "rm -rf node_modules && rm -rf build && rm -rf .turbo" }, - "devDependencies": { - "@biomejs/biome": "2.0.0", - "@types/node": "^17.0.21", - "config-schema": "*", - "decimal.js-light": "^2.5.1", - "graphql-request": "5.0.0", - "i18n": "^0.15.1", - "jest": "27.2.4", - "type-graphql": "^1.1.1", - "typescript": "^4.9.5" - }, "dependencies": { "database": "*", "esbuild": "^0.25.2", + "i18n": "^0.15.1", "jose": "^4.14.4", "log4js": "^6.9.1", "shared": "*", "sodium-native": "^3.4.1", "zod": "^3.25.61" }, + "devDependencies": { + "@biomejs/biome": "2.0.0", + "@types/node": "^17.0.21", + "config-schema": "*", + "decimal.js-light": "^2.5.1", + "graphql-request": "5.0.0", + "jest": "27.2.4", + "type-graphql": "^1.1.1", + "typescript": "^4.9.5" + }, "engines": { "node": ">=18" } diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index 6846ed143..5b93a3d2b 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -1,38 +1,35 @@ import { + CommunityLoggingView, + countOpenPendingTransactions, Community as DbCommunity, FederatedCommunity as DbFederatedCommunity, PendingTransaction as DbPendingTransaction, User as dbUser, - TransactionLink as DbTransactionLink, - PendingTransactionLoggingView, - CommunityLoggingView, - UserLoggingView, - countOpenPendingTransactions, - getCommunityByUuid, - findUserByIdentifier, findTransactionLinkByCode, + findUserByIdentifier, + getCommunityByUuid, + PendingTransactionLoggingView, + UserLoggingView } from 'database' import { Decimal } from 'decimal.js-light' -import { LOG4JS_BASE_CATEGORY_NAME } from '@config/const' import { CONFIG as CONFIG_CORE } from '@/config' +import { LOG4JS_BASE_CATEGORY_NAME } from '@config/const' import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' -import { SendCoinsArgs } from '@federation/client/1_0/model/SendCoinsArgs' import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' import { SendCoinsClientFactory } from '@federation/client/SendCoinsClientFactory' -import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' import { TransactionTypeId } from '@graphql/enum/TransactionTypeId' +import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' // import { LogError } from '@server/LogError' import { calculateSenderBalance } from '@util/calculateSenderBalance' import { fullName } from '@util/utilities' import { getLogger } from 'log4js' -import { settlePendingSenderTransaction } from './settlePendingSenderTransaction' -import { SendCoinsArgsLoggingView } from '@federation/client/1_0/logging/SendCoinsArgsLogging.view' import { SendCoinsResultLoggingView } from '@federation/client/1_0/logging/SendCoinsResultLogging.view' import { EncryptedTransferArgs } from '@graphql/model/EncryptedTransferArgs' import { randombytes_random } from 'sodium-native' +import { settlePendingSenderTransaction } from './settlePendingSenderTransaction' import { storeForeignUser } from './storeForeignUser' const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.${method}`) From b0688fd8fe4b2e509b7fadb88ddca966d6528f91 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 25 Aug 2025 15:19:47 +0200 Subject: [PATCH 10/48] after change i18n dependency --- bun.lock | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bun.lock b/bun.lock index d524f7999..9b49f0b8d 100644 --- a/bun.lock +++ b/bun.lock @@ -184,9 +184,11 @@ "dependencies": { "database": "*", "esbuild": "^0.25.2", + "i18n": "^0.15.1", "jose": "^4.14.4", "log4js": "^6.9.1", "shared": "*", + "sodium-native": "^3.4.1", "zod": "^3.25.61", }, "devDependencies": { @@ -195,7 +197,6 @@ "config-schema": "*", "decimal.js-light": "^2.5.1", "graphql-request": "5.0.0", - "i18n": "^0.15.1", "jest": "27.2.4", "type-graphql": "^1.1.1", "typescript": "^4.9.5", From 7910528a6f363c3da655c8b54d21f0ca200df294 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 25 Aug 2025 16:55:29 +0200 Subject: [PATCH 11/48] reorg all imports in core to relative pathes --- .../resolver/ContributionResolver.test.ts | 2 +- .../resolver/TransactionLinkResolver.ts | 1 + .../src/graphql/resolver/UserResolver.test.ts | 2 +- .../federation/client/1_0/SendCoinsClient.ts | 6 +++--- .../1_0/logging/SendCoinsArgsLogging.view.ts | 2 +- .../logging/SendCoinsResultLogging.view.ts | 2 +- .../federation/client/1_1/SendCoinsClient.ts | 2 +- .../client/SendCoinsClientFactory.ts | 6 +++--- core/src/graphql/logging/DecayLogging.view.ts | 2 +- .../logic/interpretEncryptedTransferArgs.ts | 4 ++-- .../src/graphql/logic/processXComSendCoins.ts | 20 +++++++++---------- .../logic/settlePendingSenderTransaction.ts | 2 +- core/src/graphql/logic/storeForeignUser.ts | 4 ++-- core/src/util/calculateSenderBalance.ts | 2 +- core/tsconfig.json | 2 +- 15 files changed, 30 insertions(+), 29 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 14dfa614f..6dee20592 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -50,7 +50,7 @@ import { garrickOllivander } from '@/seeds/users/garrick-ollivander' import { peterLustig } from '@/seeds/users/peter-lustig' import { raeuberHotzenplotz } from '@/seeds/users/raeuber-hotzenplotz' import { stephenHawking } from '@/seeds/users/stephen-hawking' -import { getFirstDayOfPreviousNMonth } from '@/util/utilities' +import { getFirstDayOfPreviousNMonth } from 'core' import { getLogger } from 'config-schema/test/testSetup' import { getLogger as originalGetLogger } from 'log4js' diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 28375bcab..532cfec2f 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -8,6 +8,7 @@ import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionType } from '@enum/ContributionType' import { ContributionLink } from '@model/ContributionLink' import { RedeemJwtLink } from '@model/RedeemJwtLink' +import { Community } from '@model/Community' import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink' import { User } from '@model/User' import { QueryLinkResult } from '@union/QueryLinkResult' diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index bf2cb1f59..64817bd3e 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -65,7 +65,7 @@ import { garrickOllivander } from '@/seeds/users/garrick-ollivander' import { peterLustig } from '@/seeds/users/peter-lustig' import { stephenHawking } from '@/seeds/users/stephen-hawking' import { printTimeDuration } from '@/util/time' -import { objectValuesToArray } from '@/util/utilities' +import { objectValuesToArray } from 'core' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { getLogger } from 'config-schema/test/testSetup' diff --git a/core/src/federation/client/1_0/SendCoinsClient.ts b/core/src/federation/client/1_0/SendCoinsClient.ts index bb8d2c858..a872c438d 100644 --- a/core/src/federation/client/1_0/SendCoinsClient.ts +++ b/core/src/federation/client/1_0/SendCoinsClient.ts @@ -1,15 +1,15 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' import { GraphQLClient } from 'graphql-request' -import { ensureUrlEndsWithSlash } from '@/util/utilities' +import { ensureUrlEndsWithSlash } from '../../../util/utilities' import { getLogger } from 'log4js' -import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { LOG4JS_BASE_CATEGORY_NAME } from '../../../config/const' import { revertSendCoins as revertSendCoinsQuery } from './query/revertSendCoins' import { revertSettledSendCoins as revertSettledSendCoinsQuery } from './query/revertSettledSendCoins' import { settleSendCoins as settleSendCoinsQuery } from './query/settleSendCoins' import { voteForSendCoins as voteForSendCoinsQuery } from './query/voteForSendCoins' -import { EncryptedTransferArgs } from '@graphql/model/EncryptedTransferArgs' +import { EncryptedTransferArgs } from '../../../graphql/model/EncryptedTransferArgs' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.client.1_0.SendCoinsClient`) diff --git a/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts b/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts index 1db8c2887..11afa4346 100644 --- a/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts +++ b/core/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { SendCoinsArgs } from '@federation/client/1_0/model/SendCoinsArgs' +import { SendCoinsArgs } from '../model/SendCoinsArgs' export class SendCoinsArgsLoggingView extends AbstractLoggingView { public constructor(private self: SendCoinsArgs) { diff --git a/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts b/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts index 383f4fd37..1eb08c432 100644 --- a/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts +++ b/core/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' +import { SendCoinsResult } from '../model/SendCoinsResult' export class SendCoinsResultLoggingView extends AbstractLoggingView { public constructor(private self: SendCoinsResult) { diff --git a/core/src/federation/client/1_1/SendCoinsClient.ts b/core/src/federation/client/1_1/SendCoinsClient.ts index 8c7f9caec..b0eab7c0c 100644 --- a/core/src/federation/client/1_1/SendCoinsClient.ts +++ b/core/src/federation/client/1_1/SendCoinsClient.ts @@ -1,3 +1,3 @@ -import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' +import { SendCoinsClient as V1_0_SendCoinsClient } from '../1_0/SendCoinsClient' export class SendCoinsClient extends V1_0_SendCoinsClient {} diff --git a/core/src/federation/client/SendCoinsClientFactory.ts b/core/src/federation/client/SendCoinsClientFactory.ts index 8251da3cb..4a2772175 100644 --- a/core/src/federation/client/SendCoinsClientFactory.ts +++ b/core/src/federation/client/SendCoinsClientFactory.ts @@ -1,8 +1,8 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database' -import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' -import { SendCoinsClient as V1_1_SendCoinsClient } from '@federation/client/1_1/SendCoinsClient' -import { ApiVersionType } from '@federation/enum/apiVersionType' +import { SendCoinsClient as V1_0_SendCoinsClient } from './1_0/SendCoinsClient' +import { SendCoinsClient as V1_1_SendCoinsClient } from './1_1/SendCoinsClient' +import { ApiVersionType } from '../enum/apiVersionType' type SendCoinsClient = V1_0_SendCoinsClient | V1_1_SendCoinsClient diff --git a/core/src/graphql/logging/DecayLogging.view.ts b/core/src/graphql/logging/DecayLogging.view.ts index f4f20ab6f..2c485447a 100644 --- a/core/src/graphql/logging/DecayLogging.view.ts +++ b/core/src/graphql/logging/DecayLogging.view.ts @@ -1,6 +1,6 @@ import { AbstractLoggingView } from 'database' -import { Decay } from '@graphql/model/Decay' +import { Decay } from '../model/Decay' import type { Decay as DecayInterface } from 'shared' export class DecayLoggingView extends AbstractLoggingView { diff --git a/core/src/graphql/logic/interpretEncryptedTransferArgs.ts b/core/src/graphql/logic/interpretEncryptedTransferArgs.ts index 0d522bff7..301f6da16 100644 --- a/core/src/graphql/logic/interpretEncryptedTransferArgs.ts +++ b/core/src/graphql/logic/interpretEncryptedTransferArgs.ts @@ -6,10 +6,10 @@ import { CommunityLoggingView, getHomeCommunity } from 'database' import { verifyAndDecrypt } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const' -const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.interpretEncryptedTransferArgs`) +const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.logic.interpretEncryptedTransferArgs`) export const interpretEncryptedTransferArgs = async (args: EncryptedTransferArgs): Promise => { - const methodLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.interpretEncryptedTransferArgs-method`) + const methodLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.logic.interpretEncryptedTransferArgs-method`) methodLogger.addContext('handshakeID', args.handshakeID) methodLogger.debug('interpretEncryptedTransferArgs()... args:', args) // first find with args.publicKey the community 'requestingCom', which starts the request diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index 5b93a3d2b..19c75898f 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -13,21 +13,21 @@ import { } from 'database' import { Decimal } from 'decimal.js-light' -import { CONFIG as CONFIG_CORE } from '@/config' -import { LOG4JS_BASE_CATEGORY_NAME } from '@config/const' +import { CONFIG as CONFIG_CORE } from '../../config' +import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const' -import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient' -import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' -import { SendCoinsClientFactory } from '@federation/client/SendCoinsClientFactory' -import { TransactionTypeId } from '@graphql/enum/TransactionTypeId' +import { SendCoinsClient as V1_0_SendCoinsClient } from '../../federation/client/1_0/SendCoinsClient' +import { SendCoinsResult } from '../../federation/client/1_0/model/SendCoinsResult' +import { SendCoinsClientFactory } from '../../federation/client/SendCoinsClientFactory' +import { TransactionTypeId } from '../../graphql/enum/TransactionTypeId' import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' // import { LogError } from '@server/LogError' -import { calculateSenderBalance } from '@util/calculateSenderBalance' -import { fullName } from '@util/utilities' +import { calculateSenderBalance } from '../../util/calculateSenderBalance' +import { fullName } from '../../util/utilities' import { getLogger } from 'log4js' -import { SendCoinsResultLoggingView } from '@federation/client/1_0/logging/SendCoinsResultLogging.view' -import { EncryptedTransferArgs } from '@graphql/model/EncryptedTransferArgs' +import { SendCoinsResultLoggingView } from '../../federation/client/1_0/logging/SendCoinsResultLogging.view' +import { EncryptedTransferArgs } from '../../graphql/model/EncryptedTransferArgs' import { randombytes_random } from 'sodium-native' import { settlePendingSenderTransaction } from './settlePendingSenderTransaction' import { storeForeignUser } from './storeForeignUser' diff --git a/core/src/graphql/logic/settlePendingSenderTransaction.ts b/core/src/graphql/logic/settlePendingSenderTransaction.ts index 8abd511c1..87ab8116c 100644 --- a/core/src/graphql/logic/settlePendingSenderTransaction.ts +++ b/core/src/graphql/logic/settlePendingSenderTransaction.ts @@ -10,7 +10,7 @@ import { } from 'database' import { Decimal } from 'decimal.js-light' -import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const' import { PendingTransactionState } from 'shared' // import { LogError } from '@/server/LogError' import { calculateSenderBalance } from 'core' diff --git a/core/src/graphql/logic/storeForeignUser.ts b/core/src/graphql/logic/storeForeignUser.ts index 402a9a835..1e6b8153f 100644 --- a/core/src/graphql/logic/storeForeignUser.ts +++ b/core/src/graphql/logic/storeForeignUser.ts @@ -1,7 +1,7 @@ import { Community as DbCommunity, User as DbUser, findForeignUserByUuids } from 'database' -import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult' -import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { SendCoinsResult } from '../../federation/client/1_0/model/SendCoinsResult' +import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const' import { getLogger } from 'log4js' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.logic.storeForeignUser`) diff --git a/core/src/util/calculateSenderBalance.ts b/core/src/util/calculateSenderBalance.ts index ce7609895..7fe5ae19f 100644 --- a/core/src/util/calculateSenderBalance.ts +++ b/core/src/util/calculateSenderBalance.ts @@ -1,6 +1,6 @@ import { Decimal } from 'decimal.js-light' -import { Decay } from '@graphql/model/Decay' +import { Decay } from '../graphql/model/Decay' import { getLastTransaction } from 'database' diff --git a/core/tsconfig.json b/core/tsconfig.json index 660381127..c30aab30d 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -51,7 +51,7 @@ "@federation/*": ["src/federation/*"], "@graphql/*": ["src/graphql/*"], "@util/*": ["src/util/*"], - "@validation/*": ["src/validation/*"], + "@validation/*": ["src/validation/*"] }, // "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ From 1ad378aa2204a34815e9d108d6af42e0af228b80 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 25 Aug 2025 21:41:31 +0200 Subject: [PATCH 12/48] correct path for mock transaction-lock --- backend/src/graphql/resolver/TransactionLinkResolver.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 03ac5524b..6997c0e93 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -43,7 +43,7 @@ const logErrorLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`) jest.mock('@/password/EncryptorUtils') // mock semaphore to allow use fake timers -jest.mock('@/util/TRANSACTIONS_LOCK') +jest.mock('database/util/TRANSACTIONS_LOCK') TRANSACTIONS_LOCK.acquire = jest.fn().mockResolvedValue(jest.fn()) let mutate: ApolloServerTestClient['mutate'] From a0cde876cd21c3981717bd2f80b16cb7635e6e7e Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 25 Aug 2025 23:07:48 +0200 Subject: [PATCH 13/48] correct import of entities --- database/src/queries/communities.ts | 2 +- database/src/queries/transactionLinks.ts | 2 +- database/src/queries/transactions.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/database/src/queries/communities.ts b/database/src/queries/communities.ts index 3afdaf883..edc3bd7ed 100644 --- a/database/src/queries/communities.ts +++ b/database/src/queries/communities.ts @@ -1,4 +1,4 @@ -import { Community as DbCommunity } from '../entity/Community' +import { Community as DbCommunity } from '../entity' /** * Retrieves the home community, i.e., a community that is not foreign. diff --git a/database/src/queries/transactionLinks.ts b/database/src/queries/transactionLinks.ts index 9a4cda064..eb9908101 100644 --- a/database/src/queries/transactionLinks.ts +++ b/database/src/queries/transactionLinks.ts @@ -1,4 +1,4 @@ -import { TransactionLink as DbTransactionLink } from "../entity/TransactionLink" +import { TransactionLink as DbTransactionLink } from "../entity" export async function findTransactionLinkByCode(code: string): Promise { return await DbTransactionLink.findOneOrFail({ diff --git a/database/src/queries/transactions.ts b/database/src/queries/transactions.ts index 0e5b236e2..5df8186e7 100644 --- a/database/src/queries/transactions.ts +++ b/database/src/queries/transactions.ts @@ -1,4 +1,4 @@ -import { Transaction as DbTransaction } from 'database' +import { Transaction as DbTransaction } from '../entity' export const getLastTransaction = async ( userId: number, From bfd2e61d65f6b9c8ee45b24b2793117a057dc818 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 25 Aug 2025 23:54:48 +0200 Subject: [PATCH 14/48] modify jest.mock for TRANSACTIONS_LOCK --- backend/src/graphql/resolver/TransactionLinkResolver.test.ts | 2 +- database/src/util/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 6997c0e93..03ac5524b 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -43,7 +43,7 @@ const logErrorLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`) jest.mock('@/password/EncryptorUtils') // mock semaphore to allow use fake timers -jest.mock('database/util/TRANSACTIONS_LOCK') +jest.mock('@/util/TRANSACTIONS_LOCK') TRANSACTIONS_LOCK.acquire = jest.fn().mockResolvedValue(jest.fn()) let mutate: ApolloServerTestClient['mutate'] diff --git a/database/src/util/index.ts b/database/src/util/index.ts index b16b20d19..d2fde2126 100644 --- a/database/src/util/index.ts +++ b/database/src/util/index.ts @@ -1,2 +1,2 @@ export * from './TRANSACTIONS_LOCK' -export * from './TRANSACTION_LINK_LOCK' \ No newline at end of file +export * from './TRANSACTION_LINK_LOCK' From 738fe6f9ec4721184a767c130d17a925475a2975 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Tue, 26 Aug 2025 00:06:01 +0200 Subject: [PATCH 15/48] next try jest.mock TRANSACTIONS_LOCK --- backend/src/graphql/resolver/TransactionLinkResolver.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 03ac5524b..bac8e6cea 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -43,7 +43,7 @@ const logErrorLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`) jest.mock('@/password/EncryptorUtils') // mock semaphore to allow use fake timers -jest.mock('@/util/TRANSACTIONS_LOCK') +jest.mock('database') TRANSACTIONS_LOCK.acquire = jest.fn().mockResolvedValue(jest.fn()) let mutate: ApolloServerTestClient['mutate'] From ce1cf8595694d1b3d8667bab1c2e5532876eca70 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Tue, 26 Aug 2025 00:27:55 +0200 Subject: [PATCH 16/48] next try --- backend/src/graphql/resolver/TransactionLinkResolver.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index bac8e6cea..6997c0e93 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -43,7 +43,7 @@ const logErrorLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`) jest.mock('@/password/EncryptorUtils') // mock semaphore to allow use fake timers -jest.mock('database') +jest.mock('database/util/TRANSACTIONS_LOCK') TRANSACTIONS_LOCK.acquire = jest.fn().mockResolvedValue(jest.fn()) let mutate: ApolloServerTestClient['mutate'] From 071488f0e8824c2c9ff6743a90a7dd562125fc87 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 26 Aug 2025 08:03:11 +0200 Subject: [PATCH 17/48] need full path for mocking part of submodule --- backend/src/graphql/resolver/TransactionLinkResolver.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 6997c0e93..d7c2fc713 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -43,7 +43,7 @@ const logErrorLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`) jest.mock('@/password/EncryptorUtils') // mock semaphore to allow use fake timers -jest.mock('database/util/TRANSACTIONS_LOCK') +jest.mock('database/src/util/TRANSACTIONS_LOCK') TRANSACTIONS_LOCK.acquire = jest.fn().mockResolvedValue(jest.fn()) let mutate: ApolloServerTestClient['mutate'] From 16fcaad7d4b941e6cfc97163d8f6582bf004b390 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 26 Aug 2025 08:07:08 +0200 Subject: [PATCH 18/48] add type specification for sodium in core --- bun.lock | 1 + core/package.json | 1 + yarn.lock | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/bun.lock b/bun.lock index 9b49f0b8d..564c3b0fa 100644 --- a/bun.lock +++ b/bun.lock @@ -194,6 +194,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", + "@types/sodium-native": "^2.3.5", "config-schema": "*", "decimal.js-light": "^2.5.1", "graphql-request": "5.0.0", diff --git a/core/package.json b/core/package.json index 092b4ff00..e1d805c66 100644 --- a/core/package.json +++ b/core/package.json @@ -37,6 +37,7 @@ "devDependencies": { "@biomejs/biome": "2.0.0", "@types/node": "^17.0.21", + "@types/sodium-native": "^2.3.5", "config-schema": "*", "decimal.js-light": "^2.5.1", "graphql-request": "5.0.0", diff --git a/yarn.lock b/yarn.lock index 235b04ce6..2b815e0ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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" From 75477a493ed474ad54a9cebba5d3478a3d64636d Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 26 Aug 2025 08:20:01 +0200 Subject: [PATCH 19/48] add @types/i18n in core --- bun.lock | 1 + core/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/bun.lock b/bun.lock index 564c3b0fa..5c1e61306 100644 --- a/bun.lock +++ b/bun.lock @@ -193,6 +193,7 @@ }, "devDependencies": { "@biomejs/biome": "2.0.0", + "@types/i18n": "^0.13.4", "@types/node": "^17.0.21", "@types/sodium-native": "^2.3.5", "config-schema": "*", diff --git a/core/package.json b/core/package.json index e1d805c66..9e745f948 100644 --- a/core/package.json +++ b/core/package.json @@ -36,6 +36,7 @@ }, "devDependencies": { "@biomejs/biome": "2.0.0", + "@types/i18n": "^0.13.4", "@types/node": "^17.0.21", "@types/sodium-native": "^2.3.5", "config-schema": "*", From d7c5c852e92be7e556143667526e4afc86cfb18d Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 27 Aug 2025 16:03:42 +0200 Subject: [PATCH 20/48] correct devDependencies after Darios info --- core/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/package.json b/core/package.json index 092b4ff00..9e745f948 100644 --- a/core/package.json +++ b/core/package.json @@ -36,7 +36,9 @@ }, "devDependencies": { "@biomejs/biome": "2.0.0", + "@types/i18n": "^0.13.4", "@types/node": "^17.0.21", + "@types/sodium-native": "^2.3.5", "config-schema": "*", "decimal.js-light": "^2.5.1", "graphql-request": "5.0.0", From 15157ed2595f79ae2891d815738deeeceecffc41 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 27 Aug 2025 16:04:27 +0200 Subject: [PATCH 21/48] correct jest.mock TRANSACTION_LOCK after Darios info --- backend/src/graphql/resolver/TransactionLinkResolver.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts index 6997c0e93..d7c2fc713 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.test.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.test.ts @@ -43,7 +43,7 @@ const logErrorLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.server.LogError`) jest.mock('@/password/EncryptorUtils') // mock semaphore to allow use fake timers -jest.mock('database/util/TRANSACTIONS_LOCK') +jest.mock('database/src/util/TRANSACTIONS_LOCK') TRANSACTIONS_LOCK.acquire = jest.fn().mockResolvedValue(jest.fn()) let mutate: ApolloServerTestClient['mutate'] From f844e08c8d218b12e36ccc6910d59f0c4b4f4adb Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 27 Aug 2025 16:40:52 +0200 Subject: [PATCH 22/48] add invokation of processXComCompleteTransaction in Disbursement-Process --- .../client/1_0/DisbursementClient.ts | 8 +++---- .../src/graphql/logic/processXComSendCoins.ts | 2 +- .../api/1_0/resolver/DisbursementResolver.ts | 21 +++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/backend/src/federation/client/1_0/DisbursementClient.ts b/backend/src/federation/client/1_0/DisbursementClient.ts index abaf1818b..8ca859070 100644 --- a/backend/src/federation/client/1_0/DisbursementClient.ts +++ b/backend/src/federation/client/1_0/DisbursementClient.ts @@ -31,10 +31,10 @@ export class DisbursementClient { logger.debug('sendDisburseJwtToSenderCommunity against endpoint=', this.endpoint) try { const { data } = await this.client.rawRequest<{ processDisburseJwtOnSenderCommunity: string }>(processDisburseJwtOnSenderCommunityQuery, { args }) - const responseJwt = data?.processDisburseJwtOnSenderCommunity - if (responseJwt) { - logger.debug('received response jwt', responseJwt) - return responseJwt + const response = data?.processDisburseJwtOnSenderCommunity + if (response) { + logger.debug('received response:', response) + return response } } catch (err) { const errmsg = `sendDisburseJwtToSenderCommunity failed for endpoint=${this.endpoint}, err=${err}` diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index 19c75898f..dc8e3127f 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -42,9 +42,9 @@ export async function processXComCompleteTransaction( amount: string, memo: string, code?: string, - creationDate?: Date, recipientfirstname?: string, recipientalias?: string, + creationDate?: Date, ): Promise { const methodLogger = createLogger(`processXComCompleteTransaction`) // processing a x-community sendCoins diff --git a/federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts b/federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts index 629da9e54..2388aaec0 100644 --- a/federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/DisbursementResolver.ts @@ -5,6 +5,7 @@ import { LOG4JS_BASE_CATEGORY_NAME } from "@/config/const" import { interpretEncryptedTransferArgs } from "core" import { EncryptedTransferArgs } from "core" import { DisburseJwtPayloadType } from "shared" +import { processXComCompleteTransaction } from "core" const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.api.1_0.resolver.DisbursementResolver.${method}`) @@ -29,5 +30,25 @@ export class DisbursementResolver { if(methodLogger.isDebugEnabled()) { methodLogger.debug(`processDisburseJwtOnSenderCommunity() via apiVersion=1_0 ...`, authArgs) } + let result = 'Disbursement of Redeem-Link failed!' + try { + if(await processXComCompleteTransaction( + authArgs.sendercommunityuuid, + authArgs.sendergradidoid, + authArgs.recipientcommunityuuid, + authArgs.recipientgradidoid, + authArgs.amount, + authArgs.memo, + authArgs.code, + authArgs.recipientfirstname, + authArgs.recipientalias, + )) { + result = 'Disbursement of Redeem-Link successfull!' + } + } catch (err) { + result = `Error in Disbursement of Redeem-Link: ` + err + methodLogger.error(result) + } + return result } } \ No newline at end of file From 1d248f9e344ee8d386dbf056ad565ed0fb244733 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 27 Aug 2025 23:29:30 +0200 Subject: [PATCH 23/48] introduce encryptAndSign for createRedeemJwt --- .../resolver/TransactionLinkResolver.ts | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 532cfec2f..227f6b4ba 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -425,27 +425,41 @@ export class TransactionLinkResolver { alias, validUntil, }) - - const redeemJwtPayloadType = new RedeemJwtPayloadType( - senderCommunityUuid, - gradidoId, - alias ?? firstName ?? '', - code, - amount, - memo, - validUntil ?? '', - ) - // TODO:encode/sign the jwt normally with the private key of the sender/home community, but interims with uuid - const homeCom = await getHomeCommunity() - if (!homeCom) { - throw new LogError('Home community not found') + try { + const redeemJwtPayloadType = new RedeemJwtPayloadType( + senderCommunityUuid, + gradidoId, + alias ?? firstName ?? '', + code, + amount, + memo, + validUntil ?? '', + ) + // encode/sign the jwt with the private key of the sender/home community + const senderCom = await getCommunityByUuid(senderCommunityUuid) + if (!senderCom) { + throw new LogError('Sender community not found') + } + if (!senderCom.privateJwtKey) { + throw new LogError('Sender community privateJwtKey is not set') + } + const recipientCom = await getCommunityByUuid(recipientCommunityUuid) + if (!recipientCom) { + throw new LogError('Recipient community not found') + } + if (!recipientCom.publicJwtKey) { + throw new LogError('Recipient community publicJwtKey is not set') + } + const redeemJwt = await encryptAndSign(redeemJwtPayloadType, senderCom.privateJwtKey!, recipientCom.publicJwtKey!) + if (!redeemJwt) { + throw new LogError('Redeem JWT was not created successfully') + } + return redeemJwt + } catch (e) { + const errmsg = `Error on creating Redeem JWT: error=${e}` + methodLogger.error(errmsg) + throw new LogError(errmsg) } - if (!homeCom.communityUuid) { - throw new LogError('Home community UUID is not set') - } - const redeemJwt = await encode(redeemJwtPayloadType, homeCom.communityUuid) - // TODO: encrypt the payload with the public key of the target community - return redeemJwt } @Authorized([RIGHTS.DISBURSE_TRANSACTION_LINK]) From 9d9e6a14be7074da4382df6c890bcd5cf0258631 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Thu, 28 Aug 2025 19:02:02 +0200 Subject: [PATCH 24/48] transfer redeemJwt in an envelopJwt with pubKey --- .../resolver/TransactionLinkResolver.ts | 177 +++++++++--------- .../src/graphql/resolver/util/communities.ts | 5 + shared/src/index.ts | 1 + .../payloadtypes/SignedTransferPayloadType.ts | 21 +++ 4 files changed, 117 insertions(+), 87 deletions(-) create mode 100644 shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 227f6b4ba..e4d042914 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -6,13 +6,13 @@ import { TransactionLinkFilters } from '@arg/TransactionLinkFilters' import { ContributionCycleType } from '@enum/ContributionCycleType' import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionType } from '@enum/ContributionType' +import { Community } from '@model/Community' import { ContributionLink } from '@model/ContributionLink' import { RedeemJwtLink } from '@model/RedeemJwtLink' -import { Community } from '@model/Community' import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink' import { User } from '@model/User' import { QueryLinkResult } from '@union/QueryLinkResult' -import { Decay, TransactionTypeId } from 'core' +import { Decay, interpretEncryptedTransferArgs, TransactionTypeId } from 'core' import { AppDatabase, Community as DbCommunity, Contribution as DbContribution, ContributionLink as DbContributionLink, FederatedCommunity as DbFederatedCommunity, Transaction as DbTransaction, @@ -48,11 +48,14 @@ import { randombytes_random } from 'sodium-native' import { executeTransaction } from './TransactionResolver' import { getAuthenticatedCommunities, + getCommunityByIdentifier, + getCommunityByPublicKey, getCommunityByUuid, } from './util/communities' import { getUserCreation, validateContribution } from './util/creations' import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' import { transactionLinkList } from './util/transactionLinkList' +import { SignedTransferPayloadType } from 'shared' const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.TransactionLinkResolver.${method}`) @@ -454,7 +457,31 @@ export class TransactionLinkResolver { if (!redeemJwt) { throw new LogError('Redeem JWT was not created successfully') } - return redeemJwt + // prepare the args for the client invocation + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = redeemJwt + args.handshakeID = randombytes_random().toString() + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('successfully created RedeemJWT-Response with args:', args) + } + const signedTransferPayload = new SignedTransferPayloadType( + args.publicKey, + args.jwt, + args.handshakeID, + ) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('successfully created RedeemJWT-Response with signedTransferPayload:', signedTransferPayload) + } + const signedTransferJwt = await encode(signedTransferPayload, senderCom.privateJwtKey!) + if (!signedTransferJwt) { + throw new LogError('SignedTransfer JWT was not created successfully') + } + if(methodLogger.isDebugEnabled()) { + methodLogger.debug('successfully created RedeemJWT-Response with signedTransferJwt:', signedTransferJwt) + } + + return signedTransferJwt } catch (e) { const errmsg = `Error on creating Redeem JWT: error=${e}` methodLogger.error(errmsg) @@ -592,98 +619,75 @@ export class TransactionLinkResolver { } async queryRedeemJwtLink(code: string, logger: Logger): Promise { - logger.debug('TransactionLinkResolver.queryRedeemJwtLink... redeem jwt-token found') - // decode token first to get the senderCommunityUuid as input for verify token - const decodedPayload = decode(code) - logger.debug('TransactionLinkResolver.queryRedeemJwtLink... decodedPayload=', decodedPayload) - if ( - decodedPayload != null && - decodedPayload.tokentype === RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE - ) { - const redeemJwtPayload = new RedeemJwtPayloadType( - decodedPayload.sendercommunityuuid as string, - decodedPayload.sendergradidoid as string, - decodedPayload.sendername as string, - decodedPayload.redeemcode as string, - decodedPayload.amount as string, - decodedPayload.memo as string, - decodedPayload.validuntil as string, - ) - logger.debug( - 'TransactionLinkResolver.queryRedeemJwtLink... redeemJwtPayload=', - redeemJwtPayload, - ) - const senderCom = await getCommunityByUuid(redeemJwtPayload.sendercommunityuuid) + logger.debug('queryRedeemJwtLink... redeem jwt-token found') + + // decode token first to get the EncryptedTransferArgs with the senderCommunity.publicKey as input to verify token + const decodedPayload = decode(code) as SignedTransferPayloadType + logger.debug('queryRedeemJwtLink... decodedPayload=', decodedPayload) + if(decodedPayload !== null && decodedPayload.tokentype === SignedTransferPayloadType.SIGNED_TRANSFER_TYPE) { + const signedTransferPayload = new SignedTransferPayloadType( + decodedPayload.publicKey, + decodedPayload.jwt, + decodedPayload.handshakeID) + logger.debug('queryRedeemJwtLink... signedTransferPayload=', signedTransferPayload) + const senderCom = await getCommunityByPublicKey(Buffer.from(signedTransferPayload.publicKey)) if (!senderCom) { - throw new LogError('Sender community not found:', redeemJwtPayload.sendercommunityuuid) + const errmsg = `Sender community not found with publicKey=${signedTransferPayload.publicKey}` + logger.error(errmsg) + throw new Error(errmsg) } - logger.debug('TransactionLinkResolver.queryRedeemJwtLink... senderCom=', senderCom) - if (!senderCom.communityUuid) { - throw new LogError('Sender community UUID is not set') - } - // now with the sender community UUID the jwt token can be verified - const verifiedJwtPayload = await verify('handshakeID', code, senderCom.communityUuid) - logger.debug( - 'TransactionLinkResolver.queryRedeemJwtLink... nach verify verifiedJwtPayload=', - verifiedJwtPayload, - ) + logger.debug('queryRedeemJwtLink... senderCom=', senderCom) + const verifiedJwtPayload = await verify(signedTransferPayload.handshakeID, signedTransferPayload.jwt, signedTransferPayload.publicKey) as SignedTransferPayloadType + logger.debug('queryRedeemJwtLink... verifiedJwtPayload=', verifiedJwtPayload) let verifiedRedeemJwtPayload: RedeemJwtPayloadType | null = null - if (verifiedJwtPayload !== null) { - if (verifiedJwtPayload.exp !== undefined) { - const expDate = new Date(verifiedJwtPayload.exp * 1000) + if (verifiedJwtPayload === null) { + const errmsg = `Error on verify transferred redeem token with publicKey=${signedTransferPayload.publicKey}` + logger.error(errmsg) + throw new Error(errmsg) + } else { + const encryptedTransferArgs = new EncryptedTransferArgs() + encryptedTransferArgs.publicKey = verifiedJwtPayload.publicKey + encryptedTransferArgs.jwt = verifiedJwtPayload.jwt + encryptedTransferArgs.handshakeID = verifiedJwtPayload.handshakeID + + verifiedRedeemJwtPayload = await interpretEncryptedTransferArgs(encryptedTransferArgs) as RedeemJwtPayloadType + if(logger.isDebugEnabled()) { + logger.debug(`queryRedeemJwtLink() ...`, verifiedRedeemJwtPayload) + } + if (!verifiedRedeemJwtPayload) { + const errmsg = `invalid authentication payload of requesting community with publicKey` + verifiedJwtPayload.publicKey + logger.error(errmsg) + throw new Error(errmsg) + } + if (verifiedRedeemJwtPayload.tokentype === RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE) { + const errmsg = `Wrong tokentype in redeem JWT: type=` + verifiedRedeemJwtPayload.tokentype + ' vs expected ' + RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE + logger.error(errmsg) + throw new Error(errmsg) + } + if(senderCom?.communityUuid !== verifiedRedeemJwtPayload.sendercommunityuuid) { + const errmsg = `Mismatch of sender community UUID in redeem JWT against transfer JWT: uuid=` + senderCom.communityUuid + ' vs ' + verifiedRedeemJwtPayload.sendercommunityuuid + logger.error(errmsg) + throw new Error(errmsg) + } + if (verifiedRedeemJwtPayload.exp !== undefined) { + const expDate = new Date(verifiedRedeemJwtPayload.exp * 1000) logger.debug( - 'TransactionLinkResolver.queryRedeemJwtLink... expDate, exp =', + 'queryRedeemJwtLink... expDate, exp =', expDate, - verifiedJwtPayload.exp, + verifiedRedeemJwtPayload.exp, ) if (expDate < new Date()) { - throw new LogError('Redeem JWT-Token expired! jwtPayload.exp=', expDate) + const errmsg = `Redeem JWT-Token expired! jwtPayload.exp=${expDate}` + logger.error(errmsg) + throw new Error(errmsg) } } - if (verifiedJwtPayload.tokentype === RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE) { - logger.debug( - 'TransactionLinkResolver.queryRedeemJwtLink... verifiedJwtPayload.tokentype=', - verifiedJwtPayload.tokentype, - ) - verifiedRedeemJwtPayload = new RedeemJwtPayloadType( - verifiedJwtPayload.sendercommunityuuid as string, - verifiedJwtPayload.sendergradidoid as string, - verifiedJwtPayload.sendername as string, - verifiedJwtPayload.redeemcode as string, - verifiedJwtPayload.amount as string, - verifiedJwtPayload.memo as string, - verifiedJwtPayload.validuntil as string, - ) - logger.debug( - 'TransactionLinkResolver.queryRedeemJwtLink... nach verify verifiedRedeemJwtPayload=', - verifiedRedeemJwtPayload, - ) - } - } - if (verifiedRedeemJwtPayload === null) { - logger.debug( - 'TransactionLinkResolver.queryRedeemJwtLink... verifiedRedeemJwtPayload===null', - ) - verifiedRedeemJwtPayload = new RedeemJwtPayloadType( - decodedPayload.sendercommunityuuid as string, - decodedPayload.sendergradidoid as string, - decodedPayload.sendername as string, - decodedPayload.redeemcode as string, - decodedPayload.amount as string, - decodedPayload.memo as string, - decodedPayload.validuntil as string, - ) - } else { - // TODO: as long as the verification fails, fallback to simply decoded payload - verifiedRedeemJwtPayload = redeemJwtPayload - logger.debug( - 'TransactionLinkResolver.queryRedeemJwtLink... fallback to decode verifiedRedeemJwtPayload=', - verifiedRedeemJwtPayload, - ) } const homeCommunity = await getHomeCommunity() if (!homeCommunity) { - throw new LogError('Home community not found') + const errmsg = `Home community not found` + logger.error(errmsg) + throw new Error(errmsg) } const recipientCommunity = new Community(homeCommunity) const senderCommunity = new Community(senderCom) @@ -699,10 +703,9 @@ export class TransactionLinkResolver { logger.debug('TransactionLinkResolver.queryRedeemJwtLink... redeemJwtLink=', redeemJwtLink) return redeemJwtLink } else { - throw new LogError( - 'Redeem with wrong type of JWT-Token or expired! decodedPayload=', - decodedPayload, - ) + const errmsg = `transfer of redeem JWT with wrong envelope! code=${code}` + logger.error(errmsg) + throw new Error(errmsg) } } } diff --git a/backend/src/graphql/resolver/util/communities.ts b/backend/src/graphql/resolver/util/communities.ts index ee7a0f96d..d1288a1ea 100644 --- a/backend/src/graphql/resolver/util/communities.ts +++ b/backend/src/graphql/resolver/util/communities.ts @@ -78,6 +78,11 @@ export async function getCommunityByUuid(communityUuid: string): Promise { + return await DbCommunity.findOne({ + where: [{ publicKey: publicKey }], + }) +} export async function getAuthenticatedCommunities(): Promise { const dbCommunities: DbCommunity[] = await DbCommunity.find({ diff --git a/shared/src/index.ts b/shared/src/index.ts index afbe82bce..dd7965fdc 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -12,4 +12,5 @@ export * from './jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType' export * from './jwt/payloadtypes/RedeemJwtPayloadType' export * from './jwt/payloadtypes/SendCoinsJwtPayloadType' export * from './jwt/payloadtypes/SendCoinsResponseJwtPayloadType' +export * from './jwt/payloadtypes/SignedTransferPayloadType' diff --git a/shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts b/shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts new file mode 100644 index 000000000..26c4235f3 --- /dev/null +++ b/shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts @@ -0,0 +1,21 @@ +import { JwtPayloadType } from './JwtPayloadType' + +export class SignedTransferPayloadType extends JwtPayloadType { + static SIGNED_TRANSFER_TYPE = 'signed-transfer' + + publicKey: string + jwt: string + + constructor( + publicKey: string, + jwt: string, + handshakeID: string, + ) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + super(handshakeID) + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + this.tokentype = SignedTransferPayloadType.SIGNED_TRANSFER_TYPE + this.publicKey = publicKey + this.jwt = jwt + } +} From e1fc80f6bbb1dfc40aa70f69b5eeae0cd0de6cd0 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Thu, 28 Aug 2025 19:18:37 +0200 Subject: [PATCH 25/48] search senderCom with publicKey as Buffer(string, hex) --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index e4d042914..8432ae9d5 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -630,7 +630,7 @@ export class TransactionLinkResolver { decodedPayload.jwt, decodedPayload.handshakeID) logger.debug('queryRedeemJwtLink... signedTransferPayload=', signedTransferPayload) - const senderCom = await getCommunityByPublicKey(Buffer.from(signedTransferPayload.publicKey)) + const senderCom = await getCommunityByPublicKey(Buffer.from(signedTransferPayload.publicKey, 'hex')) if (!senderCom) { const errmsg = `Sender community not found with publicKey=${signedTransferPayload.publicKey}` logger.error(errmsg) From 364bb05da813de75ff4267cd8f548304f2a5b90b Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 29 Aug 2025 00:49:34 +0200 Subject: [PATCH 26/48] now use the correct senderCom.publicJwtKey to verify transferredRedeemJwt --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 8432ae9d5..f5341d383 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -637,7 +637,7 @@ export class TransactionLinkResolver { throw new Error(errmsg) } logger.debug('queryRedeemJwtLink... senderCom=', senderCom) - const verifiedJwtPayload = await verify(signedTransferPayload.handshakeID, signedTransferPayload.jwt, signedTransferPayload.publicKey) as SignedTransferPayloadType + const verifiedJwtPayload = await verify(signedTransferPayload.handshakeID, signedTransferPayload.jwt, senderCom.publicJwtKey!) as SignedTransferPayloadType logger.debug('queryRedeemJwtLink... verifiedJwtPayload=', verifiedJwtPayload) let verifiedRedeemJwtPayload: RedeemJwtPayloadType | null = null if (verifiedJwtPayload === null) { From 0c8b233dfd6392e630e26a3ea672904ec23ff1da Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 29 Aug 2025 14:32:43 +0200 Subject: [PATCH 27/48] correct result treatment of verifyJwtResult --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index f5341d383..80a5e94d3 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -637,14 +637,15 @@ export class TransactionLinkResolver { throw new Error(errmsg) } logger.debug('queryRedeemJwtLink... senderCom=', senderCom) - const verifiedJwtPayload = await verify(signedTransferPayload.handshakeID, signedTransferPayload.jwt, senderCom.publicJwtKey!) as SignedTransferPayloadType - logger.debug('queryRedeemJwtLink... verifiedJwtPayload=', verifiedJwtPayload) + const verifiedJwtResult = await verify(signedTransferPayload.handshakeID, signedTransferPayload.jwt, senderCom.publicJwtKey!) + logger.debug('queryRedeemJwtLink... verifiedJwtResult=', verifiedJwtResult) let verifiedRedeemJwtPayload: RedeemJwtPayloadType | null = null - if (verifiedJwtPayload === null) { + if (verifiedJwtResult === null) { const errmsg = `Error on verify transferred redeem token with publicKey=${signedTransferPayload.publicKey}` logger.error(errmsg) throw new Error(errmsg) } else { + const verifiedJwtPayload = verifiedJwtResult.payload as SignedTransferPayloadType const encryptedTransferArgs = new EncryptedTransferArgs() encryptedTransferArgs.publicKey = verifiedJwtPayload.publicKey encryptedTransferArgs.jwt = verifiedJwtPayload.jwt From d5c7f036c47877ddd6eb128b9f3224e4d8e25263 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 29 Aug 2025 15:02:36 +0200 Subject: [PATCH 28/48] next try --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 80a5e94d3..68dec8279 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -153,7 +153,7 @@ export class TransactionLinkResolver { @Query(() => QueryLinkResult) async queryTransactionLink(@Arg('code') code: string): Promise { const methodLogger = createLogger('queryTransactionLink') - methodLogger.addContext('code', code.substring(0, 6)) + methodLogger.addContext('handshakeID', randombytes_random().toString()) methodLogger.debug('queryTransactionLink...') if (code.match(/^CL-/)) { const contributionLink = await DbContributionLink.findOneOrFail({ From 4857852f8d45a62dc339c379959a848d55d4f20d Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 1 Sep 2025 16:55:20 +0200 Subject: [PATCH 29/48] next try to queryRedeemJwtLink --- .../graphql/resolver/TransactionLinkResolver.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 68dec8279..1e0a06bfb 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -36,7 +36,7 @@ import { Context, getClientTimezoneOffset, getUser } from '@/server/context' import { calculateBalance } from '@/util/validate' import { fullName } from 'core' import { TRANSACTION_LINK_LOCK, TRANSACTIONS_LOCK } from 'database' -import { calculateDecay, decode, DisburseJwtPayloadType, encode, encryptAndSign, RedeemJwtPayloadType, verify } from 'shared' +import { calculateDecay, decode, DisburseJwtPayloadType, encode, encryptAndSign, EncryptedJWEJwtPayloadType, RedeemJwtPayloadType, verify } from 'shared' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient' @@ -624,6 +624,8 @@ export class TransactionLinkResolver { // decode token first to get the EncryptedTransferArgs with the senderCommunity.publicKey as input to verify token const decodedPayload = decode(code) as SignedTransferPayloadType logger.debug('queryRedeemJwtLink... decodedPayload=', decodedPayload) + logger.debug('switch logger-context to received token-handshakeID:' + decodedPayload.handshakeID) + logger.addContext('handshakeID', decodedPayload.handshakeID) if(decodedPayload !== null && decodedPayload.tokentype === SignedTransferPayloadType.SIGNED_TRANSFER_TYPE) { const signedTransferPayload = new SignedTransferPayloadType( decodedPayload.publicKey, @@ -637,15 +639,18 @@ export class TransactionLinkResolver { throw new Error(errmsg) } logger.debug('queryRedeemJwtLink... senderCom=', senderCom) - const verifiedJwtResult = await verify(signedTransferPayload.handshakeID, signedTransferPayload.jwt, senderCom.publicJwtKey!) - logger.debug('queryRedeemJwtLink... verifiedJwtResult=', verifiedJwtResult) + const jweVerifyResult = await verify(signedTransferPayload.handshakeID, signedTransferPayload.jwt, senderCom.publicJwtKey!) + logger.debug('queryRedeemJwtLink... jweVerifyResult=', jweVerifyResult) let verifiedRedeemJwtPayload: RedeemJwtPayloadType | null = null - if (verifiedJwtResult === null) { + if (jweVerifyResult === null) { const errmsg = `Error on verify transferred redeem token with publicKey=${signedTransferPayload.publicKey}` logger.error(errmsg) throw new Error(errmsg) } else { - const verifiedJwtPayload = verifiedJwtResult.payload as SignedTransferPayloadType + const jwePayload = jweVerifyResult.payload as EncryptedJWEJwtPayloadType + logger.debug('queryRedeemJwtLink... jwePayload=', jwePayload) + const verifiedJwtPayload = jweVerifyResult.payload as SignedTransferPayloadType + logger.debug('queryRedeemJwtLink... verifiedJwtPayload=', verifiedJwtPayload) const encryptedTransferArgs = new EncryptedTransferArgs() encryptedTransferArgs.publicKey = verifiedJwtPayload.publicKey encryptedTransferArgs.jwt = verifiedJwtPayload.jwt From 5e21df03857bee65b74f96ef1d840967cac115cd Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 1 Sep 2025 17:13:59 +0200 Subject: [PATCH 30/48] correct initialization of EncryptedTransferArgs --- .../src/graphql/resolver/TransactionLinkResolver.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 1e0a06bfb..eb7e0be16 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -647,21 +647,17 @@ export class TransactionLinkResolver { logger.error(errmsg) throw new Error(errmsg) } else { - const jwePayload = jweVerifyResult.payload as EncryptedJWEJwtPayloadType - logger.debug('queryRedeemJwtLink... jwePayload=', jwePayload) - const verifiedJwtPayload = jweVerifyResult.payload as SignedTransferPayloadType - logger.debug('queryRedeemJwtLink... verifiedJwtPayload=', verifiedJwtPayload) const encryptedTransferArgs = new EncryptedTransferArgs() - encryptedTransferArgs.publicKey = verifiedJwtPayload.publicKey - encryptedTransferArgs.jwt = verifiedJwtPayload.jwt - encryptedTransferArgs.handshakeID = verifiedJwtPayload.handshakeID + encryptedTransferArgs.publicKey = signedTransferPayload.publicKey + encryptedTransferArgs.jwt = signedTransferPayload.jwt + encryptedTransferArgs.handshakeID = signedTransferPayload.handshakeID verifiedRedeemJwtPayload = await interpretEncryptedTransferArgs(encryptedTransferArgs) as RedeemJwtPayloadType if(logger.isDebugEnabled()) { logger.debug(`queryRedeemJwtLink() ...`, verifiedRedeemJwtPayload) } if (!verifiedRedeemJwtPayload) { - const errmsg = `invalid authentication payload of requesting community with publicKey` + verifiedJwtPayload.publicKey + const errmsg = `invalid authentication payload of requesting community with publicKey` + signedTransferPayload.publicKey logger.error(errmsg) throw new Error(errmsg) } From 3dada669ddd31e5dc3a5b789c4aa325dfcb61704 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 1 Sep 2025 17:32:34 +0200 Subject: [PATCH 31/48] correct check on token type --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index eb7e0be16..99668d724 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -661,7 +661,7 @@ export class TransactionLinkResolver { logger.error(errmsg) throw new Error(errmsg) } - if (verifiedRedeemJwtPayload.tokentype === RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE) { + if (verifiedRedeemJwtPayload.tokentype !== RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE) { const errmsg = `Wrong tokentype in redeem JWT: type=` + verifiedRedeemJwtPayload.tokentype + ' vs expected ' + RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE logger.error(errmsg) throw new Error(errmsg) From d2ad847d2221b92e03c462daf781c37604122f0e Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 15:21:56 +0200 Subject: [PATCH 32/48] add logoutput for testing --- .../LinkInformations/RedeemCommunitySelection.vue | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue b/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue index 46e9eb81f..0739ce33c 100644 --- a/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue +++ b/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue @@ -167,14 +167,19 @@ async function onSwitch(event) { alias: props.linkData.senderUser?.alias, validUntil: props.linkData.validUntil, }) - // console.log('RedeemCommunitySelection.onSwitch... response=', data) + console.log('RedeemCommunitySelection.onSwitch... response=', data) if (!data?.createRedeemJwt) { throw new Error('Failed to get redeem token') } const targetUrl = currentRecipientCommunity.value.url.replace(/\/api\/?$/, '') + console.log('RedeemCommunitySelection.onSwitch... targetUrl=', targetUrl) + console.log( + 'RedeemCommunitySelection.onSwitch... data.createRedeemJwt=', + data.createRedeemJwt, + ) window.location.href = targetUrl + '/redeem/' + data.createRedeemJwt } catch (error) { - // console.error('RedeemCommunitySelection.onSwitch error:', error) + console.error('RedeemCommunitySelection.onSwitch error:', error) throw error } } From eb7e2ad57918e8762609019ec0d4ffa46dee75fb Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 15:41:11 +0200 Subject: [PATCH 33/48] other logoutput for testings --- .../RedeemCommunitySelection.vue | 9 +- frontend/src/pages/TransactionLink.vue | 179 +++++++++--------- 2 files changed, 90 insertions(+), 98 deletions(-) diff --git a/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue b/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue index 0739ce33c..46e9eb81f 100644 --- a/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue +++ b/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue @@ -167,19 +167,14 @@ async function onSwitch(event) { alias: props.linkData.senderUser?.alias, validUntil: props.linkData.validUntil, }) - console.log('RedeemCommunitySelection.onSwitch... response=', data) + // console.log('RedeemCommunitySelection.onSwitch... response=', data) if (!data?.createRedeemJwt) { throw new Error('Failed to get redeem token') } const targetUrl = currentRecipientCommunity.value.url.replace(/\/api\/?$/, '') - console.log('RedeemCommunitySelection.onSwitch... targetUrl=', targetUrl) - console.log( - 'RedeemCommunitySelection.onSwitch... data.createRedeemJwt=', - data.createRedeemJwt, - ) window.location.href = targetUrl + '/redeem/' + data.createRedeemJwt } catch (error) { - console.error('RedeemCommunitySelection.onSwitch error:', error) + // console.error('RedeemCommunitySelection.onSwitch error:', error) throw error } } diff --git a/frontend/src/pages/TransactionLink.vue b/frontend/src/pages/TransactionLink.vue index 285625882..edf46bd58 100644 --- a/frontend/src/pages/TransactionLink.vue +++ b/frontend/src/pages/TransactionLink.vue @@ -116,8 +116,8 @@ const tokenExpiresInSeconds = computed(() => { }) const validLink = computed(() => { - // console.log('TransactionLink.validLink... linkData.value.validUntil=', linkData.value.validUntil) - // console.log('TransactionLink.validLink... new Date()=', new Date()) + console.log('TransactionLink.validLink... linkData.value.validUntil=', linkData.value.validUntil) + console.log('TransactionLink.validLink... new Date()=', new Date()) if (!isTransactionLinkLoaded.value) { return false } @@ -125,46 +125,46 @@ const validLink = computed(() => { return false } const validUntilDate = new Date(linkData.value.validUntil) - // console.log('TransactionLink.validLink... validUntilDate=', validUntilDate) - // console.log('TransactionLink.validLink... new Date()=', new Date()) - // console.log( - // 'TransactionLink.validLink... validUntilDate.getTime() >= new Date().getTime()=', - // validUntilDate.getTime() >= new Date().getTime(), - // ) + console.log('TransactionLink.validLink... validUntilDate=', validUntilDate) + console.log('TransactionLink.validLink... new Date()=', new Date()) + console.log( + 'TransactionLink.validLink... validUntilDate.getTime() >= new Date().getTime()=', + validUntilDate.getTime() >= new Date().getTime(), + ) return validUntilDate.getTime() >= new Date().getTime() }) const itemType = computed(() => { - // console.log('TransactionLink.itemType... isTransactionLinkLoaded=', isTransactionLinkLoaded.value) + console.log('TransactionLink.itemType... isTransactionLinkLoaded=', isTransactionLinkLoaded.value) if (isTransactionLinkLoaded.value) { - // console.log('TransactionLink.itemType... linkData.value=', linkData.value) + console.log('TransactionLink.itemType... linkData.value=', linkData.value) if (linkData.value.deletedAt) { - // console.log('TransactionLink.itemType... TEXT_DELETED') + console.log('TransactionLink.itemType... TEXT_DELETED') return 'TEXT_DELETED' } const validUntilDate = new Date(linkData.value.validUntil) - // console.log('TransactionLink.itemType... validUntilDate=', validUntilDate) - // console.log('TransactionLink.itemType... new Date()=', new Date()) - // console.log( - // 'TransactionLink.itemType... validUntilDate.getTime() < new Date().getTime()=', - // validUntilDate.getTime() < new Date().getTime(), - // ) + console.log('TransactionLink.itemType... validUntilDate=', validUntilDate) + console.log('TransactionLink.itemType... new Date()=', new Date()) + console.log( + 'TransactionLink.itemType... validUntilDate.getTime() < new Date().getTime()=', + validUntilDate.getTime() < new Date().getTime(), + ) if (validUntilDate.getTime() < new Date().getTime()) { - // console.log('TransactionLink.itemType... TEXT_EXPIRED') + console.log('TransactionLink.itemType... TEXT_EXPIRED') return 'TEXT_EXPIRED' } if (linkData.value.redeemedAt) { - // console.log('TransactionLink.itemType... TEXT_REDEEMED') + console.log('TransactionLink.itemType... TEXT_REDEEMED') return 'TEXT_REDEEMED' } if (linkData.value.deletedAt) { - // console.log('TransactionLink.itemType... TEXT_DELETED') + console.log('TransactionLink.itemType... TEXT_DELETED') return 'TEXT_DELETED' } if (store.state.token && store.state.tokenTime) { if (tokenExpiresInSeconds.value < 5) { - // console.log('TransactionLink.itemType... REDEEM_SELECT_COMMUNITY') + console.log('TransactionLink.itemType... REDEEM_SELECT_COMMUNITY') if (CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE) { return 'REDEEM_SELECT_COMMUNITY' } else { @@ -172,28 +172,28 @@ const itemType = computed(() => { } } } - // console.log( - // 'TransactionLink.itemType... linkData.value.recipientUser=', - // linkData.value.recipientUser, - // ) - // console.log('TransactionLink.itemType... linkData.value=', linkData.value) - // console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) - // console.log('TransactionLink.itemType... isRedeemJwtLink=', isRedeemJwtLink.value) - // console.log('TransactionLink.itemType... linkData.value.senderUser=', linkData.value.senderUser) - // console.log( - // 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', - // linkData.value.recipientUser?.gradidoID, - // ) - // console.log( - // 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', - // linkData.value.senderUser?.gradidoID, - // ) + console.log( + 'TransactionLink.itemType... linkData.value.recipientUser=', + linkData.value.recipientUser, + ) + console.log('TransactionLink.itemType... linkData.value=', linkData.value) + console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) + console.log('TransactionLink.itemType... isRedeemJwtLink=', isRedeemJwtLink.value) + console.log('TransactionLink.itemType... linkData.value.senderUser=', linkData.value.senderUser) + console.log( + 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', + linkData.value.recipientUser?.gradidoID, + ) + console.log( + 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', + linkData.value.senderUser?.gradidoID, + ) if ( linkData.value.senderUser && linkData.value.recipientUser && linkData.value.senderUser.gradidoID === linkData.value.recipientUser.gradidoID ) { - // console.log('TransactionLink.itemType... SELF_CREATOR') + console.log('TransactionLink.itemType... SELF_CREATOR') return 'SELF_CREATOR' } if ( @@ -202,22 +202,22 @@ const itemType = computed(() => { linkData.value.senderUser.gradidoID !== linkData.value.recipientUser.gradidoID && store.state.gradidoID === linkData.value.recipientUser.gradidoID ) { - // console.log('TransactionLink.itemType... VALID') - // console.log('TransactionLink.itemType... linkData.value=', linkData.value) - // console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) - // console.log( - // 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', - // linkData.value.recipientUser.gradidoID, - // ) - // console.log( - // 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', - // linkData.value.senderUser.gradidoID, - // ) + console.log('TransactionLink.itemType... VALID') + console.log('TransactionLink.itemType... linkData.value=', linkData.value) + console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) + console.log( + 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', + linkData.value.recipientUser.gradidoID, + ) + console.log( + 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', + linkData.value.senderUser.gradidoID, + ) return 'VALID' } } if (CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE) { - // console.log('TransactionLink.itemType...last return= REDEEM_SELECT_COMMUNITY') + console.log('TransactionLink.itemType...last return= REDEEM_SELECT_COMMUNITY') return 'REDEEM_SELECT_COMMUNITY' } else { return 'LOGGED_OUT' @@ -225,8 +225,8 @@ const itemType = computed(() => { }) const itemTypeExt = computed(() => { - // console.log('TransactionLink.itemTypeExt... itemType=', itemType.value) - // console.log('TransactionLink.itemTypeExt... validLink=', validLink.value) + console.log('TransactionLink.itemTypeExt... itemType=', itemType.value) + console.log('TransactionLink.itemTypeExt... validLink=', validLink.value) if (itemType.value.startsWith('TEXT')) { return 'TEXT' } @@ -234,13 +234,13 @@ const itemTypeExt = computed(() => { }) watch(itemType, (newItemType) => { - // console.log('TransactionLink.watch... itemType=', itemType.value) - // console.log('TransactionLink.watch... validLink=', validLink.value) + console.log('TransactionLink.watch... itemType=', itemType.value) + console.log('TransactionLink.watch... validLink=', validLink.value) updateRedeemedBoxText(newItemType) }) function updateRedeemedBoxText(type) { - // console.log('TransactionLink.updateRedeemedBoxText... type=', type) + console.log('TransactionLink.updateRedeemedBoxText... type=', type) switch (type) { case 'TEXT_DELETED': redeemedBoxText.value = t('gdd_per_link.link-deleted', { @@ -260,90 +260,87 @@ function updateRedeemedBoxText(type) { default: redeemedBoxText.value = '' } - // console.log('TransactionLink.updateRedeemedBoxText... redeemedBoxText=', redeemedBoxText) + console.log('TransactionLink.updateRedeemedBoxText... redeemedBoxText=', redeemedBoxText) } const emit = defineEmits(['set-mobile-start']) onMounted(() => { - // console.log('TransactionLink.onMounted... params=', params) + console.log('TransactionLink.onMounted... params=', params) emit('set-mobile-start', false) }) onResult(() => { - // console.log('TransactionLink.onResult... result=', result.value) - // console.log('TransactionLink.onResult... stringify result=', JSON.stringify(result.value)) + console.log('TransactionLink.onResult... result=', result.value) + console.log('TransactionLink.onResult... stringify result=', JSON.stringify(result.value)) if (result.value?.queryTransactionLink?.__typename === 'TransactionLink') { - // console.log('TransactionLink.onResult... TransactionLink') + console.log('TransactionLink.onResult... TransactionLink') isTransactionLinkLoaded.value = true setTransactionLinkInformation() } else if (result.value?.queryTransactionLink?.__typename === 'ContributionLink') { - // console.log('TransactionLink.onResult... ContributionLink') + console.log('TransactionLink.onResult... ContributionLink') isTransactionLinkLoaded.value = true setContributionLinkInformation() } else if (result.value?.queryTransactionLink?.__typename === 'RedeemJwtLink') { - // console.log('TransactionLink.onResult... RedeemJwtLink') + console.log('TransactionLink.onResult... RedeemJwtLink') isTransactionLinkLoaded.value = true setRedeemJwtLinkInformation() } else { - // console.log('TransactionLink.onResult... unknown type:', result.value) + console.log('TransactionLink.onResult... unknown type:', result.value) } }) onError(() => { - // console.log('TransactionLink.onError... error=', error) + console.log('TransactionLink.onError... error=', error) toastError(t('gdd_per_link.redeemlink-error')) }) function setTransactionLinkInformation() { - // console.log('TransactionLink.setTransactionLinkInformation... result=', result.value) + console.log('TransactionLink.setTransactionLinkInformation... result=', result.value) // const queryTransactionLink = result.value.queryTransactionLink const deepCopy = JSON.parse(JSON.stringify(result.value)) - // console.log('TransactionLink.setTransactionLinkInformation... deepCopy=', deepCopy) + console.log('TransactionLink.setTransactionLinkInformation... deepCopy=', deepCopy) if (deepCopy && deepCopy.queryTransactionLink.__typename === 'TransactionLink') { - // console.log('TransactionLink.setTransactionLinkInformation... typename === TransactionLink') + console.log('TransactionLink.setTransactionLinkInformation... typename === TransactionLink') // recipientUser is only set if the user is logged in if (store.state.gradidoID !== null) { - // console.log( - // 'TransactionLink.setTransactionLinkInformation... gradidoID=', - // store.state.gradidoID, - // ) + console.log( + 'TransactionLink.setTransactionLinkInformation... gradidoID=', + store.state.gradidoID, + ) deepCopy.queryTransactionLink.recipientUser = { __typename: 'User', gradidoID: store.state.gradidoID, firstName: store.state.firstName, alias: store.state.alias, } - // console.log( - // 'TransactionLink.setTransactionLinkInformation... deepCopy.queryTransactionLink.recipientUser=', - // deepCopy.queryTransactionLink.recipientUser, - // ) + console.log( + 'TransactionLink.setTransactionLinkInformation... deepCopy.queryTransactionLink.recipientUser=', + deepCopy.queryTransactionLink.recipientUser, + ) } linkData.value = deepCopy.queryTransactionLink - // console.log('TransactionLink.setTransactionLinkInformation... linkData.value=', linkData.value) + console.log('TransactionLink.setTransactionLinkInformation... linkData.value=', linkData.value) } } function setContributionLinkInformation() { linkData.value = result.value.queryTransactionLink if (linkData.value.__typename === 'ContributionLink' && store.state.token) { - // console.log('TransactionLink.setTransactionLinkInformation... typename === ContributionLink') + console.log('TransactionLink.setTransactionLinkInformation... typename === ContributionLink') // explicit no await mutationLink(linkData.value.amount) } } function setRedeemJwtLinkInformation() { - // console.log('TransactionLink.setRedeemJwtLinkInformation... result=', result.value) + console.log('TransactionLink.setRedeemJwtLinkInformation... result=', result.value) const deepCopy = JSON.parse(JSON.stringify(result.value)) - // console.log('TransactionLink.setRedeemJwtLinkInformation... deepCopy=', deepCopy) + console.log('TransactionLink.setRedeemJwtLinkInformation... deepCopy=', deepCopy) if (deepCopy) { // recipientUser is only set if the user is logged in if (store.state.gradidoID !== null) { - // console.log( - // 'TransactionLink.setRedeemJwtLinkInformation... gradidoID=', - // store.state.gradidoID, - // ) + console.log('TransactionLink.setRedeemJwtLinkInformation... gradidoID=', store.state.gradidoID) deepCopy.queryTransactionLink.recipientUser = { __typename: 'User', gradidoID: store.state.gradidoID, @@ -351,19 +348,19 @@ function setRedeemJwtLinkInformation() { alias: store.state.alias, } } - // console.log( - // 'TransactionLink.setRedeemJwtLinkInformation... deepCopy.queryTransactionLink.recipientUser=', - // deepCopy.queryTransactionLink.recipientUser, - // ) + console.log( + 'TransactionLink.setRedeemJwtLinkInformation... deepCopy.queryTransactionLink.recipientUser=', + deepCopy.queryTransactionLink.recipientUser, + ) linkData.value = deepCopy.queryTransactionLink - // console.log('TransactionLink.setRedeemJwtLinkInformation... linkData.value=', linkData.value) + console.log('TransactionLink.setRedeemJwtLinkInformation... linkData.value=', linkData.value) } } async function mutationLink(amount) { - // console.log('TransactionLink.mutationLink... params=', params) + console.log('TransactionLink.mutationLink... params=', params) if (isRedeemJwtLink.value) { - // console.log('TransactionLink.mutationLink... trigger disbursement from recipient-community') + console.log('TransactionLink.mutationLink... trigger disbursement from recipient-community') try { await disburseMutate({ code: params.code, @@ -375,7 +372,7 @@ async function mutationLink(amount) { await router.push('/overview') } } else { - // console.log('TransactionLink.mutationLink... local transaction or contribution') + console.log('TransactionLink.mutationLink... local transaction or contribution') try { await redeemMutate({ code: redeemCode.value, From 50b45a79bffa49a49dcf66a76f4828a450c0e9e2 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 16:09:47 +0200 Subject: [PATCH 34/48] more logoutput for tests --- frontend/src/pages/TransactionLink.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/pages/TransactionLink.vue b/frontend/src/pages/TransactionLink.vue index edf46bd58..e6da36121 100644 --- a/frontend/src/pages/TransactionLink.vue +++ b/frontend/src/pages/TransactionLink.vue @@ -359,6 +359,8 @@ function setRedeemJwtLinkInformation() { async function mutationLink(amount) { console.log('TransactionLink.mutationLink... params=', params) + console.log('TransactionLink.mutationLink... linkData.value=', linkData.value) + console.log('TransactionLink.mutationLink... linkData=', linkData) if (isRedeemJwtLink.value) { console.log('TransactionLink.mutationLink... trigger disbursement from recipient-community') try { From 9318d173289c5586f7c3bb3db794275db9690646 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 16:34:59 +0200 Subject: [PATCH 35/48] correct parameters for invokation of disburseMutation --- frontend/src/pages/TransactionLink.vue | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/TransactionLink.vue b/frontend/src/pages/TransactionLink.vue index e6da36121..60c110553 100644 --- a/frontend/src/pages/TransactionLink.vue +++ b/frontend/src/pages/TransactionLink.vue @@ -365,7 +365,17 @@ async function mutationLink(amount) { console.log('TransactionLink.mutationLink... trigger disbursement from recipient-community') try { await disburseMutate({ - code: params.code, + senderCommunityUuid: linkData.value.senderCommunity.uuid, + senderGradidoId: linkData.value.senderUser.gradidoID, + recipientCommunityUuid: linkData.value.recipientCommunity.uuid, + recipientCommunityName: linkData.value.recipientCommunity.name, + recipientGradidoId: linkData.value.recipientUser.gradidoID, + recipientFirstName: linkData.value.recipientUser.firstName, + code: linkData.value.code, + amount: linkData.value.amount, + memo: linkData.value.memo, + validUntil: linkData.value.validUntil, + recipientAlias: linkData.value.recipientUser.alias, }) toastSuccess(t('gdd_per_link.disbured', { n: amount })) await router.push('/overview') From be51e3709292e8ea70409c509d0a482cf4016890 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 17:01:50 +0200 Subject: [PATCH 36/48] remove loggers and export DisbursementResolver --- federation/src/graphql/api/1_0/schema.ts | 3 +- frontend/src/pages/TransactionLink.vue | 178 +++++++++++------------ 2 files changed, 91 insertions(+), 90 deletions(-) diff --git a/federation/src/graphql/api/1_0/schema.ts b/federation/src/graphql/api/1_0/schema.ts index 7b88fba5c..fcb05c803 100644 --- a/federation/src/graphql/api/1_0/schema.ts +++ b/federation/src/graphql/api/1_0/schema.ts @@ -1,9 +1,10 @@ import { NonEmptyArray } from 'type-graphql' import { AuthenticationResolver } from './resolver/AuthenticationResolver' +import { DisbursementResolver } from './resolver/DisbursementResolver' import { PublicCommunityInfoResolver } from './resolver/PublicCommunityInfoResolver' import { PublicKeyResolver } from './resolver/PublicKeyResolver' import { SendCoinsResolver } from './resolver/SendCoinsResolver' export const getApiResolvers = (): NonEmptyArray => { - return [AuthenticationResolver, PublicCommunityInfoResolver, PublicKeyResolver, SendCoinsResolver] + return [AuthenticationResolver, DisbursementResolver, PublicCommunityInfoResolver, PublicKeyResolver, SendCoinsResolver] } diff --git a/frontend/src/pages/TransactionLink.vue b/frontend/src/pages/TransactionLink.vue index 60c110553..2e81d8913 100644 --- a/frontend/src/pages/TransactionLink.vue +++ b/frontend/src/pages/TransactionLink.vue @@ -116,8 +116,8 @@ const tokenExpiresInSeconds = computed(() => { }) const validLink = computed(() => { - console.log('TransactionLink.validLink... linkData.value.validUntil=', linkData.value.validUntil) - console.log('TransactionLink.validLink... new Date()=', new Date()) + // console.log('TransactionLink.validLink... linkData.value.validUntil=', linkData.value.validUntil) + // console.log('TransactionLink.validLink... new Date()=', new Date()) if (!isTransactionLinkLoaded.value) { return false } @@ -125,46 +125,46 @@ const validLink = computed(() => { return false } const validUntilDate = new Date(linkData.value.validUntil) - console.log('TransactionLink.validLink... validUntilDate=', validUntilDate) - console.log('TransactionLink.validLink... new Date()=', new Date()) - console.log( - 'TransactionLink.validLink... validUntilDate.getTime() >= new Date().getTime()=', - validUntilDate.getTime() >= new Date().getTime(), - ) + // console.log('TransactionLink.validLink... validUntilDate=', validUntilDate) + // console.log('TransactionLink.validLink... new Date()=', new Date()) + // console.log( + // 'TransactionLink.validLink... validUntilDate.getTime() >= new Date().getTime()=', + // validUntilDate.getTime() >= new Date().getTime(), + // ) return validUntilDate.getTime() >= new Date().getTime() }) const itemType = computed(() => { - console.log('TransactionLink.itemType... isTransactionLinkLoaded=', isTransactionLinkLoaded.value) + // console.log('TransactionLink.itemType... isTransactionLinkLoaded=', isTransactionLinkLoaded.value) if (isTransactionLinkLoaded.value) { - console.log('TransactionLink.itemType... linkData.value=', linkData.value) + // console.log('TransactionLink.itemType... linkData.value=', linkData.value) if (linkData.value.deletedAt) { - console.log('TransactionLink.itemType... TEXT_DELETED') + // console.log('TransactionLink.itemType... TEXT_DELETED') return 'TEXT_DELETED' } const validUntilDate = new Date(linkData.value.validUntil) - console.log('TransactionLink.itemType... validUntilDate=', validUntilDate) - console.log('TransactionLink.itemType... new Date()=', new Date()) - console.log( - 'TransactionLink.itemType... validUntilDate.getTime() < new Date().getTime()=', - validUntilDate.getTime() < new Date().getTime(), - ) + // console.log('TransactionLink.itemType... validUntilDate=', validUntilDate) + // console.log('TransactionLink.itemType... new Date()=', new Date()) + // console.log( + // 'TransactionLink.itemType... validUntilDate.getTime() < new Date().getTime()=', + // validUntilDate.getTime() < new Date().getTime(), + // ) if (validUntilDate.getTime() < new Date().getTime()) { console.log('TransactionLink.itemType... TEXT_EXPIRED') return 'TEXT_EXPIRED' } if (linkData.value.redeemedAt) { - console.log('TransactionLink.itemType... TEXT_REDEEMED') + // console.log('TransactionLink.itemType... TEXT_REDEEMED') return 'TEXT_REDEEMED' } if (linkData.value.deletedAt) { - console.log('TransactionLink.itemType... TEXT_DELETED') + // console.log('TransactionLink.itemType... TEXT_DELETED') return 'TEXT_DELETED' } if (store.state.token && store.state.tokenTime) { if (tokenExpiresInSeconds.value < 5) { - console.log('TransactionLink.itemType... REDEEM_SELECT_COMMUNITY') + // console.log('TransactionLink.itemType... REDEEM_SELECT_COMMUNITY') if (CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE) { return 'REDEEM_SELECT_COMMUNITY' } else { @@ -172,28 +172,28 @@ const itemType = computed(() => { } } } - console.log( - 'TransactionLink.itemType... linkData.value.recipientUser=', - linkData.value.recipientUser, - ) - console.log('TransactionLink.itemType... linkData.value=', linkData.value) - console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) - console.log('TransactionLink.itemType... isRedeemJwtLink=', isRedeemJwtLink.value) - console.log('TransactionLink.itemType... linkData.value.senderUser=', linkData.value.senderUser) - console.log( - 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', - linkData.value.recipientUser?.gradidoID, - ) - console.log( - 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', - linkData.value.senderUser?.gradidoID, - ) + // console.log( + // 'TransactionLink.itemType... linkData.value.recipientUser=', + // linkData.value.recipientUser, + // ) + // console.log('TransactionLink.itemType... linkData.value=', linkData.value) + // console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) + // console.log('TransactionLink.itemType... isRedeemJwtLink=', isRedeemJwtLink.value) + // console.log('TransactionLink.itemType... linkData.value.senderUser=', linkData.value.senderUser) + // console.log( + // 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', + // linkData.value.recipientUser?.gradidoID, + // ) + // console.log( + // 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', + // linkData.value.senderUser?.gradidoID, + // ) if ( linkData.value.senderUser && linkData.value.recipientUser && linkData.value.senderUser.gradidoID === linkData.value.recipientUser.gradidoID ) { - console.log('TransactionLink.itemType... SELF_CREATOR') + // console.log('TransactionLink.itemType... SELF_CREATOR') return 'SELF_CREATOR' } if ( @@ -202,22 +202,22 @@ const itemType = computed(() => { linkData.value.senderUser.gradidoID !== linkData.value.recipientUser.gradidoID && store.state.gradidoID === linkData.value.recipientUser.gradidoID ) { - console.log('TransactionLink.itemType... VALID') - console.log('TransactionLink.itemType... linkData.value=', linkData.value) - console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) - console.log( - 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', - linkData.value.recipientUser.gradidoID, - ) - console.log( - 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', - linkData.value.senderUser.gradidoID, - ) + // console.log('TransactionLink.itemType... VALID') + // console.log('TransactionLink.itemType... linkData.value=', linkData.value) + // console.log('TransactionLink.itemType... store.state.gradidoID=', store.state.gradidoID) + // console.log( + // 'TransactionLink.itemType... linkData.value.recipientUser.gradidoID=', + // linkData.value.recipientUser.gradidoID, + // ) + // console.log( + // 'TransactionLink.itemType... linkData.value.senderUser.gradidoID=', + // linkData.value.senderUser.gradidoID, + // ) return 'VALID' } } if (CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE) { - console.log('TransactionLink.itemType...last return= REDEEM_SELECT_COMMUNITY') + // console.log('TransactionLink.itemType...last return= REDEEM_SELECT_COMMUNITY') return 'REDEEM_SELECT_COMMUNITY' } else { return 'LOGGED_OUT' @@ -225,8 +225,8 @@ const itemType = computed(() => { }) const itemTypeExt = computed(() => { - console.log('TransactionLink.itemTypeExt... itemType=', itemType.value) - console.log('TransactionLink.itemTypeExt... validLink=', validLink.value) + // console.log('TransactionLink.itemTypeExt... itemType=', itemType.value) + // console.log('TransactionLink.itemTypeExt... validLink=', validLink.value) if (itemType.value.startsWith('TEXT')) { return 'TEXT' } @@ -234,13 +234,13 @@ const itemTypeExt = computed(() => { }) watch(itemType, (newItemType) => { - console.log('TransactionLink.watch... itemType=', itemType.value) - console.log('TransactionLink.watch... validLink=', validLink.value) + // console.log('TransactionLink.watch... itemType=', itemType.value) + // console.log('TransactionLink.watch... validLink=', validLink.value) updateRedeemedBoxText(newItemType) }) function updateRedeemedBoxText(type) { - console.log('TransactionLink.updateRedeemedBoxText... type=', type) + // console.log('TransactionLink.updateRedeemedBoxText... type=', type) switch (type) { case 'TEXT_DELETED': redeemedBoxText.value = t('gdd_per_link.link-deleted', { @@ -260,87 +260,87 @@ function updateRedeemedBoxText(type) { default: redeemedBoxText.value = '' } - console.log('TransactionLink.updateRedeemedBoxText... redeemedBoxText=', redeemedBoxText) + // console.log('TransactionLink.updateRedeemedBoxText... redeemedBoxText=', redeemedBoxText) } const emit = defineEmits(['set-mobile-start']) onMounted(() => { - console.log('TransactionLink.onMounted... params=', params) + // console.log('TransactionLink.onMounted... params=', params) emit('set-mobile-start', false) }) onResult(() => { - console.log('TransactionLink.onResult... result=', result.value) - console.log('TransactionLink.onResult... stringify result=', JSON.stringify(result.value)) + // console.log('TransactionLink.onResult... result=', result.value) + // console.log('TransactionLink.onResult... stringify result=', JSON.stringify(result.value)) if (result.value?.queryTransactionLink?.__typename === 'TransactionLink') { - console.log('TransactionLink.onResult... TransactionLink') + // console.log('TransactionLink.onResult... TransactionLink') isTransactionLinkLoaded.value = true setTransactionLinkInformation() } else if (result.value?.queryTransactionLink?.__typename === 'ContributionLink') { - console.log('TransactionLink.onResult... ContributionLink') + // console.log('TransactionLink.onResult... ContributionLink') isTransactionLinkLoaded.value = true setContributionLinkInformation() } else if (result.value?.queryTransactionLink?.__typename === 'RedeemJwtLink') { - console.log('TransactionLink.onResult... RedeemJwtLink') + // console.log('TransactionLink.onResult... RedeemJwtLink') isTransactionLinkLoaded.value = true setRedeemJwtLinkInformation() } else { - console.log('TransactionLink.onResult... unknown type:', result.value) + // console.log('TransactionLink.onResult... unknown type:', result.value) } }) onError(() => { - console.log('TransactionLink.onError... error=', error) + // console.log('TransactionLink.onError... error=', error) toastError(t('gdd_per_link.redeemlink-error')) }) function setTransactionLinkInformation() { - console.log('TransactionLink.setTransactionLinkInformation... result=', result.value) + // console.log('TransactionLink.setTransactionLinkInformation... result=', result.value) // const queryTransactionLink = result.value.queryTransactionLink const deepCopy = JSON.parse(JSON.stringify(result.value)) - console.log('TransactionLink.setTransactionLinkInformation... deepCopy=', deepCopy) + // console.log('TransactionLink.setTransactionLinkInformation... deepCopy=', deepCopy) if (deepCopy && deepCopy.queryTransactionLink.__typename === 'TransactionLink') { - console.log('TransactionLink.setTransactionLinkInformation... typename === TransactionLink') + // console.log('TransactionLink.setTransactionLinkInformation... typename === TransactionLink') // recipientUser is only set if the user is logged in if (store.state.gradidoID !== null) { - console.log( - 'TransactionLink.setTransactionLinkInformation... gradidoID=', - store.state.gradidoID, - ) + // console.log( + // 'TransactionLink.setTransactionLinkInformation... gradidoID=', + // store.state.gradidoID, + // ) deepCopy.queryTransactionLink.recipientUser = { __typename: 'User', gradidoID: store.state.gradidoID, firstName: store.state.firstName, alias: store.state.alias, } - console.log( - 'TransactionLink.setTransactionLinkInformation... deepCopy.queryTransactionLink.recipientUser=', - deepCopy.queryTransactionLink.recipientUser, - ) + // console.log( + // 'TransactionLink.setTransactionLinkInformation... deepCopy.queryTransactionLink.recipientUser=', + // deepCopy.queryTransactionLink.recipientUser, + // ) } linkData.value = deepCopy.queryTransactionLink - console.log('TransactionLink.setTransactionLinkInformation... linkData.value=', linkData.value) + // console.log('TransactionLink.setTransactionLinkInformation... linkData.value=', linkData.value) } } function setContributionLinkInformation() { linkData.value = result.value.queryTransactionLink if (linkData.value.__typename === 'ContributionLink' && store.state.token) { - console.log('TransactionLink.setTransactionLinkInformation... typename === ContributionLink') + // console.log('TransactionLink.setTransactionLinkInformation... typename === ContributionLink') // explicit no await mutationLink(linkData.value.amount) } } function setRedeemJwtLinkInformation() { - console.log('TransactionLink.setRedeemJwtLinkInformation... result=', result.value) + // console.log('TransactionLink.setRedeemJwtLinkInformation... result=', result.value) const deepCopy = JSON.parse(JSON.stringify(result.value)) - console.log('TransactionLink.setRedeemJwtLinkInformation... deepCopy=', deepCopy) + // console.log('TransactionLink.setRedeemJwtLinkInformation... deepCopy=', deepCopy) if (deepCopy) { // recipientUser is only set if the user is logged in if (store.state.gradidoID !== null) { - console.log('TransactionLink.setRedeemJwtLinkInformation... gradidoID=', store.state.gradidoID) + // console.log('TransactionLink.setRedeemJwtLinkInformation... gradidoID=', store.state.gradidoID) deepCopy.queryTransactionLink.recipientUser = { __typename: 'User', gradidoID: store.state.gradidoID, @@ -348,21 +348,21 @@ function setRedeemJwtLinkInformation() { alias: store.state.alias, } } - console.log( - 'TransactionLink.setRedeemJwtLinkInformation... deepCopy.queryTransactionLink.recipientUser=', - deepCopy.queryTransactionLink.recipientUser, - ) + // console.log( + // 'TransactionLink.setRedeemJwtLinkInformation... deepCopy.queryTransactionLink.recipientUser=', + // deepCopy.queryTransactionLink.recipientUser, + // ) linkData.value = deepCopy.queryTransactionLink - console.log('TransactionLink.setRedeemJwtLinkInformation... linkData.value=', linkData.value) + // console.log('TransactionLink.setRedeemJwtLinkInformation... linkData.value=', linkData.value) } } async function mutationLink(amount) { - console.log('TransactionLink.mutationLink... params=', params) - console.log('TransactionLink.mutationLink... linkData.value=', linkData.value) - console.log('TransactionLink.mutationLink... linkData=', linkData) + // console.log('TransactionLink.mutationLink... params=', params) + // console.log('TransactionLink.mutationLink... linkData.value=', linkData.value) + // console.log('TransactionLink.mutationLink... linkData=', linkData) if (isRedeemJwtLink.value) { - console.log('TransactionLink.mutationLink... trigger disbursement from recipient-community') + // console.log('TransactionLink.mutationLink... trigger disbursement from recipient-community') try { await disburseMutate({ senderCommunityUuid: linkData.value.senderCommunity.uuid, @@ -384,7 +384,7 @@ async function mutationLink(amount) { await router.push('/overview') } } else { - console.log('TransactionLink.mutationLink... local transaction or contribution') + // console.log('TransactionLink.mutationLink... local transaction or contribution') try { await redeemMutate({ code: redeemCode.value, From 881e78dfd55f8f355336bbd241a9bc05a9a42bf1 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 17:36:27 +0200 Subject: [PATCH 37/48] correct publicKey in DisbursementRequest of EncryptedTransferArgs --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 99668d724..4ddd082d2 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -565,7 +565,7 @@ export class TransactionLinkResolver { methodLogger.debug('jws=', jws) } const args = new EncryptedTransferArgs() - args.publicKey = senderCom.publicKey.toString('hex') + args.publicKey = recipientCom.publicKey.toString('hex') args.jwt = jws args.handshakeID = handshakeID try { From d92b9c81e72f9f40573f2b7c3542fc341a9939bd Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 18:42:30 +0200 Subject: [PATCH 38/48] remove console.log --- frontend/src/pages/TransactionLink.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/TransactionLink.vue b/frontend/src/pages/TransactionLink.vue index 2e81d8913..53a742313 100644 --- a/frontend/src/pages/TransactionLink.vue +++ b/frontend/src/pages/TransactionLink.vue @@ -151,7 +151,7 @@ const itemType = computed(() => { // validUntilDate.getTime() < new Date().getTime(), // ) if (validUntilDate.getTime() < new Date().getTime()) { - console.log('TransactionLink.itemType... TEXT_EXPIRED') + // console.log('TransactionLink.itemType... TEXT_EXPIRED') return 'TEXT_EXPIRED' } if (linkData.value.redeemedAt) { From 29809bf9839f0852e94cae6530f70609bbf39875 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 22:05:36 +0200 Subject: [PATCH 39/48] remove inactive code --- .../graphql/resolver/TransactionResolver.ts | 74 ------------------- 1 file changed, 74 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 2ef7b69ff..c9d68de35 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -467,80 +467,6 @@ export class TransactionResolver { amount.valueOf(), memo, ) - /* - // processing a x-community sendCoins - logger.info('X-Com: processing a x-community transaction...') - if (!CONFIG.FEDERATION_XCOM_SENDCOINS_ENABLED) { - throw new LogError('X-Community sendCoins disabled per configuration!') - } - const recipCom = await getCommunityByIdentifier(recipientCommunityIdentifier) - logger.debug('recipient community: ', recipCom?.id) - if (recipCom === null) { - throw new LogError( - `no recipient community found for identifier: ${recipientCommunityIdentifier}`, - ) - } - if (recipCom !== null && recipCom.authenticatedAt === null) { - throw new LogError('recipient community is connected, but still not authenticated yet!') - } - let pendingResult: SendCoinsResponseJwtPayloadType | null = null - let committingResult: SendCoinsResult - const creationDate = new Date() - - try { - pendingResult = await processXComPendingSendCoins( - recipCom, - homeCom, - creationDate, - amount, - memo, - senderUser, - recipientIdentifier, - ) - logger.debug('processXComPendingSendCoins result: ', pendingResult) - if (pendingResult && pendingResult.vote && pendingResult.recipGradidoID) { - logger.debug('vor processXComCommittingSendCoins... ') - committingResult = await processXComCommittingSendCoins( - recipCom, - homeCom, - creationDate, - amount, - memo, - senderUser, - pendingResult, - ) - logger.debug('processXComCommittingSendCoins result: ', committingResult) - if (!committingResult.vote) { - logger.fatal('FATAL ERROR: on processXComCommittingSendCoins for', committingResult) - throw new LogError( - 'FATAL ERROR: on processXComCommittingSendCoins with ', - recipientCommunityIdentifier, - recipientIdentifier, - amount.toString(), - memo, - ) - } - // after successful x-com-tx store the recipient as foreign user - logger.debug('store recipient as foreign user...') - if (await storeForeignUser(recipCom, committingResult)) { - logger.info( - 'X-Com: new foreign user inserted successfully...', - recipCom.communityUuid, - committingResult.recipGradidoID, - ) - } - } - } catch (err) { - throw new LogError( - 'ERROR: on processXComCommittingSendCoins with ', - recipientCommunityIdentifier, - recipientIdentifier, - amount.toString(), - memo, - err, - ) - } - */ } return true } From 951e92f88a837d0d95c51aece800c644abbf580f Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 3 Sep 2025 22:47:40 +0200 Subject: [PATCH 40/48] increase timeouts --- e2e-tests/cypress.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/cypress.config.ts b/e2e-tests/cypress.config.ts index b182e7f32..254640e81 100644 --- a/e2e-tests/cypress.config.ts +++ b/e2e-tests/cypress.config.ts @@ -35,8 +35,8 @@ export default defineConfig({ excludeSpecPattern: '*.js', baseUrl: 'http://127.0.0.1:3000', chromeWebSecurity: false, - defaultCommandTimeout: 25000, - pageLoadTimeout: 24000, + defaultCommandTimeout: 50000, + pageLoadTimeout: 32000, supportFile: 'cypress/support/index.ts', viewportHeight: 720, viewportWidth: 1280, From 12b2caa73563e6f641b42a04ab66bb0d58093b25 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 16:35:55 +0200 Subject: [PATCH 41/48] removed federation-config properties from backend, because of shift to core-modul --- backend/.env.dist | 2 +- backend/.env.org | 2 +- backend/.env.template | 2 +- backend/src/config/index.ts | 16 ++++++++-------- backend/src/config/schema.ts | 9 +++++---- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/backend/.env.dist b/backend/.env.dist index 8d5ba317c..5794b6130 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -63,7 +63,7 @@ WEBHOOK_ELOPAGE_SECRET=secret # Federation FEDERATION_VALIDATE_COMMUNITY_TIMER=60000 -FEDERATION_XCOM_SENDCOINS_ENABLED=false +# FEDERATION_XCOM_SENDCOINS_ENABLED=false # GMS # GMS_ACTIVE=true diff --git a/backend/.env.org b/backend/.env.org index a0082aab1..2999c5ccc 100644 --- a/backend/.env.org +++ b/backend/.env.org @@ -63,7 +63,7 @@ LOG_LEVEL=INFO # Federation FEDERATION_VALIDATE_COMMUNITY_TIMER=60000 -FEDERATION_XCOM_SENDCOINS_ENABLED=false +# FEDERATION_XCOM_SENDCOINS_ENABLED=false # GMS # GMS_ACTIVE=true diff --git a/backend/.env.template b/backend/.env.template index 6c3867978..ba26f4122 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -63,7 +63,7 @@ WEBHOOK_ELOPAGE_SECRET=$WEBHOOK_ELOPAGE_SECRET # Federation FEDERATION_VALIDATE_COMMUNITY_TIMER=$FEDERATION_VALIDATE_COMMUNITY_TIMER -FEDERATION_XCOM_SENDCOINS_ENABLED=$FEDERATION_XCOM_SENDCOINS_ENABLED +# FEDERATION_XCOM_SENDCOINS_ENABLED=$FEDERATION_XCOM_SENDCOINS_ENABLED # GMS GMS_ACTIVE=$GMS_ACTIVE diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 9d61c2da4..85b82cc27 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -99,19 +99,19 @@ const webhook = { process.env.APP_SECRET = server.JWT_SECRET const federation = { - FEDERATION_BACKEND_SEND_ON_API: process.env.FEDERATION_BACKEND_SEND_ON_API ?? '1_0', +// FEDERATION_BACKEND_SEND_ON_API: process.env.FEDERATION_BACKEND_SEND_ON_API ?? '1_0', // ?? operator don't work here as expected FEDERATION_VALIDATE_COMMUNITY_TIMER: Number( process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER ?? 60000, ), - FEDERATION_XCOM_SENDCOINS_ENABLED: - process.env.FEDERATION_XCOM_SENDCOINS_ENABLED === 'true' || false, +// FEDERATION_XCOM_SENDCOINS_ENABLED: +// process.env.FEDERATION_XCOM_SENDCOINS_ENABLED === 'true' || false, // default value for community-uuid is equal uuid of stage-3 - FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID: - process.env.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID ?? '56a55482-909e-46a4-bfa2-cd025e894ebc', - FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: parseInt( - process.env.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS ?? '3', - ), +// FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID: +// process.env.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID ?? '56a55482-909e-46a4-bfa2-cd025e894ebc', +// FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: parseInt( +// process.env.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS ?? '3', +// ), } const gms = { diff --git a/backend/src/config/schema.ts b/backend/src/config/schema.ts index f305a7488..7baea6c07 100644 --- a/backend/src/config/schema.ts +++ b/backend/src/config/schema.ts @@ -208,20 +208,20 @@ export const schema = Joi.object({ .default(10) .description('Time in minutes before a new code can be requested') .required(), - +/* FEDERATION_BACKEND_SEND_ON_API: Joi.string() .pattern(/^\d+_\d+$/) .default('1_0') .description('API Version of sending requests to another communities, e.g., "1_0"') .required(), - +*/ FEDERATION_VALIDATE_COMMUNITY_TIMER: Joi.number() .integer() .min(1000) .default(60000) .description('Timer interval in milliseconds for community validation') .required(), - +/* FEDERATION_XCOM_SENDCOINS_ENABLED: Joi.boolean() .default(false) .description('Enable or disable the federation send coins feature') @@ -235,12 +235,13 @@ export const schema = Joi.object({ ) .required(), - FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: Joi.number() + FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: Joi.number() .integer() .min(0) .default(3) .description('Maximum number of retries for reverting send coins transactions') .required(), +*/ GMS_CREATE_USER_THROW_ERRORS: Joi.boolean() .default(false) From 1ef2505c030fcf5efcaeb5d888d270219b2da4dd Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 16:41:57 +0200 Subject: [PATCH 42/48] correct config core export and usage --- backend/src/federation/authenticateCommunities.ts | 4 ++-- core/src/index.ts | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/src/federation/authenticateCommunities.ts b/backend/src/federation/authenticateCommunities.ts index 179c7e996..ad2d91469 100644 --- a/backend/src/federation/authenticateCommunities.ts +++ b/backend/src/federation/authenticateCommunities.ts @@ -1,7 +1,7 @@ import { CommunityLoggingView, Community as DbCommunity, FederatedCommunity as DbFederatedCommunity, FederatedCommunityLoggingView, getHomeCommunity } from 'database' import { validate as validateUUID, version as versionUUID } from 'uuid' import { randombytes_random } from 'sodium-native' -import { CONFIG } from '@/config' +import { CONFIG as CONFIG_CORE } from 'core' import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient' import { ensureUrlEndsWithSlash } from 'core' @@ -27,7 +27,7 @@ export async function startCommunityAuthentication( methodLogger.debug('homeComA', new CommunityLoggingView(homeComA!)) const homeFedComA = await DbFederatedCommunity.findOneByOrFail({ foreign: false, - apiVersion: CONFIG.FEDERATION_BACKEND_SEND_ON_API, + apiVersion: CONFIG_CORE.FEDERATION_BACKEND_SEND_ON_API, }) methodLogger.debug('homeFedComA', new FederatedCommunityLoggingView(homeFedComA)) const comB = await DbCommunity.findOneByOrFail({ publicKey: fedComB.publicKey }) diff --git a/core/src/index.ts b/core/src/index.ts index 85042ef0b..a355bb9bd 100644 --- a/core/src/index.ts +++ b/core/src/index.ts @@ -21,3 +21,5 @@ export * from './graphql/model/EncryptedTransferArgs' export * from './util/calculateSenderBalance' export * from './util/utilities' export * from './validation/user' +export * from './config/index' + From 0b973ee2e12cda90a7256d57e562b696939d0a7a Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 16:45:24 +0200 Subject: [PATCH 43/48] remove inactive code --- backend/.env.dist | 1 - backend/.env.org | 1 - backend/.env.template | 1 - backend/src/config/index.ts | 10 ---------- backend/src/config/schema.ts | 31 ++----------------------------- 5 files changed, 2 insertions(+), 42 deletions(-) diff --git a/backend/.env.dist b/backend/.env.dist index 5794b6130..133ba5554 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -63,7 +63,6 @@ WEBHOOK_ELOPAGE_SECRET=secret # Federation FEDERATION_VALIDATE_COMMUNITY_TIMER=60000 -# FEDERATION_XCOM_SENDCOINS_ENABLED=false # GMS # GMS_ACTIVE=true diff --git a/backend/.env.org b/backend/.env.org index 2999c5ccc..2267fdc50 100644 --- a/backend/.env.org +++ b/backend/.env.org @@ -63,7 +63,6 @@ LOG_LEVEL=INFO # Federation FEDERATION_VALIDATE_COMMUNITY_TIMER=60000 -# FEDERATION_XCOM_SENDCOINS_ENABLED=false # GMS # GMS_ACTIVE=true diff --git a/backend/.env.template b/backend/.env.template index ba26f4122..9b0bc7df2 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -63,7 +63,6 @@ WEBHOOK_ELOPAGE_SECRET=$WEBHOOK_ELOPAGE_SECRET # Federation FEDERATION_VALIDATE_COMMUNITY_TIMER=$FEDERATION_VALIDATE_COMMUNITY_TIMER -# FEDERATION_XCOM_SENDCOINS_ENABLED=$FEDERATION_XCOM_SENDCOINS_ENABLED # GMS GMS_ACTIVE=$GMS_ACTIVE diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 85b82cc27..aa0a7dbf2 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -99,19 +99,9 @@ const webhook = { process.env.APP_SECRET = server.JWT_SECRET const federation = { -// FEDERATION_BACKEND_SEND_ON_API: process.env.FEDERATION_BACKEND_SEND_ON_API ?? '1_0', - // ?? operator don't work here as expected FEDERATION_VALIDATE_COMMUNITY_TIMER: Number( process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER ?? 60000, ), -// FEDERATION_XCOM_SENDCOINS_ENABLED: -// process.env.FEDERATION_XCOM_SENDCOINS_ENABLED === 'true' || false, - // default value for community-uuid is equal uuid of stage-3 -// FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID: -// process.env.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID ?? '56a55482-909e-46a4-bfa2-cd025e894ebc', -// FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: parseInt( -// process.env.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS ?? '3', -// ), } const gms = { diff --git a/backend/src/config/schema.ts b/backend/src/config/schema.ts index 7baea6c07..144608992 100644 --- a/backend/src/config/schema.ts +++ b/backend/src/config/schema.ts @@ -208,40 +208,13 @@ export const schema = Joi.object({ .default(10) .description('Time in minutes before a new code can be requested') .required(), -/* - FEDERATION_BACKEND_SEND_ON_API: Joi.string() - .pattern(/^\d+_\d+$/) - .default('1_0') - .description('API Version of sending requests to another communities, e.g., "1_0"') - .required(), -*/ - FEDERATION_VALIDATE_COMMUNITY_TIMER: Joi.number() + + FEDERATION_VALIDATE_COMMUNITY_TIMER: Joi.number() .integer() .min(1000) .default(60000) .description('Timer interval in milliseconds for community validation') .required(), -/* - FEDERATION_XCOM_SENDCOINS_ENABLED: Joi.boolean() - .default(false) - .description('Enable or disable the federation send coins feature') - .optional(), - - FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID: Joi.string() - .uuid() - .default('56a55482-909e-46a4-bfa2-cd025e894ebc') - .description( - 'UUID of the receiver community for federation cross-community transactions if the receiver is unknown', - ) - .required(), - - FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: Joi.number() - .integer() - .min(0) - .default(3) - .description('Maximum number of retries for reverting send coins transactions') - .required(), -*/ GMS_CREATE_USER_THROW_ERRORS: Joi.boolean() .default(false) From 30e7ecd7d9e788028ffbcf3e563bcf99eab28a54 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 16:49:33 +0200 Subject: [PATCH 44/48] remove eslint command-lines --- shared/src/jwt/payloadtypes/EncryptedJWEJwtPayloadType.ts | 2 -- .../jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType.ts | 2 -- shared/src/jwt/payloadtypes/OpenConnectionJwtPayloadType.ts | 2 -- shared/src/jwt/payloadtypes/RedeemJwtPayloadType.ts | 2 -- shared/src/jwt/payloadtypes/SendCoinsJwtPayloadType.ts | 2 -- shared/src/jwt/payloadtypes/SendCoinsResponseJwtPayloadType.ts | 2 -- shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts | 2 -- 7 files changed, 14 deletions(-) diff --git a/shared/src/jwt/payloadtypes/EncryptedJWEJwtPayloadType.ts b/shared/src/jwt/payloadtypes/EncryptedJWEJwtPayloadType.ts index f353d885b..0d6d86476 100644 --- a/shared/src/jwt/payloadtypes/EncryptedJWEJwtPayloadType.ts +++ b/shared/src/jwt/payloadtypes/EncryptedJWEJwtPayloadType.ts @@ -9,9 +9,7 @@ export class EncryptedJWEJwtPayloadType extends JwtPayloadType { handshakeID: string, jwe: string, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call super(handshakeID) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.tokentype = EncryptedJWEJwtPayloadType.ENCRYPTED_JWE_TYPE this.jwe = jwe } diff --git a/shared/src/jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType.ts b/shared/src/jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType.ts index 7b4992284..544e23800 100644 --- a/shared/src/jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType.ts +++ b/shared/src/jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType.ts @@ -11,9 +11,7 @@ export class OpenConnectionCallbackJwtPayloadType extends JwtPayloadType { oneTimeCode: string, url: string, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call super(handshakeID) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.tokentype = OpenConnectionCallbackJwtPayloadType.OPEN_CONNECTION_CALLBACK_TYPE this.oneTimeCode = oneTimeCode this.url = url diff --git a/shared/src/jwt/payloadtypes/OpenConnectionJwtPayloadType.ts b/shared/src/jwt/payloadtypes/OpenConnectionJwtPayloadType.ts index 3a3c249cb..a9e7e0a5a 100644 --- a/shared/src/jwt/payloadtypes/OpenConnectionJwtPayloadType.ts +++ b/shared/src/jwt/payloadtypes/OpenConnectionJwtPayloadType.ts @@ -9,9 +9,7 @@ export class OpenConnectionJwtPayloadType extends JwtPayloadType { handshakeID: string, url: string, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call super(handshakeID) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.tokentype = OpenConnectionJwtPayloadType.OPEN_CONNECTION_TYPE this.url = url } diff --git a/shared/src/jwt/payloadtypes/RedeemJwtPayloadType.ts b/shared/src/jwt/payloadtypes/RedeemJwtPayloadType.ts index faeda2b71..841f725e1 100644 --- a/shared/src/jwt/payloadtypes/RedeemJwtPayloadType.ts +++ b/shared/src/jwt/payloadtypes/RedeemJwtPayloadType.ts @@ -20,9 +20,7 @@ export class RedeemJwtPayloadType extends JwtPayloadType { memo: string, validUntil: string, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call super('handshakeID') - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.tokentype = RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE this.sendercommunityuuid = senderCom this.sendergradidoid = senderUser diff --git a/shared/src/jwt/payloadtypes/SendCoinsJwtPayloadType.ts b/shared/src/jwt/payloadtypes/SendCoinsJwtPayloadType.ts index 6048eb254..833b004fc 100644 --- a/shared/src/jwt/payloadtypes/SendCoinsJwtPayloadType.ts +++ b/shared/src/jwt/payloadtypes/SendCoinsJwtPayloadType.ts @@ -26,9 +26,7 @@ export class SendCoinsJwtPayloadType extends JwtPayloadType { senderUserName: string, senderAlias?: string | null, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call super(handshakeID) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.tokentype = SendCoinsJwtPayloadType.SEND_COINS_TYPE this.recipientCommunityUuid = recipientCommunityUuid this.recipientUserIdentifier = recipientUserIdentifier diff --git a/shared/src/jwt/payloadtypes/SendCoinsResponseJwtPayloadType.ts b/shared/src/jwt/payloadtypes/SendCoinsResponseJwtPayloadType.ts index e76cf00eb..fb08d6a97 100644 --- a/shared/src/jwt/payloadtypes/SendCoinsResponseJwtPayloadType.ts +++ b/shared/src/jwt/payloadtypes/SendCoinsResponseJwtPayloadType.ts @@ -17,9 +17,7 @@ export class SendCoinsResponseJwtPayloadType extends JwtPayloadType { recipLastName: string | null, recipAlias: string | null, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call super(handshakeID) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.tokentype = SendCoinsResponseJwtPayloadType.SEND_COINS_RESPONSE_TYPE this.vote = vote this.recipGradidoID = recipGradidoID diff --git a/shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts b/shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts index 26c4235f3..1b3f3a468 100644 --- a/shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts +++ b/shared/src/jwt/payloadtypes/SignedTransferPayloadType.ts @@ -11,9 +11,7 @@ export class SignedTransferPayloadType extends JwtPayloadType { jwt: string, handshakeID: string, ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call super(handshakeID) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.tokentype = SignedTransferPayloadType.SIGNED_TRANSFER_TYPE this.publicKey = publicKey this.jwt = jwt From abbfed963e203c1b6c0ce14d42be3a2bcbd205d7 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 17:09:00 +0200 Subject: [PATCH 45/48] camelcase the parameter names of processXComCompleteTransaction --- .../src/graphql/logic/processXComSendCoins.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/core/src/graphql/logic/processXComSendCoins.ts b/core/src/graphql/logic/processXComSendCoins.ts index dc8e3127f..5b3d6584a 100644 --- a/core/src/graphql/logic/processXComSendCoins.ts +++ b/core/src/graphql/logic/processXComSendCoins.ts @@ -35,15 +35,15 @@ import { storeForeignUser } from './storeForeignUser' const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.${method}`) export async function processXComCompleteTransaction( - sendercommunityuuid: string, - sendergradidoid: string, - recipientcommunityuuid: string, - recipientgradidoid: string, + senderCommunityUuid: string, + senderGradidoId: string, + recipientCommunityUuid: string, + recipientGradidoId: string, amount: string, memo: string, code?: string, - recipientfirstname?: string, - recipientalias?: string, + recipientFirstName?: string, + recipientAlias?: string, creationDate?: Date, ): Promise { const methodLogger = createLogger(`processXComCompleteTransaction`) @@ -54,23 +54,23 @@ export async function processXComCompleteTransaction( methodLogger.error(errmsg) throw new Error(errmsg) } - const senderCom = await getCommunityByUuid(sendercommunityuuid) + const senderCom = await getCommunityByUuid(senderCommunityUuid) methodLogger.debug('sender community: ', senderCom?.id) if (senderCom === null) { - const errmsg = `no sender community found for identifier: ${sendercommunityuuid}` + const errmsg = `no sender community found for identifier: ${senderCommunityUuid}` methodLogger.error(errmsg) throw new Error(errmsg) } - const senderUser = await findUserByIdentifier(sendergradidoid, sendercommunityuuid) + const senderUser = await findUserByIdentifier(senderGradidoId, senderCommunityUuid) if (senderUser === null) { - const errmsg = `no sender user found for identifier: ${sendercommunityuuid}:${sendergradidoid}` + const errmsg = `no sender user found for identifier: ${senderCommunityUuid}:${senderGradidoId}` methodLogger.error(errmsg) throw new Error(errmsg) } - const recipientCom = await getCommunityByUuid(recipientcommunityuuid) + const recipientCom = await getCommunityByUuid(recipientCommunityUuid) methodLogger.debug('recipient community: ', recipientCom?.id) if (recipientCom === null) { - const errmsg = `no recipient community found for identifier: ${recipientcommunityuuid}` + const errmsg = `no recipient community found for identifier: ${recipientCommunityUuid}` methodLogger.error(errmsg) throw new Error(errmsg) } @@ -107,7 +107,7 @@ export async function processXComCompleteTransaction( new Decimal(amount), memo, senderUser, - recipientgradidoid, + recipientGradidoId, ) methodLogger.debug('processXComPendingSendCoins result: ', pendingResult) if (pendingResult && pendingResult.vote && pendingResult.recipGradidoID) { @@ -127,7 +127,7 @@ export async function processXComCompleteTransaction( throw new Error( 'FATAL ERROR: on processXComCommittingSendCoins with ' + recipientCom.communityUuid + - recipientgradidoid + + recipientGradidoId + amount.toString() + memo, ) @@ -144,8 +144,8 @@ export async function processXComCompleteTransaction( } } catch (err) { const errmsg = `ERROR: on processXComCommittingSendCoins with ` + - recipientcommunityuuid + - recipientgradidoid + + recipientCommunityUuid + + recipientGradidoId + amount.toString() + memo + err From 42007418b1d08ce1dfc97ec026e231bcb20a3aa4 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 17:57:21 +0200 Subject: [PATCH 46/48] use getCommunityByUuid --- backend/src/graphql/resolver/TransactionLinkResolver.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 4ddd082d2..8acbd7b53 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -523,7 +523,7 @@ export class TransactionLinkResolver { recipientAlias, }) } - const senderCom = await DbCommunity.findOneBy({ communityUuid: senderCommunityUuid }) + const senderCom = await getCommunityByUuid(senderCommunityUuid) if (!senderCom) { const errmsg = `Sender community not found with uuid=${senderCommunityUuid}` methodLogger.error(errmsg) @@ -535,7 +535,7 @@ export class TransactionLinkResolver { methodLogger.error(errmsg) throw new LogError(errmsg) } - const recipientCom = await DbCommunity.findOneBy({ communityUuid: recipientCommunityUuid }) + const recipientCom = await getCommunityByUuid(recipientCommunityUuid) if (!recipientCom) { const errmsg = `Recipient community not found with uuid=${recipientCommunityUuid}` methodLogger.error(errmsg) From b96cbd064caf8dfd436ee7025345d92f0c7e314b Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 18:02:45 +0200 Subject: [PATCH 47/48] removed unused configs --- core/tsconfig.json | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/core/tsconfig.json b/core/tsconfig.json index c30aab30d..b8e0f1d0a 100644 --- a/core/tsconfig.json +++ b/core/tsconfig.json @@ -44,15 +44,8 @@ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - "baseUrl": ".", /* Base directory to resolve non-absolute module names. */ - "paths": { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - "@/*": ["src/*"], - "@config/*": ["src/config/*"], - "@federation/*": ["src/federation/*"], - "@graphql/*": ["src/graphql/*"], - "@util/*": ["src/util/*"], - "@validation/*": ["src/validation/*"] - }, + // "baseUrl": ".", /* Base directory to resolve non-absolute module names. */ + // "paths": { }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": ["bun-types"], /* Type declaration files to be included in compilation. */ From 2f43f37a420968abe3ebafa3da6e3895d4b8a1de Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 5 Sep 2025 18:31:12 +0200 Subject: [PATCH 48/48] reinserted the porperty FEDERATION_XCOM_SENDCOINS_ENABLED --- backend/.env.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/.env.dist b/backend/.env.dist index 133ba5554..8d5ba317c 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -63,6 +63,7 @@ WEBHOOK_ELOPAGE_SECRET=secret # Federation FEDERATION_VALIDATE_COMMUNITY_TIMER=60000 +FEDERATION_XCOM_SENDCOINS_ENABLED=false # GMS # GMS_ACTIVE=true