@voltro/plugin-economy 0.0.0-stage → 0.88.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 (177) hide show
  1. package/CHANGELOG.md +24492 -0
  2. package/LICENSE +61 -0
  3. package/README.md +2719 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +9841 -0
  6. package/dist/amount.js +20 -0
  7. package/dist/appleIap.server.js +262 -0
  8. package/dist/appleIapNotifications.server.js +162 -0
  9. package/dist/appleIapTrust.server.js +30 -0
  10. package/dist/bundleValue.server.js +112 -0
  11. package/dist/canonicalDataJson.js +10 -0
  12. package/dist/capture.js +53 -0
  13. package/dist/codePort.fixture.js +123 -0
  14. package/dist/codeStore.server.js +439 -0
  15. package/dist/codeTables.entity.js +43 -0
  16. package/dist/codes.d.ts +150 -0
  17. package/dist/codes.js +82 -0
  18. package/dist/components.d.ts +397 -0
  19. package/dist/components.js +283 -0
  20. package/dist/consistency.server.js +115 -0
  21. package/dist/containerStore.server.js +687 -0
  22. package/dist/containerStore.testFixtures.js +75 -0
  23. package/dist/containerTables.entity.js +45 -0
  24. package/dist/containers.d.ts +311 -0
  25. package/dist/containers.fixture.js +128 -0
  26. package/dist/containers.js +214 -0
  27. package/dist/containers.server.js +39 -0
  28. package/dist/containersPort.fixture.js +74 -0
  29. package/dist/currency.js +32 -0
  30. package/dist/declarationFixtures.js +61 -0
  31. package/dist/economy-app/events/economy.refundReversed.event.ts +1 -0
  32. package/dist/economy-app/events/economy.refunded.event.ts +1 -0
  33. package/dist/economyPort.fixture.js +124 -0
  34. package/dist/errors.d.ts +14 -0
  35. package/dist/errors.js +21 -0
  36. package/dist/events.d.ts +46 -0
  37. package/dist/events.js +1 -0
  38. package/dist/googleIap.server.js +391 -0
  39. package/dist/googleIapNotifications.server.js +130 -0
  40. package/dist/googleIapSubscription.server.js +183 -0
  41. package/dist/iap.d.ts +309 -0
  42. package/dist/iap.js +303 -0
  43. package/dist/iap.testFixtures.js +144 -0
  44. package/dist/iapAccountTables.entity.js +39 -0
  45. package/dist/iapAccounts.server.js +200 -0
  46. package/dist/iapBinding.server.js +523 -0
  47. package/dist/iapCheckout.server.js +97 -0
  48. package/dist/iapCompletion.server.js +55 -0
  49. package/dist/iapCurrentState.server.js +107 -0
  50. package/dist/iapCurrentState.testFixtures.js +22 -0
  51. package/dist/iapCurrentStatePort.fixture.js +63 -0
  52. package/dist/iapEntitlements.d.ts +79 -0
  53. package/dist/iapEntitlements.js +57 -0
  54. package/dist/iapEntitlements.server.js +48 -0
  55. package/dist/iapEntitlementsBinding.server.js +105 -0
  56. package/dist/iapEntitlementsPort.fixture.js +80 -0
  57. package/dist/iapInstalledEntitlements.testFixtures.js +75 -0
  58. package/dist/iapInstalledNotifications.testFixtures.js +93 -0
  59. package/dist/iapInventoryRefunds.server.js +261 -0
  60. package/dist/iapNotificationCustodyPort.fixture.js +67 -0
  61. package/dist/iapNotificationPort.fixture.js +73 -0
  62. package/dist/iapNotificationProcessor.server.js +134 -0
  63. package/dist/iapNotificationProcessor.testFixtures.js +63 -0
  64. package/dist/iapNotificationProcessorPort.fixture.js +55 -0
  65. package/dist/iapNotificationSchedule.server.js +69 -0
  66. package/dist/iapNotificationStore.server.js +352 -0
  67. package/dist/iapNotificationStore.testFixtures.js +31 -0
  68. package/dist/iapNotificationTables.entity.js +48 -0
  69. package/dist/iapNotificationTarget.server.js +36 -0
  70. package/dist/iapNotificationTarget.testFixtures.js +29 -0
  71. package/dist/iapNotifications.d.ts +644 -0
  72. package/dist/iapNotifications.js +6 -0
  73. package/dist/iapNotifications.server.js +95 -0
  74. package/dist/iapNotificationsBinding.server.js +232 -0
  75. package/dist/iapNotificationsSystemPort.fixture.js +50 -0
  76. package/dist/iapPlugin.testFixtures.js +59 -0
  77. package/dist/iapPort.fixture.js +74 -0
  78. package/dist/iapProviderCapture.server.js +17 -0
  79. package/dist/iapRecovery.d.ts +146 -0
  80. package/dist/iapRecovery.js +89 -0
  81. package/dist/iapRefundEventDelivery.server.js +82 -0
  82. package/dist/iapRefundEvents.js +44 -0
  83. package/dist/iapRefundEventsPort.fixture.js +59 -0
  84. package/dist/iapRefundPort.fixture.js +54 -0
  85. package/dist/iapRefundTables.entity.js +55 -0
  86. package/dist/iapRefunds.d.ts +755 -0
  87. package/dist/iapRefunds.js +6 -0
  88. package/dist/iapRefunds.server.js +553 -0
  89. package/dist/iapRefunds.testFixtures.js +64 -0
  90. package/dist/iapSpendAdmission.server.js +98 -0
  91. package/dist/iapStore.server.js +740 -0
  92. package/dist/iapStore.testFixtures.js +127 -0
  93. package/dist/iapTables.entity.js +80 -0
  94. package/dist/iapVerification.server.js +120 -0
  95. package/dist/index.d.ts +2984 -0
  96. package/dist/index.js +15 -0
  97. package/dist/intentionRecovery.js +133 -0
  98. package/dist/ledger.js +77 -0
  99. package/dist/loyalty.d.ts +274 -0
  100. package/dist/loyalty.fixture.js +92 -0
  101. package/dist/loyalty.js +311 -0
  102. package/dist/loyaltyBinding.server.js +203 -0
  103. package/dist/loyaltyPort.fixture.js +86 -0
  104. package/dist/loyaltyShopSource.server.js +90 -0
  105. package/dist/loyaltyStore.server.js +552 -0
  106. package/dist/loyaltyStore.testFixtures.js +82 -0
  107. package/dist/loyaltyTables.entity.js +49 -0
  108. package/dist/offerMerchandising.fixture.js +114 -0
  109. package/dist/offerMerchandising.js +282 -0
  110. package/dist/offerPolicies.d.ts +441 -0
  111. package/dist/offerPolicies.fixture.js +53 -0
  112. package/dist/offerPolicies.js +267 -0
  113. package/dist/piggyBanks.d.ts +272 -0
  114. package/dist/piggyBanks.fixture.js +70 -0
  115. package/dist/piggyBanks.js +200 -0
  116. package/dist/piggyBinding.server.js +204 -0
  117. package/dist/piggyPort.fixture.js +72 -0
  118. package/dist/piggyStore.server.js +610 -0
  119. package/dist/piggyStore.testFixtures.js +97 -0
  120. package/dist/piggyTables.entity.js +40 -0
  121. package/dist/plugin.js +1047 -0
  122. package/dist/port.js +12 -0
  123. package/dist/price.d.ts +99 -0
  124. package/dist/price.js +143 -0
  125. package/dist/purchaseRecovery.js +55 -0
  126. package/dist/reports.server.js +114 -0
  127. package/dist/rpc.d.ts +3201 -0
  128. package/dist/rpc.js +1200 -0
  129. package/dist/sanctionsTradeAuthority.server.js +79 -0
  130. package/dist/server.d.ts +3856 -0
  131. package/dist/server.js +43 -0
  132. package/dist/shop.d.ts +279 -0
  133. package/dist/shop.js +195 -0
  134. package/dist/shop.testFixtures.js +113 -0
  135. package/dist/shopPort.fixture.js +71 -0
  136. package/dist/shopPresentation.js +67 -0
  137. package/dist/shopStore.server.js +623 -0
  138. package/dist/shopTables.entity.js +62 -0
  139. package/dist/shopUiCopy.js +56 -0
  140. package/dist/spendLimits.d.ts +140 -0
  141. package/dist/spendLimits.fixture.js +52 -0
  142. package/dist/spendLimits.js +154 -0
  143. package/dist/spendLimitsPort.fixture.js +119 -0
  144. package/dist/subscriptionBinding.server.js +210 -0
  145. package/dist/subscriptionStore.server.js +642 -0
  146. package/dist/subscriptionStore.testFixtures.js +71 -0
  147. package/dist/subscriptionTables.entity.js +36 -0
  148. package/dist/subscriptions.d.ts +394 -0
  149. package/dist/subscriptions.fixture.js +96 -0
  150. package/dist/subscriptions.js +212 -0
  151. package/dist/subscriptionsPort.fixture.js +75 -0
  152. package/dist/systemFixtures.js +88 -0
  153. package/dist/tables.entity.js +82 -0
  154. package/dist/testing.d.ts +4615 -0
  155. package/dist/testing.js +29 -0
  156. package/dist/tradeAuthority.server.js +171 -0
  157. package/dist/tradeBinding.server.js +200 -0
  158. package/dist/tradeComponents.js +341 -0
  159. package/dist/tradeEscrow.server.js +231 -0
  160. package/dist/tradeEscrow.testFixtures.js +132 -0
  161. package/dist/tradeExpiry.server.js +42 -0
  162. package/dist/tradeRecovery.js +47 -0
  163. package/dist/tradeStore.server.js +749 -0
  164. package/dist/tradeStore.testFixtures.js +72 -0
  165. package/dist/tradeTables.entity.js +65 -0
  166. package/dist/tradeUiCopy.js +78 -0
  167. package/dist/trades.d.ts +246 -0
  168. package/dist/trades.fixture.js +102 -0
  169. package/dist/trades.js +288 -0
  170. package/dist/tradesPort.fixture.js +93 -0
  171. package/dist/walletEscrow.js +105 -0
  172. package/dist/walletEscrow.server.js +375 -0
  173. package/dist/walletKeys.server.js +4 -0
  174. package/dist/walletStore.js +570 -0
  175. package/dist/web.d.ts +2257 -0
  176. package/dist/web.js +8 -0
  177. package/package.json +161 -4
@@ -0,0 +1,687 @@
1
+ import { EconomyError as e, economyError as t } from "./errors.js";
2
+ import { captureBoundMethods as n, dataList as r, dataObject as i, identifier as a } from "./capture.js";
3
+ import { captureCurrencies as o } from "./currency.js";
4
+ import { defaultPriceResolver as s, priceResolverContext as c, resolvePrice as l } from "./price.js";
5
+ import { captureShopOrderReceipt as u, shopInteger as d, shopPayment as f } from "./shop.js";
6
+ import { captureContainerIntent as p, defaultContainerEligibility as m, defaultContainerProbability as h, defaultContainerRoll as g, defineContainer as _, discloseContainer as v, resolveContainerDistribution as y, resolveContainerEligibility as b, resolveContainerRoll as x } from "./containers.js";
7
+ import { cryptoContainerRandom as S } from "./containers.server.js";
8
+ import { containerDefinitionsTable as C, containerOpeningsTable as w, containerSubjectsTable as T, containerTenantsTable as E } from "./containerTables.entity.js";
9
+ import { Effect as D, Result as O } from "effect";
10
+ import { systemSubject as k } from "@voltro/protocol";
11
+ import { createHash as A } from "node:crypto";
12
+ import { and as ee, eq as j, queryFor as M } from "@voltro/database";
13
+ import { executeSqlMutations as te, prepareSqlMutation as ne, prepareSqlMutationGroup as re } from "@voltro/database/sql";
14
+ import { InventoryError as N } from "@voltro/plugin-inventory/errors";
15
+ // src/containerStore.server.ts
16
+ var P = (e) => A("sha256").update(JSON.stringify(e)).digest("hex"), F = (e, ...t) => e + P(t).slice(0, 56), I = (e, t) => P([e, a(t)]), L = (n) => n instanceof e ? n : n instanceof N && [
17
+ "conflict",
18
+ "erased",
19
+ "limit_exceeded",
20
+ "forbidden",
21
+ "not_found",
22
+ "invalid_record"
23
+ ].includes(n.code) ? t(n.code) : t("unavailable"), R = (e) => D.tryPromise({
24
+ try: e,
25
+ catch: L
26
+ }), z = (e) => {
27
+ try {
28
+ return e();
29
+ } catch (e) {
30
+ return D.fail(L(e));
31
+ }
32
+ }, B = async (e) => {
33
+ let t = await D.runPromise(D.result(e));
34
+ if (O.isFailure(t)) throw t.failure;
35
+ return t.success;
36
+ }, V = (e) => {
37
+ let t = e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN;
38
+ return d(t, 0, 864e13);
39
+ }, H = class extends Error {
40
+ constructor() {
41
+ super("Original container opening replay"), this.name = "OpeningReplay";
42
+ }
43
+ }, ie = (e) => {
44
+ let c = i(e, [
45
+ "containers",
46
+ "currencies",
47
+ "realMoney",
48
+ "economy",
49
+ "inventory",
50
+ "accessSource",
51
+ "version",
52
+ "probability",
53
+ "roll",
54
+ "random",
55
+ "eligibility",
56
+ "priceResolver",
57
+ "systemAccount",
58
+ "maxHistoryRows",
59
+ "now"
60
+ ]), l = o(c.currencies), u = c.realMoney ?? !1;
61
+ if (typeof u != "boolean") throw t("invalid_input");
62
+ let f = Object.freeze(r(c.containers, 256).map((e) => _(e, l, u)));
63
+ if (!f.length || new Set(f.map((e) => e.id)).size !== f.length) throw t("invalid_input");
64
+ for (let e of f) if (f.some((t) => t.group === e.group && JSON.stringify(t.pity) !== JSON.stringify(e.pity))) throw t("invalid_input");
65
+ let p = n(c.economy, ["prepareTransfer"]), v = c.inventory === void 0 ? void 0 : n(c.inventory, ["prepareGrant"]);
66
+ if (f.some((e) => e.drops.some((e) => e.items.length)) && !v) throw t("invalid_input");
67
+ let y = n(c.accessSource, ["read"]), b = n(c.random ?? S, ["draw"]), x = c.probability ?? h, C = c.roll ?? g, w = c.eligibility ?? m, T = c.priceResolver ?? s, E = c.now ?? Date.now;
68
+ if ([
69
+ x,
70
+ C,
71
+ w,
72
+ T,
73
+ E
74
+ ].some((e) => typeof e != "function")) throw t("invalid_input");
75
+ let D = a(c.version);
76
+ if (D === "default.v1") throw t("invalid_input");
77
+ return Object.freeze({
78
+ containers: f,
79
+ currencies: l,
80
+ realMoney: u,
81
+ economy: p,
82
+ inventory: v,
83
+ accessSource: y,
84
+ random: b,
85
+ version: D,
86
+ probability: x,
87
+ roll: C,
88
+ eligibility: w,
89
+ priceResolver: T,
90
+ systemAccount: a(c.systemAccount ?? "containers"),
91
+ maxHistoryRows: d(c.maxHistoryRows ?? 1e4, 1, 1e5),
92
+ now: E
93
+ });
94
+ }, U = (n, r) => {
95
+ let s = ie(r), m = k("economy.containers"), S = () => d(s.now(), 0, 864e13), O = (e, t) => F("eus_", e, t), A = (e, t, n) => F("euo_", e, t, n), N = (e, t, n, r, i, a) => P([
96
+ e,
97
+ t,
98
+ n,
99
+ r,
100
+ i,
101
+ a
102
+ ]), L = (e) => {
103
+ let n = structuredClone(e);
104
+ if (n.type !== "user") throw t("forbidden");
105
+ return Object.freeze({
106
+ tenant: a(n.tenantId),
107
+ owner: a(n.id)
108
+ });
109
+ }, U = async (e, t) => {
110
+ await n.insertIgnore(E.tableName, {
111
+ id: F("eut_", e),
112
+ tenantId: e,
113
+ admission: 0
114
+ }, { conflictColumns: ["id"] }), await n.insertIgnore(T.tableName, {
115
+ id: O(e, t),
116
+ tenantId: e,
117
+ ownerId: t,
118
+ erased: !1,
119
+ admission: 0,
120
+ pendingId: null
121
+ }, { conflictColumns: ["id"] });
122
+ }, W = async (e, n, r, i = !1) => {
123
+ let a = F("eut_", n);
124
+ if (await e.updateMany(E.tableName, { admission: 0 }, { where: j("id", a) }) !== 1) throw t("unavailable");
125
+ let o = (await e.query(M(E).where(j("id", a)).limit(1).descriptor))[0];
126
+ if (!o || o.tenantId !== n || o.admission !== 0) throw t("invalid_record");
127
+ let s = O(n, r);
128
+ if (await e.updateMany(T.tableName, { admission: 0 }, { where: j("id", s) }) !== 1) throw t("unavailable");
129
+ let c = (await e.query(M(T).where(j("id", s)).limit(1).descriptor))[0];
130
+ if (!c || c.tenantId !== n || c.admission !== 0 || c.erased !== !0 && c.erased !== !1 || c.erased === !1 && c.ownerId !== r || c.erased === !0 && (c.ownerId !== null || c.pendingId !== null)) throw t("invalid_record");
131
+ if (c.erased === !0 && !i) throw t("erased");
132
+ if (c.pendingId !== null && !/^euo_[a-f0-9]{56}$/.test(String(c.pendingId))) throw t("invalid_record");
133
+ return c;
134
+ }, G = async (e, n, r, i) => {
135
+ let a = (await e.query(M(w).where(j("id", i)).limit(1).descriptor))[0];
136
+ if (a && (a.tenantId !== n || a.ownerKey !== O(n, r) || a.ownerId !== r)) throw t("invalid_record");
137
+ return a;
138
+ }, K = (e) => {
139
+ let n = i(e.intent, [
140
+ "request",
141
+ "container",
142
+ "currencies",
143
+ "realMoney",
144
+ "rulesVersion",
145
+ "basis",
146
+ "misses",
147
+ "distribution",
148
+ "at",
149
+ "probabilityDefault",
150
+ "rollDefault"
151
+ ], "invalid_record"), r = i(n.request, [
152
+ "containerId",
153
+ "containerVersion",
154
+ "containerDigest",
155
+ "disclosureDigest",
156
+ "requestId",
157
+ "currency"
158
+ ], "invalid_record"), s = p({
159
+ containerId: r.containerId,
160
+ containerVersion: r.containerVersion,
161
+ containerDigest: r.containerDigest,
162
+ disclosureDigest: r.disclosureDigest,
163
+ requestId: r.requestId,
164
+ currency: r.currency === null ? void 0 : r.currency
165
+ }), c = o(n.currencies);
166
+ if (typeof n.realMoney != "boolean" || typeof n.probabilityDefault != "boolean" || typeof n.rollDefault != "boolean") throw t("invalid_record");
167
+ let l = _(n.container, c, n.realMoney), u = a(n.rulesVersion), f = d(n.basis, 0, 1e5), m = d(n.misses, 0, l.pity ? l.pity.after - 1 : 0), h = d(n.at, 0, 864e13), g = i(n.distribution, [
168
+ "entries",
169
+ "total",
170
+ "guaranteed"
171
+ ], "invalid_record"), v = {
172
+ container: l,
173
+ currencies: c,
174
+ realMoney: n.realMoney,
175
+ misses: m
176
+ }, b = y(v, () => g.entries);
177
+ if (g.total !== b.total || g.guaranteed !== b.guaranteed || n.probabilityDefault && JSON.stringify(b) !== JSON.stringify(y(v)) || e.id !== A(a(e.tenantId), a(e.ownerId), s.requestId) || e.ownerKey !== O(String(e.tenantId), String(e.ownerId)) || e.digest !== P([
178
+ e.tenantId,
179
+ e.ownerId,
180
+ s
181
+ ]) || s.containerId !== l.id || s.containerVersion !== l.version || s.containerDigest !== I(l, u) || s.disclosureDigest !== N(String(e.tenantId), String(e.ownerId), s.containerDigest, f, m, b) || V(e.createdAt) !== h) throw t("invalid_record");
182
+ return Object.freeze({
183
+ request: s,
184
+ container: l,
185
+ currencies: c,
186
+ realMoney: n.realMoney,
187
+ rulesVersion: u,
188
+ basis: f,
189
+ misses: m,
190
+ distribution: b,
191
+ at: h,
192
+ probabilityDefault: n.probabilityDefault,
193
+ rollDefault: n.rollDefault
194
+ });
195
+ }, q = (e) => {
196
+ let n = K(e), r = i(e.selection, [
197
+ "draw",
198
+ "distribution",
199
+ "dropId",
200
+ "misses",
201
+ "price",
202
+ "adjustments",
203
+ "at"
204
+ ], "invalid_record"), o = {
205
+ container: n.container,
206
+ currencies: n.currencies,
207
+ realMoney: n.realMoney,
208
+ misses: n.misses
209
+ }, s = i(r.distribution, [
210
+ "entries",
211
+ "total",
212
+ "guaranteed"
213
+ ], "invalid_record"), u = y(o, () => s.entries);
214
+ if (u.total !== s.total || u.guaranteed !== s.guaranteed || JSON.stringify(u) !== JSON.stringify(n.distribution)) throw t("invalid_record");
215
+ let f = x(o, r.draw, () => u.entries, n.rollDefault ? g : () => a(r.dropId));
216
+ if (f.drop.id !== r.dropId || f.misses !== r.misses) throw t("invalid_record");
217
+ let p = c(n.container.price, n.currencies, n.realMoney, r.adjustments), m = l(p, () => r.price), h = d(r.at, n.at, 864e13);
218
+ return Object.freeze({
219
+ intent: n,
220
+ distribution: u,
221
+ drop: f.drop,
222
+ misses: f.misses,
223
+ price: m,
224
+ adjustments: p.adjustments,
225
+ at: h,
226
+ draw: r.draw
227
+ });
228
+ }, J = (e) => {
229
+ if (e.state !== "fulfilled" || e.sequence === null || e.ownerId === null) throw t("invalid_record");
230
+ let n = q(e), { intent: r, drop: o } = n, s = i(e.receipt, [
231
+ "operationId",
232
+ "containerId",
233
+ "containerVersion",
234
+ "containerDigest",
235
+ "dropId",
236
+ "rarity",
237
+ "previousMisses",
238
+ "misses",
239
+ "sequence",
240
+ "at",
241
+ "distribution",
242
+ "pricePaid",
243
+ "transfers",
244
+ "grants"
245
+ ], "invalid_record"), c = d(s.at, n.at, 864e13), l = d(s.sequence, 1, 1e5), p = f(n.price, r.request.currency, 1);
246
+ if (s.operationId !== e.id || s.containerId !== r.container.id || s.containerVersion !== r.container.version || s.containerDigest !== r.request.containerDigest || s.dropId !== o.id || s.rarity !== o.rarity || s.previousMisses !== r.misses || s.misses !== n.misses || l !== e.sequence || l !== r.basis + 1 || V(e.fulfilledAt) !== c) throw t("invalid_record");
247
+ let m = u({
248
+ orderId: e.id,
249
+ offerId: r.container.id,
250
+ offerVersion: r.container.version,
251
+ offerDigest: r.request.containerDigest,
252
+ quantity: 1,
253
+ at: c,
254
+ pricePaid: s.pricePaid,
255
+ transfers: s.transfers,
256
+ grants: s.grants
257
+ }), h = i(s.distribution, [
258
+ "entries",
259
+ "total",
260
+ "guaranteed"
261
+ ], "invalid_record"), g = y({
262
+ container: r.container,
263
+ currencies: r.currencies,
264
+ realMoney: r.realMoney,
265
+ misses: r.misses
266
+ }, () => h.entries);
267
+ if (JSON.stringify(m.pricePaid) !== JSON.stringify(p) || h.total !== g.total || h.guaranteed !== g.guaranteed || JSON.stringify(g) !== JSON.stringify(n.distribution)) throw t("invalid_record");
268
+ let _ = [...p.kind === "virtual" && BigInt(p.amount) > 0n ? [{
269
+ currency: p.currency,
270
+ amount: p.amount
271
+ }] : [], ...o.currencies];
272
+ if (m.transfers.length !== _.length || m.grants.length !== o.items.length || m.transfers.some((e, t) => e.currency !== _[t].currency || e.amount !== _[t].amount || e.at < r.at || e.at > c) || m.grants.some((e, t) => e.at < r.at || e.at > c || e.changes.reduce((e, t) => e + t.delta, 0) !== o.items[t].qty)) throw t("invalid_record");
273
+ return Object.freeze({
274
+ operationId: a(e.id),
275
+ containerId: r.container.id,
276
+ containerVersion: r.container.version,
277
+ containerDigest: r.request.containerDigest,
278
+ dropId: o.id,
279
+ rarity: o.rarity,
280
+ previousMisses: r.misses,
281
+ misses: n.misses,
282
+ sequence: l,
283
+ at: c,
284
+ distribution: n.distribution,
285
+ pricePaid: p,
286
+ transfers: m.transfers,
287
+ grants: m.grants
288
+ });
289
+ }, Y = async (e, n, r, i = !1) => {
290
+ let a = await e.query(M(w).where(ee(j("tenantId", n), j("ownerKey", O(n, r)))).limit(s.maxHistoryRows + 1).descriptor);
291
+ if (a.length > s.maxHistoryRows) throw t("limit_exceeded");
292
+ let o = [];
293
+ for (let e of a) {
294
+ if (!/^euo_[a-f0-9]{56}$/.test(String(e.id)) || e.ownerKey !== O(n, r) || e.tenantId !== n) throw t("invalid_record");
295
+ if (e.state === "erased") {
296
+ if (!i) throw t("erased");
297
+ if (e.ownerId !== null || e.digest !== null || e.intent !== null || e.selection !== null || e.receipt !== null) throw t("invalid_record");
298
+ } else {
299
+ if (e.ownerId !== r) throw t("invalid_record");
300
+ if (e.state === "fulfilled") o.push({
301
+ row: e,
302
+ receipt: J(e),
303
+ intent: K(e)
304
+ });
305
+ else if (e.state === "pending") {
306
+ if (K(e), e.selection !== null && q(e), e.receipt !== null || e.sequence !== null || e.fulfilledAt !== null) throw t("invalid_record");
307
+ } else throw t("invalid_record");
308
+ }
309
+ }
310
+ if (o.sort((e, t) => e.receipt.sequence - t.receipt.sequence), a.filter((e) => e.state === "pending").length > 1 || o.some((e, t) => e.receipt.sequence !== t + 1 || t > 0 && e.receipt.at < o[t - 1].receipt.at)) throw t("invalid_record");
311
+ return {
312
+ rows: a,
313
+ accepted: o
314
+ };
315
+ }, X = (e, n) => {
316
+ let r = 0;
317
+ for (let i of e) if (i.intent.container.group === n.group) {
318
+ if (JSON.stringify(i.intent.container.pity) !== JSON.stringify(n.pity) || i.receipt.previousMisses !== r) throw t("conflict");
319
+ r = i.receipt.misses;
320
+ }
321
+ return r;
322
+ }, Z = async (e, n, r, a) => {
323
+ let o = s.accessSource.read(Object.freeze({
324
+ tenantId: e,
325
+ ownerId: n,
326
+ container: r,
327
+ at: a
328
+ }));
329
+ if (!D.isEffect(o)) throw t("invalid_input");
330
+ let u = i(await B(o), [
331
+ "isMinor",
332
+ "country",
333
+ "eligible",
334
+ "adjustments"
335
+ ]);
336
+ if (typeof u.isMinor != "boolean" || typeof u.eligible != "boolean" || typeof u.country != "string" || !/^[A-Z]{2}$/.test(u.country)) throw t("invalid_input");
337
+ let d = Object.freeze({
338
+ container: r,
339
+ at: a,
340
+ isMinor: u.isMinor,
341
+ country: u.country,
342
+ eligible: u.eligible
343
+ });
344
+ if (!b(d, s.currencies, s.realMoney, s.eligibility)) throw t("forbidden");
345
+ let f = c(r.price, s.currencies, s.realMoney, u.adjustments);
346
+ return {
347
+ price: l(f, s.priceResolver),
348
+ adjustments: f.adjustments
349
+ };
350
+ }, Q = async (e, r, i, a) => n.transactional(async (n) => {
351
+ let o = await W(n, e, r), s = await G(n, e, r, i);
352
+ if (s && s.digest !== a) throw t("conflict");
353
+ if (s?.state === "fulfilled") return {
354
+ row: s,
355
+ receipt: J(s)
356
+ };
357
+ if (s && (s.state !== "pending" || o.pendingId !== i)) throw t("invalid_record");
358
+ return {
359
+ row: s,
360
+ receipt: void 0
361
+ };
362
+ }), ae = (e, r) => z(() => {
363
+ let { tenant: i, owner: a } = L(e), o = p(r), c = A(i, a, o.requestId), l = P([
364
+ i,
365
+ a,
366
+ o
367
+ ]);
368
+ return R(async () => {
369
+ await U(i, a);
370
+ let e = await Q(i, a, c, l);
371
+ if (e.receipt) return e.receipt;
372
+ if (!e.row) {
373
+ let r = s.containers.find((e) => e.id === o.containerId);
374
+ if (!r) throw t("not_found");
375
+ if (r.version !== o.containerVersion || I(r, s.version) !== o.containerDigest) throw t("conflict");
376
+ f(r.price, o.currency, 1);
377
+ let u = S();
378
+ await Z(i, a, r, u);
379
+ let d = await n.transactional(async (e) => {
380
+ await W(e, i, a);
381
+ let t = await Y(e, i, a);
382
+ return {
383
+ basis: t.accepted.length,
384
+ misses: X(t.accepted, r)
385
+ };
386
+ }), p = y({
387
+ container: r,
388
+ currencies: s.currencies,
389
+ realMoney: s.realMoney,
390
+ misses: d.misses
391
+ }, s.probability);
392
+ if (o.disclosureDigest !== N(i, a, o.containerDigest, d.basis, d.misses, p)) throw t("conflict");
393
+ if (await n.transactional(async (e) => {
394
+ let n = await W(e, i, a), f = await G(e, i, a, c);
395
+ if (f) {
396
+ if (f.digest !== l) throw t("conflict");
397
+ return;
398
+ }
399
+ if (n.pendingId !== null) throw t("conflict");
400
+ let m = await Y(e, i, a);
401
+ if (m.rows.length >= s.maxHistoryRows) throw t("limit_exceeded");
402
+ if (m.rows.some((e) => e.state === "pending") || (m.accepted.at(-1)?.receipt.at ?? 0) > u) throw t("invalid_record");
403
+ let v = X(m.accepted, r), y = F("eud_", i, r.id, r.version, s.version);
404
+ if (m.accepted.length !== d.basis || v !== d.misses) throw t("conflict");
405
+ let b = (await e.query(M(C).where(j("id", y)).limit(1).descriptor))[0];
406
+ if (b) {
407
+ if (b.tenantId !== i || b.rulesVersion !== s.version || typeof b.realMoney != "boolean" || I(_(b.definition, b.currencies, b.realMoney), s.version) !== o.containerDigest) throw t("conflict");
408
+ } else await e.insert(C.tableName, {
409
+ id: y,
410
+ tenantId: i,
411
+ definition: r,
412
+ currencies: s.currencies,
413
+ realMoney: s.realMoney,
414
+ rulesVersion: s.version,
415
+ createdAt: new Date(u)
416
+ });
417
+ await e.insert(w.tableName, {
418
+ id: c,
419
+ tenantId: i,
420
+ ownerId: a,
421
+ ownerKey: O(i, a),
422
+ state: "pending",
423
+ digest: l,
424
+ intent: {
425
+ request: o,
426
+ container: r,
427
+ currencies: s.currencies,
428
+ realMoney: s.realMoney,
429
+ rulesVersion: s.version,
430
+ basis: m.accepted.length,
431
+ misses: v,
432
+ distribution: p,
433
+ at: u,
434
+ probabilityDefault: s.probability === h,
435
+ rollDefault: s.roll === g
436
+ },
437
+ selection: null,
438
+ receipt: null,
439
+ sequence: null,
440
+ createdAt: new Date(u),
441
+ fulfilledAt: null
442
+ }), await e.update(T.tableName, O(i, a), { pendingId: c });
443
+ }), e = await Q(i, a, c, l), e.receipt) return e.receipt;
444
+ }
445
+ if (!e.row) throw t("invalid_record");
446
+ let r = K(e.row);
447
+ if (r.rulesVersion !== s.version || !s.containers.some((e) => I(e, s.version) === r.request.containerDigest)) throw t("conflict");
448
+ let u = S();
449
+ if (u < r.at) throw t("invalid_record");
450
+ let d = await Z(i, a, r.container, u);
451
+ if (e.row.selection === null) {
452
+ let o = {
453
+ container: r.container,
454
+ currencies: r.currencies,
455
+ realMoney: r.realMoney,
456
+ misses: r.misses
457
+ }, f = r.distribution, p = await B(s.random.draw(f.total)), m = x(o, p, () => f.entries, s.roll), h = {
458
+ draw: p,
459
+ distribution: f,
460
+ dropId: m.drop.id,
461
+ misses: m.misses,
462
+ price: d.price,
463
+ adjustments: d.adjustments,
464
+ at: u
465
+ };
466
+ if (await n.transactional(async (e) => {
467
+ let n = await W(e, i, a), r = await G(e, i, a, c);
468
+ if (!r || r.digest !== l) throw t("invalid_record");
469
+ if (r.state !== "fulfilled") {
470
+ if (r.state !== "pending" || n.pendingId !== c) throw t("conflict");
471
+ r.selection === null && await e.update(w.tableName, c, { selection: h });
472
+ }
473
+ }), e = await Q(i, a, c, l), e.receipt) return e.receipt;
474
+ }
475
+ if (!e.row) throw t("invalid_record");
476
+ let p = q(e.row), v = f(p.price, o.currency, 1), b = [];
477
+ b.push(ne(n, async (e) => {
478
+ let n = await W(e, i, a), o = await G(e, i, a, c);
479
+ if (!o || o.digest !== l) throw t("invalid_record");
480
+ if (o.state === "fulfilled") throw J(o), new H();
481
+ if (o.state !== "pending" || n.pendingId !== c || JSON.stringify(q(o)) !== JSON.stringify(p)) throw t("conflict");
482
+ let s = await Y(e, i, a);
483
+ if (s.accepted.length !== r.basis || X(s.accepted, r.container) !== r.misses) throw t("conflict");
484
+ return null;
485
+ })), v.kind === "virtual" && BigInt(v.amount) > 0n && b.push(await B(s.economy.prepareTransfer(m, {
486
+ tenantId: i,
487
+ requestId: F("euk_", c, "debit"),
488
+ currency: v.currency,
489
+ amount: v.amount,
490
+ from: {
491
+ kind: "wallet",
492
+ ownerKind: "player",
493
+ ownerId: a
494
+ },
495
+ to: {
496
+ kind: "system",
497
+ id: s.systemAccount
498
+ },
499
+ reason: "container.open",
500
+ ref: {
501
+ kind: "container-opening",
502
+ id: c
503
+ }
504
+ })));
505
+ for (let [e, t] of p.drop.currencies.entries()) b.push(await B(s.economy.prepareTransfer(m, {
506
+ tenantId: i,
507
+ requestId: F("euk_", c, "gift", String(e)),
508
+ currency: t.currency,
509
+ amount: t.amount,
510
+ from: {
511
+ kind: "system",
512
+ id: s.systemAccount
513
+ },
514
+ to: {
515
+ kind: "wallet",
516
+ ownerKind: "player",
517
+ ownerId: a
518
+ },
519
+ reason: "container.reward",
520
+ ref: {
521
+ kind: "container-opening",
522
+ id: c
523
+ }
524
+ })));
525
+ for (let [e, n] of p.drop.items.entries()) {
526
+ if (!s.inventory) throw t("unavailable");
527
+ b.push(await B(s.inventory.prepareGrant(m, {
528
+ tenantId: i,
529
+ owner: {
530
+ ownerKind: "player",
531
+ ownerId: a
532
+ },
533
+ itemId: n.itemId,
534
+ qty: n.qty,
535
+ requestId: F("euk_", c, "item", String(e)),
536
+ reason: "container.reward",
537
+ ref: {
538
+ kind: "container-opening",
539
+ id: c
540
+ }
541
+ })));
542
+ }
543
+ let E = S();
544
+ if (E < u) throw t("invalid_record");
545
+ let D = p.drop.currencies.length + +(v.kind === "virtual" && BigInt(v.amount) > 0n), k = re(n, b, async (e, n) => {
546
+ let s = {
547
+ operationId: c,
548
+ containerId: r.container.id,
549
+ containerVersion: r.container.version,
550
+ containerDigest: o.containerDigest,
551
+ dropId: p.drop.id,
552
+ rarity: p.drop.rarity,
553
+ previousMisses: r.misses,
554
+ misses: p.misses,
555
+ sequence: r.basis + 1,
556
+ at: E,
557
+ distribution: p.distribution,
558
+ pricePaid: v,
559
+ transfers: n.slice(1, 1 + D),
560
+ grants: n.slice(1 + D)
561
+ };
562
+ await e.update(w.tableName, c, {
563
+ state: "fulfilled",
564
+ sequence: s.sequence,
565
+ receipt: s,
566
+ fulfilledAt: new Date(E)
567
+ }), await e.update(T.tableName, O(i, a), { pendingId: null });
568
+ let l = await G(e, i, a, c);
569
+ if (!l) throw t("invalid_record");
570
+ return J(l);
571
+ });
572
+ try {
573
+ return (await te(n, [k]))[0];
574
+ } catch (e) {
575
+ if (e instanceof H) {
576
+ let e = await Q(i, a, c, l);
577
+ if (e.receipt) return e.receipt;
578
+ }
579
+ throw e;
580
+ }
581
+ });
582
+ }), $ = async (e, n, r) => {
583
+ let i = (await e.query(M(T).where(j("id", O(n, r))).limit(1).descriptor))[0];
584
+ if (i && (i.tenantId !== n || i.erased !== !0 && i.erased !== !1 || i.erased === !1 && i.ownerId !== r || i.erased === !0 && i.ownerId !== null)) throw t("invalid_record");
585
+ if (i?.erased === !0) throw t("erased");
586
+ if (!i && (await e.query(M(w).where(ee(j("tenantId", n), j("ownerKey", O(n, r)))).limit(1).descriptor)).length) throw t("invalid_record");
587
+ }, oe = (e, r) => z(() => {
588
+ let { tenant: i, owner: a } = L(e), o = p(r), s = A(i, a, o.requestId), c = P([
589
+ i,
590
+ a,
591
+ o
592
+ ]);
593
+ return R(async () => n.transactional(async (e) => {
594
+ await $(e, i, a);
595
+ let n = await G(e, i, a, s);
596
+ if (!n) return Object.freeze({
597
+ requestId: o.requestId,
598
+ state: "not-observed"
599
+ });
600
+ if (n.digest !== c) throw t("conflict");
601
+ if (n.state === "fulfilled") return Object.freeze({
602
+ requestId: o.requestId,
603
+ state: "fulfilled",
604
+ receipt: J(n)
605
+ });
606
+ if (n.state !== "pending") throw t("invalid_record");
607
+ return K(n), n.selection !== null && q(n), Object.freeze({
608
+ requestId: o.requestId,
609
+ state: "pending"
610
+ });
611
+ }));
612
+ }), se = (t) => z(() => {
613
+ let { tenant: r, owner: i } = L(t);
614
+ return R(async () => {
615
+ let t = await n.transactional(async (e) => (await $(e, r, i), Y(e, r, i))), a = S(), o = [];
616
+ for (let n of s.containers) try {
617
+ let e = await Z(r, i, n, a), c = X(t.accepted, n), l = {
618
+ container: n,
619
+ misses: c,
620
+ currencies: s.currencies,
621
+ realMoney: s.realMoney
622
+ }, u = I(n, s.version), d = y(l, s.probability);
623
+ o.push(Object.freeze({
624
+ container: n,
625
+ containerDigest: u,
626
+ disclosureDigest: N(r, i, u, t.accepted.length, c, d),
627
+ misses: c,
628
+ price: e.price,
629
+ disclosure: v(l, () => d.entries)
630
+ }));
631
+ } catch (t) {
632
+ if (!(t instanceof e) || t.code !== "forbidden") throw t;
633
+ }
634
+ return Object.freeze(o);
635
+ });
636
+ }), ce = (e) => {
637
+ let n = i(e, [
638
+ "tenantId",
639
+ "subjectId",
640
+ "kind"
641
+ ]);
642
+ if (n.kind !== "guest" && n.kind !== "user") throw t("invalid_input");
643
+ return {
644
+ tenant: a(n.tenantId),
645
+ owner: a(n.subjectId)
646
+ };
647
+ };
648
+ return Object.freeze({
649
+ list: se,
650
+ open: ae,
651
+ receipt: oe,
652
+ exportSubject: (e) => z(() => {
653
+ let { tenant: r, owner: i } = ce(e);
654
+ return R(async () => n.transactional(async (e) => {
655
+ let n = (await e.query(M(T).where(j("id", O(r, i))).limit(1).descriptor))[0];
656
+ if (n?.erased === !0) {
657
+ if (n.tenantId !== r || n.ownerId !== null) throw t("invalid_record");
658
+ return { openings: [] };
659
+ }
660
+ return await $(e, r, i), { openings: (await Y(e, r, i)).rows };
661
+ }));
662
+ }),
663
+ eraseSubject: (e) => z(() => {
664
+ let { tenant: t, owner: r } = ce(e);
665
+ return R(async () => {
666
+ await U(t, r), await n.transactional(async (e) => {
667
+ await W(e, t, r, !0);
668
+ let n = await Y(e, t, r, !0);
669
+ for (let t of n.rows) await e.update(w.tableName, String(t.id), {
670
+ ownerId: null,
671
+ state: "erased",
672
+ digest: null,
673
+ intent: null,
674
+ selection: null,
675
+ receipt: null
676
+ });
677
+ await e.update(T.tableName, O(t, r), {
678
+ ownerId: null,
679
+ erased: !0,
680
+ pendingId: null
681
+ });
682
+ });
683
+ });
684
+ })
685
+ });
686
+ };
687
+ export { I as containerDefinitionDigest, U as dataStoreContainers, ie as resolveContainersStoreOptions };