mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
fix and refactor dlt
This commit is contained in:
parent
4dc4451b2f
commit
93883ae9f2
@ -61,6 +61,7 @@
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/lodash.clonedeep": "^4.5.6",
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/node-fetch": "^2.6.11",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/sodium-native": "^2.3.5",
|
||||
"@types/uuid": "^8.3.4",
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { User } from '@entity/User'
|
||||
import { gql, GraphQLClient } from 'graphql-request'
|
||||
// eslint-disable-next-line import/named, n/no-extraneous-import
|
||||
import { FetchError } from 'node-fetch'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
import { AccountType } from './enum/AccountType'
|
||||
import { TransactionDraft } from './model/TransactionDraft'
|
||||
import { TransactionResult } from './model/TransactionResult'
|
||||
import { UserAccountDraft } from './model/UserAccountDraft'
|
||||
import { UserIdentifier } from './model/UserIdentifier'
|
||||
|
||||
const sendTransaction = gql`
|
||||
mutation ($input: TransactionDraft!) {
|
||||
@ -46,17 +47,6 @@ const registerAddress = gql`
|
||||
}
|
||||
`
|
||||
|
||||
// from ChatGPT
|
||||
function getTransactionTypeString(id: TransactionTypeId): string {
|
||||
const key = Object.keys(TransactionTypeId).find(
|
||||
(key) => TransactionTypeId[key as keyof typeof TransactionTypeId] === id,
|
||||
)
|
||||
if (key === undefined) {
|
||||
throw new LogError('invalid transaction type id: ' + id.toString())
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// Source: https://refactoring.guru/design-patterns/singleton/typescript/example
|
||||
// and ../federation/client/FederationClientFactory.ts
|
||||
/**
|
||||
@ -109,92 +99,74 @@ export class DltConnectorClient {
|
||||
return DltConnectorClient.instance
|
||||
}
|
||||
|
||||
private getTransactionParams(input: DbTransaction | User): TransactionDraft | UserAccountDraft {
|
||||
if (input instanceof DbTransaction) {
|
||||
return new TransactionDraft(input)
|
||||
} else if (input instanceof User) {
|
||||
return new UserAccountDraft(input)
|
||||
}
|
||||
throw new LogError('transaction should be either Transaction or User Entity')
|
||||
}
|
||||
|
||||
private handleTransactionResult(result: TransactionResult) {
|
||||
if (result.error) {
|
||||
throw new Error(result.error.message)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private async sendTransaction(input: TransactionDraft) {
|
||||
const {
|
||||
data: { sendTransaction: result },
|
||||
} = await this.client.rawRequest<{ sendTransaction: TransactionResult }>(sendTransaction, {
|
||||
input,
|
||||
})
|
||||
return this.handleTransactionResult(result)
|
||||
}
|
||||
|
||||
private async registerAddress(input: UserAccountDraft) {
|
||||
const {
|
||||
data: { registerAddress: result },
|
||||
} = await this.client.rawRequest<{ registerAddress: TransactionResult }>(registerAddress, {
|
||||
input,
|
||||
})
|
||||
return this.handleTransactionResult(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* transmit transaction via dlt-connector to iota
|
||||
* and update dltTransactionId of transaction in db with iota message id
|
||||
*/
|
||||
public async transmitTransaction(
|
||||
transaction: DbTransaction,
|
||||
transaction: DbTransaction | User,
|
||||
): Promise<TransactionResult | undefined> {
|
||||
// we don't need the receive transactions, there contain basically the same data as the send transactions
|
||||
if ((transaction.typeId as TransactionTypeId) === TransactionTypeId.RECEIVE) {
|
||||
if (
|
||||
transaction instanceof DbTransaction &&
|
||||
(transaction.typeId as TransactionTypeId) === TransactionTypeId.RECEIVE
|
||||
) {
|
||||
return
|
||||
}
|
||||
const typeString = getTransactionTypeString(transaction.typeId)
|
||||
// no negative values in dlt connector, gradido concept don't use negative values so the code don't use it too
|
||||
const amountString = transaction.amount.abs().toString()
|
||||
const params = {
|
||||
input: {
|
||||
user: {
|
||||
uuid: transaction.userGradidoID,
|
||||
communityUuid: transaction.userCommunityUuid,
|
||||
} as UserIdentifier,
|
||||
linkedUser: {
|
||||
uuid: transaction.linkedUserGradidoID,
|
||||
communityUuid: transaction.linkedUserCommunityUuid,
|
||||
} as UserIdentifier,
|
||||
amount: amountString,
|
||||
type: typeString,
|
||||
createdAt: transaction.balanceDate.toISOString(),
|
||||
targetDate: transaction.creationDate?.toISOString(),
|
||||
},
|
||||
}
|
||||
|
||||
const input = this.getTransactionParams(transaction)
|
||||
try {
|
||||
// TODO: add account nr for user after they have also more than one account in backend
|
||||
logger.debug('transmit transaction to dlt connector', params)
|
||||
const {
|
||||
data: { sendTransaction: result },
|
||||
} = await this.client.rawRequest<{ sendTransaction: TransactionResult }>(
|
||||
sendTransaction,
|
||||
params,
|
||||
)
|
||||
if (result.error) {
|
||||
throw new Error(result.error.message)
|
||||
logger.debug('transmit transaction or user to dlt connector', input)
|
||||
if (input instanceof TransactionDraft) {
|
||||
return await this.sendTransaction(input)
|
||||
} else if (input instanceof UserAccountDraft) {
|
||||
return await this.registerAddress(input)
|
||||
} else {
|
||||
throw new LogError('unhandled branch reached')
|
||||
}
|
||||
console.log(result)
|
||||
return result
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
logger.error(e)
|
||||
if (e instanceof FetchError) {
|
||||
throw e
|
||||
} else if (e instanceof Error) {
|
||||
throw new LogError(`from dlt-connector: ${e.message}`)
|
||||
} else {
|
||||
throw new LogError('Exception sending transfer transaction to dlt-connector', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async registerAddress(dbUser: User): Promise<TransactionResult | undefined> {
|
||||
const params = {
|
||||
input: {
|
||||
user: {
|
||||
uuid: dbUser.gradidoID,
|
||||
communityUuid: dbUser.communityUuid,
|
||||
accountNr: 1,
|
||||
} as UserIdentifier,
|
||||
createdAt: dbUser.createdAt.toISOString(),
|
||||
accountType: AccountType.COMMUNITY_HUMAN,
|
||||
} as UserAccountDraft,
|
||||
}
|
||||
try {
|
||||
const {
|
||||
data: { registerAddress: result },
|
||||
} = await this.client.rawRequest<{ registerAddress: TransactionResult }>(
|
||||
registerAddress,
|
||||
params,
|
||||
)
|
||||
logger.info('send register address transaction to dlt-connector', {
|
||||
params,
|
||||
result,
|
||||
})
|
||||
if (result.error) {
|
||||
throw new Error(result.error.message)
|
||||
}
|
||||
return result
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new LogError(`from dlt-connector: ${e.message}`)
|
||||
} else {
|
||||
throw new LogError('Exception sending register address transaction to dlt-connector', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
backend/src/apis/dltConnector/model/TransactionDraft.ts
Executable file
38
backend/src/apis/dltConnector/model/TransactionDraft.ts
Executable file
@ -0,0 +1,38 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
import { Transaction } from '@entity/Transaction'
|
||||
|
||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { UserIdentifier } from './UserIdentifier'
|
||||
|
||||
export class TransactionDraft {
|
||||
user: UserIdentifier
|
||||
linkedUser: UserIdentifier
|
||||
amount: string
|
||||
type: string
|
||||
createdAt: string
|
||||
// only for creation transactions
|
||||
targetDate?: string
|
||||
|
||||
constructor(transaction: Transaction) {
|
||||
if (
|
||||
!transaction.linkedUserGradidoID ||
|
||||
!transaction.linkedUserCommunityUuid ||
|
||||
!transaction.userCommunityUuid
|
||||
) {
|
||||
throw new LogError(
|
||||
`missing necessary field in transaction: ${transaction.id}, need linkedUserGradidoID, linkedUserCommunityUuid and userCommunityUuid`,
|
||||
)
|
||||
}
|
||||
this.user = new UserIdentifier(transaction.userGradidoID, transaction.userCommunityUuid)
|
||||
this.linkedUser = new UserIdentifier(
|
||||
transaction.linkedUserGradidoID,
|
||||
transaction.linkedUserCommunityUuid,
|
||||
)
|
||||
this.amount = transaction.amount.abs().toString()
|
||||
this.type = TransactionTypeId[transaction.typeId]
|
||||
this.createdAt = transaction.balanceDate.toISOString()
|
||||
this.targetDate = transaction.creationDate?.toISOString()
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,17 @@
|
||||
import { User } from '@entity/User'
|
||||
|
||||
import { AccountType } from '@/apis/dltConnector/enum/AccountType'
|
||||
|
||||
import { UserIdentifier } from './UserIdentifier'
|
||||
|
||||
export interface UserAccountDraft {
|
||||
export class UserAccountDraft {
|
||||
user: UserIdentifier
|
||||
createdAt: string
|
||||
accountType: AccountType
|
||||
|
||||
constructor(user: User) {
|
||||
this.user = new UserIdentifier(user.gradidoID, user.communityUuid)
|
||||
this.createdAt = user.createdAt.toISOString()
|
||||
this.accountType = AccountType.COMMUNITY_HUMAN
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
export interface UserIdentifier {
|
||||
export class UserIdentifier {
|
||||
uuid: string
|
||||
communityUuid: string
|
||||
accountNr?: number
|
||||
|
||||
constructor(uuid: string, communityUuid: string, accountNr?: number) {
|
||||
this.uuid = uuid
|
||||
this.communityUuid = communityUuid
|
||||
this.accountNr = accountNr
|
||||
}
|
||||
}
|
||||
|
||||
142
backend/src/apis/dltConnector/sendTransactionsToDltConnector.ts
Normal file
142
backend/src/apis/dltConnector/sendTransactionsToDltConnector.ts
Normal file
@ -0,0 +1,142 @@
|
||||
import { DltTransaction } from '@entity/DltTransaction'
|
||||
import { DltUser } from '@entity/DltUser'
|
||||
import { Transaction } from '@entity/Transaction'
|
||||
import { User } from '@entity/User'
|
||||
// eslint-disable-next-line import/named, n/no-extraneous-import
|
||||
import { FetchError } from 'node-fetch'
|
||||
|
||||
import { DltConnectorClient } from '@dltConnector/DltConnectorClient'
|
||||
|
||||
import { TransactionResult } from '@/apis/dltConnector/model/TransactionResult'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import {
|
||||
InterruptiveSleepManager,
|
||||
TRANSMIT_TO_IOTA_INTERRUPTIVE_SLEEP_KEY,
|
||||
} from '@/util/InterruptiveSleepManager'
|
||||
|
||||
let isLoopRunning = true
|
||||
|
||||
export const stopSendTransactionsToDltConnector = (): void => {
|
||||
isLoopRunning = false
|
||||
}
|
||||
|
||||
function logTransactionResult(
|
||||
type: 'dltUser' | 'dltTransaction',
|
||||
data: { id: number; messageId: string; error: string | null },
|
||||
): void {
|
||||
if (data.error) {
|
||||
logger.error(`Store ${type} with error: id=${data.id}, error=${data.error}`)
|
||||
} else {
|
||||
logger.info(`Store ${type}: messageId=${data.messageId}, id=${data.id}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function saveTransactionResult(
|
||||
pendingTransaction: User | Transaction,
|
||||
messageId: string,
|
||||
error: string | null,
|
||||
): Promise<void> {
|
||||
if (pendingTransaction instanceof User) {
|
||||
const dltUser = DltUser.create()
|
||||
dltUser.userId = pendingTransaction.id
|
||||
dltUser.messageId = messageId
|
||||
dltUser.error = error
|
||||
await DltUser.save(dltUser)
|
||||
logTransactionResult('dltUser', dltUser)
|
||||
} else if (pendingTransaction instanceof Transaction) {
|
||||
const dltTransaction = DltTransaction.create()
|
||||
dltTransaction.transactionId = pendingTransaction.id
|
||||
dltTransaction.messageId = messageId
|
||||
dltTransaction.error = error
|
||||
await DltTransaction.save(dltTransaction)
|
||||
logTransactionResult('dltTransaction', dltTransaction)
|
||||
}
|
||||
}
|
||||
|
||||
async function findNextPendingTransaction(): Promise<Transaction | User | null> {
|
||||
const lastTransactionPromise: Promise<Transaction | null> = Transaction.createQueryBuilder()
|
||||
.leftJoin(DltTransaction, 'dltTransaction', 'Transaction.id = dltTransaction.transactionId')
|
||||
.where('dltTransaction.transaction_id IS NULL')
|
||||
// eslint-disable-next-line camelcase
|
||||
.orderBy({ balance_date: 'ASC', Transaction_id: 'ASC' })
|
||||
.limit(1)
|
||||
.getOne()
|
||||
|
||||
const lastUserPromise: Promise<User | null> = User.createQueryBuilder()
|
||||
.leftJoin(DltUser, 'dltUser', 'User.id = dltUser.userId')
|
||||
.where('dltUser.user_id IS NULL')
|
||||
// eslint-disable-next-line camelcase
|
||||
.orderBy({ User_created_at: 'ASC', User_id: 'ASC' })
|
||||
.limit(1)
|
||||
.getOne()
|
||||
|
||||
const results = await Promise.all([lastTransactionPromise, lastUserPromise])
|
||||
if (results[0] && results[1]) {
|
||||
return results[0].balanceDate < results[1].createdAt ? results[0] : results[1]
|
||||
} else if (results[0]) {
|
||||
return results[0]
|
||||
} else if (results[1]) {
|
||||
return results[1]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async function processPendingTransactions(dltConnector: DltConnectorClient): Promise<void> {
|
||||
let pendingTransaction: Transaction | User | null = null
|
||||
while ((pendingTransaction = await findNextPendingTransaction())) {
|
||||
let result: TransactionResult | undefined
|
||||
let messageId = ''
|
||||
let error: string | null = null
|
||||
|
||||
try {
|
||||
result = await dltConnector.transmitTransaction(pendingTransaction)
|
||||
if (result?.succeed && result.recipe) {
|
||||
messageId = result.recipe.messageIdHex
|
||||
} else {
|
||||
error = 'skipped'
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof FetchError) {
|
||||
throw e
|
||||
}
|
||||
error = e instanceof Error ? e.message : String(e)
|
||||
}
|
||||
|
||||
await saveTransactionResult(pendingTransaction, messageId, error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendTransactionsToDltConnector(): Promise<void> {
|
||||
const dltConnector = DltConnectorClient.getInstance()
|
||||
|
||||
if (!dltConnector) {
|
||||
logger.info('Sending to DltConnector currently not configured...')
|
||||
isLoopRunning = false
|
||||
return
|
||||
}
|
||||
|
||||
logger.info('Starting sendTransactionsToDltConnector task')
|
||||
|
||||
// eslint-disable-next-line no-unmodified-loop-condition
|
||||
while (isLoopRunning) {
|
||||
try {
|
||||
// return after no pending transactions are left
|
||||
await processPendingTransactions(dltConnector)
|
||||
await InterruptiveSleepManager.getInstance().sleep(
|
||||
TRANSMIT_TO_IOTA_INTERRUPTIVE_SLEEP_KEY,
|
||||
1000,
|
||||
)
|
||||
} catch (e) {
|
||||
// couldn't connect to dlt-connector? We wait
|
||||
if (e instanceof FetchError) {
|
||||
logger.error(`error connecting dlt-connector, wait 5 seconds before retry: ${String(e)}`)
|
||||
await InterruptiveSleepManager.getInstance().sleep(
|
||||
TRANSMIT_TO_IOTA_INTERRUPTIVE_SLEEP_KEY,
|
||||
5000,
|
||||
)
|
||||
} else {
|
||||
logger.error(`Error while sending to DLT-connector or writing messageId`, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import { fullName } from '@/util/utilities'
|
||||
import { calculateBalance } from '@/util/validate'
|
||||
|
||||
import { sendTransactionsToDltConnector } from '../../tasks/sendTransactionsToDltConnector'
|
||||
import { sendTransactionsToDltConnector } from '../../apis/dltConnector/sendTransactionsToDltConnector'
|
||||
|
||||
import { executeTransaction } from './TransactionResolver'
|
||||
import { getUserCreation, validateContribution } from './util/creations'
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { CONFIG } from './config'
|
||||
import { startValidateCommunities } from './federation/validateCommunities'
|
||||
import { createServer } from './server/createServer'
|
||||
import { sendTransactionsToDltConnector } from './tasks/sendTransactionsToDltConnector'
|
||||
import { sendTransactionsToDltConnector } from './apis/dltConnector/sendTransactionsToDltConnector'
|
||||
|
||||
async function main() {
|
||||
const { app } = await createServer()
|
||||
|
||||
@ -1,129 +0,0 @@
|
||||
import { DltTransaction } from '@entity/DltTransaction'
|
||||
import { DltUser } from '@entity/DltUser'
|
||||
import { Transaction } from '@entity/Transaction'
|
||||
import { User } from '@entity/User'
|
||||
|
||||
import { DltConnectorClient } from '@dltConnector/DltConnectorClient'
|
||||
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import {
|
||||
InterruptiveSleepManager,
|
||||
TRANSMIT_TO_IOTA_INTERRUPTIVE_SLEEP_KEY,
|
||||
} from '@/util/InterruptiveSleepManager'
|
||||
|
||||
let running = true
|
||||
|
||||
export const stopSendTransactionsToDltConnector = (): void => {
|
||||
running = false
|
||||
}
|
||||
|
||||
export async function sendTransactionsToDltConnector(): Promise<void> {
|
||||
const dltConnector = DltConnectorClient.getInstance()
|
||||
if (!dltConnector) {
|
||||
logger.info('sending to DltConnector currently not configured...')
|
||||
running = false
|
||||
return
|
||||
}
|
||||
logger.info('start sendTransactionsToDltConnector task')
|
||||
|
||||
// eslint-disable-next-line no-unmodified-loop-condition
|
||||
while (running) {
|
||||
try {
|
||||
// loop while work could be found
|
||||
while (true) {
|
||||
const pendingTransaction = await findNextPendingTransaction()
|
||||
if (pendingTransaction instanceof User) {
|
||||
const dltUser = DltUser.create()
|
||||
dltUser.userId = pendingTransaction.id
|
||||
try {
|
||||
const result = await dltConnector.registerAddress(pendingTransaction)
|
||||
if (result?.succeed && result.recipe) {
|
||||
dltUser.messageId = result.recipe.messageIdHex
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
dltUser.error = e.message
|
||||
} else if (typeof e === 'string') {
|
||||
dltUser.error = e
|
||||
}
|
||||
}
|
||||
// wait until saved, necessary before next call to findNextPendingTransaction
|
||||
await DltUser.save(dltUser)
|
||||
if (dltUser.messageId) {
|
||||
logger.info('store dltUser: messageId=%s, id=%d', dltUser.messageId, dltUser.id)
|
||||
} else {
|
||||
logger.error('store dltUser with error: id=%d, error=%s', dltUser.id, dltUser.error)
|
||||
}
|
||||
} else if (pendingTransaction instanceof Transaction) {
|
||||
const dltTransaction = DltTransaction.create()
|
||||
dltTransaction.transactionId = pendingTransaction.id
|
||||
try {
|
||||
const result = await dltConnector.transmitTransaction(pendingTransaction)
|
||||
if (result?.succeed && result.recipe) {
|
||||
dltTransaction.messageId = result.recipe.messageIdHex
|
||||
} else {
|
||||
dltTransaction.error = 'skipped'
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
dltTransaction.error = e.message
|
||||
} else if (typeof e === 'string') {
|
||||
dltTransaction.error = e
|
||||
}
|
||||
}
|
||||
// wait until saved, necessary before next call to findNextPendingTransaction
|
||||
await DltTransaction.save(dltTransaction)
|
||||
if (dltTransaction.messageId) {
|
||||
logger.info(
|
||||
'store dltTransaction: messageId=%s, id=%d',
|
||||
dltTransaction.messageId,
|
||||
dltTransaction.id,
|
||||
)
|
||||
} else {
|
||||
logger.error(
|
||||
'store dltTransaction with error: id=%d, error=%s',
|
||||
dltTransaction.id,
|
||||
dltTransaction.error,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
await InterruptiveSleepManager.getInstance().sleep(
|
||||
TRANSMIT_TO_IOTA_INTERRUPTIVE_SLEEP_KEY,
|
||||
1000,
|
||||
)
|
||||
} catch (e) {
|
||||
logger.error(`error while sending to dlt-connector or writing messageId`, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function findNextPendingTransaction(): Promise<Transaction | User | null> {
|
||||
const lastTransactionPromise: Promise<Transaction | null> = Transaction.createQueryBuilder()
|
||||
.leftJoin(DltTransaction, 'dltTransaction', 'Transaction.id = dltTransaction.transactionId')
|
||||
.where('dltTransaction.transaction_id IS NULL')
|
||||
// eslint-disable-next-line camelcase
|
||||
.orderBy({ balance_date: 'ASC', Transaction_id: 'ASC' })
|
||||
.limit(1)
|
||||
.getOne()
|
||||
|
||||
const lastUserPromise: Promise<User | null> = User.createQueryBuilder()
|
||||
.leftJoin(DltUser, 'dltUser', 'User.id = dltUser.userId')
|
||||
.where('dltUser.user_id IS NULL')
|
||||
// eslint-disable-next-line camelcase
|
||||
.orderBy({ User_created_at: 'ASC', User_id: 'ASC' })
|
||||
.limit(1)
|
||||
.getOne()
|
||||
|
||||
const results = await Promise.all([lastTransactionPromise, lastUserPromise])
|
||||
if (results[0] && results[1]) {
|
||||
return results[0].balanceDate < results[1].createdAt ? results[0] : results[1]
|
||||
} else if (results[0]) {
|
||||
return results[0]
|
||||
} else if (results[1]) {
|
||||
return results[1]
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -1126,6 +1126,14 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node-fetch@^2.6.11":
|
||||
version "2.6.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24"
|
||||
integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^4.0.0"
|
||||
|
||||
"@types/node@*", "@types/node@^16.10.3":
|
||||
version "16.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.3.tgz#7a8f2838603ea314d1d22bb3171d899e15c57bd5"
|
||||
@ -3417,6 +3425,15 @@ form-data@^3.0.0:
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48"
|
||||
integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
import { InputTransactionType } from '@enum/InputTransactionType'
|
||||
import { isValidDateString, isValidNumberString } from '@validator/DateString'
|
||||
import { IsEnum, IsObject, ValidateNested } from 'class-validator'
|
||||
import { InputType, Field } from 'type-graphql'
|
||||
|
||||
import { InputTransactionType } from '@enum/InputTransactionType'
|
||||
import { isValidDateString, isValidNumberString } from '@validator/DateString'
|
||||
|
||||
import { UserIdentifier } from './UserIdentifier'
|
||||
|
||||
@InputType()
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
// https://www.npmjs.com/package/@apollo/protobufjs
|
||||
|
||||
import { isValidDateString } from '@validator/DateString'
|
||||
import { IsEnum, IsObject, ValidateNested } from 'class-validator'
|
||||
import { InputType, Field } from 'type-graphql'
|
||||
|
||||
import { isValidDateString } from '@validator/DateString'
|
||||
|
||||
import { AccountType } from '@/graphql/enum/AccountType'
|
||||
|
||||
import { UserIdentifier } from './UserIdentifier'
|
||||
|
||||
@ -19,7 +19,7 @@ export class TransactionResult {
|
||||
@Field(() => TransactionError, { nullable: true })
|
||||
error?: TransactionError
|
||||
|
||||
// if no error happend, the message id of the iota transaction
|
||||
// if no error happened, the message id of the iota transaction
|
||||
@Field(() => TransactionRecipe, { nullable: true })
|
||||
recipe?: TransactionRecipe
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { TransactionDraft } from '@input/TransactionDraft'
|
||||
import { Resolver, Arg, Mutation } from 'type-graphql'
|
||||
|
||||
import { TransactionDraft } from '@input/TransactionDraft'
|
||||
|
||||
import { SendToIotaContext } from '@/interactions/sendToIota/SendToIota.context'
|
||||
|
||||
import { TransactionError } from '../model/TransactionError'
|
||||
|
||||
@ -38,4 +38,4 @@ export function isValidNumberString(validationOptions?: ValidationOptions) {
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import { UserKeyPairRole } from './UserKeyPair.role'
|
||||
|
||||
/**
|
||||
* @DCI-Context
|
||||
* Context for calculating key pair for signing transactions
|
||||
* Context for calculating key pair for signing transactions
|
||||
*/
|
||||
export async function KeyPairCalculation(input: UserIdentifier | string): Promise<KeyPairEd25519> {
|
||||
const cache = KeyPairCacheManager.getInstance()
|
||||
|
||||
@ -1082,7 +1082,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690"
|
||||
integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==
|
||||
|
||||
"@types/node-fetch@^2.6.1":
|
||||
"@types/node-fetch@^2.6.1", "@types/node-fetch@^2.6.11":
|
||||
version "2.6.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24"
|
||||
integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==
|
||||
@ -2112,6 +2112,11 @@ cssstyle@^2.3.0:
|
||||
dependencies:
|
||||
cssom "~0.3.6"
|
||||
|
||||
data-uri-to-buffer@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
|
||||
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
|
||||
|
||||
data-urls@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
|
||||
@ -2931,6 +2936,14 @@ fb-watchman@^2.0.0:
|
||||
dependencies:
|
||||
bser "2.1.1"
|
||||
|
||||
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
|
||||
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
|
||||
dependencies:
|
||||
node-domexception "^1.0.0"
|
||||
web-streams-polyfill "^3.0.3"
|
||||
|
||||
figures@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
|
||||
@ -3050,6 +3063,13 @@ form-data@^4.0.0:
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
formdata-polyfill@^4.0.10:
|
||||
version "4.0.10"
|
||||
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
|
||||
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
|
||||
dependencies:
|
||||
fetch-blob "^3.1.2"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
@ -4670,6 +4690,11 @@ node-api-headers@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-1.3.0.tgz#bb32c6b3e33fb0004bd93c66787bf00998c834ea"
|
||||
integrity sha512-8Bviwtw4jNhv0B2qDjj4M5e6GyAuGtxsmZTrFJu3S3Z0+oHwIgSUdIKkKJmZd+EbMo7g3v4PLBbrjxwmZOqMBg==
|
||||
|
||||
node-domexception@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
|
||||
|
||||
node-fetch@^2.6.12, node-fetch@^2.6.7:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
@ -4677,6 +4702,15 @@ node-fetch@^2.6.12, node-fetch@^2.6.7:
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-fetch@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b"
|
||||
integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==
|
||||
dependencies:
|
||||
data-uri-to-buffer "^4.0.0"
|
||||
fetch-blob "^3.1.4"
|
||||
formdata-polyfill "^4.0.10"
|
||||
|
||||
node-gyp-build@^4.8.1:
|
||||
version "4.8.2"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa"
|
||||
@ -6265,6 +6299,11 @@ walker@^1.0.7:
|
||||
dependencies:
|
||||
makeerror "1.0.12"
|
||||
|
||||
web-streams-polyfill@^3.0.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
|
||||
integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user