mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
add backendTransaction table, update dltConnectorClient code and test
This commit is contained in:
parent
bcaae7002c
commit
ba13144ad3
2533
backend/log.txt
Normal file
2533
backend/log.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,8 +25,6 @@ let testEnv: {
|
||||
jest.mock('graphql-request', () => {
|
||||
const originalModule = jest.requireActual('graphql-request')
|
||||
|
||||
let testCursor = 0
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
@ -38,30 +36,11 @@ jest.mock('graphql-request', () => {
|
||||
// why not using mockResolvedValueOnce or mockReturnValueOnce?
|
||||
// I have tried, but it didn't work and return every time the first value
|
||||
request: jest.fn().mockImplementation(() => {
|
||||
testCursor++
|
||||
if (testCursor === 4) {
|
||||
return Promise.resolve(
|
||||
// invalid, is 33 Bytes long as binary
|
||||
{
|
||||
transmitTransaction: {
|
||||
dltTransactionIdHex:
|
||||
'723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc516212A',
|
||||
},
|
||||
},
|
||||
)
|
||||
} else if (testCursor === 5) {
|
||||
throw Error('Connection error')
|
||||
} else {
|
||||
return Promise.resolve(
|
||||
// valid, is 32 Bytes long as binary
|
||||
{
|
||||
transmitTransaction: {
|
||||
dltTransactionIdHex:
|
||||
'723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
return Promise.resolve({
|
||||
transmitTransaction: {
|
||||
succeed: true,
|
||||
},
|
||||
})
|
||||
}),
|
||||
}
|
||||
}),
|
||||
@ -134,7 +113,10 @@ describe('transmitTransaction', () => {
|
||||
const localTransaction = new DbTransaction()
|
||||
localTransaction.typeId = 12
|
||||
try {
|
||||
await DltConnectorClient.getInstance()?.transmitTransaction(localTransaction)
|
||||
await DltConnectorClient.getInstance()?.transmitTransaction(
|
||||
localTransaction,
|
||||
'senderCommunityUUID',
|
||||
)
|
||||
} catch (e) {
|
||||
expect(e).toMatchObject(
|
||||
new LogError('invalid transaction type id: ' + localTransaction.typeId.toString()),
|
||||
|
||||
@ -6,6 +6,7 @@ import { CONFIG } from '@/config'
|
||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
|
||||
const sendTransaction = gql`
|
||||
mutation ($input: TransactionInput!) {
|
||||
@ -125,15 +126,14 @@ export class DltConnectorClient {
|
||||
transaction: DbTransaction,
|
||||
type: 'sender' | 'recipient',
|
||||
): Promise<string> {
|
||||
const confirmingUserId = transaction.contribution?.confirmedBy
|
||||
let confirmingUser: DbUser | undefined
|
||||
let confirmingUserId: number | undefined
|
||||
logger.info('confirming user id', confirmingUserId)
|
||||
if (confirmingUserId) {
|
||||
confirmingUser = await DbUser.findOneOrFail({ where: { id: confirmingUserId } })
|
||||
}
|
||||
switch (transaction.typeId) {
|
||||
case TransactionTypeId.CREATION:
|
||||
if (!confirmingUserId || !confirmingUser) {
|
||||
confirmingUserId = (
|
||||
await Contribution.findOneOrFail({ where: { transactionId: transaction.id } })
|
||||
).confirmedBy
|
||||
if (!confirmingUserId) {
|
||||
throw new LogError(
|
||||
"couldn't find id of confirming moderator for contribution transaction!",
|
||||
)
|
||||
@ -170,8 +170,8 @@ export class DltConnectorClient {
|
||||
protected async getCorrectUserIdentifier(
|
||||
transaction: DbTransaction,
|
||||
senderCommunityUuid: string,
|
||||
recipientCommunityUuid: string,
|
||||
type: 'sender' | 'recipient',
|
||||
recipientCommunityUuid?: string,
|
||||
): Promise<UserIdentifier> {
|
||||
// sender and receiver user on creation transaction
|
||||
// sender user on send transaction (SEND and RECEIVE)
|
||||
@ -195,7 +195,7 @@ export class DltConnectorClient {
|
||||
public async transmitTransaction(
|
||||
transaction: DbTransaction,
|
||||
senderCommunityUuid: string,
|
||||
recipientCommunityUuid: string,
|
||||
recipientCommunityUuid?: string,
|
||||
): Promise<boolean> {
|
||||
const typeString = getTransactionTypeString(transaction.typeId)
|
||||
// no negative values in dlt connector, gradido concept don't use negative values so the code don't use it too
|
||||
@ -205,14 +205,14 @@ export class DltConnectorClient {
|
||||
senderUser: await this.getCorrectUserIdentifier(
|
||||
transaction,
|
||||
senderCommunityUuid,
|
||||
recipientCommunityUuid,
|
||||
'sender',
|
||||
recipientCommunityUuid,
|
||||
),
|
||||
recipientUser: await this.getCorrectUserIdentifier(
|
||||
transaction,
|
||||
senderCommunityUuid,
|
||||
recipientCommunityUuid,
|
||||
'recipient',
|
||||
recipientCommunityUuid,
|
||||
),
|
||||
amount: amountString,
|
||||
type: typeString,
|
||||
|
||||
@ -24,6 +24,15 @@ import { CONFIG } from '@/config'
|
||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||
|
||||
import { sendTransactionsToDltConnector } from './sendTransactionsToDltConnector'
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
import { User } from '@entity/User'
|
||||
import { userFactory } from '@/seeds/factory/user'
|
||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||
import { creations } from '@/seeds/creation'
|
||||
import { creationFactory } from '@/seeds/factory/creation'
|
||||
import { peterLustig } from '@/seeds/users/peter-lustig'
|
||||
import { raeuberHotzenplotz } from '@/seeds/users/raeuber-hotzenplotz'
|
||||
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
|
||||
|
||||
/*
|
||||
// Mock the GraphQLClient
|
||||
@ -423,9 +432,17 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
|
||||
describe('with 3 creations and active dlt-connector', () => {
|
||||
it('found 3 dlt-transactions', async () => {
|
||||
txCREATION1 = await createTxCREATION1(false)
|
||||
txCREATION2 = await createTxCREATION2(false)
|
||||
txCREATION3 = await createTxCREATION3(false)
|
||||
await userFactory(testEnv, bibiBloxberg)
|
||||
await userFactory(testEnv, peterLustig)
|
||||
await userFactory(testEnv, raeuberHotzenplotz)
|
||||
await userFactory(testEnv, bobBaumeister)
|
||||
let count = 0
|
||||
for (const creation of creations) {
|
||||
await creationFactory(testEnv, creation)
|
||||
count++
|
||||
// we need only 3 for testing
|
||||
if (count >= 3) break
|
||||
}
|
||||
await createHomeCommunity()
|
||||
|
||||
CONFIG.DLT_CONNECTOR = true
|
||||
@ -435,10 +452,7 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return {
|
||||
data: {
|
||||
sendTransaction: {
|
||||
dltTransactionIdHex:
|
||||
'723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
},
|
||||
sendTransaction: { succeed: true },
|
||||
},
|
||||
} as Response<unknown>
|
||||
})
|
||||
@ -464,7 +478,7 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
transactionId: transactions[0].id,
|
||||
messageId: '723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
messageId: 'sended',
|
||||
verified: false,
|
||||
createdAt: expect.any(Date),
|
||||
verifiedAt: null,
|
||||
@ -472,7 +486,7 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
transactionId: transactions[1].id,
|
||||
messageId: '723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
messageId: 'sended',
|
||||
verified: false,
|
||||
createdAt: expect.any(Date),
|
||||
verifiedAt: null,
|
||||
@ -480,7 +494,7 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
transactionId: transactions[2].id,
|
||||
messageId: '723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
messageId: 'sended',
|
||||
verified: false,
|
||||
createdAt: expect.any(Date),
|
||||
verifiedAt: null,
|
||||
@ -514,10 +528,7 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return {
|
||||
data: {
|
||||
sendTransaction: {
|
||||
dltTransactionIdHex:
|
||||
'723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
},
|
||||
sendTransaction: { succeed: true },
|
||||
},
|
||||
} as Response<unknown>
|
||||
})
|
||||
@ -569,7 +580,7 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
transactionId: txSEND1to2.id,
|
||||
messageId: '723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
messageId: 'sended',
|
||||
verified: false,
|
||||
createdAt: expect.any(Date),
|
||||
verifiedAt: null,
|
||||
@ -577,7 +588,7 @@ describe('create and send Transactions to DltConnector', () => {
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
transactionId: txRECEIVE2From1.id,
|
||||
messageId: '723e3fab62c5d3e2f62fd72ba4e622bcd53eff35262e3f3526327fe41bc51621',
|
||||
messageId: 'sended',
|
||||
verified: false,
|
||||
createdAt: expect.any(Date),
|
||||
verifiedAt: null,
|
||||
|
||||
@ -23,7 +23,6 @@ export async function sendTransactionsToDltConnector(): Promise<void> {
|
||||
if (!senderCommunityUuid) {
|
||||
throw new Error('Cannot find community uuid of home community')
|
||||
}
|
||||
const recipientCommunityUuid = ''
|
||||
if (dltConnector) {
|
||||
logger.debug('with sending to DltConnector...')
|
||||
const dltTransactions = await DltTransaction.find({
|
||||
@ -37,27 +36,23 @@ export async function sendTransactionsToDltConnector(): Promise<void> {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
const messageId = await dltConnector.transmitTransaction(
|
||||
const result = await dltConnector.transmitTransaction(
|
||||
dltTx.transaction,
|
||||
senderCommunityUuid,
|
||||
recipientCommunityUuid,
|
||||
)
|
||||
const dltMessageId = Buffer.from(messageId, 'hex')
|
||||
if (dltMessageId.length !== 32) {
|
||||
logger.error(
|
||||
'Error dlt message id is invalid: %s, should by 32 Bytes long in binary after converting from hex',
|
||||
dltMessageId,
|
||||
)
|
||||
return
|
||||
// message id isn't known at this point of time, because transaction will not direct sended to iota,
|
||||
// it will first go to db and then sended, if no transaction is in db before
|
||||
if (result) {
|
||||
dltTx.messageId = 'sended'
|
||||
await DltTransaction.save(dltTx)
|
||||
logger.info('store messageId=%s in dltTx=%d', dltTx.messageId, dltTx.id)
|
||||
}
|
||||
dltTx.messageId = dltMessageId.toString('hex')
|
||||
await DltTransaction.save(dltTx)
|
||||
logger.info('store messageId=%s in dltTx=%d', dltTx.messageId, dltTx.id)
|
||||
} catch (e) {
|
||||
logger.error(
|
||||
`error while sending to dlt-connector or writing messageId of dltTx=${dltTx.id}`,
|
||||
e,
|
||||
)
|
||||
console.log('error', e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
13
dlt-connector/src/data/BackendTransaction.factory.ts
Normal file
13
dlt-connector/src/data/BackendTransaction.factory.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { BackendTransaction } from '@entity/BackendTransaction'
|
||||
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
|
||||
export class BackendTransactionFactory {
|
||||
public static createFromTransactionDraft(transactionDraft: TransactionDraft): BackendTransaction {
|
||||
const backendTransaction = BackendTransaction.create()
|
||||
backendTransaction.backendTransactionId = transactionDraft.backendTransactionId
|
||||
backendTransaction.typeId = transactionDraft.type
|
||||
backendTransaction.createdAt = new Date(transactionDraft.createdAt)
|
||||
return backendTransaction
|
||||
}
|
||||
}
|
||||
7
dlt-connector/src/data/BackendTransaction.repository.ts
Normal file
7
dlt-connector/src/data/BackendTransaction.repository.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { BackendTransaction } from '@entity/BackendTransaction'
|
||||
|
||||
import { getDataSource } from '@/typeorm/DataSource'
|
||||
|
||||
export const BackendTransactionRepository = getDataSource()
|
||||
.getRepository(BackendTransaction)
|
||||
.extend({})
|
||||
@ -4,11 +4,13 @@ import { Transaction } from '@entity/Transaction'
|
||||
|
||||
import { GradidoTransaction } from '@/data/proto/3_3/GradidoTransaction'
|
||||
import { TransactionBody } from '@/data/proto/3_3/TransactionBody'
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { bodyBytesToTransactionBody, transactionBodyToBodyBytes } from '@/utils/typeConverter'
|
||||
|
||||
import { AccountRepository } from './Account.repository'
|
||||
import { BackendTransactionFactory } from './BackendTransaction.factory'
|
||||
import { CommunityRepository } from './Community.repository'
|
||||
import { TransactionBodyBuilder } from './proto/TransactionBody.builder'
|
||||
|
||||
@ -91,8 +93,13 @@ export class TransactionBuilder {
|
||||
return this
|
||||
}
|
||||
|
||||
public setBackendTransactionId(backendTransactionId: number): TransactionBuilder {
|
||||
this.transaction.backendTransactionId = backendTransactionId
|
||||
public addBackendTransaction(transactionDraft: TransactionDraft): TransactionBuilder {
|
||||
if (!this.transaction.backendTransactions) {
|
||||
this.transaction.backendTransactions = []
|
||||
}
|
||||
this.transaction.backendTransactions.push(
|
||||
BackendTransactionFactory.createFromTransactionDraft(transactionDraft),
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
@ -20,30 +20,21 @@ export const TransactionRepository = getDataSource()
|
||||
relations: { signingAccount: true },
|
||||
})
|
||||
},
|
||||
async findExistingTransactionAndMissingMessageIds(messageIDsHex: string[]): Promise<{
|
||||
existingTransactions: Transaction[]
|
||||
missingMessageIdsHex: string[]
|
||||
}> {
|
||||
const existingTransactions = await this.createQueryBuilder('Transaction')
|
||||
findExistingTransactionAndMissingMessageIds(messageIDsHex: string[]): Promise<Transaction[]> {
|
||||
return this.createQueryBuilder('Transaction')
|
||||
.where('HEX(Transaction.iota_message_id) IN (:...messageIDs)', {
|
||||
messageIDs: messageIDsHex,
|
||||
})
|
||||
.leftJoinAndSelect('Transaction.community', 'Community')
|
||||
.leftJoinAndSelect('Transaction.otherCommunity', 'OtherCommunity')
|
||||
.leftJoinAndSelect('Transaction.recipientAccount', 'RecipientAccount')
|
||||
.leftJoinAndSelect('Transaction.backendTransactions', 'BackendTransactions')
|
||||
.leftJoinAndSelect('RecipientAccount.user', 'RecipientUser')
|
||||
.leftJoinAndSelect('Transaction.signingAccount', 'SigningAccount')
|
||||
.leftJoinAndSelect('SigningAccount.user', 'SigningUser')
|
||||
.getMany()
|
||||
|
||||
const foundMessageIds = existingTransactions
|
||||
.map((recipe) => recipe.iotaMessageId?.toString('hex'))
|
||||
.filter((messageId) => !!messageId)
|
||||
// find message ids for which we don't already have a transaction recipe
|
||||
const missingMessageIdsHex = messageIDsHex.filter(
|
||||
(id: string) => !foundMessageIds.includes(id),
|
||||
)
|
||||
return { existingTransactions, missingMessageIdsHex }
|
||||
},
|
||||
async removeConfirmedTransaction(transactions: Transaction[]): Promise<Transaction[]> {
|
||||
removeConfirmedTransaction(transactions: Transaction[]): Transaction[] {
|
||||
return transactions.filter(
|
||||
(transaction: Transaction) =>
|
||||
transaction.runningHash === undefined || transaction.runningHash.length === 0,
|
||||
|
||||
@ -4,8 +4,8 @@ import { TransactionDraft } from '@input/TransactionDraft'
|
||||
|
||||
import { TransactionRepository } from '@/data/Transaction.repository'
|
||||
import { CreateTransactionRecipeContext } from '@/interactions/backendToDb/transaction/CreateTransationRecipe.context'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { TransactionErrorType } from '../enum/TransactionErrorType'
|
||||
import { TransactionError } from '../model/TransactionError'
|
||||
import { TransactionRecipe } from '../model/TransactionRecipe'
|
||||
import { TransactionResult } from '../model/TransactionResult'
|
||||
@ -21,22 +21,28 @@ export class TransactionResolver {
|
||||
try {
|
||||
await createTransactionRecipeContext.run()
|
||||
const transactionRecipe = createTransactionRecipeContext.getTransactionRecipe()
|
||||
await transactionRecipe.save()
|
||||
// check if a transaction with this signature already exist
|
||||
const existingRecipe = await TransactionRepository.findBySignature(
|
||||
transactionRecipe.signature,
|
||||
)
|
||||
if (existingRecipe) {
|
||||
// transaction recipe with this signature already exist, we need only to store the backendTransaction
|
||||
if (transactionRecipe.backendTransactions.length !== 1) {
|
||||
throw new LogError('unexpected backend transaction count', {
|
||||
count: transactionRecipe.backendTransactions.length,
|
||||
transactionId: transactionRecipe.id,
|
||||
})
|
||||
}
|
||||
const backendTransaction = transactionRecipe.backendTransactions[0]
|
||||
backendTransaction.transactionId = transactionRecipe.id
|
||||
await backendTransaction.save()
|
||||
} else {
|
||||
// we can store the transaction and with that automatic the backend transaction
|
||||
await transactionRecipe.save()
|
||||
}
|
||||
return new TransactionResult(new TransactionRecipe(transactionRecipe))
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (error: any) {
|
||||
if (error.code === 'ER_DUP_ENTRY') {
|
||||
const existingRecipe = await TransactionRepository.findBySignature(
|
||||
createTransactionRecipeContext.getTransactionRecipe().signature,
|
||||
)
|
||||
if (!existingRecipe) {
|
||||
throw new TransactionError(
|
||||
TransactionErrorType.LOGIC_ERROR,
|
||||
"recipe cannot be added because signature exist but couldn't load this existing receipt",
|
||||
)
|
||||
}
|
||||
return new TransactionResult(new TransactionRecipe(existingRecipe))
|
||||
}
|
||||
if (error instanceof TransactionError) {
|
||||
return new TransactionResult(error)
|
||||
} else {
|
||||
|
||||
@ -40,11 +40,11 @@ export class TransactionRecipeRole {
|
||||
.setSigningAccount(signingAccount)
|
||||
.setRecipientAccount(recipientAccount)
|
||||
.fromTransactionDraft(transactionDraft)
|
||||
// build transaction entity
|
||||
|
||||
// build transaction entity
|
||||
this.transactionBuilder
|
||||
.fromTransactionBodyBuilder(transactionBodyBuilder)
|
||||
.setBackendTransactionId(transactionDraft.backendTransactionId)
|
||||
.addBackendTransaction(transactionDraft)
|
||||
await this.transactionBuilder.setSenderCommunityFromSenderUser(senderUser)
|
||||
if (recipientUser.communityUuid !== senderUser.communityUuid) {
|
||||
await this.transactionBuilder.setOtherCommunityFromRecipientUser(recipientUser)
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, ManyToOne, JoinColumn } from 'typeorm'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer'
|
||||
import { Transaction } from '../Transaction'
|
||||
|
||||
@Entity('backend_transactions')
|
||||
export class BackendTransaction extends BaseEntity {
|
||||
@PrimaryGeneratedColumn('increment', { unsigned: true, type: 'bigint' })
|
||||
id: number
|
||||
|
||||
@Column({ name: 'backend_transaction_id', type: 'bigint', unsigned: true, nullable: true })
|
||||
backendTransactionId?: number
|
||||
|
||||
@ManyToOne(() => Transaction, (transaction) => transaction.backendTransactions)
|
||||
@JoinColumn({ name: 'transaction_id' })
|
||||
transaction?: Transaction
|
||||
|
||||
@Column({ name: 'transaction_id', type: 'bigint', unsigned: true, nullable: true })
|
||||
transactionId?: number
|
||||
|
||||
@Column({ name: 'type_id', unsigned: true, nullable: false })
|
||||
typeId: number
|
||||
|
||||
// account balance based on creation date
|
||||
@Column({
|
||||
name: 'balance',
|
||||
type: 'decimal',
|
||||
precision: 40,
|
||||
scale: 20,
|
||||
nullable: true,
|
||||
transformer: DecimalTransformer,
|
||||
})
|
||||
balance?: Decimal
|
||||
|
||||
@Column({ name: 'created_at', type: 'datetime', precision: 3 })
|
||||
createdAt: Date
|
||||
|
||||
// use timestamp from iota milestone which is only in seconds precision, so no need to use 3 Bytes extra here
|
||||
@Column({ name: 'confirmed_at', type: 'datetime', nullable: true })
|
||||
confirmedAt?: Date
|
||||
|
||||
@Column({ name: 'verifiedOnBackend', type: 'tinyint', default: false })
|
||||
verifiedOnBackend: boolean
|
||||
}
|
||||
@ -6,12 +6,14 @@ import {
|
||||
OneToOne,
|
||||
JoinColumn,
|
||||
BaseEntity,
|
||||
OneToMany,
|
||||
} from 'typeorm'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer'
|
||||
import { Account } from '../Account'
|
||||
import { Community } from '../Community'
|
||||
import { BackendTransaction } from '../BackendTransaction'
|
||||
|
||||
@Entity('transactions')
|
||||
export class Transaction extends BaseEntity {
|
||||
@ -21,9 +23,6 @@ export class Transaction extends BaseEntity {
|
||||
@Column({ name: 'iota_message_id', type: 'binary', length: 32, nullable: true })
|
||||
iotaMessageId?: Buffer
|
||||
|
||||
@Column({ name: 'backend_transaction_id', type: 'bigint', unsigned: true, nullable: true })
|
||||
backendTransactionId?: number
|
||||
|
||||
@OneToOne(() => Transaction)
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
paringTransaction?: Transaction
|
||||
@ -120,4 +119,10 @@ export class Transaction extends BaseEntity {
|
||||
// use timestamp from iota milestone which is only in seconds precision, so no need to use 3 Bytes extra here
|
||||
@Column({ name: 'confirmed_at', type: 'datetime', nullable: true })
|
||||
confirmedAt?: Date
|
||||
|
||||
@OneToMany(() => BackendTransaction, (backendTransaction) => backendTransaction.transaction, {
|
||||
cascade: ['insert', 'update'],
|
||||
})
|
||||
@JoinColumn({ name: 'transaction_id' })
|
||||
backendTransactions: BackendTransaction[]
|
||||
}
|
||||
|
||||
1
dlt-database/entity/BackendTransaction.ts
Normal file
1
dlt-database/entity/BackendTransaction.ts
Normal file
@ -0,0 +1 @@
|
||||
export { BackendTransaction } from './0003-refactor_transaction_recipe/BackendTransaction'
|
||||
@ -1,5 +1,6 @@
|
||||
import { Account } from './Account'
|
||||
import { AccountCommunity } from './AccountCommunity'
|
||||
import { BackendTransaction } from './BackendTransaction'
|
||||
import { Community } from './Community'
|
||||
import { InvalidTransaction } from './InvalidTransaction'
|
||||
import { Migration } from './Migration'
|
||||
@ -9,6 +10,7 @@ import { User } from './User'
|
||||
export const entities = [
|
||||
AccountCommunity,
|
||||
Account,
|
||||
BackendTransaction,
|
||||
Community,
|
||||
InvalidTransaction,
|
||||
Migration,
|
||||
|
||||
@ -34,7 +34,6 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis
|
||||
`CREATE TABLE \`transactions\` (
|
||||
\`id\` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`iota_message_id\` varbinary(32) NULL DEFAULT NULL,
|
||||
\`backend_transaction_id\` bigint unsigned NULL DEFAULT NULL,
|
||||
\`paring_transaction_id\` bigint unsigned NULL DEFAULT NULL,
|
||||
\`signing_account_id\` int unsigned NULL DEFAULT NULL,
|
||||
\`recipient_account_id\` int unsigned NULL DEFAULT NULL,
|
||||
@ -62,6 +61,22 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis
|
||||
`,
|
||||
)
|
||||
|
||||
await queryFn(
|
||||
`CREATE TABLE \`backend_transactions\` (
|
||||
\`id\` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
|
||||
\`backend_transaction_id\` BIGINT UNSIGNED NOT NULL,
|
||||
\`transaction_id\` BIGINT UNSIGNED NULL DEFAULT NULL,
|
||||
\`type_id\` INT UNSIGNED NOT NULL,
|
||||
\`balance\` DECIMAL(40, 20) NULL DEFAULT NULL,
|
||||
\`created_at\` DATETIME(3) NOT NULL,
|
||||
\`confirmed_at\` DATETIME NULL DEFAULT NULL,
|
||||
\`verifiedOnBackend\` TINYINT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (\`id\`),
|
||||
FOREIGN KEY (\`transaction_id\`) REFERENCES transactions(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`,
|
||||
)
|
||||
|
||||
await queryFn(`ALTER TABLE \`communities\` ADD UNIQUE(\`iota_topic\`);`)
|
||||
|
||||
await queryFn(`ALTER TABLE \`users\` CHANGE \`created_at\` \`created_at\` DATETIME(3) NOT NULL;`)
|
||||
@ -126,6 +141,7 @@ export async function downgrade(queryFn: (query: string, values?: any[]) => Prom
|
||||
await queryFn(`ALTER TABLE \`invalid_transactions\` DROP INDEX \`iota_message_id\`;`)
|
||||
await queryFn(`ALTER TABLE \`invalid_transactions\` ADD INDEX(\`iota_message_id\`); `)
|
||||
await queryFn(`DROP TABLE \`transactions\`;`)
|
||||
await queryFn(`DROP TABLE \`backend_transactions\`;`)
|
||||
|
||||
await queryFn(
|
||||
`ALTER TABLE \`users\` CHANGE \`created_at\` \`created_at\` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3);`,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user