From 8b3653016be15d0d8f9b73b1afdf4fe9270baad8 Mon Sep 17 00:00:00 2001 From: Einhornimmond Date: Mon, 20 Sep 2021 18:42:04 +0200 Subject: [PATCH] get balance working with apollo --- backend/src/graphql/models/User.ts | 3 ++ .../src/graphql/resolvers/BalanceResolver.ts | 20 +++++++++-- backend/src/index.ts | 7 +++- backend/src/typeorm/connection.ts | 23 ++++++++++++ backend/src/typeorm/entity/Balance.ts | 25 +++++++++++++ backend/src/typeorm/entity/Group.ts | 25 +++++++++++++ backend/src/typeorm/entity/User.ts | 35 +++++++++++++++++++ backend/src/util/decay.ts | 4 +++ backend/src/util/round.ts | 17 +++++++++ 9 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 backend/src/typeorm/connection.ts create mode 100644 backend/src/typeorm/entity/Balance.ts create mode 100644 backend/src/typeorm/entity/Group.ts create mode 100644 backend/src/typeorm/entity/User.ts create mode 100644 backend/src/util/decay.ts create mode 100644 backend/src/util/round.ts diff --git a/backend/src/graphql/models/User.ts b/backend/src/graphql/models/User.ts index 47037d483..31d456da5 100644 --- a/backend/src/graphql/models/User.ts +++ b/backend/src/graphql/models/User.ts @@ -15,6 +15,7 @@ export class User { this.lastName = json.last_name this.username = json.username this.description = json.description + this.pubkey = json.public_hex this.language = json.language } @@ -33,6 +34,8 @@ export class User { @Field(() => String) description: string + @Field(() => String) + pubkey: string /* @Field(() => String) pubkey: string diff --git a/backend/src/graphql/resolvers/BalanceResolver.ts b/backend/src/graphql/resolvers/BalanceResolver.ts index 27e0d4890..fdcc1ec1f 100644 --- a/backend/src/graphql/resolvers/BalanceResolver.ts +++ b/backend/src/graphql/resolvers/BalanceResolver.ts @@ -5,14 +5,30 @@ import { Resolver, Query, Ctx, Authorized } from 'type-graphql' import CONFIG from '../../config' import { Balance } from '../models/Balance' import { apiGet } from '../../apis/loginAPI' +import { User as tUser } from '../../typeorm/entity/User' +import { Balance as tBalance } from '../../typeorm/entity/Balance' +import calculateDecay from '../../util/decay' +import { roundFloorFrom4 } from '../../util/round' @Resolver() export class BalanceResolver { @Authorized() @Query(() => Balance) async balance(@Ctx() context: any): Promise { - const result = await apiGet(CONFIG.COMMUNITY_API_URL + 'getBalance/' + context.sessionId) + // get public key for current logged in user + const result = await apiGet(CONFIG.LOGIN_API_URL + 'login?session_id=' + context.sessionId) if (!result.success) throw new Error(result.data) - return new Balance(result.data) + + // load user and balance + const userEntity = await tUser.findByPubkeyHex(result.data.user.public_hex) + const balanceEntity = await tBalance.findByUser(userEntity.id) + const now = new Date() + const balance = new Balance({ + balance: roundFloorFrom4(balanceEntity.amount), + decay: roundFloorFrom4(calculateDecay(balanceEntity.amount, balanceEntity.recordDate, now)), + decay_date: now.toString(), + }) + + return balance } } diff --git a/backend/src/index.ts b/backend/src/index.ts index 07086c544..2e1af7342 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -8,6 +8,7 @@ import { ApolloServer } from 'apollo-server-express' import { RowDataPacket } from 'mysql2/promise' import connection from './database/connection' +import typeOrmConnection from './typeorm/connection' import CONFIG from './config' // TODO move to extern @@ -48,7 +49,11 @@ async function main() { throw new Error(`Wrong database version - the backend requires '${DB_VERSION}'`) } - // const connection = await createConnection() + const toCon = await typeOrmConnection() + if (!toCon.isConnected) { + throw new Error(`Couldn't open typeorm db connection`) + } + const schema = await buildSchema({ resolvers: [UserResolver, BalanceResolver, TransactionResolver, GdtResolver], authChecker: isAuthorized, diff --git a/backend/src/typeorm/connection.ts b/backend/src/typeorm/connection.ts new file mode 100644 index 000000000..f954593ad --- /dev/null +++ b/backend/src/typeorm/connection.ts @@ -0,0 +1,23 @@ +import { createConnection, Connection } from 'typeorm' +import CONFIG from '../config' +import path from 'path' + +const connection = async (): Promise => { + const con = await createConnection({ + name: 'default', + type: 'mysql', + host: CONFIG.DB_HOST, + port: CONFIG.DB_PORT, + username: CONFIG.DB_USER, + password: CONFIG.DB_PASSWORD, + database: CONFIG.DB_DATABASE, + entities: [path.join(__dirname, 'entity', '*.ts')], + synchronize: false, + }) + + // await con.connect() + + return con +} + +export default connection diff --git a/backend/src/typeorm/entity/Balance.ts b/backend/src/typeorm/entity/Balance.ts new file mode 100644 index 000000000..1cde6bcc2 --- /dev/null +++ b/backend/src/typeorm/entity/Balance.ts @@ -0,0 +1,25 @@ +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' + +@Entity('state_balances') +export class Balance extends BaseEntity { + @PrimaryGeneratedColumn() + id: number + + @Column({ name: 'state_user_id' }) + userId: number + + @Column({ type: 'datetime' }) + modified: Date + + @Column({ name: 'record_date', type: 'datetime' }) + recordDate: Date + + @Column({ type: 'bigint' }) + amount: number + + static findByUser(userId: number): Promise { + return this.createQueryBuilder('balance') + .where('balance.userId = :userId', { userId }) + .getOneOrFail() + } +} diff --git a/backend/src/typeorm/entity/Group.ts b/backend/src/typeorm/entity/Group.ts new file mode 100644 index 000000000..6694ea742 --- /dev/null +++ b/backend/src/typeorm/entity/Group.ts @@ -0,0 +1,25 @@ +/* import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm"; +import { User } from "./User" + +@Entity() +export class Group { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + alias: string; + + @Column() + name: string; + + @Column() + url: string; + + @Column() + description: string; + + @OneToMany(type => User, user => user.group) + users: User[]; + +} */ diff --git a/backend/src/typeorm/entity/User.ts b/backend/src/typeorm/entity/User.ts new file mode 100644 index 000000000..2aab67cdd --- /dev/null +++ b/backend/src/typeorm/entity/User.ts @@ -0,0 +1,35 @@ +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' + +// import { Group } from "./Group" +@Entity() +export class User extends BaseEntity { + @PrimaryGeneratedColumn() + id: number + + // @ManyToOne(type => Group, group => group.users) + // group: Group; + + @Column({ type: 'binary', length: 32 }) + pubkey: Buffer + + @Column() + email: string + + @Column() + firstName: string + + @Column() + lastName: string + + @Column() + username: string + + @Column() + disabled: boolean + + static findByPubkeyHex(pubkeyHex: string): Promise { + return this.createQueryBuilder('user') + .where('hex(user.pubkey) = :pubkeyHex', { pubkeyHex }) + .getOneOrFail() + } +} diff --git a/backend/src/util/decay.ts b/backend/src/util/decay.ts new file mode 100644 index 000000000..44a041a00 --- /dev/null +++ b/backend/src/util/decay.ts @@ -0,0 +1,4 @@ +export default function (amount: number, from: Date, to: Date): number { + const decayDuration = (to.getTime() - from.getTime()) / 1000 + return amount * Math.pow(0.99999997802044727, decayDuration) +} diff --git a/backend/src/util/round.ts b/backend/src/util/round.ts new file mode 100644 index 000000000..18e15afcd --- /dev/null +++ b/backend/src/util/round.ts @@ -0,0 +1,17 @@ +function roundCeilFrom4(decimal: number): number { + return Math.ceil(decimal / 100) / 100 +} + +function roundFloorFrom4(decimal: number): number { + return Math.floor(decimal / 100) / 100 +} + +function roundCeilFrom2(decimal: number): number { + return Math.ceil(decimal / 100) +} + +function roundFloorFrom2(decimal: number): number { + return Math.floor(decimal / 100) +} + +export { roundCeilFrom4, roundFloorFrom4, roundCeilFrom2, roundFloorFrom2 }