mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 01:46:07 +00:00
first draft of write senderPendingTX
This commit is contained in:
parent
7d8b97b861
commit
48af8a7a90
@ -19,7 +19,7 @@ const constants = {
|
||||
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
|
||||
CONFIG_VERSION: {
|
||||
DEFAULT: 'DEFAULT',
|
||||
EXPECTED: 'v18.2023-07-10',
|
||||
EXPECTED: 'v19.2023-08-25',
|
||||
CURRENT: '',
|
||||
},
|
||||
}
|
||||
@ -124,6 +124,9 @@ if (
|
||||
const federation = {
|
||||
FEDERATION_VALIDATE_COMMUNITY_TIMER:
|
||||
Number(process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER) || 60000,
|
||||
// default value for community-uuid is equal uuid of stage-3
|
||||
FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID:
|
||||
process.env.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID ?? '56a55482-909e-46a4-bfa2-cd025e894ebc',
|
||||
}
|
||||
|
||||
export const CONFIG = {
|
||||
|
||||
@ -6,6 +6,7 @@ import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
import { SendCoinsArgs } from './model/SendCoinsArgs'
|
||||
import { voteForSendCoins } from './query/voteForSendCoins'
|
||||
import { SendCoinsResult } from './model/SendCoinsResult'
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export class SendCoinsClient {
|
||||
@ -27,23 +28,25 @@ export class SendCoinsClient {
|
||||
})
|
||||
}
|
||||
|
||||
voteForSendCoins = async (args: SendCoinsArgs): Promise<boolean> => {
|
||||
voteForSendCoins = async (args: SendCoinsArgs): Promise<SendCoinsResult | null> => {
|
||||
logger.debug('X-Com: voteForSendCoins against endpoint', this.endpoint)
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { data } = await this.client.rawRequest(voteForSendCoins, { args })
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
if (!data?.voteForSendCoins) {
|
||||
logger.warn('X-Com: voteForSendCoins without response data from endpoint', this.endpoint)
|
||||
return false
|
||||
if (!data?.voteForSendCoins?.SendCoinsResult.vote) {
|
||||
logger.warn(
|
||||
'X-Com: voteForSendCoins failed with: ',
|
||||
data?.voteForSendCoins?.SendCoinsResult,
|
||||
)
|
||||
return null
|
||||
}
|
||||
logger.debug(
|
||||
'X-Com: voteForSendCoins successful from endpoint',
|
||||
this.endpoint,
|
||||
'X-Com: voteForSendCoins successful with result=',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
data.voteForSendCoins.vote,
|
||||
data.voteForSendCoins.SendCoinsResult,
|
||||
)
|
||||
return true
|
||||
return data.voteForSendCoins.SendCoinsResult
|
||||
} catch (err) {
|
||||
throw new LogError(`X-Com: voteForSendCoins failed for endpoint=${this.endpoint}:`, err)
|
||||
}
|
||||
|
||||
17
backend/src/federation/client/1_0/model/SendCoinsResult.ts
Normal file
17
backend/src/federation/client/1_0/model/SendCoinsResult.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { ArgsType, Field } from 'type-graphql'
|
||||
|
||||
@ArgsType()
|
||||
export class SendCoinsResult {
|
||||
constructor() {
|
||||
this.vote = false
|
||||
}
|
||||
|
||||
@Field(() => Boolean)
|
||||
vote: boolean
|
||||
|
||||
@Field(() => String)
|
||||
receiverFirstName: string
|
||||
|
||||
@Field(() => String)
|
||||
receiverLastName: string
|
||||
}
|
||||
80
backend/src/graphql/resolver/util/processXComSendCoins.ts
Normal file
80
backend/src/graphql/resolver/util/processXComSendCoins.ts
Normal file
@ -0,0 +1,80 @@
|
||||
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 { 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 { backendLogger as logger } from '@/server/logger'
|
||||
import { CONFIG } from '@/config'
|
||||
import { fullName } from '@/util/utilities'
|
||||
import { calculateSenderBalance } from '@/util/calculateSenderBalance'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
|
||||
export async function processXComSendCoins(
|
||||
receiverFCom: DbFederatedCommunity,
|
||||
senderFCom: DbFederatedCommunity,
|
||||
receiverCom: DbCommunity,
|
||||
senderCom: DbCommunity,
|
||||
creationDate: Date,
|
||||
amount: Decimal,
|
||||
memo: string,
|
||||
sender: dbUser,
|
||||
recipient: dbUser,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
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)
|
||||
}
|
||||
|
||||
const client = SendCoinsClientFactory.getInstance(receiverFCom)
|
||||
// eslint-disable-next-line camelcase
|
||||
if (client instanceof V1_0_SendCoinsClient) {
|
||||
const args = new SendCoinsArgs()
|
||||
args.communityReceiverIdentifier = receiverCom.communityUuid
|
||||
? receiverCom.communityUuid
|
||||
: CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID
|
||||
args.userReceiverIdentifier = recipient.gradidoID
|
||||
args.creationDate = creationDate
|
||||
args.amount = amount
|
||||
args.memo = memo
|
||||
args.communitySenderIdentifier = senderCom.communityUuid
|
||||
? senderCom.communityUuid
|
||||
: 'homeCom-UUID'
|
||||
args.userSenderIdentifier = sender.gradidoID
|
||||
args.userSenderName = fullName(sender.firstName, sender.lastName)
|
||||
const result = await client.voteForSendCoins(args)
|
||||
if(result) {
|
||||
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 = userSenderName
|
||||
pendingTx.memo = memo
|
||||
pendingTx.previous = receiveBalance ? receiveBalance.lastTransactionId : null
|
||||
pendingTx.state = PendingTransactionState.NEW
|
||||
pendingTx.typeId = TransactionTypeId.RECEIVE
|
||||
pendingTx.userCommunityUuid = communityReceiverIdentifier
|
||||
pendingTx.userGradidoID = userReceiverIdentifier
|
||||
pendingTx.userName = fullName(receiverUser.firstName, receiverUser.lastName)
|
||||
|
||||
await DbPendingTransaction.insert(pendingTx)
|
||||
logger.debug(`voteForSendCoins()-1_0... successfull`)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(`Error:`, err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
21
backend/src/util/calculateSenderBalance.ts
Normal file
21
backend/src/util/calculateSenderBalance.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Decay } from '@model/Decay'
|
||||
|
||||
import { getLastTransaction } from '@/graphql/resolver/util/getLastTransaction'
|
||||
|
||||
import { calculateDecay } from './decay'
|
||||
|
||||
export async function calculateSenderBalance(
|
||||
userId: number,
|
||||
amount: Decimal,
|
||||
time: Date,
|
||||
): Promise<{ balance: Decimal; decay: Decay; lastTransactionId: number } | null> {
|
||||
const lastTransaction = await getLastTransaction(userId)
|
||||
if (!lastTransaction) return null
|
||||
|
||||
const decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, time)
|
||||
|
||||
const balance = decay.balance.add(amount.toString())
|
||||
return { balance, lastTransactionId: lastTransaction.id, decay }
|
||||
}
|
||||
17
federation/src/graphql/api/1_0/model/SendCoinsResult.ts
Normal file
17
federation/src/graphql/api/1_0/model/SendCoinsResult.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { ArgsType, Field } from 'type-graphql'
|
||||
|
||||
@ArgsType()
|
||||
export class SendCoinsResult {
|
||||
constructor() {
|
||||
this.vote = false
|
||||
}
|
||||
|
||||
@Field(() => Boolean)
|
||||
vote: boolean
|
||||
|
||||
@Field(() => String)
|
||||
receiverFirstName: string
|
||||
|
||||
@Field(() => String)
|
||||
receiverLastName: string
|
||||
}
|
||||
@ -11,6 +11,7 @@ import { TransactionTypeId } from '../enum/TransactionTypeId'
|
||||
import { calculateRecepientBalance } from '@/graphql/util/calculateRecepientBalance'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { fullName } from '@/graphql/util/fullName'
|
||||
import { SendCoinsResult } from '../model/SendCoinsResult'
|
||||
|
||||
@Resolver()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@ -28,7 +29,8 @@ export class SendCoinsResolver {
|
||||
userSenderIdentifier,
|
||||
userSenderName,
|
||||
}: SendCoinsArgs,
|
||||
): Promise<boolean> {
|
||||
): Promise<SendCoinsResult> {
|
||||
const result = new SendCoinsResult()
|
||||
logger.debug(`voteForSendCoins() via apiVersion=1_0 ...`)
|
||||
try {
|
||||
// first check if receiver community is correct
|
||||
@ -68,10 +70,13 @@ export class SendCoinsResolver {
|
||||
pendingTx.userName = fullName(receiverUser.firstName, receiverUser.lastName)
|
||||
|
||||
await DbPendingTransaction.insert(pendingTx)
|
||||
result.vote = true
|
||||
result.receiverFirstName = receiverUser.firstName
|
||||
result.receiverLastName = receiverUser.lastName
|
||||
logger.debug(`voteForSendCoins()-1_0... successfull`)
|
||||
} catch (err) {
|
||||
throw new LogError(`Error in voteForSendCoins: `, err)
|
||||
}
|
||||
return true
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user