@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.
- package/dist/src/chain.d.ts +436 -4
- package/dist/src/chain.js +80 -0
- package/dist/src/chain.test.d.ts +1 -0
- package/dist/src/chain.test.js +112 -0
- package/dist/src/contracts.d.ts +196 -20
- package/dist/src/contracts.js +245 -17
- package/dist/src/contracts.test.d.ts +1 -0
- package/dist/src/contracts.test.js +243 -0
- package/dist/src/conversionRates.d.ts +99 -8
- package/dist/src/conversionRates.js +74 -4
- package/dist/src/conversionRates.test.d.ts +1 -0
- package/dist/src/conversionRates.test.js +473 -0
- package/dist/src/currencies.d.ts +113 -9
- package/dist/src/currencies.js +119 -38
- package/dist/src/currencies.test.d.ts +1 -0
- package/dist/src/currencies.test.js +343 -0
- package/dist/src/data/countries.json +166 -166
- package/dist/src/deposit.d.ts +69 -1
- package/dist/src/deposit.js +52 -1
- package/dist/src/depositKeys.d.ts +154 -0
- package/dist/src/depositKeys.js +104 -0
- package/dist/src/depositKeys.test.d.ts +1 -0
- package/dist/src/depositKeys.test.js +231 -0
- package/dist/src/endpoints.d.ts +51 -0
- package/dist/src/endpoints.js +70 -0
- package/dist/src/endpoints.test.d.ts +1 -0
- package/dist/src/endpoints.test.js +54 -0
- package/dist/src/events.d.ts +40 -2
- package/dist/src/events.js +86 -10
- package/dist/src/events.test.d.ts +1 -0
- package/dist/src/events.test.js +111 -0
- package/dist/src/fees.d.ts +136 -0
- package/dist/src/fees.js +178 -0
- package/dist/src/fees.test.d.ts +1 -0
- package/dist/src/fees.test.js +165 -0
- package/dist/src/ids.d.ts +125 -22
- package/dist/src/ids.js +211 -61
- package/dist/src/ids.test.d.ts +1 -0
- package/dist/src/ids.test.js +607 -0
- package/dist/src/index.d.ts +30 -1
- package/dist/src/index.js +30 -1
- package/dist/src/input.d.ts +23 -4
- package/dist/src/input.js +23 -4
- package/dist/src/intent.d.ts +38 -2
- package/dist/src/intent.js +28 -1
- package/dist/src/intent.test.d.ts +1 -0
- package/dist/src/intent.test.js +119 -0
- package/dist/src/json.d.ts +38 -1
- package/dist/src/json.js +38 -2
- package/dist/src/normalization.d.ts +224 -0
- package/dist/src/normalization.js +119 -0
- package/dist/src/normalization.test.d.ts +1 -0
- package/dist/src/normalization.test.js +284 -0
- package/dist/src/participants.d.ts +19 -4
- package/dist/src/participants.js +19 -4
- package/dist/src/payment.d.ts +333 -16
- package/dist/src/payment.js +768 -58
- package/dist/src/payment.test.d.ts +1 -0
- package/dist/src/payment.test.js +272 -0
- package/dist/src/peer-types.d.ts +327 -0
- package/dist/src/peer-types.js +169 -0
- package/dist/src/profit.d.ts +26 -5
- package/dist/src/profit.js +31 -8
- package/dist/src/profit.test.d.ts +1 -0
- package/dist/src/profit.test.js +315 -0
- package/dist/src/reputation.d.ts +125 -0
- package/dist/src/reputation.js +188 -0
- package/dist/src/reputation.test.d.ts +1 -0
- package/dist/src/reputation.test.js +156 -0
- package/dist/src/sort.d.ts +49 -10
- package/dist/src/sort.js +40 -9
- package/dist/src/sort.test.d.ts +1 -0
- package/dist/src/sort.test.js +216 -0
- package/dist/src/stateKey.d.ts +35 -0
- package/dist/src/stateKey.js +36 -0
- package/dist/src/stats.d.ts +55 -1
- package/dist/src/stats.js +46 -1
- package/dist/src/stats.test.d.ts +1 -0
- package/dist/src/stats.test.js +104 -0
- package/dist/src/time.d.ts +59 -9
- package/dist/src/time.js +71 -15
- package/dist/src/time.test.d.ts +1 -0
- package/dist/src/time.test.js +231 -0
- package/dist/src/tokens.d.ts +11972 -145
- package/dist/src/tokens.js +98 -17
- package/dist/src/tokens.test.d.ts +1 -0
- package/dist/src/tokens.test.js +193 -0
- package/dist/src/units.d.ts +183 -0
- package/dist/src/units.js +206 -6
- package/dist/src/units.test.d.ts +1 -0
- package/dist/src/units.test.js +327 -0
- package/dist/src/zkp2p-types.d.ts +273 -4
- package/dist/src/zkp2p-types.js +169 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +116 -26
- package/scripts/convert-svg.ts +0 -22
- package/src/chain.ts +0 -27
- package/src/contracts.ts +0 -89
- package/src/conversionRates.ts +0 -356
- package/src/currencies.ts +0 -286
- package/src/data/countries.json +0 -1099
- package/src/deposit.ts +0 -2
- package/src/events.ts +0 -21
- package/src/flags/eur.svg +0 -4
- package/src/flags/usd.svg +0 -25
- package/src/flags.ts +0 -4
- package/src/global.d.ts +0 -9
- package/src/ids.ts +0 -137
- package/src/index.ts +0 -16
- package/src/input.ts +0 -35
- package/src/intent.ts +0 -15
- package/src/json.ts +0 -42
- package/src/participants.ts +0 -14
- package/src/payment.ts +0 -573
- package/src/profit.ts +0 -55
- package/src/sort.ts +0 -49
- package/src/stats.ts +0 -10
- package/src/time.ts +0 -123
- package/src/tokens.ts +0 -159
- package/src/units.ts +0 -120
- package/src/zkp2p-types.ts +0 -55
- 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
|
+
};
|
package/dist/src/stats.d.ts
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
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
|
+
});
|
package/dist/src/time.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @param
|
|
32
|
-
* @
|
|
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,
|
|
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";
|