mppx 0.8.13 → 0.8.14

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 (123) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/Errors.d.ts +10 -0
  3. package/dist/Errors.d.ts.map +1 -1
  4. package/dist/Errors.js +11 -2
  5. package/dist/Errors.js.map +1 -1
  6. package/dist/Method.d.ts +105 -3
  7. package/dist/Method.d.ts.map +1 -1
  8. package/dist/Method.js +102 -2
  9. package/dist/Method.js.map +1 -1
  10. package/dist/client/internal/Fetch.d.ts.map +1 -1
  11. package/dist/client/internal/Fetch.js +12 -2
  12. package/dist/client/internal/Fetch.js.map +1 -1
  13. package/dist/client/internal/MethodChallenge.d.ts +17 -0
  14. package/dist/client/internal/MethodChallenge.d.ts.map +1 -0
  15. package/dist/client/internal/MethodChallenge.js +11 -0
  16. package/dist/client/internal/MethodChallenge.js.map +1 -0
  17. package/dist/server/Mppx.d.ts +23 -4
  18. package/dist/server/Mppx.d.ts.map +1 -1
  19. package/dist/server/Mppx.js +91 -82
  20. package/dist/server/Mppx.js.map +1 -1
  21. package/dist/tempo/client/Methods.d.ts +1 -0
  22. package/dist/tempo/client/Methods.d.ts.map +1 -1
  23. package/dist/tempo/internal/fee-payer.d.ts +1 -0
  24. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  25. package/dist/tempo/internal/fee-payer.js +7 -2
  26. package/dist/tempo/internal/fee-payer.js.map +1 -1
  27. package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -1
  28. package/dist/tempo/legacy/client/ChannelOps.js +2 -1
  29. package/dist/tempo/legacy/client/ChannelOps.js.map +1 -1
  30. package/dist/tempo/server/Charge.d.ts +38 -77
  31. package/dist/tempo/server/Charge.d.ts.map +1 -1
  32. package/dist/tempo/server/Charge.js +289 -209
  33. package/dist/tempo/server/Charge.js.map +1 -1
  34. package/dist/tempo/server/Methods.d.ts +12 -1
  35. package/dist/tempo/server/Methods.d.ts.map +1 -1
  36. package/dist/tempo/server/Methods.js +4 -0
  37. package/dist/tempo/server/Methods.js.map +1 -1
  38. package/dist/tempo/server/Relay.d.ts +48 -0
  39. package/dist/tempo/server/Relay.d.ts.map +1 -0
  40. package/dist/tempo/server/Relay.js +177 -0
  41. package/dist/tempo/server/Relay.js.map +1 -0
  42. package/dist/tempo/server/SponsorBudget.d.ts +59 -0
  43. package/dist/tempo/server/SponsorBudget.d.ts.map +1 -0
  44. package/dist/tempo/server/SponsorBudget.js +144 -0
  45. package/dist/tempo/server/SponsorBudget.js.map +1 -0
  46. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  47. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  48. package/dist/tempo/server/internal/html.gen.js +1 -1
  49. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  50. package/dist/tempo/session/client/ChannelOps.d.ts +7 -1
  51. package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -1
  52. package/dist/tempo/session/client/ChannelOps.js +9 -4
  53. package/dist/tempo/session/client/ChannelOps.js.map +1 -1
  54. package/dist/tempo/session/client/CredentialState.d.ts +5 -1
  55. package/dist/tempo/session/client/CredentialState.d.ts.map +1 -1
  56. package/dist/tempo/session/client/CredentialState.js +37 -19
  57. package/dist/tempo/session/client/CredentialState.js.map +1 -1
  58. package/dist/tempo/session/client/Runtime.d.ts +8 -0
  59. package/dist/tempo/session/client/Runtime.d.ts.map +1 -1
  60. package/dist/tempo/session/client/Runtime.js +17 -0
  61. package/dist/tempo/session/client/Runtime.js.map +1 -1
  62. package/dist/tempo/session/client/Session.d.ts +15 -5
  63. package/dist/tempo/session/client/Session.d.ts.map +1 -1
  64. package/dist/tempo/session/client/Session.js +93 -36
  65. package/dist/tempo/session/client/Session.js.map +1 -1
  66. package/dist/tempo/session/client/SessionManager.d.ts +8 -1
  67. package/dist/tempo/session/client/SessionManager.d.ts.map +1 -1
  68. package/dist/tempo/session/client/SessionManager.js +54 -26
  69. package/dist/tempo/session/client/SessionManager.js.map +1 -1
  70. package/dist/tempo/session/client/Transports.d.ts +7 -5
  71. package/dist/tempo/session/client/Transports.d.ts.map +1 -1
  72. package/dist/tempo/session/client/Transports.js +48 -24
  73. package/dist/tempo/session/client/Transports.js.map +1 -1
  74. package/dist/tempo/session/precompile/Chain.d.ts.map +1 -1
  75. package/dist/tempo/session/precompile/Chain.js +96 -8
  76. package/dist/tempo/session/precompile/Chain.js.map +1 -1
  77. package/dist/tempo/session/precompile/Channel.d.ts +2 -0
  78. package/dist/tempo/session/precompile/Channel.d.ts.map +1 -1
  79. package/dist/tempo/session/precompile/Channel.js +4 -0
  80. package/dist/tempo/session/precompile/Channel.js.map +1 -1
  81. package/dist/tempo/session/server/RequestState.js +3 -1
  82. package/dist/tempo/session/server/RequestState.js.map +1 -1
  83. package/package.json +1 -1
  84. package/src/Errors.test.ts +23 -0
  85. package/src/Errors.ts +21 -2
  86. package/src/Method.test.ts +102 -1
  87. package/src/Method.ts +241 -5
  88. package/src/client/Mppx.test-d.ts +3 -3
  89. package/src/client/internal/Fetch.ts +16 -7
  90. package/src/client/internal/MethodChallenge.ts +30 -0
  91. package/src/server/Mppx.test-d.ts +2 -0
  92. package/src/server/Mppx.test.ts +205 -0
  93. package/src/server/Mppx.ts +167 -103
  94. package/src/tempo/PublicExports.test-d.ts +20 -0
  95. package/src/tempo/internal/fee-payer.ts +7 -3
  96. package/src/tempo/legacy/client/ChannelOps.test.ts +7 -0
  97. package/src/tempo/legacy/client/ChannelOps.ts +2 -1
  98. package/src/tempo/server/Charge.test.ts +337 -63
  99. package/src/tempo/server/Charge.ts +435 -267
  100. package/src/tempo/server/Methods.ts +11 -0
  101. package/src/tempo/server/Relay.test.ts +523 -0
  102. package/src/tempo/server/Relay.ts +288 -0
  103. package/src/tempo/server/SponsorBudget.test.ts +125 -0
  104. package/src/tempo/server/SponsorBudget.ts +213 -0
  105. package/src/tempo/server/internal/html.gen.ts +1 -1
  106. package/src/tempo/session/client/ChannelOps.test.ts +17 -2
  107. package/src/tempo/session/client/ChannelOps.ts +12 -4
  108. package/src/tempo/session/client/CredentialState.ts +61 -20
  109. package/src/tempo/session/client/Runtime.test.ts +12 -0
  110. package/src/tempo/session/client/Runtime.ts +22 -0
  111. package/src/tempo/session/client/Session.test.ts +235 -2
  112. package/src/tempo/session/client/Session.ts +130 -41
  113. package/src/tempo/session/client/SessionManager.test.ts +102 -4
  114. package/src/tempo/session/client/SessionManager.ts +71 -27
  115. package/src/tempo/session/client/Transports.test.ts +32 -1
  116. package/src/tempo/session/client/Transports.ts +79 -35
  117. package/src/tempo/session/precompile/Chain.integration.test.ts +19 -1
  118. package/src/tempo/session/precompile/Chain.test.ts +197 -10
  119. package/src/tempo/session/precompile/Chain.ts +102 -8
  120. package/src/tempo/session/precompile/Channel.test.ts +9 -0
  121. package/src/tempo/session/precompile/Channel.ts +5 -0
  122. package/src/tempo/session/server/RequestState.test.ts +8 -1
  123. package/src/tempo/session/server/RequestState.ts +2 -2
@@ -0,0 +1,144 @@
1
+ import { VerificationFailedError } from '../../Errors.js';
2
+ const initialPollIntervalMs = 10;
3
+ const maxPollIntervalMs = 250;
4
+ const preparedLeaseMs = 30_000;
5
+ function key(parameters) {
6
+ return `mppx:charge:sponsor-budget:${parameters.chainId}:${parameters.sponsor.toLowerCase()}`;
7
+ }
8
+ function isState(value) {
9
+ return value?.version === 1 && typeof value.reservations === 'object';
10
+ }
11
+ async function mutateOwned(store, handle, mutate) {
12
+ return store.update(key(handle), (current) => {
13
+ if (!isState(current))
14
+ return { op: 'noop', result: false };
15
+ const reservation = current.reservations[handle.id];
16
+ if (!reservation || reservation.owner !== handle.owner)
17
+ return { op: 'noop', result: false };
18
+ const reservations = { ...current.reservations };
19
+ const next = mutate(reservation);
20
+ if (next)
21
+ reservations[handle.id] = next;
22
+ else
23
+ delete reservations[handle.id];
24
+ if (Object.keys(reservations).length === 0)
25
+ return { op: 'delete', result: true };
26
+ return {
27
+ op: 'set',
28
+ value: { reservations, version: 1 },
29
+ result: true,
30
+ };
31
+ });
32
+ }
33
+ async function reconcile(store, parameters) {
34
+ const state = await store.get(key(parameters));
35
+ if (!isState(state))
36
+ return;
37
+ const now = Date.now();
38
+ await Promise.all(Object.entries(state.reservations).map(async ([id, reservation]) => {
39
+ const handle = {
40
+ chainId: parameters.chainId,
41
+ id,
42
+ owner: reservation.owner,
43
+ sponsor: parameters.sponsor,
44
+ };
45
+ if (reservation.expiresAt <= now ||
46
+ (reservation.phase === 'prepared' && reservation.leaseUntil <= now)) {
47
+ await release(store, handle);
48
+ return;
49
+ }
50
+ if (reservation.phase === 'prepared')
51
+ return;
52
+ try {
53
+ await parameters.getReceipt(reservation.transactionHash);
54
+ }
55
+ catch {
56
+ return;
57
+ }
58
+ await release(store, handle);
59
+ }));
60
+ }
61
+ /**
62
+ * Reserves aggregate sponsor fee capacity across processes.
63
+ *
64
+ * Pending broadcasts remain charged to the budget until a receipt is observed
65
+ * or their expiring nonce becomes invalid. Capacity waiters do not rewrite the
66
+ * shared state while waiting.
67
+ *
68
+ * @internal
69
+ */
70
+ export async function reserve(store, parameters) {
71
+ if (parameters.fee > parameters.maxTotalFee)
72
+ throw new VerificationFailedError({
73
+ reason: 'Sponsored transaction fee exceeds the aggregate sponsor budget',
74
+ });
75
+ let pollIntervalMs = initialPollIntervalMs;
76
+ for (;;) {
77
+ const now = Date.now();
78
+ if (now >= parameters.waitUntil)
79
+ throw new VerificationFailedError({
80
+ reason: 'Sponsored transaction expired while waiting for sponsor budget',
81
+ });
82
+ await reconcile(store, parameters);
83
+ const result = await store.update(key(parameters), (current) => {
84
+ if (current !== null && !isState(current))
85
+ return { op: 'noop', result: 'invalid' };
86
+ const reservations = { ...(current?.reservations ?? {}) };
87
+ const existing = reservations[parameters.id];
88
+ if (existing)
89
+ return { op: 'noop', result: 'duplicate' };
90
+ const values = Object.values(reservations);
91
+ const totalFee = values.reduce((total, reservation) => total + BigInt(reservation.fee), 0n);
92
+ if (values.length >= parameters.maxReservations ||
93
+ totalFee + parameters.fee > parameters.maxTotalFee)
94
+ return { op: 'noop', result: 'wait' };
95
+ reservations[parameters.id] = {
96
+ expiresAt: parameters.expiresAt,
97
+ fee: parameters.fee.toString(),
98
+ leaseUntil: Math.min(parameters.expiresAt, now + preparedLeaseMs),
99
+ owner: parameters.owner,
100
+ phase: 'prepared',
101
+ transactionHash: parameters.transactionHash,
102
+ };
103
+ return {
104
+ op: 'set',
105
+ value: { reservations, version: 1 },
106
+ result: 'reserved',
107
+ };
108
+ });
109
+ if (result === 'reserved')
110
+ return parameters;
111
+ if (result === 'invalid')
112
+ throw new VerificationFailedError({
113
+ reason: 'Sponsor budget store contains incompatible state',
114
+ });
115
+ if (result === 'duplicate')
116
+ throw new VerificationFailedError({
117
+ reason: 'Sponsored transaction already has a budget reservation',
118
+ });
119
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollIntervalMs, parameters.waitUntil - now)));
120
+ pollIntervalMs = Math.min(pollIntervalMs * 2, maxPollIntervalMs);
121
+ }
122
+ }
123
+ /**
124
+ * Advances a reservation before and after the broadcast call.
125
+ *
126
+ * The owner token fences stale workers from mutating a replacement reservation.
127
+ *
128
+ * @internal
129
+ */
130
+ export async function transition(store, handle, phase) {
131
+ return mutateOwned(store, handle, (reservation) => ({
132
+ ...reservation,
133
+ phase,
134
+ }));
135
+ }
136
+ /**
137
+ * Releases a reservation only when the caller still owns it.
138
+ *
139
+ * @internal
140
+ */
141
+ export async function release(store, handle) {
142
+ return mutateOwned(store, handle, () => null);
143
+ }
144
+ //# sourceMappingURL=SponsorBudget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SponsorBudget.js","sourceRoot":"","sources":["../../../src/tempo/server/SponsorBudget.ts"],"names":[],"mappings":"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"}