mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
first draft for settlePendingReceiverTransaction
This commit is contained in:
parent
1016dd071a
commit
6acf2f3c5b
@ -7,6 +7,7 @@ import { backendLogger as logger } from '@/server/logger'
|
||||
import { SendCoinsArgs } from './model/SendCoinsArgs'
|
||||
import { revertSendCoins } from './query/revertSendCoins'
|
||||
import { voteForSendCoins } from './query/voteForSendCoins'
|
||||
import { settleSendCoins } from './query/settleSendCoins'
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export class SendCoinsClient {
|
||||
@ -72,22 +73,20 @@ export class SendCoinsClient {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
commitSendCoins = async (args: SendCoinsArgs): Promise<boolean> => {
|
||||
logger.debug(`X-Com: commitSendCoins against endpoint='${this.endpoint}'...`)
|
||||
settleSendCoins = async (args: SendCoinsArgs): Promise<boolean> => {
|
||||
logger.debug(`X-Com: settleSendCoins against endpoint='${this.endpoint}'...`)
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { data } = await this.client.rawRequest(commitSendCoins, { args })
|
||||
const { data } = await this.client.rawRequest(settleSendCoins, { args })
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
if (!data?.commitSendCoins?.acknowledged) {
|
||||
logger.warn('X-Com: commitSendCoins without response data from endpoint', this.endpoint)
|
||||
logger.warn('X-Com: settleSendCoins without response data from endpoint', this.endpoint)
|
||||
return false
|
||||
}
|
||||
logger.debug(`X-Com: commitSendCoins successful from endpoint=${this.endpoint}`)
|
||||
logger.debug(`X-Com: settleSendCoins successful from endpoint=${this.endpoint}`)
|
||||
return true
|
||||
} catch (err) {
|
||||
throw new LogError(`X-Com: commitSendCoins failed for endpoint=${this.endpoint}`, err)
|
||||
throw new LogError(`X-Com: settleSendCoins failed for endpoint=${this.endpoint}`, err)
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
25
backend/src/federation/client/1_0/query/settleSendCoins.ts
Normal file
25
backend/src/federation/client/1_0/query/settleSendCoins.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { gql } from 'graphql-request'
|
||||
|
||||
export const settleSendCoins = gql`
|
||||
mutation (
|
||||
$communityReceiverIdentifier: String!
|
||||
$userReceiverIdentifier: String!
|
||||
$creationDate: Date!
|
||||
$amount: Decimal!
|
||||
$memo: String!
|
||||
$communitySenderIdentifier: String!
|
||||
$userSenderIdentifier: String!
|
||||
$userSenderName: String!
|
||||
) {
|
||||
settleSendCoins(
|
||||
communityReceiverIdentifier: $communityReceiverIdentifier
|
||||
userReceiverIdentifier: $userReceiverIdentifier
|
||||
creationDate: $creationDate
|
||||
amount: $amount
|
||||
memo: $memo
|
||||
communitySenderIdentifier: $communitySenderIdentifier
|
||||
userSenderIdentifier: $userSenderIdentifier
|
||||
userSenderName: $userSenderName
|
||||
)
|
||||
}
|
||||
`
|
||||
@ -3,6 +3,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import { getConnection, In } from '@dbTools/typeorm'
|
||||
import { PendingTransaction as DbPendingTransaction } from '@entity/PendingTransaction'
|
||||
import { Transaction as dbTransaction } from '@entity/Transaction'
|
||||
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
|
||||
import { User as dbUser } from '@entity/User'
|
||||
@ -12,6 +13,7 @@ import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql'
|
||||
import { Paginated } from '@arg/Paginated'
|
||||
import { TransactionSendArgs } from '@arg/TransactionSendArgs'
|
||||
import { Order } from '@enum/Order'
|
||||
import { PendingTransactionState } from '@enum/PendingTransactionState'
|
||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { Transaction } from '@model/Transaction'
|
||||
import { TransactionList } from '@model/TransactionList'
|
||||
@ -52,6 +54,22 @@ export const executeTransaction = async (
|
||||
try {
|
||||
logger.info('executeTransaction', amount, memo, sender, recipient)
|
||||
|
||||
const openSenderPendingTx = await DbPendingTransaction.count({
|
||||
where: [
|
||||
{ userGradidoID: sender.gradidoID, state: PendingTransactionState.NEW },
|
||||
{ linkedUserGradidoID: sender.gradidoID, state: PendingTransactionState.NEW },
|
||||
],
|
||||
})
|
||||
const openReceiverPendingTx = await DbPendingTransaction.count({
|
||||
where: [
|
||||
{ userGradidoID: recipient.gradidoID, state: PendingTransactionState.NEW },
|
||||
{ linkedUserGradidoID: recipient.gradidoID, state: PendingTransactionState.NEW },
|
||||
],
|
||||
})
|
||||
if (openSenderPendingTx > 0 || openReceiverPendingTx > 0) {
|
||||
throw new LogError('There are still pending Transactions for Sender and/or Recipient')
|
||||
}
|
||||
|
||||
if (sender.id === recipient.id) {
|
||||
throw new LogError('Sender and Recipient are the same', sender.id)
|
||||
}
|
||||
|
||||
@ -114,3 +114,70 @@ export async function processXComPendingSendCoins(
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export async function processXComCommittingSendCoins(
|
||||
receiverFCom: DbFederatedCommunity,
|
||||
receiverCom: DbCommunity,
|
||||
senderCom: DbCommunity,
|
||||
creationDate: Date,
|
||||
amount: Decimal,
|
||||
memo: string,
|
||||
sender: dbUser,
|
||||
recipient: dbUser,
|
||||
): Promise<boolean> {
|
||||
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.communityReceiverIdentifier = pendingTx.linkedUserCommunityUuid
|
||||
? pendingTx.linkedUserCommunityUuid
|
||||
: CONFIG.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID
|
||||
if (pendingTx.linkedUserGradidoID) {
|
||||
args.userReceiverIdentifier = pendingTx.linkedUserGradidoID
|
||||
}
|
||||
args.creationDate = pendingTx.balanceDate
|
||||
args.amount = pendingTx.amount
|
||||
args.memo = pendingTx.memo
|
||||
args.communitySenderIdentifier = pendingTx.userCommunityUuid
|
||||
args.userSenderIdentifier = pendingTx.userGradidoID
|
||||
if (pendingTx.userName) {
|
||||
args.userSenderName = pendingTx.userName
|
||||
}
|
||||
logger.debug(`X-Com: ready for settleSendCoins with args=`, args)
|
||||
const acknoleged = await client.settleSendCoins(args)
|
||||
logger.debug(`X-Com: returnd from settleSendCoins:`, acknoleged)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(`Error:`, err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
12
federation/src/graphql/api/1_0/const/const.ts
Normal file
12
federation/src/graphql/api/1_0/const/const.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
export const MAX_CREATION_AMOUNT = new Decimal(1000)
|
||||
export const FULL_CREATION_AVAILABLE = [
|
||||
MAX_CREATION_AMOUNT,
|
||||
MAX_CREATION_AMOUNT,
|
||||
MAX_CREATION_AMOUNT,
|
||||
]
|
||||
export const CONTRIBUTIONLINK_NAME_MAX_CHARS = 100
|
||||
export const CONTRIBUTIONLINK_NAME_MIN_CHARS = 5
|
||||
export const MEMO_MAX_CHARS = 255
|
||||
export const MEMO_MIN_CHARS = 5
|
||||
@ -8,9 +8,11 @@ import { User as DbUser } from '@entity/User'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { PendingTransactionState } from '../enum/PendingTransactionState'
|
||||
import { TransactionTypeId } from '../enum/TransactionTypeId'
|
||||
import { calculateRecepientBalance } from '@/graphql/util/calculateRecepientBalance'
|
||||
import { calculateRecepientBalance } from '../util/calculateRecepientBalance'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { fullName } from '@/graphql/util/fullName'
|
||||
import { settlePendingReceiveTransaction } from '../util/settlePendingReceiveTransaction'
|
||||
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from '../const/const'
|
||||
|
||||
@Resolver()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@ -50,6 +52,14 @@ export class SendCoinsResolver {
|
||||
homeCom.name,
|
||||
)
|
||||
}
|
||||
if (memo.length < MEMO_MIN_CHARS) {
|
||||
throw new LogError('Memo text is too short', memo.length)
|
||||
}
|
||||
|
||||
if (memo.length > MEMO_MAX_CHARS) {
|
||||
throw new LogError('Memo text is too long', memo.length)
|
||||
}
|
||||
|
||||
const receiveBalance = await calculateRecepientBalance(receiverUser.id, amount, creationDate)
|
||||
const pendingTx = DbPendingTransaction.create()
|
||||
pendingTx.amount = amount
|
||||
@ -151,4 +161,85 @@ export class SendCoinsResolver {
|
||||
throw new LogError(`Error in revertSendCoins: `, err)
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
async settleSendCoins(
|
||||
@Args()
|
||||
{
|
||||
communityReceiverIdentifier,
|
||||
userReceiverIdentifier,
|
||||
creationDate,
|
||||
amount,
|
||||
memo,
|
||||
communitySenderIdentifier,
|
||||
userSenderIdentifier,
|
||||
userSenderName,
|
||||
}: SendCoinsArgs,
|
||||
): Promise<boolean> {
|
||||
logger.debug(`settleSendCoins() via apiVersion=1_0 ...`)
|
||||
try {
|
||||
// first check if receiver community is correct
|
||||
const homeCom = await DbCommunity.findOneByOrFail({
|
||||
communityUuid: communityReceiverIdentifier,
|
||||
})
|
||||
/*
|
||||
if (!homeCom) {
|
||||
throw new LogError(
|
||||
`settleSendCoins with wrong communityReceiverIdentifier`,
|
||||
communityReceiverIdentifier,
|
||||
)
|
||||
}
|
||||
*/
|
||||
// second check if receiver user exists in this community
|
||||
const receiverUser = await DbUser.findOneByOrFail({ gradidoID: userReceiverIdentifier })
|
||||
/*
|
||||
if (!receiverUser) {
|
||||
throw new LogError(
|
||||
`settleSendCoins with unknown userReceiverIdentifier in the community=`,
|
||||
homeCom.name,
|
||||
)
|
||||
}
|
||||
*/
|
||||
const pendingTx = await DbPendingTransaction.findOneBy({
|
||||
userCommunityUuid: communityReceiverIdentifier,
|
||||
userGradidoID: userReceiverIdentifier,
|
||||
state: PendingTransactionState.NEW,
|
||||
typeId: TransactionTypeId.RECEIVE,
|
||||
balanceDate: creationDate,
|
||||
linkedUserCommunityUuid: communitySenderIdentifier,
|
||||
linkedUserGradidoID: userSenderIdentifier,
|
||||
})
|
||||
logger.debug('XCom: settleSendCoins found pendingTX=', pendingTx)
|
||||
if (pendingTx && pendingTx.amount === amount && pendingTx.memo === memo) {
|
||||
logger.debug('XCom: settleSendCoins matching pendingTX for settlement...')
|
||||
try {
|
||||
await settlePendingReceiveTransaction(homeCom, receiverUser, pendingTx)
|
||||
logger.debug('XCom: settlePendingReceiveTransaction successfully...')
|
||||
} catch (err) {
|
||||
throw new LogError('Error in settlePendingReceiveTransaction: ', err)
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
'XCom: settlePendingReceiveTransaction NOT matching pendingTX for settlement...',
|
||||
)
|
||||
throw new LogError(
|
||||
`Can't find in settlePendingReceiveTransaction the pending receiver TX for args=`,
|
||||
communityReceiverIdentifier,
|
||||
userReceiverIdentifier,
|
||||
PendingTransactionState.NEW,
|
||||
TransactionTypeId.RECEIVE,
|
||||
creationDate,
|
||||
amount,
|
||||
memo,
|
||||
communitySenderIdentifier,
|
||||
userSenderIdentifier,
|
||||
userSenderName,
|
||||
)
|
||||
}
|
||||
logger.debug(`settlePendingReceiveTransaction()-1_0... successfull`)
|
||||
return true
|
||||
} catch (err) {
|
||||
throw new LogError(`Error in settlePendingReceiveTransaction: `, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { calculateDecay } from '@/graphql/util/decay'
|
||||
import { getLastTransaction } from '@/graphql/util/getLastTransaction'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { getLastTransaction } from './getLastTransaction'
|
||||
import { calculateDecay } from './decay'
|
||||
import { Decay } from '../api/1_0/model/Decay'
|
||||
import { Decay } from '../model/Decay'
|
||||
|
||||
export async function calculateRecepientBalance(
|
||||
userId: number,
|
||||
@ -0,0 +1,199 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable new-cap */
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import { getConnection, In } from '@dbTools/typeorm'
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
import { PendingTransaction as DbPendingTransaction } from '@entity/PendingTransaction'
|
||||
import { Transaction as dbTransaction } from '@entity/Transaction'
|
||||
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { PendingTransactionState } from '../enum/PendingTransactionState'
|
||||
import { TransactionTypeId } from '../enum/TransactionTypeId'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { federationLogger as logger } from '@/server/logger'
|
||||
|
||||
import { getLastTransaction } from '@/graphql/util/getLastTransaction'
|
||||
import { TRANSACTIONS_LOCK } from '@/graphql/util/TRANSACTIONS_LOCK'
|
||||
|
||||
export async function settlePendingReceiveTransaction(
|
||||
homeCom: DbCommunity,
|
||||
receiverUser: DbUser,
|
||||
pendingTx: DbPendingTransaction,
|
||||
): Promise<boolean> {
|
||||
// acquire lock
|
||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||
try {
|
||||
logger.info('X-Com: settlePendingReceiveTransaction:', homeCom, receiverUser, pendingTx)
|
||||
|
||||
const openSenderPendingTx = await DbPendingTransaction.count({
|
||||
where: [
|
||||
{ userGradidoID: pendingTx?.userGradidoID, state: PendingTransactionState.NEW },
|
||||
{ linkedUserGradidoID: pendingTx?.linkedUserGradidoID, state: PendingTransactionState.NEW },
|
||||
],
|
||||
})
|
||||
const openReceiverPendingTx = await DbPendingTransaction.count({
|
||||
where: [
|
||||
{ userGradidoID: userReceiverIdentifier, state: PendingTransactionState.NEW },
|
||||
{ linkedUserGradidoID: userReceiverIdentifier, state: PendingTransactionState.NEW },
|
||||
],
|
||||
})
|
||||
if (openSenderPendingTx > 1 || openReceiverPendingTx > 1) {
|
||||
throw new LogError('There are more than 1 pending Transactions for Sender and/or Recipient')
|
||||
}
|
||||
|
||||
if (
|
||||
communityReceiverIdentifier === communitySenderIdentifier &&
|
||||
communitySenderIdentifier === userSenderIdentifier
|
||||
) {
|
||||
throw new LogError('Sender and Recipient are the same user: ', userSenderName)
|
||||
}
|
||||
|
||||
if (memo.length < MEMO_MIN_CHARS) {
|
||||
throw new LogError('Memo text is too short', memo.length)
|
||||
}
|
||||
|
||||
if (memo.length > MEMO_MAX_CHARS) {
|
||||
throw new LogError('Memo text is too long', memo.length)
|
||||
}
|
||||
|
||||
const recipientUser = await DbUser.findOneByOrFail({ gradidoID: userReceiverIdentifier })
|
||||
const lastTransaction = await getLastTransaction(recipientUser.id)
|
||||
const pendingTx = await DbPendingTransaction.findOneByOrFail({
|
||||
userId: recipientUser.id,
|
||||
userGradidoID: recipientUser.gradidoID,
|
||||
})
|
||||
|
||||
if (lastTransaction?.id !== pendingTx.previous) {
|
||||
throw new LogError(
|
||||
`X-Com: missmatching transaction order! lastTransationId=${lastTransaction?.id} != pendingTx.previous=${pendingTx.previous}`,
|
||||
)
|
||||
}
|
||||
// validate amount
|
||||
const receivedCallDate = new Date()
|
||||
const sendBalance = await calculateBalance(
|
||||
sender.id,
|
||||
amount.mul(-1),
|
||||
receivedCallDate,
|
||||
transactionLink,
|
||||
)
|
||||
logger.debug(`calculated Balance=${sendBalance}`)
|
||||
if (!sendBalance) {
|
||||
throw new LogError('User has not enough GDD or amount is < 0', sendBalance)
|
||||
}
|
||||
|
||||
const queryRunner = getConnection().createQueryRunner()
|
||||
await queryRunner.connect()
|
||||
await queryRunner.startTransaction('REPEATABLE READ')
|
||||
logger.debug(`open Transaction to write...`)
|
||||
try {
|
||||
// transaction
|
||||
const transactionSend = new dbTransaction()
|
||||
transactionSend.typeId = TransactionTypeId.SEND
|
||||
transactionSend.memo = memo
|
||||
transactionSend.userId = sender.id
|
||||
transactionSend.userGradidoID = sender.gradidoID
|
||||
transactionSend.userName = fullName(sender.firstName, sender.lastName)
|
||||
transactionSend.linkedUserId = recipient.id
|
||||
transactionSend.linkedUserGradidoID = recipient.gradidoID
|
||||
transactionSend.linkedUserName = fullName(recipient.firstName, recipient.lastName)
|
||||
transactionSend.amount = amount.mul(-1)
|
||||
transactionSend.balance = sendBalance.balance
|
||||
transactionSend.balanceDate = receivedCallDate
|
||||
transactionSend.decay = sendBalance.decay.decay
|
||||
transactionSend.decayStart = sendBalance.decay.start
|
||||
transactionSend.previous = sendBalance.lastTransactionId
|
||||
transactionSend.transactionLinkId = transactionLink ? transactionLink.id : null
|
||||
await queryRunner.manager.insert(dbTransaction, transactionSend)
|
||||
|
||||
logger.debug(`sendTransaction inserted: ${dbTransaction}`)
|
||||
|
||||
const transactionReceive = new dbTransaction()
|
||||
transactionReceive.typeId = TransactionTypeId.RECEIVE
|
||||
transactionReceive.memo = memo
|
||||
transactionReceive.userId = recipient.id
|
||||
transactionReceive.userGradidoID = recipient.gradidoID
|
||||
transactionReceive.userName = fullName(recipient.firstName, recipient.lastName)
|
||||
transactionReceive.linkedUserId = sender.id
|
||||
transactionReceive.linkedUserGradidoID = sender.gradidoID
|
||||
transactionReceive.linkedUserName = fullName(sender.firstName, sender.lastName)
|
||||
transactionReceive.amount = amount
|
||||
const receiveBalance = await calculateBalance(recipient.id, amount, receivedCallDate)
|
||||
transactionReceive.balance = receiveBalance ? receiveBalance.balance : amount
|
||||
transactionReceive.balanceDate = receivedCallDate
|
||||
transactionReceive.decay = receiveBalance ? receiveBalance.decay.decay : new Decimal(0)
|
||||
transactionReceive.decayStart = receiveBalance ? receiveBalance.decay.start : null
|
||||
transactionReceive.previous = receiveBalance ? receiveBalance.lastTransactionId : null
|
||||
transactionReceive.linkedTransactionId = transactionSend.id
|
||||
transactionReceive.transactionLinkId = transactionLink ? transactionLink.id : null
|
||||
await queryRunner.manager.insert(dbTransaction, transactionReceive)
|
||||
logger.debug(`receive Transaction inserted: ${dbTransaction}`)
|
||||
|
||||
// Save linked transaction id for send
|
||||
transactionSend.linkedTransactionId = transactionReceive.id
|
||||
await queryRunner.manager.update(dbTransaction, { id: transactionSend.id }, transactionSend)
|
||||
logger.debug('send Transaction updated', transactionSend)
|
||||
|
||||
if (transactionLink) {
|
||||
logger.info('transactionLink', transactionLink)
|
||||
transactionLink.redeemedAt = receivedCallDate
|
||||
transactionLink.redeemedBy = recipient.id
|
||||
await queryRunner.manager.update(
|
||||
dbTransactionLink,
|
||||
{ id: transactionLink.id },
|
||||
transactionLink,
|
||||
)
|
||||
}
|
||||
|
||||
await queryRunner.commitTransaction()
|
||||
logger.info(`commit Transaction successful...`)
|
||||
|
||||
await EVENT_TRANSACTION_SEND(sender, recipient, transactionSend, transactionSend.amount)
|
||||
|
||||
await EVENT_TRANSACTION_RECEIVE(
|
||||
recipient,
|
||||
sender,
|
||||
transactionReceive,
|
||||
transactionReceive.amount,
|
||||
)
|
||||
|
||||
// trigger to send transaction via dlt-connector
|
||||
void sendTransactionsToDltConnector()
|
||||
} catch (e) {
|
||||
await queryRunner.rollbackTransaction()
|
||||
throw new LogError('Transaction was not successful', e)
|
||||
} finally {
|
||||
await queryRunner.release()
|
||||
}
|
||||
void sendTransactionReceivedEmail({
|
||||
firstName: recipient.firstName,
|
||||
lastName: recipient.lastName,
|
||||
email: recipient.emailContact.email,
|
||||
language: recipient.language,
|
||||
senderFirstName: sender.firstName,
|
||||
senderLastName: sender.lastName,
|
||||
senderEmail: sender.emailContact.email,
|
||||
transactionAmount: amount,
|
||||
})
|
||||
if (transactionLink) {
|
||||
void sendTransactionLinkRedeemedEmail({
|
||||
firstName: sender.firstName,
|
||||
lastName: sender.lastName,
|
||||
email: sender.emailContact.email,
|
||||
language: sender.language,
|
||||
senderFirstName: recipient.firstName,
|
||||
senderLastName: recipient.lastName,
|
||||
senderEmail: recipient.emailContact.email,
|
||||
transactionAmount: amount,
|
||||
transactionMemo: memo,
|
||||
})
|
||||
}
|
||||
logger.info(`finished executeTransaction successfully`)
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
return true
|
||||
}
|
||||
4
federation/src/graphql/util/TRANSACTIONS_LOCK.ts
Normal file
4
federation/src/graphql/util/TRANSACTIONS_LOCK.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { Semaphore } from 'await-semaphore'
|
||||
|
||||
const CONCURRENT_TRANSACTIONS = 1
|
||||
export const TRANSACTIONS_LOCK = new Semaphore(CONCURRENT_TRANSACTIONS)
|
||||
Loading…
x
Reference in New Issue
Block a user