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