mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
lokaler zwischenstand
This commit is contained in:
parent
a013fd241a
commit
4aeb1b60a2
@ -19,7 +19,7 @@ const constants = {
|
||||
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
|
||||
CONFIG_VERSION: {
|
||||
DEFAULT: 'DEFAULT',
|
||||
EXPECTED: 'v19.2023-09-01',
|
||||
EXPECTED: 'v20.2023-09-19',
|
||||
CURRENT: '',
|
||||
},
|
||||
}
|
||||
@ -122,6 +122,7 @@ if (
|
||||
}
|
||||
|
||||
const federation = {
|
||||
FEDERATION_BACKEND_SEND_ON_API: process.env.FEDERATION_BACKEND_SEND_ON_API || '1_0',
|
||||
FEDERATION_VALIDATE_COMMUNITY_TIMER:
|
||||
Number(process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER) || 60000,
|
||||
FEDERATION_XCOM_SENDCOINS_ENABLED:
|
||||
|
||||
@ -5,6 +5,7 @@ import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
import { SendCoinsArgs } from './model/SendCoinsArgs'
|
||||
import { SendCoinsResult } from './model/SendCoinsResult'
|
||||
import { revertSendCoins } from './query/revertSendCoins'
|
||||
import { revertSettledSendCoins } from './query/revertSettledSendCoins'
|
||||
import { settleSendCoins } from './query/settleSendCoins'
|
||||
@ -30,27 +31,30 @@ export class SendCoinsClient {
|
||||
})
|
||||
}
|
||||
|
||||
voteForSendCoins = async (args: SendCoinsArgs): Promise<string | undefined> => {
|
||||
voteForSendCoins = async (args: SendCoinsArgs): Promise<SendCoinsResult> => {
|
||||
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?.voteForSendCoins) {
|
||||
if (!data?.voteForSendCoins?.vote) {
|
||||
logger.warn(
|
||||
'X-Com: voteForSendCoins failed with: ',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
data.voteForSendCoins.voteForSendCoins,
|
||||
data.voteForSendCoins.recipGradidoID,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
data.voteForSendCoins.recipName,
|
||||
)
|
||||
return
|
||||
return new SendCoinsResult()
|
||||
}
|
||||
logger.debug(
|
||||
'X-Com: voteForSendCoins successful with result=',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
data.voteForSendCoins,
|
||||
)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
||||
return data.voteForSendCoins.voteForSendCoins
|
||||
const result = new SendCoinsResult()
|
||||
result.vote = true
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
||||
result.recipGradidoID = data.voteForSendCoins.recipGradidoID
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
||||
result.recipName = data.voteForSendCoins.recipName
|
||||
logger.debug('X-Com: voteForSendCoins successful with result=', result)
|
||||
return result
|
||||
} catch (err) {
|
||||
throw new LogError(`X-Com: voteForSendCoins failed for endpoint=${this.endpoint}:`, err)
|
||||
}
|
||||
|
||||
@ -9,9 +9,9 @@ export class SendCoinsResult {
|
||||
@Field(() => Boolean)
|
||||
vote: boolean
|
||||
|
||||
@Field(() => String)
|
||||
receiverFirstName: string
|
||||
@Field(() => String, { nullable: true })
|
||||
recipGradidoID: string | null
|
||||
|
||||
@Field(() => String)
|
||||
receiverLastName: string
|
||||
@Field(() => String, { nullable: true })
|
||||
recipName: string | null
|
||||
}
|
||||
|
||||
@ -20,6 +20,10 @@ export const voteForSendCoins = gql`
|
||||
senderCommunityUuid: $senderCommunityUuid
|
||||
senderUserUuid: $senderUserUuid
|
||||
senderUserName: $senderUserName
|
||||
)
|
||||
) {
|
||||
vote
|
||||
recipGradidoID
|
||||
recipName
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@ -58,7 +58,7 @@ let bob: User
|
||||
let peter: User
|
||||
|
||||
let homeCom: DbCommunity
|
||||
// let foreignCom: DbCommunity
|
||||
let foreignCom: DbCommunity
|
||||
|
||||
describe('send coins', () => {
|
||||
beforeAll(async () => {
|
||||
@ -67,7 +67,7 @@ describe('send coins', () => {
|
||||
await userFactory(testEnv, stephenHawking)
|
||||
await userFactory(testEnv, garrickOllivander)
|
||||
homeCom = DbCommunity.create()
|
||||
homeCom.communityUuid = 'homeCom-UUID'
|
||||
homeCom.communityUuid = '7f474922-b6d8-4b64-8cd0-ebf0a1d8756e'
|
||||
homeCom.creationDate = new Date('2000-01-01')
|
||||
homeCom.description = 'homeCom description'
|
||||
homeCom.foreign = false
|
||||
@ -77,6 +77,17 @@ describe('send coins', () => {
|
||||
homeCom.url = 'homeCom url'
|
||||
homeCom = await DbCommunity.save(homeCom)
|
||||
|
||||
foreignCom = DbCommunity.create()
|
||||
foreignCom.communityUuid = '7f474922-b6d8-4b64-8cd0-cea0a1d8756e'
|
||||
foreignCom.creationDate = new Date('2000-06-06')
|
||||
foreignCom.description = 'homeCom description'
|
||||
foreignCom.foreign = true
|
||||
foreignCom.name = 'foreignCom name'
|
||||
foreignCom.privateKey = Buffer.from('foreignCom privateKey')
|
||||
foreignCom.publicKey = Buffer.from('foreignCom publicKey')
|
||||
foreignCom.url = 'foreignCom url'
|
||||
foreignCom = await DbCommunity.save(foreignCom)
|
||||
|
||||
bobData = {
|
||||
email: 'bob@baumeister.de',
|
||||
password: 'Aa12345_',
|
||||
@ -583,6 +594,27 @@ describe('send coins', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe.only('X-Com send coins via gradido ID', () => {
|
||||
it('sends the coins', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
recipientCommunityIdentifier: foreignCom.communityUuid,
|
||||
recipientIdentifier: peter?.gradidoID,
|
||||
amount: 10,
|
||||
memo: 'x-com send via gradido ID',
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
sendCoins: true,
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('more transactions to test semaphore', () => {
|
||||
it('sends the coins four times in a row', async () => {
|
||||
await expect(
|
||||
|
||||
@ -43,6 +43,7 @@ import { getLastTransaction } from './util/getLastTransaction'
|
||||
import { getTransactionList } from './util/getTransactionList'
|
||||
import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector'
|
||||
import { transactionLinkSummary } from './util/transactionLinkSummary'
|
||||
import { processXComPendingSendCoins } from './util/processXComSendCoins'
|
||||
|
||||
export const executeTransaction = async (
|
||||
amount: Decimal,
|
||||
@ -545,6 +546,17 @@ export class TransactionResolver {
|
||||
if (!(await isCommunityAuthenticated(recipientCommunityIdentifier))) {
|
||||
throw new LogError('recipient commuity is connected, but still not authenticated yet!')
|
||||
}
|
||||
const recipCom = await dbCommunity.findOneOrFail({
|
||||
where: { communityUuid: recipientCommunityIdentifier },
|
||||
})
|
||||
await processXComPendingSendCoins(
|
||||
recipCom,
|
||||
homeCom,
|
||||
amount,
|
||||
memo,
|
||||
senderUser,
|
||||
recipientIdentifier,
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -19,27 +19,24 @@ 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,
|
||||
recipientIdentifier: string,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
logger.debug(
|
||||
`XCom: processXComPendingSendCoins...`,
|
||||
receiverFCom,
|
||||
receiverCom,
|
||||
senderCom,
|
||||
creationDate,
|
||||
amount,
|
||||
memo,
|
||||
sender,
|
||||
recipient,
|
||||
recipientIdentifier,
|
||||
)
|
||||
const creationDate = new Date()
|
||||
// first calculate the sender balance and check if the transaction is allowed
|
||||
const senderBalance = await calculateSenderBalance(sender.id, amount.mul(-1), creationDate)
|
||||
if (!senderBalance) {
|
||||
@ -47,24 +44,32 @@ export async function processXComPendingSendCoins(
|
||||
}
|
||||
logger.debug(`X-Com: calculated senderBalance = `, senderBalance)
|
||||
|
||||
const receiverFCom = await DbFederatedCommunity.findOneOrFail({
|
||||
where: {
|
||||
publicKey: receiverCom.publicKey,
|
||||
apiVersion: CONFIG.FEDERATION_BACKEND_SEND_ON_API,
|
||||
},
|
||||
})
|
||||
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
|
||||
if (receiverCom.communityUuid) {
|
||||
args.recipientCommunityUuid = receiverCom.communityUuid
|
||||
}
|
||||
args.recipientUserIdentifier = recipientIdentifier
|
||||
args.creationDate = creationDate.toISOString()
|
||||
args.amount = amount
|
||||
args.memo = memo
|
||||
args.senderCommunityUuid = senderCom.communityUuid ? senderCom.communityUuid : 'homeCom-UUID'
|
||||
if (senderCom.communityUuid) {
|
||||
args.senderCommunityUuid = senderCom.communityUuid
|
||||
}
|
||||
args.senderUserUuid = sender.gradidoID
|
||||
args.senderUserName = fullName(sender.firstName, sender.lastName)
|
||||
logger.debug(`X-Com: ready for voteForSendCoins with args=`, args)
|
||||
const recipientName = await client.voteForSendCoins(args)
|
||||
logger.debug(`X-Com: returnd from voteForSendCoins:`, recipientName)
|
||||
if (recipientName) {
|
||||
const sendCoinsResult = await client.voteForSendCoins(args)
|
||||
logger.debug(`X-Com: returnd from voteForSendCoins:`, sendCoinsResult)
|
||||
if (sendCoinsResult.vote) {
|
||||
// writing the pending transaction on receiver-side was successfull, so now write the sender side
|
||||
try {
|
||||
const pendingTx = DbPendingTransaction.create()
|
||||
@ -73,11 +78,11 @@ export async function processXComPendingSendCoins(
|
||||
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 = recipientName
|
||||
if (receiverCom.communityUuid) {
|
||||
pendingTx.linkedUserCommunityUuid = receiverCom.communityUuid
|
||||
}
|
||||
pendingTx.linkedUserGradidoID = sendCoinsResult.recipGradidoID
|
||||
pendingTx.linkedUserName = sendCoinsResult.recipName
|
||||
pendingTx.memo = memo
|
||||
pendingTx.previous = senderBalance ? senderBalance.lastTransactionId : null
|
||||
pendingTx.state = PendingTransactionState.NEW
|
||||
|
||||
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, { nullable: true })
|
||||
recipGradidoID: string | null
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
recipName: string | null
|
||||
}
|
||||
@ -14,6 +14,7 @@ import { settlePendingReceiveTransaction } from '../util/settlePendingReceiveTra
|
||||
// import { checkTradingLevel } from '@/graphql/util/checkTradingLevel'
|
||||
import { revertSettledReceiveTransaction } from '../util/revertSettledReceiveTransaction'
|
||||
import { findUserByIdentifier } from '@/graphql/util/findUserByIdentifier'
|
||||
import { SendCoinsResult } from '../model/SendCoinsResult'
|
||||
|
||||
@Resolver()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@ -31,7 +32,7 @@ export class SendCoinsResolver {
|
||||
senderUserUuid,
|
||||
senderUserName,
|
||||
}: SendCoinsArgs,
|
||||
): Promise<string> {
|
||||
): Promise<SendCoinsResult> {
|
||||
logger.debug(
|
||||
`voteForSendCoins() via apiVersion=1_0 ...`,
|
||||
recipientCommunityUuid,
|
||||
@ -43,7 +44,7 @@ export class SendCoinsResolver {
|
||||
senderUserUuid,
|
||||
senderUserName,
|
||||
)
|
||||
let result: string
|
||||
const result = new SendCoinsResult()
|
||||
// first check if receiver community is correct
|
||||
const homeCom = await DbCommunity.findOneBy({
|
||||
communityUuid: recipientCommunityUuid,
|
||||
@ -88,7 +89,9 @@ export class SendCoinsResolver {
|
||||
pendingTx.userName = fullName(receiverUser.firstName, receiverUser.lastName)
|
||||
|
||||
await DbPendingTransaction.insert(pendingTx)
|
||||
result = pendingTx.userName
|
||||
result.vote = true
|
||||
result.recipName = pendingTx.userName
|
||||
result.recipGradidoID = pendingTx.userGradidoID
|
||||
logger.debug(`voteForSendCoins()-1_0... successfull`)
|
||||
} catch (err) {
|
||||
throw new LogError(`Error in voteForSendCoins: `, err)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user