Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(background)!: better payment confirmation & message #694

Merged
merged 36 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c9ddb61
fix(background)!: better payment confirmation message
sidvishnoi Nov 1, 2024
05efcb0
wait before first attempt; rename function
sidvishnoi Nov 4, 2024
28d4b03
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 4, 2024
244ab38
make PaymentSession.pay always return OutgoingPayment; retry/throw ot…
sidvishnoi Nov 4, 2024
2148d3f
try different signature: get last outgoingPayment regardless of error
sidvishnoi Nov 4, 2024
a0ee3c6
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 7, 2024
30eb935
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 7, 2024
465ba9c
use async generator in polling; handle more errors; more abstraction
sidvishnoi Nov 7, 2024
951dc74
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 7, 2024
52abeaa
require only outgoingPaymentId in polling
sidvishnoi Nov 7, 2024
c96aa90
nit
sidvishnoi Nov 7, 2024
48cf703
nit: style/import
sidvishnoi Nov 7, 2024
6f93b1c
ui & message improvements
sidvishnoi Nov 8, 2024
d4e89fd
use same error message for `OutgoingPayment.failed = true`
sidvishnoi Nov 8, 2024
d57f918
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 11, 2024
4b13c73
reduce polling initial delay from 2.5s to 1.5s
sidvishnoi Nov 11, 2024
a0768ee
walletAddress check
sidvishnoi Nov 11, 2024
e11cf13
fix typo in error key name
sidvishnoi Nov 11, 2024
3df3acd
comment on null assertion
sidvishnoi Nov 11, 2024
cba0301
use payStatus full/partial instead of success/warn; also in bg
sidvishnoi Nov 11, 2024
d1e3681
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 13, 2024
bca0dbf
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 15, 2024
6560b41
update comment for isMissingGrantPermissionsError
sidvishnoi Nov 15, 2024
387cc08
handle case isMissingGrantPermissionsError is actually isTokenInactiv…
sidvishnoi Nov 15, 2024
715746e
update success/failure states; add partial status; update msgs
sidvishnoi Nov 15, 2024
2979f04
update success message to remove URL
sidvishnoi Nov 15, 2024
34ac427
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 19, 2024
b626ad3
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 22, 2024
3021b41
use opacity animation on message, slide is distracting
sidvishnoi Nov 22, 2024
3c8434c
fix disabled styles
sidvishnoi Nov 22, 2024
d2ae2ce
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 25, 2024
6efb7ba
update _locales key description
sidvishnoi Nov 25, 2024
9032cc4
handle insufficient grant by checking token's access values
sidvishnoi Nov 25, 2024
fb115d1
add todo comment
sidvishnoi Nov 25, 2024
0678549
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 26, 2024
5347047
Merge branch 'main' into payment-confirmation
sidvishnoi Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@
"pay_error_notEnoughFunds": {
"message": "Insufficient funds to complete the payment."
},
"pay_error_outgoingPaymentFailed": {
"message": "Payment failed."
},
"pay_error_outgoingPaymentCompletionLimitReached": {
"message": "Payment not finished yet.",
"description": "We were polling for completion, but it's not finished yet"
},
"pay_error_invalidReceivers": {
"message": "At the moment, you cannot pay this website.",
"description": "We cannot send money (probable cause: un-peered wallets)"
Expand Down
25 changes: 23 additions & 2 deletions src/background/services/monetization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,17 +265,38 @@ export class MonetizationService {

const splitAmount = Number(amount) / payableSessions.length;
// TODO: handle paying across two grants (when one grant doesn't have enough funds)
const results = await Promise.allSettled(
let results = await Promise.allSettled(
payableSessions.map((session) => session.pay(splitAmount)),
);
const signal = AbortSignal.timeout(8_000); // can use other signals as well, such as popup closed etc.
sidvishnoi marked this conversation as resolved.
Show resolved Hide resolved
results = await Promise.allSettled(
results.map((e) => {
if (e.status !== 'fulfilled') throw e.reason;
if (!e.value) return e.value;
const outgoingPaymentId = e.value.id;
return this.openPaymentsService.outgoingPaymentWaitForCompletion(
outgoingPaymentId,
{ signal, maxAttempts: 10 },
);
}),
);

const totalSentAmount = results
.filter((e) => e.status === 'fulfilled')
.reduce((acc, curr) => acc + BigInt(curr.value?.value ?? 0), 0n);
.reduce(
(acc, curr) => acc + BigInt(curr.value?.debitAmount?.value ?? 0),
0n,
);
if (totalSentAmount === 0n) {
const isNotEnoughFunds = results
.filter((e) => e.status === 'rejected')
.some((e) => isOutOfBalanceError(e.reason));
// TODO: If sentAmount is zero in all outgoing payments, and
// pay_error_outgoingPaymentCompletionLimitReached, it also likely means
// we don't have enough funds.
//
// TODO: If sentAmount is non-zero but not equal to debitAmount, show
// warning that not entire payment went through (yet?)
if (isNotEnoughFunds) {
throw new Error(this.t('pay_error_notEnoughFunds'));
}
Expand Down
40 changes: 39 additions & 1 deletion src/background/services/openPayments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
errorWithKeyToJSON,
getWalletInformation,
isErrorWithKey,
sleep,
withResolvers,
type ErrorWithKeyLike,
} from '@/shared/helpers';
Expand Down Expand Up @@ -694,7 +695,7 @@ export class OpenPaymentsService {
},
{
type: 'outgoing-payment',
actions: ['create'],
actions: ['create', 'read'],
sidvishnoi marked this conversation as resolved.
Show resolved Hide resolved
identifier: walletAddress.id,
limits: {
debitAmount: {
Expand Down Expand Up @@ -881,6 +882,43 @@ export class OpenPaymentsService {
return outgoingPayment;
}

async outgoingPaymentWaitForCompletion(
sidvishnoi marked this conversation as resolved.
Show resolved Hide resolved
outgoingPaymentId: OutgoingPayment['id'],
{
signal,
maxAttempts = 10,
}: Partial<{ signal: AbortSignal; maxAttempts: number }> = {},
) {
let attempt = 0;
let outgoingPayment: undefined | OutgoingPayment;
while (++attempt <= maxAttempts) {
signal?.throwIfAborted();
sidvishnoi marked this conversation as resolved.
Show resolved Hide resolved
try {
outgoingPayment = await this.client!.outgoingPayment.get({
url: outgoingPaymentId,
accessToken: this.token.value,
});
if (outgoingPayment.failed) {
throw new ErrorWithKey('pay_error_outgoingPaymentFailed');
}
if (
outgoingPayment.debitAmount.value === outgoingPayment.sentAmount.value
) {
return outgoingPayment;
}
signal?.throwIfAborted();
await sleep(1500);
} catch (error) {
if (isTokenExpiredError(error)) {
await this.rotateToken();
} else {
throw error;
}
}
}
throw new ErrorWithKey('pay_error_outgoingPaymentCompletionLimitReached');
}

async probeDebitAmount(
amount: AmountValue,
incomingPayment: IncomingPayment['id'],
Expand Down
2 changes: 1 addition & 1 deletion src/background/services/paymentSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ export class PaymentSession {
}
}

return outgoingPayment?.debitAmount;
return outgoingPayment;
}

private setAmount(amount: bigint): void {
Expand Down