@kasufinance/kasu-sdk 2.4.2 → 2.6.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 (180) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +201 -253
  3. package/dist/bundle.cjs.js +5472 -1710
  4. package/dist/bundle.esm.js +5415 -1713
  5. package/dist/domain/au-minimum.d.ts +135 -0
  6. package/dist/domain/au-minimum.js +154 -0
  7. package/dist/domain/au-minimum.js.map +1 -0
  8. package/dist/domain/au-minimum.test.js +202 -0
  9. package/dist/domain/au-minimum.test.js.map +1 -0
  10. package/dist/domain/deposit-bounds.d.ts +62 -0
  11. package/dist/domain/deposit-bounds.js +84 -0
  12. package/dist/domain/deposit-bounds.js.map +1 -0
  13. package/dist/domain/deposit-bounds.test.d.ts +1 -0
  14. package/dist/domain/deposit-bounds.test.js +135 -0
  15. package/dist/domain/deposit-bounds.test.js.map +1 -0
  16. package/dist/domain/index.d.ts +40 -0
  17. package/dist/domain/index.js +33 -0
  18. package/dist/domain/index.js.map +1 -0
  19. package/dist/domain/loan-contract.d.ts +174 -0
  20. package/dist/domain/loan-contract.js +160 -0
  21. package/dist/domain/loan-contract.js.map +1 -0
  22. package/dist/domain/loan-contract.test.d.ts +1 -0
  23. package/dist/domain/loan-contract.test.js +255 -0
  24. package/dist/domain/loan-contract.test.js.map +1 -0
  25. package/dist/domain/partners.d.ts +34 -0
  26. package/dist/domain/partners.js +43 -0
  27. package/dist/domain/partners.js.map +1 -0
  28. package/dist/domain/partners.test.d.ts +1 -0
  29. package/dist/domain/partners.test.js +53 -0
  30. package/dist/domain/partners.test.js.map +1 -0
  31. package/dist/domain/pools.d.ts +70 -0
  32. package/dist/domain/pools.js +134 -0
  33. package/dist/domain/pools.js.map +1 -0
  34. package/dist/domain/pools.test.d.ts +1 -0
  35. package/dist/domain/pools.test.js +184 -0
  36. package/dist/domain/pools.test.js.map +1 -0
  37. package/dist/domain/rates.d.ts +83 -0
  38. package/dist/domain/rates.js +120 -0
  39. package/dist/domain/rates.js.map +1 -0
  40. package/dist/domain/rates.test.d.ts +1 -0
  41. package/dist/domain/rates.test.js +181 -0
  42. package/dist/domain/rates.test.js.map +1 -0
  43. package/dist/domain/requests.d.ts +181 -0
  44. package/dist/domain/requests.js +202 -0
  45. package/dist/domain/requests.js.map +1 -0
  46. package/dist/domain/requests.test.d.ts +1 -0
  47. package/dist/domain/requests.test.js +470 -0
  48. package/dist/domain/requests.test.js.map +1 -0
  49. package/dist/domain/settlement.d.ts +97 -0
  50. package/dist/domain/settlement.js +117 -0
  51. package/dist/domain/settlement.js.map +1 -0
  52. package/dist/domain/settlement.test.d.ts +1 -0
  53. package/dist/domain/settlement.test.js +152 -0
  54. package/dist/domain/settlement.test.js.map +1 -0
  55. package/dist/domain/tranche-display-name.d.ts +17 -0
  56. package/dist/domain/tranche-display-name.js +30 -0
  57. package/dist/domain/tranche-display-name.js.map +1 -0
  58. package/dist/domain/tranche-display-name.test.d.ts +1 -0
  59. package/dist/domain/tranche-display-name.test.js +58 -0
  60. package/dist/domain/tranche-display-name.test.js.map +1 -0
  61. package/dist/domain/tranches.d.ts +89 -0
  62. package/dist/domain/tranches.js +150 -0
  63. package/dist/domain/tranches.js.map +1 -0
  64. package/dist/domain/tranches.test.d.ts +1 -0
  65. package/dist/domain/tranches.test.js +206 -0
  66. package/dist/domain/tranches.test.js.map +1 -0
  67. package/dist/domain/wallet-errors.d.ts +37 -0
  68. package/dist/domain/wallet-errors.js +56 -0
  69. package/dist/domain/wallet-errors.js.map +1 -0
  70. package/dist/domain/wallet-errors.test.d.ts +1 -0
  71. package/dist/domain/wallet-errors.test.js +71 -0
  72. package/dist/domain/wallet-errors.test.js.map +1 -0
  73. package/dist/facade/chain-configs.js +61 -1
  74. package/dist/facade/chain-configs.js.map +1 -1
  75. package/dist/facade/config.test.d.ts +1 -0
  76. package/dist/facade/config.test.js +216 -0
  77. package/dist/facade/config.test.js.map +1 -0
  78. package/dist/facade/deposits.d.ts +22 -1
  79. package/dist/facade/deposits.js +24 -1
  80. package/dist/facade/deposits.js.map +1 -1
  81. package/dist/facade/facade.test.d.ts +1 -0
  82. package/dist/{tests → facade}/facade.test.js +87 -5
  83. package/dist/facade/facade.test.js.map +1 -0
  84. package/dist/facade/index.d.ts +2 -1
  85. package/dist/facade/index.js +2 -0
  86. package/dist/facade/index.js.map +1 -1
  87. package/dist/facade/kasu.d.ts +49 -8
  88. package/dist/facade/kasu.js +117 -13
  89. package/dist/facade/kasu.js.map +1 -1
  90. package/dist/facade/strategies.d.ts +25 -0
  91. package/dist/facade/strategies.js +36 -0
  92. package/dist/facade/strategies.js.map +1 -1
  93. package/dist/facade/types.d.ts +57 -2
  94. package/dist/facade/unused-pool-ids.d.ts +31 -0
  95. package/dist/facade/unused-pool-ids.js +57 -0
  96. package/dist/facade/unused-pool-ids.js.map +1 -0
  97. package/dist/facade/user-portfolio.d.ts +18 -0
  98. package/dist/facade/user-portfolio.js +23 -0
  99. package/dist/facade/user-portfolio.js.map +1 -1
  100. package/dist/index.d.ts +2 -0
  101. package/dist/index.js +6 -0
  102. package/dist/index.js.map +1 -1
  103. package/dist/sdk-config.d.ts +11 -0
  104. package/dist/sdk-config.js +8 -1
  105. package/dist/sdk-config.js.map +1 -1
  106. package/dist/services/DataService/data-service.d.ts +5 -0
  107. package/dist/services/DataService/data-service.js +10 -12
  108. package/dist/services/DataService/data-service.js.map +1 -1
  109. package/dist/services/DataService/directus-client.d.ts +26 -0
  110. package/dist/services/DataService/directus-client.js +38 -0
  111. package/dist/services/DataService/directus-client.js.map +1 -0
  112. package/dist/services/Locking/calculate-apy.test.d.ts +1 -0
  113. package/dist/services/Locking/calculate-apy.test.js +41 -0
  114. package/dist/services/Locking/calculate-apy.test.js.map +1 -0
  115. package/dist/services/Locking/locking.d.ts +14 -0
  116. package/dist/services/Locking/locking.js +16 -2
  117. package/dist/services/Locking/locking.js.map +1 -1
  118. package/dist/services/UserLending/user-lending.js +11 -7
  119. package/dist/services/UserLending/user-lending.js.map +1 -1
  120. package/dist/tests/sample.test.js +46 -25
  121. package/dist/tests/sample.test.js.map +1 -1
  122. package/package.json +43 -12
  123. package/src/domain/au-minimum.test.ts +371 -0
  124. package/src/domain/au-minimum.ts +192 -0
  125. package/src/domain/deposit-bounds.test.ts +200 -0
  126. package/src/domain/deposit-bounds.ts +118 -0
  127. package/src/domain/index.ts +134 -0
  128. package/src/domain/loan-contract.test.ts +343 -0
  129. package/src/domain/loan-contract.ts +275 -0
  130. package/src/domain/partners.test.ts +83 -0
  131. package/src/domain/partners.ts +66 -0
  132. package/src/domain/pools.test.ts +260 -0
  133. package/src/domain/pools.ts +150 -0
  134. package/src/domain/rates.test.ts +254 -0
  135. package/src/domain/rates.ts +120 -0
  136. package/src/domain/requests.test.ts +653 -0
  137. package/src/domain/requests.ts +414 -0
  138. package/src/domain/settlement.test.ts +198 -0
  139. package/src/domain/settlement.ts +161 -0
  140. package/src/domain/tranche-display-name.test.ts +96 -0
  141. package/src/domain/tranche-display-name.ts +34 -0
  142. package/src/domain/tranches.test.ts +300 -0
  143. package/src/domain/tranches.ts +177 -0
  144. package/src/domain/wallet-errors.test.ts +100 -0
  145. package/src/domain/wallet-errors.ts +56 -0
  146. package/src/facade/chain-configs.ts +62 -1
  147. package/src/facade/config.test.ts +265 -0
  148. package/src/facade/deposits.ts +25 -0
  149. package/src/{tests → facade}/facade.test.ts +134 -5
  150. package/src/facade/index.ts +4 -0
  151. package/src/facade/kasu.ts +155 -12
  152. package/src/facade/strategies.ts +36 -0
  153. package/src/facade/types.ts +60 -2
  154. package/src/facade/unused-pool-ids.ts +59 -0
  155. package/src/facade/user-portfolio.ts +24 -0
  156. package/src/index.ts +8 -0
  157. package/src/sdk-config.ts +19 -1
  158. package/src/services/DataService/data-service.ts +14 -26
  159. package/src/services/DataService/directus-client.ts +54 -0
  160. package/src/services/Locking/calculate-apy.test.ts +52 -0
  161. package/src/services/Locking/locking.ts +16 -2
  162. package/src/services/UserLending/user-lending.ts +17 -21
  163. package/src/tests/sample.test.ts +54 -33
  164. package/.eslintignore +0 -3
  165. package/.eslintrc.json +0 -90
  166. package/.github/workflows/ci.yml +0 -39
  167. package/.github/workflows/gitleaks.yml +0 -22
  168. package/.github/workflows/main.yml +0 -41
  169. package/.gitleaksignore +0 -19
  170. package/.prettierignore +0 -3
  171. package/.prettierrc +0 -28
  172. package/CLAUDE.md +0 -410
  173. package/copy-abi.ps1 +0 -15
  174. package/dist/tests/facade.test.js.map +0 -1
  175. package/index.ts +0 -2
  176. package/jest-config.ts +0 -9
  177. package/jest.config.js +0 -8
  178. package/rollup.config.js +0 -45
  179. package/tsconfig.json +0 -27
  180. /package/dist/{tests/facade.test.d.ts → domain/au-minimum.test.d.ts} +0 -0
@@ -0,0 +1,470 @@
1
+ import { UserRequestStatus } from '../services/UserLending/subgraph-types';
2
+ import { countSubmissions, deriveRequestState, firstSubmissionTimestamp, isCycleClosed, submissionEvents, } from './requests';
3
+ /**
4
+ * Ported from kasu-ui `src/features/portfolio/lib/derive-transaction-view.test.ts`.
5
+ * The status-word, detail-line, tranche-rename and `splitPoolName` cases stay
6
+ * there — they assert copy and display, which this layer does not own. What
7
+ * comes across is every assertion about codes, kind, amounts, ids and counts,
8
+ * because those are the branch behaviour.
9
+ */
10
+ const TRANCHE_ID = '0xtranche-senior';
11
+ const OTHER_TRANCHE_ID = '0xtranche-mezzanine';
12
+ const POOL_ID = '0xPool-PayFi';
13
+ const POOL_NAME = 'Payment Finance (PayFi) - Payment Clearing Houses';
14
+ const REQUESTED = UserRequestStatus.REQUESTED;
15
+ const PROCESSING = UserRequestStatus.PROCESSING;
16
+ const PROCESSED = UserRequestStatus.PROCESSED;
17
+ function makeRequest(overrides = {}) {
18
+ return Object.assign({ id: 'req-1', userId: '0xuser', lendingPool: {
19
+ id: POOL_ID,
20
+ name: POOL_NAME,
21
+ tranches: [{ orderId: '0' }],
22
+ }, requestType: 'Deposit', trancheId: TRANCHE_ID, trancheName: 'Senior', requestedAmount: '100', acceptedAmount: '0', rejectedAmount: '0', timestamp: 1700000000, status: REQUESTED, canCancel: true, events: [], nftId: '', apy: '0', fixedTermConfig: undefined }, overrides);
23
+ }
24
+ function event(partial) {
25
+ return Object.assign({ id: 'evt', requestType: 'Initiated', assetAmount: '0', totalRequested: '0', totalAccepted: '0', totalRejected: '0', index: 0, timestamp: 1700000000, transactionHash: '0x', trancheName: 'Senior', trancheId: TRANCHE_ID, apy: '0', epochId: '0' }, partial);
26
+ }
27
+ describe('deriveRequestState — every branch of the derivation', () => {
28
+ it('deposit just submitted, cycle open → pending · inflow · +requested', () => {
29
+ const state = deriveRequestState(makeRequest());
30
+ expect(state.statusCode).toBe('pending');
31
+ expect(state.kind).toBe('inflow');
32
+ expect(state.amount).toBe(100);
33
+ expect(state.cycleClosed).toBe(false);
34
+ expect(state.canCancel).toBe(true);
35
+ });
36
+ it('deposit while its pool is clearing (canCancel false) → pending, cycle CLOSED', () => {
37
+ const state = deriveRequestState(makeRequest({ canCancel: false }));
38
+ expect(state.statusCode).toBe('pending');
39
+ expect(state.cycleClosed).toBe(true);
40
+ });
41
+ it('a STICKY Processing raw status with an open cycle stays pending and open', () => {
42
+ // The subgraph never resets `status` after a partial fill — `canCancel`
43
+ // alone decides open/closed.
44
+ const state = deriveRequestState(makeRequest({ status: PROCESSING, canCancel: true }));
45
+ expect(state.statusCode).toBe('pending');
46
+ expect(state.cycleClosed).toBe(false);
47
+ expect(state.rawStatus).toBe(PROCESSING);
48
+ });
49
+ it('deposit fully accepted → complete · inflow · +accepted', () => {
50
+ const state = deriveRequestState(makeRequest({
51
+ status: PROCESSED,
52
+ canCancel: false,
53
+ acceptedAmount: '100',
54
+ }));
55
+ expect(state.statusCode).toBe('complete');
56
+ expect(state.kind).toBe('inflow');
57
+ expect(state.amount).toBe(100);
58
+ });
59
+ it('deposit partially accepted → partial · inflow · the accepted figure', () => {
60
+ const state = deriveRequestState(makeRequest({
61
+ status: PROCESSED,
62
+ canCancel: false,
63
+ acceptedAmount: '60',
64
+ rejectedAmount: '40',
65
+ }));
66
+ expect(state.statusCode).toBe('partial');
67
+ expect(state.kind).toBe('inflow');
68
+ expect(state.amount).toBe(60);
69
+ expect(state.requestedAmount).toBe(100);
70
+ expect(state.acceptedAmount).toBe(60);
71
+ });
72
+ it('deposit fully rejected → rejected · neutral · 0 — a rejection IS a resolution', () => {
73
+ const state = deriveRequestState(makeRequest({
74
+ status: PROCESSED,
75
+ canCancel: false,
76
+ rejectedAmount: '100',
77
+ }));
78
+ expect(state.statusCode).toBe('rejected');
79
+ expect(state.kind).toBe('neutral');
80
+ expect(state.amount).toBe(0);
81
+ });
82
+ it('deposit cancelled → cancelled · neutral · 0', () => {
83
+ const state = deriveRequestState(makeRequest({ events: [event({ requestType: 'Cancelled' })] }));
84
+ expect(state.statusCode).toBe('cancelled');
85
+ expect(state.kind).toBe('neutral');
86
+ expect(state.amount).toBe(0);
87
+ });
88
+ it('a Cancelled event outranks a resolved status', () => {
89
+ const state = deriveRequestState(makeRequest({
90
+ status: PROCESSED,
91
+ canCancel: false,
92
+ acceptedAmount: '100',
93
+ events: [event({ requestType: 'Cancelled' })],
94
+ }));
95
+ expect(state.statusCode).toBe('cancelled');
96
+ expect(state.amount).toBe(0);
97
+ });
98
+ it('deposit reallocated (Accepted into another tranche) → reallocated · inflow', () => {
99
+ const state = deriveRequestState(makeRequest({
100
+ status: PROCESSED,
101
+ canCancel: false,
102
+ acceptedAmount: '100',
103
+ events: [
104
+ event({
105
+ requestType: 'Accepted',
106
+ trancheId: OTHER_TRANCHE_ID,
107
+ trancheName: 'Mezzanine',
108
+ assetAmount: '100',
109
+ }),
110
+ ],
111
+ }));
112
+ expect(state.statusCode).toBe('reallocated');
113
+ expect(state.kind).toBe('inflow');
114
+ expect(state.amount).toBe(100);
115
+ });
116
+ it('an Accepted event into the SAME tranche is not a reallocation', () => {
117
+ const state = deriveRequestState(makeRequest({
118
+ status: PROCESSED,
119
+ canCancel: false,
120
+ acceptedAmount: '100',
121
+ events: [
122
+ event({
123
+ requestType: 'Accepted',
124
+ trancheId: TRANCHE_ID.toUpperCase(),
125
+ assetAmount: '100',
126
+ }),
127
+ ],
128
+ }));
129
+ // Tranche ids are compared case-insensitively, so an upper-cased
130
+ // spelling of the same tranche must not read as a move.
131
+ expect(state.statusCode).toBe('complete');
132
+ });
133
+ it('an explicit Reallocated event is a reallocation whatever the tranche', () => {
134
+ const state = deriveRequestState(makeRequest({
135
+ status: PROCESSED,
136
+ canCancel: false,
137
+ acceptedAmount: '100',
138
+ events: [
139
+ event({
140
+ requestType: 'Reallocated',
141
+ assetAmount: '100',
142
+ }),
143
+ ],
144
+ }));
145
+ expect(state.statusCode).toBe('reallocated');
146
+ });
147
+ it('a withdrawal is never reallocated, whatever its events say', () => {
148
+ const state = deriveRequestState(makeRequest({
149
+ requestType: 'Withdrawal',
150
+ status: PROCESSED,
151
+ canCancel: false,
152
+ acceptedAmount: '100',
153
+ events: [
154
+ event({
155
+ requestType: 'Accepted',
156
+ trancheId: OTHER_TRANCHE_ID,
157
+ assetAmount: '100',
158
+ }),
159
+ ],
160
+ }));
161
+ expect(state.statusCode).toBe('complete');
162
+ expect(state.kind).toBe('outflow');
163
+ });
164
+ it('withdrawal submitted, cycle open → pending · outflow · −requested', () => {
165
+ const state = deriveRequestState(makeRequest({ requestType: 'Withdrawal' }));
166
+ expect(state.statusCode).toBe('pending');
167
+ expect(state.kind).toBe('outflow');
168
+ expect(state.amount).toBe(-100);
169
+ });
170
+ it('withdrawal fully filled → complete · −accepted', () => {
171
+ const state = deriveRequestState(makeRequest({
172
+ requestType: 'Withdrawal',
173
+ status: PROCESSED,
174
+ canCancel: false,
175
+ acceptedAmount: '100',
176
+ }));
177
+ expect(state.statusCode).toBe('complete');
178
+ expect(state.amount).toBe(-100);
179
+ });
180
+ it('withdrawal partly filled with a LIVE remainder → partial while the cycle is open', () => {
181
+ // Realistic shape: the sticky raw status reads Processing, canCancel
182
+ // marks the new cycle open — the request returns to the queue with a
183
+ // live Cancel.
184
+ const state = deriveRequestState(makeRequest({
185
+ requestType: 'Withdrawal',
186
+ status: PROCESSING,
187
+ canCancel: true,
188
+ acceptedAmount: '60',
189
+ }));
190
+ expect(state.statusCode).toBe('partial');
191
+ expect(state.kind).toBe('outflow');
192
+ expect(state.amount).toBe(-60);
193
+ expect(state.cycleClosed).toBe(false);
194
+ });
195
+ it('withdrawal partly filled, pool CLEARING → pending with the cycle closed (locked remainder)', () => {
196
+ const state = deriveRequestState(makeRequest({
197
+ requestType: 'Withdrawal',
198
+ status: PROCESSING,
199
+ canCancel: false,
200
+ acceptedAmount: '60',
201
+ }));
202
+ expect(state.statusCode).toBe('pending');
203
+ expect(state.cycleClosed).toBe(true);
204
+ expect(state.amount).toBe(-100);
205
+ });
206
+ it('withdrawal partly filled, TERMINAL → partial', () => {
207
+ const state = deriveRequestState(makeRequest({
208
+ requestType: 'Withdrawal',
209
+ status: PROCESSED,
210
+ canCancel: false,
211
+ acceptedAmount: '60',
212
+ }));
213
+ expect(state.statusCode).toBe('partial');
214
+ expect(state.amount).toBe(-60);
215
+ });
216
+ it('forced withdrawal → forced · outflow · −accepted', () => {
217
+ const state = deriveRequestState(makeRequest({
218
+ requestType: 'Withdrawal',
219
+ status: PROCESSED,
220
+ canCancel: false,
221
+ acceptedAmount: '80',
222
+ events: [event({ requestType: 'Forced' })],
223
+ }));
224
+ expect(state.statusCode).toBe('forced');
225
+ expect(state.kind).toBe('outflow');
226
+ expect(state.amount).toBe(-80);
227
+ });
228
+ it('a Forced event on a DEPOSIT is not a forced withdrawal', () => {
229
+ const state = deriveRequestState(makeRequest({
230
+ status: PROCESSED,
231
+ canCancel: false,
232
+ acceptedAmount: '80',
233
+ events: [event({ requestType: 'Forced' })],
234
+ }));
235
+ expect(state.statusCode).toBe('complete');
236
+ expect(state.kind).toBe('inflow');
237
+ });
238
+ it('withdrawal cancelled → cancelled · neutral · 0', () => {
239
+ const state = deriveRequestState(makeRequest({
240
+ requestType: 'Withdrawal',
241
+ events: [event({ requestType: 'Cancelled' })],
242
+ }));
243
+ expect(state.statusCode).toBe('cancelled');
244
+ expect(state.kind).toBe('neutral');
245
+ expect(state.amount).toBe(0);
246
+ });
247
+ });
248
+ describe('deriveRequestState — the cancelled-amount recovery', () => {
249
+ it('recovers a zeroed requestedAmount from the Initiated event', () => {
250
+ const state = deriveRequestState(makeRequest({
251
+ requestedAmount: '0',
252
+ events: [
253
+ event({ requestType: 'Initiated', assetAmount: '250' }),
254
+ event({ requestType: 'Cancelled', index: 1 }),
255
+ ],
256
+ }));
257
+ expect(state.requestedAmount).toBe(250);
258
+ expect(state.initiatedAmount).toBe(250);
259
+ });
260
+ it('falls back to 0 when the cancelled request has no Initiated event', () => {
261
+ const state = deriveRequestState(makeRequest({
262
+ requestedAmount: '0',
263
+ events: [event({ requestType: 'Cancelled' })],
264
+ }));
265
+ expect(state.requestedAmount).toBe(0);
266
+ expect(state.initiatedAmount).toBeNull();
267
+ });
268
+ it('does not recover for a request that was NOT cancelled', () => {
269
+ // A live request with a genuinely zero requested amount keeps it; only
270
+ // the cancelled branch reaches for the Initiated event.
271
+ const state = deriveRequestState(makeRequest({
272
+ requestedAmount: '0',
273
+ events: [
274
+ event({ requestType: 'Initiated', assetAmount: '250' }),
275
+ ],
276
+ }));
277
+ expect(state.requestedAmount).toBe(0);
278
+ expect(state.initiatedAmount).toBe(250);
279
+ });
280
+ });
281
+ describe('deriveRequestState — ids, counts and pass-through fields', () => {
282
+ it('takes contractId from the Initiated EVENT, not the request id', () => {
283
+ const state = deriveRequestState(makeRequest({
284
+ events: [
285
+ event({ requestType: 'Initiated', id: 'req-1-0' }),
286
+ event({
287
+ requestType: 'Increased',
288
+ id: 'req-1-1',
289
+ index: 1,
290
+ }),
291
+ ],
292
+ }));
293
+ expect(state.contractId).toBe('req-1-0');
294
+ expect(state.id).toBe('req-1');
295
+ });
296
+ it('leaves contractId empty when nothing was Initiated', () => {
297
+ expect(deriveRequestState(makeRequest()).contractId).toBe('');
298
+ });
299
+ it('lowercases the pool id and leaves the pool name raw', () => {
300
+ const state = deriveRequestState(makeRequest());
301
+ expect(state.poolId).toBe(POOL_ID.toLowerCase());
302
+ expect(state.poolName).toBe(POOL_NAME);
303
+ });
304
+ it('leaves the tranche name RAW — the display rename is the app’s', () => {
305
+ // An Apxium pool: kasu-ui shows "Upper Mezzanine" here, this layer must
306
+ // not, or a renamed name would reach matching code.
307
+ const state = deriveRequestState(makeRequest({
308
+ lendingPool: {
309
+ id: '0xpool-apxium',
310
+ name: 'Taxation Funding (Tax Pay) - Diversified Businesses',
311
+ tranches: [{ orderId: '0' }],
312
+ },
313
+ }));
314
+ expect(state.trancheName).toBe('Senior');
315
+ });
316
+ it('defaults fixedTermConfigId to "0" for a variable-rate request', () => {
317
+ expect(deriveRequestState(makeRequest()).fixedTermConfigId).toBe('0');
318
+ });
319
+ it('passes a fixed-term configId through', () => {
320
+ const state = deriveRequestState(makeRequest({
321
+ fixedTermConfig: {
322
+ configId: '7',
323
+ apy: '0.1',
324
+ epochLockDuration: '4',
325
+ epochInterestRate: '0.002',
326
+ },
327
+ }));
328
+ expect(state.fixedTermConfigId).toBe('7');
329
+ });
330
+ it('counts only submissions into submissionCount and takes the earliest one', () => {
331
+ const state = deriveRequestState(makeRequest({
332
+ events: [
333
+ event({
334
+ requestType: 'Initiated',
335
+ timestamp: 1700000500,
336
+ }),
337
+ event({
338
+ requestType: 'Increased',
339
+ timestamp: 1700000100,
340
+ index: 1,
341
+ }),
342
+ event({
343
+ requestType: 'Accepted',
344
+ timestamp: 1700000900,
345
+ index: 2,
346
+ }),
347
+ ],
348
+ }));
349
+ expect(state.submissionCount).toBe(2);
350
+ expect(state.firstSubmissionTimestamp).toBe(1700000100);
351
+ });
352
+ it('reports a null first-submission timestamp before the Initiated event indexes', () => {
353
+ const state = deriveRequestState(makeRequest());
354
+ expect(state.submissionCount).toBe(0);
355
+ expect(state.firstSubmissionTimestamp).toBeNull();
356
+ });
357
+ it('keeps "the subgraph reported nothing" distinct from a reported zero', () => {
358
+ expect(deriveRequestState(makeRequest()).acceptedAmount).toBe(0);
359
+ expect(deriveRequestState(makeRequest({ acceptedAmount: '' }))
360
+ .acceptedAmount).toBeNull();
361
+ expect(deriveRequestState(makeRequest({
362
+ acceptedAmount: undefined,
363
+ })).acceptedAmount).toBeNull();
364
+ });
365
+ });
366
+ /**
367
+ * The transition rule: `cancelled` is reachable only from a Cancelled EVENT,
368
+ * and every derivation lands on exactly one of the seven codes.
369
+ */
370
+ describe('deriveRequestState — permitted transitions', () => {
371
+ const FIXTURES = [
372
+ {},
373
+ { canCancel: false },
374
+ { status: PROCESSING, canCancel: true },
375
+ { status: PROCESSED, canCancel: false, acceptedAmount: '100' },
376
+ { status: PROCESSED, canCancel: false, rejectedAmount: '100' },
377
+ {
378
+ requestType: 'Withdrawal',
379
+ status: PROCESSING,
380
+ canCancel: true,
381
+ acceptedAmount: '60',
382
+ },
383
+ {
384
+ requestType: 'Withdrawal',
385
+ status: PROCESSED,
386
+ canCancel: false,
387
+ acceptedAmount: '60',
388
+ },
389
+ { events: [event({ requestType: 'Cancelled' })] },
390
+ ];
391
+ const CODES = [
392
+ 'pending',
393
+ 'complete',
394
+ 'partial',
395
+ 'rejected',
396
+ 'reallocated',
397
+ 'cancelled',
398
+ 'forced',
399
+ ];
400
+ it('every derivation lands on exactly one known code', () => {
401
+ for (const overrides of FIXTURES) {
402
+ expect(CODES).toContain(deriveRequestState(makeRequest(overrides)).statusCode);
403
+ }
404
+ });
405
+ it('cancelled derives ONLY from a Cancelled event', () => {
406
+ var _a;
407
+ for (const overrides of FIXTURES) {
408
+ const hasCancelEvent = ((_a = overrides.events) !== null && _a !== void 0 ? _a : []).some((e) => e.requestType === 'Cancelled');
409
+ const state = deriveRequestState(makeRequest(overrides));
410
+ expect(state.statusCode === 'cancelled').toBe(hasCancelEvent);
411
+ }
412
+ });
413
+ it('the loan-agreement affordance follows from requestType + statusCode', () => {
414
+ // kasu-ui's `canViewContract`, reconstructed from the two fields this
415
+ // layer exposes: deposits have an agreement unless nothing was ever
416
+ // issued (cancelled / fully rejected); withdrawals sign none.
417
+ const canView = (s) => s.requestType === 'Deposit' &&
418
+ s.statusCode !== 'cancelled' &&
419
+ s.statusCode !== 'rejected';
420
+ expect(canView(deriveRequestState(makeRequest()))).toBe(true);
421
+ expect(canView(deriveRequestState(makeRequest({ events: [event({ requestType: 'Cancelled' })] })))).toBe(false);
422
+ expect(canView(deriveRequestState(makeRequest({
423
+ status: PROCESSED,
424
+ canCancel: false,
425
+ rejectedAmount: '100',
426
+ })))).toBe(false);
427
+ expect(canView(deriveRequestState(makeRequest({ requestType: 'Withdrawal' })))).toBe(false);
428
+ });
429
+ });
430
+ describe('submissionEvents / countSubmissions', () => {
431
+ const events = [
432
+ event({ requestType: 'Initiated' }),
433
+ event({ requestType: 'Accepted', index: 1 }),
434
+ event({ requestType: 'Increased', index: 2 }),
435
+ event({ requestType: 'Rejected', index: 3 }),
436
+ event({ requestType: 'Cancelled', index: 4 }),
437
+ event({ requestType: 'Reallocated', index: 5 }),
438
+ event({ requestType: 'Forced', index: 6 }),
439
+ ];
440
+ it('keeps only Initiated + Increased, in input order', () => {
441
+ expect(submissionEvents(events).map((e) => e.requestType)).toEqual([
442
+ 'Initiated',
443
+ 'Increased',
444
+ ]);
445
+ });
446
+ it('counts them', () => {
447
+ expect(countSubmissions(events)).toBe(2);
448
+ expect(countSubmissions([])).toBe(0);
449
+ });
450
+ });
451
+ describe('firstSubmissionTimestamp', () => {
452
+ it('returns the earliest submission timestamp, ignoring outcome events', () => {
453
+ expect(firstSubmissionTimestamp([
454
+ event({ requestType: 'Initiated', timestamp: 300 }),
455
+ event({ requestType: 'Increased', timestamp: 200 }),
456
+ event({ requestType: 'Accepted', timestamp: 100 }),
457
+ ], 999)).toBe(200);
458
+ });
459
+ it('falls back when the bundle carries no submission yet', () => {
460
+ expect(firstSubmissionTimestamp([], 42)).toBe(42);
461
+ expect(firstSubmissionTimestamp([event({ requestType: 'Accepted', timestamp: 1 })], 42)).toBe(42);
462
+ });
463
+ });
464
+ describe('isCycleClosed', () => {
465
+ it('is the inverse of the SDK per-pool cancel signal', () => {
466
+ expect(isCycleClosed({ canCancel: true })).toBe(false);
467
+ expect(isCycleClosed({ canCancel: false })).toBe(true);
468
+ });
469
+ });
470
+ //# sourceMappingURL=requests.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.test.js","sourceRoot":"","sources":["../../src/domain/requests.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAM3E,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,aAAa,EACb,gBAAgB,GACnB,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AAEH,MAAM,UAAU,GAAG,kBAAkB,CAAC;AACtC,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;AAC/C,MAAM,OAAO,GAAG,cAAc,CAAC;AAC/B,MAAM,SAAS,GAAG,mDAAmD,CAAC;AAEtE,MAAM,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC;AAC9C,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC;AAChD,MAAM,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC;AAE9C,SAAS,WAAW,CAAC,YAAkC,EAAE;IACrD,uBACI,EAAE,EAAE,OAAO,EACX,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE;YACT,EAAE,EAAE,OAAO;YACX,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;SAC/B,EACD,WAAW,EAAE,SAAS,EACtB,SAAS,EAAE,UAAU,EACrB,WAAW,EAAE,QAAQ,EACrB,eAAe,EAAE,KAAK,EACtB,cAAc,EAAE,GAAG,EACnB,cAAc,EAAE,GAAG,EACnB,SAAS,EAAE,UAAa,EACxB,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,IAAI,EACf,MAAM,EAAE,EAAE,EACV,KAAK,EAAE,EAAE,EACT,GAAG,EAAE,GAAG,EACR,eAAe,EAAE,SAAS,IACvB,SAAS,EACd;AACN,CAAC;AAED,SAAS,KAAK,CAAC,OAAkC;IAC7C,uBACI,EAAE,EAAE,KAAK,EACT,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,GAAG,EAChB,cAAc,EAAE,GAAG,EACnB,aAAa,EAAE,GAAG,EAClB,aAAa,EAAE,GAAG,EAClB,KAAK,EAAE,CAAC,EACR,SAAS,EAAE,UAAa,EACxB,eAAe,EAAE,IAAI,EACrB,WAAW,EAAE,QAAQ,EACrB,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,GAAG,IACT,OAAO,EACZ;AACN,CAAC;AAED,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;IACjE,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC1E,MAAM,KAAK,GAAG,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACpF,MAAM,KAAK,GAAG,kBAAkB,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAChF,wEAAwE;QACxE,6BAA6B;QAC7B,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CACvD,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAC9D,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;SACxB,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC3E,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,IAAI;YACpB,cAAc,EAAE,IAAI;SACvB,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACrF,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;SACxB,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACnD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CACjE,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;YACrB,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;SAChD,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QAClF,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;YACrB,MAAM,EAAE;gBACJ,KAAK,CAAC;oBACF,WAAW,EAAE,UAAU;oBACvB,SAAS,EAAE,gBAAgB;oBAC3B,WAAW,EAAE,WAAW;oBACxB,WAAW,EAAE,KAAK;iBACrB,CAAC;aACL;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACrE,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;YACrB,MAAM,EAAE;gBACJ,KAAK,CAAC;oBACF,WAAW,EAAE,UAAU;oBACvB,SAAS,EAAE,UAAU,CAAC,WAAW,EAAE;oBACnC,WAAW,EAAE,KAAK;iBACrB,CAAC;aACL;SACJ,CAAC,CACL,CAAC;QACF,iEAAiE;QACjE,wDAAwD;QACxD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC5E,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;YACrB,MAAM,EAAE;gBACJ,KAAK,CAAC;oBACF,WAAW,EAAE,aAAa;oBAC1B,WAAW,EAAE,KAAK;iBACrB,CAAC;aACL;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QAClE,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;YACrB,MAAM,EAAE;gBACJ,KAAK,CAAC;oBACF,WAAW,EAAE,UAAU;oBACvB,SAAS,EAAE,gBAAgB;oBAC3B,WAAW,EAAE,KAAK;iBACrB,CAAC;aACL;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QACzE,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAC7C,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;SACxB,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QACxF,qEAAqE;QACrE,qEAAqE;QACrE,eAAe;QACf,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,IAAI;YACf,cAAc,EAAE,IAAI;SACvB,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QAClG,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,IAAI;SACvB,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,IAAI;SACvB,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QACxD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,IAAI;YACpB,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;SAC7C,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAC9D,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,IAAI;YACpB,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;SAC7C,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;SAChD,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAChE,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QAClE,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,eAAe,EAAE,GAAG;YACpB,MAAM,EAAE;gBACJ,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;gBACvD,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;aAChD;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QACzE,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,eAAe,EAAE,GAAG;YACpB,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;SAChD,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC7D,uEAAuE;QACvE,wDAAwD;QACxD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,eAAe,EAAE,GAAG;YACpB,MAAM,EAAE;gBACJ,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;aAC1D;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0DAA0D,EAAE,GAAG,EAAE;IACtE,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACrE,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE;gBACJ,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;gBAClD,KAAK,CAAC;oBACF,WAAW,EAAE,WAAW;oBACxB,EAAE,EAAE,SAAS;oBACb,KAAK,EAAE,CAAC;iBACX,CAAC;aACL;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC3D,MAAM,KAAK,GAAG,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACrE,wEAAwE;QACxE,oDAAoD;QACpD,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,WAAW,EAAE;gBACT,EAAE,EAAE,eAAe;gBACnB,IAAI,EAAE,qDAAqD;gBAC3D,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;aAC/B;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC5C,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,eAAe,EAAE;gBACb,QAAQ,EAAE,GAAG;gBACb,GAAG,EAAE,KAAK;gBACV,iBAAiB,EAAE,GAAG;gBACtB,iBAAiB,EAAE,OAAO;aAC7B;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QAC/E,MAAM,KAAK,GAAG,kBAAkB,CAC5B,WAAW,CAAC;YACR,MAAM,EAAE;gBACJ,KAAK,CAAC;oBACF,WAAW,EAAE,WAAW;oBACxB,SAAS,EAAE,UAAa;iBAC3B,CAAC;gBACF,KAAK,CAAC;oBACF,WAAW,EAAE,WAAW;oBACxB,SAAS,EAAE,UAAa;oBACxB,KAAK,EAAE,CAAC;iBACX,CAAC;gBACF,KAAK,CAAC;oBACF,WAAW,EAAE,UAAU;oBACvB,SAAS,EAAE,UAAa;oBACxB,KAAK,EAAE,CAAC;iBACX,CAAC;aACL;SACJ,CAAC,CACL,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,UAAa,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACpF,MAAM,KAAK,GAAG,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC3E,MAAM,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,CACF,kBAAkB,CAAC,WAAW,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC;aAClD,cAAc,CACtB,CAAC,QAAQ,EAAE,CAAC;QACb,MAAM,CACF,kBAAkB,CACd,WAAW,CAAC;YACR,cAAc,EAAE,SAA8B;SACjD,CAAC,CACL,CAAC,cAAc,CACnB,CAAC,QAAQ,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH;;;GAGG;AACH,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;IACxD,MAAM,QAAQ,GAA2B;QACrC,EAAE;QACF,EAAE,SAAS,EAAE,KAAK,EAAE;QACpB,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE;QACvC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE;QAC9D,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE;QAC9D;YACI,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,IAAI;YACf,cAAc,EAAE,IAAI;SACvB;QACD;YACI,WAAW,EAAE,YAAY;YACzB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,IAAI;SACvB;QACD,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE;KACpD,CAAC;IAEF,MAAM,KAAK,GAAG;QACV,SAAS;QACT,UAAU;QACV,SAAS;QACT,UAAU;QACV,aAAa;QACb,WAAW;QACX,QAAQ;KACX,CAAC;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QACxD,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CACnB,kBAAkB,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CACxD,CAAC;QACN,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;;QACrD,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,cAAc,GAAG,CAAC,MAAA,SAAS,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,CAChD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CACvC,CAAC;YACF,MAAM,KAAK,GAAG,kBAAkB,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClE,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC3E,sEAAsE;QACtE,oEAAoE;QACpE,8DAA8D;QAC9D,MAAM,OAAO,GAAG,CAAC,CAGhB,EAAW,EAAE,CACV,CAAC,CAAC,WAAW,KAAK,SAAS;YAC3B,CAAC,CAAC,UAAU,KAAK,WAAW;YAC5B,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC;QAEhC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,CACF,OAAO,CACH,kBAAkB,CACd,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CACjE,CACJ,CACJ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,CACF,OAAO,CACH,kBAAkB,CACd,WAAW,CAAC;YACR,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,KAAK;SACxB,CAAC,CACL,CACJ,CACJ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,CACF,OAAO,CACH,kBAAkB,CACd,WAAW,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAC7C,CACJ,CACJ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACjD,MAAM,MAAM,GAAG;QACX,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;QACnC,KAAK,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC5C,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC7C,KAAK,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC5C,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC7C,KAAK,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC/C,KAAK,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;KAC7C,CAAC;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/D,WAAW;YACX,WAAW;SACd,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;QACnB,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC1E,MAAM,CACF,wBAAwB,CACpB;YACI,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;YACnD,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;YACnD,KAAK,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;SACrD,EACD,GAAG,CACN,CACJ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,wBAAwB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClD,MAAM,CACF,wBAAwB,CACpB,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,EAClD,EAAE,CACL,CACJ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Cycles and the clearing window — the protocol's weekly clock, as numbers.
3
+ *
4
+ * Lifted verbatim from kasu-ui's `features/portfolio/lib/settlement-window.ts`
5
+ * and `features/lending/lib/cycle-dates.ts`. The two formatters that live
6
+ * beside `deriveCycleDates` there (`formatCycleDate`, `formatCycleCloseUtc`)
7
+ * print words and stay in the applications; everything here is unix seconds in
8
+ * and unix seconds out.
9
+ *
10
+ * The clearing window is the fixed 48 hours immediately preceding an epoch
11
+ * end. Inside it, pending requests are being processed and cannot be modified,
12
+ * and the countdown runs to the epoch end. Outside it, the countdown runs to
13
+ * the next clearing-window start.
14
+ *
15
+ * The epoch end comes straight from the chain (`nextEpochStartTimestamp`, i.e.
16
+ * the SDK's `getNextEpochDate`) — the same value the protocol's own
17
+ * `getNextClearingPeriodDate` derives from — so the window always lines up
18
+ * with the real weekly schedule (Tue 06:00 → Thu 06:00 UTC on Base) instead of
19
+ * a projected subgraph timestamp that can drift off the grid.
20
+ */
21
+ /**
22
+ * Clearing-window length — a fixed 48h protocol constant. Exported so every
23
+ * consumer derives the window from the same number this module runs on.
24
+ */
25
+ export declare const CLEARING_WINDOW_SECONDS: number;
26
+ export type SettlementWindowState = {
27
+ phase: 'awaiting';
28
+ secondsUntilClearing: number;
29
+ nextClearingStart: number;
30
+ } | {
31
+ phase: 'clearing';
32
+ secondsUntilEpochEnd: number;
33
+ epochEnd: number;
34
+ } | {
35
+ phase: 'unknown';
36
+ };
37
+ export interface SettlementWindowInput {
38
+ /** Now, in unix seconds. */
39
+ nowSeconds: number;
40
+ /**
41
+ * Authoritative epoch end, in unix seconds — the chain's
42
+ * `nextEpochStartTimestamp` (SDK `getNextEpochDate`). During an epoch this
43
+ * is in the future; it refetches to the next boundary once it rolls.
44
+ */
45
+ nextEpochStart: number;
46
+ /** Clearing-window length; defaults to the 48h protocol constant. */
47
+ clearingWindowSeconds?: number;
48
+ }
49
+ /**
50
+ * Which phase of the weekly cycle `nowSeconds` falls in, and how long is left
51
+ * of it.
52
+ *
53
+ * `'unknown'` when no epoch boundary has been loaded yet, or when the one on
54
+ * hand is stale (it has already elapsed — the on-chain value refetches to the
55
+ * next boundary shortly after rollover). A caller must render its "no cycle
56
+ * loaded" state there, never a zeroed countdown.
57
+ */
58
+ export declare function computeSettlementWindow({ nowSeconds, nextEpochStart, clearingWindowSeconds, }: SettlementWindowInput): SettlementWindowState;
59
+ /**
60
+ * The next cycle boundary strictly after `nowSeconds`, in unix seconds — the
61
+ * cycle close (`nextEpochStart − 48h`) while the window is still open, the
62
+ * epoch end once we are inside it.
63
+ *
64
+ * `undefined` when there is no boundary left to wait for: no epoch boundary
65
+ * loaded, or a cached one that has already elapsed — the same staleness rule
66
+ * `computeSettlementWindow` applies before it reports `'unknown'`.
67
+ *
68
+ * Split out of the state machine because some consumers need the INSTANT
69
+ * rather than the phase: one to flush the cycle-dependent caches when the
70
+ * clock crosses it, one to move a pre-commit screen's snapshot clock at the
71
+ * same moment.
72
+ */
73
+ export declare function nextCycleBoundary(nextEpochStart: number | undefined, nowSeconds: number, clearingWindowSeconds?: number): number | undefined;
74
+ export interface CycleDates {
75
+ /** Unix seconds — the next cycle close (clearing-window start). */
76
+ close: number;
77
+ /** Unix seconds — the outcome-confirmed-by boundary (close + 48h). */
78
+ outcome: number;
79
+ }
80
+ /**
81
+ * The cycle-close and outcome dates for a request submitted `now`.
82
+ *
83
+ * - The cycle "closes" (stops accepting requests, starts processing) at the
84
+ * start of the 48h clearing window, i.e. 48h before the epoch end.
85
+ * - Processing takes up to 48h, so the outcome is confirmed by the epoch end
86
+ * (close + 48h).
87
+ *
88
+ * Returns `null` when the epoch boundary is not available or is stale — a
89
+ * caller then omits the dates entirely (omit, don't stub).
90
+ *
91
+ * The common case is a request submitted OUTSIDE the clearing window: the
92
+ * close is `nextEpochStart − 48h` and the outcome is `nextEpochStart`. When
93
+ * the request lands INSIDE the current clearing window (that close is already
94
+ * in the past), it queues for the NEXT weekly cycle, so the close is advanced
95
+ * by whole weeks until it is in the future.
96
+ */
97
+ export declare function deriveCycleDates(nextEpochStart: number | undefined, nowSeconds: number): CycleDates | null;