@paraswap/dex-lib 2.37.4 → 2.37.5-dexalot
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/abi/dexalot/DexalotMainnetRFQ.json +65 -0
- package/build/config.js +4 -2
- package/build/config.js.map +1 -1
- package/build/dex/dexalot/config.js +4 -4
- package/build/dex/dexalot/config.js.map +1 -1
- package/build/dex/dexalot/dexalot.d.ts +1 -1
- package/build/dex/dexalot/dexalot.js +1 -5
- package/build/dex/dexalot/dexalot.js.map +1 -1
- package/build/dex/idex.d.ts +1 -1
- package/build/dex/index.js +2 -0
- package/build/dex/index.js.map +1 -1
- package/build/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/abi/dexalot/DexalotMainnetRFQ.json +952 -0
- package/src/config.ts +5 -2
- package/src/dex/dexalot/config.ts +18 -0
- package/src/dex/dexalot/constants.ts +29 -0
- package/src/dex/dexalot/dexalot-e2e.test.ts +192 -0
- package/src/dex/dexalot/dexalot-integration.test.ts +188 -0
- package/src/dex/dexalot/dexalot.ts +998 -0
- package/src/dex/dexalot/rate-fetcher.ts +197 -0
- package/src/dex/dexalot/types.ts +131 -0
- package/src/dex/dexalot/validators.ts +46 -0
- package/src/dex/idex.ts +2 -0
- package/src/dex/index.ts +2 -0
- package/src/types.ts +1 -0
- package/tests/constants-e2e.ts +1 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { IDexHelper } from '../../dex-helper';
|
|
2
|
+
import { Fetcher } from '../../lib/fetcher/fetcher';
|
|
3
|
+
import { validateAndCast } from '../../lib/validators';
|
|
4
|
+
import { Logger, Token } from '../../types';
|
|
5
|
+
import {
|
|
6
|
+
DexalotRateFetcherConfig,
|
|
7
|
+
DexalotPairsResponse,
|
|
8
|
+
PairDataMap,
|
|
9
|
+
DexalotPricesResponse,
|
|
10
|
+
PriceDataMap,
|
|
11
|
+
DexalotBlacklistResponse,
|
|
12
|
+
} from './types';
|
|
13
|
+
import {
|
|
14
|
+
pricesResponseValidator,
|
|
15
|
+
pairsResponseValidator,
|
|
16
|
+
blacklistResponseValidator,
|
|
17
|
+
} from './validators';
|
|
18
|
+
import { Network } from '../../constants';
|
|
19
|
+
|
|
20
|
+
export class RateFetcher {
|
|
21
|
+
private pairsFetcher: Fetcher<DexalotPairsResponse>;
|
|
22
|
+
private pairsCacheKey: string;
|
|
23
|
+
private pairsCacheTTL: number;
|
|
24
|
+
|
|
25
|
+
private rateFetcher: Fetcher<DexalotPricesResponse>;
|
|
26
|
+
private pricesCacheKey: string;
|
|
27
|
+
private pricesCacheTTL: number;
|
|
28
|
+
|
|
29
|
+
private tokensAddrCacheKey: string;
|
|
30
|
+
private tokensCacheKey: string;
|
|
31
|
+
private tokensCacheTTL: number;
|
|
32
|
+
|
|
33
|
+
private blacklistFetcher: Fetcher<DexalotBlacklistResponse>;
|
|
34
|
+
private blacklistCacheKey: string;
|
|
35
|
+
private blacklistCacheTTL: number;
|
|
36
|
+
|
|
37
|
+
constructor(
|
|
38
|
+
private dexHelper: IDexHelper,
|
|
39
|
+
private dexKey: string,
|
|
40
|
+
private network: Network,
|
|
41
|
+
private logger: Logger,
|
|
42
|
+
config: DexalotRateFetcherConfig,
|
|
43
|
+
) {
|
|
44
|
+
this.pairsCacheKey = config.rateConfig.pairsCacheKey;
|
|
45
|
+
this.pairsCacheTTL = config.rateConfig.pairsCacheTTLSecs;
|
|
46
|
+
this.pricesCacheKey = config.rateConfig.pricesCacheKey;
|
|
47
|
+
this.pricesCacheTTL = config.rateConfig.pricesCacheTTLSecs;
|
|
48
|
+
this.tokensAddrCacheKey = config.rateConfig.tokensAddrCacheKey;
|
|
49
|
+
this.tokensCacheKey = config.rateConfig.tokensCacheKey;
|
|
50
|
+
this.tokensCacheTTL = config.rateConfig.tokensCacheTTLSecs;
|
|
51
|
+
this.blacklistCacheKey = config.rateConfig.blacklistCacheKey;
|
|
52
|
+
this.blacklistCacheTTL = config.rateConfig.blacklistCacheTTLSecs;
|
|
53
|
+
|
|
54
|
+
this.pairsFetcher = new Fetcher<DexalotPairsResponse>(
|
|
55
|
+
dexHelper.httpRequest,
|
|
56
|
+
{
|
|
57
|
+
info: {
|
|
58
|
+
requestOptions: config.rateConfig.pairsReqParams,
|
|
59
|
+
caster: (data: unknown) => {
|
|
60
|
+
return validateAndCast<DexalotPairsResponse>(
|
|
61
|
+
data,
|
|
62
|
+
pairsResponseValidator,
|
|
63
|
+
);
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
handler: this.handlePairsResponse.bind(this),
|
|
67
|
+
},
|
|
68
|
+
config.rateConfig.pairsIntervalMs,
|
|
69
|
+
logger,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
this.rateFetcher = new Fetcher<DexalotPricesResponse>(
|
|
73
|
+
dexHelper.httpRequest,
|
|
74
|
+
{
|
|
75
|
+
info: {
|
|
76
|
+
requestOptions: config.rateConfig.pricesReqParams,
|
|
77
|
+
caster: (data: unknown) => {
|
|
78
|
+
return validateAndCast<DexalotPricesResponse>(
|
|
79
|
+
data,
|
|
80
|
+
pricesResponseValidator,
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
handler: this.handleRatesResponse.bind(this),
|
|
85
|
+
},
|
|
86
|
+
config.rateConfig.pricesIntervalMs,
|
|
87
|
+
logger,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
this.blacklistFetcher = new Fetcher<DexalotBlacklistResponse>(
|
|
91
|
+
dexHelper.httpRequest,
|
|
92
|
+
{
|
|
93
|
+
info: {
|
|
94
|
+
requestOptions: config.rateConfig.blacklistReqParams,
|
|
95
|
+
caster: (data: unknown) => {
|
|
96
|
+
return validateAndCast<DexalotBlacklistResponse>(
|
|
97
|
+
data,
|
|
98
|
+
blacklistResponseValidator,
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
handler: this.handleBlacklistResponse.bind(this),
|
|
103
|
+
},
|
|
104
|
+
config.rateConfig.blacklistIntervalMs,
|
|
105
|
+
logger,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
start() {
|
|
110
|
+
this.pairsFetcher.startPolling();
|
|
111
|
+
this.rateFetcher.startPolling();
|
|
112
|
+
this.blacklistFetcher.startPolling();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
stop() {
|
|
116
|
+
this.pairsFetcher.stopPolling();
|
|
117
|
+
this.rateFetcher.stopPolling();
|
|
118
|
+
this.blacklistFetcher.stopPolling();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private handlePairsResponse(resp: DexalotPairsResponse): void {
|
|
122
|
+
const pairs = resp;
|
|
123
|
+
const dexPairs: PairDataMap = {};
|
|
124
|
+
const tokenMap: { [address: string]: Token } = {};
|
|
125
|
+
const tokenAddrMap: { [symbol: string]: string } = {};
|
|
126
|
+
Object.keys(pairs).forEach(pair => {
|
|
127
|
+
dexPairs[pair.toLowerCase()] = pairs[pair];
|
|
128
|
+
tokenAddrMap[pairs[pair].base.toLowerCase()] =
|
|
129
|
+
pairs[pair].baseAddress.toLowerCase();
|
|
130
|
+
tokenAddrMap[pairs[pair].quote.toLowerCase()] =
|
|
131
|
+
pairs[pair].quoteAddress.toLowerCase();
|
|
132
|
+
tokenMap[pairs[pair].baseAddress.toLowerCase()] = {
|
|
133
|
+
address: pairs[pair].baseAddress.toLowerCase(),
|
|
134
|
+
symbol: pairs[pair].base,
|
|
135
|
+
decimals: pairs[pair].baseDecimals,
|
|
136
|
+
};
|
|
137
|
+
tokenMap[pairs[pair].quoteAddress.toLowerCase()] = {
|
|
138
|
+
address: pairs[pair].quoteAddress.toLowerCase(),
|
|
139
|
+
symbol: pairs[pair].quote,
|
|
140
|
+
decimals: pairs[pair].quoteDecimals,
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
this.dexHelper.cache.setex(
|
|
145
|
+
this.dexKey,
|
|
146
|
+
this.network,
|
|
147
|
+
this.pairsCacheKey,
|
|
148
|
+
this.pairsCacheTTL,
|
|
149
|
+
JSON.stringify(dexPairs),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
this.dexHelper.cache.setex(
|
|
153
|
+
this.dexKey,
|
|
154
|
+
this.network,
|
|
155
|
+
this.tokensCacheKey,
|
|
156
|
+
this.tokensCacheTTL,
|
|
157
|
+
JSON.stringify(tokenMap),
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
this.dexHelper.cache.setex(
|
|
161
|
+
this.dexKey,
|
|
162
|
+
this.network,
|
|
163
|
+
this.tokensAddrCacheKey,
|
|
164
|
+
this.tokensCacheTTL,
|
|
165
|
+
JSON.stringify(tokenAddrMap),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private handleRatesResponse(resp: DexalotPricesResponse): void {
|
|
170
|
+
const { prices } = resp;
|
|
171
|
+
const dexPrices: PriceDataMap = {};
|
|
172
|
+
Object.keys(prices).forEach(pair => {
|
|
173
|
+
dexPrices[pair.toLowerCase()] = prices[pair];
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
this.dexHelper.cache.setex(
|
|
177
|
+
this.dexKey,
|
|
178
|
+
this.network,
|
|
179
|
+
this.pricesCacheKey,
|
|
180
|
+
this.pricesCacheTTL,
|
|
181
|
+
JSON.stringify(dexPrices),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private async handleBlacklistResponse(
|
|
186
|
+
resp: DexalotBlacklistResponse,
|
|
187
|
+
): Promise<void> {
|
|
188
|
+
const { blacklist } = resp;
|
|
189
|
+
this.dexHelper.cache.setex(
|
|
190
|
+
this.dexKey,
|
|
191
|
+
this.network,
|
|
192
|
+
this.blacklistCacheKey,
|
|
193
|
+
this.blacklistCacheTTL,
|
|
194
|
+
JSON.stringify(blacklist.map((item) => item.toLowerCase())),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { RequestHeaders } from '../../dex-helper';
|
|
2
|
+
import { Token } from '../../types';
|
|
3
|
+
import { Method } from '../../dex-helper/irequest-wrapper';
|
|
4
|
+
|
|
5
|
+
type RFQOrder = {
|
|
6
|
+
nonceAndMeta: string;
|
|
7
|
+
expiry: number;
|
|
8
|
+
makerAsset: string;
|
|
9
|
+
takerAsset: string;
|
|
10
|
+
maker: string;
|
|
11
|
+
taker: string;
|
|
12
|
+
makerAmount: string;
|
|
13
|
+
takerAmount: string;
|
|
14
|
+
signature?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type RFQResponse = {
|
|
18
|
+
order: RFQOrder;
|
|
19
|
+
signature: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type RFQResponseError = {
|
|
23
|
+
Reason: string;
|
|
24
|
+
ReasonCode: string;
|
|
25
|
+
Success: boolean;
|
|
26
|
+
RetryAfter?: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type DexalotData = {
|
|
30
|
+
quoteData?: RFQOrder;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type DexParams = {
|
|
34
|
+
mainnetRFQAddress: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export enum ClobSide {
|
|
38
|
+
BID = 'BID',
|
|
39
|
+
ASK = 'ASK',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class DexalotRfqError extends Error {}
|
|
43
|
+
|
|
44
|
+
export type PairData = {
|
|
45
|
+
base: string;
|
|
46
|
+
quote: string;
|
|
47
|
+
liquidityUSD: number;
|
|
48
|
+
isSrcBase?: boolean;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type PairDataMap = {
|
|
52
|
+
[pair: string]: PairData;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type PairDataResp = {
|
|
56
|
+
base: string;
|
|
57
|
+
quote: string;
|
|
58
|
+
liquidityUSD: number;
|
|
59
|
+
baseAddress: string;
|
|
60
|
+
quoteAddress: string;
|
|
61
|
+
baseDecimals: number;
|
|
62
|
+
quoteDecimals: number;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export type DexalotPairsResponse = {
|
|
66
|
+
[pair: string]: PairDataResp;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
type PriceData = {
|
|
70
|
+
bids: string[][];
|
|
71
|
+
asks: string[][];
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type PriceDataMap = {
|
|
75
|
+
[pair: string]: PriceData;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type DexalotPricesResponse = {
|
|
79
|
+
prices: PriceDataMap;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export type TokenAddrDataMap = {
|
|
83
|
+
[symbol: string]: string;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export type TokenDataMap = {
|
|
87
|
+
[address: string]: Token;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type DexalotBlacklistResponse = {
|
|
91
|
+
blacklist: string[];
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type DexalotRateFetcherConfig = {
|
|
95
|
+
rateConfig: {
|
|
96
|
+
pairsReqParams: {
|
|
97
|
+
url: string;
|
|
98
|
+
headers?: RequestHeaders;
|
|
99
|
+
params?: any;
|
|
100
|
+
};
|
|
101
|
+
pricesReqParams: {
|
|
102
|
+
url: string;
|
|
103
|
+
headers?: RequestHeaders;
|
|
104
|
+
params?: any;
|
|
105
|
+
};
|
|
106
|
+
blacklistReqParams: {
|
|
107
|
+
url: string;
|
|
108
|
+
headers?: RequestHeaders;
|
|
109
|
+
params?: any;
|
|
110
|
+
};
|
|
111
|
+
pairsIntervalMs: number;
|
|
112
|
+
pricesIntervalMs: number;
|
|
113
|
+
blacklistIntervalMs: number;
|
|
114
|
+
pairsCacheKey: string;
|
|
115
|
+
pricesCacheKey: string;
|
|
116
|
+
tokensAddrCacheKey: string;
|
|
117
|
+
tokensCacheKey: string;
|
|
118
|
+
blacklistCacheKey: string;
|
|
119
|
+
blacklistCacheTTLSecs: number;
|
|
120
|
+
pairsCacheTTLSecs: number;
|
|
121
|
+
pricesCacheTTLSecs: number;
|
|
122
|
+
tokensCacheTTLSecs: number;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export type DexalotAPIParameters = {
|
|
127
|
+
url: string;
|
|
128
|
+
headers?: RequestHeaders;
|
|
129
|
+
params?: any;
|
|
130
|
+
method?: Method;
|
|
131
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import joi from 'joi';
|
|
2
|
+
|
|
3
|
+
const pairValidator = joi.object({
|
|
4
|
+
base: joi.string().min(1).required(),
|
|
5
|
+
quote: joi.string().min(1).required(),
|
|
6
|
+
liquidityUSD: joi.number().min(0).required(),
|
|
7
|
+
baseAddress: joi.string().min(1).required(),
|
|
8
|
+
quoteAddress: joi.string().min(1).required(),
|
|
9
|
+
baseDecimals: joi.number().min(0).required(),
|
|
10
|
+
quoteDecimals: joi.number().min(0).required(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const pairsResponseValidator = joi
|
|
14
|
+
.object()
|
|
15
|
+
.pattern(joi.string(), pairValidator);
|
|
16
|
+
|
|
17
|
+
const orderbookRecordValidator = joi
|
|
18
|
+
.array()
|
|
19
|
+
.items(joi.string().min(1))
|
|
20
|
+
.length(2);
|
|
21
|
+
|
|
22
|
+
const orderbookValidator = joi.object({
|
|
23
|
+
bids: joi.array().items(orderbookRecordValidator).required(),
|
|
24
|
+
asks: joi.array().items(orderbookRecordValidator).required(),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const pricesResponseValidator = joi.object({
|
|
28
|
+
prices: joi.object().pattern(joi.string(), orderbookValidator),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const tokenValidator = joi.object({
|
|
32
|
+
symbol: joi.string().min(1).required(),
|
|
33
|
+
name: joi.string().min(1).required(),
|
|
34
|
+
description: joi.string().min(1).required(),
|
|
35
|
+
address: joi.string().min(1).required(),
|
|
36
|
+
decimals: joi.number().min(0).required(),
|
|
37
|
+
type: joi.string().min(1).required(),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export const tokensResponseValidator = joi.object({
|
|
41
|
+
tokens: joi.object().pattern(joi.string(), tokenValidator),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export const blacklistResponseValidator = joi.object({
|
|
45
|
+
blacklist: joi.array().items(joi.string().min(1)).required(),
|
|
46
|
+
});
|
package/src/dex/idex.ts
CHANGED
|
@@ -131,9 +131,11 @@ export interface IDexPricing<ExchangeData> {
|
|
|
131
131
|
blockNumber: number,
|
|
132
132
|
// list of pool identifiers to use for pricing, if undefined use all pools
|
|
133
133
|
limitPools?: string[],
|
|
134
|
+
|
|
134
135
|
// I don't like putting this as new params, but in order to not change interface
|
|
135
136
|
// across all integrations, done it like this
|
|
136
137
|
transferFees?: TransferFeeParams,
|
|
138
|
+
isFirstSwap?: boolean,
|
|
137
139
|
): Promise<ExchangePrices<ExchangeData> | null>;
|
|
138
140
|
|
|
139
141
|
// Returns estimated gas cost for calldata for DEX when used in multiSwap.
|
package/src/dex/index.ts
CHANGED
|
@@ -76,6 +76,7 @@ import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3';
|
|
|
76
76
|
import { Algebra } from './algebra/algebra';
|
|
77
77
|
import { QuickPerps } from './quick-perps/quick-perps';
|
|
78
78
|
import { NomiswapV2 } from './uniswap-v2/nomiswap-v2';
|
|
79
|
+
import { Dexalot } from './dexalot/dexalot';
|
|
79
80
|
|
|
80
81
|
const LegacyDexes = [
|
|
81
82
|
CurveV2,
|
|
@@ -102,6 +103,7 @@ const LegacyDexes = [
|
|
|
102
103
|
];
|
|
103
104
|
|
|
104
105
|
const Dexes = [
|
|
106
|
+
Dexalot,
|
|
105
107
|
CurveV1,
|
|
106
108
|
CurveFork,
|
|
107
109
|
Swerve,
|
package/src/types.ts
CHANGED
package/tests/constants-e2e.ts
CHANGED
|
@@ -1081,7 +1081,7 @@ export const Holders: {
|
|
|
1081
1081
|
TSD: '0x691A89db352B72dDb249bFe16503494eC0D920A4',
|
|
1082
1082
|
THO: '0xc40d16c47394a506d451475c8a7c46c1175c1da1',
|
|
1083
1083
|
aAvaUSDT: '0x50B1Ba98Cf117c9682048D56628B294ebbAA4ec2',
|
|
1084
|
-
USDT: '
|
|
1084
|
+
USDT: '0x4a58555884297dcd9d2198c9fec52b4cabc90fc6',
|
|
1085
1085
|
aAvaWAVAX: '0x1B18Df70863636AEe4BfBAb6F7C70ceBCA9bA404',
|
|
1086
1086
|
oldFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b',
|
|
1087
1087
|
newFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b',
|