mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
adjustments
This commit is contained in:
parent
e1cc58381e
commit
4dc4451b2f
@ -13,13 +13,18 @@ import { UserAccountDraft } from './model/UserAccountDraft'
|
||||
import { UserIdentifier } from './model/UserIdentifier'
|
||||
|
||||
const sendTransaction = gql`
|
||||
mutation ($input: TransactionInput!) {
|
||||
mutation ($input: TransactionDraft!) {
|
||||
sendTransaction(data: $input) {
|
||||
error {
|
||||
message
|
||||
name
|
||||
}
|
||||
succeed
|
||||
recipe {
|
||||
createdAt
|
||||
type
|
||||
messageIdHex
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -32,6 +37,11 @@ const registerAddress = gql`
|
||||
name
|
||||
}
|
||||
succeed
|
||||
recipe {
|
||||
createdAt
|
||||
type
|
||||
messageIdHex
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -126,7 +136,6 @@ export class DltConnectorClient {
|
||||
amount: amountString,
|
||||
type: typeString,
|
||||
createdAt: transaction.balanceDate.toISOString(),
|
||||
backendTransactionId: transaction.id,
|
||||
targetDate: transaction.creationDate?.toISOString(),
|
||||
},
|
||||
}
|
||||
@ -142,9 +151,14 @@ export class DltConnectorClient {
|
||||
if (result.error) {
|
||||
throw new Error(result.error.message)
|
||||
}
|
||||
console.log(result)
|
||||
return result
|
||||
} catch (e) {
|
||||
throw new LogError('Error send sending transaction to dlt-connector: ', e)
|
||||
if (e instanceof Error) {
|
||||
throw new LogError(`from dlt-connector: ${e.message}`)
|
||||
} else {
|
||||
throw new LogError('Exception sending transfer transaction to dlt-connector', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,11 +186,15 @@ export class DltConnectorClient {
|
||||
result,
|
||||
})
|
||||
if (result.error) {
|
||||
logger.error('Error sending register address transaction to dlt-connector', result.error)
|
||||
throw new Error(result.error.message)
|
||||
}
|
||||
return result
|
||||
} catch (e) {
|
||||
logger.error('Exception sending register address transaction to dlt-connector', e)
|
||||
if (e instanceof Error) {
|
||||
throw new LogError(`from dlt-connector: ${e.message}`)
|
||||
} else {
|
||||
throw new LogError('Exception sending register address transaction to dlt-connector', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,10 @@ import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import { communityDbUser } from '@/util/communityUser'
|
||||
import { hasElopageBuys } from '@/util/hasElopageBuys'
|
||||
import { InterruptiveSleepManager, TRANSMIT_TO_IOTA_INTERRUPTIVE_SLEEP_KEY } from '@/util/InterruptiveSleepManager'
|
||||
import {
|
||||
InterruptiveSleepManager,
|
||||
TRANSMIT_TO_IOTA_INTERRUPTIVE_SLEEP_KEY,
|
||||
} from '@/util/InterruptiveSleepManager'
|
||||
import { getTimeDurationObject, printTimeDuration } from '@/util/time'
|
||||
|
||||
import random from 'random-bigint'
|
||||
|
||||
@ -33,31 +33,60 @@ export async function sendTransactionsToDltConnector(): Promise<void> {
|
||||
while (true) {
|
||||
const pendingTransaction = await findNextPendingTransaction()
|
||||
if (pendingTransaction instanceof User) {
|
||||
const result = await dltConnector.registerAddress(pendingTransaction)
|
||||
if (result?.succeed && result.recipe) {
|
||||
const dltUser = DltUser.create()
|
||||
dltUser.userId = pendingTransaction.id
|
||||
dltUser.messageId = result.recipe.messageIdHex
|
||||
// wait until saved, necessary before next call to findNextPendingTransaction
|
||||
await DltUser.save(dltUser)
|
||||
logger.info('store dltUser: messageId=%s in dltTx=%d', dltUser.messageId, dltUser.id)
|
||||
const dltUser = DltUser.create()
|
||||
dltUser.userId = pendingTransaction.id
|
||||
try {
|
||||
const result = await dltConnector.registerAddress(pendingTransaction)
|
||||
if (result?.succeed && result.recipe) {
|
||||
dltUser.messageId = result.recipe.messageIdHex
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
dltUser.error = e.message
|
||||
} else if (typeof e === 'string') {
|
||||
dltUser.error = e
|
||||
}
|
||||
}
|
||||
// wait until saved, necessary before next call to findNextPendingTransaction
|
||||
await DltUser.save(dltUser)
|
||||
if (dltUser.messageId) {
|
||||
logger.info('store dltUser: messageId=%s, id=%d', dltUser.messageId, dltUser.id)
|
||||
} else {
|
||||
logger.error('store dltUser with error: id=%d, error=%s', dltUser.id, dltUser.error)
|
||||
}
|
||||
} else if (pendingTransaction instanceof Transaction) {
|
||||
const result = await dltConnector.transmitTransaction(pendingTransaction)
|
||||
if (result?.succeed && result.recipe) {
|
||||
const dltTransaction = DltTransaction.create()
|
||||
dltTransaction.transactionId = pendingTransaction.id
|
||||
dltTransaction.messageId = result.recipe.messageIdHex
|
||||
// wait until saved, necessary before next call to findNextPendingTransaction
|
||||
await DltTransaction.save(dltTransaction)
|
||||
const dltTransaction = DltTransaction.create()
|
||||
dltTransaction.transactionId = pendingTransaction.id
|
||||
try {
|
||||
const result = await dltConnector.transmitTransaction(pendingTransaction)
|
||||
if (result?.succeed && result.recipe) {
|
||||
dltTransaction.messageId = result.recipe.messageIdHex
|
||||
} else {
|
||||
dltTransaction.error = 'skipped'
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
dltTransaction.error = e.message
|
||||
} else if (typeof e === 'string') {
|
||||
dltTransaction.error = e
|
||||
}
|
||||
}
|
||||
// wait until saved, necessary before next call to findNextPendingTransaction
|
||||
await DltTransaction.save(dltTransaction)
|
||||
if (dltTransaction.messageId) {
|
||||
logger.info(
|
||||
'store dltTransaction: messageId=%s in dltTx=%d',
|
||||
'store dltTransaction: messageId=%s, id=%d',
|
||||
dltTransaction.messageId,
|
||||
dltTransaction.id,
|
||||
)
|
||||
} else {
|
||||
logger.error(
|
||||
'store dltTransaction with error: id=%d, error=%s',
|
||||
dltTransaction.id,
|
||||
dltTransaction.error,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// nothing to do, break inner loop and sleep until new work has arrived
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -72,22 +101,21 @@ export async function sendTransactionsToDltConnector(): Promise<void> {
|
||||
}
|
||||
|
||||
async function findNextPendingTransaction(): Promise<Transaction | User | null> {
|
||||
const lastTransactionPromise: Promise<Transaction | undefined> = Transaction.createQueryBuilder()
|
||||
.select()
|
||||
.leftJoin(DltTransaction, 'dltTransaction', 'transaction.id = dltTransaction.transactionId')
|
||||
.where('dltTransaction.transactionId IS NULL')
|
||||
const lastTransactionPromise: Promise<Transaction | null> = Transaction.createQueryBuilder()
|
||||
.leftJoin(DltTransaction, 'dltTransaction', 'Transaction.id = dltTransaction.transactionId')
|
||||
.where('dltTransaction.transaction_id IS NULL')
|
||||
// eslint-disable-next-line camelcase
|
||||
.orderBy({ balance_date: 'ASC', id: 'ASC' })
|
||||
.orderBy({ balance_date: 'ASC', Transaction_id: 'ASC' })
|
||||
.limit(1)
|
||||
.getRawOne()
|
||||
.getOne()
|
||||
|
||||
const lastUserPromise: Promise<User | undefined> = User.createQueryBuilder()
|
||||
.leftJoin(DltUser, 'dltUser', 'user.id = dltUser.userId')
|
||||
.where('dltUser.userId IS NULL')
|
||||
const lastUserPromise: Promise<User | null> = User.createQueryBuilder()
|
||||
.leftJoin(DltUser, 'dltUser', 'User.id = dltUser.userId')
|
||||
.where('dltUser.user_id IS NULL')
|
||||
// eslint-disable-next-line camelcase
|
||||
.orderBy({ created_at: 'ASC', id: 'ASC' })
|
||||
.orderBy({ User_created_at: 'ASC', User_id: 'ASC' })
|
||||
.limit(1)
|
||||
.getRawOne()
|
||||
.getOne()
|
||||
|
||||
const results = await Promise.all([lastTransactionPromise, lastUserPromise])
|
||||
if (results[0] && results[1]) {
|
||||
|
||||
36
database/entity/0087-add_dlt_users_table/DltTransaction.ts
Normal file
36
database/entity/0087-add_dlt_users_table/DltTransaction.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
|
||||
import { Transaction } from '../Transaction'
|
||||
|
||||
@Entity('dlt_transactions', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
|
||||
export class DltTransaction extends BaseEntity {
|
||||
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||
id: number
|
||||
|
||||
@Column({ name: 'transaction_id', type: 'int', unsigned: true, nullable: false })
|
||||
transactionId: number
|
||||
|
||||
@Column({
|
||||
name: 'message_id',
|
||||
length: 64,
|
||||
nullable: true,
|
||||
default: null,
|
||||
collation: 'utf8mb4_unicode_ci',
|
||||
})
|
||||
messageId: string
|
||||
|
||||
@Column({ name: 'verified', type: 'bool', nullable: false, default: false })
|
||||
verified: boolean
|
||||
|
||||
@Column({ name: 'created_at', default: () => 'CURRENT_TIMESTAMP(3)', nullable: false })
|
||||
createdAt: Date
|
||||
|
||||
@Column({ name: 'verified_at', nullable: true, default: null, type: 'datetime' })
|
||||
verifiedAt: Date | null
|
||||
|
||||
@Column({ name: 'error', type: 'text', nullable: true })
|
||||
error: string | null
|
||||
|
||||
@OneToOne(() => Transaction, (transaction) => transaction.dltTransaction)
|
||||
@JoinColumn({ name: 'transaction_id' })
|
||||
transaction?: Transaction | null
|
||||
}
|
||||
@ -27,6 +27,9 @@ export class DltUser extends BaseEntity {
|
||||
@Column({ name: 'verified_at', nullable: true, default: null, type: 'datetime' })
|
||||
verifiedAt: Date | null
|
||||
|
||||
@Column({ name: 'error', type: 'text', nullable: true })
|
||||
error: string | null
|
||||
|
||||
@OneToOne(() => User, (user) => user.dltUser)
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user?: User | null
|
||||
|
||||
@ -1 +1 @@
|
||||
export { DltTransaction } from './0070-add_dlt_transactions_table/DltTransaction'
|
||||
export { DltTransaction } from './0087-add_dlt_users_table/DltTransaction'
|
||||
|
||||
@ -3,17 +3,28 @@
|
||||
|
||||
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||
await queryFn(`
|
||||
CREATE TABLE dlt_users (
|
||||
id int unsigned NOT NULL AUTO_INCREMENT,
|
||||
user_id int(10) unsigned NOT NULL,
|
||||
message_id varchar(64) NULL DEFAULT NULL,
|
||||
verified tinyint(4) NOT NULL DEFAULT 0,
|
||||
created_at datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
verified_at datetime(3),
|
||||
CREATE TABLE \`dlt_users\` (
|
||||
\`id\` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`user_id\` int(10) unsigned NOT NULL,
|
||||
\`message_id\` varchar(64) NULL DEFAULT NULL,
|
||||
\`verified\` tinyint(4) NOT NULL DEFAULT 0,
|
||||
\`created_at\` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
\`verified_at\` datetime(3),
|
||||
\`error\` text NULL DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
|
||||
|
||||
await queryFn(
|
||||
'ALTER TABLE `dlt_transactions` RENAME COLUMN `transactions_id` TO `transaction_id`;',
|
||||
)
|
||||
await queryFn('ALTER TABLE `dlt_transactions` ADD COLUMN `error` text NULL DEFAULT NULL;')
|
||||
}
|
||||
|
||||
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||
await queryFn(`DROP TABLE dlt_users;`)
|
||||
await queryFn(`DROP TABLE \`dlt_users\`;`)
|
||||
|
||||
await queryFn(
|
||||
'ALTER TABLE `dlt_transactions` RENAME COLUMN `transaction_id` TO `transactions_id`;',
|
||||
)
|
||||
await queryFn('ALTER TABLE `dlt_transactions` DROP COLUMN `error`;')
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import { JsonRpcEitherResponse } from 'jsonrpc-ts-client/dist/types/utils/jsonrp
|
||||
import { CONFIG } from '@/config'
|
||||
import { logger } from '@/logging/logger'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { confirmedTransactionFromBase64, getEnumValue } from '@/utils/typeConverter'
|
||||
import { confirmedTransactionFromBase64 } from '@/utils/typeConverter'
|
||||
|
||||
const client = new JsonRpcClient({
|
||||
url: CONFIG.NODE_SERVER_URL,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
import { InputTransactionType } from '@enum/InputTransactionType'
|
||||
import { isValidDateString, isValidNumberString } from '@validator/DateString'
|
||||
import { IsEnum, IsObject, IsPositive, ValidateNested } from 'class-validator'
|
||||
import { InputType, Field, Int } from 'type-graphql'
|
||||
import { IsEnum, IsObject, ValidateNested } from 'class-validator'
|
||||
import { InputType, Field } from 'type-graphql'
|
||||
|
||||
import { UserIdentifier } from './UserIdentifier'
|
||||
|
||||
@ -18,10 +18,6 @@ export class TransactionDraft {
|
||||
@ValidateNested()
|
||||
linkedUser: UserIdentifier
|
||||
|
||||
@Field(() => Int)
|
||||
@IsPositive()
|
||||
backendTransactionId: number
|
||||
|
||||
@Field(() => String)
|
||||
@isValidNumberString()
|
||||
amount: string
|
||||
|
||||
@ -72,9 +72,21 @@ async function main() {
|
||||
|
||||
const communityDraft = await backend.getHomeCommunityDraft()
|
||||
KeyPairCacheManager.getInstance().setHomeCommunityUUID(communityDraft.uuid)
|
||||
logger.info('home community topic: %s', uuid4ToHash(communityDraft.uuid).convertToHex())
|
||||
logger.info('gradido node server: %s', CONFIG.NODE_SERVER_URL)
|
||||
// ask gradido node if community blockchain was created
|
||||
const firstTransaction = await getTransaction(1, uuid4ToHash(communityDraft.uuid).convertToHex())
|
||||
if (!firstTransaction) {
|
||||
try {
|
||||
const firstTransaction = await getTransaction(
|
||||
1,
|
||||
uuid4ToHash(communityDraft.uuid).convertToHex(),
|
||||
)
|
||||
if (!firstTransaction) {
|
||||
// if not exist, create community root transaction
|
||||
await SendToIotaContext(communityDraft)
|
||||
}
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('error requesting gradido node: ', e)
|
||||
// if not exist, create community root transaction
|
||||
await SendToIotaContext(communityDraft)
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ export class CreationTransactionRole extends AbstractTransactionRole {
|
||||
}
|
||||
builder
|
||||
.setCreatedAt(new Date(this.self.createdAt))
|
||||
.setMemo('dummy memo for creation')
|
||||
.setTransactionCreation(
|
||||
new TransferAmount(recipientKeyPair.getPublicKey(), this.self.amount.toString()),
|
||||
new Date(this.self.targetDate),
|
||||
|
||||
@ -26,6 +26,7 @@ export class TransferTransactionRole extends AbstractTransactionRole {
|
||||
const recipientKeyPair = await KeyPairCalculation(this.self.linkedUser)
|
||||
builder
|
||||
.setCreatedAt(new Date(this.self.createdAt))
|
||||
.setMemo('dummy memo for transfer')
|
||||
.setTransactionTransfer(
|
||||
new TransferAmount(senderKeyPair.getPublicKey(), this.self.amount.toString()),
|
||||
recipientKeyPair.getPublicKey(),
|
||||
|
||||
@ -15,7 +15,6 @@ export class TransactionDraftLoggingView extends AbstractLoggingView {
|
||||
return {
|
||||
user: new UserIdentifierLoggingView(this.self.user).toJSON(),
|
||||
linkedUser: new UserIdentifierLoggingView(this.self.linkedUser).toJSON(),
|
||||
backendTransactionId: this.self.backendTransactionId,
|
||||
amount: Number(this.self.amount),
|
||||
type: getEnumValue(InputTransactionType, this.self.type),
|
||||
createdAt: this.self.createdAt,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user