diff --git a/src/background/services/paymentSession.ts b/src/background/services/paymentSession.ts index cc881c7e..6feed1d8 100644 --- a/src/background/services/paymentSession.ts +++ b/src/background/services/paymentSession.ts @@ -64,86 +64,83 @@ 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') + 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 } - 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 if (isInvalidReceiverError(e)) { - this.isInvalid = true - this.events.emit('open_payments.invalid_receiver', { - tabId: this.tabId - }) - break - } else { - throw e - } - } - } - 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 - ) - - if (amountInReceiversScale === 0n) { - const amount = convert( - MIN_SEND_AMOUNT, - receiverAssetScale, - senderAssetScale + // 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(amount) + this.setAmount(BigInt(amount)) return + } catch (e) { + if (isTokenExpiredError(e)) { + await this.openPaymentsService.rotateToken() + } else if (isNonPositiveAmountError(e)) { + continue + } else if (isInvalidReceiverError(e)) { + this.markInvalid() + this.events.emit('open_payments.invalid_receiver', { + tabId: this.tabId + }) + break + } else { + throw e + } } } + // return + // } this.amount = amountToSend.toString() this.intervalInMs = DEFAULT_INTERVAL_MS diff --git a/src/background/utils.test.ts b/src/background/utils.test.ts index bbf85e72..ffaba9c7 100644 --- a/src/background/utils.test.ts +++ b/src/background/utils.test.ts @@ -65,4 +65,17 @@ describe('getNextSendableAmount', () => { '80' ]) }) + + it('from assetScale 2 to 2', () => { + expect(take(getNextSendableAmount(2, 2), 8)).toEqual([ + '1', + '2', + '4', + '8', + '15', + '27', + '47', + '80' + ]) + }) })