/* import { Community as DbCommunity } from '@entity/Community' import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' import { PendingTransaction as DbPendingTransaction } from '@entity/PendingTransaction' import { User as dbUser } from '@entity/User' import { Decimal } from 'decimal.js-light' import { CONFIG } from '@/config' import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs' // eslint-disable-next-line camelcase import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient' import { SendCoinsClientFactory } from '@/federation/client/SendCoinsClientFactory' import { PendingTransactionState } from '@/graphql/enum/PendingTransactionState' import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId' import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' import { calculateSenderBalance } from '@/util/calculateSenderBalance' import { fullName } from '@/util/utilities' import { settlePendingSenderTransaction } from './settlePendingSenderTransaction' export async function processXComPendingSendCoins( receiverFCom: DbFederatedCommunity, receiverCom: DbCommunity, senderCom: DbCommunity, creationDate: Date, amount: Decimal, memo: string, sender: dbUser, recipient: dbUser, ): Promise { try { logger.debug( `XCom: processXComPendingSendCoins...`, receiverFCom, receiverCom, senderCom, creationDate, amount, memo, sender, recipient, ) // first calculate the sender balance and check if the transaction is allowed const senderBalance = await calculateSenderBalance(sender.id, amount.mul(-1), creationDate) if (!senderBalance) { throw new LogError('User has not enough GDD or amount is < 0', senderBalance) } logger.debug(`X-Com: calculated senderBalance = `, senderBalance) const client = SendCoinsClientFactory.getInstance(receiverFCom) // eslint-disable-next-line camelcase if (client instanceof V1_0_SendCoinsClient) { const args = new SendCoinsArgs() args.recipientCommunityUuid = receiverCom.communityUuid ? receiverCom.communityUuid : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID args.recipientUserIdentifier = recipient.gradidoID args.creationDate = creationDate.toISOString() args.amount = amount args.memo = memo args.senderCommunityUuid = senderCom.communityUuid ? senderCom.communityUuid : 'homeCom-UUID' args.senderUserUuid = sender.gradidoID args.senderUserName = fullName(sender.firstName, sender.lastName) logger.debug(`X-Com: ready for voteForSendCoins with args=`, args) const sendCoinsResult = await client.voteForSendCoins(args) logger.debug(`X-Com: returnd from voteForSendCoins:`, sendCoinsResult) if (sendCoinsResult) { // 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 ? senderBalance.balance : new Decimal(0) pendingTx.balanceDate = creationDate pendingTx.decay = senderBalance ? senderBalance.decay.decay : new Decimal(0) pendingTx.decayStart = senderBalance ? senderBalance.decay.start : null pendingTx.linkedUserCommunityUuid = receiverCom.communityUuid ? receiverCom.communityUuid : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID pendingTx.linkedUserGradidoID = recipient.gradidoID pendingTx.linkedUserName = sendCoinsResult.recipName 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.userGradidoID = sender.gradidoID pendingTx.userName = fullName(sender.firstName, sender.lastName) logger.debug(`X-Com: initialized sender pendingTX=`, pendingTx) await DbPendingTransaction.insert(pendingTx) logger.debug(`X-Com: sender pendingTx successfully inserted...`) } catch (err) { logger.error(`Error in writing sender pending transaction: `, err) // revert the existing pending transaction on receiver side let revertCount = 0 logger.debug(`X-Com: first try to revertSendCoins of receiver`) do { if (await client.revertSendCoins(args)) { logger.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, ) } logger.debug(`voteForSendCoins()-1_0... successfull`) } } } catch (err) { logger.error(`Error:`, err) } return true } export async function processXComCommittingSendCoins( receiverFCom: DbFederatedCommunity, receiverCom: DbCommunity, senderCom: DbCommunity, creationDate: Date, amount: Decimal, memo: string, sender: dbUser, recipient: dbUser, ): Promise { try { logger.debug( `XCom: processXComCommittingSendCoins...`, receiverFCom, receiverCom, senderCom, creationDate, amount, memo, sender, recipient, ) // first find pending Tx with given parameters const pendingTx = await DbPendingTransaction.findOneBy({ userCommunityUuid: senderCom.communityUuid ? senderCom.communityUuid : 'homeCom-UUID', userGradidoID: sender.gradidoID, userName: fullName(sender.firstName, sender.lastName), linkedUserCommunityUuid: receiverCom.communityUuid ? receiverCom.communityUuid : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID, linkedUserGradidoID: recipient.gradidoID, typeId: TransactionTypeId.SEND, state: PendingTransactionState.NEW, balanceDate: creationDate, memo, }) if (pendingTx) { logger.debug(`X-Com: find pending Tx for settlement:`, pendingTx) const client = SendCoinsClientFactory.getInstance(receiverFCom) // eslint-disable-next-line camelcase if (client instanceof V1_0_SendCoinsClient) { const args = new SendCoinsArgs() args.recipientCommunityUuid = pendingTx.linkedUserCommunityUuid ? pendingTx.linkedUserCommunityUuid : CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID if (pendingTx.linkedUserGradidoID) { args.recipientUserIdentifier = pendingTx.linkedUserGradidoID } args.creationDate = pendingTx.balanceDate.toISOString() args.amount = pendingTx.amount args.memo = pendingTx.memo args.senderCommunityUuid = pendingTx.userCommunityUuid args.senderUserUuid = pendingTx.userGradidoID if (pendingTx.userName) { args.senderUserName = pendingTx.userName } logger.debug(`X-Com: ready for settleSendCoins with args=`, args) const acknowledge = await client.settleSendCoins(args) logger.debug(`X-Com: returnd from settleSendCoins:`, acknowledge) if (acknowledge) { // settle the pending transaction on receiver-side was successfull, so now settle the sender side try { await settlePendingSenderTransaction(senderCom, sender, pendingTx) } catch (err) { logger.error(`Error in writing sender pending transaction: `, err) // revert the existing pending transaction on receiver side let revertCount = 0 logger.debug(`X-Com: first try to revertSetteledSendCoins of receiver`) do { if (await client.revertSettledSendCoins(args)) { logger.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') } } while (CONFIG.FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS > revertCount++) throw new LogError( `Error in reverting receiver pending transaction even after revertCount=`, revertCount, ) } } } } } catch (err) { logger.error(`Error:`, err) } return true } */