Merge pull request #3537 from gradido/3536-feature-modify-frontend-for-cross-community-redeem-link-disbursement

feat(frontend): modify frontend for cross community redeem link disbursement
This commit is contained in:
clauspeterhuebner 2025-09-22 22:30:04 +02:00 committed by GitHub
commit 097fcd7103
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 155 additions and 84 deletions

View File

@ -4,6 +4,7 @@ import {
Community as DbCommunity,
FederatedCommunity as DbFederatedCommunity,
PendingTransaction as DbPendingTransaction,
TransactionLink as DbTransactionLink,
User as dbUser,
findTransactionLinkByCode,
findUserByIdentifier,
@ -16,21 +17,22 @@ import { Decimal } from 'decimal.js-light'
import { CONFIG as CONFIG_CORE } from '../../config'
import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const'
import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared'
import { SendCoinsClient as V1_0_SendCoinsClient } from '../../federation/client/1_0/SendCoinsClient'
import { SendCoinsResult } from '../../federation/client/1_0/model/SendCoinsResult'
import { SendCoinsClientFactory } from '../../federation/client/SendCoinsClientFactory'
import { TransactionTypeId } from '../../graphql/enum/TransactionTypeId'
import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared'
// import { LogError } from '@server/LogError'
import { getLogger } from 'log4js'
import { calculateSenderBalance } from '../../util/calculateSenderBalance'
import { fullName } from '../../util/utilities'
import { getLogger } from 'log4js'
import { randombytes_random } from 'sodium-native'
import { SendCoinsResultLoggingView } from '../../federation/client/1_0/logging/SendCoinsResultLogging.view'
import { EncryptedTransferArgs } from '../../graphql/model/EncryptedTransferArgs'
import { randombytes_random } from 'sodium-native'
import { settlePendingSenderTransaction } from './settlePendingSenderTransaction'
import { storeForeignUser } from './storeForeignUser'
import { storeLinkAsRedeemed } from './storeLinkAsRedeemed'
const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.util.processXComSendCoins.${method}`)
@ -79,9 +81,10 @@ export async function processXComCompleteTransaction(
methodLogger.error(errmsg)
throw new Error(errmsg)
}
let dbTransactionLink: DbTransactionLink | null = null
if(code !== undefined) {
try {
const dbTransactionLink = await findTransactionLinkByCode(code)
dbTransactionLink = await findTransactionLinkByCode(code)
if (dbTransactionLink && dbTransactionLink.validUntil < new Date()) {
const errmsg = `TransactionLink ${code} is expired!`
methodLogger.error(errmsg)
@ -108,6 +111,7 @@ export async function processXComCompleteTransaction(
memo,
senderUser,
recipientGradidoId,
dbTransactionLink?.id,
)
methodLogger.debug('processXComPendingSendCoins result: ', pendingResult)
if (pendingResult && pendingResult.vote && pendingResult.recipGradidoID) {
@ -120,6 +124,7 @@ export async function processXComCompleteTransaction(
memo,
senderUser,
pendingResult,
dbTransactionLink?.id,
)
methodLogger.debug('processXComCommittingSendCoins result: ', committingResult)
if (!committingResult.vote) {
@ -134,14 +139,31 @@ export async function processXComCompleteTransaction(
}
// after successful x-com-tx store the recipient as foreign user
methodLogger.debug('store recipient as foreign user...')
if (await storeForeignUser(recipientCom, committingResult)) {
const foreignUser = await storeForeignUser(recipientCom, committingResult)
if (foreignUser) {
methodLogger.info(
'X-Com: new foreign user inserted successfully...',
recipientCom.communityUuid,
committingResult.recipGradidoID,
)
} else {
const errmsg = `X-Com: Error storing foreign user for ${recipientCom.communityUuid} ${committingResult.recipGradidoID}`
methodLogger.error(errmsg)
throw new Error(errmsg)
}
}
if(dbTransactionLink !== null) {
// after successful x-com-tx per link store the link as redeemed
methodLogger.debug('store link as redeemed...')
if (await storeLinkAsRedeemed(dbTransactionLink, foreignUser!, creationDate)) {
methodLogger.info(
'X-Com: store link as redeemed successfully...',
dbTransactionLink.code,
foreignUser!.id,
creationDate,
)
}
}
}
} catch (err) {
const errmsg = `ERROR: on processXComCommittingSendCoins with ` +
recipientCommunityUuid +
@ -163,6 +185,7 @@ export async function processXComPendingSendCoins(
memo: string,
sender: dbUser,
recipientIdentifier: string,
transactionLinkId?: number,
): Promise<SendCoinsResponseJwtPayloadType | null> {
let voteResult: SendCoinsResponseJwtPayloadType
const methodLogger = createLogger(`processXComPendingSendCoins`)
@ -176,7 +199,8 @@ export async function processXComPendingSendCoins(
amount: amount.toString(),
memo: memo.substring(0, 5),
sender: new UserLoggingView(sender),
recipientIdentifier
recipientIdentifier,
transactionLinkId
}
)
}
@ -216,7 +240,8 @@ export async function processXComPendingSendCoins(
senderCom.communityUuid!,
sender.gradidoID,
fullName(sender.firstName, sender.lastName),
sender.alias
sender.alias,
transactionLinkId
)
if(methodLogger.isDebugEnabled()) {
methodLogger.debug(`ready for voteForSendCoins with payload=${payload}`)
@ -277,6 +302,7 @@ export async function processXComPendingSendCoins(
pendingTx.userId = sender.id
pendingTx.userGradidoID = sender.gradidoID
pendingTx.userName = fullName(sender.firstName, sender.lastName)
pendingTx.transactionLinkId = transactionLinkId
if(methodLogger.isDebugEnabled()) {
methodLogger.debug(`initialized sender pendingTX=${new PendingTransactionLoggingView(pendingTx)}`)
}
@ -326,6 +352,7 @@ export async function processXComCommittingSendCoins(
memo: string,
sender: dbUser,
recipient: SendCoinsResult,
transactionLinkId?: number,
): Promise<SendCoinsResult> {
const methodLogger = createLogger(`processXComCommittingSendCoins`)
const handshakeID = randombytes_random().toString()
@ -342,6 +369,7 @@ export async function processXComCommittingSendCoins(
memo: memo.substring(0, 5),
sender: new UserLoggingView(sender),
recipient: new SendCoinsResultLoggingView(recipient),
transactionLinkId,
}
)
}
@ -384,6 +412,7 @@ export async function processXComCommittingSendCoins(
pendingTx.userGradidoID!,
pendingTx.userName!,
sender.alias,
pendingTx.transactionLinkId,
)
payload.recipientCommunityUuid = pendingTx.linkedUserCommunityUuid
? pendingTx.linkedUserCommunityUuid

View File

@ -92,7 +92,7 @@ export async function settlePendingSenderTransaction(
transactionSend.decay = sendBalance.decay.decay // pendingTx.decay
transactionSend.decayStart = sendBalance.decay.start // pendingTx.decayStart
transactionSend.previous = pendingTx.previous
transactionSend.linkedTransactionId = pendingTx.linkedTransactionId
transactionSend.transactionLinkId = pendingTx.transactionLinkId
await queryRunner.manager.insert(dbTransaction, transactionSend)
logger.debug(`send Transaction inserted: ${transactionSend}`)

View File

@ -9,7 +9,7 @@ const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.logic.storeForeig
export async function storeForeignUser(
recipCom: DbCommunity,
committingResult: SendCoinsResult,
): Promise<boolean> {
): Promise<DbUser | null> {
if (recipCom.communityUuid !== null && committingResult.recipGradidoID !== null) {
try {
const user = await findForeignUserByUuids(recipCom.communityUuid, committingResult.recipGradidoID)
@ -35,7 +35,7 @@ export async function storeForeignUser(
foreignUser = await DbUser.save(foreignUser)
logger.debug('new foreignUser inserted:', foreignUser)
return true
return foreignUser
} else if (
user.firstName !== committingResult.recipFirstName ||
user.lastName !== committingResult.recipLastName ||
@ -57,15 +57,15 @@ export async function storeForeignUser(
}
await DbUser.save(user)
logger.debug('update recipient successful.', user)
return true
return user
} else {
logger.debug('foreignUser still exists...:', user)
return true
return user
}
} catch (err) {
logger.error('error in storeForeignUser;', err)
return false
return null
}
}
return false
return null
}

View File

@ -0,0 +1,17 @@
import { TransactionLink as DbTransactionLink, User as DbUser } from "database";
export async function storeLinkAsRedeemed(
dbTransactionLink: DbTransactionLink,
foreignUser: DbUser,
creationDate: Date,
): Promise<boolean> {
try {
dbTransactionLink.redeemedBy = foreignUser.id
dbTransactionLink.redeemedAt = creationDate
await DbTransactionLink.save(dbTransactionLink)
return true
} catch (err) {
console.error('error in storeLinkAsRedeemed;', err)
return false
}
}

View File

@ -104,6 +104,7 @@ export class SendCoinsResolver {
pendingTx.userCommunityUuid = authArgs.recipientCommunityUuid
pendingTx.userGradidoID = receiverUser.gradidoID
pendingTx.userName = fullName(receiverUser.firstName, receiverUser.lastName)
pendingTx.transactionLinkId = authArgs.transactionLinkId
await DbPendingTransaction.insert(pendingTx)
const responseArgs = new SendCoinsResponseJwtPayloadType(

View File

@ -92,6 +92,7 @@ export async function settlePendingReceiveTransaction(
transactionReceive.decayStart = receiveBalance ? receiveBalance.decay.start : null
transactionReceive.previous = receiveBalance ? receiveBalance.lastTransactionId : null
transactionReceive.linkedTransactionId = pendingTx.linkedTransactionId
transactionReceive.transactionLinkId = pendingTx.transactionLinkId
await queryRunner.manager.insert(dbTransaction, transactionReceive)
logger.debug(`receive Transaction inserted: ${new TransactionLoggingView(transactionReceive)}`)

View File

@ -6,15 +6,30 @@
:is-redeem-jwt-link="isRedeemJwtLink"
class="redeem-community-selection"
>
<BCard bg-variant="muted" text-variant="dark" border-variant="info">
<BRow bg-variant="muted" text-variant="dark">
<h1 v-if="linkData.amount === ''">{{ $t('gdd_per_link.redeemlink-error') }}</h1>
<h1 v-if="!isContributionLink && linkData.amount !== ''">
<template v-if="linkData.senderUser">
{{ linkData.senderUser.firstName }}
{{ $t('transaction-link.send_you') }} {{ linkData.amount }} {{ $t('GDD-long') }}
</template>
</h1>
<BRow>
<BCol class="mb-4" cols="12">
<b>{{ linkData.memo }}</b>
</BCol>
</BRow>
<BRow v-if="!isContributionLink && linkData.amount !== ''">
<BCol class="mb-4" cols="12">
<BRow>
<BCol v-if="!isRedeemJwtLink">
{{ $t('gdd_per_link.recipientCommunitySelection') }}
<BCol v-if="!isRedeemJwtLink" class="fw-bold">
<div v-if="isForeignCommunitySelected">
{{ $t('gdd_per_link.recipientCommunityRedirection') }}
</div>
<div v-else>
{{ $t('gdd_per_link.recipientCommunitySelection') }}
</div>
</BCol>
<BCol v-else>{{ $t('gdd_per_link.recipientCommunityFix') }}</BCol>
</BRow>
<h3>
<BRow>
@ -25,11 +40,7 @@
@update:model-value="setRecipientCommunity"
/>
</BCol>
<BCol v-else>
{{ currentRecipientCommunity.name }}
</BCol>
<BCol v-if="isForeignCommunitySelected" sm="12" md="6" class="mt-4 mt-lg-0">
<p>{{ $t('gdd_per_link.switchCommunity') }}</p>
<BButton variant="gradido" @click="onSwitch">
{{ $t('gdd_per_link.to-switch') }}
</BButton>
@ -37,13 +48,8 @@
</BRow>
</h3>
</BCol>
<template v-if="linkData.senderUser">
{{ linkData.senderUser.firstName }}
{{ $t('transaction-link.send_you') }} {{ $filters.GDD(linkData.amount) }}
</template>
</h1>
<b>{{ linkData.memo }}</b>
</BCard>
</BRow>
</BRow>
</div>
</template>
<script setup>
@ -142,16 +148,16 @@ async function onSwitch(event) {
// console.log('RedeemCommunitySelection.onSwitch... props=', props)
if (isForeignCommunitySelected.value) {
// console.log('RedeemCommunitySelection.onSwitch vor createRedeemJwt params:', {
// gradidoId: props.linkData.senderUser?.gradidoID,
// senderCommunityUuid: senderCommunity.value.uuid,
// senderCommunityName: senderCommunity.value.name,
// recipientCommunityUuid: currentRecipientCommunity.value.uuid,
// code: props.redeemCode,
// amount: props.linkData.amount,
// memo: props.linkData.memo,
// firstName: props.linkData.senderUser?.firstName,
// alias: props.linkData.senderUser?.alias,
// validUntil: props.linkData.validUntil,
// gradidoId: props.linkData.senderUser?.gradidoID,
// senderCommunityUuid: senderCommunity.value.uuid,
// senderCommunityName: senderCommunity.value.name,
// recipientCommunityUuid: currentRecipientCommunity.value.uuid,
// code: props.redeemCode,
// amount: props.linkData.amount,
// memo: props.linkData.memo,
// firstName: props.linkData.senderUser?.firstName,
// alias: props.linkData.senderUser?.alias,
// validUntil: props.linkData.validUntil,
// })
// eslint-disable-next-line no-useless-catch
try {

View File

@ -1,41 +1,31 @@
<template>
<div class="redeem-select-community">
<redeem-community-selection
v-model:recipient-community="recipientCommunity"
:link-data="props.linkData"
:redeem-code="props.redeemCode"
:is-transaction-link-loaded="props.isTransactionLinkLoaded"
:is-contribution-link="props.isContributionLink"
:is-redeem-jwt-link="props.isRedeemJwtLink"
/>
<BCard v-if="props.isTransactionLinkLoaded">
<div class="mb-2">
<h2>{{ $t('gdd_per_link.redeem') }}</h2>
<redeem-community-selection
v-model:recipient-community="recipientCommunity"
:link-data="props.linkData"
:redeem-code="props.redeemCode"
:is-transaction-link-loaded="props.isTransactionLinkLoaded"
:is-contribution-link="props.isContributionLink"
:is-redeem-jwt-link="props.isRedeemJwtLink"
/>
<div v-if="!isForeignCommunitySelected">
<h2>{{ $t('gdd_per_link.redeem-community') }} {{ recipientCommunity.name }}</h2>
<BRow>
<BCol sm="12" md="6">
<p>{{ $t('gdd_per_link.no-account') }}</p>
<BButton variant="primary" :to="routeWithParamsAndQuery('Register')">
{{ $t('gdd_per_link.to-register') }}
</BButton>
</BCol>
<BCol sm="12" md="6" class="mt-4 mt-lg-0">
<p>{{ $t('gdd_per_link.has-account') }}</p>
<BButton variant="gradido" :to="routeWithParamsAndQuery('Login')">
{{ $t('gdd_per_link.to-login') }}
</BButton>
</BCol>
</BRow>
</div>
<BRow>
<BCol sm="12" md="6">
<p>{{ $t('gdd_per_link.no-account') }}</p>
<BButton
variant="primary"
:disabled="isForeignCommunitySelected"
:to="routeWithParamsAndQuery('Register')"
>
{{ $t('gdd_per_link.to-register') }}
</BButton>
</BCol>
<BCol sm="12" md="6" class="mt-4 mt-lg-0">
<p>{{ $t('gdd_per_link.has-account') }}</p>
<BButton
variant="gradido"
:disabled="isForeignCommunitySelected"
:to="routeWithParamsAndQuery('Login')"
>
{{ $t('gdd_per_link.to-login') }}
</BButton>
</BCol>
</BRow>
</BCard>
</div>
</template>

View File

@ -7,6 +7,7 @@
"85": "85%",
"Chat": "Chat",
"GDD": "GDD",
"GDD-long": "Gradido",
"GDT": "GDT",
"GMS": {
"title": "Geo Matching System GMS (in Entwicklung)",
@ -271,16 +272,16 @@
"no-account": "Du besitzt noch kein Gradido Konto?",
"no-redeem": "Du darfst deinen eigenen Link nicht einlösen!",
"not-copied": "Dein Gerät lässt das Kopieren leider nicht zu! Bitte kopiere den Link von Hand!",
"recipientCommunityFix": "Empfänger-Gemeinschaft des Link-Guthabens...",
"recipientCommunitySelection": "Wähle deine Gemeinschaft zum Einlösen des Link-Guthabens...",
"recipientCommunityRedirection": "Zum Gutschreiben weiterleiten zu:",
"recipientCommunitySelection": "Gradido-Gemeinschaft wählen:",
"redeem": "Einlösen",
"redeem-community": "Gutschreiben in ",
"redeemed": "Erfolgreich eingelöst! Deinem Konto wurden {n} GDD gutgeschrieben.",
"redeemed-at": "Der Link wurde bereits am {date} eingelöst.",
"redeemlink-error": "Dieser Einlöse-Link ist nicht vollständig.",
"switchCommunity": "Du hast eine andere Gemeinschaft ausgewählt...",
"to-login": "Log dich ein",
"to-register": "Registriere ein neues Konto.",
"to-switch": "Wechsle zur Gemeinschaft",
"to-switch": "Jetzt weiterleiten",
"validUntil": "Gültig bis",
"validUntilDate": "Der Link ist bis zum {date} gültig."
},

View File

@ -7,6 +7,7 @@
"85": "85%",
"Chat": "Chat",
"GDD": "GDD",
"GDD-long": "Gradido",
"GDT": "GDT",
"GMS": {
"title": "Geo Matching System GMS (in develop)",
@ -271,16 +272,16 @@
"no-account": "You don't have a Gradido account yet?",
"no-redeem": "You not allowed to redeem your own link!",
"not-copied": "Unfortunately, your device does not allow copying! Please copy the link by hand!",
"recipientCommunityFix": "Recipient Community of the Link-Balance...",
"recipientCommunitySelection": "Select your Community to redeem the link-deposit...",
"recipientCommunityRedirection": "Redirect for crediting to:",
"recipientCommunitySelection": "Select Gradido community:",
"redeem": "Redeem",
"redeem-community": "Credit in ",
"redeemed": "Successfully redeemed! Your account has been credited with {n} GDD.",
"redeemed-at": "The link was already redeemed on {date}.",
"redeemlink-error": "This redemption link is not complete.",
"switchCommunity": "You have selected a foreign Community...",
"to-login": "Log in",
"to-register": "Register a new account.",
"to-switch": "Switch to Community",
"to-switch": "Redirect now",
"validUntil": "Valid until",
"validUntilDate": "The link is valid until {date}."
},

View File

@ -216,12 +216,16 @@
"no-account": "Aún no tienes una cuenta de Gradido?",
"no-redeem": "No puedes canjear tu propio enlace!",
"not-copied": "¡Desafortunadamente, su dispositivo no permite copiar! Copie el enlace manualmente!",
"recipientCommunityRedirection": "Redirigir para abonar a:",
"recipientCommunitySelection": "Seleccionar comunidad Gradido:",
"redeem": "Canjear",
"redeem-community": "Acreditar en ",
"redeemed": "¡Canjeado con éxito! Tu cuenta ha sido acreditada con {n} GDD.",
"redeemed-at": "El enlace ya se canjeó el {date}.",
"redeemed-title": "canjeado",
"to-login": "iniciar sesión",
"to-register": "Registre una nueva cuenta.",
"to-switch": "Redirigir ahora",
"validUntil": "Válido hasta",
"validUntilDate": "El enlace es válido hasta el {date} ."
},

View File

@ -222,12 +222,16 @@
"no-account": "Vous n'avez pas encore de compte Gradido?",
"no-redeem": "Vous n'êtes pas autorisé à percevoir votre propre lien!",
"not-copied": "Malheureusement votre appareil ne permet pas de copier! Veuillez copier le lien manuellement svp!",
"recipientCommunityRedirection": "Pour créditer, rediriger vers:",
"recipientCommunitySelection": "Choisir la communauté Gradido :",
"redeem": "Encaisser",
"redeem-community": "Créditer dans ",
"redeemed": "Encaissé avec succès! Votre compte est crédité de {n} GDD.",
"redeemed-at": "Le lien a déjà été perçu le {date}.",
"redeemed-title": "encaisser",
"to-login": "Connexion",
"to-register": "Enregistrer un nouveau compte.",
"to-switch": "Rediriger maintenant",
"validUntil": "Valide jusqu'au",
"validUntilDate": "Le lien est valide jusqu'au {date}."
},

View File

@ -216,12 +216,16 @@
"no-account": "Je hebt nog geen Gradido rekening?",
"no-redeem": "Je mag je eigen link niet inwisselen!",
"not-copied": "Jouw apparaat laat het kopiëren helaas niet toe! Kopieer de link alsjeblieft met de hand!",
"recipientCommunityRedirection": "Naar crediteren doorsturen naar:",
"recipientCommunitySelection": "Gradido-gemeenschap selecteren:",
"redeem": "Inwisselen",
"redeem-community": "Crediteren in ",
"redeemed": "Succesvol ingewisseld! Op jouw rekening werden {n} GDD bijgeschreven.",
"redeemed-at": "De link werd al op {date} ingewisseld.",
"redeemed-title": "ingewisseld",
"to-login": "Inloggen",
"to-register": "Registreer een nieuwe rekening.",
"to-switch": "Nu doorsturen",
"validUntil": "Geldig tot",
"validUntilDate": "De link is geldig tot {date}."
},

View File

@ -164,10 +164,15 @@ const itemType = computed(() => {
}
if (store.state.token && store.state.tokenTime) {
if (tokenExpiresInSeconds.value < 5) {
// console.log('TransactionLink.itemType... REDEEM_SELECT_COMMUNITY')
// console.log(
// 'TransactionLink.itemType... CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE=',
// CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE,
// )
if (CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE) {
// console.log('TransactionLink.itemType... REDEEM_SELECT_COMMUNITY')
return 'REDEEM_SELECT_COMMUNITY'
} else {
// console.log('TransactionLink.itemType... LOGGED_OUT')
return 'LOGGED_OUT'
}
}
@ -216,10 +221,15 @@ const itemType = computed(() => {
return 'VALID'
}
}
// console.log(
// 'TransactionLink.itemType... vor last return CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE=',
// CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE,
// )
if (CONFIG.CROSS_TX_REDEEM_LINK_ACTIVE) {
// console.log('TransactionLink.itemType...last return= REDEEM_SELECT_COMMUNITY')
return 'REDEEM_SELECT_COMMUNITY'
} else {
// console.log('TransactionLink.itemType... last return= LOGGED_OUT')
return 'LOGGED_OUT'
}
})
@ -338,7 +348,7 @@ function setRedeemJwtLinkInformation() {
const deepCopy = JSON.parse(JSON.stringify(result.value))
// console.log('TransactionLink.setRedeemJwtLinkInformation... deepCopy=', deepCopy)
if (deepCopy) {
// recipientUser is only set if the user is logged in
// console.log('TransactionLink.setRedeemJwtLinkInformation... recipientUser is only set if the user is logged in')
if (store.state.gradidoID !== null) {
// console.log('TransactionLink.setRedeemJwtLinkInformation... gradidoID=', store.state.gradidoID)
deepCopy.queryTransactionLink.recipientUser = {

View File

@ -13,6 +13,7 @@ export class SendCoinsJwtPayloadType extends JwtPayloadType {
senderUserUuid: string
senderUserName: string
senderAlias?: string | null
transactionLinkId?: number | null
constructor(
handshakeID: string,
@ -25,6 +26,7 @@ export class SendCoinsJwtPayloadType extends JwtPayloadType {
senderUserUuid: string,
senderUserName: string,
senderAlias?: string | null,
transactionLinkId?: number | null,
) {
super(handshakeID)
this.tokentype = SendCoinsJwtPayloadType.SEND_COINS_TYPE
@ -37,5 +39,6 @@ export class SendCoinsJwtPayloadType extends JwtPayloadType {
this.senderUserUuid = senderUserUuid
this.senderUserName = senderUserName
this.senderAlias = senderAlias
this.transactionLinkId = transactionLinkId
}
}