changes to distingue between redeemJWT and disburseJWT

This commit is contained in:
clauspeterhuebner 2025-04-25 19:19:17 +02:00
parent 6241058027
commit c2294611bd
15 changed files with 282 additions and 81 deletions

View File

@ -25,6 +25,7 @@ export enum RIGHTS {
CREATE_TRANSACTION_LINK = 'CREATE_TRANSACTION_LINK',
DELETE_TRANSACTION_LINK = 'DELETE_TRANSACTION_LINK',
REDEEM_TRANSACTION_LINK = 'REDEEM_TRANSACTION_LINK',
DISBURSE_TRANSACTION_LINK = 'DISBURSE_TRANSACTION_LINK',
LIST_TRANSACTION_LINKS = 'LIST_TRANSACTION_LINKS',
GDT_BALANCE = 'GDT_BALANCE',
CREATE_CONTRIBUTION = 'CREATE_CONTRIBUTION',

View File

@ -15,6 +15,7 @@ export const USER_RIGHTS = [
RIGHTS.CREATE_TRANSACTION_LINK,
RIGHTS.DELETE_TRANSACTION_LINK,
RIGHTS.REDEEM_TRANSACTION_LINK,
RIGHTS.DISBURSE_TRANSACTION_LINK,
RIGHTS.LIST_TRANSACTION_LINKS,
RIGHTS.GDT_BALANCE,
RIGHTS.CREATE_CONTRIBUTION,

View File

@ -0,0 +1,48 @@
// import { JWTPayload } from 'jose'
import { JwtPayloadType } from './JwtPayloadType'
export class DisburseJwtPayloadType extends JwtPayloadType {
static DISBURSE_ACTIVATION_TYPE = 'disburse-activation'
sendercommunityuuid: string
sendergradidoid: string
recipientcommunityuuid: string
recipientcommunityname: string
recipientgradidoid: string
recipientfirstname: string
code: string
amount: string
memo: string
validuntil: string
recipientalias: string
constructor(
senderCommunityUuid: string,
senderGradidoId: string,
recipientCommunityUuid: string,
recipientCommunityName: string,
recipientGradidoId: string,
recipientFirstName: string,
code: string,
amount: string,
memo: string,
validUntil: string,
recipientAlias: string,
) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
super()
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
this.tokentype = DisburseJwtPayloadType.DISBURSE_ACTIVATION_TYPE
this.sendercommunityuuid = senderCommunityUuid
this.sendergradidoid = senderGradidoId
this.recipientcommunityuuid = recipientCommunityUuid
this.recipientcommunityname = recipientCommunityName
this.recipientgradidoid = recipientGradidoId
this.recipientfirstname = recipientFirstName
this.code = code
this.amount = amount
this.memo = memo
this.validuntil = validUntil
this.recipientalias = recipientAlias
}
}

View File

@ -1,7 +1,7 @@
// import { JWTPayload } from 'jose'
import { JwtPayloadType } from './JwtPayloadType'
export class DisbursementJwtPayloadType extends JwtPayloadType {
export class RedeemJwtPayloadType extends JwtPayloadType {
static REDEEM_ACTIVATION_TYPE = 'redeem-activation'
sendercommunityuuid: string
@ -24,7 +24,7 @@ export class DisbursementJwtPayloadType extends JwtPayloadType {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
super()
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
this.tokentype = DisbursementJwtPayloadType.REDEEM_ACTIVATION_TYPE
this.tokentype = RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE
this.sendercommunityuuid = senderCom
this.sendergradidoid = senderUser
this.sendername = sendername

View File

@ -1,15 +1,15 @@
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field } from 'type-graphql'
import { DisbursementJwtPayloadType } from '@/auth/jwt/payloadtypes/DisbursementJwtPayloadType'
import { RedeemJwtPayloadType } from '@/auth/jwt/payloadtypes/RedeemJwtPayloadType'
import { Community } from './Community'
import { User } from './User'
@ObjectType()
export class DisbursementLink {
export class RedeemJwtLink {
constructor(
disbursementPayload: DisbursementJwtPayloadType,
redeemJwtPayload: RedeemJwtPayloadType,
senderCommunity: Community,
senderUser: User,
recipientCommunity: Community,
@ -23,10 +23,10 @@ export class DisbursementLink {
} else {
this.recipientUser = null
}
this.amount = new Decimal(disbursementPayload.amount)
this.memo = disbursementPayload.memo
this.code = disbursementPayload.redeemcode
this.validUntil = new Date(disbursementPayload.validuntil)
this.amount = new Decimal(redeemJwtPayload.amount)
this.memo = redeemJwtPayload.memo
this.code = redeemJwtPayload.redeemcode
this.validUntil = new Date(redeemJwtPayload.validuntil)
}
@Field(() => Community)

View File

@ -20,13 +20,13 @@ import { TransactionTypeId } from '@enum/TransactionTypeId'
import { Community } from '@model/Community'
import { ContributionLink } from '@model/ContributionLink'
import { Decay } from '@model/Decay'
import { DisbursementLink } from '@model/DisbursementLink'
import { RedeemJwtLink } from '@model/RedeemJwtLink'
import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink'
import { User } from '@model/User'
import { QueryLinkResult } from '@union/QueryLinkResult'
import { verify, encode, decode } from '@/auth/jwt/JWT'
import { DisbursementJwtPayloadType } from '@/auth/jwt/payloadtypes/DisbursementJwtPayloadType'
import { RedeemJwtPayloadType } from '@/auth/jwt/payloadtypes/RedeemJwtPayloadType'
import { RIGHTS } from '@/auth/RIGHTS'
import {
EVENT_CONTRIBUTION_LINK_REDEEM,
@ -54,6 +54,7 @@ import { getUserCreation, validateContribution } from './util/creations'
import { getLastTransaction } from './util/getLastTransaction'
import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector'
import { transactionLinkList } from './util/transactionLinkList'
import { DisburseJwtPayloadType } from '@/auth/jwt/payloadtypes/DisburseJwtPayloadType'
// TODO: do not export, test it inside the resolver
export const transactionLinkCode = (date: Date): string => {
@ -182,8 +183,8 @@ export class TransactionLinkResolver {
const communities = await getAuthenticatedCommunities()
return new TransactionLink(dbTransactionLink, new User(user), redeemedBy, communities)
} else {
// disbursement jwt-token
return await this.queryDisbursementLink(code)
// redeem jwt-token
return await this.queryRedeemJwtLink(code)
}
}
}
@ -396,7 +397,7 @@ export class TransactionLinkResolver {
@Authorized([RIGHTS.QUERY_REDEEM_JWT])
@Mutation(() => String)
async createRedeemJwt(
@Arg('gradidoID') gradidoID: string,
@Arg('gradidoId') gradidoId: string,
@Arg('senderCommunityUuid') senderCommunityUuid: string,
@Arg('senderCommunityName') senderCommunityName: string,
@Arg('receiverCommunityUuid') receiverCommunityUuid: string,
@ -408,7 +409,7 @@ export class TransactionLinkResolver {
@Arg('validUntil', { nullable: true }) validUntil?: string,
): Promise<string> {
logger.debug('TransactionLinkResolver.queryRedeemJwt... args=', {
gradidoID,
gradidoId,
senderCommunityUuid,
senderCommunityName,
receiverCommunityUuid,
@ -420,9 +421,9 @@ export class TransactionLinkResolver {
validUntil,
})
const disbursementJwtPayloadType = new DisbursementJwtPayloadType(
const redeemJwtPayloadType = new RedeemJwtPayloadType(
senderCommunityUuid,
gradidoID,
gradidoId,
alias ?? firstName ?? '',
code,
amount,
@ -434,11 +435,63 @@ export class TransactionLinkResolver {
if (!homeCom.communityUuid) {
throw new LogError('Home community UUID is not set')
}
const redeemJwt = await encode(disbursementJwtPayloadType, homeCom.communityUuid)
const redeemJwt = await encode(redeemJwtPayloadType, homeCom.communityUuid)
// TODO: encrypt the payload with the public key of the target community
return redeemJwt
}
@Authorized([RIGHTS.DISBURSE_TRANSACTION_LINK])
@Mutation(() => Boolean)
async disburseTransactionLink(
@Ctx() context: Context,
@Arg('senderCommunityUuid') senderCommunityUuid: string,
@Arg('senderGradidoId') senderGradidoId: string,
@Arg('recipientCommunityUuid') recipientCommunityUuid: string,
@Arg('recipientCommunityName') recipientCommunityName: string,
@Arg('recipientGradidoId') recipientGradidoId: string,
@Arg('recipientFirstName') recipientFirstName: string,
@Arg('code') code: string,
@Arg('amount') amount: string,
@Arg('memo') memo: string,
@Arg('validUntil', { nullable: true }) validUntil?: string,
@Arg('recipientAlias', { nullable: true }) recipientAlias?: string,
): Promise<boolean> {
logger.debug('TransactionLinkResolver.disburseTransactionLink... args=', {
senderGradidoId,
senderCommunityUuid,
recipientCommunityUuid,
recipientCommunityName,
recipientGradidoId,
recipientFirstName,
code,
amount,
memo,
validUntil,
recipientAlias,
})
const disburseJwt = await this.createDisburseJwt(
senderCommunityUuid,
senderGradidoId,
recipientCommunityUuid,
recipientCommunityName,
recipientGradidoId,
recipientFirstName,
code,
amount,
memo,
validUntil ?? '',
recipientAlias ?? '',
)
logger.debug('TransactionLinkResolver.disburseTransactionLink... disburseJwt=', disburseJwt)
// now send the disburseJwt to the sender community to invoke a x-community-tx to disbures the redeemLink
try {
// await sendDisburseJwtToSenderCommunity(context, disburseJwt)
} catch (e) {
throw new LogError('Disburse JWT was not sent successfully', e)
}
return true
}
@Authorized([RIGHTS.LIST_TRANSACTION_LINKS])
@Query(() => TransactionLinkResult)
async listTransactionLinks(
@ -475,16 +528,16 @@ export class TransactionLinkResolver {
return transactionLinkList(paginated, filters, user)
}
async queryDisbursementLink(code: string): Promise<DisbursementLink> {
logger.debug('TransactionLinkResolver.queryDisbursementLink... disbursement jwt-token found')
async queryRedeemJwtLink(code: string): Promise<RedeemJwtLink> {
logger.debug('TransactionLinkResolver.queryRedeemJwtLink... redeem jwt-token found')
// decode token first to get the senderCommunityUuid as input for verify token
const decodedPayload = decode(code)
logger.debug('TransactionLinkResolver.queryDisbursementLink... decodedPayload=', decodedPayload)
logger.debug('TransactionLinkResolver.queryRedeemJwtLink... decodedPayload=', decodedPayload)
if (
decodedPayload != null &&
decodedPayload.tokentype === DisbursementJwtPayloadType.REDEEM_ACTIVATION_TYPE
decodedPayload.tokentype === RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE
) {
const disburseJwtPayload = new DisbursementJwtPayloadType(
const redeemJwtPayload = new RedeemJwtPayloadType(
decodedPayload.sendercommunityuuid as string,
decodedPayload.sendergradidoid as string,
decodedPayload.sendername as string,
@ -494,60 +547,61 @@ export class TransactionLinkResolver {
decodedPayload.validuntil as string,
)
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... disburseJwtPayload=',
disburseJwtPayload,
'TransactionLinkResolver.queryRedeemJwtLink... redeemJwtPayload=',
redeemJwtPayload,
)
const senderCom = await getCommunityByUuid(disburseJwtPayload.sendercommunityuuid)
const senderCom = await getCommunityByUuid(redeemJwtPayload.sendercommunityuuid)
if (!senderCom) {
throw new LogError('Sender community not found:', disburseJwtPayload.sendercommunityuuid)
throw new LogError('Sender community not found:', redeemJwtPayload.sendercommunityuuid)
}
logger.debug('TransactionLinkResolver.queryDisbursementLink... senderCom=', senderCom)
logger.debug('TransactionLinkResolver.queryRedeemJwtLink... senderCom=', senderCom)
if (!senderCom.communityUuid) {
throw new LogError('Sender community UUID is not set')
}
// now with the sender community UUID the jwt token can be verified
const jwtPayload = await verify(code, senderCom.communityUuid)
const verifiedJwtPayload = await verify(code, senderCom.communityUuid)
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... nach verify jwtPayload=',
jwtPayload,
'TransactionLinkResolver.queryRedeemJwtLink... nach verify verifiedJwtPayload=',
verifiedJwtPayload,
)
let verifiedPayload: DisbursementJwtPayloadType | null = null
if (jwtPayload !== null) {
if (jwtPayload.exp !== undefined) {
const expDate = new Date(jwtPayload.exp * 1000)
let verifiedRedeemJwtPayload: RedeemJwtPayloadType | null = null
if (verifiedJwtPayload !== null) {
if (verifiedJwtPayload.exp !== undefined) {
const expDate = new Date(verifiedJwtPayload.exp * 1000)
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... expDate, exp =',
'TransactionLinkResolver.queryRedeemJwtLink... expDate, exp =',
expDate,
jwtPayload.exp,
verifiedJwtPayload.exp,
)
if (expDate < new Date()) {
throw new LogError('Redeem JWT-Token expired! jwtPayload.exp=', expDate)
}
} else if (jwtPayload.tokentype === DisbursementJwtPayloadType.REDEEM_ACTIVATION_TYPE) {
}
if (verifiedJwtPayload.tokentype === RedeemJwtPayloadType.REDEEM_ACTIVATION_TYPE) {
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... jwtPayload.tokentype=',
jwtPayload.tokentype,
'TransactionLinkResolver.queryRedeemJwtLink... verifiedJwtPayload.tokentype=',
verifiedJwtPayload.tokentype,
)
verifiedPayload = new DisbursementJwtPayloadType(
jwtPayload.sendercommunityuuid as string,
jwtPayload.sendergradidoid as string,
jwtPayload.sendername as string,
jwtPayload.redeemcode as string,
jwtPayload.amount as string,
jwtPayload.memo as string,
jwtPayload.validuntil as string,
verifiedRedeemJwtPayload = new RedeemJwtPayloadType(
verifiedJwtPayload.sendercommunityuuid as string,
verifiedJwtPayload.sendergradidoid as string,
verifiedJwtPayload.sendername as string,
verifiedJwtPayload.redeemcode as string,
verifiedJwtPayload.amount as string,
verifiedJwtPayload.memo as string,
verifiedJwtPayload.validuntil as string,
)
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... nach verify verifiedPayload=',
verifiedPayload,
'TransactionLinkResolver.queryRedeemJwtLink... nach verify verifiedRedeemJwtPayload=',
verifiedRedeemJwtPayload,
)
}
}
if (verifiedPayload === null) {
if (verifiedRedeemJwtPayload === null) {
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... nach verify verifiedPayload= null',
'TransactionLinkResolver.queryRedeemJwtLink... verifiedRedeemJwtPayload===null',
)
verifiedPayload = new DisbursementJwtPayloadType(
verifiedRedeemJwtPayload = new RedeemJwtPayloadType(
decodedPayload.sendercommunityuuid as string,
decodedPayload.sendergradidoid as string,
decodedPayload.sendername as string,
@ -558,29 +612,26 @@ export class TransactionLinkResolver {
)
} else {
// TODO: as long as the verification fails, fallback to simply decoded payload
verifiedPayload = disburseJwtPayload
verifiedRedeemJwtPayload = redeemJwtPayload
logger.debug(
'TransactionLinkResolver.queryRedeemJwtLink... fallback to decode verifiedRedeemJwtPayload=',
verifiedRedeemJwtPayload,
)
}
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... nach decode verifiedPayload=',
verifiedPayload,
)
const homeCommunity = await getHomeCommunity()
const recipientCommunity = new Community(homeCommunity)
const senderCommunity = new Community(senderCom)
const senderUser = new User(null)
senderUser.gradidoID = verifiedPayload.sendergradidoid
senderUser.firstName = verifiedPayload.sendername
const disbursementLink = new DisbursementLink(
verifiedPayload,
senderUser.gradidoID = verifiedRedeemJwtPayload.sendergradidoid
senderUser.firstName = verifiedRedeemJwtPayload.sendername
const redeemJwtLink = new RedeemJwtLink(
verifiedRedeemJwtPayload,
senderCommunity,
senderUser,
recipientCommunity,
)
logger.debug(
'TransactionLinkResolver.queryDisbursementLink... disbursementLink=',
disbursementLink,
)
return disbursementLink
logger.debug('TransactionLinkResolver.queryRedeemJwtLink... redeemJwtLink=', redeemJwtLink)
return redeemJwtLink
} else {
throw new LogError(
'Redeem with wrong type of JWT-Token or expired! decodedPayload=',
@ -588,4 +639,51 @@ export class TransactionLinkResolver {
)
}
}
async createDisburseJwt(
senderCommunityUuid: string,
senderGradidoId: string,
recipientCommunityUuid: string,
recipientCommunityName: string,
recipientGradidoId: string,
recipientFirstName: string,
code: string,
amount: string,
memo: string,
validUntil: string,
recipientAlias: string,
): Promise<string> {
logger.debug('TransactionLinkResolver.createDisburseJwt... args=', {
senderCommunityUuid,
senderGradidoId,
recipientCommunityUuid,
recipientCommunityName,
recipientGradidoId,
recipientFirstName,
code,
amount,
memo,
validUntil,
recipientAlias,
})
const disburseJwtPayloadType = new DisburseJwtPayloadType(
senderCommunityUuid,
senderGradidoId,
recipientCommunityUuid,
recipientCommunityName,
recipientGradidoId,
recipientFirstName,
code,
amount,
memo,
validUntil,
recipientAlias,
)
// TODO:encode/sign the jwt normally with the private key of the recipient community, but interims with uuid
const disburseJwt = await encode(disburseJwtPayloadType, recipientCommunityUuid)
logger.debug('TransactionLinkResolver.createDisburseJwt... disburseJwt=', disburseJwt)
// TODO: encrypt the payload with the public key of the target/sender community
return disburseJwt
}
}

View File

@ -1,15 +1,15 @@
import { createUnionType } from 'type-graphql'
import { ContributionLink } from '@model/ContributionLink'
import { DisbursementLink } from '@model/DisbursementLink'
import { RedeemJwtLink } from '@/graphql/model/RedeemJwtLink'
import { TransactionLink } from '@model/TransactionLink'
export const QueryLinkResult = createUnionType({
name: 'QueryLinkResult', // the name of the GraphQL union
types: () => [TransactionLink, DisbursementLink, ContributionLink] as const, // function that returns tuple of object types classes
resolveType: (value: TransactionLink | DisbursementLink | ContributionLink) => {
types: () => [TransactionLink, RedeemJwtLink, ContributionLink] as const, // function that returns tuple of object types classes
resolveType: (value: TransactionLink | RedeemJwtLink | ContributionLink) => {
if (value instanceof TransactionLink) return TransactionLink
if (value instanceof DisbursementLink) return DisbursementLink
if (value instanceof RedeemJwtLink) return RedeemJwtLink
if (value instanceof ContributionLink) return ContributionLink
return null
},

View File

@ -226,3 +226,34 @@ export const createRedeemJwtMutation = gql`
)
}
`
export const disburseTransactionLink = gql`
mutation (
$senderCommunityUuid: String!
$senderGradidoId: String!
$recipientCommunityUuid: String!
$recipientCommunityName: String!
$recipientGradidoId: String!
$recipientFirstName: String!
$code: String!
$amount: String!
$memo: String!
$validUntil: String
$recipientAlias: String
) {
disburseTransactionLink(
senderCommunityUuid: $senderCommunityUuid
senderGradidoId: $senderGradidoId
recipientCommunityUuid: $recipientCommunityUuid
recipientCommunityName: $recipientCommunityName
recipientGradidoId: $recipientGradidoId
recipientFirstName: $recipientFirstName
code: $code
amount: $amount
memo: $memo
validUntil: $validUntil
recipientAlias: $recipientAlias
)
}
`

View File

@ -235,6 +235,7 @@
"credit-your-gradido": "Damit die Gradido gutgeschrieben werden können, klicke auf den Link!",
"delete-the-link": "Den Link löschen?",
"deleted": "Der Link wurde gelöscht!",
"disbured": "Auszahlung des Link-Guthabens erfolgreich initiiert! Die Gutschrift von {n} GDD wird zeitnah auf dein Konto gebucht",
"expiredOn": "Abgelaufen am",
"has-account": "Du besitzt bereits ein Gradido Konto?",
"header": "Gradidos versenden per Link",

View File

@ -235,6 +235,7 @@
"credit-your-gradido": "For the Gradido to be credited, click on the link!",
"delete-the-link": "Delete the link?",
"deleted": "The link was deleted!",
"disbured": "Disbursement of the Link-Ammount initiated! The transfer of {n} GDD into your account will be completed shortly.",
"expiredOn": "Expired on",
"has-account": "You already have a Gradido account?",
"header": "Send Gradidos via link",

View File

@ -198,6 +198,7 @@
"decay-14-day": "Disminución gradual por 14 días",
"delete-the-link": "Eliminar el enlace?",
"deleted": "El enlace ha sido eliminado!",
"disbured": "Disbursement of the Link-Ammount initiated! The transfer of {n} GDD into your account will be completed shortly.",
"expiredOn": "Vencido el:",
"has-account": "Ya tienes una cuenta Gradido?",
"header": "Transferir Gradidos por medio de un enlace",

View File

@ -204,6 +204,7 @@
"credit-your-gradido": "Pour l'accréditation du Gradido, cliquer sur le lien!",
"delete-the-link": "Supprimer le lien?",
"deleted": "Le lien a été supprimé!",
"disbured": "Disbursement of the Link-Ammount initiated! The transfer of {n} GDD into your account will be completed shortly.",
"expiredOn": "A expiré le",
"has-account": "Vous avez déjà un compte Gradido?",
"header": "Envoyer des Gradidos via lien",

View File

@ -198,6 +198,7 @@
"decay-14-day": "Vergankelijkheid voor 14 dagen",
"delete-the-link": "De link verwijderen?",
"deleted": "De link werd verwijderd!",
"disbured": "Disbursement of the Link-Ammount initiated! The transfer of {n} GDD into your account will be completed shortly.",
"expiredOn": "Afgelopen op",
"has-account": "Heb je al een Gradido rekening?",
"header": "Gradidos per link versturen",

View File

@ -162,6 +162,7 @@
"decay-14-day": "14 günlük erime",
"delete-the-link": "Link silinsin mi?",
"deleted": "Link silindi!",
"disbured": "Disbursement of the Link-Ammount initiated! The transfer of {n} GDD into your account will be completed shortly.",
"expiredOn": "Geçerlilik süresi",
"has-account": "Halihazırda bir Gradido hesabın var mı?",
"header": "Gradidoları link yoluyla gönderin",

View File

@ -45,7 +45,7 @@ import RedeemValid from '@/components/LinkInformations/RedeemValid'
import RedeemedTextBox from '@/components/LinkInformations/RedeemedTextBox'
import { useAppToast } from '@/composables/useToast'
import { queryTransactionLink } from '@/graphql/queries'
import { redeemTransactionLink } from '@/graphql/mutations'
import { disburseTransactionLink, redeemTransactionLink } from '@/graphql/mutations'
import { useI18n } from 'vue-i18n'
const { toastError, toastSuccess } = useAppToast()
@ -82,6 +82,7 @@ const { result, onResult, error, onError } = useQuery(queryTransactionLink, {
})
const { mutate: redeemMutate } = useMutation(redeemTransactionLink)
const { mutate: disburseMutate } = useMutation(disburseTransactionLink)
const isContributionLink = computed(() => {
return params.code?.search(/^CL-/) === 0
@ -261,15 +262,30 @@ function setDisbursementLinkInformation() {
async function mutationLink(amount) {
console.log('TransactionLink.mutationLink... params=', params)
try {
await redeemMutate({
code: redeemCode.value,
})
toastSuccess(t('gdd_per_link.redeemed', { n: amount }))
await router.push('/overview')
} catch (err) {
toastError(err.message)
await router.push('/overview')
if (isDisbursementLink.value) {
console.log('TransactionLink.mutationLink... trigger disbursement from recipient-community')
try {
await disburseMutate({
code: params.code,
})
toastSuccess(t('gdd_per_link.disbured', { n: amount }))
await router.push('/overview')
} catch (err) {
toastError(err.message)
await router.push('/overview')
}
} else {
console.log('TransactionLink.mutationLink... local transaction or contribution')
try {
await redeemMutate({
code: redeemCode.value,
})
toastSuccess(t('gdd_per_link.redeemed', { n: amount }))
await router.push('/overview')
} catch (err) {
toastError(err.message)
await router.push('/overview')
}
}
}
</script>