@solana/mpp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +212 -0
  2. package/dist/Methods.d.ts +1 -213
  3. package/dist/Methods.d.ts.map +1 -1
  4. package/dist/Methods.js +1 -158
  5. package/dist/Methods.js.map +1 -1
  6. package/dist/client/Methods.d.ts +0 -2
  7. package/dist/client/Methods.d.ts.map +1 -1
  8. package/dist/client/Methods.js +0 -2
  9. package/dist/client/Methods.js.map +1 -1
  10. package/dist/client/index.d.ts +0 -1
  11. package/dist/client/index.d.ts.map +1 -1
  12. package/dist/client/index.js +0 -1
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/index.d.ts +0 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +0 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/server/Charge.d.ts +2 -2
  19. package/dist/server/Charge.d.ts.map +1 -1
  20. package/dist/server/Charge.js +4 -0
  21. package/dist/server/Charge.js.map +1 -1
  22. package/dist/server/Methods.d.ts +0 -2
  23. package/dist/server/Methods.d.ts.map +1 -1
  24. package/dist/server/Methods.js +0 -2
  25. package/dist/server/Methods.js.map +1 -1
  26. package/dist/server/index.d.ts +0 -1
  27. package/dist/server/index.d.ts.map +1 -1
  28. package/dist/server/index.js +0 -1
  29. package/dist/server/index.js.map +1 -1
  30. package/package.json +1 -9
  31. package/src/Methods.ts +1 -171
  32. package/src/client/Methods.ts +0 -3
  33. package/src/client/index.ts +0 -1
  34. package/src/index.ts +0 -29
  35. package/src/server/Charge.ts +7 -2
  36. package/src/server/Methods.ts +0 -3
  37. package/src/server/index.ts +0 -1
  38. package/dist/client/Session.d.ts +0 -195
  39. package/dist/client/Session.d.ts.map +0 -1
  40. package/dist/client/Session.js +0 -411
  41. package/dist/client/Session.js.map +0 -1
  42. package/dist/server/Session.d.ts +0 -171
  43. package/dist/server/Session.d.ts.map +0 -1
  44. package/dist/server/Session.js +0 -430
  45. package/dist/server/Session.js.map +0 -1
  46. package/dist/session/ChannelStore.d.ts +0 -12
  47. package/dist/session/ChannelStore.d.ts.map +0 -1
  48. package/dist/session/ChannelStore.js +0 -88
  49. package/dist/session/ChannelStore.js.map +0 -1
  50. package/dist/session/Types.d.ts +0 -179
  51. package/dist/session/Types.d.ts.map +0 -1
  52. package/dist/session/Types.js +0 -2
  53. package/dist/session/Types.js.map +0 -1
  54. package/dist/session/Voucher.d.ts +0 -7
  55. package/dist/session/Voucher.d.ts.map +0 -1
  56. package/dist/session/Voucher.js +0 -118
  57. package/dist/session/Voucher.js.map +0 -1
  58. package/dist/session/authorizers/BudgetAuthorizer.d.ts +0 -90
  59. package/dist/session/authorizers/BudgetAuthorizer.d.ts.map +0 -1
  60. package/dist/session/authorizers/BudgetAuthorizer.js +0 -398
  61. package/dist/session/authorizers/BudgetAuthorizer.js.map +0 -1
  62. package/dist/session/authorizers/SwigSessionAuthorizer.d.ts +0 -104
  63. package/dist/session/authorizers/SwigSessionAuthorizer.d.ts.map +0 -1
  64. package/dist/session/authorizers/SwigSessionAuthorizer.js +0 -522
  65. package/dist/session/authorizers/SwigSessionAuthorizer.js.map +0 -1
  66. package/dist/session/authorizers/UnboundedAuthorizer.d.ts +0 -36
  67. package/dist/session/authorizers/UnboundedAuthorizer.d.ts.map +0 -1
  68. package/dist/session/authorizers/UnboundedAuthorizer.js +0 -204
  69. package/dist/session/authorizers/UnboundedAuthorizer.js.map +0 -1
  70. package/dist/session/authorizers/index.d.ts +0 -5
  71. package/dist/session/authorizers/index.d.ts.map +0 -1
  72. package/dist/session/authorizers/index.js +0 -5
  73. package/dist/session/authorizers/index.js.map +0 -1
  74. package/dist/session/authorizers/makeSessionAuthorizer.d.ts +0 -19
  75. package/dist/session/authorizers/makeSessionAuthorizer.d.ts.map +0 -1
  76. package/dist/session/authorizers/makeSessionAuthorizer.js +0 -72
  77. package/dist/session/authorizers/makeSessionAuthorizer.js.map +0 -1
  78. package/dist/session/index.d.ts +0 -5
  79. package/dist/session/index.d.ts.map +0 -1
  80. package/dist/session/index.js +0 -5
  81. package/dist/session/index.js.map +0 -1
  82. package/src/client/Session.ts +0 -630
  83. package/src/server/Session.ts +0 -687
  84. package/src/session/ChannelStore.ts +0 -128
  85. package/src/session/Types.ts +0 -189
  86. package/src/session/Voucher.ts +0 -158
  87. package/src/session/authorizers/BudgetAuthorizer.ts +0 -574
  88. package/src/session/authorizers/SwigSessionAuthorizer.ts +0 -767
  89. package/src/session/authorizers/UnboundedAuthorizer.ts +0 -284
  90. package/src/session/authorizers/index.ts +0 -4
  91. package/src/session/authorizers/makeSessionAuthorizer.ts +0 -104
  92. package/src/session/index.ts +0 -4
@@ -1,630 +0,0 @@
1
- import type { TransactionSigner } from '@solana/kit';
2
- import { type Challenge, Credential, Method, z } from 'mppx';
3
-
4
- import * as Methods from '../Methods.js';
5
- import type { SessionAuthorizer, SessionCredentialPayload } from '../session/Types.js';
6
-
7
- type SessionAsset = {
8
- decimals: number;
9
- kind: 'sol' | 'spl';
10
- mint?: string;
11
- symbol?: string;
12
- };
13
-
14
- type SessionPricing = {
15
- amountPerUnit: string;
16
- meter: string;
17
- minDebit?: string;
18
- unit: string;
19
- };
20
-
21
- type SessionChallengeRequest = {
22
- asset: SessionAsset;
23
- channelProgram: string;
24
- network?: string;
25
- pricing?: SessionPricing;
26
- recipient: string;
27
- sessionDefaults?: {
28
- closeBehavior?: 'payer_must_close' | 'server_may_finalize';
29
- settleInterval?: { kind: string; minIncrement?: string; seconds?: number };
30
- suggestedDeposit?: string;
31
- ttlSeconds?: number;
32
- };
33
- };
34
-
35
- type ActiveChannel = {
36
- asset: SessionAsset;
37
- channelId: string;
38
- channelProgram: string;
39
- cumulativeAmount: bigint;
40
- depositAmount: bigint;
41
- network: string;
42
- recipient: string;
43
- sequence: number;
44
- serverNonce: string;
45
- };
46
-
47
- export const sessionContextSchema = z.object({
48
- action: z.optional(z.enum(['open', 'update', 'topup', 'close'])),
49
- additionalAmount: z.optional(z.string()),
50
- channelId: z.optional(z.string()),
51
- cumulativeAmount: z.optional(z.string()),
52
- depositAmount: z.optional(z.string()),
53
- openTx: z.optional(z.string()),
54
- sequence: z.optional(z.number()),
55
- topupTx: z.optional(z.string()),
56
- });
57
-
58
- export type SessionContext = z.infer<typeof sessionContextSchema>;
59
-
60
- export function session(parameters: session.Parameters) {
61
- const { signer, authorizer, autoOpen = true, autoTopup = false, settleOnLimitHit = false, onProgress } = parameters;
62
-
63
- let activeChannel: ActiveChannel | null = null;
64
-
65
- return Method.toClient(Methods.session, {
66
- context: sessionContextSchema,
67
-
68
- async createCredential({ challenge, context }) {
69
- const request = challenge.request as SessionChallengeRequest;
70
- const recipient = request.recipient;
71
- const network = request.network ?? 'mainnet-beta';
72
- const asset = request.asset;
73
- const channelProgram = request.channelProgram;
74
- const pricing = request.pricing;
75
- const sessionDefaults = request.sessionDefaults;
76
-
77
- onProgress?.({
78
- asset,
79
- network,
80
- recipient,
81
- type: 'challenge',
82
- });
83
-
84
- if (context?.action === 'topup') {
85
- return await handleTopupAction(challenge, context, authorizer, activeChannel, channelProgram, network);
86
- }
87
-
88
- if (context?.action === 'close') {
89
- const credential = await handleCloseAction(
90
- challenge,
91
- context,
92
- authorizer,
93
- activeChannel,
94
- channelProgram,
95
- recipient,
96
- network,
97
- onProgress,
98
- );
99
-
100
- activeChannel = null;
101
- return credential;
102
- }
103
-
104
- if (context?.action === 'open') {
105
- if (!context.channelId) {
106
- throw new Error('channelId is required for open action');
107
- }
108
-
109
- if (!context.depositAmount) {
110
- throw new Error('depositAmount is required for open action');
111
- }
112
-
113
- const channelId = context.channelId;
114
- const depositAmount = context.depositAmount;
115
- const parsedDepositAmount = parseNonNegativeAmount(depositAmount, 'context.depositAmount');
116
- const serverNonce = crypto.randomUUID();
117
-
118
- onProgress?.({ channelId, type: 'opening' });
119
-
120
- const openResult = await authorizer.authorizeOpen({
121
- asset,
122
- channelId,
123
- channelProgram,
124
- depositAmount,
125
- network,
126
- pricing,
127
- recipient,
128
- serverNonce,
129
- });
130
-
131
- const payer = resolveOpenPayer(openResult.voucher.voucher.payer, signer);
132
-
133
- const payload: SessionCredentialPayload = {
134
- action: 'open',
135
- authorizationMode: authorizer.getMode(),
136
- channelId,
137
- depositAmount,
138
- openTx: context.openTx ?? openResult.openTx,
139
- payer,
140
- ...(openResult.expiresAt ? { expiresAt: openResult.expiresAt } : {}),
141
- capabilities: {
142
- ...(openResult.capabilities.maxCumulativeAmount
143
- ? {
144
- maxCumulativeAmount: openResult.capabilities.maxCumulativeAmount,
145
- }
146
- : {}),
147
- ...(openResult.capabilities.allowedActions
148
- ? { allowedActions: openResult.capabilities.allowedActions }
149
- : {}),
150
- },
151
- voucher: openResult.voucher,
152
- };
153
-
154
- activeChannel = {
155
- asset: normalizeAsset(asset),
156
- channelId,
157
- channelProgram,
158
- cumulativeAmount: parseNonNegativeAmount(
159
- openResult.voucher.voucher.cumulativeAmount,
160
- 'voucher.cumulativeAmount',
161
- ),
162
- depositAmount: parsedDepositAmount,
163
- network,
164
- recipient,
165
- sequence: assertNonNegativeSequence(openResult.voucher.voucher.sequence),
166
- serverNonce: openResult.voucher.voucher.serverNonce,
167
- };
168
-
169
- onProgress?.({ channelId, type: 'opened' });
170
-
171
- return Credential.serialize({
172
- challenge,
173
- payload,
174
- });
175
- }
176
-
177
- if (context?.action === 'update') {
178
- const channelId = context.channelId ?? activeChannel?.channelId;
179
- if (!channelId) {
180
- throw new Error('channelId is required for update action');
181
- }
182
-
183
- if (!activeChannel || activeChannel.channelId !== channelId) {
184
- throw new Error('Cannot update a channel that is not active');
185
- }
186
-
187
- if (!context.cumulativeAmount) {
188
- throw new Error('cumulativeAmount is required for update action');
189
- }
190
-
191
- if (context.sequence === undefined) {
192
- throw new Error('sequence is required for update action');
193
- }
194
-
195
- const nextCumulativeAmount = parseNonNegativeAmount(
196
- context.cumulativeAmount,
197
- 'context.cumulativeAmount',
198
- );
199
- const nextSequence = assertNonNegativeSequence(context.sequence);
200
-
201
- onProgress?.({
202
- channelId,
203
- cumulativeAmount: nextCumulativeAmount.toString(),
204
- type: 'updating',
205
- });
206
-
207
- const updateResult = await authorizer.authorizeUpdate({
208
- channelId,
209
- channelProgram,
210
- cumulativeAmount: nextCumulativeAmount.toString(),
211
- meter: pricing?.meter ?? 'session',
212
- network,
213
- recipient,
214
- sequence: nextSequence,
215
- serverNonce: activeChannel.serverNonce,
216
- units: pricing ? '1' : '0',
217
- });
218
-
219
- const payload: SessionCredentialPayload = {
220
- action: 'update',
221
- channelId,
222
- voucher: updateResult.voucher,
223
- };
224
-
225
- activeChannel.cumulativeAmount = parseNonNegativeAmount(
226
- updateResult.voucher.voucher.cumulativeAmount,
227
- 'voucher.cumulativeAmount',
228
- );
229
- activeChannel.sequence = assertNonNegativeSequence(updateResult.voucher.voucher.sequence);
230
- activeChannel.serverNonce = updateResult.voucher.voucher.serverNonce;
231
-
232
- onProgress?.({
233
- channelId,
234
- cumulativeAmount: activeChannel.cumulativeAmount.toString(),
235
- type: 'updated',
236
- });
237
-
238
- return Credential.serialize({
239
- challenge,
240
- payload,
241
- });
242
- }
243
-
244
- const scopedActiveChannel =
245
- activeChannel &&
246
- matchesScope(activeChannel, {
247
- asset,
248
- channelProgram,
249
- network,
250
- recipient,
251
- })
252
- ? activeChannel
253
- : null;
254
-
255
- if (!scopedActiveChannel) {
256
- if (!autoOpen) {
257
- throw new Error('No active session channel for challenge scope and autoOpen is disabled');
258
- }
259
-
260
- const channelId = crypto.randomUUID();
261
- const serverNonce = crypto.randomUUID();
262
- const depositAmount = sessionDefaults?.suggestedDeposit ?? '0';
263
- const parsedDepositAmount = parseNonNegativeAmount(depositAmount, 'sessionDefaults.suggestedDeposit');
264
-
265
- onProgress?.({ channelId, type: 'opening' });
266
-
267
- const openResult = await authorizer.authorizeOpen({
268
- asset,
269
- channelId,
270
- channelProgram,
271
- depositAmount,
272
- network,
273
- pricing,
274
- recipient,
275
- serverNonce,
276
- });
277
-
278
- const payer = resolveOpenPayer(openResult.voucher.voucher.payer, signer);
279
-
280
- const payload: SessionCredentialPayload = {
281
- action: 'open',
282
- authorizationMode: authorizer.getMode(),
283
- channelId,
284
- depositAmount,
285
- openTx: openResult.openTx,
286
- payer,
287
- ...(openResult.expiresAt ? { expiresAt: openResult.expiresAt } : {}),
288
- capabilities: {
289
- ...(openResult.capabilities.maxCumulativeAmount
290
- ? {
291
- maxCumulativeAmount: openResult.capabilities.maxCumulativeAmount,
292
- }
293
- : {}),
294
- ...(openResult.capabilities.allowedActions
295
- ? { allowedActions: openResult.capabilities.allowedActions }
296
- : {}),
297
- },
298
- voucher: openResult.voucher,
299
- };
300
-
301
- activeChannel = {
302
- asset: normalizeAsset(asset),
303
- channelId,
304
- channelProgram,
305
- cumulativeAmount: parseNonNegativeAmount(
306
- openResult.voucher.voucher.cumulativeAmount,
307
- 'voucher.cumulativeAmount',
308
- ),
309
- depositAmount: parsedDepositAmount,
310
- network,
311
- recipient,
312
- sequence: assertNonNegativeSequence(openResult.voucher.voucher.sequence),
313
- serverNonce: openResult.voucher.voucher.serverNonce,
314
- };
315
-
316
- onProgress?.({ channelId, type: 'opened' });
317
-
318
- return Credential.serialize({
319
- challenge,
320
- payload,
321
- });
322
- }
323
-
324
- const debitIncrement = resolveDebitIncrement(pricing);
325
- const nextCumulativeAmount = scopedActiveChannel.cumulativeAmount + debitIncrement;
326
- const nextSequence = scopedActiveChannel.sequence + 1;
327
-
328
- if (nextCumulativeAmount > scopedActiveChannel.depositAmount) {
329
- if (!autoTopup) {
330
- if (!settleOnLimitHit) {
331
- throw new Error('Voucher cumulative amount exceeds tracked deposit and autoTopup is disabled');
332
- }
333
-
334
- const closeCredential = await handleCloseAction(
335
- challenge,
336
- {
337
- action: 'close',
338
- channelId: scopedActiveChannel.channelId,
339
- },
340
- authorizer,
341
- scopedActiveChannel,
342
- channelProgram,
343
- recipient,
344
- network,
345
- onProgress,
346
- );
347
-
348
- activeChannel = null;
349
- return closeCredential;
350
- }
351
-
352
- const additionalAmount = resolveAutoTopupAmount(
353
- sessionDefaults?.suggestedDeposit,
354
- nextCumulativeAmount,
355
- scopedActiveChannel.depositAmount,
356
- );
357
-
358
- const topupResult = await authorizer.authorizeTopup({
359
- additionalAmount: additionalAmount.toString(),
360
- channelId: scopedActiveChannel.channelId,
361
- channelProgram,
362
- network,
363
- });
364
-
365
- scopedActiveChannel.depositAmount += additionalAmount;
366
-
367
- const payload: SessionCredentialPayload = {
368
- action: 'topup',
369
- additionalAmount: additionalAmount.toString(),
370
- channelId: scopedActiveChannel.channelId,
371
- topupTx: topupResult.topupTx,
372
- };
373
-
374
- return Credential.serialize({
375
- challenge,
376
- payload,
377
- });
378
- }
379
-
380
- onProgress?.({
381
- channelId: scopedActiveChannel.channelId,
382
- cumulativeAmount: nextCumulativeAmount.toString(),
383
- type: 'updating',
384
- });
385
-
386
- const updateResult = await authorizer.authorizeUpdate({
387
- channelId: scopedActiveChannel.channelId,
388
- channelProgram,
389
- cumulativeAmount: nextCumulativeAmount.toString(),
390
- meter: pricing?.meter ?? 'session',
391
- network,
392
- recipient,
393
- sequence: nextSequence,
394
- serverNonce: scopedActiveChannel.serverNonce,
395
- units: pricing ? '1' : '0',
396
- });
397
-
398
- const payload: SessionCredentialPayload = {
399
- action: 'update',
400
- channelId: scopedActiveChannel.channelId,
401
- voucher: updateResult.voucher,
402
- };
403
-
404
- scopedActiveChannel.cumulativeAmount = parseNonNegativeAmount(
405
- updateResult.voucher.voucher.cumulativeAmount,
406
- 'voucher.cumulativeAmount',
407
- );
408
- scopedActiveChannel.sequence = assertNonNegativeSequence(updateResult.voucher.voucher.sequence);
409
- scopedActiveChannel.serverNonce = updateResult.voucher.voucher.serverNonce;
410
-
411
- onProgress?.({
412
- channelId: scopedActiveChannel.channelId,
413
- cumulativeAmount: scopedActiveChannel.cumulativeAmount.toString(),
414
- type: 'updated',
415
- });
416
-
417
- return Credential.serialize({
418
- challenge,
419
- payload,
420
- });
421
- },
422
- });
423
- }
424
-
425
- async function handleTopupAction(
426
- challenge: Challenge.Challenge,
427
- context: SessionContext,
428
- authorizer: SessionAuthorizer,
429
- activeChannel: ActiveChannel | null,
430
- channelProgram: string,
431
- network: string,
432
- ): Promise<string> {
433
- const channelId = context.channelId ?? activeChannel?.channelId;
434
- if (!channelId) {
435
- throw new Error('channelId is required for topup action');
436
- }
437
- if (!context.additionalAmount) {
438
- throw new Error('additionalAmount is required for topup action');
439
- }
440
-
441
- const additionalAmount = parseNonNegativeAmount(context.additionalAmount, 'context.additionalAmount');
442
-
443
- const topupResult = await authorizer.authorizeTopup({
444
- additionalAmount: additionalAmount.toString(),
445
- channelId,
446
- channelProgram,
447
- network,
448
- });
449
-
450
- if (activeChannel && activeChannel.channelId === channelId) {
451
- activeChannel.depositAmount += additionalAmount;
452
- }
453
-
454
- const payload: SessionCredentialPayload = {
455
- action: 'topup',
456
- additionalAmount: additionalAmount.toString(),
457
- channelId,
458
- topupTx: topupResult.topupTx,
459
- };
460
-
461
- return Credential.serialize({ challenge, payload });
462
- }
463
-
464
- async function handleCloseAction(
465
- challenge: Challenge.Challenge,
466
- context: SessionContext,
467
- authorizer: SessionAuthorizer,
468
- activeChannel: ActiveChannel | null,
469
- channelProgram: string,
470
- recipient: string,
471
- network: string,
472
- onProgress?: session.Parameters['onProgress'],
473
- ): Promise<string> {
474
- const channelId = context.channelId ?? activeChannel?.channelId;
475
- if (!channelId) {
476
- throw new Error('channelId is required for close action');
477
- }
478
-
479
- if (!activeChannel || activeChannel.channelId !== channelId) {
480
- throw new Error('Cannot close a channel that is not active');
481
- }
482
-
483
- const finalSequence = activeChannel.sequence + 1;
484
-
485
- onProgress?.({ channelId, type: 'closing' });
486
-
487
- const closeResult = await authorizer.authorizeClose({
488
- channelId,
489
- channelProgram,
490
- finalCumulativeAmount: activeChannel.cumulativeAmount.toString(),
491
- network,
492
- recipient,
493
- sequence: finalSequence,
494
- serverNonce: activeChannel.serverNonce,
495
- });
496
-
497
- const payload: SessionCredentialPayload = {
498
- action: 'close',
499
- channelId,
500
- ...(closeResult.closeTx ? { closeTx: closeResult.closeTx } : {}),
501
- voucher: closeResult.voucher,
502
- };
503
-
504
- onProgress?.({ channelId, type: 'closed' });
505
-
506
- return Credential.serialize({ challenge, payload });
507
- }
508
-
509
- function resolveDebitIncrement(pricing?: SessionPricing): bigint {
510
- if (pricing?.minDebit !== undefined) {
511
- return parseNonNegativeAmount(pricing.minDebit, 'pricing.minDebit');
512
- }
513
-
514
- if (pricing?.amountPerUnit !== undefined) {
515
- return parseNonNegativeAmount(pricing.amountPerUnit, 'pricing.amountPerUnit');
516
- }
517
-
518
- return 0n;
519
- }
520
-
521
- function resolveAutoTopupAmount(
522
- suggestedDeposit: string | undefined,
523
- nextCumulativeAmount: bigint,
524
- depositAmount: bigint,
525
- ): bigint {
526
- const shortfall = nextCumulativeAmount - depositAmount;
527
- if (shortfall <= 0n) {
528
- return 0n;
529
- }
530
-
531
- if (suggestedDeposit === undefined) {
532
- return shortfall;
533
- }
534
-
535
- const parsedSuggestedDeposit = parseNonNegativeAmount(suggestedDeposit, 'sessionDefaults.suggestedDeposit');
536
- return parsedSuggestedDeposit > shortfall ? parsedSuggestedDeposit : shortfall;
537
- }
538
-
539
- function matchesScope(
540
- active: ActiveChannel,
541
- scope: {
542
- asset: SessionAsset;
543
- channelProgram: string;
544
- network: string;
545
- recipient: string;
546
- },
547
- ): boolean {
548
- if (active.recipient !== scope.recipient) {
549
- return false;
550
- }
551
-
552
- if (active.network !== scope.network) {
553
- return false;
554
- }
555
-
556
- if (active.channelProgram !== scope.channelProgram) {
557
- return false;
558
- }
559
-
560
- return sameAsset(active.asset, scope.asset);
561
- }
562
-
563
- function sameAsset(left: SessionAsset, right: SessionAsset): boolean {
564
- return (
565
- left.kind === right.kind &&
566
- left.decimals === right.decimals &&
567
- (left.mint ?? '') === (right.mint ?? '') &&
568
- (left.symbol ?? '') === (right.symbol ?? '')
569
- );
570
- }
571
-
572
- function normalizeAsset(asset: SessionAsset): SessionAsset {
573
- return {
574
- decimals: asset.decimals,
575
- kind: asset.kind,
576
- ...(asset.mint ? { mint: asset.mint } : {}),
577
- ...(asset.symbol ? { symbol: asset.symbol } : {}),
578
- };
579
- }
580
-
581
- function assertNonNegativeSequence(value: number): number {
582
- if (!Number.isInteger(value) || value < 0) {
583
- throw new Error('voucher.sequence must be a non-negative integer');
584
- }
585
-
586
- return value;
587
- }
588
-
589
- function parseNonNegativeAmount(value: string, field: string): bigint {
590
- let amount: bigint;
591
- try {
592
- amount = BigInt(value);
593
- } catch {
594
- throw new Error(`${field} must be a valid integer string`);
595
- }
596
-
597
- if (amount < 0n) {
598
- throw new Error(`${field} must be non-negative`);
599
- }
600
-
601
- return amount;
602
- }
603
-
604
- function resolveOpenPayer(voucherPayer: string, signer?: TransactionSigner): string {
605
- if (signer && signer.address !== voucherPayer) {
606
- throw new Error(`Open voucher payer ${voucherPayer} does not match signer address ${signer.address}`);
607
- }
608
-
609
- return voucherPayer;
610
- }
611
-
612
- export declare namespace session {
613
- type Parameters = {
614
- authorizer: SessionAuthorizer;
615
- autoOpen?: boolean;
616
- autoTopup?: boolean;
617
- onProgress?: (event: ProgressEvent) => void;
618
- settleOnLimitHit?: boolean;
619
- signer?: TransactionSigner;
620
- };
621
-
622
- type ProgressEvent =
623
- | { asset: SessionAsset; network: string; recipient: string; type: 'challenge' }
624
- | { channelId: string; cumulativeAmount: string; type: 'updated' }
625
- | { channelId: string; cumulativeAmount: string; type: 'updating' }
626
- | { channelId: string; type: 'closed' }
627
- | { channelId: string; type: 'closing' }
628
- | { channelId: string; type: 'opened' }
629
- | { channelId: string; type: 'opening' };
630
- }