@provex/utils 1.0.16 → 1.2.3

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 (122) hide show
  1. package/dist/src/chain.d.ts +436 -4
  2. package/dist/src/chain.js +80 -0
  3. package/dist/src/chain.test.d.ts +1 -0
  4. package/dist/src/chain.test.js +112 -0
  5. package/dist/src/contracts.d.ts +196 -20
  6. package/dist/src/contracts.js +245 -17
  7. package/dist/src/contracts.test.d.ts +1 -0
  8. package/dist/src/contracts.test.js +243 -0
  9. package/dist/src/conversionRates.d.ts +99 -8
  10. package/dist/src/conversionRates.js +74 -4
  11. package/dist/src/conversionRates.test.d.ts +1 -0
  12. package/dist/src/conversionRates.test.js +473 -0
  13. package/dist/src/currencies.d.ts +113 -9
  14. package/dist/src/currencies.js +119 -38
  15. package/dist/src/currencies.test.d.ts +1 -0
  16. package/dist/src/currencies.test.js +343 -0
  17. package/dist/src/data/countries.json +166 -166
  18. package/dist/src/deposit.d.ts +69 -1
  19. package/dist/src/deposit.js +52 -1
  20. package/dist/src/depositKeys.d.ts +154 -0
  21. package/dist/src/depositKeys.js +104 -0
  22. package/dist/src/depositKeys.test.d.ts +1 -0
  23. package/dist/src/depositKeys.test.js +231 -0
  24. package/dist/src/endpoints.d.ts +51 -0
  25. package/dist/src/endpoints.js +70 -0
  26. package/dist/src/endpoints.test.d.ts +1 -0
  27. package/dist/src/endpoints.test.js +54 -0
  28. package/dist/src/events.d.ts +40 -2
  29. package/dist/src/events.js +86 -10
  30. package/dist/src/events.test.d.ts +1 -0
  31. package/dist/src/events.test.js +111 -0
  32. package/dist/src/fees.d.ts +136 -0
  33. package/dist/src/fees.js +178 -0
  34. package/dist/src/fees.test.d.ts +1 -0
  35. package/dist/src/fees.test.js +165 -0
  36. package/dist/src/ids.d.ts +125 -22
  37. package/dist/src/ids.js +211 -61
  38. package/dist/src/ids.test.d.ts +1 -0
  39. package/dist/src/ids.test.js +607 -0
  40. package/dist/src/index.d.ts +30 -1
  41. package/dist/src/index.js +30 -1
  42. package/dist/src/input.d.ts +23 -4
  43. package/dist/src/input.js +23 -4
  44. package/dist/src/intent.d.ts +38 -2
  45. package/dist/src/intent.js +28 -1
  46. package/dist/src/intent.test.d.ts +1 -0
  47. package/dist/src/intent.test.js +119 -0
  48. package/dist/src/json.d.ts +38 -1
  49. package/dist/src/json.js +38 -2
  50. package/dist/src/normalization.d.ts +224 -0
  51. package/dist/src/normalization.js +119 -0
  52. package/dist/src/normalization.test.d.ts +1 -0
  53. package/dist/src/normalization.test.js +284 -0
  54. package/dist/src/participants.d.ts +19 -4
  55. package/dist/src/participants.js +19 -4
  56. package/dist/src/payment.d.ts +333 -16
  57. package/dist/src/payment.js +768 -58
  58. package/dist/src/payment.test.d.ts +1 -0
  59. package/dist/src/payment.test.js +272 -0
  60. package/dist/src/peer-types.d.ts +327 -0
  61. package/dist/src/peer-types.js +169 -0
  62. package/dist/src/profit.d.ts +26 -5
  63. package/dist/src/profit.js +31 -8
  64. package/dist/src/profit.test.d.ts +1 -0
  65. package/dist/src/profit.test.js +315 -0
  66. package/dist/src/reputation.d.ts +125 -0
  67. package/dist/src/reputation.js +188 -0
  68. package/dist/src/reputation.test.d.ts +1 -0
  69. package/dist/src/reputation.test.js +156 -0
  70. package/dist/src/sort.d.ts +49 -10
  71. package/dist/src/sort.js +40 -9
  72. package/dist/src/sort.test.d.ts +1 -0
  73. package/dist/src/sort.test.js +216 -0
  74. package/dist/src/stateKey.d.ts +35 -0
  75. package/dist/src/stateKey.js +36 -0
  76. package/dist/src/stats.d.ts +55 -1
  77. package/dist/src/stats.js +46 -1
  78. package/dist/src/stats.test.d.ts +1 -0
  79. package/dist/src/stats.test.js +104 -0
  80. package/dist/src/time.d.ts +59 -9
  81. package/dist/src/time.js +71 -15
  82. package/dist/src/time.test.d.ts +1 -0
  83. package/dist/src/time.test.js +231 -0
  84. package/dist/src/tokens.d.ts +11972 -145
  85. package/dist/src/tokens.js +98 -17
  86. package/dist/src/tokens.test.d.ts +1 -0
  87. package/dist/src/tokens.test.js +193 -0
  88. package/dist/src/units.d.ts +183 -0
  89. package/dist/src/units.js +206 -6
  90. package/dist/src/units.test.d.ts +1 -0
  91. package/dist/src/units.test.js +327 -0
  92. package/dist/src/zkp2p-types.d.ts +273 -4
  93. package/dist/src/zkp2p-types.js +169 -1
  94. package/dist/tsconfig.tsbuildinfo +1 -1
  95. package/package.json +116 -26
  96. package/scripts/convert-svg.ts +0 -22
  97. package/src/chain.ts +0 -27
  98. package/src/contracts.ts +0 -89
  99. package/src/conversionRates.ts +0 -356
  100. package/src/currencies.ts +0 -286
  101. package/src/data/countries.json +0 -1099
  102. package/src/deposit.ts +0 -2
  103. package/src/events.ts +0 -21
  104. package/src/flags/eur.svg +0 -4
  105. package/src/flags/usd.svg +0 -25
  106. package/src/flags.ts +0 -4
  107. package/src/global.d.ts +0 -9
  108. package/src/ids.ts +0 -137
  109. package/src/index.ts +0 -16
  110. package/src/input.ts +0 -35
  111. package/src/intent.ts +0 -15
  112. package/src/json.ts +0 -42
  113. package/src/participants.ts +0 -14
  114. package/src/payment.ts +0 -573
  115. package/src/profit.ts +0 -55
  116. package/src/sort.ts +0 -49
  117. package/src/stats.ts +0 -10
  118. package/src/time.ts +0 -123
  119. package/src/tokens.ts +0 -159
  120. package/src/units.ts +0 -120
  121. package/src/zkp2p-types.ts +0 -55
  122. package/tsconfig.json +0 -18
@@ -0,0 +1,216 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { orderedSort, orderedSortThenById } from './sort.js';
4
+ describe('sort', () => {
5
+ describe('orderedSort', () => {
6
+ describe('with numbers', () => {
7
+ it('should sort ascending', () => {
8
+ assert.equal(orderedSort(1, 2, 'asc'), -1);
9
+ assert.equal(orderedSort(2, 1, 'asc'), 1);
10
+ assert.equal(orderedSort(1, 1, 'asc'), 0);
11
+ });
12
+ it('should sort descending', () => {
13
+ assert.ok(orderedSort(1, 2, 'desc') > 0);
14
+ assert.ok(orderedSort(2, 1, 'desc') < 0);
15
+ // Use loose equality to handle -0 === 0 case
16
+ assert.ok(orderedSort(1, 1, 'desc') == 0);
17
+ });
18
+ it('should handle negative numbers', () => {
19
+ assert.equal(orderedSort(-5, -3, 'asc'), -2);
20
+ assert.equal(orderedSort(-3, -5, 'asc'), 2);
21
+ assert.equal(orderedSort(-5, 5, 'asc'), -10);
22
+ });
23
+ it('should handle zero', () => {
24
+ assert.equal(orderedSort(0, 1, 'asc'), -1);
25
+ assert.equal(orderedSort(1, 0, 'asc'), 1);
26
+ assert.equal(orderedSort(0, 0, 'asc'), 0);
27
+ });
28
+ it('should handle decimals', () => {
29
+ assert.ok(orderedSort(1.5, 2.5, 'asc') < 0);
30
+ assert.ok(orderedSort(2.5, 1.5, 'asc') > 0);
31
+ assert.equal(orderedSort(1.5, 1.5, 'asc'), 0);
32
+ });
33
+ });
34
+ describe('with strings', () => {
35
+ it('should sort ascending', () => {
36
+ assert.ok(orderedSort('a', 'b', 'asc') < 0);
37
+ assert.ok(orderedSort('b', 'a', 'asc') > 0);
38
+ assert.equal(orderedSort('a', 'a', 'asc'), 0);
39
+ });
40
+ it('should sort descending', () => {
41
+ const result1 = orderedSort('a', 'b', 'desc');
42
+ const result2 = orderedSort('b', 'a', 'desc');
43
+ assert.ok(result1 > 0, `Expected positive, got ${result1}`);
44
+ assert.ok(result2 < 0, `Expected negative, got ${result2}`);
45
+ // Use loose equality to handle -0 === 0 case
46
+ assert.ok(orderedSort('a', 'a', 'desc') == 0);
47
+ });
48
+ it('should handle case-sensitive sorting', () => {
49
+ const result1 = orderedSort('A', 'a', 'asc');
50
+ const result2 = orderedSort('a', 'A', 'asc');
51
+ // localeCompare is case-sensitive
52
+ assert.notEqual(result1, 0, `'A' and 'a' should not be equal`);
53
+ assert.notEqual(result2, 0, `'a' and 'A' should not be equal`);
54
+ // They should sort opposite to each other
55
+ assert.ok((result1 < 0 && result2 > 0) || (result1 > 0 && result2 < 0));
56
+ });
57
+ it('should handle empty strings', () => {
58
+ assert.ok(orderedSort('', 'a', 'asc') < 0);
59
+ assert.ok(orderedSort('a', '', 'asc') > 0);
60
+ assert.equal(orderedSort('', '', 'asc'), 0);
61
+ });
62
+ it('should sort multi-character strings', () => {
63
+ assert.ok(orderedSort('apple', 'banana', 'asc') < 0);
64
+ assert.ok(orderedSort('banana', 'apple', 'asc') > 0);
65
+ assert.equal(orderedSort('apple', 'apple', 'asc'), 0);
66
+ });
67
+ });
68
+ describe('with bigints', () => {
69
+ it('should sort ascending', () => {
70
+ assert.equal(orderedSort(1n, 2n, 'asc'), -1);
71
+ assert.equal(orderedSort(2n, 1n, 'asc'), 1);
72
+ assert.equal(orderedSort(1n, 1n, 'asc'), 0);
73
+ });
74
+ it('should sort descending', () => {
75
+ assert.ok(orderedSort(1n, 2n, 'desc') > 0);
76
+ assert.ok(orderedSort(2n, 1n, 'desc') < 0);
77
+ // Use loose equality to handle -0 === 0 case
78
+ assert.ok(orderedSort(1n, 1n, 'desc') == 0);
79
+ });
80
+ it('should handle large bigints', () => {
81
+ const large1 = 999999999999999999n;
82
+ const large2 = 1000000000000000000n;
83
+ assert.equal(orderedSort(large1, large2, 'asc'), -1);
84
+ assert.equal(orderedSort(large2, large1, 'asc'), 1);
85
+ });
86
+ it('should handle negative bigints', () => {
87
+ assert.equal(orderedSort(-5n, -3n, 'asc'), -1);
88
+ assert.equal(orderedSort(-3n, -5n, 'asc'), 1);
89
+ assert.equal(orderedSort(-5n, 5n, 'asc'), -1);
90
+ });
91
+ it('should handle zero', () => {
92
+ assert.equal(orderedSort(0n, 1n, 'asc'), -1);
93
+ assert.equal(orderedSort(1n, 0n, 'asc'), 1);
94
+ assert.equal(orderedSort(0n, 0n, 'asc'), 0);
95
+ });
96
+ });
97
+ describe('with mixed types (fallback to string comparison)', () => {
98
+ it('should convert to strings and compare ascending', () => {
99
+ // number vs string - should use string comparison
100
+ const result = orderedSort(123, 'abc', 'asc');
101
+ assert.ok(typeof result === 'number');
102
+ });
103
+ it('should convert to strings and compare descending', () => {
104
+ const result = orderedSort(123, 'abc', 'desc');
105
+ assert.ok(typeof result === 'number');
106
+ });
107
+ it('should handle equal mixed types', () => {
108
+ // When converted to strings, '123' should equal '123'
109
+ const result = orderedSort('123', 123, 'asc');
110
+ assert.equal(result, 0);
111
+ });
112
+ });
113
+ });
114
+ describe('orderedSortThenById', () => {
115
+ const createMockDeposit = (depositId, timestamp) => ({
116
+ depositId,
117
+ transaction: {
118
+ block: {
119
+ timestamp,
120
+ },
121
+ },
122
+ });
123
+ it('should sort by value first', () => {
124
+ const a = createMockDeposit(1n, 1000n);
125
+ const b = createMockDeposit(2n, 1000n);
126
+ const result = orderedSortThenById({
127
+ aVal: 100,
128
+ bVal: 200,
129
+ orderDirection: 'asc',
130
+ a,
131
+ b,
132
+ });
133
+ assert.ok(result < 0); // a comes before b
134
+ });
135
+ it('should use timestamp as tiebreaker', () => {
136
+ const a = createMockDeposit(1n, 1000n);
137
+ const b = createMockDeposit(2n, 2000n);
138
+ const result = orderedSortThenById({
139
+ aVal: 100,
140
+ bVal: 100, // Same value
141
+ orderDirection: 'asc',
142
+ a,
143
+ b,
144
+ });
145
+ assert.ok(result < 0); // a has earlier timestamp
146
+ });
147
+ it('should use depositId as final tiebreaker', () => {
148
+ const a = createMockDeposit(1n, 1000n);
149
+ const b = createMockDeposit(2n, 1000n);
150
+ const result = orderedSortThenById({
151
+ aVal: 100,
152
+ bVal: 100, // Same value
153
+ orderDirection: 'asc',
154
+ a, // Same timestamp
155
+ b,
156
+ });
157
+ assert.ok(result < 0); // a has smaller depositId
158
+ });
159
+ it('should return 0 for identical entries', () => {
160
+ const a = createMockDeposit(1n, 1000n);
161
+ const b = createMockDeposit(1n, 1000n);
162
+ const result = orderedSortThenById({
163
+ aVal: 100,
164
+ bVal: 100,
165
+ orderDirection: 'asc',
166
+ a,
167
+ b,
168
+ });
169
+ assert.equal(result, 0);
170
+ });
171
+ it('should respect order direction for primary sort', () => {
172
+ const a = createMockDeposit(1n, 1000n);
173
+ const b = createMockDeposit(2n, 1000n);
174
+ const resultAsc = orderedSortThenById({
175
+ aVal: 100,
176
+ bVal: 200,
177
+ orderDirection: 'asc',
178
+ a,
179
+ b,
180
+ });
181
+ const resultDesc = orderedSortThenById({
182
+ aVal: 100,
183
+ bVal: 200,
184
+ orderDirection: 'desc',
185
+ a,
186
+ b,
187
+ });
188
+ assert.ok(resultAsc < 0);
189
+ assert.ok(resultDesc > 0);
190
+ });
191
+ it('should handle bigint values', () => {
192
+ const a = createMockDeposit(1n, 1000n);
193
+ const b = createMockDeposit(2n, 1000n);
194
+ const result = orderedSortThenById({
195
+ aVal: 100n,
196
+ bVal: 200n,
197
+ orderDirection: 'asc',
198
+ a,
199
+ b,
200
+ });
201
+ assert.ok(result < 0);
202
+ });
203
+ it('should handle string values', () => {
204
+ const a = createMockDeposit(1n, 1000n);
205
+ const b = createMockDeposit(2n, 1000n);
206
+ const result = orderedSortThenById({
207
+ aVal: 'alpha',
208
+ bVal: 'beta',
209
+ orderDirection: 'asc',
210
+ a,
211
+ b,
212
+ });
213
+ assert.ok(result < 0);
214
+ });
215
+ });
216
+ });
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @fileoverview State key constants for the indexer's contractStateLink table.
3
+ *
4
+ * The contractStateLink table tracks the current value of various contract
5
+ * configuration parameters. State keys identify which parameter is being tracked.
6
+ *
7
+ * @see {@link indexer} for how these are used in event handlers
8
+ */
9
+ /**
10
+ * State keys for contract configuration tracking.
11
+ * Each key corresponds to a different contract parameter that can change over time.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Used in indexer to track current dust threshold
16
+ * await updateContractState({
17
+ * stateKey: stateKey.dustThreshold,
18
+ * value: event.args.newThreshold,
19
+ * ...
20
+ * })
21
+ * ```
22
+ */
23
+ export declare const stateKey: {
24
+ readonly dustRecipient: "dustRecipient";
25
+ readonly dustThreshold: "dustThreshold";
26
+ readonly protocolFee: "protocolFee";
27
+ readonly protocolFeeRecipient: "protocolFeeRecipient";
28
+ };
29
+ export type StateKey = (typeof stateKey)[keyof typeof stateKey];
30
+ /**
31
+ * Type guard to check if a string is a valid state key.
32
+ * @param key - The string to check
33
+ * @returns True if the key is a valid StateKey
34
+ */
35
+ export declare const isStateKey: (key: string) => key is StateKey;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview State key constants for the indexer's contractStateLink table.
3
+ *
4
+ * The contractStateLink table tracks the current value of various contract
5
+ * configuration parameters. State keys identify which parameter is being tracked.
6
+ *
7
+ * @see {@link indexer} for how these are used in event handlers
8
+ */
9
+ /**
10
+ * State keys for contract configuration tracking.
11
+ * Each key corresponds to a different contract parameter that can change over time.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Used in indexer to track current dust threshold
16
+ * await updateContractState({
17
+ * stateKey: stateKey.dustThreshold,
18
+ * value: event.args.newThreshold,
19
+ * ...
20
+ * })
21
+ * ```
22
+ */
23
+ export const stateKey = {
24
+ dustRecipient: 'dustRecipient',
25
+ dustThreshold: 'dustThreshold',
26
+ protocolFee: 'protocolFee',
27
+ protocolFeeRecipient: 'protocolFeeRecipient',
28
+ };
29
+ /**
30
+ * Type guard to check if a string is a valid state key.
31
+ * @param key - The string to check
32
+ * @returns True if the key is a valid StateKey
33
+ */
34
+ export const isStateKey = (key) => {
35
+ return key in stateKey;
36
+ };
@@ -1,7 +1,61 @@
1
+ /**
2
+ * @fileoverview Statistical event type definitions for the indexer.
3
+ *
4
+ * These event types categorize different liquidity movements for
5
+ * aggregated statistics (hourly, daily, monthly summaries).
6
+ *
7
+ * @see {@link ids} for stat ID generation
8
+ */
9
+ /**
10
+ * Types of statistical events tracked by the indexer.
11
+ * Each event type represents a different category of liquidity movement.
12
+ *
13
+ * - `deposit`: Funds added to a deposit
14
+ * - `withdrawal`: Funds removed from a deposit
15
+ * - `exchange`: Intent fulfilled, funds exchanged
16
+ * - `fee`: Protocol fees collected
17
+ * - `dust`: Dust amounts collected
18
+ */
19
+ export declare const statEvent: {
20
+ readonly deposit: "deposit";
21
+ readonly withdrawal: "withdrawal";
22
+ readonly exchange: "exchange";
23
+ readonly fee: "fee";
24
+ readonly dust: "dust";
25
+ readonly intentSignaled: "intent-signaled";
26
+ readonly intentFulfilled: "intent-fulfilled";
27
+ readonly intentCancelled: "intent-cancelled";
28
+ readonly intentExpired: "intent-expired";
29
+ readonly fillTime: "fill-time";
30
+ };
31
+ /**
32
+ * Union type of all valid stat event types.
33
+ */
34
+ export type StatEvent = (typeof statEvent)[keyof typeof statEvent];
35
+ /**
36
+ * Type guard to check if a string is a valid stat event type.
37
+ */
38
+ export declare const isStatEvent: (event: string) => event is StatEvent;
39
+ /**
40
+ * Stat actions represent different types of liquidity movements.
41
+ * Alias for statEvent to maintain consistency with usage patterns.
42
+ */
1
43
  export declare const statAction: {
2
44
  readonly deposit: "deposit";
3
45
  readonly withdrawal: "withdrawal";
4
46
  readonly exchange: "exchange";
47
+ readonly fee: "fee";
48
+ readonly dust: "dust";
49
+ readonly intentSignaled: "intent-signaled";
50
+ readonly intentFulfilled: "intent-fulfilled";
51
+ readonly intentCancelled: "intent-cancelled";
52
+ readonly intentExpired: "intent-expired";
53
+ readonly fillTime: "fill-time";
5
54
  };
6
- export type StatAction = (typeof statAction)[keyof typeof statAction];
55
+ export type StatAction = StatEvent;
56
+ /**
57
+ * Type guard to check if a string is a valid stat action.
58
+ * @param action - The string to check
59
+ * @returns True if the action is a valid StatAction
60
+ */
7
61
  export declare const isStatAction: (action: string) => action is StatAction;
package/dist/src/stats.js CHANGED
@@ -1,8 +1,53 @@
1
- export const statAction = {
1
+ /**
2
+ * @fileoverview Statistical event type definitions for the indexer.
3
+ *
4
+ * These event types categorize different liquidity movements for
5
+ * aggregated statistics (hourly, daily, monthly summaries).
6
+ *
7
+ * @see {@link ids} for stat ID generation
8
+ */
9
+ /**
10
+ * Types of statistical events tracked by the indexer.
11
+ * Each event type represents a different category of liquidity movement.
12
+ *
13
+ * - `deposit`: Funds added to a deposit
14
+ * - `withdrawal`: Funds removed from a deposit
15
+ * - `exchange`: Intent fulfilled, funds exchanged
16
+ * - `fee`: Protocol fees collected
17
+ * - `dust`: Dust amounts collected
18
+ */
19
+ export const statEvent = {
2
20
  deposit: 'deposit',
3
21
  withdrawal: 'withdrawal',
4
22
  exchange: 'exchange',
23
+ fee: 'fee',
24
+ dust: 'dust',
25
+ // Intent lifecycle stats — one row per intent, bucketed by day/hour/month.
26
+ // Eliminates the need to paginate raw intentSignaled/intentFulfilled tables for KPIs.
27
+ intentSignaled: 'intent-signaled',
28
+ intentFulfilled: 'intent-fulfilled',
29
+ intentCancelled: 'intent-cancelled',
30
+ intentExpired: 'intent-expired',
31
+ // Fill time: amount = fillTimeSeconds. Individual data points (not accumulated)
32
+ // so median/percentile can be computed per time bucket.
33
+ fillTime: 'fill-time',
5
34
  };
35
+ /**
36
+ * Type guard to check if a string is a valid stat event type.
37
+ */
38
+ export const isStatEvent = (event) => {
39
+ return event in statEvent;
40
+ };
41
+ /**
42
+ * Stat actions represent different types of liquidity movements.
43
+ * Alias for statEvent to maintain consistency with usage patterns.
44
+ */
45
+ export const statAction = statEvent;
46
+ /**
47
+ * Type guard to check if a string is a valid stat action.
48
+ * @param action - The string to check
49
+ * @returns True if the action is a valid StatAction
50
+ */
6
51
  export const isStatAction = (action) => {
7
52
  return action in statAction;
8
53
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,104 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { statEvent, isStatEvent, statAction, isStatAction, } from './stats.js';
4
+ describe('stats', () => {
5
+ describe('statEvent', () => {
6
+ it('should define deposit event', () => {
7
+ assert.equal(statEvent.deposit, 'deposit');
8
+ });
9
+ it('should define withdrawal event', () => {
10
+ assert.equal(statEvent.withdrawal, 'withdrawal');
11
+ });
12
+ it('should define exchange event', () => {
13
+ assert.equal(statEvent.exchange, 'exchange');
14
+ });
15
+ it('should define fee event', () => {
16
+ assert.equal(statEvent.fee, 'fee');
17
+ });
18
+ it('should define dust event', () => {
19
+ assert.equal(statEvent.dust, 'dust');
20
+ });
21
+ it('should have exactly 5 event types', () => {
22
+ const eventCount = Object.keys(statEvent).length;
23
+ assert.equal(eventCount, 5);
24
+ });
25
+ });
26
+ describe('isStatEvent', () => {
27
+ it('should return true for valid stat events', () => {
28
+ assert.equal(isStatEvent('deposit'), true);
29
+ assert.equal(isStatEvent('withdrawal'), true);
30
+ assert.equal(isStatEvent('exchange'), true);
31
+ assert.equal(isStatEvent('fee'), true);
32
+ assert.equal(isStatEvent('dust'), true);
33
+ });
34
+ it('should return false for invalid stat events', () => {
35
+ assert.equal(isStatEvent('invalid'), false);
36
+ assert.equal(isStatEvent(''), false);
37
+ assert.equal(isStatEvent('DEPOSIT'), false); // case-sensitive
38
+ assert.equal(isStatEvent('transfer'), false);
39
+ });
40
+ it('should work as a type guard', () => {
41
+ const event = 'deposit';
42
+ if (isStatEvent(event)) {
43
+ // TypeScript should narrow the type here
44
+ const typedEvent = event;
45
+ assert.equal(typedEvent, 'deposit');
46
+ }
47
+ else {
48
+ assert.fail('Expected deposit to be a valid stat event');
49
+ }
50
+ });
51
+ });
52
+ describe('statAction', () => {
53
+ it('should be an alias for statEvent', () => {
54
+ assert.deepEqual(statAction, statEvent);
55
+ });
56
+ it('should have the same keys as statEvent', () => {
57
+ const eventKeys = Object.keys(statEvent).sort();
58
+ const actionKeys = Object.keys(statAction).sort();
59
+ assert.deepEqual(eventKeys, actionKeys);
60
+ });
61
+ });
62
+ describe('isStatAction', () => {
63
+ it('should return true for valid stat actions', () => {
64
+ assert.equal(isStatAction('deposit'), true);
65
+ assert.equal(isStatAction('withdrawal'), true);
66
+ assert.equal(isStatAction('exchange'), true);
67
+ assert.equal(isStatAction('fee'), true);
68
+ assert.equal(isStatAction('dust'), true);
69
+ });
70
+ it('should return false for invalid stat actions', () => {
71
+ assert.equal(isStatAction('invalid'), false);
72
+ assert.equal(isStatAction(''), false);
73
+ assert.equal(isStatAction('WITHDRAWAL'), false); // case-sensitive
74
+ });
75
+ it('should work as a type guard', () => {
76
+ const action = 'exchange';
77
+ if (isStatAction(action)) {
78
+ // TypeScript should narrow the type here
79
+ const typedAction = action;
80
+ assert.equal(typedAction, 'exchange');
81
+ }
82
+ else {
83
+ assert.fail('Expected exchange to be a valid stat action');
84
+ }
85
+ });
86
+ });
87
+ describe('type consistency', () => {
88
+ it('StatEvent and StatAction should be assignable to each other', () => {
89
+ const event = 'deposit';
90
+ const action = event; // Should compile
91
+ assert.equal(event, action);
92
+ });
93
+ it('all statEvent values should be valid StatEvent types', () => {
94
+ for (const [key, value] of Object.entries(statEvent)) {
95
+ assert.ok(isStatEvent(value), `${key} should be a valid StatEvent`);
96
+ }
97
+ });
98
+ it('all statAction values should be valid StatAction types', () => {
99
+ for (const [key, value] of Object.entries(statAction)) {
100
+ assert.ok(isStatAction(value), `${key} should be a valid StatAction`);
101
+ }
102
+ });
103
+ });
104
+ });
@@ -1,4 +1,18 @@
1
- /** Interval in milliseconds */
1
+ /**
2
+ * @fileoverview Time and date utilities for formatting and calculations.
3
+ *
4
+ * Provides:
5
+ * - Interval constants in milliseconds for time calculations
6
+ * - Human-readable relative time formatting ("5m ago", "2d 3h ago")
7
+ * - Duration formatting for time ranges
8
+ * - Absolute timestamp formatting
9
+ *
10
+ * @see {@link units} for blockchain timestamp conversion
11
+ */
12
+ /**
13
+ * Time unit relationships for manual calculations.
14
+ * Use these when building complex time expressions.
15
+ */
2
16
  export declare const intervalIn: {
3
17
  readonly yearInDays: 365;
4
18
  readonly quarterInMonths: 3;
@@ -9,7 +23,19 @@ export declare const intervalIn: {
9
23
  readonly secondInMinutes: 60;
10
24
  readonly millisecondInSecond: 1000;
11
25
  };
12
- /** Intervals in milliseconds */
26
+ /**
27
+ * Common time intervals in milliseconds.
28
+ * Use for timeout calculations, polling intervals, and date math.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * // Set a 5 minute timeout
33
+ * setTimeout(callback, 5 * interval.minute)
34
+ *
35
+ * // Calculate time 1 day ago
36
+ * const yesterday = Date.now() - interval.day
37
+ * ```
38
+ */
13
39
  export declare const interval: {
14
40
  readonly second: 1000;
15
41
  readonly minute: number;
@@ -18,20 +44,33 @@ export declare const interval: {
18
44
  readonly month: number;
19
45
  readonly year: number;
20
46
  };
21
- /** Default display intervals */
47
+ /**
48
+ * Default number of time units to display in statistics/charts.
49
+ * Used for "show last N hours/days/months" UI controls.
50
+ */
22
51
  export declare const defaultDisplayInterval: {
23
52
  readonly hour: number;
24
53
  readonly day: number;
25
54
  readonly month: 60;
26
55
  };
27
56
  /**
28
- * Format a timestamp
29
- * @param timestamp - The timestamp to format
30
- * @param param1.anchor - The anchor date
31
- * @param param1.showSeconds - Whether to show seconds
32
- * @returns The formatted timestamp
57
+ * Format a timestamp as a human-readable relative time string.
58
+ * Produces compact strings like "5m ago", "2h 30m ago", "3d ago".
59
+ *
60
+ * @param timestamp - The timestamp to format (Date, number in ms, or date string)
61
+ * @param options - Optional configuration
62
+ * @param options.anchor - Reference date for "ago" calculation (default: now)
63
+ * @param options.showSeconds - Whether to show seconds for very recent times
64
+ * @returns Human-readable relative time string
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * formatTimestamp(Date.now() - 5 * 60 * 1000) // "5m ago"
69
+ * formatTimestamp(Date.now() - 2.5 * 60 * 60 * 1000) // "2h 30m ago"
70
+ * formatTimestamp(Date.now() - 3 * 24 * 60 * 60 * 1000) // "3d 0h ago"
71
+ * ```
33
72
  */
34
- export declare const formatTimestamp: (timestamp: number | Date | string, { anchor, showSeconds, }?: {
73
+ export declare const formatTimestamp: (timestamp: number | Date | string, options?: {
35
74
  anchor?: Date;
36
75
  showSeconds?: boolean;
37
76
  }) => string;
@@ -45,10 +84,21 @@ export declare const formatDuration: ({ start, until, }?: {
45
84
  start?: Date;
46
85
  until?: Date;
47
86
  }) => string;
87
+ /**
88
+ * Format an absolute timestamp to a human-readable string
89
+ * @param timestamp - Unix timestamp in seconds or milliseconds (auto-detected)
90
+ * @param options - Intl.DateTimeFormatOptions for formatting
91
+ * @returns Formatted absolute timestamp string
92
+ */
93
+ export declare const formatAbsoluteTimestamp: (timestamp: number | bigint, options?: Intl.DateTimeFormatOptions) => string;
48
94
  /**
49
95
  * Sleep for a given number of milliseconds
50
96
  * @param ms - The number of milliseconds to sleep
51
97
  * @returns A promise that resolves after the given number of milliseconds
52
98
  */
53
99
  export declare const sleep: (ms: number) => Promise<unknown>;
100
+ /**
101
+ * Time resolution keys for aggregated statistics.
102
+ * Used by the indexer to bucket events by time period.
103
+ */
54
104
  export type TimeResolutionKey = "hour" | "day" | "month";