Files
minibits_wallet/src/services/wallet/revertTask.ts
T
2026-05-11 22:33:22 +02:00

137 lines
3.9 KiB
TypeScript

import {log} from '../logService'
import {
Transaction,
TransactionData,
TransactionStatus,
} from '../../models/Transaction'
import {rootStoreInstance} from '../../models'
import AppError, {Err} from '../../utils/AppError'
import { TransactionTaskResult } from '../walletService'
import { WalletUtils } from './utils'
import { MintUnit } from './currency'
import { Token, getEncodedToken, normalizeProofAmounts } from '@cashu/cashu-ts'
const {
mintsStore,
proofsStore,
walletStore
} = rootStoreInstance
export const REVERT_TASK = 'revertTask'
export const revertTask = async function (
transaction: Transaction
): Promise<TransactionTaskResult> {
let transactionData = [] as unknown as TransactionData
try {
transactionData = JSON.parse(transaction.data)
} catch (e) {}
const unit = transaction.unit as MintUnit
try {
const allProofs = proofsStore.getByTransactionId(transaction.id)
const pendingProofs = allProofs.filter(p => p.isPending === true)
if(pendingProofs.length === 0) {
throw new AppError(Err.VALIDATION_ERROR, 'Missing proofs to swap')
}
const mintInstance = mintsStore.findByUrl(transaction.mint)
if(!mintInstance) {
throw new AppError(Err.VALIDATION_ERROR, 'Missing mint')
}
// We will swap pending proofs with the mint for fresh ones that we receive to the wallet.
// This will invalidate originally sent proofs effectively reverting the transaction.
const encodedToken: Token = {
mint: mintInstance.mintUrl,
proofs: normalizeProofAmounts(pendingProofs),
unit
}
const receivedResult = await walletStore.receive(
transaction.mint,
unit as MintUnit,
encodedToken,
transaction.id
)
const receivedProofs = receivedResult.proofs
const mintFeePaid = receivedResult.swapFeePaid
// store freshed proofs as encoded token in tx data
const outputToken = getEncodedToken({
mint: mintInstance.mintUrl,
proofs: normalizeProofAmounts(receivedProofs),
unit
})
// Remove original pending proofs
proofsStore.moveToSpent(pendingProofs)
// add fresh proofs to spendable wallet
const { updatedAmount: receivedAmount } = proofsStore.addOrUpdate(receivedProofs, {
mintUrl: mintInstance.mintUrl,
unit,
tId: transaction.id,
isPending: false,
isSpent: false
})
// Update transaction status
transactionData.push({
status: TransactionStatus.REVERTED,
mintFeePaid,
createdAt: new Date(),
})
const balanceAfter = proofsStore.getUnitBalance(unit)?.unitBalance
transaction.update({
status: TransactionStatus.REVERTED,
data: JSON.stringify(transactionData),
outputToken,
balanceAfter,
...(mintFeePaid > 0 && {fee: mintFeePaid})
})
return {
taskFunction: REVERT_TASK,
mintUrl: mintInstance.mintUrl,
transaction,
message: `Transaction has been reverted and funds were returned to spendable balance.`,
receivedAmount,
} as TransactionTaskResult
} catch (e: any) {
if (transaction) {
transactionData.push({
status: TransactionStatus.ERROR,
error: WalletUtils.formatError(e),
errorToken: e.params?.errorToken || undefined
})
transaction.update({
status: TransactionStatus.ERROR,
data: JSON.stringify(transactionData)
})
}
log.error(e.name, e.message)
return {
taskFunction: REVERT_TASK,
mintUrl: transaction.mint,
transaction,
message: e.message,
error: WalletUtils.formatError(e),
} as TransactionTaskResult
}
}