From acbcf5e27b75b57e9bd00e8d662fc206f997e863 Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Mon, 21 Jul 2025 17:03:16 +0200 Subject: [PATCH] save current work --- .../federation/client/1_0/SendCoinsClient.ts | 11 +- .../client/1_0/query/revertSendCoins.ts | 2 +- .../1_0/query/revertSettledSendCoins.ts | 2 +- .../client/1_0/query/settleSendCoins.ts | 2 +- .../client/1_0/query/voteForSendCoins.ts | 2 +- .../resolver/util/processXComSendCoins.ts | 146 +++++++++--------- 6 files changed, 83 insertions(+), 82 deletions(-) diff --git a/backend/src/federation/client/1_0/SendCoinsClient.ts b/backend/src/federation/client/1_0/SendCoinsClient.ts index cdd1f464e..dcbc21012 100644 --- a/backend/src/federation/client/1_0/SendCoinsClient.ts +++ b/backend/src/federation/client/1_0/SendCoinsClient.ts @@ -6,8 +6,6 @@ import { ensureUrlEndsWithSlash } from '@/util/utilities' import { getLogger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { SendCoinsArgsLoggingView } from './logging/SendCoinsArgsLogging.view' -import { SendCoinsArgs } from './model/SendCoinsArgs' import { revertSendCoins as revertSendCoinsQuery } from './query/revertSendCoins' import { revertSettledSendCoins as revertSettledSendCoinsQuery } from './query/revertSettledSendCoins' import { settleSendCoins as settleSendCoinsQuery } from './query/settleSendCoins' @@ -50,10 +48,9 @@ export class SendCoinsClient { return null } - async revertSendCoins(args: SendCoinsArgs): Promise { + async revertSendCoins(args: EncryptedTransferArgs): Promise { logger.debug('revertSendCoins against endpoint=', this.endpoint) try { - logger.debug(`revertSendCoins with args=`, new SendCoinsArgsLoggingView(args)) const { data } = await this.client.rawRequest<{ revertSendCoins: boolean }>( revertSendCoinsQuery, { args }, @@ -71,10 +68,9 @@ export class SendCoinsClient { } } - async settleSendCoins(args: SendCoinsArgs): Promise { + async settleSendCoins(args: EncryptedTransferArgs): Promise { logger.debug(`settleSendCoins against endpoint='${this.endpoint}'...`) try { - logger.debug(`settleSendCoins with args=`, new SendCoinsArgsLoggingView(args)) const { data } = await this.client.rawRequest<{ settleSendCoins: boolean }>( settleSendCoinsQuery, { args }, @@ -91,10 +87,9 @@ export class SendCoinsClient { } } - async revertSettledSendCoins(args: SendCoinsArgs): Promise { + async revertSettledSendCoins(args: EncryptedTransferArgs): Promise { logger.debug(`revertSettledSendCoins against endpoint='${this.endpoint}'...`) try { - logger.debug(`revertSettledSendCoins with args=`, new SendCoinsArgsLoggingView(args)) const { data } = await this.client.rawRequest<{ revertSettledSendCoins: boolean }>( revertSettledSendCoinsQuery, { args }, diff --git a/backend/src/federation/client/1_0/query/revertSendCoins.ts b/backend/src/federation/client/1_0/query/revertSendCoins.ts index ea7d28f77..62209a11a 100644 --- a/backend/src/federation/client/1_0/query/revertSendCoins.ts +++ b/backend/src/federation/client/1_0/query/revertSendCoins.ts @@ -1,7 +1,7 @@ import { gql } from 'graphql-request' export const revertSendCoins = gql` - mutation ($args: SendCoinsArgs!) { + mutation ($args: EncryptedTransferArgs!) { revertSendCoins(data: $args) } ` diff --git a/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts b/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts index 3965df396..89c6712d3 100644 --- a/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts +++ b/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts @@ -1,7 +1,7 @@ import { gql } from 'graphql-request' export const revertSettledSendCoins = gql` - mutation ($args: SendCoinsArgs!) { + mutation ($args: EncryptedTransferArgs!) { revertSettledSendCoins(data: $args) } ` diff --git a/backend/src/federation/client/1_0/query/settleSendCoins.ts b/backend/src/federation/client/1_0/query/settleSendCoins.ts index f5143b27d..a8d2ea349 100644 --- a/backend/src/federation/client/1_0/query/settleSendCoins.ts +++ b/backend/src/federation/client/1_0/query/settleSendCoins.ts @@ -1,7 +1,7 @@ import { gql } from 'graphql-request' export const settleSendCoins = gql` - mutation ($args: SendCoinsArgs!) { + mutation ($args: EncryptedTransferArgs!) { settleSendCoins(data: $args) } ` diff --git a/backend/src/federation/client/1_0/query/voteForSendCoins.ts b/backend/src/federation/client/1_0/query/voteForSendCoins.ts index d2550eb1a..45c87bfda 100644 --- a/backend/src/federation/client/1_0/query/voteForSendCoins.ts +++ b/backend/src/federation/client/1_0/query/voteForSendCoins.ts @@ -1,7 +1,7 @@ import { gql } from 'graphql-request' export const voteForSendCoins = gql` - mutation ($args: SendCoinsArgs!) { + mutation ($args: EncryptedTransferArgs!) { voteForSendCoins(data: $args) { vote recipGradidoID diff --git a/backend/src/graphql/resolver/util/processXComSendCoins.ts b/backend/src/graphql/resolver/util/processXComSendCoins.ts index 859ab963a..fa50d3353 100644 --- a/backend/src/graphql/resolver/util/processXComSendCoins.ts +++ b/backend/src/graphql/resolver/util/processXComSendCoins.ts @@ -16,7 +16,7 @@ import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0 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 } from 'shared' +import { encryptAndSign, PendingTransactionState, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared' import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' import { LogError } from '@/server/LogError' @@ -41,7 +41,7 @@ export async function processXComPendingSendCoins( sender: dbUser, recipientIdentifier: string, ): Promise { - let voteResult: SendCoinsResult + let voteResult: SendCoinsResponseJwtPayloadType try { const methodLogger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.processXComPendingSendCoins`) // even if debug is not enabled, attributes are processed so we skip the entire call for performance reasons @@ -105,77 +105,83 @@ export async function processXComPendingSendCoins( args.handshakeID = handshakeID methodLogger.debug('before client.voteForSendCoins() args:', args) - voteResult = await client.voteForSendCoins(args) - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`returned from voteForSendCoins: ${new SendCoinsResultLoggingView(voteResult)}`) - } - if (voteResult.vote) { - methodLogger.debug('prepare pendingTransaction for sender...') - args.senderAlias = sender.alias - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`ready for voteForSendCoins with args=${new SendCoinsArgsLoggingView(args)}`) - } - voteResult = await client.voteForSendCoins(args) - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`returned from voteForSendCoins: ${new SendCoinsResultLoggingView(voteResult)}`) - } - if (voteResult.vote) { - methodLogger.debug('prepare pendingTransaction for sender...') - // writing the pending transaction on receiver-side was successfull, so now write the sender side - try { - const pendingTx = DbPendingTransaction.create() - pendingTx.amount = amount.mul(-1) - pendingTx.balance = senderBalance.balance - pendingTx.balanceDate = creationDate - pendingTx.decay = senderBalance ? senderBalance.decay.decay : new Decimal(0) - pendingTx.decayStart = senderBalance ? senderBalance.decay.start : null - if (receiverCom.communityUuid) { - pendingTx.linkedUserCommunityUuid = receiverCom.communityUuid - } - if (voteResult.recipGradidoID) { - pendingTx.linkedUserGradidoID = voteResult.recipGradidoID - } - if (voteResult.recipFirstName && voteResult.recipLastName) { - pendingTx.linkedUserName = fullName(voteResult.recipFirstName, voteResult.recipLastName) - } - pendingTx.memo = memo - pendingTx.previous = senderBalance ? senderBalance.lastTransactionId : null - pendingTx.state = PendingTransactionState.NEW - pendingTx.typeId = TransactionTypeId.SEND - if (senderCom.communityUuid) { - pendingTx.userCommunityUuid = senderCom.communityUuid - } - pendingTx.userId = sender.id - pendingTx.userGradidoID = sender.gradidoID - pendingTx.userName = fullName(sender.firstName, sender.lastName) - if(methodLogger.isDebugEnabled()) { - methodLogger.debug(`initialized sender pendingTX=${new PendingTransactionLoggingView(pendingTx)}`) - } - - await DbPendingTransaction.insert(pendingTx) - methodLogger.debug('sender pendingTx successfully inserted...') - } catch (err) { - 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 revertSendCoins of receiver') - do { - if (await client.revertSendCoins(args)) { - methodLogger.debug(`revertSendCoins()-1_0... successfull after revertCount=${revertCount}`) - // treat revertingSendCoins as an error of the whole sendCoins-process - throw new LogError('Error in writing sender pending transaction: ', err) - } - } while (CONFIG.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS > revertCount++) - throw new LogError( - `Error in reverting receiver pending transaction even after revertCount=${revertCount}`, - err, - ) + const responseJwt = await client.voteForSendCoins(args) + methodLogger.debug(`response of voteForSendCoins():`, responseJwt) + if (responseJwt !== null) { + voteResult = await verifyAndDecrypt(handshakeID, responseJwt, senderCom.privateJwtKey!, receiverCom.publicJwtKey!) as SendCoinsResponseJwtPayloadType + methodLogger.debug(`received payload from voteForSendCoins():`, voteResult) + if (voteResult.tokentype !== SendCoinsResponseJwtPayloadType.SEND_COINS_RESPONSE_TYPE) { + const errmsg = `Invalid tokentype in voteForSendCoins-response of community with publicKey` + receiverCom.publicKey + methodLogger.error(errmsg) + methodLogger.removeContext('handshakeID') + throw new Error('Error in X-Com-TX protocol...') } - methodLogger.debug('voteForSendCoins()-1_0... successfull') + if (voteResult.vote) { + methodLogger.debug('prepare pendingTransaction for sender...') + // writing the pending transaction on receiver-side was successfull, so now write the sender side + try { + const pendingTx = DbPendingTransaction.create() + pendingTx.amount = amount.mul(-1) + pendingTx.balance = senderBalance.balance + pendingTx.balanceDate = creationDate + pendingTx.decay = senderBalance ? senderBalance.decay.decay : new Decimal(0) + pendingTx.decayStart = senderBalance ? senderBalance.decay.start : null + if (receiverCom.communityUuid) { + pendingTx.linkedUserCommunityUuid = receiverCom.communityUuid + } + if (voteResult.recipGradidoID) { + pendingTx.linkedUserGradidoID = voteResult.recipGradidoID + } + if (voteResult.recipFirstName && voteResult.recipLastName) { + pendingTx.linkedUserName = fullName(voteResult.recipFirstName, voteResult.recipLastName) + } + pendingTx.memo = memo + pendingTx.previous = senderBalance ? senderBalance.lastTransactionId : null + pendingTx.state = PendingTransactionState.NEW + pendingTx.typeId = TransactionTypeId.SEND + if (senderCom.communityUuid) { + pendingTx.userCommunityUuid = senderCom.communityUuid + } + pendingTx.userId = sender.id + pendingTx.userGradidoID = sender.gradidoID + pendingTx.userName = fullName(sender.firstName, sender.lastName) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`initialized sender pendingTX=${new PendingTransactionLoggingView(pendingTx)}`) + } + + await DbPendingTransaction.insert(pendingTx) + methodLogger.debug('sender pendingTx successfully inserted...') + } catch (err) { + 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 revertSendCoins of receiver') + do { + if (await client.revertSendCoins(args)) { + methodLogger.debug(`revertSendCoins()-1_0... successfull after revertCount=${revertCount}`) + // treat revertingSendCoins as an error of the whole sendCoins-process + throw new LogError('Error in writing sender pending transaction: ', err) + } + } while (CONFIG.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS > revertCount++) + throw new LogError( + `Error in reverting receiver pending transaction even after revertCount=${revertCount}`, + err, + ) + } + methodLogger.debug('voteForSendCoins()-1_0... successfull') + } else { + methodLogger.error(`break with error on writing pendingTransaction for recipient... ${voteResult}`) + } + const result = new SendCoinsResult() + result.vote = voteResult.vote + result.recipGradidoID = voteResult.recipGradidoID + result.recipFirstName = voteResult.recipFirstName + result.recipLastName = voteResult.recipLastName + result.recipAlias = voteResult.recipAlias + return result } else { - methodLogger.error(`break with error on writing pendingTransaction for recipient... ${new SendCoinsResultLoggingView(voteResult)}`) + methodLogger.error(`break with no response from voteForSendCoins()-1_0...`) } - return voteResult } } catch (err: any) { throw new LogError(`Error: ${err.message}`, err)