@voltro/plugin-economy 0.0.0-stage → 0.87.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 +24329 -0
  2. package/LICENSE +61 -0
  3. package/README.md +2719 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +9189 -0
  6. package/dist/amount.js +21 -0
  7. package/dist/appleIap.server.js +263 -0
  8. package/dist/appleIapNotifications.server.js +163 -0
  9. package/dist/appleIapTrust.server.js +31 -0
  10. package/dist/bundleValue.server.js +113 -0
  11. package/dist/canonicalDataJson.js +11 -0
  12. package/dist/capture.js +54 -0
  13. package/dist/codePort.fixture.js +124 -0
  14. package/dist/codeStore.server.js +440 -0
  15. package/dist/codeTables.entity.js +44 -0
  16. package/dist/codes.d.ts +150 -0
  17. package/dist/codes.js +83 -0
  18. package/dist/components.d.ts +397 -0
  19. package/dist/components.js +284 -0
  20. package/dist/consistency.server.js +116 -0
  21. package/dist/containerStore.server.js +688 -0
  22. package/dist/containerStore.testFixtures.js +76 -0
  23. package/dist/containerTables.entity.js +46 -0
  24. package/dist/containers.d.ts +311 -0
  25. package/dist/containers.fixture.js +129 -0
  26. package/dist/containers.js +215 -0
  27. package/dist/containers.server.js +40 -0
  28. package/dist/containersPort.fixture.js +75 -0
  29. package/dist/currency.js +33 -0
  30. package/dist/declarationFixtures.js +62 -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 +125 -0
  34. package/dist/errors.d.ts +14 -0
  35. package/dist/errors.js +22 -0
  36. package/dist/events.d.ts +46 -0
  37. package/dist/events.js +1 -0
  38. package/dist/googleIap.server.js +392 -0
  39. package/dist/googleIapNotifications.server.js +131 -0
  40. package/dist/googleIapSubscription.server.js +184 -0
  41. package/dist/iap.d.ts +309 -0
  42. package/dist/iap.js +304 -0
  43. package/dist/iap.testFixtures.js +145 -0
  44. package/dist/iapAccountTables.entity.js +40 -0
  45. package/dist/iapAccounts.server.js +201 -0
  46. package/dist/iapBinding.server.js +524 -0
  47. package/dist/iapCheckout.server.js +98 -0
  48. package/dist/iapCompletion.server.js +56 -0
  49. package/dist/iapCurrentState.server.js +108 -0
  50. package/dist/iapCurrentState.testFixtures.js +23 -0
  51. package/dist/iapCurrentStatePort.fixture.js +64 -0
  52. package/dist/iapEntitlements.d.ts +79 -0
  53. package/dist/iapEntitlements.js +58 -0
  54. package/dist/iapEntitlements.server.js +49 -0
  55. package/dist/iapEntitlementsBinding.server.js +106 -0
  56. package/dist/iapEntitlementsPort.fixture.js +81 -0
  57. package/dist/iapInstalledEntitlements.testFixtures.js +76 -0
  58. package/dist/iapInstalledNotifications.testFixtures.js +94 -0
  59. package/dist/iapInventoryRefunds.server.js +262 -0
  60. package/dist/iapNotificationCustodyPort.fixture.js +68 -0
  61. package/dist/iapNotificationPort.fixture.js +74 -0
  62. package/dist/iapNotificationProcessor.server.js +135 -0
  63. package/dist/iapNotificationProcessor.testFixtures.js +64 -0
  64. package/dist/iapNotificationProcessorPort.fixture.js +56 -0
  65. package/dist/iapNotificationSchedule.server.js +70 -0
  66. package/dist/iapNotificationStore.server.js +353 -0
  67. package/dist/iapNotificationStore.testFixtures.js +32 -0
  68. package/dist/iapNotificationTables.entity.js +49 -0
  69. package/dist/iapNotificationTarget.server.js +37 -0
  70. package/dist/iapNotificationTarget.testFixtures.js +30 -0
  71. package/dist/iapNotifications.d.ts +644 -0
  72. package/dist/iapNotifications.js +6 -0
  73. package/dist/iapNotifications.server.js +96 -0
  74. package/dist/iapNotificationsBinding.server.js +233 -0
  75. package/dist/iapNotificationsSystemPort.fixture.js +51 -0
  76. package/dist/iapPlugin.testFixtures.js +60 -0
  77. package/dist/iapPort.fixture.js +75 -0
  78. package/dist/iapProviderCapture.server.js +18 -0
  79. package/dist/iapRecovery.d.ts +146 -0
  80. package/dist/iapRecovery.js +90 -0
  81. package/dist/iapRefundEventDelivery.server.js +83 -0
  82. package/dist/iapRefundEvents.js +45 -0
  83. package/dist/iapRefundEventsPort.fixture.js +60 -0
  84. package/dist/iapRefundPort.fixture.js +55 -0
  85. package/dist/iapRefundTables.entity.js +56 -0
  86. package/dist/iapRefunds.d.ts +755 -0
  87. package/dist/iapRefunds.js +6 -0
  88. package/dist/iapRefunds.server.js +554 -0
  89. package/dist/iapRefunds.testFixtures.js +65 -0
  90. package/dist/iapSpendAdmission.server.js +99 -0
  91. package/dist/iapStore.server.js +741 -0
  92. package/dist/iapStore.testFixtures.js +128 -0
  93. package/dist/iapTables.entity.js +81 -0
  94. package/dist/iapVerification.server.js +121 -0
  95. package/dist/index.d.ts +2984 -0
  96. package/dist/index.js +15 -0
  97. package/dist/intentionRecovery.js +134 -0
  98. package/dist/ledger.js +78 -0
  99. package/dist/loyalty.d.ts +274 -0
  100. package/dist/loyalty.fixture.js +93 -0
  101. package/dist/loyalty.js +312 -0
  102. package/dist/loyaltyBinding.server.js +204 -0
  103. package/dist/loyaltyPort.fixture.js +87 -0
  104. package/dist/loyaltyShopSource.server.js +91 -0
  105. package/dist/loyaltyStore.server.js +553 -0
  106. package/dist/loyaltyStore.testFixtures.js +83 -0
  107. package/dist/loyaltyTables.entity.js +50 -0
  108. package/dist/offerMerchandising.fixture.js +115 -0
  109. package/dist/offerMerchandising.js +283 -0
  110. package/dist/offerPolicies.d.ts +441 -0
  111. package/dist/offerPolicies.fixture.js +54 -0
  112. package/dist/offerPolicies.js +268 -0
  113. package/dist/piggyBanks.d.ts +272 -0
  114. package/dist/piggyBanks.fixture.js +71 -0
  115. package/dist/piggyBanks.js +201 -0
  116. package/dist/piggyBinding.server.js +205 -0
  117. package/dist/piggyPort.fixture.js +73 -0
  118. package/dist/piggyStore.server.js +611 -0
  119. package/dist/piggyStore.testFixtures.js +98 -0
  120. package/dist/piggyTables.entity.js +41 -0
  121. package/dist/plugin.js +1048 -0
  122. package/dist/port.js +13 -0
  123. package/dist/price.d.ts +99 -0
  124. package/dist/price.js +144 -0
  125. package/dist/purchaseRecovery.js +56 -0
  126. package/dist/reports.server.js +115 -0
  127. package/dist/rpc.d.ts +3201 -0
  128. package/dist/rpc.js +1201 -0
  129. package/dist/sanctionsTradeAuthority.server.js +80 -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 +196 -0
  134. package/dist/shop.testFixtures.js +114 -0
  135. package/dist/shopPort.fixture.js +72 -0
  136. package/dist/shopPresentation.js +68 -0
  137. package/dist/shopStore.server.js +624 -0
  138. package/dist/shopTables.entity.js +63 -0
  139. package/dist/shopUiCopy.js +57 -0
  140. package/dist/spendLimits.d.ts +140 -0
  141. package/dist/spendLimits.fixture.js +53 -0
  142. package/dist/spendLimits.js +155 -0
  143. package/dist/spendLimitsPort.fixture.js +120 -0
  144. package/dist/subscriptionBinding.server.js +211 -0
  145. package/dist/subscriptionStore.server.js +643 -0
  146. package/dist/subscriptionStore.testFixtures.js +72 -0
  147. package/dist/subscriptionTables.entity.js +37 -0
  148. package/dist/subscriptions.d.ts +394 -0
  149. package/dist/subscriptions.fixture.js +97 -0
  150. package/dist/subscriptions.js +213 -0
  151. package/dist/subscriptionsPort.fixture.js +76 -0
  152. package/dist/systemFixtures.js +89 -0
  153. package/dist/tables.entity.js +83 -0
  154. package/dist/testing.d.ts +4615 -0
  155. package/dist/testing.js +29 -0
  156. package/dist/tradeAuthority.server.js +172 -0
  157. package/dist/tradeBinding.server.js +201 -0
  158. package/dist/tradeComponents.js +342 -0
  159. package/dist/tradeEscrow.server.js +232 -0
  160. package/dist/tradeEscrow.testFixtures.js +133 -0
  161. package/dist/tradeExpiry.server.js +43 -0
  162. package/dist/tradeRecovery.js +48 -0
  163. package/dist/tradeStore.server.js +750 -0
  164. package/dist/tradeStore.testFixtures.js +73 -0
  165. package/dist/tradeTables.entity.js +66 -0
  166. package/dist/tradeUiCopy.js +79 -0
  167. package/dist/trades.d.ts +246 -0
  168. package/dist/trades.fixture.js +103 -0
  169. package/dist/trades.js +289 -0
  170. package/dist/tradesPort.fixture.js +94 -0
  171. package/dist/walletEscrow.js +106 -0
  172. package/dist/walletEscrow.server.js +376 -0
  173. package/dist/walletKeys.server.js +5 -0
  174. package/dist/walletStore.js +571 -0
  175. package/dist/web.d.ts +2257 -0
  176. package/dist/web.js +9 -0
  177. package/package.json +161 -4
@@ -0,0 +1,571 @@
1
+ import { EconomyError as e, economyError as t } from "./errors.js";
2
+ import { dataList as n, dataObject as r, identifier as i } from "./capture.js";
3
+ import { economyAmount as a, economyAmountString as o, nonNegativeAmount as s, positiveAmount as c } from "./amount.js";
4
+ import { captureCurrencies as l, defineCurrency as u } from "./currency.js";
5
+ import { readVerifiedIapCurrentState as d } from "./iapCurrentState.server.js";
6
+ import { walletHash as f, walletKey as p } from "./walletKeys.server.js";
7
+ import { applyWalletPosting as m, applyWalletRefundPosting as h, captureAccount as g, economyAccountKey as _, planEscrowLedgerTransfer as v, planLedgerTransfer as y } from "./ledger.js";
8
+ import { economyCurrenciesTable as b, economyLedgerTable as x, economySubjectsTable as S, economyTransactionsTable as C, economyWalletsTable as w } from "./tables.entity.js";
9
+ import { walletEscrowParticipant as T } from "./walletEscrow.server.js";
10
+ import { assertSpendBudget as ee, captureSpendLimitsOptions as E, projectSpend as te, resolveSpendBudget as ne } from "./spendLimits.js";
11
+ import { Effect as D, Result as re, Schema as O } from "effect";
12
+ import { and as k, eq as A, inSet as j, queryFor as M } from "@voltro/database";
13
+ import { executeSqlMutations as ie, prepareSqlMutation as ae } from "@voltro/database/sql";
14
+ //#region src/walletStore.ts
15
+ var N = (n) => n instanceof e ? n : t("unavailable"), P = (e) => D.tryPromise({
16
+ try: e,
17
+ catch: N
18
+ }), F = (e) => {
19
+ let n = e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN;
20
+ if (!Number.isSafeInteger(n) || n < 0 || n > 864e13) throw t("invalid_record");
21
+ return n;
22
+ }, I = O.Struct({
23
+ txId: O.String,
24
+ currency: O.String,
25
+ amount: O.String,
26
+ at: O.Number
27
+ }), L = (e) => {
28
+ let n = O.decodeUnknownSync(I)(e.receipt);
29
+ if (n.txId !== e.id || F(e.createdAt) > n.at || !Number.isSafeInteger(n.at) || n.at < 0 || n.at > 864e13) throw t("invalid_record");
30
+ return Object.freeze({
31
+ txId: i(n.txId),
32
+ currency: i(n.currency),
33
+ amount: o(c(n.amount)),
34
+ at: n.at
35
+ });
36
+ }, R = (e, t, n) => p("ecw_", e, _(t), n), z = async (e, n, r, a) => {
37
+ let o = /* @__PURE__ */ new Map();
38
+ for (let c = 0; c < r.length; c += 128) {
39
+ let l = r.slice(c, c + 128), u = await e.query(M(x).where(k(A("tenantId", n), j("txId", l))).limit(l.length * 2 + 1).descriptor), d = await e.query(M(C).where(k(A("tenantId", n), j("id", l))).limit(l.length + 1).descriptor);
40
+ if (u.length !== l.length * 2 || d.length !== l.length) throw t("invalid_record");
41
+ for (let e of l) {
42
+ let r = u.filter((t) => t.txId === e), c = d.find((t) => t.id === e);
43
+ if (r.length !== 2 || !c || c.tenantId !== n || c.state !== "committed" && c.state !== "erased") throw t("invalid_record");
44
+ let l = c.state === "committed" ? L(c) : null;
45
+ if (l && (l.currency !== a || typeof c.digest != "string" || !/^[0-9a-f]{64}$/.test(c.digest)) || !l && (c.receipt !== null || c.digest !== null || c.escrow !== null)) throw t("invalid_record");
46
+ let f = 0n, m = [];
47
+ for (let o of r) {
48
+ let r = s(o.debit), c = s(o.credit);
49
+ if (o.tenantId !== n || o.currency !== a || r === 0n == (c === 0n) || o.id !== p("ecl_", e, r > 0n ? "0" : "1") || l && ((r > 0n ? r : c).toString() !== l.amount || F(o.at) !== l.at)) throw t("invalid_record");
50
+ if (o.accountKind === "system") {
51
+ if (o.ownerId !== null || o.ownerKind !== null || o.walletKey !== null) throw t("invalid_record");
52
+ m.push(_({
53
+ kind: "system",
54
+ id: i(o.systemAccount)
55
+ }));
56
+ } else if (o.accountKind === "wallet") {
57
+ if (o.systemAccount !== null) throw t("invalid_record");
58
+ if (o.ownerId === null && o.ownerKind === null && o.walletKey === null && !l) m.push("erased:" + String(o.id));
59
+ else {
60
+ if (o.ownerKind !== "player" && o.ownerKind !== "guild") throw t("invalid_record");
61
+ let e = {
62
+ kind: "wallet",
63
+ ownerKind: o.ownerKind,
64
+ ownerId: i(o.ownerId)
65
+ };
66
+ if (o.walletKey !== R(n, e, a)) throw t("invalid_record");
67
+ m.push(_(e));
68
+ }
69
+ } else throw t("invalid_record");
70
+ f += c - r;
71
+ }
72
+ let h = r.find((e) => BigInt(String(e.debit)) > 0n), g = r.find((e) => BigInt(String(e.credit)) > 0n), v = h?.reason === "escrow.tax" && typeof h.systemAccount == "string" && h.systemAccount.startsWith("escrow.") && !h.systemAccount.startsWith("escrow.tax.") && typeof g?.systemAccount == "string" && g.systemAccount.startsWith("escrow.tax.");
73
+ if (r[0].reason !== r[1].reason || r[0].refKind !== r[1].refKind || r[0].refId !== r[1].refId || r[0].actor !== r[1].actor || f !== 0n || m[0] === m[1] || r.every((e) => e.accountKind === "system") && !v || F(r[0].at) !== F(r[1].at)) throw t("invalid_record");
74
+ o.set(e, {
75
+ pair: r,
76
+ receipt: c
77
+ });
78
+ }
79
+ }
80
+ return o;
81
+ }, oe = (e) => {
82
+ let a = r(e, [
83
+ "currencies",
84
+ "allowedServices",
85
+ "maxLedgerRows",
86
+ "maxExportRows",
87
+ "now",
88
+ "spendLimits"
89
+ ]), o = l(a.currencies), s = n(a.allowedServices ?? [], 256).map((e) => i(e));
90
+ if (new Set(s).size !== s.length) throw t("invalid_input");
91
+ let c = a.maxLedgerRows ?? 1e4, u = a.maxExportRows ?? 1e4, d = a.now ?? Date.now;
92
+ if (typeof c != "number" || !Number.isSafeInteger(c) || c < 2 || c > 1e5 || typeof u != "number" || !Number.isSafeInteger(u) || u < 1 || u > 1e5 || typeof d != "function") throw t("invalid_input");
93
+ return Object.freeze({
94
+ currencies: o,
95
+ allowedServices: Object.freeze(s),
96
+ maxLedgerRows: c,
97
+ maxExportRows: u,
98
+ now: d,
99
+ spendLimits: a.spendLimits === void 0 ? void 0 : E(a.spendLimits, o)
100
+ });
101
+ }, B = (e, n) => {
102
+ let l = oe(n), E = new Set(l.allowedServices), O = new Map(l.currencies.map((e) => [e.id, e])), I = () => {
103
+ let e = l.now();
104
+ if (!Number.isSafeInteger(e) || e < 0 || e > 864e13) throw t("unavailable");
105
+ return e;
106
+ }, B = (e) => e.type === "system" || e.type === "service" && E.has(e.service), V = (e) => {
107
+ let n = O.get(e);
108
+ if (!n) throw t("invalid_currency");
109
+ return n;
110
+ }, H = (e, t) => p("ecs_", e, _(t)), U = async (t, n) => {
111
+ if (n.kind !== "wallet") return;
112
+ let r = H(t, n);
113
+ try {
114
+ await e.insertIgnore(S.tableName, {
115
+ id: r,
116
+ tenantId: t,
117
+ ownerKind: n.ownerKind,
118
+ ownerId: n.ownerId,
119
+ erased: !1,
120
+ admission: 0,
121
+ entriesCount: 0
122
+ }, { conflictColumns: ["id"] });
123
+ } catch (t) {
124
+ if (!(await e.query(M(S).where(A("id", r)).limit(1).descriptor))[0]) throw t;
125
+ }
126
+ }, W = async (e, n, r, i = !1) => {
127
+ if (r.kind !== "wallet") throw t("invalid_input");
128
+ let a = H(n, r);
129
+ if (await e.updateMany(S.tableName, { admission: 0 }, { where: A("id", a) }) !== 1) throw t("unavailable");
130
+ let o = (await e.query(M(S).where(A("id", a)).limit(1).descriptor))[0];
131
+ if (!o || o.tenantId !== n || o.ownerKind !== r.ownerKind || o.admission !== 0 || typeof o.entriesCount != "number" || !Number.isSafeInteger(o.entriesCount) || o.entriesCount < 0 || o.entriesCount > 1e5) throw t("invalid_record");
132
+ if (o.erased === !0) {
133
+ if (i && o.ownerId === null) return o;
134
+ throw t("erased");
135
+ }
136
+ if (o.ownerId !== r.ownerId || o.erased !== !1) throw t("invalid_record");
137
+ return o;
138
+ }, G = async (t, n) => {
139
+ let r = p("ecc_", t, n.id);
140
+ try {
141
+ await e.insertIgnore(b.tableName, {
142
+ id: r,
143
+ tenantId: t,
144
+ currency: n.id,
145
+ config: n,
146
+ admission: 0
147
+ }, { conflictColumns: ["id"] });
148
+ } catch (t) {
149
+ if (!(await e.query(M(b).where(A("id", r)).limit(1).descriptor))[0]) throw t;
150
+ }
151
+ }, K = async (e, n, r, i) => {
152
+ let a = p("ecc_", n, r);
153
+ if (await e.updateMany(b.tableName, { admission: 0 }, { where: A("id", a) }) !== 1) throw t("unavailable");
154
+ let o = (await e.query(M(b).where(A("id", a)).limit(1).descriptor))[0];
155
+ if (!o || o.tenantId !== n || o.currency !== r) throw t("invalid_record");
156
+ if (i && f(u(o.config)) !== f(i)) throw t("conflict");
157
+ }, q = async (e, n, r, i, a = l.maxExportRows) => {
158
+ let o = await e.query(M(n).where(k(A("tenantId", r), A("ownerKind", i.ownerKind), A("ownerId", i.ownerId))).orderBy("id", "asc").limit(a + 1).descriptor);
159
+ if (o.length > a) throw t("limit_exceeded");
160
+ if (o.some((e) => e.tenantId !== r || e.ownerKind !== i.ownerKind || e.ownerId !== i.ownerId)) throw t("invalid_record");
161
+ return o;
162
+ }, J = async (e, n, r, i) => {
163
+ let a = R(n, r, i), o = (await e.query(M(w).where(A("id", a)).limit(1).descriptor))[0];
164
+ if (!o) return null;
165
+ if (o.tenantId !== n || o.ownerId !== r.ownerId || o.ownerKind !== r.ownerKind || o.currency !== i) throw t("invalid_record");
166
+ return o;
167
+ }, Y = async (e, n, r) => {
168
+ let i = await W(e, n, r), a = await q(e, x, n, r, l.maxLedgerRows);
169
+ if (a.length !== i.entriesCount) throw t("invalid_record");
170
+ return a;
171
+ }, se = /* @__PURE__ */ new WeakMap(), X = Object.freeze(Object.create(null)), Z = (n, c, u) => {
172
+ try {
173
+ let d = structuredClone(n), g = u === X ? v(c) : y(c);
174
+ if (!B(d) || g.postings.some((e) => e.account.kind === "system" && e.account.id.startsWith("escrow.")) && u !== X) throw t("forbidden");
175
+ let b = u === void 0 ? void 0 : se.get(u), T = V(g.currency), E = f(b ? [
176
+ g,
177
+ b.originalTxId,
178
+ b.debtPolicy
179
+ ] : g), O = p("ect_", g.tenantId, g.requestId), j = g.postings.map((e) => e.account).filter((e) => e.kind === "wallet").sort((e, t) => H(g.tenantId, e).localeCompare(H(g.tenantId, t)));
180
+ return P(async () => {
181
+ for (let e of j) await U(g.tenantId, e);
182
+ await G(g.tenantId, T);
183
+ let n = await e.transactional(async (e) => {
184
+ for (let t of j) await W(e, g.tenantId, t);
185
+ await K(e, g.tenantId, T.id, T);
186
+ let n = (await e.query(M(C).where(A("id", O)).limit(1).descriptor))[0];
187
+ if (n?.state === "committed") {
188
+ if (n.tenantId !== g.tenantId || n.digest !== E) throw t("conflict");
189
+ return L(n);
190
+ }
191
+ if (n?.state === "erased") throw t("erased");
192
+ }), c = n?.at ?? I(), u, f = g.postings.find((e) => e.account.kind === "wallet" && BigInt(e.debit) > 0n)?.account, v = l.spendLimits, y = v?.limits.find((e) => e.currency === T.id);
193
+ if (!n && !b && v && y && f?.kind === "wallet") {
194
+ let e = Object.freeze({
195
+ tenantId: g.tenantId,
196
+ ownerId: f.ownerId,
197
+ ownerKind: f.ownerKind,
198
+ currency: T.id,
199
+ at: c
200
+ }), n = v.source.read(e);
201
+ if (!D.isEffect(n)) throw t("invalid_record");
202
+ let i = await D.runPromise(D.result(n));
203
+ if (re.isFailure(i)) throw i.failure;
204
+ let a = r(i.success, [
205
+ "tenantId",
206
+ "ownerId",
207
+ "ownerKind",
208
+ "currency",
209
+ "at",
210
+ "allowed",
211
+ "minor",
212
+ "observedAt",
213
+ "daily",
214
+ "monthly",
215
+ "blockedUntil"
216
+ ], "invalid_record");
217
+ if (a.tenantId !== e.tenantId || a.ownerId !== e.ownerId || a.ownerKind !== e.ownerKind || a.currency !== e.currency || a.at !== c) throw t("invalid_record");
218
+ u = ne({
219
+ limit: y,
220
+ facts: i.success,
221
+ version: v.version
222
+ }, v.policy);
223
+ }
224
+ try {
225
+ await e.insertIgnore(C.tableName, {
226
+ id: O,
227
+ tenantId: g.tenantId,
228
+ state: "pending",
229
+ digest: null,
230
+ receipt: null,
231
+ escrow: null,
232
+ admission: 0,
233
+ createdAt: new Date(c)
234
+ }, { conflictColumns: ["id"] });
235
+ } catch (t) {
236
+ if (!(await e.query(M(C).where(A("id", O)).limit(1).descriptor))[0]) throw t;
237
+ }
238
+ return ae(e, async (e) => {
239
+ for (let t of j) await W(e, g.tenantId, t);
240
+ if (await K(e, g.tenantId, T.id, T), await e.updateMany(C.tableName, { admission: 0 }, { where: A("id", O) }) !== 1) throw t("unavailable");
241
+ let n = (await e.query(M(C).where(A("id", O)).limit(1).descriptor))[0];
242
+ if (!n || n.tenantId !== g.tenantId) throw t("invalid_record");
243
+ if (n.state === "erased") throw t("erased");
244
+ if (n.state === "committed") {
245
+ if (n.digest !== E) throw t("conflict");
246
+ return L(n);
247
+ }
248
+ if (n.state !== "pending" || n.digest !== null || n.receipt !== null || n.escrow !== null || F(n.createdAt) > c || (await e.query(M(x).where(k(A("tenantId", g.tenantId), A("txId", O))).limit(1).descriptor)).length !== 0) throw t("invalid_record");
249
+ if (b) {
250
+ b.assertFresh();
251
+ let n = (await z(e, g.tenantId, [b.originalTxId], T.id)).get(b.originalTxId), r = n.pair.find((e) => BigInt(String(e.credit)) > 0n), i = n.pair.find((e) => BigInt(String(e.debit)) > 0n), a = g.postings[0].account, o = g.postings[1].account;
252
+ if (a.kind !== "wallet" || o.kind !== "system" || !r || !i || r.ownerId !== a.ownerId || r.ownerKind !== a.ownerKind || i.systemAccount !== o.id || i.reason !== "iap.fulfill" || BigInt(g.amount) > BigInt(String(r.credit))) throw t("invalid_record");
253
+ }
254
+ let r = [];
255
+ for (let n of g.postings) {
256
+ if (n.account.kind !== "wallet") continue;
257
+ let d = await Y(e, g.tenantId, n.account);
258
+ if (d.length >= l.maxLedgerRows) throw t("limit_exceeded");
259
+ let f = d.filter((e) => e.currency === T.id), p = await J(e, g.tenantId, n.account, T.id);
260
+ if (p && F(p.updatedAt) > c) throw t("invalid_record");
261
+ if (!b && BigInt(n.debit) > 0n && (await q(e, w, g.tenantId, n.account)).some((e) => a(e.balance) < 0n && e.debtPolicy === "blockSpend")) throw t("forbidden");
262
+ if (u && BigInt(n.debit) > 0n) {
263
+ await z(e, g.tenantId, [...new Set(f.map((e) => i(e.txId)))], T.id);
264
+ let r = te(f.map((e) => ({
265
+ id: i(e.id),
266
+ debit: String(e.debit),
267
+ credit: String(e.credit),
268
+ at: F(e.at)
269
+ })), c);
270
+ if (r.balance !== o(s(p?.balance ?? "0"))) throw t("invalid_record");
271
+ ee(r, n.debit, u);
272
+ }
273
+ let _ = (b ? h : m)(p?.balance ?? "0", n, T), v = p?.debtPolicy ?? null;
274
+ if (v !== null && v !== "allowNegative" && v !== "blockSpend" || BigInt(p?.balance ?? "0") < 0n && v === null) throw t("invalid_record");
275
+ r.push({
276
+ account: n.account,
277
+ row: p,
278
+ next: _,
279
+ debtPolicy: BigInt(_) < 0n ? v === "blockSpend" || b?.debtPolicy === "blockSpend" ? "blockSpend" : "allowNegative" : null
280
+ });
281
+ }
282
+ for (let t of r) {
283
+ let n = R(g.tenantId, t.account, T.id);
284
+ t.row ? await e.update(w.tableName, n, {
285
+ balance: t.next,
286
+ debtPolicy: t.debtPolicy,
287
+ updatedAt: new Date(c)
288
+ }) : await e.insert(w.tableName, {
289
+ id: n,
290
+ tenantId: g.tenantId,
291
+ ownerId: t.account.ownerId,
292
+ ownerKind: t.account.ownerKind,
293
+ currency: T.id,
294
+ balance: t.next,
295
+ debtPolicy: t.debtPolicy,
296
+ updatedAt: new Date(c)
297
+ });
298
+ }
299
+ for (let [t, n] of g.postings.entries()) {
300
+ let a = n.account, o = a.kind === "wallet" ? r.find((e) => _(e.account) === _(a)) : null, s = a.kind === "wallet" ? Number((await W(e, g.tenantId, a)).entriesCount) + 1 : null;
301
+ await e.insert(x.tableName, {
302
+ id: p("ecl_", O, String(t)),
303
+ tenantId: g.tenantId,
304
+ txId: O,
305
+ currency: T.id,
306
+ accountKind: a.kind,
307
+ ownerId: a.kind === "wallet" ? a.ownerId : null,
308
+ ownerKind: a.kind === "wallet" ? a.ownerKind : null,
309
+ walletKey: a.kind === "wallet" ? R(g.tenantId, a, T.id) : null,
310
+ systemAccount: a.kind === "system" ? a.id : null,
311
+ ownerSequence: s,
312
+ debtPolicy: o?.debtPolicy ?? null,
313
+ debit: n.debit,
314
+ credit: n.credit,
315
+ reason: g.reason,
316
+ refKind: g.ref.kind,
317
+ refId: g.ref.id,
318
+ actor: i(d.id),
319
+ at: new Date(c)
320
+ });
321
+ }
322
+ for (let t of j) {
323
+ let n = await W(e, g.tenantId, t);
324
+ await e.update(S.tableName, H(g.tenantId, t), { entriesCount: Number(n.entriesCount) + 1 });
325
+ }
326
+ let f = Object.freeze({
327
+ txId: O,
328
+ currency: T.id,
329
+ amount: g.amount,
330
+ at: c
331
+ });
332
+ return await e.update(C.tableName, O, {
333
+ state: "committed",
334
+ digest: E,
335
+ receipt: f
336
+ }), f;
337
+ });
338
+ });
339
+ } catch (e) {
340
+ return D.fail(N(e));
341
+ }
342
+ }, ce = (e, t) => Z(e, t), le = (n, a, o) => {
343
+ try {
344
+ let s = structuredClone(n), l = r(o, [
345
+ "requestId",
346
+ "currency",
347
+ "amount",
348
+ "debtPolicy"
349
+ ]), u = i(l.requestId), f = i(l.currency), p = c(l.amount).toString();
350
+ if (!B(s)) throw t("forbidden");
351
+ if (l.debtPolicy !== "allowNegative" && l.debtPolicy !== "blockSpend") throw t("invalid_input");
352
+ let m = l.debtPolicy;
353
+ return d(a).pipe(D.flatMap(({ original: n, state: r, assertFresh: a }) => P(async () => {
354
+ let o = n.receipt.transfers.find((e) => e.currency === f);
355
+ if (!o || BigInt(p) > BigInt(o.amount) * BigInt(r.refundNumerator) / BigInt(r.refundDenominator)) throw t("forbidden");
356
+ let c = (await e.transactional(async (e) => (await z(e, n.scope.tenantId, [o.txId], f)).get(o.txId))).pair.find((e) => BigInt(String(e.debit)) > 0n);
357
+ if (!c || c.accountKind !== "system" || c.reason !== "iap.fulfill") throw t("invalid_record");
358
+ let l = Object.freeze(Object.create(null));
359
+ se.set(l, {
360
+ originalTxId: o.txId,
361
+ debtPolicy: m,
362
+ assertFresh: a
363
+ });
364
+ let d = Z(s, {
365
+ tenantId: n.scope.tenantId,
366
+ requestId: u,
367
+ currency: f,
368
+ amount: p,
369
+ from: {
370
+ kind: "wallet",
371
+ ownerKind: "player",
372
+ ownerId: n.scope.ownerId
373
+ },
374
+ to: {
375
+ kind: "system",
376
+ id: i(c.systemAccount)
377
+ },
378
+ reason: "iap.refund",
379
+ ref: {
380
+ kind: "iap-order",
381
+ id: n.orderId
382
+ }
383
+ }, l), h = await D.runPromise(D.result(d));
384
+ if (re.isFailure(h)) throw h.failure;
385
+ return h.success;
386
+ })), D.catchDefect(() => D.fail(t("unavailable"))));
387
+ } catch (e) {
388
+ return D.fail(N(e));
389
+ }
390
+ }, ue = (t, n) => D.flatMap(ce(t, n), (t) => P(async () => (await ie(e, [t]))[0])), de = (n) => {
391
+ try {
392
+ let r = structuredClone(n);
393
+ if (r.type !== "user") throw t("forbidden");
394
+ let a = i(r.tenantId), s = i(r.id), c = {
395
+ kind: "wallet",
396
+ ownerKind: "player",
397
+ ownerId: s
398
+ };
399
+ return P(async () => {
400
+ let n = (await e.query(M(S).where(A("id", H(a, c))).limit(1).descriptor))[0];
401
+ if (n?.erased === !0) throw t("erased");
402
+ if (n && (n.tenantId !== a || n.ownerKind !== "player" || n.ownerId !== s || n.erased !== !1)) throw t("invalid_record");
403
+ let r = await q(e, w, a, c);
404
+ return Object.freeze(l.currencies.map((e) => {
405
+ let n = r.find((t) => t.currency === e.id), i = o(n?.balance ?? "0");
406
+ if (BigInt(i) < 0n && (e.kind !== "hard" || n?.debtPolicy !== "allowNegative" && n?.debtPolicy !== "blockSpend")) throw t("invalid_record");
407
+ if (BigInt(i) > BigInt(e.cap)) throw t("conflict");
408
+ return Object.freeze({
409
+ currency: e.id,
410
+ balance: i,
411
+ updatedAt: n ? F(n.updatedAt) : null
412
+ });
413
+ }));
414
+ });
415
+ } catch (e) {
416
+ return D.fail(N(e));
417
+ }
418
+ }, Q = (n) => (r, a, c, l) => {
419
+ try {
420
+ let u = structuredClone(r), d = i(a), f = g(c), p = V(i(l));
421
+ if (!B(u)) throw t("forbidden");
422
+ if (f.kind !== "wallet") throw t("invalid_input");
423
+ return P(async () => (await U(d, f), await G(d, p), e.transactional(async (e) => {
424
+ await W(e, d, f), await K(e, d, p.id, p);
425
+ let r = R(d, f, p.id), a = (await Y(e, d, f)).filter((e) => e.currency === p.id);
426
+ if (a.some((e) => e.walletKey !== r)) throw t("invalid_record");
427
+ await z(e, d, [...new Set(a.map((e) => i(e.txId)))], p.id);
428
+ let c = 0n;
429
+ for (let e of a) {
430
+ if (e.accountKind !== "wallet" || e.tenantId !== d || e.ownerId !== f.ownerId || e.ownerKind !== f.ownerKind || e.currency !== p.id) throw t("invalid_record");
431
+ let n = s(e.debit), r = s(e.credit);
432
+ if (n === 0n == (r === 0n)) throw t("invalid_record");
433
+ c += r - n;
434
+ }
435
+ let l = a.filter((e) => e.ownerSequence != null).sort((e, t) => Number(e.ownerSequence) - Number(t.ownerSequence));
436
+ if (l.some((e, t) => !Number.isSafeInteger(e.ownerSequence) || Number(e.ownerSequence) < 1 || t > 0 && Number(e.ownerSequence) <= Number(l[t - 1].ownerSequence) || e.debtPolicy != null && e.debtPolicy !== "allowNegative" && e.debtPolicy !== "blockSpend")) throw t("invalid_record");
437
+ let u = c < 0n ? l[l.length - 1]?.debtPolicy : null;
438
+ if (c < 0n && u !== "allowNegative" && u !== "blockSpend") throw t("invalid_record");
439
+ let m = o(c);
440
+ if (c < 0n && (p.kind !== "hard" || !a.some((e) => e.reason === "iap.refund" && BigInt(String(e.debit)) > 0n))) throw t("invalid_record");
441
+ if (c > BigInt(p.cap)) throw t("currency_cap_reached");
442
+ let h = await J(e, d, f, p.id), g = o(h?.balance ?? "0"), _ = g === m && (h?.debtPolicy ?? null) === (u ?? null);
443
+ if (n && !_) {
444
+ let n = I();
445
+ if (h && F(h.updatedAt) > n) throw t("invalid_record");
446
+ h ? await e.update(w.tableName, r, {
447
+ balance: m,
448
+ debtPolicy: c < 0n ? u : null,
449
+ updatedAt: new Date(n)
450
+ }) : await e.insert(w.tableName, {
451
+ id: r,
452
+ tenantId: d,
453
+ ownerId: f.ownerId,
454
+ ownerKind: f.ownerKind,
455
+ currency: p.id,
456
+ balance: m,
457
+ debtPolicy: u ?? null,
458
+ updatedAt: new Date(n)
459
+ });
460
+ }
461
+ return Object.freeze({
462
+ currency: p.id,
463
+ balance: n ? m : g,
464
+ ledgerBalance: m,
465
+ ledgerRows: a.length,
466
+ matches: n || _
467
+ });
468
+ })));
469
+ } catch (e) {
470
+ return D.fail(N(e));
471
+ }
472
+ }, fe = (n, a) => {
473
+ try {
474
+ let o = r(n, [
475
+ "subjectId",
476
+ "tenantId",
477
+ "kind"
478
+ ]);
479
+ if (o.kind !== "user" && o.kind !== "guest") throw t("invalid_input");
480
+ let s = i(o.tenantId), c = Object.freeze({
481
+ kind: "wallet",
482
+ ownerKind: "player",
483
+ ownerId: i(o.subjectId)
484
+ });
485
+ return P(async () => (await U(s, c), e.transactional(async (e) => {
486
+ await W(e, s, c, !0);
487
+ let n = await e.query(M(b).where(A("tenantId", s)).orderBy("id", "asc").limit(l.maxExportRows + 1).descriptor);
488
+ if (n.length > l.maxExportRows) throw t("limit_exceeded");
489
+ for (let t of n) await K(e, s, i(t.currency));
490
+ return (await W(e, s, c, !0)).erased || await Y(e, s, c), a(e, s, c);
491
+ })));
492
+ } catch (e) {
493
+ return D.fail(N(e));
494
+ }
495
+ }, pe = (e) => fe(e, async (e, n, r) => {
496
+ let a = await q(e, w, n, r), s = await q(e, x, n, r), c = [...new Set(s.map((e) => i(e.txId)))], l = [];
497
+ for (let r = 0; r < c.length; r += 128) {
498
+ let i = await e.query(M(C).where(k(A("tenantId", n), j("id", c.slice(r, r + 128)))).limit(129).descriptor);
499
+ if (i.length > 128) throw t("invalid_record");
500
+ for (let e of i) e.escrow !== null && l.push(e.escrow);
501
+ }
502
+ return {
503
+ ...l.length ? { escrows: l } : {},
504
+ wallets: a.map((e) => ({
505
+ currency: i(e.currency),
506
+ balance: o(e.balance),
507
+ updatedAt: F(e.updatedAt)
508
+ })),
509
+ ledger: s.map((e) => ({
510
+ txId: i(e.txId),
511
+ currency: i(e.currency),
512
+ debit: o(e.debit),
513
+ credit: o(e.credit),
514
+ reason: i(e.reason),
515
+ refKind: e.refKind,
516
+ refId: e.refId,
517
+ actor: e.actor,
518
+ at: F(e.at)
519
+ }))
520
+ };
521
+ }), me = (e) => fe(e, async (e, t, n) => {
522
+ let r = await q(e, x, t, n), a = await q(e, w, t, n), o = [...new Set(r.map((e) => i(e.txId)))], s = await $.taxTransactionIds(e, t, n, o);
523
+ for (let n of [.../* @__PURE__ */ new Set([...o, ...s])].sort()) await e.updateMany(x.tableName, {
524
+ refKind: null,
525
+ refId: null,
526
+ actor: null
527
+ }, { where: k(A("tenantId", t), A("txId", n)) }), await e.update(C.tableName, n, {
528
+ state: "erased",
529
+ digest: null,
530
+ receipt: null,
531
+ escrow: null
532
+ });
533
+ for (let t of r) await e.update(x.tableName, String(t.id), {
534
+ ownerId: null,
535
+ ownerKind: null,
536
+ walletKey: null
537
+ });
538
+ for (let t of a) await e.delete(w.tableName, String(t.id));
539
+ await e.update(S.tableName, H(t, n), {
540
+ ownerId: null,
541
+ erased: !0
542
+ });
543
+ }), $ = T(e, {
544
+ allowedServices: l.allowedServices,
545
+ prepareTransfer: (e, t) => Z(e, t, X),
546
+ readEvidence: z,
547
+ decodeReceipt: L,
548
+ ledgerAt: F,
549
+ seedWallet: U,
550
+ fenceWallet: W,
551
+ fenceCurrency: K
552
+ });
553
+ return Object.freeze({
554
+ prepareEscrowReserve: $.prepareEscrowReserve,
555
+ prepareEscrowRelease: $.prepareEscrowRelease,
556
+ prepareEscrowSettle: $.prepareEscrowSettle,
557
+ prepareEscrowTaxSettle: $.prepareEscrowTaxSettle,
558
+ prepareEscrowReserveTaxSettle: $.prepareEscrowReserveTaxSettle,
559
+ escrow: $.escrow,
560
+ transfer: ue,
561
+ prepareTransfer: ce,
562
+ prepareIapRefund: le,
563
+ mine: de,
564
+ auditWallet: Q(!1),
565
+ rebuildWallet: Q(!0),
566
+ exportSubject: pe,
567
+ eraseSubject: me
568
+ });
569
+ };
570
+ //#endregion
571
+ export { B as dataStoreEconomy, F as economyLedgerAt, R as economyWalletKey, z as readEconomyTransferEvidence, oe as resolveEconomyStoreOptions };