mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
write unit test, small improvements
This commit is contained in:
parent
e7b3cda215
commit
184fe3a2c2
@ -31,7 +31,7 @@ const database = {
|
||||
const iota = {
|
||||
IOTA_API_URL: process.env.IOTA_API_URL ?? 'https://chrysalis-nodes.iota.org',
|
||||
IOTA_COMMUNITY_ALIAS: process.env.IOTA_COMMUNITY_ALIAS ?? 'GRADIDO: TestHelloWelt2',
|
||||
IOTA_HOME_COMMUNITY_SEED: process.env.IOTA_HOME_COMMUNITY_SEED ?? null,
|
||||
IOTA_HOME_COMMUNITY_SEED: process.env.IOTA_HOME_COMMUNITY_SEED?.substring(0, 32) ?? null,
|
||||
}
|
||||
|
||||
const dltConnector = {
|
||||
|
||||
@ -3,10 +3,13 @@ import { entropyToMnemonic, mnemonicToSeedSync } from 'bip39'
|
||||
// eslint-disable-next-line camelcase
|
||||
import { randombytes_buf } from 'sodium-native'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
export class Mnemonic {
|
||||
private _passphrase = ''
|
||||
public constructor(seed?: Buffer | string) {
|
||||
if (seed) {
|
||||
Mnemonic.validateSeed(seed)
|
||||
this._passphrase = entropyToMnemonic(seed)
|
||||
return
|
||||
}
|
||||
@ -22,4 +25,24 @@ export class Mnemonic {
|
||||
public get seed(): Buffer {
|
||||
return mnemonicToSeedSync(this._passphrase)
|
||||
}
|
||||
|
||||
public static validateSeed(seed: Buffer | string): void {
|
||||
let seedBuffer: Buffer
|
||||
if (!Buffer.isBuffer(seed)) {
|
||||
seedBuffer = Buffer.from(seed, 'hex')
|
||||
} else {
|
||||
seedBuffer = seed
|
||||
}
|
||||
if (seedBuffer.length < 16 || seedBuffer.length > 32 || seedBuffer.length % 4 !== 0) {
|
||||
throw new LogError(
|
||||
'invalid seed, must be in binary between 16 and 32 Bytes, Power of 4, for more infos: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic',
|
||||
{
|
||||
seedBufferHex: seedBuffer.toString('hex'),
|
||||
toShort: seedBuffer.length < 16,
|
||||
toLong: seedBuffer.length > 32,
|
||||
powerOf4: seedBuffer.length % 4,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ export class UserLogic {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param parentKeys if undefined use home community key pair
|
||||
* @param parentKeys from home community for own user
|
||||
* @returns
|
||||
*/
|
||||
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
import { Mnemonic } from './data/Mnemonic'
|
||||
import createServer from './server/createServer'
|
||||
import { stopTransmitToIota, transmitToIota } from './tasks/transmitToIota'
|
||||
|
||||
async function main() {
|
||||
if (CONFIG.IOTA_HOME_COMMUNITY_SEED) {
|
||||
Mnemonic.validateSeed(CONFIG.IOTA_HOME_COMMUNITY_SEED)
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`DLT_CONNECTOR_PORT=${CONFIG.DLT_CONNECTOR_PORT}`)
|
||||
const { app } = await createServer()
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
import 'reflect-metadata'
|
||||
import { Community } from '@entity/Community'
|
||||
import { TestDB } from '@test/TestDB'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { CommunityDraft } from '@/graphql/input/CommunityDraft'
|
||||
|
||||
import { AddCommunityContext } from './AddCommunity.context'
|
||||
|
||||
CONFIG.IOTA_HOME_COMMUNITY_SEED = '034b0229a2ba4e98e1cc5e8767dca886279b484303ffa73546bd5f5bf0b71285'
|
||||
|
||||
jest.mock('@typeorm/DataSource', () => ({
|
||||
getDataSource: jest.fn(() => TestDB.instance.dbConnect),
|
||||
}))
|
||||
|
||||
describe('interactions/backendToDb/community/AddCommunity Context Test', () => {
|
||||
beforeAll(async () => {
|
||||
await TestDB.instance.setupTestDB()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await TestDB.instance.teardownTestDB()
|
||||
})
|
||||
|
||||
const homeCommunityDraft = new CommunityDraft()
|
||||
homeCommunityDraft.uuid = 'a2fd0fee-f3ba-4bef-a62a-10a34b0e2754'
|
||||
homeCommunityDraft.foreign = false
|
||||
homeCommunityDraft.createdAt = '2024-01-25T13:09:55.339Z'
|
||||
// calculated from a2fd0fee-f3ba-4bef-a62a-10a34b0e2754 with iotaTopicFromCommunityUUID
|
||||
const iotaTopic = '7be2ad83f279a3aaf6d62371cb6be301e2e3c7a3efda9c89984e8f6a7865d9ce'
|
||||
|
||||
const foreignCommunityDraft = new CommunityDraft()
|
||||
foreignCommunityDraft.uuid = '70df8de5-0fb7-4153-a124-4ff86965be9a'
|
||||
foreignCommunityDraft.foreign = true
|
||||
foreignCommunityDraft.createdAt = '2024-01-25T13:34:28.020Z'
|
||||
|
||||
it('with home community, without iota topic', async () => {
|
||||
const context = new AddCommunityContext(homeCommunityDraft)
|
||||
await context.run()
|
||||
const homeCommunity = await Community.findOneOrFail({ where: { iotaTopic } })
|
||||
expect(homeCommunity).toMatchObject({
|
||||
id: 1,
|
||||
iotaTopic,
|
||||
foreign: 0,
|
||||
rootPubkey: Buffer.from(
|
||||
'07cbf56d4b6b7b188c5f6250c0f4a01d0e44e1d422db1935eb375319ad9f9af0',
|
||||
'hex',
|
||||
),
|
||||
createdAt: new Date('2024-01-25T13:09:55.339Z'),
|
||||
})
|
||||
})
|
||||
|
||||
it('with foreign community', async () => {
|
||||
const context = new AddCommunityContext(foreignCommunityDraft, 'randomTopic')
|
||||
await context.run()
|
||||
const foreignCommunity = await Community.findOneOrFail({ where: { foreign: true } })
|
||||
expect(foreignCommunity).toMatchObject({
|
||||
id: 2,
|
||||
iotaTopic: 'randomTopic',
|
||||
foreign: 1,
|
||||
createdAt: new Date('2024-01-25T13:34:28.020Z'),
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,243 @@
|
||||
import 'reflect-metadata'
|
||||
import { Account } from '@entity/Account'
|
||||
import { Community } from '@entity/Community'
|
||||
import { TestDB } from '@test/TestDB'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { AccountFactory } from '@/data/Account.factory'
|
||||
import { KeyPair } from '@/data/KeyPair'
|
||||
import { Mnemonic } from '@/data/Mnemonic'
|
||||
import { CrossGroupType } from '@/data/proto/3_3/enum/CrossGroupType'
|
||||
import { TransactionType } from '@/data/proto/3_3/enum/TransactionType'
|
||||
import { TransactionBody } from '@/data/proto/3_3/TransactionBody'
|
||||
import { UserFactory } from '@/data/User.factory'
|
||||
import { UserLogic } from '@/data/User.logic'
|
||||
import { AccountType } from '@/graphql/enum/AccountType'
|
||||
import { InputTransactionType } from '@/graphql/enum/InputTransactionType'
|
||||
import { CommunityDraft } from '@/graphql/input/CommunityDraft'
|
||||
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
|
||||
import { UserAccountDraft } from '@/graphql/input/UserAccountDraft'
|
||||
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
|
||||
import { TransactionBodyLoggingView } from '@/logging/TransactionBodyLogging.view'
|
||||
import { TransactionLoggingView } from '@/logging/TransactionLogging.view'
|
||||
|
||||
import { AddCommunityContext } from '../community/AddCommunity.context'
|
||||
|
||||
import { CreateTransactionRecipeContext } from './CreateTransationRecipe.context'
|
||||
|
||||
jest.mock('@typeorm/DataSource', () => ({
|
||||
getDataSource: jest.fn(() => TestDB.instance.dbConnect),
|
||||
}))
|
||||
|
||||
CONFIG.IOTA_HOME_COMMUNITY_SEED = '034b0229a2ba4e98e1cc5e8767dca886279b484303ffa73546bd5f5bf0b71285'
|
||||
const homeCommunityUuid = v4()
|
||||
const foreignCommunityUuid = v4()
|
||||
|
||||
function createUserIdentifier(userUuid: string, communityUuid: string): UserIdentifier {
|
||||
const user = new UserIdentifier()
|
||||
user.uuid = userUuid
|
||||
user.communityUuid = communityUuid
|
||||
return user
|
||||
}
|
||||
|
||||
const keyPair = new KeyPair(new Mnemonic(CONFIG.IOTA_HOME_COMMUNITY_SEED))
|
||||
const foreignKeyPair = new KeyPair(
|
||||
new Mnemonic('5d4e163c078cc6b51f5c88f8422bc8f21d1d59a284515ab1ea79e1c176ebec50'),
|
||||
)
|
||||
const moderator = createUserIdentifier('ff8bbdcb-fc8b-4b5d-98e3-8bd7e1afcdbb', homeCommunityUuid)
|
||||
const firstUser = createUserIdentifier('8e47e32e-0182-4099-b94d-0cac567d1392', homeCommunityUuid)
|
||||
const secondUser = createUserIdentifier('9c8611dd-ee93-4cdb-a600-396c2ca91cc7', homeCommunityUuid)
|
||||
const foreignUser = createUserIdentifier(
|
||||
'b0155716-5219-4c50-b3d3-0757721ae0d2',
|
||||
foreignCommunityUuid,
|
||||
)
|
||||
|
||||
function createUserAndAccount(userIdentifier: UserIdentifier): Account {
|
||||
const accountDraft = new UserAccountDraft()
|
||||
accountDraft.user = userIdentifier
|
||||
accountDraft.createdAt = new Date().toISOString()
|
||||
accountDraft.accountType = AccountType.COMMUNITY_HUMAN
|
||||
let _keyPair: KeyPair
|
||||
if (userIdentifier.communityUuid === homeCommunityUuid) {
|
||||
_keyPair = keyPair
|
||||
} else {
|
||||
_keyPair = foreignKeyPair
|
||||
}
|
||||
const user = UserFactory.create(accountDraft, _keyPair)
|
||||
const userLogic = new UserLogic(user)
|
||||
const account = AccountFactory.createAccountFromUserAccountDraft(
|
||||
accountDraft,
|
||||
userLogic.calculateKeyPair(_keyPair),
|
||||
)
|
||||
account.user = user
|
||||
return account
|
||||
}
|
||||
|
||||
describe('interactions/backendToDb/transaction/Create Transaction Recipe Context Test', () => {
|
||||
beforeAll(async () => {
|
||||
await TestDB.instance.setupTestDB()
|
||||
const homeCommunityDraft = new CommunityDraft()
|
||||
homeCommunityDraft.uuid = homeCommunityUuid
|
||||
homeCommunityDraft.foreign = false
|
||||
homeCommunityDraft.createdAt = '2024-01-25T13:09:55.339Z'
|
||||
let addCommunityContext = new AddCommunityContext(homeCommunityDraft)
|
||||
await addCommunityContext.run()
|
||||
|
||||
const foreignCommunityDraft = new CommunityDraft()
|
||||
foreignCommunityDraft.uuid = foreignCommunityUuid
|
||||
foreignCommunityDraft.foreign = true
|
||||
foreignCommunityDraft.createdAt = '2024-01-25T13:34:28.020Z'
|
||||
addCommunityContext = new AddCommunityContext(foreignCommunityDraft)
|
||||
await addCommunityContext.run()
|
||||
|
||||
const foreignCommunity = await Community.findOneOrFail({ where: { foreign: true } })
|
||||
// that isn't entirely correct, normally only the public key from foreign community is know, and will be come form blockchain
|
||||
foreignKeyPair.fillInCommunityKeys(foreignCommunity)
|
||||
foreignCommunity.save()
|
||||
|
||||
const accounts = [
|
||||
createUserAndAccount(moderator),
|
||||
createUserAndAccount(firstUser),
|
||||
createUserAndAccount(secondUser),
|
||||
createUserAndAccount(foreignUser),
|
||||
]
|
||||
await Account.save(accounts)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await TestDB.instance.teardownTestDB()
|
||||
})
|
||||
|
||||
it('creation transaction', async () => {
|
||||
const creationTransactionDraft = new TransactionDraft()
|
||||
creationTransactionDraft.amount = new Decimal('2000')
|
||||
creationTransactionDraft.backendTransactionId = 1
|
||||
creationTransactionDraft.createdAt = new Date().toISOString()
|
||||
creationTransactionDraft.linkedUser = moderator
|
||||
creationTransactionDraft.user = firstUser
|
||||
creationTransactionDraft.type = InputTransactionType.CREATION
|
||||
creationTransactionDraft.targetDate = new Date().toISOString()
|
||||
const context = new CreateTransactionRecipeContext(creationTransactionDraft)
|
||||
await context.run()
|
||||
const transaction = context.getTransactionRecipe()
|
||||
|
||||
// console.log(new TransactionLoggingView(transaction))
|
||||
expect(
|
||||
transaction.signingAccount?.derive2Pubkey.compare(
|
||||
Buffer.from('19ea7313abc54f120ee0041e5b3b63e34562b0a19b96fa3e6e23cc9bff827a36', 'hex'),
|
||||
),
|
||||
).toBe(0)
|
||||
expect(
|
||||
transaction.recipientAccount?.derive2Pubkey.compare(
|
||||
Buffer.from('5875e1a5e101301cc774b7462566ec2d1a0b04a091dab2e32cecd713b3346224', 'hex'),
|
||||
),
|
||||
).toBe(0)
|
||||
|
||||
expect(transaction).toMatchObject({
|
||||
type: TransactionType.GRADIDO_CREATION,
|
||||
protocolVersion: '3.3',
|
||||
community: {
|
||||
rootPubkey: Buffer.from(
|
||||
'07cbf56d4b6b7b188c5f6250c0f4a01d0e44e1d422db1935eb375319ad9f9af0',
|
||||
'hex',
|
||||
),
|
||||
foreign: 0,
|
||||
},
|
||||
amount: new Decimal(2000),
|
||||
backendTransactions: [
|
||||
{
|
||||
typeId: InputTransactionType.CREATION,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const body = TransactionBody.fromBodyBytes(transaction.bodyBytes)
|
||||
// console.log(new TransactionBodyLoggingView(body))
|
||||
expect(body.creation).toBeDefined()
|
||||
if (!body.creation) throw new Error()
|
||||
const bodyReceiverPubkey = Buffer.from(body.creation.recipient.pubkey)
|
||||
expect(
|
||||
bodyReceiverPubkey.compare(
|
||||
Buffer.from('5875e1a5e101301cc774b7462566ec2d1a0b04a091dab2e32cecd713b3346224', 'hex'),
|
||||
),
|
||||
).toBe(0)
|
||||
expect(body).toMatchObject({
|
||||
type: CrossGroupType.LOCAL,
|
||||
creation: {
|
||||
recipient: {
|
||||
amount: '2000',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('local send transaction', async () => {
|
||||
const sendTransactionDraft = new TransactionDraft()
|
||||
sendTransactionDraft.amount = new Decimal('100')
|
||||
sendTransactionDraft.backendTransactionId = 1
|
||||
sendTransactionDraft.createdAt = new Date().toISOString()
|
||||
sendTransactionDraft.linkedUser = secondUser
|
||||
sendTransactionDraft.user = firstUser
|
||||
sendTransactionDraft.type = InputTransactionType.SEND
|
||||
sendTransactionDraft.targetDate = new Date().toISOString()
|
||||
const context = new CreateTransactionRecipeContext(sendTransactionDraft)
|
||||
await context.run()
|
||||
const transaction = context.getTransactionRecipe()
|
||||
const body = TransactionBody.fromBodyBytes(transaction.bodyBytes)
|
||||
console.log(new TransactionBodyLoggingView(body))
|
||||
console.log(new TransactionLoggingView(transaction))
|
||||
})
|
||||
|
||||
it('local recv transaction', async () => {
|
||||
const recvTransactionDraft = new TransactionDraft()
|
||||
recvTransactionDraft.amount = new Decimal('100')
|
||||
recvTransactionDraft.backendTransactionId = 1
|
||||
recvTransactionDraft.createdAt = new Date().toISOString()
|
||||
recvTransactionDraft.linkedUser = secondUser
|
||||
recvTransactionDraft.user = firstUser
|
||||
recvTransactionDraft.type = InputTransactionType.RECEIVE
|
||||
recvTransactionDraft.targetDate = new Date().toISOString()
|
||||
const context = new CreateTransactionRecipeContext(recvTransactionDraft)
|
||||
await context.run()
|
||||
const transaction = context.getTransactionRecipe()
|
||||
const body = TransactionBody.fromBodyBytes(transaction.bodyBytes)
|
||||
console.log(new TransactionBodyLoggingView(body))
|
||||
console.log(new TransactionLoggingView(transaction))
|
||||
})
|
||||
|
||||
it('cross group send transaction', async () => {
|
||||
const crossGroupSendTransactionDraft = new TransactionDraft()
|
||||
crossGroupSendTransactionDraft.amount = new Decimal('100')
|
||||
crossGroupSendTransactionDraft.backendTransactionId = 1
|
||||
crossGroupSendTransactionDraft.createdAt = new Date().toISOString()
|
||||
crossGroupSendTransactionDraft.linkedUser = foreignUser
|
||||
crossGroupSendTransactionDraft.user = firstUser
|
||||
crossGroupSendTransactionDraft.type = InputTransactionType.SEND
|
||||
crossGroupSendTransactionDraft.targetDate = new Date().toISOString()
|
||||
const context = new CreateTransactionRecipeContext(crossGroupSendTransactionDraft)
|
||||
await context.run()
|
||||
const transaction = context.getTransactionRecipe()
|
||||
const body = TransactionBody.fromBodyBytes(transaction.bodyBytes)
|
||||
console.log(new TransactionBodyLoggingView(body))
|
||||
console.log(new TransactionLoggingView(transaction))
|
||||
})
|
||||
|
||||
it('cross group recv transaction', async () => {
|
||||
const crossGroupRecvTransactionDraft = new TransactionDraft()
|
||||
crossGroupRecvTransactionDraft.amount = new Decimal('100')
|
||||
crossGroupRecvTransactionDraft.backendTransactionId = 1
|
||||
crossGroupRecvTransactionDraft.createdAt = new Date().toISOString()
|
||||
crossGroupRecvTransactionDraft.linkedUser = foreignUser
|
||||
crossGroupRecvTransactionDraft.user = firstUser
|
||||
crossGroupRecvTransactionDraft.type = InputTransactionType.RECEIVE
|
||||
crossGroupRecvTransactionDraft.targetDate = new Date().toISOString()
|
||||
const context = new CreateTransactionRecipeContext(crossGroupRecvTransactionDraft)
|
||||
await context.run()
|
||||
const transaction = context.getTransactionRecipe()
|
||||
const body = TransactionBody.fromBodyBytes(transaction.bodyBytes)
|
||||
console.log(new TransactionBodyLoggingView(body))
|
||||
console.log(new TransactionLoggingView(transaction))
|
||||
})
|
||||
})
|
||||
@ -16,7 +16,7 @@ export class AccountLoggingView extends AbstractLoggingView {
|
||||
id: this.account.id,
|
||||
user: this.account.user ? new UserLoggingView(this.account.user).toJSON() : null,
|
||||
derivationIndex: this.account.derivationIndex,
|
||||
derive2pubkey: this.account.derive2Pubkey.toString(this.bufferStringFormat),
|
||||
derive2Pubkey: this.account.derive2Pubkey.toString(this.bufferStringFormat),
|
||||
type: getEnumValue(AddressType, this.account.type),
|
||||
createdAt: this.dateToString(this.account.createdAt),
|
||||
confirmedAt: this.dateToString(this.account.confirmedAt),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user