Improve transfer error handling, fix min sendable message when paying to a lightning address

This commit is contained in:
minibits-cash
2024-12-21 00:21:31 +01:00
parent 87a07ae7f2
commit dbcc8d8d4f
6 changed files with 60 additions and 56 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "minibits_wallet",
"version": "0.1.10-beta.13",
"version": "0.1.10-beta.14",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
+1
View File
@@ -251,6 +251,7 @@
"isPending": "Payment is pending",
"maximumPay": "Maximum amount to pay is %{amount} %{currency}.",
"minimumWithdraw": "Minimal withdraw amount is %{amount} %{currency}.",
"minimumPay": "Minimal payment amount is %{amount} %{currency}.",
"pay": "Pay",
"payFrom": "Pay from",
"payFromWallet": "Pay from wallet",
+1 -1
View File
@@ -507,7 +507,7 @@ const onRequestLnurlInvoice = async function () {
}
if (lnurlPayParams.minSendable && amountSats < lnurlPayParams.minSendable / 1000) {
setInfo(translate('payCommon.minimumWithdraw', {
setInfo(translate('payCommon.minimumPay', {
amount: roundUp(lnurlPayParams.minSendable / 1000, 0),
currency: CurrencyCode.SAT
}))
+4 -1
View File
@@ -465,10 +465,13 @@ export const sendFromMintSync = async function (
// try to clean spent proofs if that was the swap error cause
if (e.params && e.params.message && e.params.message.includes('Token already spent')) {
log.error('[sendFromMintSync] Going to clean spent proofs from pending', {transactionId})
await WalletTask.syncStateWithMintSync({
proofsToSync: proofsStore.getByMint(mintUrl, {isPending: true}),
mintUrl,
isPending: false
isPending: true
})
}
+52 -52
View File
@@ -306,76 +306,86 @@ export const transferTask = async function (
}
} catch (e: any) {
let message = e.message
let returnMessage = ''
let message = e.message
let taskResult: TransactionTaskResult = {
taskFunction: TRANSFER,
mintUrl,
transaction,
message,
nwcEvent
} as TransactionTaskResult
if (transaction) {
// release lock
if(lockedProofsCounter) {
lockedProofsCounter.resetInFlight(transaction.id)
}
if (proofsToMeltFrom.length > 0) {
const walletInstance = await walletStore.getWallet(mintUrl, unit, {withSeed: true})
const refreshedMeltQuote = await walletInstance.checkMeltQuote(meltQuote.quote)
taskResult.meltQuote = refreshedMeltQuote
if(refreshedMeltQuote.state = MeltQuoteState.PENDING) {
log.warn('[transfer]', 'proofsToMeltFrom from transfer with error are pending by mint', {
proofsToMeltFromAmount,
unit,
transactionId: transaction.id
})
if(refreshedMeltQuote.state === MeltQuoteState.PAID) {
message = 'Lightning payment did not complete in time. Your ecash will remain pending until the payment completes or fails.'
// needs to be returned as error so we do not return
message = `Lightning invoice has been successfully paid, however some error occured: ${e.message}`
} else if(refreshedMeltQuote.state === MeltQuoteState.PAID) {
log.error('[transfer]', 'Transfer throwed error but the payment suceeded', {
log.error('[transfer]', message, {
error: e.message,
refreshedMeltQuote,
unit,
transactionId: transaction.id
})
taskResult.preimage = refreshedMeltQuote.payment_preimage
taskResult.message = message
} else if(refreshedMeltQuote.state = MeltQuoteState.PENDING) {
message = 'Lightning payment did not complete in time. Your ecash will remain pending until the payment completes or fails.'
taskResult.message = message
log.error('[transfer]', message, {
error: `${e.message}: ${e.params.message}`,
unit,
transactionId: transaction.id
})
await WalletTask.syncStateWithMintSync({
proofsToSync: proofsStore.getByMint(mintUrl, {isPending: true}),
mintUrl,
isPending: true
})
})
message = `Lightning invoice has been successfully paid, however some error occured: ${e.message}`
return {
taskFunction: TRANSFER,
mintUrl,
transaction,
message,
meltQuote: refreshedMeltQuote,
preimage: refreshedMeltQuote.payment_preimage,
nwcEvent
} as TransactionTaskResult
} else {
// if melt quote is UNPAID return proofs from pending to spendable balance
proofsStore.removeProofs(proofsToMeltFrom, true, true)
proofsStore.addProofs(proofsToMeltFrom)
returnMessage = "Ecash reserved for this payment was returned to spendable balance."
log.error('[transfer]', {returnMessage, proofsToMeltFromAmount})
if (e.params && e.params.message && e.params.message.includes('Token already spent')) {
if(e.message.includes('Token already spent')) {
// clean whole spendable balance from spent so that user can retry
const proofsToClean = proofsStore.getByMint(mintUrl, {isPending: false, unit})
await WalletTask.syncStateWithMintSync(
{
proofsToSync: proofsToClean,
mintUrl,
isPending: true
}
)
message = 'Token already spent, going to sync wallet pending proofs'
taskResult.message = message
log.error('[transfer]', message, {
transactionId: transaction.id
})
} else {
// if melt quote is UNPAID return proofs from pending to spendable balance
proofsStore.removeProofs(proofsToMeltFrom, true, true)
proofsStore.addProofs(proofsToMeltFrom)
message = "Ecash reserved for this payment was returned to spendable balance."
log.error('[transfer]', message, {
proofsToMeltFromAmount,
transactionId: transaction.id
})
}
}
await WalletTask.syncStateWithMintSync({
proofsToSync: proofsStore.getByMint(mintUrl, {isPending: true}),
mintUrl,
isPending: true
})
}
transactionData.push({
@@ -390,16 +400,6 @@ export const transferTask = async function (
)
}
log.error('[transfer]', e.name, e.message, e.params)
return {
taskFunction: TRANSFER,
mintUrl,
transaction,
message,
error: WalletUtils.formatError(e),
meltQuote,
nwcEvent
} as TransactionTaskResult
return taskResult
}
}
+1 -1
View File
@@ -1080,7 +1080,7 @@ const _handleInFlightByMintTask = async function (mint: Mint): Promise<WalletTas
} catch (e: any) {
// silent
log.error('[_handleInFlightByMintTask]', e.name, {message: e.message, mintUrl})
// make sure we release the lock
// make sure we release the lock // maybe we should keep inflight in case of error to retry next time?
proofsCounter.resetInFlight(transactionId)
return {