@paraswap/dex-lib 2.13.0 → 2.14.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.
- package/build/config.js +5 -23
- package/build/config.js.map +1 -1
- package/build/dex/curve-v1/config.js +0 -2
- package/build/dex/curve-v1/config.js.map +1 -1
- package/build/dex/curve-v1/curve-v1.js +0 -2
- package/build/dex/curve-v1/curve-v1.js.map +1 -1
- package/build/dex/curve-v1/types.d.ts +0 -1
- package/build/dex/curve-v1/types.js.map +1 -1
- package/build/dex/index.js +2 -2
- package/build/dex/index.js.map +1 -1
- package/build/dex/simple-exchange.d.ts +0 -1
- package/build/dex/simple-exchange.js +1 -3
- package/build/dex/simple-exchange.js.map +1 -1
- package/build/lib/decoders.d.ts +1 -2
- package/build/lib/decoders.js +1 -8
- package/build/lib/decoders.js.map +1 -1
- package/build/lib/multi-wrapper.d.ts +1 -2
- package/build/lib/multi-wrapper.js.map +1 -1
- package/build/lib/tokens/balancer-fetcher.js +5 -4
- package/build/lib/tokens/balancer-fetcher.js.map +1 -1
- package/build/lib/tokens/utils.d.ts +2 -2
- package/build/lib/tokens/utils.js +1 -1
- package/build/lib/tokens/utils.js.map +1 -1
- package/build/types.d.ts +0 -3
- package/dex-template/__DexName__-e2e.test.ts.template +0 -1
- package/dex-template/__DexName__-events.test.ts.template +0 -1
- package/dex-template/__DexName__-integration.test.ts.template +0 -1
- package/dex-template/__DexName__-pool.ts.template +5 -8
- package/package.json +1 -1
- package/scripts/generate-bytecode.ts +0 -2
- package/src/abi/woo-fi/WooFeeManager.abi.json +318 -0
- package/src/abi/{woo-fi-v2/WooPPV2.abi.json → woo-fi/WooPP.abi.json} +169 -201
- package/src/abi/{woo-fi-v2/WooOracleV2.abi.json → woo-fi/Wooracle.abi.json} +50 -148
- package/src/config.ts +5 -27
- package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +1 -0
- package/src/dex/curve-v1/config.ts +0 -2
- package/src/dex/curve-v1/curve-v1-e2e.test.ts +37 -18
- package/src/dex/curve-v1/curve-v1.ts +0 -2
- package/src/dex/curve-v1/types.ts +0 -1
- package/src/dex/index.ts +2 -2
- package/src/dex/simple-exchange.ts +1 -4
- package/src/dex/woo-fi/config.ts +141 -0
- package/src/dex/woo-fi/constants.ts +21 -0
- package/src/dex/woo-fi/types.ts +55 -0
- package/src/dex/woo-fi/woo-fi-decimal-math.ts +45 -0
- package/src/dex/woo-fi/woo-fi-e2e.test.ts +183 -0
- package/src/dex/woo-fi/woo-fi-integration.test.ts +416 -0
- package/src/dex/woo-fi/woo-fi-math.ts +527 -0
- package/src/dex/woo-fi/woo-fi.ts +693 -0
- package/src/lib/decoders.ts +1 -12
- package/src/lib/multi-wrapper.ts +1 -2
- package/src/lib/tokens/balancer-fetcher.ts +6 -5
- package/src/lib/tokens/utils.ts +3 -5
- package/src/types.ts +0 -4
- package/tests/constants-e2e.ts +9 -9
- package/tests/tenderly-simulation.ts +1 -1
- package/tests/utils-e2e.ts +0 -2
- package/tests/utils.ts +0 -2
- package/src/abi/woo-fi-v2/IntegrationHelper.abi.json +0 -116
- package/src/dex/woo-fi-v2/config.ts +0 -87
- package/src/dex/woo-fi-v2/constants.ts +0 -22
- package/src/dex/woo-fi-v2/decoders.ts +0 -45
- package/src/dex/woo-fi-v2/types.ts +0 -63
- package/src/dex/woo-fi-v2/utils.ts +0 -19
- package/src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts +0 -216
- package/src/dex/woo-fi-v2/woo-fi-v2-integration.test.ts +0 -495
- package/src/dex/woo-fi-v2/woo-fi-v2-math.ts +0 -195
- package/src/dex/woo-fi-v2/woo-fi-v2-pool.ts +0 -112
- package/src/dex/woo-fi-v2/woo-fi-v2.ts +0 -487
- package/src/lib/log-messages-suppressor.ts +0 -173
- package/src/lib/stateful-rpc-poller/state-polling-manager.ts +0 -320
- package/src/lib/stateful-rpc-poller/stateful-rpc-poller.ts +0 -604
- package/src/lib/stateful-rpc-poller/types.ts +0 -66
- package/src/lib/stateful-rpc-poller/utils.ts +0 -23
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
import { assert } from 'console';
|
|
3
|
-
import { IDexHelper } from '../../dex-helper';
|
|
4
|
-
import { Logger } from '../../types';
|
|
5
|
-
import { MultiResult } from '../multi-wrapper';
|
|
6
|
-
import { IStatefulRpcPoller } from './types';
|
|
7
|
-
|
|
8
|
-
export class StatePollingManager {
|
|
9
|
-
// This is for update pool states function. If we see state for new block and
|
|
10
|
-
// the diff is bigger than this number, than something might be wrong and
|
|
11
|
-
// we warn about this
|
|
12
|
-
static readonly DEFAULT_BLOCK_NUMBER_DIFFERENCE_TO_ALERT = 10;
|
|
13
|
-
|
|
14
|
-
private static __instances: Record<string, StatePollingManager> = {};
|
|
15
|
-
|
|
16
|
-
static getInstance(dexHelper: IDexHelper): StatePollingManager {
|
|
17
|
-
const network = dexHelper.config.data.network;
|
|
18
|
-
if (StatePollingManager.__instances[network] === undefined) {
|
|
19
|
-
StatePollingManager.__instances[network] = new StatePollingManager(
|
|
20
|
-
dexHelper,
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
return StatePollingManager.__instances[network];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private _lastProcessedBlockNumber = 0;
|
|
27
|
-
|
|
28
|
-
private logger: Logger;
|
|
29
|
-
|
|
30
|
-
private _registeredPendingPools: IStatefulRpcPoller<any, any>[] = [];
|
|
31
|
-
|
|
32
|
-
// ALl registered instances from identifier to instance
|
|
33
|
-
private _poolsToInstances: Record<string, IStatefulRpcPoller<any, any>> = {};
|
|
34
|
-
|
|
35
|
-
// This pools will be updated if we see new block and the time has come
|
|
36
|
-
private _poolsToBeUpdated: Set<string> = new Set();
|
|
37
|
-
|
|
38
|
-
// This pools wont be updated before we change _isStateToBeUpdated to true
|
|
39
|
-
private _idlePools: Set<string> = new Set();
|
|
40
|
-
|
|
41
|
-
private constructor(protected dexHelper: IDexHelper) {
|
|
42
|
-
this.logger = this.dexHelper.getLogger(
|
|
43
|
-
`${this.constructor.name}-${dexHelper.config.data.network}`,
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
get isMaster() {
|
|
48
|
-
return !this.dexHelper.config.isSlave;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
enableStateTracking(identifierKey: string) {
|
|
52
|
-
assert(
|
|
53
|
-
this._poolsToInstances[identifierKey] !== undefined,
|
|
54
|
-
`enableTracking: pool with identifierKey=${identifierKey} is not initialized`,
|
|
55
|
-
);
|
|
56
|
-
this._poolsToBeUpdated.add(identifierKey);
|
|
57
|
-
this._idlePools.delete(identifierKey);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
disableStateTracking(identifierKey: string) {
|
|
61
|
-
assert(
|
|
62
|
-
this._poolsToInstances[identifierKey] !== undefined,
|
|
63
|
-
`disableStateTracking: pool with identifierKey=${identifierKey} is not initialized`,
|
|
64
|
-
);
|
|
65
|
-
this._poolsToBeUpdated.delete(identifierKey);
|
|
66
|
-
this._idlePools.add(identifierKey);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async onBlockNumber(blockNumber: number): Promise<void> {
|
|
70
|
-
if (!this.isMaster) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Events-client calls several times for the same blockNumber sometimes
|
|
75
|
-
// I want to filter them. The only condition, that matters is that blockNumbers are the same
|
|
76
|
-
if (this._lastProcessedBlockNumber === blockNumber) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
this._lastProcessedBlockNumber = blockNumber;
|
|
80
|
-
|
|
81
|
-
const poolsToBeUpdated: IStatefulRpcPoller<any, any>[] = [];
|
|
82
|
-
|
|
83
|
-
Array.from(this._poolsToBeUpdated).forEach(p => {
|
|
84
|
-
const pool = this._keyToPoolInstance(p);
|
|
85
|
-
|
|
86
|
-
// We always expect pools in _poolsToBeUpdated to participate in updates
|
|
87
|
-
assert(
|
|
88
|
-
pool.isPoolParticipateInUpdates,
|
|
89
|
-
`onBlockNumber: pool=${p} from ${pool.dexKey} is not participate in updates`,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
!pool.isPoolInTheMiddleOfUpdate &&
|
|
94
|
-
pool.isTimeToTriggerUpdate(blockNumber)
|
|
95
|
-
) {
|
|
96
|
-
pool.isPoolInTheMiddleOfUpdate = true;
|
|
97
|
-
poolsToBeUpdated.push(pool);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
if (poolsToBeUpdated.length === 0) {
|
|
102
|
-
this.logger.debug(
|
|
103
|
-
`onBlockNumber=${blockNumber} no pools to be updated. Skipping`,
|
|
104
|
-
);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this._updatePoolStates(poolsToBeUpdated)
|
|
109
|
-
.then(receivedBlockNumber => {
|
|
110
|
-
// There is no guarantee that we receive latest state. This is our best effort
|
|
111
|
-
if (
|
|
112
|
-
Math.abs(blockNumber - receivedBlockNumber) >
|
|
113
|
-
StatePollingManager.DEFAULT_BLOCK_NUMBER_DIFFERENCE_TO_ALERT
|
|
114
|
-
) {
|
|
115
|
-
this.logger.warn(
|
|
116
|
-
`onBlockNumber=${blockNumber} at least for some pools receivedBlockNumber=${receivedBlockNumber} is lower than expected`,
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
this.logger.info(
|
|
120
|
-
`onBlockNumber=${blockNumber} updated ${
|
|
121
|
-
poolsToBeUpdated.length
|
|
122
|
-
} pools: ${poolsToBeUpdated
|
|
123
|
-
.map(p => p.identifierKey)
|
|
124
|
-
.slice(0, 10)
|
|
125
|
-
.join(',')} (sample)`,
|
|
126
|
-
);
|
|
127
|
-
})
|
|
128
|
-
.catch(e =>
|
|
129
|
-
this.logger.error(
|
|
130
|
-
`onBlockNumber=${blockNumber} error while updating pools: ${e}`,
|
|
131
|
-
),
|
|
132
|
-
)
|
|
133
|
-
.finally(() => {
|
|
134
|
-
poolsToBeUpdated.forEach(pool => {
|
|
135
|
-
pool.isPoolInTheMiddleOfUpdate = false;
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
protected async _updatePoolStates(
|
|
141
|
-
poolsToBeUpdated: IStatefulRpcPoller<any, any>[],
|
|
142
|
-
blockNumber: number | 'latest' = 'latest',
|
|
143
|
-
numberOfChunks?: number,
|
|
144
|
-
): Promise<number> {
|
|
145
|
-
const indexDividers: number[] = [];
|
|
146
|
-
|
|
147
|
-
const multiCalls = poolsToBeUpdated
|
|
148
|
-
.map((p, i) => {
|
|
149
|
-
const callData = p.getFetchStateWithBlockInfoMultiCalls();
|
|
150
|
-
indexDividers.push(callData.length);
|
|
151
|
-
return callData;
|
|
152
|
-
})
|
|
153
|
-
.flat();
|
|
154
|
-
|
|
155
|
-
assert(
|
|
156
|
-
indexDividers.length === poolsToBeUpdated.length,
|
|
157
|
-
'indexDividers.length === poolsToBeUpdated.length',
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
const results = (await this.dexHelper.multiWrapper.tryAggregate(
|
|
161
|
-
false,
|
|
162
|
-
multiCalls,
|
|
163
|
-
blockNumber,
|
|
164
|
-
numberOfChunks,
|
|
165
|
-
)) as [MultiResult<number>, ...MultiResult<any>[]];
|
|
166
|
-
|
|
167
|
-
let minBlockNumber = 0;
|
|
168
|
-
const lastUpdatedAtMs = Date.now();
|
|
169
|
-
|
|
170
|
-
// Let's pack each result into relevant pools
|
|
171
|
-
const unFlattenedResults: [MultiResult<number>, ...MultiResult<any>[]][] =
|
|
172
|
-
[];
|
|
173
|
-
|
|
174
|
-
let accumulatedStart = 0;
|
|
175
|
-
indexDividers.forEach(divider => {
|
|
176
|
-
unFlattenedResults.push(
|
|
177
|
-
results.slice(accumulatedStart, accumulatedStart + divider) as [
|
|
178
|
-
MultiResult<number>,
|
|
179
|
-
...MultiResult<any>[],
|
|
180
|
-
],
|
|
181
|
-
);
|
|
182
|
-
accumulatedStart += divider;
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
assert(
|
|
186
|
-
unFlattenedResults.length === poolsToBeUpdated.length,
|
|
187
|
-
'unFlattenedResults.length === poolsToBeUpdated.length',
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
await Promise.all(
|
|
191
|
-
unFlattenedResults.map(async (result, index) => {
|
|
192
|
-
const pool = poolsToBeUpdated[index];
|
|
193
|
-
try {
|
|
194
|
-
const parsedStateResult =
|
|
195
|
-
pool.parseStateFromMultiResultsWithBlockInfo(
|
|
196
|
-
result,
|
|
197
|
-
lastUpdatedAtMs,
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
minBlockNumber =
|
|
201
|
-
minBlockNumber === 0
|
|
202
|
-
? parsedStateResult.blockNumber
|
|
203
|
-
: Math.min(parsedStateResult.blockNumber, minBlockNumber);
|
|
204
|
-
|
|
205
|
-
await pool.setState(
|
|
206
|
-
parsedStateResult.value,
|
|
207
|
-
parsedStateResult.blockNumber,
|
|
208
|
-
parsedStateResult.lastUpdatedAtMs,
|
|
209
|
-
);
|
|
210
|
-
} catch (e) {
|
|
211
|
-
this.logger.error(
|
|
212
|
-
`onBlockNumber=${blockNumber} error while parsing state from multicall for pool=${pool.identifierKey} from ${pool.dexKey}: ${e}`,
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
}),
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
return minBlockNumber;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// When this method is called, we expect that all pools are initialized
|
|
222
|
-
private _keyToPoolInstance(
|
|
223
|
-
identifierKey: string,
|
|
224
|
-
): IStatefulRpcPoller<any, any> {
|
|
225
|
-
const pool = this._poolsToInstances[identifierKey];
|
|
226
|
-
assert(
|
|
227
|
-
pool !== undefined,
|
|
228
|
-
`keyToPoolInstance: pool=${identifierKey} is undefined`,
|
|
229
|
-
);
|
|
230
|
-
return pool;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Once you instantiated all your pools, you should trigger at the end of initializing this method
|
|
234
|
-
// So all state will be initialized. It is not part of constructor, because and that time we don't have
|
|
235
|
-
// all classes built
|
|
236
|
-
initializeAllPendingPools() {
|
|
237
|
-
if (this._registeredPendingPools.length === 0) {
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
this._registeredPendingPools.forEach(p => {
|
|
242
|
-
this.initializePool(p);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
this._registeredPendingPools = [];
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
registerPendingPool<T, M>(statefulRpcPoller: IStatefulRpcPoller<T, M>) {
|
|
249
|
-
if (this._poolsToInstances[statefulRpcPoller.identifierKey]) {
|
|
250
|
-
this.logger.error(
|
|
251
|
-
`Attempt to register initialized pool=${statefulRpcPoller.identifierKey}`,
|
|
252
|
-
);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const alreadyRegisteredAsPending = this._registeredPendingPools.some(
|
|
257
|
-
p => p.identifierKey === statefulRpcPoller.identifierKey,
|
|
258
|
-
);
|
|
259
|
-
if (alreadyRegisteredAsPending) {
|
|
260
|
-
this.logger.error(
|
|
261
|
-
`Attempt to register pool=${statefulRpcPoller.identifierKey} twice`,
|
|
262
|
-
);
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
this._registeredPendingPools.push(statefulRpcPoller);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
async initializePool<T, M>(statefulRpcPoller: IStatefulRpcPoller<T, M>) {
|
|
269
|
-
const { identifierKey } = statefulRpcPoller;
|
|
270
|
-
|
|
271
|
-
if (
|
|
272
|
-
this._idlePools.has(identifierKey) ||
|
|
273
|
-
this._poolsToBeUpdated.has(identifierKey) ||
|
|
274
|
-
this._poolsToInstances.hasOwnProperty(identifierKey)
|
|
275
|
-
) {
|
|
276
|
-
this.logger.warn(
|
|
277
|
-
`Attempt to reinitialize existing poolIdentifier=` +
|
|
278
|
-
`${identifierKey}. Maybe there is memory leak`,
|
|
279
|
-
);
|
|
280
|
-
} else {
|
|
281
|
-
this._poolsToInstances[identifierKey] = statefulRpcPoller;
|
|
282
|
-
statefulRpcPoller.isPoolParticipateInUpdates
|
|
283
|
-
? this._poolsToBeUpdated.add(identifierKey)
|
|
284
|
-
: this._idlePools.add(identifierKey);
|
|
285
|
-
|
|
286
|
-
let currentBlockNumber: number | undefined;
|
|
287
|
-
// This complication is only for pool tracker. We don't have block manager there and
|
|
288
|
-
// this is workaround to get current block number
|
|
289
|
-
if (
|
|
290
|
-
this.dexHelper.blockManager &&
|
|
291
|
-
this.dexHelper.blockManager.getActiveChainHead
|
|
292
|
-
) {
|
|
293
|
-
currentBlockNumber =
|
|
294
|
-
this.dexHelper.blockManager.getActiveChainHead()?.number;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (currentBlockNumber === undefined) {
|
|
298
|
-
currentBlockNumber =
|
|
299
|
-
await this.dexHelper.web3Provider.eth.getBlockNumber();
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
assert(
|
|
303
|
-
currentBlockNumber !== undefined,
|
|
304
|
-
'currentBlockNumber !== undefined',
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
statefulRpcPoller
|
|
308
|
-
.initializeState()
|
|
309
|
-
.then(() => {
|
|
310
|
-
this.logger.info(`Successfully initialized pool=${identifierKey}`);
|
|
311
|
-
})
|
|
312
|
-
.catch(e => {
|
|
313
|
-
// Must never happen
|
|
314
|
-
this.logger.error(
|
|
315
|
-
`initializePool: pool=${identifierKey} from ${statefulRpcPoller.dexKey} error while initializing state: ${e}`,
|
|
316
|
-
);
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|