From 31d47d753743c52f4d362204f9d65dd99fb29e1c Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 21 Sep 2023 18:45:53 +0200 Subject: [PATCH] next try for x-com sendCoins --- backend/log4js-config.json | 1 + .../federation/client/1_0/SendCoinsClient.ts | 57 ++++++++++++------- .../client/1_0/model/SendCoinsResult.ts | 4 +- .../client/1_0/query/revertSendCoins.ts | 7 ++- .../1_0/query/revertSettledSendCoins.ts | 8 ++- .../client/1_0/query/settleSendCoins.ts | 7 ++- .../graphql/resolver/TransactionResolver.ts | 6 +- .../src/graphql/resolver/util/communities.ts | 34 ++++++----- .../resolver/util/processXComSendCoins.ts | 25 +++++--- .../graphql/api/1_0/model/SendCoinsResult.ts | 4 +- .../api/1_0/resolver/SendCoinsResolver.ts | 54 ++++++------------ 11 files changed, 119 insertions(+), 88 deletions(-) diff --git a/backend/log4js-config.json b/backend/log4js-config.json index 1cbd4519c..90111a5ba 100644 --- a/backend/log4js-config.json +++ b/backend/log4js-config.json @@ -121,6 +121,7 @@ { "appenders": [ + "out", "backend", "errors" ], diff --git a/backend/src/federation/client/1_0/SendCoinsClient.ts b/backend/src/federation/client/1_0/SendCoinsClient.ts index 359393cda..e8bd5c578 100644 --- a/backend/src/federation/client/1_0/SendCoinsClient.ts +++ b/backend/src/federation/client/1_0/SendCoinsClient.ts @@ -34,21 +34,14 @@ export class SendCoinsClient { voteForSendCoins = async (args: SendCoinsArgs): Promise => { logger.debug('X-Com: voteForSendCoins against endpoint=', this.endpoint) try { - logger.debug(`SendCoinsClient: voteForSendCoins with args=`, args) + logger.debug(`X-Com: SendCoinsClient: voteForSendCoins with args=`, args) // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { data } = await this.client.rawRequest(voteForSendCoins, { args }) - logger.debug(`SendCoinsClient: after rawRequest...`, data) - const sendCoinsResult = data as SendCoinsResult + logger.debug(`X-Com: SendCoinsClient: after rawRequest...data:`, data) // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (!sendCoinsResult.vote) { - logger.warn( - 'X-Com: voteForSendCoins failed with: ', - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - sendCoinsResult.recipGradidoID, - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - sendCoinsResult.recipName, - ) - return sendCoinsResult + if (!data?.voteForSendCoins?.vote) { + logger.warn('X-Com: voteForSendCoins failed with: ', data) + return new SendCoinsResult() } const result = new SendCoinsResult() result.vote = true @@ -66,17 +59,24 @@ export class SendCoinsClient { revertSendCoins = async (args: SendCoinsArgs): Promise => { logger.debug('X-Com: revertSendCoins against endpoint=', this.endpoint) try { + logger.debug(`X-Com: SendCoinsClient: revertSendCoins with args=`, args) // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { data } = await this.client.rawRequest(revertSendCoins, { args }) + logger.debug(`X-Com: SendCoinsClient: after revertSendCoins: data=`, data) // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!data?.revertSendCoins?.revertSendCoins) { logger.warn('X-Com: revertSendCoins without response data from endpoint', this.endpoint) return false } - logger.debug(`X-Com: revertSendCoins successful from endpoint=${this.endpoint}`) + logger.debug( + `X-Com: SendCoinsClient: revertSendCoins successful from endpoint=${this.endpoint}`, + ) return true } catch (err) { - logger.error(`X-Com: revertSendCoins failed for endpoint=${this.endpoint}`, err) + logger.error( + `X-Com: SendCoinsClient: revertSendCoins failed for endpoint=${this.endpoint}`, + err, + ) return false } } @@ -84,37 +84,54 @@ export class SendCoinsClient { settleSendCoins = async (args: SendCoinsArgs): Promise => { logger.debug(`X-Com: settleSendCoins against endpoint='${this.endpoint}'...`) try { + logger.debug(`X-Com: SendCoinsClient: settleSendCoins with args=`, args) // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { data } = await this.client.rawRequest(settleSendCoins, { args }) + logger.debug(`X-Com: SendCoinsClient: after settleSendCoins: data=`, data) // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!data?.settleSendCoins?.acknowledged) { - logger.warn('X-Com: settleSendCoins without response data from endpoint', this.endpoint) + logger.warn( + 'X-Com: SendCoinsClient: settleSendCoins without response data from endpoint', + this.endpoint, + ) return false } - logger.debug(`X-Com: settleSendCoins successful from endpoint=${this.endpoint}`) + logger.debug( + `X-Com: SendCoinsClient: settleSendCoins successful from endpoint=${this.endpoint}`, + ) return true } catch (err) { - throw new LogError(`X-Com: settleSendCoins failed for endpoint=${this.endpoint}`, err) + throw new LogError( + `X-Com: SendCoinsClient: settleSendCoins failed for endpoint=${this.endpoint}`, + err, + ) } } revertSettledSendCoins = async (args: SendCoinsArgs): Promise => { logger.debug(`X-Com: revertSettledSendCoins against endpoint='${this.endpoint}'...`) try { + logger.debug(`X-Com: SendCoinsClient: revertSettledSendCoins with args=`, args) // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { data } = await this.client.rawRequest(revertSettledSendCoins, { args }) + logger.debug(`X-Com: SendCoinsClient: after revertSettledSendCoins: data=`, data) // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!data?.revertSettledSendCoins?.acknowledged) { logger.warn( - 'X-Com: revertSettledSendCoins without response data from endpoint', + 'X-Com: SendCoinsClient: revertSettledSendCoins without response data from endpoint', this.endpoint, ) return false } - logger.debug(`X-Com: revertSettledSendCoins successful from endpoint=${this.endpoint}`) + logger.debug( + `X-Com: SendCoinsClient: revertSettledSendCoins successful from endpoint=${this.endpoint}`, + ) return true } catch (err) { - throw new LogError(`X-Com: revertSettledSendCoins failed for endpoint=${this.endpoint}`, err) + throw new LogError( + `X-Com: SendCoinsClient: revertSettledSendCoins failed for endpoint=${this.endpoint}`, + err, + ) } } } diff --git a/backend/src/federation/client/1_0/model/SendCoinsResult.ts b/backend/src/federation/client/1_0/model/SendCoinsResult.ts index 1258db4cb..930d22ff5 100644 --- a/backend/src/federation/client/1_0/model/SendCoinsResult.ts +++ b/backend/src/federation/client/1_0/model/SendCoinsResult.ts @@ -10,8 +10,8 @@ export class SendCoinsResult { vote: boolean @Field(() => String, { nullable: true }) - recipGradidoID: string | null | undefined + recipGradidoID: string | null @Field(() => String, { nullable: true }) - recipName: string | null | undefined + recipName: string | null } diff --git a/backend/src/federation/client/1_0/query/revertSendCoins.ts b/backend/src/federation/client/1_0/query/revertSendCoins.ts index 9cc23fe64..ea7d28f77 100644 --- a/backend/src/federation/client/1_0/query/revertSendCoins.ts +++ b/backend/src/federation/client/1_0/query/revertSendCoins.ts @@ -1,6 +1,11 @@ import { gql } from 'graphql-request' export const revertSendCoins = gql` + mutation ($args: SendCoinsArgs!) { + revertSendCoins(data: $args) + } +` +/* mutation ( $recipientCommunityUuid: String! $recipientUserIdentifier: String! @@ -22,4 +27,4 @@ export const revertSendCoins = gql` senderUserName: $senderUserName ) } -` +*/ diff --git a/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts b/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts index 74cdbd867..3965df396 100644 --- a/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts +++ b/backend/src/federation/client/1_0/query/revertSettledSendCoins.ts @@ -1,6 +1,12 @@ import { gql } from 'graphql-request' export const revertSettledSendCoins = gql` + mutation ($args: SendCoinsArgs!) { + revertSettledSendCoins(data: $args) + } +` +/* + mutation ( $recipientCommunityUuid: String! $recipientUserIdentifier: String! @@ -22,4 +28,4 @@ export const revertSettledSendCoins = gql` senderUserName: $senderUserName ) } -` +*/ diff --git a/backend/src/federation/client/1_0/query/settleSendCoins.ts b/backend/src/federation/client/1_0/query/settleSendCoins.ts index 1696a0900..206a6544c 100644 --- a/backend/src/federation/client/1_0/query/settleSendCoins.ts +++ b/backend/src/federation/client/1_0/query/settleSendCoins.ts @@ -1,6 +1,11 @@ import { gql } from 'graphql-request' export const settleSendCoins = gql` + mutation ($args: SendCoinsArgs!) { + settleSendCoins(data: $args) + } +` +/* mutation ( $recipientCommunityUuid: String! $recipientUserIdentifier: String! @@ -22,4 +27,4 @@ export const settleSendCoins = gql` senderUserName: $senderUserName ) } -` +*/ \ No newline at end of file diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index e7c2f751c..0c35ed401 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -74,7 +74,9 @@ export const executeTransaction = async ( ], }) if (openSenderPendingTx > 0 || openReceiverPendingTx > 0) { - throw new LogError('There are still pending Transactions for Sender and/or Recipient') + throw new LogError( + `There exist still ongoing 'Pending-Transactions' for the involved users on sender-side!`, + ) } if (sender.id === recipient.id) { @@ -529,7 +531,7 @@ export class TransactionResolver { logger.info('successful executeTransaction', amount, memo, senderUser, recipientUser) } else { // processing a x-community sendCoins - logger.debug('processing a x-community transaction...') + logger.debug('X-Com: processing a x-community transaction...') if (!CONFIG.FEDERATION_XCOM_SENDCOINS_ENABLED) { throw new LogError('X-Community sendCoins disabled per configuration!') } diff --git a/backend/src/graphql/resolver/util/communities.ts b/backend/src/graphql/resolver/util/communities.ts index 59e79f077..f55816229 100644 --- a/backend/src/graphql/resolver/util/communities.ts +++ b/backend/src/graphql/resolver/util/communities.ts @@ -1,14 +1,14 @@ import { Community as DbCommunity } from '@entity/Community' export async function isHomeCommunity(communityIdentifier: string): Promise { - const homeCommunity = await DbCommunity.findOneByOrFail({ foreign: false }) - if (communityIdentifier === homeCommunity.id.toString()) { - return true - } else if (communityIdentifier === homeCommunity.name) { - return true - } else if (communityIdentifier === homeCommunity.communityUuid) { - return true - } else if (communityIdentifier === homeCommunity.url) { + const homeCommunity = await DbCommunity.findOne({ + where: [ + { foreign: false, communityUuid: communityIdentifier }, + { foreign: false, name: communityIdentifier }, + { foreign: false, url: communityIdentifier }, + ], + }) + if (homeCommunity) { return true } else { return false @@ -16,11 +16,6 @@ export async function isHomeCommunity(communityIdentifier: string): Promise { - const community = await DbCommunity.findOneByOrFail({ name: communityIdentifier }) - return community.url -} - -export async function isCommunityAuthenticated(communityIdentifier: string): Promise { const community = await DbCommunity.findOneOrFail({ where: [ { communityUuid: communityIdentifier }, @@ -28,7 +23,18 @@ export async function isCommunityAuthenticated(communityIdentifier: string): Pro { url: communityIdentifier }, ], }) - if (community.authenticatedAt) { + return community.url +} + +export async function isCommunityAuthenticated(communityIdentifier: string): Promise { + const community = await DbCommunity.findOne({ + where: [ + { communityUuid: communityIdentifier }, + { name: communityIdentifier }, + { url: communityIdentifier }, + ], + }) + if (community?.authenticatedAt) { return true } else { return false diff --git a/backend/src/graphql/resolver/util/processXComSendCoins.ts b/backend/src/graphql/resolver/util/processXComSendCoins.ts index 5f1349b70..1cd443cd4 100644 --- a/backend/src/graphql/resolver/util/processXComSendCoins.ts +++ b/backend/src/graphql/resolver/util/processXComSendCoins.ts @@ -28,7 +28,7 @@ export async function processXComPendingSendCoins( sender: dbUser, recipientIdentifier: string, ): Promise { - let sendCoinsResult = new SendCoinsResult() + let voteResult: SendCoinsResult try { logger.debug( `XCom: processXComPendingSendCoins...`, @@ -69,9 +69,10 @@ export async function processXComPendingSendCoins( args.senderUserUuid = sender.gradidoID args.senderUserName = fullName(sender.firstName, sender.lastName) logger.debug(`X-Com: ready for voteForSendCoins with args=`, args) - sendCoinsResult = await client.voteForSendCoins(args) - logger.debug(`X-Com: returnd from voteForSendCoins:`, sendCoinsResult) - if (sendCoinsResult.vote) { + voteResult = await client.voteForSendCoins(args) + logger.debug(`X-Com: returnd from voteForSendCoins:`, voteResult) + if (voteResult.vote) { + logger.debug(`X-Com: prepare pendingTransaction for sender...`) // writing the pending transaction on receiver-side was successfull, so now write the sender side try { const pendingTx = DbPendingTransaction.create() @@ -83,17 +84,18 @@ export async function processXComPendingSendCoins( if (receiverCom.communityUuid) { pendingTx.linkedUserCommunityUuid = receiverCom.communityUuid } - if (sendCoinsResult.recipGradidoID) { - pendingTx.linkedUserGradidoID = sendCoinsResult.recipGradidoID + if (voteResult.recipGradidoID) { + pendingTx.linkedUserGradidoID = voteResult.recipGradidoID } - if (sendCoinsResult.recipName) { - pendingTx.linkedUserName = sendCoinsResult.recipName + if (voteResult.recipName) { + pendingTx.linkedUserName = voteResult.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.id = sender.id pendingTx.userGradidoID = sender.gradidoID pendingTx.userName = fullName(sender.firstName, sender.lastName) logger.debug(`X-Com: initialized sender pendingTX=`, pendingTx) @@ -118,12 +120,17 @@ export async function processXComPendingSendCoins( ) } logger.debug(`voteForSendCoins()-1_0... successfull`) + } else { + logger.debug( + `X-Com: break with error on writing pendingTransaction for recipient...`, + voteResult, + ) } } } catch (err) { throw new LogError(`Error:`, err) } - return sendCoinsResult + return new SendCoinsResult() } export async function processXComCommittingSendCoins( diff --git a/federation/src/graphql/api/1_0/model/SendCoinsResult.ts b/federation/src/graphql/api/1_0/model/SendCoinsResult.ts index 749ca87cb..930d22ff5 100644 --- a/federation/src/graphql/api/1_0/model/SendCoinsResult.ts +++ b/federation/src/graphql/api/1_0/model/SendCoinsResult.ts @@ -9,9 +9,9 @@ export class SendCoinsResult { @Field(() => Boolean) vote: boolean - @Field(() => String) + @Field(() => String, { nullable: true }) recipGradidoID: string | null - @Field(() => String) + @Field(() => String, { nullable: true }) recipName: string | null } diff --git a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts index 4a31b0bbb..caa60c0d1 100644 --- a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts @@ -57,6 +57,24 @@ export class SendCoinsResolver { homeCom.name, ) } + const openSenderPendingTx = await DbPendingTransaction.count({ + where: [ + { userGradidoID: args.senderUserUuid, state: PendingTransactionState.NEW }, + { linkedUserGradidoID: args.senderUserUuid, state: PendingTransactionState.NEW }, + ], + }) + const openReceiverPendingTx = await DbPendingTransaction.count({ + where: [ + { userGradidoID: receiverUser.gradidoID, state: PendingTransactionState.NEW }, + { linkedUserGradidoID: receiverUser.gradidoID, state: PendingTransactionState.NEW }, + ], + }) + if (openSenderPendingTx > 0 || openReceiverPendingTx > 0) { + throw new LogError( + `There exist still ongoing 'Pending-Transactions' for the involved users on receiver-side!`, + ) + } + try { const txDate = new Date(args.creationDate) const receiveBalance = await calculateRecipientBalance(receiverUser.id, args.amount, txDate) @@ -94,18 +112,6 @@ export class SendCoinsResolver { async revertSendCoins( @Arg('data') args: SendCoinsArgs, - /* - { - recipientCommunityUuid, - recipientUserIdentifier, - creationDate, - amount, - memo, - senderCommunityUuid, - senderUserUuid, - senderUserName, - }: SendCoinsArgs, - */ ): Promise { logger.debug(`revertSendCoins() via apiVersion=1_0 ...`) // first check if receiver community is correct @@ -179,18 +185,6 @@ export class SendCoinsResolver { async settleSendCoins( @Arg('data') args: SendCoinsArgs, - /* - { - recipientCommunityUuid, - recipientUserIdentifier, - creationDate, - amount, - memo, - senderCommunityUuid, - senderUserUuid, - senderUserName, - }: SendCoinsArgs, - */ ): Promise { logger.debug( `settleSendCoins() via apiVersion=1_0 ...userCommunityUuid=${ @@ -264,18 +258,6 @@ export class SendCoinsResolver { async revertSettledSendCoins( @Arg('data') args: SendCoinsArgs, - /* - { - recipientCommunityUuid, - recipientUserIdentifier, - creationDate, - amount, - memo, - senderCommunityUuid, - senderUserUuid, - senderUserName, - }: SendCoinsArgs, - */ ): Promise { logger.debug(`revertSettledSendCoins() via apiVersion=1_0 ...`) // first check if receiver community is correct