From 69ed4658f24add8e4e49b8b3fc30d89c22968b5b Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Wed, 23 Jul 2025 02:17:37 +0200 Subject: [PATCH] first codings finished --- .../resolver/util/processXComSendCoins.ts | 60 ++++--- .../api/1_0/resolver/SendCoinsResolver.ts | 161 ++++++++++-------- 2 files changed, 129 insertions(+), 92 deletions(-) diff --git a/backend/src/graphql/resolver/util/processXComSendCoins.ts b/backend/src/graphql/resolver/util/processXComSendCoins.ts index 2b153e180..91eb61a1e 100644 --- a/backend/src/graphql/resolver/util/processXComSendCoins.ts +++ b/backend/src/graphql/resolver/util/processXComSendCoins.ts @@ -204,10 +204,13 @@ export async function processXComCommittingSendCoins( sender: dbUser, recipient: SendCoinsResult, ): Promise { + const methodLogger = createLogger(`processXComCommittingSendCoins`) + const handshakeID = randombytes_random().toString() + methodLogger.addContext('handshakeID', handshakeID) const sendCoinsResult = new SendCoinsResult() try { - if(logger.isDebugEnabled()) { - logger.debug( + if(methodLogger.isDebugEnabled()) { + methodLogger.debug( 'XCom: processXComCommittingSendCoins...', { receiverCom: new CommunityLoggingView(receiverCom), senderCom: new CommunityLoggingView(senderCom), @@ -233,40 +236,49 @@ export async function processXComCommittingSendCoins( memo, }) if (pendingTx) { - if(logger.isDebugEnabled()) { - logger.debug(`find pending Tx for settlement: ${new PendingTransactionLoggingView(pendingTx)}`) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`find pending Tx for settlement: ${new PendingTransactionLoggingView(pendingTx)}`) } 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 args = new SendCoinsArgs() - args.recipientCommunityUuid = pendingTx.linkedUserCommunityUuid + const payload = new SendCoinsJwtPayloadType( + handshakeID, + pendingTx.linkedUserCommunityUuid + ? pendingTx.linkedUserCommunityUuid + : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID, + pendingTx.linkedUserGradidoID!, + pendingTx.balanceDate.toISOString(), + pendingTx.amount.mul(-1), + pendingTx.memo, + pendingTx.userCommunityUuid, + pendingTx.userGradidoID!, + pendingTx.userName!, + sender.alias, + ) + payload.recipientCommunityUuid = pendingTx.linkedUserCommunityUuid ? pendingTx.linkedUserCommunityUuid : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID if (pendingTx.linkedUserGradidoID) { - args.recipientUserIdentifier = pendingTx.linkedUserGradidoID + payload.recipientUserIdentifier = pendingTx.linkedUserGradidoID } - args.creationDate = pendingTx.balanceDate.toISOString() - args.amount = pendingTx.amount.mul(-1) - args.memo = pendingTx.memo - args.senderCommunityUuid = pendingTx.userCommunityUuid - args.senderUserUuid = pendingTx.userGradidoID - if (pendingTx.userName) { - args.senderUserName = pendingTx.userName - } - args.senderAlias = sender.alias - if(logger.isDebugEnabled()) { - logger.debug(`ready for settleSendCoins with args=${new SendCoinsArgsLoggingView(args)}`) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`ready for settleSendCoins with payload=${ JSON.stringify(payload)}`) } + const jws = await encryptAndSign(payload, senderCom.privateJwtKey!, receiverCom.publicJwtKey!) + // prepare the args for the client invocation + const args = new EncryptedTransferArgs() + args.publicKey = senderCom.publicKey.toString('hex') + args.jwt = jws + args.handshakeID = handshakeID const acknowledge = await client.settleSendCoins(args) - logger.debug(`returnd from settleSendCoins: ${acknowledge}`) + methodLogger.debug(`return from settleSendCoins: ${acknowledge}`) if (acknowledge) { // settle the pending transaction on receiver-side was successfull, so now settle the sender side try { @@ -290,13 +302,13 @@ export async function processXComCommittingSendCoins( sendCoinsResult.recipAlias = recipient.recipAlias } } catch (err) { - logger.error(`Error in writing sender pending transaction: ${JSON.stringify(err, null, 2)}`) + methodLogger.error(`Error in writing sender pending transaction: ${JSON.stringify(err, null, 2)}`) // revert the existing pending transaction on receiver side let revertCount = 0 - logger.debug('first try to revertSetteledSendCoins of receiver') + methodLogger.debug('first try to revertSetteledSendCoins of receiver') do { if (await client.revertSettledSendCoins(args)) { - logger.debug( + methodLogger.debug( `revertSettledSendCoins()-1_0... successfull after revertCount=${revertCount}`, ) // treat revertingSettledSendCoins as an error of the whole sendCoins-process @@ -312,7 +324,7 @@ export async function processXComCommittingSendCoins( } } } catch (err) { - logger.error(`Error: ${JSON.stringify(err, null, 2)}`) + methodLogger.error(`Error: ${JSON.stringify(err, null, 2)}`) sendCoinsResult.vote = false } return sendCoinsResult diff --git a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts index bb04808a7..8f918610b 100644 --- a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts @@ -10,7 +10,7 @@ import Decimal from 'decimal.js-light' import { getLogger } from 'log4js' import { Arg, Mutation, Resolver } from 'type-graphql' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { encryptAndSign, PendingTransactionState } from 'shared' +import { encryptAndSign, PendingTransactionState, verifyAndDecrypt } from 'shared' import { TransactionTypeId } from '../enum/TransactionTypeId' import { SendCoinsArgsLoggingView } from '../logger/SendCoinsArgsLogging.view' import { SendCoinsArgs } from '../model/SendCoinsArgs' @@ -213,135 +213,160 @@ export class SendCoinsResolver { @Mutation(() => Boolean) async settleSendCoins( @Arg('data') - args: SendCoinsArgs, + args: EncryptedTransferArgs, ): Promise { - logger.debug(`settleSendCoins() via apiVersion=1_0 ...`, new SendCoinsArgsLoggingView(args)) + const methodLogger = createLogger(`settleSendCoins`) + methodLogger.addContext('handshakeID', args.handshakeID) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`settleSendCoins() via apiVersion=1_0 ...`, args) + } + const authArgs = await interpretEncryptedTransferArgs(args) as SendCoinsJwtPayloadType + if (!authArgs) { + const errmsg = `invalid settleSendCoins payload of requesting community with publicKey` + args.publicKey + methodLogger.error(errmsg) + throw new Error(errmsg) + } + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`settleSendCoins() via apiVersion=1_0 ...`, authArgs) + } // first check if receiver community is correct const homeCom = await DbCommunity.findOneBy({ - communityUuid: args.recipientCommunityUuid, + communityUuid: authArgs.recipientCommunityUuid, }) if (!homeCom) { - throw new LogError( - `settleSendCoins with wrong recipientCommunityUuid`, - args.recipientCommunityUuid, - ) + const errmsg = `settleSendCoins with wrong recipientCommunityUuid` + authArgs.recipientCommunityUuid + methodLogger.error(errmsg) + throw new Error(errmsg) } // second check if receiver user exists in this community - const receiverUser = await findUserByIdentifier(args.recipientUserIdentifier) + const receiverUser = await findUserByIdentifier(authArgs.recipientUserIdentifier) if (!receiverUser) { - logger.error('Error in findUserByIdentifier') - throw new LogError( - `settleSendCoins with unknown recipientUserIdentifier in the community=`, - homeCom.name, - ) + const errmsg = `settleSendCoins with unknown recipientUserIdentifier in the community=` + homeCom.name + methodLogger.error(errmsg) + throw new Error(errmsg) } const pendingTx = await DbPendingTransaction.findOneBy({ - userCommunityUuid: args.recipientCommunityUuid, + userCommunityUuid: authArgs.recipientCommunityUuid, userGradidoID: receiverUser.gradidoID, state: PendingTransactionState.NEW, typeId: TransactionTypeId.RECEIVE, - balanceDate: new Date(args.creationDate), - linkedUserCommunityUuid: args.senderCommunityUuid, - linkedUserGradidoID: args.senderUserUuid, + balanceDate: new Date(authArgs.creationDate), + linkedUserCommunityUuid: authArgs.senderCommunityUuid, + linkedUserGradidoID: authArgs.senderUserUuid, }) - logger.debug( - 'XCom: settleSendCoins found pendingTX=', - pendingTx ? new PendingTransactionLoggingView(pendingTx) : 'null', - ) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug( + 'XCom: settleSendCoins found pendingTX=', + pendingTx ? new PendingTransactionLoggingView(pendingTx) : 'null', + ) + } if ( pendingTx && - pendingTx.amount.toString() === args.amount.toString() && - pendingTx.memo === args.memo + pendingTx.amount.toString() === authArgs.amount.toString() && + pendingTx.memo === authArgs.memo ) { - logger.debug('XCom: settleSendCoins matching pendingTX for settlement...') + methodLogger.debug('XCom: settleSendCoins matching pendingTX for settlement...') await settlePendingReceiveTransaction(homeCom, receiverUser, pendingTx) // after successful x-com-tx store the recipient as foreign user - logger.debug('store recipient as foreign user...') - if (await storeForeignUser(args)) { - logger.info( + methodLogger.debug('store recipient as foreign user...') + if (await storeForeignUser(authArgs)) { + methodLogger.info( 'X-Com: new foreign user inserted successfully...', - args.senderCommunityUuid, - args.senderUserUuid, + authArgs.senderCommunityUuid, + authArgs.senderUserUuid, ) } - logger.debug(`XCom: settlePendingReceiveTransaction()-1_0... successful`) + methodLogger.debug(`XCom: settlePendingReceiveTransaction()-1_0... successful`) return true } else { - logger.debug('XCom: settlePendingReceiveTransaction NOT matching pendingTX for settlement...') - throw new LogError( - `Can't find in settlePendingReceiveTransaction the pending receiver TX for `, - { - args: new SendCoinsArgsLoggingView(args), - pendingTransactionState: PendingTransactionState.NEW, + methodLogger.debug('XCom: settlePendingReceiveTransaction NOT matching pendingTX for settlement...') + const errmsg = `Can't find in settlePendingReceiveTransaction the pending receiver TX for ` + { + args: new SendCoinsArgsLoggingView(authArgs), + pendingTransactionState: PendingTransactionState.NEW, transactionTypeId: TransactionTypeId.RECEIVE, - }, - ) + } + methodLogger.error(errmsg) + throw new Error(errmsg) } } @Mutation(() => Boolean) async revertSettledSendCoins( @Arg('data') - args: SendCoinsArgs, + args: EncryptedTransferArgs, ): Promise { - logger.debug(`revertSettledSendCoins() via apiVersion=1_0 ...`) + const methodLogger = createLogger(`revertSettledSendCoins`) + methodLogger.addContext('handshakeID', args.handshakeID) + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`revertSettledSendCoins() via apiVersion=1_0 ...`) + } + const authArgs = await interpretEncryptedTransferArgs(args) as SendCoinsJwtPayloadType + if (!authArgs) { + const errmsg = `invalid revertSettledSendCoins payload of requesting community with publicKey` + args.publicKey + methodLogger.error(errmsg) + throw new Error(errmsg) + } + if(methodLogger.isDebugEnabled()) { + methodLogger.debug(`revertSettledSendCoins() via apiVersion=1_0 ...`, authArgs) + } // first check if receiver community is correct const homeCom = await DbCommunity.findOneBy({ - communityUuid: args.recipientCommunityUuid, + communityUuid: authArgs.recipientCommunityUuid, }) if (!homeCom) { - throw new LogError( - `revertSettledSendCoins with wrong recipientCommunityUuid`, - args.recipientCommunityUuid, - ) + const errmsg = `revertSettledSendCoins with wrong recipientCommunityUuid` + authArgs.recipientCommunityUuid + methodLogger.error(errmsg) + throw new Error(errmsg) } // second check if receiver user exists in this community - const receiverUser = await findUserByIdentifier(args.recipientUserIdentifier) + const receiverUser = await findUserByIdentifier(authArgs.recipientUserIdentifier) if (!receiverUser) { - logger.error('Error in findUserByIdentifier') - throw new LogError( - `revertSettledSendCoins with unknown recipientUserIdentifier in the community=`, - homeCom.name, - ) + const errmsg = `revertSettledSendCoins with unknown recipientUserIdentifier in the community=` + homeCom.name + methodLogger.error(errmsg) + throw new Error(errmsg) } const pendingTx = await DbPendingTransaction.findOneBy({ - userCommunityUuid: args.recipientCommunityUuid, - userGradidoID: args.recipientUserIdentifier, + userCommunityUuid: authArgs.recipientCommunityUuid, + userGradidoID: authArgs.recipientUserIdentifier, state: PendingTransactionState.SETTLED, typeId: TransactionTypeId.RECEIVE, - balanceDate: new Date(args.creationDate), - linkedUserCommunityUuid: args.senderCommunityUuid, - linkedUserGradidoID: args.senderUserUuid, + balanceDate: new Date(authArgs.creationDate), + linkedUserCommunityUuid: authArgs.senderCommunityUuid, + linkedUserGradidoID: authArgs.senderUserUuid, }) - logger.debug( + methodLogger.debug( 'XCom: revertSettledSendCoins found pendingTX=', pendingTx ? new PendingTransactionLoggingView(pendingTx) : 'null', ) if ( pendingTx && - pendingTx.amount.toString() === args.amount.toString() && - pendingTx.memo === args.memo + pendingTx.amount.toString() === authArgs.amount.toString() && + pendingTx.memo === authArgs.memo ) { - logger.debug('XCom: revertSettledSendCoins matching pendingTX for remove...') + methodLogger.debug('XCom: revertSettledSendCoins matching pendingTX for remove...') try { await revertSettledReceiveTransaction(homeCom, receiverUser, pendingTx) - logger.debug('XCom: revertSettledSendCoins pendingTX successfully') + methodLogger.debug('XCom: revertSettledSendCoins pendingTX successfully') } catch (err) { - throw new LogError('Error in revertSettledSendCoins of receiver: ', err) + const errmsg = `Error in revertSettledSendCoins of receiver: ` + err + methodLogger.error(errmsg) + throw new Error(errmsg) } } else { - logger.debug('XCom: revertSettledSendCoins NOT matching pendingTX...') - throw new LogError(`Can't find in revertSettledSendCoins the pending receiver TX for `, { - args: new SendCoinsArgsLoggingView(args), + methodLogger.debug('XCom: revertSettledSendCoins NOT matching pendingTX...') + const errmsg = `Can't find in revertSettledSendCoins the pending receiver TX for ` + { + args: new SendCoinsArgsLoggingView(authArgs), pendingTransactionState: PendingTransactionState.SETTLED, transactionTypeId: TransactionTypeId.RECEIVE, - }) + } + methodLogger.error(errmsg) + throw new Error(errmsg) } - logger.debug(`revertSendCoins()-1_0... successfull`) + methodLogger.debug(`revertSettledSendCoins()-1_0... successfull`) return true } }