@paraswap/dex-lib 2.13.1 → 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/generic-rfq/rate-fetcher.js +0 -2
- package/build/dex/generic-rfq/rate-fetcher.js.map +1 -1
- package/build/dex/generic-rfq/validators.d.ts +1 -1
- package/build/dex/generic-rfq/validators.js +26 -36
- package/build/dex/generic-rfq/validators.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 +0 -2
- 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/fetcher/fetcher.js +0 -3
- package/build/lib/fetcher/fetcher.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/generic-rfq/generic-rfq-e2e.test.ts +258 -63
- package/src/dex/generic-rfq/rate-fetcher.ts +0 -2
- package/src/dex/generic-rfq/validators.test.ts +32 -6
- package/src/dex/generic-rfq/validators.ts +32 -57
- package/src/dex/index.ts +2 -2
- package/src/dex/simple-exchange.ts +0 -3
- 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/fetcher/fetcher.ts +0 -6
- 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 -11
- package/tests/tenderly-simulation.ts +1 -1
- package/tests/utils-e2e.ts +48 -61
- package/tests/utils.ts +0 -2
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
- package/.vscode/launch.json +0 -21
- package/build/dex/aave-v3/tokens/arbitrum.json +0 -50
- package/build/dex/aave-v3/tokens/avalanche.json +0 -50
- package/build/dex/aave-v3/tokens/fantom.json +0 -62
- package/build/dex/aave-v3/tokens/mainnet.json +0 -44
- package/build/dex/aave-v3/tokens/optimism.json +0 -50
- package/build/dex/aave-v3/tokens/polygon.json +0 -98
- package/build/dex/balancer-v2/VirtualBoostedPool.d.ts +0 -79
- package/build/dex/balancer-v2/VirtualBoostedPool.js +0 -382
- package/build/dex/balancer-v2/VirtualBoostedPool.js.map +0 -1
- package/build/dex/generic-rfq/e2e-test-config.d.ts +0 -9
- package/build/dex/generic-rfq/e2e-test-config.js +0 -33
- package/build/dex/generic-rfq/e2e-test-config.js.map +0 -1
- package/build/dex/test-aave-v3/config.d.ts +0 -4
- package/build/dex/test-aave-v3/config.js +0 -15
- package/build/dex/test-aave-v3/config.js.map +0 -1
- package/build/dex/test-aave-v3/test-aave-v3-pool.d.ts +0 -39
- package/build/dex/test-aave-v3/test-aave-v3-pool.js +0 -63
- package/build/dex/test-aave-v3/test-aave-v3-pool.js.map +0 -1
- package/build/dex/test-aave-v3/test-aave-v3.d.ts +0 -37
- package/build/dex/test-aave-v3/test-aave-v3.js +0 -126
- package/build/dex/test-aave-v3/test-aave-v3.js.map +0 -1
- package/build/dex/test-aave-v3/types.d.ts +0 -6
- package/build/dex/test-aave-v3/types.js +0 -3
- package/build/dex/test-aave-v3/types.js.map +0 -1
- package/src/abi/woo-fi-v2/IntegrationHelper.abi.json +0 -116
- package/src/dex/generic-rfq/e2e-test-config.ts +0 -37
- package/src/dex/generic-rfq/generic-rfq-local-e2e.test.ts +0 -121
- 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,173 +0,0 @@
|
|
|
1
|
-
import { assert } from 'ts-essentials';
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import { Logger, LogLevels } from '../types';
|
|
4
|
-
import { Utils } from '../utils';
|
|
5
|
-
|
|
6
|
-
export const DEFAULT_LOG_PUBLISH_PERIOD_MS = 60_000;
|
|
7
|
-
|
|
8
|
-
// After this period previous logs, even if unpublished, would be discarded
|
|
9
|
-
// Because most likely they are outdated
|
|
10
|
-
export const DEFAULT_LOG_DISCARD_PERIOD_MS = 15 * 60 * 1000;
|
|
11
|
-
|
|
12
|
-
// We may have hundreds of pools failing at the same time,
|
|
13
|
-
// and we don't want to show them all
|
|
14
|
-
export const DEFAULT_LOG_MAX_IDENTITIES_TO_SHOW = 10;
|
|
15
|
-
|
|
16
|
-
export type StandardStringEnum = Readonly<Record<string, string>>;
|
|
17
|
-
|
|
18
|
-
export type MessageInfo<T extends StandardStringEnum> = {
|
|
19
|
-
key: keyof T;
|
|
20
|
-
message: T[keyof T];
|
|
21
|
-
logLevel: LogLevels;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export type MessageData = {
|
|
25
|
-
counter: number;
|
|
26
|
-
lastLoggedAtMs: number;
|
|
27
|
-
identificationInfos: string[];
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export type AggregatedLogForEntity<T extends StandardStringEnum> = {
|
|
31
|
-
[key in keyof T]?: MessageData;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/*
|
|
35
|
-
* This is helper module to reduce frequency of logging of spamming messages
|
|
36
|
-
*
|
|
37
|
-
* 1. You can only have predefined set of log messages to log
|
|
38
|
-
* First time log message is received, it is published with all arguments.
|
|
39
|
-
* Limitation - message can not include variables, but you can pass them as args
|
|
40
|
-
* If within cooldown period received another message of the same category, it
|
|
41
|
-
* is not published, but counter is increased with addition of some entity identifier
|
|
42
|
-
*
|
|
43
|
-
* 2. There is no background task running. In order to keep relevance of logs,
|
|
44
|
-
* if after certain amount of time we didn't receive logs, then we discarded accumulated ones
|
|
45
|
-
* on the next received ones and only publish relevant ones
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
export class LogMessagesSuppressor<T extends StandardStringEnum> {
|
|
49
|
-
// I don't really like this any, but couldn't come up with better solution
|
|
50
|
-
// in reasonable time. So, in order to unblock myself, do this
|
|
51
|
-
static instances: Record<string, LogMessagesSuppressor<any>> = {};
|
|
52
|
-
|
|
53
|
-
private _aggregatedLogs: AggregatedLogForEntity<T> = {};
|
|
54
|
-
|
|
55
|
-
constructor(
|
|
56
|
-
readonly entityName: string,
|
|
57
|
-
private _allMessages: Record<keyof T, MessageInfo<T>>,
|
|
58
|
-
protected logger: Logger,
|
|
59
|
-
) {}
|
|
60
|
-
|
|
61
|
-
static getLogSuppressorInstance<T extends StandardStringEnum>(
|
|
62
|
-
entityName: string,
|
|
63
|
-
allMessages: Record<keyof T, MessageInfo<T>>,
|
|
64
|
-
logger: Logger,
|
|
65
|
-
) {
|
|
66
|
-
const instance = LogMessagesSuppressor.instances[entityName];
|
|
67
|
-
if (instance === undefined) {
|
|
68
|
-
LogMessagesSuppressor.instances[entityName] =
|
|
69
|
-
new LogMessagesSuppressor<T>(entityName, allMessages, logger);
|
|
70
|
-
} else {
|
|
71
|
-
assert(
|
|
72
|
-
_.isEqual(allMessages, instance._allMessages),
|
|
73
|
-
'getLogSuppressorInstance: try to get existing instance with different allMessagesInfo',
|
|
74
|
-
);
|
|
75
|
-
assert(
|
|
76
|
-
_.isEqual(logger, instance.logger),
|
|
77
|
-
'getLogSuppressorInstance: try to get existing instance with different logger',
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
return LogMessagesSuppressor.instances[entityName];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
logMessage(
|
|
84
|
-
msgKey: keyof T,
|
|
85
|
-
identificationInfo: string = '',
|
|
86
|
-
...args: unknown[]
|
|
87
|
-
) {
|
|
88
|
-
const msgInfo = this._allMessages[msgKey];
|
|
89
|
-
assert(
|
|
90
|
-
msgInfo !== undefined,
|
|
91
|
-
`Used unrecognized msgKey=${String(msgKey)} to get msgInfo`,
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
if (this._aggregatedLogs[msgKey] === undefined) {
|
|
95
|
-
this._aggregatedLogs[msgKey] = {
|
|
96
|
-
counter: 0,
|
|
97
|
-
identificationInfos:
|
|
98
|
-
identificationInfo === '' ? [] : [identificationInfo],
|
|
99
|
-
lastLoggedAtMs: 0,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
const msgData = this._aggregatedLogs[msgKey];
|
|
103
|
-
assert(
|
|
104
|
-
msgData !== undefined,
|
|
105
|
-
`msgData is undefined for msgKey=${String(msgKey)}`,
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
const nowMs = Date.now();
|
|
109
|
-
|
|
110
|
-
const elapsedSinceLastPublish = nowMs - msgData.lastLoggedAtMs;
|
|
111
|
-
|
|
112
|
-
if (elapsedSinceLastPublish > DEFAULT_LOG_PUBLISH_PERIOD_MS) {
|
|
113
|
-
// Accumulated logs are too old to have any relevance, so better to discard them
|
|
114
|
-
if (elapsedSinceLastPublish > DEFAULT_LOG_DISCARD_PERIOD_MS) {
|
|
115
|
-
this._clearMessageData(msgData);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Make actual logging
|
|
119
|
-
// Logging is done using original logger of the entity to keep module info
|
|
120
|
-
// and not override it
|
|
121
|
-
const formattedMessage = this._formatLogMessage(
|
|
122
|
-
msgData,
|
|
123
|
-
msgInfo.message,
|
|
124
|
-
args,
|
|
125
|
-
);
|
|
126
|
-
this.logger[msgInfo.logLevel](formattedMessage);
|
|
127
|
-
this._clearMessageData(msgData);
|
|
128
|
-
} else {
|
|
129
|
-
msgData.counter++;
|
|
130
|
-
if (identificationInfo !== '') {
|
|
131
|
-
msgData.identificationInfos.push(identificationInfo);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
private _formatLogMessage(
|
|
137
|
-
msgData: MessageData,
|
|
138
|
-
message: string,
|
|
139
|
-
args: unknown[],
|
|
140
|
-
) {
|
|
141
|
-
const { counter, identificationInfos } = msgData;
|
|
142
|
-
let identities =
|
|
143
|
-
identificationInfos && identificationInfos.length === 0
|
|
144
|
-
? ''
|
|
145
|
-
: ` for entities: ${
|
|
146
|
-
identificationInfos.length > DEFAULT_LOG_MAX_IDENTITIES_TO_SHOW
|
|
147
|
-
? identificationInfos
|
|
148
|
-
.slice(DEFAULT_LOG_MAX_IDENTITIES_TO_SHOW)
|
|
149
|
-
.join(',')
|
|
150
|
-
: identificationInfos.join(',')
|
|
151
|
-
}`;
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
identificationInfos &&
|
|
155
|
-
identificationInfos.length > DEFAULT_LOG_MAX_IDENTITIES_TO_SHOW
|
|
156
|
-
) {
|
|
157
|
-
identities = `${identities}... ${identificationInfos.length} total`;
|
|
158
|
-
}
|
|
159
|
-
const argsFormatted =
|
|
160
|
-
args.length > 0
|
|
161
|
-
? ` with args: ${args.map(a => Utils.Serialize(a)).join('.')}`
|
|
162
|
-
: '';
|
|
163
|
-
return `Logged ${counter} occurrences of: "${message}"${identities}${argsFormatted}`;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
private _clearMessageData(messageData: MessageData) {
|
|
167
|
-
messageData.counter = 0;
|
|
168
|
-
if (messageData.identificationInfos) {
|
|
169
|
-
messageData.identificationInfos.length = 0;
|
|
170
|
-
}
|
|
171
|
-
messageData.lastLoggedAtMs = Date.now();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
@@ -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
|
-
}
|