@@ -84,56 +84,46 @@ export class PaymentSession {
8484 Object . assign ( this , this . deps ) ;
8585 }
8686
87- #adjustAmountLastRate: AmountValue ;
88- #adjustAmountController = new AbortController ( ) ;
89- #adjustAmountPromise: null | Promise < void > = null ;
90- adjustAmount ( rate : AmountValue ) : Promise < void > {
91- if ( this . #adjustAmountLastRate && rate !== this . #adjustAmountLastRate) {
92- this . #adjustAmountController. abort (
93- new DOMException (
94- `Aborting existing probing for rate=${ this . #adjustAmountLastRate} ` ,
95- 'AbortError' ,
96- ) ,
97- ) ;
98- this . #adjustAmountController = new AbortController ( ) ;
99- this . #adjustAmountPromise = null ;
100- }
101-
102- this . #adjustAmountLastRate = rate ;
103- this . #adjustAmountPromise ??= this . _adjustAmount (
104- rate ,
105- this . #adjustAmountController. signal ,
106- ) ;
107-
108- return this . #adjustAmountPromise;
87+ // We keep setting #minSendAmount to non-zero values as we probe. Instead of
88+ // checking #minSendAmount > 0, use this boolean to know if probing completed.
89+ #minSendAmountFound = false ;
90+ #minSendAmount = 0n ;
91+ #minSendAmountPromise: ReturnType < typeof this . _findMinSendAmount > ;
92+
93+ findMinSendAmount ( ) : Promise < void > {
94+ this . #minSendAmountPromise ??= this . _findMinSendAmount ( ) ;
95+ return this . #minSendAmountPromise;
10996 }
11097
111- private async _adjustAmount (
112- rate : AmountValue ,
113- signal : AbortSignal ,
114- ) : Promise < void > {
115- this . rate = rate ;
98+ get minSendAmount ( ) : bigint {
99+ if ( ! this . #minSendAmountFound) {
100+ throw new Error ( 'minSendAmount not figured out yet' ) ;
101+ }
102+ return this . #minSendAmount;
103+ }
116104
105+ async adjustAmount ( hourlyRate : AmountValue ) {
106+ this . rate = hourlyRate ;
117107 // The amount that needs to be sent every second.
118108 // In senders asset scale already.
119- let amountToSend = BigInt ( this . rate ) / 3600n ;
109+ await this . findMinSendAmount ( ) ;
110+ if ( this . rate !== hourlyRate ) {
111+ throw new DOMException (
112+ `Aborting existing probing for rate=${ hourlyRate } ` ,
113+ 'AbortError' ,
114+ ) ;
115+ }
116+ const amount = BigInt ( this . rate ) / 3600n ;
117+ this . setAmount ( bigIntMax ( amount , this . #minSendAmount) ) ;
118+ }
119+
120+ private async _findMinSendAmount ( signal ?: AbortSignal ) : Promise < void > {
121+ let amountToSend = bigIntMax ( this . #minSendAmount, MIN_SEND_AMOUNT ) ;
120122 const senderAssetScale = this . sender . assetScale ;
121123 const receiverAssetScale = this . receiver . assetScale ;
122124 const isCrossCurrency = this . sender . assetCode !== this . receiver . assetCode ;
123125
124126 if ( ! isCrossCurrency ) {
125- if ( amountToSend <= MIN_SEND_AMOUNT ) {
126- // We need to add another unit when using a debit amount, since
127- // @interledger /pay subtracts one unit.
128- if ( senderAssetScale <= receiverAssetScale ) {
129- amountToSend = MIN_SEND_AMOUNT + 1n ;
130- } else if ( senderAssetScale > receiverAssetScale ) {
131- // If the sender scale is greater than the receiver scale, the unit
132- // issue will not be present.
133- amountToSend = MIN_SEND_AMOUNT ;
134- }
135- }
136-
137127 // If the sender can facilitate the rate, but the amount can not be
138128 // represented in the receiver's scale we need to send the minimum amount
139129 // for the receiver (1 unit, but in the sender's asset scale)
@@ -165,14 +155,15 @@ export class PaymentSession {
165155
166156 amountToSend = BigInt ( amountIter . next ( ) . value ) ;
167157 while ( true ) {
168- signal . throwIfAborted ( ) ;
158+ signal ?. throwIfAborted ( ) ;
159+ this . #minSendAmount = amountToSend ;
169160 try {
170161 await this . createPaymentQuote (
171162 amountToSend . toString ( ) ,
172163 this . incomingPaymentUrl ,
173164 this . sender ,
174165 ) ;
175- this . setAmount ( amountToSend ) ;
166+ this . #minSendAmountFound = true ;
176167 break ;
177168 } catch ( e ) {
178169 if ( isTokenExpiredError ( e ) ) {
0 commit comments