diff --git a/database/README.md b/database/README.md index f78eca113..8d490496b 100644 --- a/database/README.md +++ b/database/README.md @@ -39,6 +39,7 @@ yarn seed ## Seeded Users | email | password | admin | +|------------------------|------------|---------| | peter@lustig.de | `Aa12345_` | `true` | | bibi@bloxberg.de | `Aa12345_` | `false` | | raeuber@hotzenplotz.de | `Aa12345_` | `false` | diff --git a/database/entity/0001-init_db/Balance.ts b/database/entity/0001-init_db/Balance.ts index c1ca359f1..1a7050daf 100644 --- a/database/entity/0001-init_db/Balance.ts +++ b/database/entity/0001-init_db/Balance.ts @@ -1,4 +1,5 @@ -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, JoinColumn, OneToOne } from 'typeorm' +import { User } from '../User' @Entity('state_balances') export class Balance extends BaseEntity { @@ -16,4 +17,8 @@ export class Balance extends BaseEntity { @Column({ type: 'bigint' }) amount: number + + @OneToOne(() => User, { nullable: false }) + @JoinColumn({ name: 'state_user_id' }) + user: User } diff --git a/database/entity/0001-init_db/TransactionSignature.ts b/database/entity/0001-init_db/TransactionSignature.ts new file mode 100644 index 000000000..df3e02ba6 --- /dev/null +++ b/database/entity/0001-init_db/TransactionSignature.ts @@ -0,0 +1,21 @@ +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm' +import { Transaction } from './Transaction' + +@Entity('transaction_signatures') +export class TransactionSignature extends BaseEntity { + @PrimaryGeneratedColumn() + id: number + + @Column({ name: 'transaction_id' }) + transactionId: number + + @Column({ type: 'binary', length: 64 }) + signature: Buffer + + @Column({ type: 'binary', length: 32 }) + pubkey: Buffer + + @ManyToOne(() => Transaction) + @JoinColumn({ name: 'transaction_id' }) + transaction: Transaction +} diff --git a/database/entity/0001-init_db/User.ts b/database/entity/0001-init_db/User.ts index 7280dca40..545d4f5c5 100644 --- a/database/entity/0001-init_db/User.ts +++ b/database/entity/0001-init_db/User.ts @@ -1,4 +1,5 @@ -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm' +import { Balance } from '../Balance' // Moriz: I do not like the idea of having two user tables @Entity('state_users') @@ -29,4 +30,7 @@ export class User extends BaseEntity { @Column() disabled: boolean + + @OneToOne(() => Balance, (balance) => balance.user) + balance: Balance } diff --git a/database/entity/TransactionSignature.ts b/database/entity/TransactionSignature.ts new file mode 100644 index 000000000..e3c9cbe1c --- /dev/null +++ b/database/entity/TransactionSignature.ts @@ -0,0 +1 @@ +export { TransactionSignature } from './0001-init_db/TransactionSignature' diff --git a/database/entity/index.ts b/database/entity/index.ts index 92b3875f8..9d3b10ea7 100644 --- a/database/entity/index.ts +++ b/database/entity/index.ts @@ -8,6 +8,7 @@ import { Migration } from './Migration' import { ServerUser } from './ServerUser' import { Transaction } from './Transaction' import { TransactionCreation } from './TransactionCreation' +import { TransactionSignature } from './TransactionSignature' import { TransactionSendCoin } from './TransactionSendCoin' import { User } from './User' import { UserSetting } from './UserSetting' @@ -25,6 +26,7 @@ export const entities = [ ServerUser, Transaction, TransactionCreation, + TransactionSignature, TransactionSendCoin, User, UserSetting, diff --git a/database/src/factories/balance.factory.ts b/database/src/factories/balance.factory.ts new file mode 100644 index 000000000..2c344be99 --- /dev/null +++ b/database/src/factories/balance.factory.ts @@ -0,0 +1,18 @@ +import Faker from 'faker' +import { define } from 'typeorm-seeding' +import { Balance } from '../../entity/Balance' +import { BalanceContext } from '../interface/TransactionContext' + +define(Balance, (faker: typeof Faker, context?: BalanceContext) => { + if (!context || !context.user) { + throw new Error('Balance: No user present!') + } + + const balance = new Balance() + balance.modified = context.modified ? context.modified : faker.date.recent() + balance.recordDate = context.recordDate ? context.recordDate : faker.date.recent() + balance.amount = context.amount ? context.amount : 10000000 + balance.user = context.user + + return balance +}) diff --git a/database/src/factories/transaction-creation.factory.ts b/database/src/factories/transaction-creation.factory.ts new file mode 100644 index 000000000..ec0b9e8a6 --- /dev/null +++ b/database/src/factories/transaction-creation.factory.ts @@ -0,0 +1,18 @@ +import Faker from 'faker' +import { define } from 'typeorm-seeding' +import { TransactionCreation } from '../../entity/TransactionCreation' +import { TransactionCreationContext } from '../interface/TransactionContext' + +define(TransactionCreation, (faker: typeof Faker, context?: TransactionCreationContext) => { + if (!context || !context.userId || !context.transaction) { + throw new Error('TransactionCreation: No userId and/or transaction present!') + } + + const transactionCreation = new TransactionCreation() + transactionCreation.userId = context.userId + transactionCreation.amount = context.amount ? context.amount : 100000 + transactionCreation.targetDate = context.targetDate ? context.targetDate : new Date() + transactionCreation.transaction = context.transaction + + return transactionCreation +}) diff --git a/database/src/factories/transaction-signature.factory.ts b/database/src/factories/transaction-signature.factory.ts new file mode 100644 index 000000000..b79e15052 --- /dev/null +++ b/database/src/factories/transaction-signature.factory.ts @@ -0,0 +1,18 @@ +import Faker from 'faker' +import { define } from 'typeorm-seeding' +import { TransactionSignature } from '../../entity/TransactionSignature' +import { TransactionSignatureContext } from '../interface/TransactionContext' +import { randomBytes } from 'crypto' + +define(TransactionSignature, (faker: typeof Faker, context?: TransactionSignatureContext) => { + if (!context || !context.transaction) { + throw new Error('TransactionSignature: No transaction present!') + } + + const transactionSignature = new TransactionSignature() + transactionSignature.signature = context.signature ? context.signature : randomBytes(64) + transactionSignature.pubkey = context.pubkey ? context.pubkey : randomBytes(32) + transactionSignature.transaction = context.transaction + + return transactionSignature +}) diff --git a/database/src/factories/transaction.factory.ts b/database/src/factories/transaction.factory.ts new file mode 100644 index 000000000..4880ace5b --- /dev/null +++ b/database/src/factories/transaction.factory.ts @@ -0,0 +1,20 @@ +import Faker from 'faker' +import { define } from 'typeorm-seeding' +import { Transaction } from '../../entity/Transaction' +import { TransactionContext } from '../interface/TransactionContext' +import { randomBytes } from 'crypto' + +define(Transaction, (faker: typeof Faker, context?: TransactionContext) => { + if (!context) context = {} + + const transaction = new Transaction() + transaction.transactionTypeId = context.transactionTypeId ? context.transactionTypeId : 2 + transaction.txHash = context.txHash ? context.txHash : randomBytes(48) + transaction.memo = context.memo || context.memo === '' ? context.memo : faker.lorem.sentence() + transaction.received = context.received ? context.received : new Date() + transaction.blockchainTypeId = context.blockchainTypeId ? context.blockchainTypeId : 1 + if (context.transactionSendCoin) transaction.transactionSendCoin = context.transactionSendCoin + if (context.transactionCreation) transaction.transactionCreation = context.transactionCreation + + return transaction +}) diff --git a/database/src/factories/user-transaction.factory.ts b/database/src/factories/user-transaction.factory.ts new file mode 100644 index 000000000..7ea79235b --- /dev/null +++ b/database/src/factories/user-transaction.factory.ts @@ -0,0 +1,19 @@ +import Faker from 'faker' +import { define } from 'typeorm-seeding' +import { UserTransaction } from '../../entity/UserTransaction' +import { UserTransactionContext } from '../interface/TransactionContext' + +define(UserTransaction, (faker: typeof Faker, context?: UserTransactionContext) => { + if (!context || !context.userId || !context.transactionId) { + throw new Error('UserTransaction: No userId and/or transactionId present!') + } + + const userTransaction = new UserTransaction() + userTransaction.userId = context.userId + userTransaction.transactionId = context.transactionId + userTransaction.transactionTypeId = context.transactionTypeId ? context.transactionTypeId : 1 + userTransaction.balance = context.balance ? context.balance : 100000 + userTransaction.balanceDate = context.balanceDate ? context.balanceDate : new Date() + + return userTransaction +}) diff --git a/database/src/index.ts b/database/src/index.ts index ec5328a9a..94566c9f5 100644 --- a/database/src/index.ts +++ b/database/src/index.ts @@ -9,6 +9,7 @@ import { CreatePeterLustigSeed } from './seeds/users/peter-lustig.admin.seed' import { CreateBibiBloxbergSeed } from './seeds/users/bibi-bloxberg.seed' import { CreateRaeuberHotzenplotzSeed } from './seeds/users/raeuber-hotzenplotz.seed' import { CreateBobBaumeisterSeed } from './seeds/users/bob-baumeister.seed' +import { DecayStartBlockSeed } from './seeds/decay-start-block.seed' const run = async (command: string) => { // Database actions not supported by our migration library @@ -59,6 +60,7 @@ const run = async (command: string) => { root: process.cwd(), configName: 'ormconfig.js', }) + await runSeeder(DecayStartBlockSeed) await runSeeder(CreatePeterLustigSeed) await runSeeder(CreateBibiBloxbergSeed) await runSeeder(CreateRaeuberHotzenplotzSeed) diff --git a/database/src/interface/TransactionContext.ts b/database/src/interface/TransactionContext.ts new file mode 100644 index 000000000..481959c5f --- /dev/null +++ b/database/src/interface/TransactionContext.ts @@ -0,0 +1,52 @@ +import { Transaction } from '../../entity/Transaction' +import { TransactionSendCoin } from '../../entity/TransactionSendCoin' +import { TransactionCreation } from '../../entity/TransactionCreation' +import { User } from '../../entity/User' + +export interface TransactionContext { + transactionTypeId?: number + txHash?: Buffer + memo?: string + received?: Date + blockchainTypeId?: number + transactionSendCoin?: TransactionSendCoin + transactionCreation?: TransactionCreation +} + +export interface BalanceContext { + modified?: Date + recordDate?: Date + amount?: number + user?: User +} + +export interface TransactionSendCoinContext { + senderPublic?: Buffer + userId?: number + recipiantPublic?: Buffer + recipiantUserId?: number + amount?: number + senderFinalBalance?: number + transaction?: Transaction +} + +export interface TransactionCreationContext { + userId?: number + amount?: number + targetDate?: Date + transaction?: Transaction +} + +export interface UserTransactionContext { + userId?: number + transactionId?: number + transactionTypeId?: number + balance?: number + balanceDate?: Date +} + +export interface TransactionSignatureContext { + signature?: Buffer + pubkey?: Buffer + transaction?: Transaction +} diff --git a/database/src/interface/UserInterface.ts b/database/src/interface/UserInterface.ts index 942158593..70be6cff4 100644 --- a/database/src/interface/UserInterface.ts +++ b/database/src/interface/UserInterface.ts @@ -27,4 +27,14 @@ export interface UserInterface { modified?: Date // flag for admin isAdmin?: boolean + // flag for balance (creation of 1000 GDD) + addBalance?: boolean + // balance + balanceModified?: Date + recordDate?: Date + targetDate?: Date + amount?: number + creationTxHash?: Buffer + signature?: Buffer + signaturePubkey?: Buffer } diff --git a/database/src/seeds/decay-start-block.seed.ts b/database/src/seeds/decay-start-block.seed.ts new file mode 100644 index 000000000..fd62ee333 --- /dev/null +++ b/database/src/seeds/decay-start-block.seed.ts @@ -0,0 +1,17 @@ +import { Factory, Seeder } from 'typeorm-seeding' +import { Transaction } from '../../entity/Transaction' + +export class DecayStartBlockSeed implements Seeder { + public async run(factory: Factory): Promise { + await factory(Transaction)({ + transactionTypeId: 9, + txHash: Buffer.from( + '9c9c4152b8a4cfbac287eee18d2d262e9de756fae726fc0ca36b788564973fff00000000000000000000000000000000', + 'hex', + ), + memo: '', + received: new Date('2021-11-30T09:13:26'), + blockchainTypeId: 1, + }).create() + } +} diff --git a/database/src/seeds/helpers/user-helpers.ts b/database/src/seeds/helpers/user-helpers.ts index 805104519..bd46ecdee 100644 --- a/database/src/seeds/helpers/user-helpers.ts +++ b/database/src/seeds/helpers/user-helpers.ts @@ -5,16 +5,28 @@ import { ServerUserContext, LoginUserRolesContext, } from '../../interface/UserContext' +import { + BalanceContext, + TransactionContext, + TransactionCreationContext, + UserTransactionContext, + TransactionSignatureContext, +} from '../../interface/TransactionContext' import { UserInterface } from '../../interface/UserInterface' import { User } from '../../../entity/User' import { LoginUser } from '../../../entity/LoginUser' import { LoginUserBackup } from '../../../entity/LoginUserBackup' import { ServerUser } from '../../../entity/ServerUser' import { LoginUserRoles } from '../../../entity/LoginUserRoles' +import { Balance } from '../../../entity/Balance' +import { Transaction } from '../../../entity/Transaction' +import { TransactionSignature } from '../../../entity/TransactionSignature' +import { UserTransaction } from '../../../entity/UserTransaction' +import { TransactionCreation } from '../../../entity/TransactionCreation' import { Factory } from 'typeorm-seeding' export const userSeeder = async (factory: Factory, userData: UserInterface): Promise => { - await factory(User)(createUserContext(userData)).create() + const user = await factory(User)(createUserContext(userData)).create() const loginUser = await factory(LoginUser)(createLoginUserContext(userData)).create() await factory(LoginUserBackup)(createLoginUserBackupContext(userData, loginUser)).create() @@ -25,9 +37,26 @@ export const userSeeder = async (factory: Factory, userData: UserInterface): Pro // It works with LoginRoles empty!! await factory(LoginUserRoles)(createLoginUserRolesContext(loginUser)).create() } + + if (userData.addBalance) { + // create some GDD for the user + await factory(Balance)(createBalanceContext(userData, user)).create() + const transaction = await factory(Transaction)( + createTransactionContext(userData, 1, 'Herzlich Willkommen bei Gradido!'), + ).create() + await factory(TransactionCreation)( + createTransactionCreationContext(userData, user, transaction), + ).create() + await factory(UserTransaction)( + createUserTransactionContext(userData, user, transaction), + ).create() + await factory(TransactionSignature)( + createTransactionSignatureContext(userData, transaction), + ).create() + } } -export const createUserContext = (context: UserInterface): UserContext => { +const createUserContext = (context: UserInterface): UserContext => { return { pubkey: context.pubKey, email: context.email, @@ -38,7 +67,7 @@ export const createUserContext = (context: UserInterface): UserContext => { } } -export const createLoginUserContext = (context: UserInterface): LoginUserContext => { +const createLoginUserContext = (context: UserInterface): LoginUserContext => { return { email: context.email, firstName: context.firstName, @@ -59,7 +88,7 @@ export const createLoginUserContext = (context: UserInterface): LoginUserContext } } -export const createLoginUserBackupContext = ( +const createLoginUserBackupContext = ( context: UserInterface, loginUser: LoginUser, ): LoginUserBackupContext => { @@ -70,7 +99,7 @@ export const createLoginUserBackupContext = ( } } -export const createServerUserContext = (context: UserInterface): ServerUserContext => { +const createServerUserContext = (context: UserInterface): ServerUserContext => { return { role: context.role, username: context.username, @@ -83,9 +112,69 @@ export const createServerUserContext = (context: UserInterface): ServerUserConte } } -export const createLoginUserRolesContext = (loginUser: LoginUser): LoginUserRolesContext => { +const createLoginUserRolesContext = (loginUser: LoginUser): LoginUserRolesContext => { return { userId: loginUser.id, roleId: 1, } } + +const createBalanceContext = (context: UserInterface, user: User): BalanceContext => { + return { + modified: context.balanceModified, + recordDate: context.recordDate, + amount: context.amount, + user, + } +} + +const createTransactionContext = ( + context: UserInterface, + type: number, + memo: string, +): TransactionContext => { + return { + transactionTypeId: type, + txHash: context.creationTxHash, + memo, + received: context.recordDate, + } +} + +const createTransactionCreationContext = ( + context: UserInterface, + user: User, + transaction: Transaction, +): TransactionCreationContext => { + return { + userId: user.id, + amount: context.amount, + targetDate: context.targetDate, + transaction, + } +} + +const createUserTransactionContext = ( + context: UserInterface, + user: User, + transaction: Transaction, +): UserTransactionContext => { + return { + userId: user.id, + transactionId: transaction.id, + transactionTypeId: transaction.transactionTypeId, + balance: context.amount, + balanceDate: context.recordDate, + } +} + +const createTransactionSignatureContext = ( + context: UserInterface, + transaction: Transaction, +): TransactionSignatureContext => { + return { + signature: context.signature, + pubkey: context.signaturePubkey, + transaction, + } +} diff --git a/database/src/seeds/users/bibi-bloxberg.ts b/database/src/seeds/users/bibi-bloxberg.ts index d87e3eb4a..30ad4eb4c 100644 --- a/database/src/seeds/users/bibi-bloxberg.ts +++ b/database/src/seeds/users/bibi-bloxberg.ts @@ -22,4 +22,21 @@ export const bibiBloxberg = { 'knife normal level all hurdle crucial color avoid warrior stadium road bachelor affair topple hawk pottery right afford immune two ceiling budget glance hour ', mnemonicType: 2, isAdmin: false, + addBalance: true, + balanceModified: new Date('2021-11-30T10:37:11'), + recordDate: new Date('2021-11-30T10:37:11'), + targetDate: new Date('2021-08-01 00:00:00'), + amount: 10000000, + creationTxHash: Buffer.from( + '51103dc0fc2ca5d5d75a9557a1e899304e5406cfdb1328d8df6414d527b0118100000000000000000000000000000000', + 'hex', + ), + signature: Buffer.from( + '2a2c71f3e41adc060bbc3086577e2d57d24eeeb0a7727339c3f85aad813808f601d7e1df56a26e0929d2e67fc054fca429ccfa283ed2782185c7f009fe008f0c', + 'hex', + ), + signaturePubkey: Buffer.from( + '7281e0ee3258b08801f3ec73e431b4519677f65c03b0382c63a913b5784ee770', + 'hex', + ), } diff --git a/database/src/seeds/users/bob-baumeister.ts b/database/src/seeds/users/bob-baumeister.ts index 33ce35656..a6933d7c1 100644 --- a/database/src/seeds/users/bob-baumeister.ts +++ b/database/src/seeds/users/bob-baumeister.ts @@ -22,4 +22,21 @@ export const bobBaumeister = { 'detail master source effort unable waste tilt flush domain orchard art truck hint barrel response gate impose peanut secret merry three uncle wink resource ', mnemonicType: 2, isAdmin: false, + addBalance: true, + balanceModified: new Date('2021-11-30T10:37:14'), + recordDate: new Date('2021-11-30T10:37:14'), + targetDate: new Date('2021-08-01 00:00:00'), + amount: 10000000, + creationTxHash: Buffer.from( + 'be095dc87acb94987e71168fee8ecbf50ecb43a180b1006e75d573b35725c69c00000000000000000000000000000000', + 'hex', + ), + signature: Buffer.from( + '1fbd6b9a3d359923b2501557f3bc79fa7e428127c8090fb16bc490b4d87870ab142b3817ddd902d22f0b26472a483233784a0e460c0622661752a13978903905', + 'hex', + ), + signaturePubkey: Buffer.from( + '7281e0ee3258b08801f3ec73e431b4519677f65c03b0382c63a913b5784ee770', + 'hex', + ), } diff --git a/database/src/seeds/users/raeuber-hotzenplotz.ts b/database/src/seeds/users/raeuber-hotzenplotz.ts index 10fcf8af1..eb2118af5 100644 --- a/database/src/seeds/users/raeuber-hotzenplotz.ts +++ b/database/src/seeds/users/raeuber-hotzenplotz.ts @@ -22,4 +22,21 @@ export const raeuberHotzenplotz = { 'gospel trip tenant mouse spider skill auto curious man video chief response same little over expire drum display fancy clinic keen throw urge basket ', mnemonicType: 2, isAdmin: false, + addBalance: true, + balanceModified: new Date('2021-11-30T10:37:13'), + recordDate: new Date('2021-11-30T10:37:13'), + targetDate: new Date('2021-08-01 00:00:00'), + amount: 10000000, + creationTxHash: Buffer.from( + '23ba44fd84deb59b9f32969ad0cb18bfa4588be1bdb99c396888506474c16c1900000000000000000000000000000000', + 'hex', + ), + signature: Buffer.from( + '756d3da061687c575d1dbc5073908f646aa5f498b0927b217c83b48af471450e571dfe8421fb8e1f1ebd1104526b7e7c6fa78684e2da59c8f7f5a8dc3d9e5b0b', + 'hex', + ), + signaturePubkey: Buffer.from( + '7281e0ee3258b08801f3ec73e431b4519677f65c03b0382c63a913b5784ee770', + 'hex', + ), }