mirror of
https://github.com/IT4Change/gradido.git
synced 2026-03-01 12:44:43 +00:00
159 lines
5.6 KiB
TypeScript
159 lines
5.6 KiB
TypeScript
import { TypeBoxFromValibot } from '@sinclair/typemap'
|
|
import { Elysia, status, t, ValidationError } from 'elysia'
|
|
import { AddressType_NONE } from 'gradido-blockchain-js'
|
|
import { getLogger } from 'log4js'
|
|
import * as v from 'valibot'
|
|
import { ensureCommunitiesAvailable } from '../client/GradidoNode/communities'
|
|
import { GradidoNodeClient } from '../client/GradidoNode/GradidoNodeClient'
|
|
import { LOG4JS_BASE_CATEGORY } from '../config/const'
|
|
import { KeyPairIdentifierLogic } from '../data/KeyPairIdentifier.logic'
|
|
import { ResolveKeyPair } from '../interactions/resolveKeyPair/ResolveKeyPair.context'
|
|
import { SendToHieroContext } from '../interactions/sendToHiero/SendToHiero.context'
|
|
import { IdentifierAccountInput, identifierAccountSchema } from '../schemas/account.schema'
|
|
import { transactionSchema } from '../schemas/transaction.schema'
|
|
import { hieroTransactionIdStringSchema } from '../schemas/typeGuard.schema'
|
|
import {
|
|
accountIdentifierSeedTypeBoxSchema,
|
|
accountIdentifierUserTypeBoxSchema,
|
|
} from './input.schema'
|
|
import { existTypeBoxSchema } from './output.schema'
|
|
|
|
const logger = getLogger(`${LOG4JS_BASE_CATEGORY}.server`)
|
|
|
|
/**
|
|
* To define a route in Elysia:
|
|
*
|
|
* 1. Choose the HTTP method: get, post, patch, put, or delete.
|
|
*
|
|
* 2. Define the route path:
|
|
* - **Params**: values inside the path.
|
|
* Example: path: `/isCommunityExist/:communityTopicId`
|
|
* → called with: GET `/isCommunityExist/0.0.21732`
|
|
*
|
|
* - **Query**: values in the query string.
|
|
* Example: path: `/isCommunityExist`
|
|
* → called with: GET `/isCommunityExist?communityTopicId=0.0.21732`
|
|
*
|
|
* 3. Write the route handler:
|
|
* Return a JSON object — often by calling your business logic.
|
|
*
|
|
* 4. Define validation schemas using TypeBoxFromValibot:
|
|
* - `params` (for path parameters)
|
|
* - `query` (for query strings)
|
|
* - `body` (for POST/PUT/PATCH requests)
|
|
* - `response` (for output)
|
|
*
|
|
* Example:
|
|
* .get(
|
|
* '/isCommunityExist/:communityTopicId',
|
|
* async ({ params: { communityTopicId } }) => ({
|
|
* exists: await isCommunityExist({ communityTopicId })
|
|
* }),
|
|
* {
|
|
* params: t.Object({ communityTopicId: TypeBoxFromValibot(hieroIdSchema) }),
|
|
* response: t.Object({ exists: t.Boolean() }),
|
|
* },
|
|
* )
|
|
*
|
|
* 🔗 More info: https://elysiajs.com/at-glance.html
|
|
*/
|
|
export const appRoutes = new Elysia()
|
|
.onError(({ code, error }) => {
|
|
if (code === 'VALIDATION' && error instanceof ValidationError) {
|
|
logger.debug(JSON.stringify(error.all[0], null, 2))
|
|
logger.error(error.all[0].summary)
|
|
return error.all[0].summary
|
|
}
|
|
return error
|
|
})
|
|
// check if account exists by user, call example:
|
|
// GET /isAccountExist/by-user/0.0.21732/408780b2-59b3-402a-94be-56a4f4f4e8ec/0
|
|
.get(
|
|
'/isAccountExist/by-user/:communityTopicId/:userUuid/:accountNr',
|
|
async ({ params: { communityTopicId, userUuid, accountNr } }) => ({
|
|
exists: await isAccountExist({
|
|
communityTopicId,
|
|
account: { userUuid, accountNr },
|
|
}),
|
|
}),
|
|
{
|
|
params: accountIdentifierUserTypeBoxSchema,
|
|
response: existTypeBoxSchema,
|
|
},
|
|
)
|
|
// check if account exists by seed, call example:
|
|
// GET /isAccountExist/by-seed/0.0.21732/0c4676adfd96519a0551596c
|
|
.get(
|
|
'/isAccountExist/by-seed/:communityTopicId/:seed',
|
|
async ({ params: { communityTopicId, seed } }) => ({
|
|
exists: await isAccountExist({
|
|
communityTopicId,
|
|
seed,
|
|
}),
|
|
}),
|
|
{
|
|
params: accountIdentifierSeedTypeBoxSchema,
|
|
response: existTypeBoxSchema,
|
|
},
|
|
)
|
|
// send transaction to hiero, call example for send transaction:
|
|
// POST /sendTransaction
|
|
// body: {
|
|
// user: {
|
|
// communityTopicId: '0.0.21732',
|
|
// account: {
|
|
// userUuid: '408780b2-59b3-402a-94be-56a4f4f4e8ec',
|
|
// accountNr: 0,
|
|
// },
|
|
// },
|
|
// linkedUser: {
|
|
// communityTopicId: '0.0.21732',
|
|
// account: {
|
|
// userUuid: '10689787-00fe-4295-a996-05c0952558d9',
|
|
// accountNr: 0,
|
|
// },
|
|
// },
|
|
// amount: 10,
|
|
// memo: 'test',
|
|
// type: 'TRANSFER',
|
|
// createdAt: '2022-01-01T00:00:00.000Z',
|
|
// }
|
|
.post(
|
|
'/sendTransaction',
|
|
async ({ body }) => ({
|
|
transactionId: await SendToHieroContext(body),
|
|
}),
|
|
{
|
|
body: TypeBoxFromValibot(transactionSchema),
|
|
response: t.Object({ transactionId: TypeBoxFromValibot(hieroTransactionIdStringSchema) }),
|
|
},
|
|
)
|
|
|
|
// function stay here for now because it is small and simple, but maybe later if more functions are added, move it to a separate file
|
|
async function isAccountExist(identifierAccount: IdentifierAccountInput): Promise<boolean> {
|
|
// check and prepare input
|
|
const startTime = Date.now()
|
|
const identifierAccountParsed = v.parse(identifierAccountSchema, identifierAccount)
|
|
// make sure gradido node knows community
|
|
await ensureCommunitiesAvailable([identifierAccountParsed.communityTopicId])
|
|
const accountKeyPair = await ResolveKeyPair(new KeyPairIdentifierLogic(identifierAccountParsed))
|
|
const publicKey = accountKeyPair.getPublicKey()
|
|
if (!publicKey) {
|
|
throw status(404, { message: "couldn't calculate account key pair" })
|
|
}
|
|
|
|
// ask gradido node server for account type, if type !== NONE account exist
|
|
const addressType = await GradidoNodeClient.getInstance().getAddressType(
|
|
publicKey.convertToHex(),
|
|
identifierAccountParsed.communityTopicId,
|
|
)
|
|
const exists = addressType !== AddressType_NONE
|
|
const endTime = Date.now()
|
|
logger.info(`isAccountExist: ${exists}, time used: ${endTime - startTime}ms`)
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug('params', identifierAccountParsed)
|
|
}
|
|
return exists
|
|
}
|
|
export type DltRoutes = typeof appRoutes
|