You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: section/session-flow.html
+118-7Lines changed: 118 additions & 7 deletions
Original file line number
Diff line number
Diff line change
@@ -44,6 +44,14 @@ <h3>Session lifecycle</h3>
44
44
<dd>
45
45
A user agent maintained ordered list of {{Session}} records created by [=initiate a session=].
46
46
</dd>
47
+
<dt><dfn>current session iterator</dfn></dt>
48
+
<dd>
49
+
A user agent maintained iterator that points to the next {{Session}} in the [=active sessions list=] to be processed for payment.
50
+
This iterator is used to implement round-robin session processing,
51
+
ensuring fair distribution of payment attempts across all active sessions.
52
+
When the [=active sessions list=] is empty, the iterator is set to a special <dfn>end iterator</dfn> value
53
+
that represents a position past the last element in the list.
54
+
</dd>
47
55
</dl>
48
56
</section>
49
57
@@ -135,7 +143,11 @@ <h3>Session initiation</h3>
135
143
Append |session| to the [=active sessions list=].
136
144
</li>
137
145
<li>
138
-
If this is the first active session, [=start payment streaming loop=].
146
+
If this is the first active session:
147
+
<ol>
148
+
<li>Set the [=current session iterator=] to point to |session|.</li>
149
+
<li>[=Schedule payment streaming tick=].</li>
150
+
</ol>
139
151
</li>
140
152
</ol>
141
153
</div>
@@ -187,7 +199,18 @@ <h3>Session termination</h3>
187
199
<divclass="algorithm">
188
200
<p>To <dfn>end session</dfn>, given a session record |session:Session|, run these steps:</p>
189
201
<ol>
190
-
<li>Remove |session| from the [=active sessions list=].</li>
202
+
<li>If |session| is the only session in the [=active sessions list=]:
203
+
<ol>
204
+
<li>Remove |session| from the [=active sessions list=].</li>
205
+
<li>Set the [=current session iterator=] to the [=end iterator=].</li>
206
+
</ol>
207
+
</li>
208
+
<li>Otherwise:
209
+
<ol>
210
+
<li>If the [=current session iterator=] points to |session|, [=select next session for payment=].</li>
211
+
<li>Remove |session| from the [=active sessions list=].</li>
212
+
</ol>
213
+
</li>
191
214
<li>The user agent MUST cancel any scheduled payment work for |session|.</li>
192
215
</ol>
193
216
</div>
@@ -200,15 +223,103 @@ <h3>Payment streaming</h3>
200
223
</p>
201
224
202
225
<divclass="algorithm">
203
-
<p>To <dfn>start payment streaming loop</dfn>, run these steps:</p>
226
+
<p>To <dfn>schedule payment streaming tick</dfn>, run these steps:</p>
204
227
<ol>
205
-
<li>
228
+
<li>Let |userWallet:UserWallet| be the result of [=get user wallet=].</li>
229
+
<li>If |userWallet| is null, then return.</li>
230
+
<li>If the [=active sessions list=] is empty, then return.</li>
231
+
<li>Let |delay:DOMHighResTimeStamp| be the result of [=compute payment delay=].</li>
232
+
<li>Schedule a task that, after |delay| has elapsed, will [=run payment streaming tick=].</li>
233
+
</ol>
234
+
</div>
235
+
236
+
<divclass="algorithm">
237
+
<p>To <dfn>run payment streaming tick</dfn>, run these steps:</p>
238
+
<ol>
239
+
<li>If the [=active sessions list=] is empty, then return.</li>
240
+
<li>Let |session:Session| be the session pointed to by the [=current session iterator=].</li>
241
+
<li>[=Select next session for payment=].</li>
242
+
<li>[=Process session for payment=] given |session|.</li>
243
+
</ol>
244
+
</div>
245
+
246
+
<divclass="algorithm">
247
+
<p>To <dfn>select next session for payment</dfn>, run these steps:</p>
248
+
<ol>
249
+
<li>If the [=active sessions list=] is empty, then set the [=current session iterator=] to the [=end iterator=].</li>
250
+
<li>Otherwise, if the [=current session iterator=] is not at the [=end iterator=],
251
+
then advance the [=current session iterator=] to the next session in the [=active sessions list=].</li>
252
+
<li>If the [=current session iterator=] is at the [=end iterator=],
253
+
then set the [=current session iterator=] to point to the first session in the [=active sessions list=].</li>
254
+
</ol>
255
+
</div>
256
+
257
+
<divclass="algorithm">
258
+
<p>To <dfn>process session for payment</dfn>, given |session:Session|, run these steps:</p>
259
+
<ol>
260
+
<li>Let |userWallet:UserWallet| be the result of [=get user wallet=].</li>
261
+
<li>If |userWallet| is null, then return.</li>
262
+
<li>If |session| is not in the [=active sessions list=], then return.</li>
263
+
<li>Let |amount:PaymentCurrencyAmount| be the result of [=compute payment amount=] given |session|.</li>
264
+
<li>Let |amountValue:DOMString| be |amount|'s {{PaymentCurrencyAmount/value}}.</li>
265
+
<li>Let |userWalletGrant:Grant| be |userWallet|'s {{UserWallet/outgoingPaymentGrant}}.</li>
266
+
<li>Let |result:OutgoingPaymentResult| be the result of [=send a create outgoing payment request=]
267
+
with |userWallet|'s {{UserWallet/walletAddressDetails}}, |session|'s {{Session/incomingPaymentId}},
268
+
|amountValue|, and |userWalletGrant|.</li>
269
+
<li>If |result| is {{OutgoingPaymentResult/"success"}}:
270
+
<ol>
271
+
<li>[=Fire monetization event=] given |session|, |amount|, and |userWallet|.</li>
272
+
<li>[=Schedule payment streaming tick=].</li>
273
+
<li>Return.</li>
274
+
</ol>
275
+
</li>
276
+
<li>Otherwise:
277
+
<ol>
278
+
<li>TODO: Handle token rotation and other failure cases.</li>
279
+
</ol>
206
280
</li>
207
281
</ol>
208
282
</div>
209
283
210
-
<p>
211
-
The session flow must gracefully handle various error conditions and provide appropriate feedback to both the website and the user.
212
-
</p>
284
+
<divclass="algorithm">
285
+
<p>To <dfn>fire monetization event</dfn>, given |session:Session|, |amount:PaymentCurrencyAmount|, and |userWallet:UserWallet|, run these steps:</p>
286
+
<ol>
287
+
<li>Let |assetScale:long| be |userWallet|.{{UserWallet/walletAddressDetails}}.{{WalletAddressDetails/assetScale}}.</li>
288
+
<li>Let |assetCode:DOMString| be |userWallet|.{{UserWallet/walletAddressDetails}}.{{WalletAddressDetails/assetCode}}.</li>
289
+
<li>Let |decimalAmount:DOMString| be the result of [=convert scaled amount to decimal=] given |amount|.{{PaymentCurrencyAmount/value}} and |assetScale|.</li>
290
+
<li>Fire a [=monetization event=] on |session|.{{Session/linkElement}} with:
291
+
<ul>
292
+
<li>{{MonetizationEvent/amountSent}}.{{MonetizationCurrencyAmount/currency}} set to |assetCode|</li>
293
+
<li>{{MonetizationEvent/amountSent}}.{{MonetizationCurrencyAmount/value}} set to |decimalAmount|</li>
294
+
<li>{{MonetizationEvent/paymentPointer}} set to |session|.{{Session/walletDetails}}.{{WalletAddressDetails/id}}</li>
295
+
<li>{{MonetizationEvent/incomingPayment}} set to |session|.{{Session/incomingPaymentId}}</li>
296
+
</ul>
297
+
</li>
298
+
</ol>
299
+
</div>
300
+
301
+
<divclass="algorithm">
302
+
<p>To <dfn>compute payment amount</dfn>, given |session:Session|, run these steps:</p>
303
+
<ol>
304
+
<li>TODO</li>
305
+
</ol>
306
+
</div>
307
+
308
+
<divclass="algorithm">
309
+
<p>To <dfn>compute payment delay</dfn>, run these steps:</p>
310
+
<ol>
311
+
<li>TODO</li>
312
+
</ol>
313
+
</div>
314
+
315
+
<divclass="algorithm">
316
+
<p>To <dfn>convert scaled amount to decimal</dfn>, given |scaledAmount:long long| and |assetScale:long|, run these steps:</p>
317
+
<ol>
318
+
<li>Let |divisor:double| be <code>Math.pow(10, |assetScale|)</code>.</li>
319
+
<li>Let |decimalValue:double| be |scaledAmount| divided by |divisor|.</li>
320
+
<li>Return a string representation of |decimalValue| formatted with |assetScale| decimal places.</li>
321
+
</ol>
322
+
<pclass="note">For example, <code>convert scaled amount to decimal(100, 2)</code> returns <code>"1.00"</code>.</p>
0 commit comments