From c36b04e2da9c7c68567380d9e5ff89a5a475be81 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Wed, 6 Nov 2024 14:08:28 +0100 Subject: [PATCH] make invoices retriable two times with feecredits and qr --- api/paidAction/index.js | 12 +++++-- api/typeDefs/paidAction.js | 12 +++++++ components/item-act.js | 2 +- components/pay-bounty.js | 2 +- components/poll.js | 2 +- components/use-paid-mutation.js | 31 ++++++++++++------- fragments/paidAction.js | 2 ++ .../migration.sql | 3 -- .../migration.sql | 5 +++ prisma/schema.prisma | 4 +-- 10 files changed, 52 insertions(+), 23 deletions(-) delete mode 100644 prisma/migrations/20241104155837_retry_action_wallet_cycling/migration.sql create mode 100644 prisma/migrations/20241106101356_retriable_invoiced_paidactions/migration.sql diff --git a/api/paidAction/index.js b/api/paidAction/index.js index ffc81822ed..413166ebae 100644 --- a/api/paidAction/index.js +++ b/api/paidAction/index.js @@ -175,7 +175,9 @@ async function performFeeCreditAction (invoiceData, actionType, paidAction, args return { result, paymentMethod: 'FEE_CREDIT', - retriable: invoiceData.retriable + retriable: invoiceEntry.retriable, + retriableWithFeeCredits: invoiceEntry.retriableWithFeeCredits, + retriableManually: invoiceEntry.retriableManually } } catch (e) { console.error('fee credit action failed', e) @@ -220,7 +222,9 @@ async function performOptimisticAction (invoiceData, actionType, paidAction, arg invoice: invoiceEntry, result: await performAction(invoiceEntry, paidAction, args, context), paymentMethod: 'OPTIMISTIC', - retriable: invoiceData.retriable + retriable: invoiceEntry.retriable, + retriableWithFeeCredits: invoiceEntry.retriableWithFeeCredits, + retriableManually: invoiceEntry.retriableManually } } if (context.tx) return await performInvoicedAction(context.tx) @@ -243,7 +247,9 @@ async function performPessimisticAction (invoiceData, actionType, paidAction, ar return { invoice: invoiceEntry, paymentMethod: 'PESSIMISTIC', - retriable: invoiceData.retriable + retriable: invoiceEntry.retriable, + retriableWithFeeCredits: invoiceEntry.retriableWithFeeCredits, + retriableManually: invoiceEntry.retriableManually } } if (context.tx) return await performInvoicedAction(context.tx) diff --git a/api/typeDefs/paidAction.js b/api/typeDefs/paidAction.js index b8d7cf68f4..1ea76a8e6e 100644 --- a/api/typeDefs/paidAction.js +++ b/api/typeDefs/paidAction.js @@ -20,6 +20,8 @@ interface PaidAction { invoice: Invoice paymentMethod: PaymentMethod! retriable: Boolean + retriableWithFeeCredits: Boolean + retriableManually: Boolean } type ItemPaidAction implements PaidAction { @@ -27,6 +29,8 @@ type ItemPaidAction implements PaidAction { invoice: Invoice paymentMethod: PaymentMethod! retriable: Boolean + retriableWithFeeCredits: Boolean + retriableManually: Boolean } type ItemActPaidAction implements PaidAction { @@ -34,6 +38,8 @@ type ItemActPaidAction implements PaidAction { invoice: Invoice paymentMethod: PaymentMethod! retriable: Boolean + retriableWithFeeCredits: Boolean + retriableManually: Boolean } type PollVotePaidAction implements PaidAction { @@ -41,6 +47,8 @@ type PollVotePaidAction implements PaidAction { invoice: Invoice paymentMethod: PaymentMethod! retriable: Boolean + retriableWithFeeCredits: Boolean + retriableManually: Boolean } type SubPaidAction implements PaidAction { @@ -48,6 +56,8 @@ type SubPaidAction implements PaidAction { invoice: Invoice paymentMethod: PaymentMethod! retriable: Boolean + retriableWithFeeCredits: Boolean + retriableManually: Boolean } type DonatePaidAction implements PaidAction { @@ -55,6 +65,8 @@ type DonatePaidAction implements PaidAction { invoice: Invoice paymentMethod: PaymentMethod! retriable: Boolean + retriableWithFeeCredits: Boolean + retriableManually: Boolean } ` diff --git a/components/item-act.js b/components/item-act.js index 36d5a0c777..5a7696b0bf 100644 --- a/components/item-act.js +++ b/components/item-act.js @@ -272,7 +272,7 @@ export function useZap () { const sats = nextTip(meSats, { ...me?.privates }) const variables = { id: item.id, sats, act: 'TIP' } - const optimisticResponse = { act: { __typename: 'ItemActPaidAction', result: { path: item.path, ...variables } } } + const optimisticResponse = { act: { __typename: 'ItemActPaidAction', result: { path: item.path, ...variables }, retriable: true, retriableManually: true, retriableWithFeeCredits: true } } try { await abortSignal.pause({ me, amount: sats }) diff --git a/components/pay-bounty.js b/components/pay-bounty.js index 35c5ebe602..c479953c0d 100644 --- a/components/pay-bounty.js +++ b/components/pay-bounty.js @@ -50,7 +50,7 @@ export default function PayBounty ({ children, item }) { const variables = { id: item.id, sats: root.bounty, act: 'TIP' } const act = useAct({ variables, - optimisticResponse: { act: { __typename: 'ItemActPaidAction', result: { ...variables, path: item.path } } }, + optimisticResponse: { act: { __typename: 'ItemActPaidAction', result: { ...variables, path: item.path }, retriable: true, retriableManually: true, retriableWithFeeCredits: true } }, ...payBountyCacheMods }) diff --git a/components/poll.js b/components/poll.js index dc694f801c..a8b819b00e 100644 --- a/components/poll.js +++ b/components/poll.js @@ -23,7 +23,7 @@ export default function Poll ({ item }) { onClick={me ? async () => { const variables = { id: v.id } - const optimisticResponse = { pollVote: { __typename: 'PollVotePaidAction', result: { id: v.id } } } + const optimisticResponse = { pollVote: { __typename: 'PollVotePaidAction', result: { id: v.id }, retriable: true, retriableManually: true, retriableWithFeeCredits: true } } try { const { error } = await pollVote({ variables, diff --git a/components/use-paid-mutation.js b/components/use-paid-mutation.js index 181f503ab7..7162d61bb6 100644 --- a/components/use-paid-mutation.js +++ b/components/use-paid-mutation.js @@ -65,6 +65,7 @@ export function usePaidMutation (mutation, console.error('could not cancel old invoice', err) } + console.log(response) if (response.retriable) { // every wallet failed, but we can still retry, so let's ask for a better invoice console.log('could not pay with any wallet, will retry with a new invoice...') @@ -77,19 +78,25 @@ export function usePaidMutation (mutation, } } - // we try one last time using fee credits - try { - console.log('could not pay with any wallet, will try with fee credits...') - const retry = await retryPaidAction({ variables: { invoiceId: parseInt(invoice.id), forceFeeCredits: true } }) - response = retry.data?.retryPaidAction - invoice = undefined - return { invoice, response } - } catch (err) { - console.log('could not pay with fee credits, will fallback to another method') - walletErrors.push(err) + console.log(response) + if (response.retriableWithFeeCredits) { + // we try one last time using fee credits + try { + console.log('could not pay with any wallet, will try with fee credits...') + const retry = await retryPaidAction({ variables: { invoiceId: parseInt(invoice.id), forceFeeCredits: true } }) + response = retry.data?.retryPaidAction + invoice = undefined + return { invoice, response } + } catch (err) { + console.log('could not pay with fee credits, will fallback to another method') + walletErrors.push(err) + } + } else { + console.log('actions is not retriable with fee credits, will fallback to another method') } - if (alwaysShowQROnFailure) { + console.log(response) + if (alwaysShowQROnFailure && response.retriableManually) { console.log('show qr code for manual payment') const retry = await retryPaidAction({ variables: { invoiceId: parseInt(invoice.id) } }) response = retry.data?.retryPaidAction @@ -187,7 +194,7 @@ export function usePaidMutation (mutation, function addOptimisticResponseExtras (optimisticResponse) { if (!optimisticResponse) return optimisticResponse const key = Object.keys(optimisticResponse)[0] - optimisticResponse[key] = { invoice: null, paymentMethod: 'OPTIMISTIC', ...optimisticResponse[key] } + optimisticResponse[key] = { invoice: null, paymentMethod: 'OPTIMISTIC', retriable: true, retriableManually: true, retriableWithFeeCredits: true, ...optimisticResponse[key] } return optimisticResponse } diff --git a/fragments/paidAction.js b/fragments/paidAction.js index c4e7994b07..bf0327e4d3 100644 --- a/fragments/paidAction.js +++ b/fragments/paidAction.js @@ -14,6 +14,8 @@ export const PAID_ACTION = gql` } paymentMethod retriable + retriableWithFeeCredits + retriableManually }` const ITEM_PAID_ACTION_FIELDS = gql` diff --git a/prisma/migrations/20241104155837_retry_action_wallet_cycling/migration.sql b/prisma/migrations/20241104155837_retry_action_wallet_cycling/migration.sql deleted file mode 100644 index a05fbe1071..0000000000 --- a/prisma/migrations/20241104155837_retry_action_wallet_cycling/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "Invoice" ADD COLUMN "actionAttempt" INTEGER NOT NULL DEFAULT 0, -ADD COLUMN "retriable" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/migrations/20241106101356_retriable_invoiced_paidactions/migration.sql b/prisma/migrations/20241106101356_retriable_invoiced_paidactions/migration.sql new file mode 100644 index 0000000000..def8151b9c --- /dev/null +++ b/prisma/migrations/20241106101356_retriable_invoiced_paidactions/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "Invoice" ADD COLUMN "actionAttempt" INTEGER NOT NULL DEFAULT 0, +ADD COLUMN "retriable" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "retriableManually" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "retriableWithFeeCredits" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1878cf4f2a..e27cb975ff 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -913,8 +913,8 @@ model Invoice { comment String? lud18Data Json? retriable Boolean @default(false) - retriableWithFeeCredits Boolean @default(true) - retriableManually Boolean @default(true) + retriableWithFeeCredits Boolean @default(false) + retriableManually Boolean @default(false) user User @relation(fields: [userId], references: [id], onDelete: Cascade) invoiceForward InvoiceForward?