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): probe even with same currency #470

Merged
merged 3 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"html": true
}
],
"no-constant-condition": "off",
"no-console": "warn",
"react/prop-types": "off",
"block-scoped-var": "error",
Expand Down
1 change: 1 addition & 0 deletions src/background/services/monetization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export class MonetizationService {

if (enabled && this.canTryPayment(connected, state)) {
sessionsArr.forEach((session) => {
if (!sessions.get(session.id)) return
const source = replacedSessions.has(session.id)
? 'request-id-reused'
: 'new-link'
Expand Down
124 changes: 59 additions & 65 deletions src/background/services/paymentSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import type { MonetizationEventDetails } from '@/shared/messages'
import type { AmountValue } from '@/shared/types'
import type { Logger } from '@/shared/logger'

const DEFAULT_INTERVAL_MS = 1000
const HOUR_MS = 3600 * 1000
const MIN_SEND_AMOUNT = 1n // 1 unit

Expand Down Expand Up @@ -59,83 +58,78 @@ export class PaymentSession {

// The amount that needs to be sent every second.
// In senders asset scale already.
const amountToSend = BigInt(this.rate) / 3600n
let amountToSend = BigInt(this.rate) / 3600n
const senderAssetScale = this.sender.assetScale
const receiverAssetScale = this.receiver.assetScale

// This all will eventually get replaced by OpenPayments response update
// that includes a min rate that we can directly use.
if (this.sender.assetCode !== this.receiver.assetCode) {
await this.setIncomingPaymentUrl()
for (const amount of getNextSendableAmount(
senderAssetScale,
receiverAssetScale,
bigIntMax(amountToSend, MIN_SEND_AMOUNT)
)) {
if (this.probingId !== localProbingId) {
// In future we can throw `new AbortError()`
throw new DOMException('Aborting existing probing', 'AbortError')
}
try {
await this.openPaymentsService.probeDebitAmount(
amount,
this.incomingPaymentUrl,
this.sender
)
this.setAmount(BigInt(amount))
return
} catch (e) {
if (isTokenExpiredError(e)) {
await this.openPaymentsService.rotateToken()
} else if (isNonPositiveAmountError(e)) {
continue
} else {
throw e
}
const isCrossCurrency = this.sender.assetCode !== this.receiver.assetCode

if (!isCrossCurrency) {
if (amountToSend <= MIN_SEND_AMOUNT) {
// We need to add another unit when using a debit amount, since
// @interledger/pay subtracts one unit.
if (senderAssetScale <= receiverAssetScale) {
amountToSend = MIN_SEND_AMOUNT + 1n
} else if (senderAssetScale > receiverAssetScale) {
// If the sender scale is greater than the receiver scale, the unit
// issue will not be present.
amountToSend = MIN_SEND_AMOUNT
}
}
return
}

if (amountToSend <= MIN_SEND_AMOUNT) {
// We need to add another unit when using a debit amount, since
// @interledger/pay subtracts one unit.
if (senderAssetScale <= receiverAssetScale) {
this.setAmount(MIN_SEND_AMOUNT + 1n)
return
}

// If the sender scale is greater than the receiver scale, the unit issue
// will not be present.
// If the sender can facilitate the rate, but the amount can not be
// represented in the receiver's scale we need to send the minimum amount
// for the receiver (1 unit, but in the sender's asset scale)
if (senderAssetScale > receiverAssetScale) {
this.setAmount(MIN_SEND_AMOUNT)
return
const amountInReceiversScale = convert(
amountToSend,
senderAssetScale,
receiverAssetScale
)

if (amountInReceiversScale === 0n) {
amountToSend = convert(
MIN_SEND_AMOUNT,
receiverAssetScale,
senderAssetScale
)
}
}
}

// If the sender can facilitate the rate, but the amount can not be
// represented in the receiver's scale we need to send the minimum amount
// for the receiver (1 unit, but in the sender's asset scale)
if (senderAssetScale > receiverAssetScale) {
const amountInReceiversScale = convert(
amountToSend,
senderAssetScale,
receiverAssetScale
)
// This all will eventually get replaced by OpenPayments response update
// that includes a min rate that we can directly use.
await this.setIncomingPaymentUrl()
const amountIter = getNextSendableAmount(
senderAssetScale,
receiverAssetScale,
bigIntMax(amountToSend, MIN_SEND_AMOUNT)
)

if (amountInReceiversScale === 0n) {
const amount = convert(
MIN_SEND_AMOUNT,
receiverAssetScale,
senderAssetScale
amountToSend = BigInt(amountIter.next().value)
while (true) {
if (this.probingId !== localProbingId) {
// In future we can throw `new AbortError()`
throw new DOMException('Aborting existing probing', 'AbortError')
}
try {
await this.openPaymentsService.probeDebitAmount(
amountToSend.toString(),
this.incomingPaymentUrl,
this.sender
)
this.setAmount(amount)
return
this.setAmount(amountToSend)
break
} catch (e) {
if (isTokenExpiredError(e)) {
await this.openPaymentsService.rotateToken()
} else if (isNonPositiveAmountError(e)) {
amountToSend = BigInt(amountIter.next().value)
continue
} else {
throw e
}
}
}

this.amount = amountToSend.toString()
this.intervalInMs = DEFAULT_INTERVAL_MS
}

get id() {
Expand Down
2 changes: 1 addition & 1 deletion src/background/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function* getNextSendableAmount(
senderAssetScale: number,
receiverAssetScale: number,
amount: bigint = 0n
): IterableIterator<AmountValue> {
): Generator<AmountValue, never, never> {
const EXPONENTIAL_INCREASE = 0.5

const scaleDiff =
Expand Down
Loading