@adriangalilea/utils 0.18.0 → 0.19.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 (97) hide show
  1. package/README.md +2 -1
  2. package/dist/bot/access-control.d.ts.map +1 -1
  3. package/dist/bot/access-control.js +17 -1
  4. package/dist/bot/access-control.js.map +1 -1
  5. package/dist/bot/callbacks.d.ts +89 -0
  6. package/dist/bot/callbacks.d.ts.map +1 -0
  7. package/dist/bot/callbacks.js +128 -0
  8. package/dist/bot/callbacks.js.map +1 -0
  9. package/dist/bot/ctx.d.ts +219 -0
  10. package/dist/bot/ctx.d.ts.map +1 -0
  11. package/dist/bot/ctx.js +52 -0
  12. package/dist/bot/ctx.js.map +1 -0
  13. package/dist/bot/index.d.ts +4 -0
  14. package/dist/bot/index.d.ts.map +1 -1
  15. package/dist/bot/index.js +4 -0
  16. package/dist/bot/index.js.map +1 -1
  17. package/dist/bot/kit.d.ts +1 -1
  18. package/dist/bot/kit.d.ts.map +1 -1
  19. package/dist/bot/kit.js +4 -2
  20. package/dist/bot/kit.js.map +1 -1
  21. package/dist/bot/menu.d.ts +23 -1
  22. package/dist/bot/menu.d.ts.map +1 -1
  23. package/dist/bot/menu.js +30 -1
  24. package/dist/bot/menu.js.map +1 -1
  25. package/dist/bot/payments/callbacks.d.ts +28 -0
  26. package/dist/bot/payments/callbacks.d.ts.map +1 -0
  27. package/dist/bot/payments/callbacks.js +102 -0
  28. package/dist/bot/payments/callbacks.js.map +1 -0
  29. package/dist/bot/payments/commands.d.ts +26 -0
  30. package/dist/bot/payments/commands.d.ts.map +1 -0
  31. package/dist/bot/payments/commands.js +41 -0
  32. package/dist/bot/payments/commands.js.map +1 -0
  33. package/dist/bot/payments/config.d.ts +30 -0
  34. package/dist/bot/payments/config.d.ts.map +1 -0
  35. package/dist/bot/payments/config.js +166 -0
  36. package/dist/bot/payments/config.js.map +1 -0
  37. package/dist/bot/payments/derive.d.ts +75 -0
  38. package/dist/bot/payments/derive.d.ts.map +1 -0
  39. package/dist/bot/payments/derive.js +151 -0
  40. package/dist/bot/payments/derive.js.map +1 -0
  41. package/dist/bot/payments/handlers.d.ts +113 -0
  42. package/dist/bot/payments/handlers.d.ts.map +1 -0
  43. package/dist/bot/payments/handlers.js +284 -0
  44. package/dist/bot/payments/handlers.js.map +1 -0
  45. package/dist/bot/payments/index.d.ts +17 -0
  46. package/dist/bot/payments/index.d.ts.map +1 -0
  47. package/dist/bot/payments/index.js +14 -0
  48. package/dist/bot/payments/index.js.map +1 -0
  49. package/dist/bot/payments/invoice.d.ts +101 -0
  50. package/dist/bot/payments/invoice.d.ts.map +1 -0
  51. package/dist/bot/payments/invoice.js +213 -0
  52. package/dist/bot/payments/invoice.js.map +1 -0
  53. package/dist/bot/payments/menu-item.d.ts +41 -0
  54. package/dist/bot/payments/menu-item.d.ts.map +1 -0
  55. package/dist/bot/payments/menu-item.js +259 -0
  56. package/dist/bot/payments/menu-item.js.map +1 -0
  57. package/dist/bot/payments/payload.d.ts +42 -0
  58. package/dist/bot/payments/payload.d.ts.map +1 -0
  59. package/dist/bot/payments/payload.js +69 -0
  60. package/dist/bot/payments/payload.js.map +1 -0
  61. package/dist/bot/payments/payouts.d.ts +88 -0
  62. package/dist/bot/payments/payouts.d.ts.map +1 -0
  63. package/dist/bot/payments/payouts.js +133 -0
  64. package/dist/bot/payments/payouts.js.map +1 -0
  65. package/dist/bot/payments/plugin.d.ts +271 -0
  66. package/dist/bot/payments/plugin.d.ts.map +1 -0
  67. package/dist/bot/payments/plugin.js +141 -0
  68. package/dist/bot/payments/plugin.js.map +1 -0
  69. package/dist/bot/payments/refund.d.ts +124 -0
  70. package/dist/bot/payments/refund.d.ts.map +1 -0
  71. package/dist/bot/payments/refund.js +308 -0
  72. package/dist/bot/payments/refund.js.map +1 -0
  73. package/dist/bot/payments/schemas.d.ts +58 -0
  74. package/dist/bot/payments/schemas.d.ts.map +1 -0
  75. package/dist/bot/payments/schemas.js +55 -0
  76. package/dist/bot/payments/schemas.js.map +1 -0
  77. package/dist/bot/payments/state.d.ts +90 -0
  78. package/dist/bot/payments/state.d.ts.map +1 -0
  79. package/dist/bot/payments/state.js +149 -0
  80. package/dist/bot/payments/state.js.map +1 -0
  81. package/dist/bot/payments/stores.d.ts +44 -0
  82. package/dist/bot/payments/stores.d.ts.map +1 -0
  83. package/dist/bot/payments/stores.js +39 -0
  84. package/dist/bot/payments/stores.js.map +1 -0
  85. package/dist/bot/payments/types.d.ts +299 -0
  86. package/dist/bot/payments/types.d.ts.map +1 -0
  87. package/dist/bot/payments/types.js +39 -0
  88. package/dist/bot/payments/types.js.map +1 -0
  89. package/dist/bot/payments/waiver.d.ts +81 -0
  90. package/dist/bot/payments/waiver.d.ts.map +1 -0
  91. package/dist/bot/payments/waiver.js +145 -0
  92. package/dist/bot/payments/waiver.js.map +1 -0
  93. package/dist/bot/storage.d.ts +154 -0
  94. package/dist/bot/storage.d.ts.map +1 -0
  95. package/dist/bot/storage.js +222 -0
  96. package/dist/bot/storage.js.map +1 -0
  97. package/package.json +24 -3
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Pure state computation over the charge log.
3
+ *
4
+ * This file is `state.ts` (not `derive.ts`) because gramio's `derive`
5
+ * concept is reserved for ctx decoration (see `derive.ts` alongside,
6
+ * which builds `ctx.payments`). The reducers here are bot-id and ctx
7
+ * agnostic — they take `ChargeRecord[]` and a session-shaped object
8
+ * and mutate the session in place.
9
+ *
10
+ * The charge log (`pay:charge:{chargeId}`) is the single source of truth
11
+ * (CLAUDE.md §"Storage layout"). Session state is a cache for O(1)
12
+ * runtime checks. This module owns the function that rebuilds the cache
13
+ * from the log.
14
+ *
15
+ * Two surfaces:
16
+ *
17
+ * `deriveState(charges)` — pure, reduces a chronological list of
18
+ * NON-refunded charges into the cache
19
+ * shape. Used by reconcile and refund
20
+ * (after marking the refunded charge).
21
+ *
22
+ * `applyCharge(session, …)` — incremental, mutates one session record
23
+ * for a single new charge. Used by
24
+ * `handlers.ts` on `successful_payment`.
25
+ *
26
+ * `revertCreditsForCharge(session, charge)` — targeted decrement
27
+ * used by refund (vip/perks are full
28
+ * re-derive territory; credits is not,
29
+ * because consumption isn't in the log).
30
+ *
31
+ * Credits balance is **not fully derivable** from the log alone — the
32
+ * log records grants, not consumption. `deriveState` therefore returns
33
+ * `totalCreditsGranted` (sum) and callers decide whether to use it as
34
+ * the balance (reconcile of fresh state) or to ignore (incremental).
35
+ */
36
+ import type { ChargeRecord, DerivedPaymentsState, PaymentsSession } from "./types.js";
37
+ /**
38
+ * Result of `deriveState`. `totalCreditsGranted` is informational —
39
+ * subtract consumption (which isn't logged) for the real balance.
40
+ */
41
+ export type DeriveResult = DerivedPaymentsState & {
42
+ readonly totalCreditsGranted: number;
43
+ };
44
+ /**
45
+ * Pure reducer over a chronological list of charges. Caller is
46
+ * responsible for filtering out refunded ones if they want
47
+ * "current state after refunds" semantics.
48
+ */
49
+ export declare const deriveState: (charges: ReadonlyArray<ChargeRecord>) => DeriveResult;
50
+ /**
51
+ * Apply a single new charge to a session in place. Idempotent across
52
+ * `chargeId` because the caller (handlers.ts) guards via the
53
+ * `pay:idempotency:{chargeId}` sentinel before this fires; we don't
54
+ * re-check here.
55
+ *
56
+ * - vip: replaces `session.pay.vip` (renewals update expiresAt;
57
+ * tier upgrades replace rung)
58
+ * - credits: increments `session.pay.credits` by the granted amount
59
+ * (covers both pack purchases AND vip renewal grants)
60
+ * - perks: set-if-absent on `session.pay.perks[key]`
61
+ */
62
+ export declare const applyCharge: (session: {
63
+ pay?: PaymentsSession;
64
+ }, charge: ChargeRecord) => void;
65
+ /**
66
+ * Subtract a refunded charge's `creditsGranted` from the session
67
+ * balance, clamping at zero. The "clamp at zero" semantics are
68
+ * deliberate: a user may have already consumed credits when the refund
69
+ * arrives, and going negative would let them buy back into a debt — we
70
+ * refuse that and accept the asymmetry (the refunded Stars are already
71
+ * leaving the bot's balance via `refundStarPayment` either way).
72
+ */
73
+ export declare const revertCreditsForCharge: (session: {
74
+ pay?: PaymentsSession;
75
+ }, charge: ChargeRecord) => void;
76
+ /**
77
+ * Rebuild vip + perks (the fully-derivable parts of session.pay.*)
78
+ * from a fresh chronological view of the charge log, **after** the
79
+ * caller has marked any newly-refunded charges. Credits balance is
80
+ * NOT touched — caller handles that explicitly via
81
+ * `revertCreditsForCharge` for the targeted decrement semantics.
82
+ *
83
+ * Used by:
84
+ * - refund.ts after `refundStarPayment` succeeds
85
+ * - reconcile (admin command) for full state recovery
86
+ */
87
+ export declare const rebuildVipAndPerks: (session: {
88
+ pay?: PaymentsSession;
89
+ }, charges: ReadonlyArray<ChargeRecord>) => void;
90
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/bot/payments/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,KAAK,EACX,YAAY,EACZ,oBAAoB,EACpB,eAAe,EAGf,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,oBAAoB,GAAG;IACjD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACvB,SAAS,aAAa,CAAC,YAAY,CAAC,KAClC,YAwCF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,GACvB,SAAS;IAAE,GAAG,CAAC,EAAE,eAAe,CAAA;CAAE,EAClC,QAAQ,YAAY,KAClB,IA0BF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GAClC,SAAS;IAAE,GAAG,CAAC,EAAE,eAAe,CAAA;CAAE,EAClC,QAAQ,YAAY,KAClB,IAMF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,GAC9B,SAAS;IAAE,GAAG,CAAC,EAAE,eAAe,CAAA;CAAE,EAClC,SAAS,aAAa,CAAC,YAAY,CAAC,KAClC,IAMF,CAAC"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Pure state computation over the charge log.
3
+ *
4
+ * This file is `state.ts` (not `derive.ts`) because gramio's `derive`
5
+ * concept is reserved for ctx decoration (see `derive.ts` alongside,
6
+ * which builds `ctx.payments`). The reducers here are bot-id and ctx
7
+ * agnostic — they take `ChargeRecord[]` and a session-shaped object
8
+ * and mutate the session in place.
9
+ *
10
+ * The charge log (`pay:charge:{chargeId}`) is the single source of truth
11
+ * (CLAUDE.md §"Storage layout"). Session state is a cache for O(1)
12
+ * runtime checks. This module owns the function that rebuilds the cache
13
+ * from the log.
14
+ *
15
+ * Two surfaces:
16
+ *
17
+ * `deriveState(charges)` — pure, reduces a chronological list of
18
+ * NON-refunded charges into the cache
19
+ * shape. Used by reconcile and refund
20
+ * (after marking the refunded charge).
21
+ *
22
+ * `applyCharge(session, …)` — incremental, mutates one session record
23
+ * for a single new charge. Used by
24
+ * `handlers.ts` on `successful_payment`.
25
+ *
26
+ * `revertCreditsForCharge(session, charge)` — targeted decrement
27
+ * used by refund (vip/perks are full
28
+ * re-derive territory; credits is not,
29
+ * because consumption isn't in the log).
30
+ *
31
+ * Credits balance is **not fully derivable** from the log alone — the
32
+ * log records grants, not consumption. `deriveState` therefore returns
33
+ * `totalCreditsGranted` (sum) and callers decide whether to use it as
34
+ * the balance (reconcile of fresh state) or to ignore (incremental).
35
+ */
36
+ /**
37
+ * Pure reducer over a chronological list of charges. Caller is
38
+ * responsible for filtering out refunded ones if they want
39
+ * "current state after refunds" semantics.
40
+ */
41
+ export const deriveState = (charges) => {
42
+ let vip;
43
+ const perks = {};
44
+ let totalCreditsGranted = 0;
45
+ // Charges are oldest-first by convention. Vip latest-wins by
46
+ // receivedAt; perks first-wins (an idempotent unlock — buying twice
47
+ // shouldn't change the unlock date).
48
+ for (const c of charges) {
49
+ if (c.paysupportState === "refunded")
50
+ continue;
51
+ totalCreditsGranted += c.creditsGranted;
52
+ if (c.vipRung !== undefined && c.subscriptionExpiresAt !== undefined) {
53
+ // Replace the active subscription only when this charge is newer
54
+ // or this is the first vip charge encountered.
55
+ if (!vip || c.receivedAt >= (vip.expiresAt ?? 0) || c.receivedAt > 0) {
56
+ vip = {
57
+ rung: c.vipRung,
58
+ chargeId: c.chargeId,
59
+ expiresAt: c.subscriptionExpiresAt,
60
+ canceled: false,
61
+ };
62
+ }
63
+ }
64
+ if (c.perkKey && !perks[c.perkKey]) {
65
+ perks[c.perkKey] = {
66
+ chargeId: c.chargeId,
67
+ at: c.receivedAt,
68
+ };
69
+ }
70
+ }
71
+ return {
72
+ credits: totalCreditsGranted,
73
+ vip,
74
+ perks,
75
+ totalCreditsGranted,
76
+ };
77
+ };
78
+ /**
79
+ * Apply a single new charge to a session in place. Idempotent across
80
+ * `chargeId` because the caller (handlers.ts) guards via the
81
+ * `pay:idempotency:{chargeId}` sentinel before this fires; we don't
82
+ * re-check here.
83
+ *
84
+ * - vip: replaces `session.pay.vip` (renewals update expiresAt;
85
+ * tier upgrades replace rung)
86
+ * - credits: increments `session.pay.credits` by the granted amount
87
+ * (covers both pack purchases AND vip renewal grants)
88
+ * - perks: set-if-absent on `session.pay.perks[key]`
89
+ */
90
+ export const applyCharge = (session, charge) => {
91
+ session.pay ??= {};
92
+ const pay = session.pay;
93
+ if (charge.creditsGranted > 0) {
94
+ pay.credits = (pay.credits ?? 0) + charge.creditsGranted;
95
+ }
96
+ if (charge.vipRung !== undefined &&
97
+ charge.subscriptionExpiresAt !== undefined) {
98
+ pay.vip = {
99
+ rung: charge.vipRung,
100
+ chargeId: charge.chargeId,
101
+ expiresAt: charge.subscriptionExpiresAt,
102
+ canceled: false,
103
+ };
104
+ }
105
+ if (charge.perkKey) {
106
+ pay.perks ??= {};
107
+ if (!pay.perks[charge.perkKey]) {
108
+ pay.perks[charge.perkKey] = {
109
+ chargeId: charge.chargeId,
110
+ at: charge.receivedAt,
111
+ };
112
+ }
113
+ }
114
+ };
115
+ /**
116
+ * Subtract a refunded charge's `creditsGranted` from the session
117
+ * balance, clamping at zero. The "clamp at zero" semantics are
118
+ * deliberate: a user may have already consumed credits when the refund
119
+ * arrives, and going negative would let them buy back into a debt — we
120
+ * refuse that and accept the asymmetry (the refunded Stars are already
121
+ * leaving the bot's balance via `refundStarPayment` either way).
122
+ */
123
+ export const revertCreditsForCharge = (session, charge) => {
124
+ if (!charge.creditsGranted)
125
+ return;
126
+ session.pay ??= {};
127
+ const pay = session.pay;
128
+ const current = pay.credits ?? 0;
129
+ pay.credits = Math.max(0, current - charge.creditsGranted);
130
+ };
131
+ /**
132
+ * Rebuild vip + perks (the fully-derivable parts of session.pay.*)
133
+ * from a fresh chronological view of the charge log, **after** the
134
+ * caller has marked any newly-refunded charges. Credits balance is
135
+ * NOT touched — caller handles that explicitly via
136
+ * `revertCreditsForCharge` for the targeted decrement semantics.
137
+ *
138
+ * Used by:
139
+ * - refund.ts after `refundStarPayment` succeeds
140
+ * - reconcile (admin command) for full state recovery
141
+ */
142
+ export const rebuildVipAndPerks = (session, charges) => {
143
+ const derived = deriveState(charges);
144
+ session.pay ??= {};
145
+ const pay = session.pay;
146
+ pay.vip = derived.vip;
147
+ pay.perks = derived.perks;
148
+ };
149
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/bot/payments/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The plugin's storage layout, in one place.
3
+ *
4
+ * Replaces the scattered `chargeKey` / `userChargesIndexKey` /
5
+ * `idempotencyKey` / `payoutKey` / `payoutsIndexKey` helpers that used
6
+ * to live in `handlers.ts`, `refund.ts`, `payouts.ts`. Every storage
7
+ * operation in the plugin goes through one of these handles.
8
+ *
9
+ * Built once at plugin construction (in `plugin.ts`) and threaded
10
+ * through every concern that needs it.
11
+ */
12
+ import type { Storage } from "@gramio/storage";
13
+ import { botIndex, botRecord, botSentinel } from "../storage.js";
14
+ import type { ChargeRecord, PayoutRecord } from "./types.js";
15
+ export type PaymentsStores = {
16
+ /** `pay:charge:<chargeId>` — authoritative per-charge record. */
17
+ readonly charges: ReturnType<typeof botRecord<ChargeRecord>>;
18
+ /** `pay:idem:<chargeId>` — fulfillment idempotency sentinel. */
19
+ readonly idempotency: ReturnType<typeof botSentinel>;
20
+ /**
21
+ * `pay:user:<userId>:charges` — newest-first cap of chargeIds for
22
+ * `/refunds` listing + menu history (v2). Factory because the key
23
+ * is per-user.
24
+ */
25
+ readonly userCharges: (userId: number) => ReturnType<typeof botIndex>;
26
+ /** `pay:payout:<batchId>` — Fragment payout record. */
27
+ readonly payouts: ReturnType<typeof botRecord<PayoutRecord>>;
28
+ /** `pay:payouts:index` — newest-first batchIds for export. */
29
+ readonly payoutsIndex: ReturnType<typeof botIndex>;
30
+ };
31
+ /**
32
+ * Construct the plugin's storage handles. Called once at plugin
33
+ * construction; the result is passed into every concern that reads or
34
+ * writes plugin state.
35
+ *
36
+ * Schemas are wired in — every `.get()` on `charges` / `payouts` runs
37
+ * the corresponding zod schema's `.parse()` and throws a clear
38
+ * `SourcedError({ source: 'storage', operation: 'validate' })` on a
39
+ * corrupted record (instead of NaN-ing downstream when the consumer
40
+ * reads a now-missing field). `idempotency` is a presence-only sentinel
41
+ * so no schema applies; `*Index` stores `string[]` so likewise.
42
+ */
43
+ export declare const buildStores: (storage: Storage) => PaymentsStores;
44
+ //# sourceMappingURL=stores.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stores.d.ts","sourceRoot":"","sources":["../../../src/bot/payments/stores.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO7D,MAAM,MAAM,cAAc,GAAG;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7D,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACrD;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;IACtE,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7D,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;CACnD,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,OAAO,KAAG,cAS7C,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The plugin's storage layout, in one place.
3
+ *
4
+ * Replaces the scattered `chargeKey` / `userChargesIndexKey` /
5
+ * `idempotencyKey` / `payoutKey` / `payoutsIndexKey` helpers that used
6
+ * to live in `handlers.ts`, `refund.ts`, `payouts.ts`. Every storage
7
+ * operation in the plugin goes through one of these handles.
8
+ *
9
+ * Built once at plugin construction (in `plugin.ts`) and threaded
10
+ * through every concern that needs it.
11
+ */
12
+ import { botIndex, botRecord, botSentinel } from "../storage.js";
13
+ import { chargeRecordSchema, payoutRecordSchema } from "./schemas.js";
14
+ /** Cap on the per-user `pay:user:<id>:charges` index. Older charges
15
+ * drop off the list but remain in `pay:charge:<id>` for the gestor
16
+ * export (which scans charges directly, not the index). */
17
+ const USER_CHARGES_CAP = 100;
18
+ /**
19
+ * Construct the plugin's storage handles. Called once at plugin
20
+ * construction; the result is passed into every concern that reads or
21
+ * writes plugin state.
22
+ *
23
+ * Schemas are wired in — every `.get()` on `charges` / `payouts` runs
24
+ * the corresponding zod schema's `.parse()` and throws a clear
25
+ * `SourcedError({ source: 'storage', operation: 'validate' })` on a
26
+ * corrupted record (instead of NaN-ing downstream when the consumer
27
+ * reads a now-missing field). `idempotency` is a presence-only sentinel
28
+ * so no schema applies; `*Index` stores `string[]` so likewise.
29
+ */
30
+ export const buildStores = (storage) => ({
31
+ charges: botRecord(storage, "pay:charge", chargeRecordSchema),
32
+ idempotency: botSentinel(storage, "pay:idem"),
33
+ userCharges: (userId) => botIndex(storage, `pay:user:${userId}:charges`, {
34
+ capacity: USER_CHARGES_CAP,
35
+ }),
36
+ payouts: botRecord(storage, "pay:payout", payoutRecordSchema),
37
+ payoutsIndex: botIndex(storage, "pay:payouts:index"),
38
+ });
39
+ //# sourceMappingURL=stores.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stores.js","sourceRoot":"","sources":["../../../src/bot/payments/stores.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGtE;;4DAE4D;AAC5D,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAmB7B;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAgB,EAAkB,EAAE,CAAC,CAAC;IACjE,OAAO,EAAE,SAAS,CAAe,OAAO,EAAE,YAAY,EAAE,kBAAkB,CAAC;IAC3E,WAAW,EAAE,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7C,WAAW,EAAE,CAAC,MAAc,EAAE,EAAE,CAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,MAAM,UAAU,EAAE;QAC/C,QAAQ,EAAE,gBAAgB;KAC1B,CAAC;IACH,OAAO,EAAE,SAAS,CAAe,OAAO,EAAE,YAAY,EAAE,kBAAkB,CAAC;IAC3E,YAAY,EAAE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;CACpD,CAAC,CAAC"}
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Type surface for `bot/payments`. Two layers:
3
+ *
4
+ * 1. **Config shapes** the consumer authors (`BotPaymentsConfig`).
5
+ * 2. **Derived types** the consumer reads through `ctx.payments`
6
+ * (`TierKey`, `AtLeastKey`, `ProductKey`) — narrowed from their
7
+ * config so e.g. `atLeast('vip.5')` is a TS error when only 2
8
+ * rungs are declared.
9
+ *
10
+ * Internal types (the ledger records, the catalog) live below and aren't
11
+ * exported through the package entrypoint.
12
+ *
13
+ * See `CLAUDE.md` in this folder for the design rationale.
14
+ */
15
+ import type { Polyglot } from "../../say/index.js";
16
+ /**
17
+ * The only Telegram-supported subscription period as of 2026 is exactly
18
+ * 2,592,000 seconds (30 days). Modeled as a literal so misconfigurations
19
+ * fail at compile time. See `sendInvoice` /
20
+ * `createInvoiceLink` docs at https://core.telegram.org/bots/api.
21
+ */
22
+ export type SubscriptionPeriod = "30d";
23
+ /** Internal value Telegram expects on the wire (seconds). */
24
+ export declare const SUBSCRIPTION_PERIOD_SECONDS: Readonly<Record<SubscriptionPeriod, number>>;
25
+ /**
26
+ * One rung of the VIP ladder. Position in the array is the rank (1-based
27
+ * id at the call site: `vip.1`, `vip.2`, …). Insert a rung at position 2
28
+ * → existing subscribers on rung 2+ shift by one, plus a trivial storage
29
+ * migration; no string-id churn.
30
+ *
31
+ * `name` is display-only Polyglot — renaming a rung is a config edit; the
32
+ * call sites (`atLeast('vip.2')`) are positional and untouched.
33
+ *
34
+ * `grants.credits` is applied **on every renewal** of this rung (not just
35
+ * the initial purchase). That's the canonical SaaS shape: "VIP gets 1000
36
+ * messages per month."
37
+ */
38
+ export type VipRung<L extends string = string> = {
39
+ readonly xtr: number;
40
+ readonly period: SubscriptionPeriod;
41
+ readonly name: Polyglot<L>;
42
+ readonly grants?: {
43
+ readonly credits?: number;
44
+ };
45
+ };
46
+ /**
47
+ * A consumable credit pack the user buys one-shot to top up their
48
+ * `session.pay.credits` balance. Like VIP rungs, packs are positionally
49
+ * identified (`credits.1`, `credits.2`, …) so the call site doesn't carry
50
+ * a name. Adding/removing packs shifts ids; storage is the charge log
51
+ * (which records the exact productKey at purchase time), so historical
52
+ * charges stay valid even if you remove a pack later.
53
+ */
54
+ export type CreditsPack<L extends string = string> = {
55
+ readonly xtr: number;
56
+ readonly grants: {
57
+ readonly credits: number;
58
+ };
59
+ readonly name?: Polyglot<L>;
60
+ };
61
+ /**
62
+ * Credits axis config. `unit` is the user-facing word for one credit
63
+ * (the menu says e.g. "1234 mensajes"). `packs` is the catalogue of
64
+ * top-up bundles surfaced in the menu and via `invoice('credits.N')`.
65
+ */
66
+ export type CreditsConfig<L extends string = string> = {
67
+ readonly unit: Polyglot<L>;
68
+ readonly packs: ReadonlyArray<CreditsPack<L>>;
69
+ };
70
+ /**
71
+ * Orthogonal one-shot unlock (a "perk"). Named via the user's own key in
72
+ * the config (`perks: { voice_mode: { … } }`), surfaced as
73
+ * `perks.voice_mode` everywhere.
74
+ */
75
+ export type Perk<L extends string = string> = {
76
+ readonly xtr: number;
77
+ readonly name: Polyglot<L>;
78
+ };
79
+ export type PerksConfig<L extends string = string> = Readonly<Record<string, Perk<L>>>;
80
+ export type LegalConfig = {
81
+ readonly sellerName: string;
82
+ readonly nif: string;
83
+ /**
84
+ * Optional terms-of-service URL. When omitted, the consent prompt's
85
+ * 📖 Terms button is hidden — there's no Telegram-side standard ToS
86
+ * to default to (unlike `privacyUrl`).
87
+ */
88
+ readonly termsUrl?: string;
89
+ /**
90
+ * Optional privacy policy URL. When omitted, defaults to Telegram's
91
+ * [Standard Bot Privacy Policy](https://telegram.org/privacy-tpa),
92
+ * which covers what this library's plugins retain (session record,
93
+ * waiver consent, charge log) under "data necessary to function".
94
+ * Override only when your bot retains data beyond what the standard
95
+ * covers.
96
+ */
97
+ readonly privacyUrl?: string;
98
+ };
99
+ /**
100
+ * Fallback when `legal.privacyUrl` is omitted. Identical to the menu
101
+ * plugin's default — both surface the same policy text.
102
+ */
103
+ export declare const DEFAULT_PRIVACY_URL = "https://telegram.org/privacy-tpa";
104
+ /**
105
+ * Art. 103(m) TRLGDCU waiver text. Versioned so a wording change forces
106
+ * re-consent; the version string is stored alongside each charge for audit.
107
+ *
108
+ * The Polyglot covers every locale the bot supports — the plugin
109
+ * validates this at construction.
110
+ */
111
+ export type WaiverConfig<L extends string = string> = {
112
+ readonly version: string;
113
+ readonly text: Polyglot<L>;
114
+ };
115
+ /**
116
+ * What the bot author passes to `botPayments({...})`. The generic `L`
117
+ * carries the bot's Polyglot language union forward into every nested
118
+ * `Polyglot<L>`, so TS catches a missing locale in any sub-config.
119
+ */
120
+ export type BotPaymentsConfig<L extends string = string> = {
121
+ readonly paysupport: string;
122
+ readonly legal: LegalConfig;
123
+ readonly waiver: WaiverConfig<L>;
124
+ readonly vip?: ReadonlyArray<VipRung<L>>;
125
+ readonly credits?: CreditsConfig<L>;
126
+ readonly perks?: PerksConfig<L>;
127
+ };
128
+ type _Range1To<N extends number, Acc extends unknown[] = [unknown]> = Acc["length"] extends N ? Acc["length"] : Acc["length"] | _Range1To<N, [...Acc, unknown]>;
129
+ /**
130
+ * Positional 1-based ids for a tuple. `[a,b,c]` → `1 | 2 | 3`.
131
+ *
132
+ * Empty tuple → `never` (no ids exist).
133
+ */
134
+ export type Indices1<V extends ReadonlyArray<unknown>> = V["length"] extends 0 ? never : V["length"] extends number ? _Range1To<V["length"]> : never;
135
+ /**
136
+ * Tier ids derivable from a `vip` config array. Bare `'vip'` is also
137
+ * accepted as "any rung" by `atLeast` (see `AtLeastKey`).
138
+ */
139
+ export type VipPositionalKeys<V extends ReadonlyArray<unknown> | undefined> = V extends ReadonlyArray<unknown> ? `vip.${Indices1<V>}` : never;
140
+ export type CreditsPackKeys<C extends CreditsConfig<string> | undefined> = C extends {
141
+ packs: infer P;
142
+ } ? P extends ReadonlyArray<unknown> ? `credits.${Indices1<P>}` : never : never;
143
+ export type PerkKeys<P extends PerksConfig<string> | undefined> = P extends PerksConfig<string> ? `perks.${keyof P & string}` : never;
144
+ /**
145
+ * Every product the user can purchase. Discriminated by prefix. Note
146
+ * `perks.X` uses the **author-supplied key** verbatim (e.g.
147
+ * `perks.voice_mode`) while `vip.N` / `credits.N` are positional.
148
+ */
149
+ export type ProductKey<Cfg extends BotPaymentsConfig<string>> = VipPositionalKeys<Cfg["vip"]> | CreditsPackKeys<Cfg["credits"]> | PerkKeys<Cfg["perks"]>;
150
+ /**
151
+ * What `ctx.payments.tier()` can return. `'free'` is the bottom rung;
152
+ * `vip.N` follows the ladder.
153
+ */
154
+ export type TierKey<Cfg extends BotPaymentsConfig<string>> = "free" | VipPositionalKeys<Cfg["vip"]>;
155
+ /**
156
+ * What `ctx.payments.atLeast(...)` accepts. Same as `TierKey` minus
157
+ * `'free'` (atLeast('free') is trivially always true and unhelpful as a
158
+ * gate) plus the bare `'vip'` synonym for "any rung in the namespace".
159
+ */
160
+ export type AtLeastKey<Cfg extends BotPaymentsConfig<string>> = "vip" | VipPositionalKeys<Cfg["vip"]>;
161
+ export type VipRungResolved = {
162
+ readonly id: `vip.${number}`;
163
+ readonly rank: number;
164
+ readonly xtr: number;
165
+ readonly periodSeconds: number;
166
+ readonly name: Polyglot<string>;
167
+ readonly creditsGranted: number;
168
+ };
169
+ export type CreditsPackResolved = {
170
+ readonly id: `credits.${number}`;
171
+ readonly xtr: number;
172
+ readonly creditsGranted: number;
173
+ readonly name?: Polyglot<string>;
174
+ };
175
+ export type PerkResolved = {
176
+ readonly id: `perks.${string}`;
177
+ readonly key: string;
178
+ readonly xtr: number;
179
+ readonly name: Polyglot<string>;
180
+ };
181
+ export type ProductCatalog = {
182
+ readonly vip: ReadonlyArray<VipRungResolved>;
183
+ readonly creditsUnit: Polyglot<string> | undefined;
184
+ readonly creditsPacks: ReadonlyArray<CreditsPackResolved>;
185
+ readonly perks: ReadonlyArray<PerkResolved>;
186
+ /** O(1) lookup by ProductKey. */
187
+ readonly byKey: ReadonlyMap<string, VipRungResolved | CreditsPackResolved | PerkResolved>;
188
+ };
189
+ export type WaiverRecord = {
190
+ readonly at: number;
191
+ readonly version: string;
192
+ readonly locale: string;
193
+ };
194
+ export type VipState = {
195
+ /** 1-based rank — index into the resolved vip ladder + 1. */
196
+ readonly rung: number;
197
+ /** Original `telegram_payment_charge_id` of the active subscription. */
198
+ readonly chargeId: string;
199
+ /** Telegram's `subscription_expiration_date` — unix seconds. */
200
+ readonly expiresAt: number;
201
+ /** True after the user toggled cancel-renewal; access keeps until `expiresAt`. */
202
+ readonly canceled: boolean;
203
+ };
204
+ export type PerkState = {
205
+ readonly chargeId: string;
206
+ readonly at: number;
207
+ };
208
+ export type PaymentsSession = {
209
+ waiver?: WaiverRecord;
210
+ credits?: number;
211
+ vip?: VipState;
212
+ perks?: Record<string, PerkState>;
213
+ };
214
+ export type PaysupportState = "none" | "opened" | "refunded";
215
+ export type ChargeRecord = {
216
+ readonly chargeId: string;
217
+ readonly userId: number;
218
+ readonly productKey: string;
219
+ readonly xtr: number;
220
+ readonly receivedAt: number;
221
+ /** Decoded invoice payload echoed back from Telegram. */
222
+ readonly payload: string;
223
+ /**
224
+ * Waiver snapshot at purchase time. Captured even if the user
225
+ * already consented earlier — defensive forensics.
226
+ */
227
+ readonly waiverSnapshot: WaiverRecord;
228
+ /**
229
+ * Telegram's `subscription_expiration_date` (unix seconds) if this
230
+ * charge was a subscription purchase. Used to compute tier expiry.
231
+ */
232
+ readonly subscriptionExpiresAt?: number;
233
+ /**
234
+ * Credits this charge grants at fulfillment / renewal. Denormalized
235
+ * onto the record so derivation works even if the catalog config
236
+ * later changes (rare, but the charge log must remain authoritative
237
+ * regardless of source-code edits). Zero for products that don't
238
+ * grant credits.
239
+ */
240
+ readonly creditsGranted: number;
241
+ /**
242
+ * 1-based vip rung this charge subscribed to, denormalized for the
243
+ * same reason as `creditsGranted`. Only set for `vip.*` charges.
244
+ */
245
+ readonly vipRung?: number;
246
+ /**
247
+ * Perk key this charge unlocked, denormalized. Only set for
248
+ * `perks.*` charges.
249
+ */
250
+ readonly perkKey?: string;
251
+ paysupportState: PaysupportState;
252
+ refundedAt?: number | null;
253
+ /** Set after `record()` claims this charge into a payout batch. */
254
+ payoutBatchId?: string | null;
255
+ };
256
+ export type PayoutRecord = {
257
+ readonly batchId: string;
258
+ readonly fromMs: number;
259
+ readonly toMs: number;
260
+ readonly tonAmount: number;
261
+ readonly eurAtReceipt: number;
262
+ readonly recordedAt: number;
263
+ /** Optional Spanish factura number issued for this payout. */
264
+ facturaNumber?: string;
265
+ };
266
+ /**
267
+ * Snapshot returned by `derive.ts` — pure function of the charge log
268
+ * for a given user. The plugin writes this into `session.pay.*` so
269
+ * runtime checks are O(1), but the log is always the truth.
270
+ */
271
+ export type DerivedPaymentsState = {
272
+ readonly credits: number;
273
+ readonly vip: VipState | undefined;
274
+ readonly perks: Record<string, PerkState>;
275
+ };
276
+ /**
277
+ * What `payments.onFulfilled(productKey, handler)` receives. Sync
278
+ * signature on purpose — the plugin always answers the
279
+ * `successful_payment` event itself; the handler does its own async work
280
+ * fire-and-forget.
281
+ */
282
+ export type FulfillmentEvent = {
283
+ readonly productKey: string;
284
+ readonly userId: number;
285
+ readonly chargeId: string;
286
+ readonly xtr: number;
287
+ readonly receivedAt: number;
288
+ };
289
+ /**
290
+ * Thrown by `credits.consume(n)` when the balance is below `n`.
291
+ * `tryConsume(n)` returns `false` instead.
292
+ */
293
+ export declare class InsufficientCredits extends Error {
294
+ readonly requested: number;
295
+ readonly available: number;
296
+ constructor(requested: number, available: number);
297
+ }
298
+ export {};
299
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/bot/payments/types.ts"],"names":[],"mappings":"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"}