federation module now with Decimal and decay calculations as in backend

This commit is contained in:
Claus-Peter Huebner 2023-08-31 23:36:07 +02:00
parent 04a84c0ae2
commit bea2ceda4c
11 changed files with 233 additions and 14 deletions

View File

@ -6,9 +6,9 @@ import { backendLogger as logger } from '@/server/logger'
import { SendCoinsArgs } from './model/SendCoinsArgs'
import { revertSendCoins } from './query/revertSendCoins'
import { revertSettledSendCoins } from './query/revertSettledSendCoins'
import { settleSendCoins } from './query/settleSendCoins'
import { voteForSendCoins } from './query/voteForSendCoins'
import { revertSettledSendCoins } from './query/revertSettledSendCoins'
// eslint-disable-next-line camelcase
export class SendCoinsClient {

View File

@ -15,6 +15,7 @@ import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
import { calculateSenderBalance } from '@/util/calculateSenderBalance'
import { fullName } from '@/util/utilities'
import { settlePendingSenderTransaction } from './settlePendingSenderTransaction'
export async function processXComPendingSendCoins(

View File

@ -8,13 +8,13 @@ import { PendingTransaction as DbPendingTransaction } from '@entity/PendingTrans
import { Transaction as dbTransaction } from '@entity/Transaction'
import { User as DbUser } from '@entity/User'
import { PendingTransactionState } from '@/graphql/enum/PendingTransactionState'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
import { calculateSenderBalance } from '@/util/calculateSenderBalance'
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
import { getLastTransaction } from './getLastTransaction'
import { calculateSenderBalance } from '@/util/calculateSenderBalance'
import { PendingTransactionState } from '@/graphql/enum/PendingTransactionState'
export async function settlePendingSenderTransaction(
homeCom: DbCommunity,

View File

@ -1,14 +1,15 @@
// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
/* eslint-disable n/no-process-env */
import { Decimal } from 'decimal.js-light'
import dotenv from 'dotenv'
dotenv.config()
/*
import Decimal from 'decimal.js-light'
Decimal.set({
precision: 25,
rounding: Decimal.ROUND_HALF_UP,
})
*/
const constants = {
DB_VERSION: '0071-add-pending_transactions-table',
@ -62,7 +63,7 @@ const federation = {
},
}
const CONFIG = {
export const CONFIG = {
...constants,
...server,
...database,

View File

@ -0,0 +1,107 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/*
import { createTestClient } from 'apollo-server-testing'
import { Community as DbCommunity } from '@entity/Community'
import CONFIG from '@/config'
import { cleanDB, testEnvironment } from '@test/helpers'
import { createServer } from '@/server/createServer'
let query: any
// to do: We need a setup for the tests that closes the connection
let con: any
CONFIG.FEDERATION_API = '1_0'
beforeAll(async () => {
const server = await createServer()
con = server.con
query = createTestClient(server.apollo).query
await cleanDB()
// DbCommunity.clear()
})
afterAll(async () => {
await con.close()
})
describe('SendCoinsResolver', () => {
const voteForSendCoinsMutation = `
mutation (
$communityReceiverIdentifier: String!
$userReceiverIdentifier: String!
$creationDate: Date!
$amount: Decimal!
$memo: String!
$communitySenderIdentifier: String!
$userSenderIdentifier: String!
$userSenderName: String!
) {
voteForSendCoins(
communityReceiverIdentifier: $communityReceiverIdentifier
userReceiverIdentifier: $userReceiverIdentifier
creationDate: $creationDate
amount: $amount
memo: $memo
communitySenderIdentifier: $communitySenderIdentifier
userSenderIdentifier: $userSenderIdentifier
userSenderName: $userSenderName
)
}
`
describe('get 1st TX at all', () => {
let homeCom: DbCommunity
let foreignCom: DbCommunity
const varsPeterLustig = {
email: 'peter@lustig.de',
firstName: 'Peter',
lastName: 'Lustig',
language: 'de',
publisherId: 1234,
}
const varsBibiBloxberg = {
email: 'bibi@bloxberg.de',
firstName: 'Bibi',
lastName: 'Bloxberg',
language: 'de',
publisherId: 1234,
}
beforeEach(async () => {
homeCom = DbCommunity.create()
homeCom.foreign = false
homeCom.url = 'homeCommunity-url'
homeCom.name = 'Community-Name'
homeCom.description = 'Community-Description'
homeCom.creationDate = new Date()
homeCom.publicKey = Buffer.from('homeCommunity-publicKey')
await DbCommunity.insert(homeCom)
foreignCom = DbCommunity.create()
foreignCom.foreign = true
foreignCom.url = 'foreignCommunity-url'
foreignCom.name = 'foreignCommunity-Name'
foreignCom.description = 'foreign Community-Description'
foreignCom.creationDate = new Date()
foreignCom.publicKey = Buffer.from('foreignCommunity-publicKey')
await DbCommunity.insert(foreignCom)
})
it('returns public CommunityInfo', async () => {
await expect(query({ query: getPublicCommunityInfoQuery })).resolves.toMatchObject({
data: {
getPublicCommunityInfo: {
name: 'Community-Name',
description: 'Community-Description',
creationDate: homeCom.creationDate?.toISOString(),
publicKey: expect.stringMatching('homeCommunity-publicKey'),
},
},
})
})
})
})
*/

View File

@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import createServer from './server/createServer'
import { createServer } from './server/createServer'
// config
import CONFIG from './config'
import { CONFIG } from './config'
async function main() {
// eslint-disable-next-line no-console

View File

@ -13,7 +13,7 @@ import cors from './cors'
import plugins from './plugins'
// config
import CONFIG from '@/config'
import { CONFIG } from '@/config'
// graphql
import schema from '@/graphql/schema'
@ -33,7 +33,7 @@ import { Logger } from 'log4js'
type ServerDef = { apollo: ApolloServer; app: Express; con: Connection }
const createServer = async (
export const createServer = async (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// context: any = serverContext,
logger: Logger = apolloLogger,

View File

@ -0,0 +1,37 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-empty-interface */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { Decimal } from 'decimal.js-light'
expect.extend({
decimalEqual(received, value) {
const pass = new Decimal(value).equals(received.toString())
if (pass) {
return {
message: () => `expected ${received} to not equal ${value}`,
pass: true,
}
} else {
return {
message: () => `expected ${received} to equal ${value}`,
pass: false,
}
}
},
})
interface CustomMatchers<R = unknown> {
decimalEqual(value: number): R
}
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace jest {
interface Expect extends CustomMatchers {}
interface Matchers<R> extends CustomMatchers<R> {}
interface InverseAsymmetricMatchers extends CustomMatchers {}
}
}

View File

@ -0,0 +1,7 @@
import { contributionDateFormatter } from '@test/helpers'
describe('contributionDateFormatter', () => {
it('formats the date correctly', () => {
expect(contributionDateFormatter(new Date('Thu Feb 29 2024 13:12:11'))).toEqual('2/29/2024')
})
})

View File

@ -0,0 +1,66 @@
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import { createServer } from '@/server/createServer'
import { entities } from '@entity/index'
import { createTestClient } from 'apollo-server-testing'
import { logger } from './testSetup'
// import { createServer } from '@/server/createServer'
// import { i18n, logger } from './testSetup'
export const headerPushMock = jest.fn((t) => {
context.token = t.value
})
const context = {
token: '',
setHeaders: {
push: headerPushMock,
forEach: jest.fn(),
},
clientTimezoneOffset: 0,
}
export const cleanDB = async () => {
// this only works as long we do not have foreign key constraints
for (const entity of entities) {
await resetEntity(entity)
}
}
export const testEnvironment = async (testLogger = logger) => {
// , testI18n = i18n) => {
const server = await createServer(testLogger) // context, testLogger, testI18n)
const con = server.con
const testClient = createTestClient(server.apollo)
const mutate = testClient.mutate
const query = testClient.query
return { mutate, query, con }
}
export const resetEntity = async (entity: any) => {
const items = await entity.find({ withDeleted: true })
if (items.length > 0) {
const ids = items.map((e: any) => e.id)
await entity.delete(ids)
}
}
export const resetToken = () => {
context.token = ''
}
// format date string as it comes from the frontend for the contribution date
export const contributionDateFormatter = (date: Date): string => {
return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`
}
export const setClientTimezoneOffset = (offset: number): void => {
context.clientTimezoneOffset = offset
}

View File

@ -54,9 +54,9 @@
"@repository/*": ["src/typeorm/repository/*"],
"@test/*": ["test/*"],
/* common */
"@common/*": ["../common/src/*"],
"@email/*": ["../common/scr/email/*"],
"@event/*": ["../common/src/event/*"],
// "@common/*": ["../common/src/*"],
// "@email/*": ["../common/scr/email/*"],
// "@event/*": ["../common/src/event/*"],
/* external */
"@typeorm/*": ["../backend/src/typeorm/*", "../../backend/src/typeorm/*"],
"@dbTools/*": ["../database/src/*", "../../database/build/src/*"],