@paraswap/dex-lib 2.49.1 → 2.49.2-hashflow
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/Redstone.json +739 -0
- package/build/abi/angle/stagToken.json +963 -0
- package/build/abi/angle-transmuter/MorphoOracle.json +193 -0
- package/build/abi/angle-transmuter/MorphoVault.json +2506 -0
- package/build/abi/angle-transmuter/Pyth.json +1534 -0
- package/build/abi/angle-transmuter/Transmuter.json +1711 -0
- package/build/abi/pharaoh/PharaohPool.abi.json +1582 -0
- package/build/abi/smardex/smardex-factory.json +185 -0
- package/build/abi/smardex/smardex-pool.json +578 -0
- package/build/abi/smardex/smardex-router.json +648 -0
- package/build/abi/trader-joe-v2_1/FactoryABI.json +1208 -0
- package/build/abi/trader-joe-v2_1/PairABI.json +1493 -0
- package/build/abi/trader-joe-v2_1/RouterABI.json +1489 -0
- package/build/abi/trader-joe-v2_1/StateMulticall.json +193 -0
- package/build/dex/angle-staked-stable/angle-staked-stable-pool.d.ts +55 -0
- package/build/dex/angle-staked-stable/angle-staked-stable-pool.js +183 -0
- package/build/dex/angle-staked-stable/angle-staked-stable-pool.js.map +1 -0
- package/build/dex/angle-staked-stable/angle-staked-stable.d.ts +50 -0
- package/build/dex/angle-staked-stable/angle-staked-stable.js +278 -0
- package/build/dex/angle-staked-stable/angle-staked-stable.js.map +1 -0
- package/build/dex/angle-staked-stable/config.d.ts +4 -0
- package/build/dex/angle-staked-stable/config.js +131 -0
- package/build/dex/angle-staked-stable/config.js.map +1 -0
- package/build/dex/angle-staked-stable/types.d.ts +17 -0
- package/build/dex/angle-staked-stable/types.js +3 -0
- package/build/dex/angle-staked-stable/types.js.map +1 -0
- package/build/dex/angle-transmuter/angle-transmuter-pool.d.ts +61 -0
- package/build/dex/angle-transmuter/angle-transmuter-pool.js +415 -0
- package/build/dex/angle-transmuter/angle-transmuter-pool.js.map +1 -0
- package/build/dex/angle-transmuter/angle-transmuter.d.ts +59 -0
- package/build/dex/angle-transmuter/angle-transmuter.js +262 -0
- package/build/dex/angle-transmuter/angle-transmuter.js.map +1 -0
- package/build/dex/angle-transmuter/backedOracle.d.ts +19 -0
- package/build/dex/angle-transmuter/backedOracle.js +56 -0
- package/build/dex/angle-transmuter/backedOracle.js.map +1 -0
- package/build/dex/angle-transmuter/config.d.ts +4 -0
- package/build/dex/angle-transmuter/config.js +30 -0
- package/build/dex/angle-transmuter/config.js.map +1 -0
- package/build/dex/angle-transmuter/constants.d.ts +77 -0
- package/build/dex/angle-transmuter/constants.js +94 -0
- package/build/dex/angle-transmuter/constants.js.map +1 -0
- package/build/dex/angle-transmuter/morphoOracle.d.ts +42 -0
- package/build/dex/angle-transmuter/morphoOracle.js +179 -0
- package/build/dex/angle-transmuter/morphoOracle.js.map +1 -0
- package/build/dex/angle-transmuter/morphoVault.d.ts +19 -0
- package/build/dex/angle-transmuter/morphoVault.js +78 -0
- package/build/dex/angle-transmuter/morphoVault.js.map +1 -0
- package/build/dex/angle-transmuter/pyth.d.ts +19 -0
- package/build/dex/angle-transmuter/pyth.js +70 -0
- package/build/dex/angle-transmuter/pyth.js.map +1 -0
- package/build/dex/angle-transmuter/redstone.d.ts +20 -0
- package/build/dex/angle-transmuter/redstone.js +73 -0
- package/build/dex/angle-transmuter/redstone.js.map +1 -0
- package/build/dex/angle-transmuter/transmuter.d.ts +52 -0
- package/build/dex/angle-transmuter/transmuter.js +374 -0
- package/build/dex/angle-transmuter/transmuter.js.map +1 -0
- package/build/dex/angle-transmuter/types.d.ts +188 -0
- package/build/dex/angle-transmuter/types.js +33 -0
- package/build/dex/angle-transmuter/types.js.map +1 -0
- package/build/dex/angle-transmuter/utils.d.ts +9 -0
- package/build/dex/angle-transmuter/utils.js +252 -0
- package/build/dex/angle-transmuter/utils.js.map +1 -0
- package/build/dex/hashflow/constants.d.ts +27 -0
- package/build/dex/hashflow/constants.js +29 -1
- package/build/dex/hashflow/constants.js.map +1 -1
- package/build/dex/hashflow/hashflow.d.ts +3 -2
- package/build/dex/hashflow/hashflow.js +77 -12
- package/build/dex/hashflow/hashflow.js.map +1 -1
- package/build/dex/hashflow/types.d.ts +11 -0
- package/build/dex/hashflow/types.js +9 -0
- package/build/dex/hashflow/types.js.map +1 -1
- package/build/dex/index.js +2 -0
- package/build/dex/index.js.map +1 -1
- package/build/dex/smardex/subgraph-queries.d.ts +1 -0
- package/build/dex/smardex/subgraph-queries.js +17 -0
- package/build/dex/smardex/subgraph-queries.js.map +1 -0
- package/build/dex/smardex/usd-reserves.d.ts +23 -0
- package/build/dex/smardex/usd-reserves.js +86 -0
- package/build/dex/smardex/usd-reserves.js.map +1 -0
- package/build/dex/solidly/config.js +12 -0
- package/build/dex/solidly/config.js.map +1 -1
- package/build/dex/solidly/forks-override/pharaohV1.d.ts +8 -0
- package/build/dex/solidly/forks-override/pharaohV1.js +15 -0
- package/build/dex/solidly/forks-override/pharaohV1.js.map +1 -0
- package/build/dex/solidly/solidly.js +1 -0
- package/build/dex/solidly/solidly.js.map +1 -1
- package/build/dex/trader-joe-v2-1-2/config.d.ts +4 -0
- package/build/dex/trader-joe-v2-1-2/config.js +47 -0
- package/build/dex/trader-joe-v2-1-2/config.js.map +1 -0
- package/build/dex/trader-joe-v2-1-2/constants.d.ts +20 -0
- package/build/dex/trader-joe-v2-1-2/constants.js +22 -0
- package/build/dex/trader-joe-v2-1-2/constants.js.map +1 -0
- package/build/dex/trader-joe-v2-1-2/math/index.d.ts +37 -0
- package/build/dex/trader-joe-v2-1-2/math/index.js +291 -0
- package/build/dex/trader-joe-v2-1-2/math/index.js.map +1 -0
- package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2-pool.d.ts +60 -0
- package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2-pool.js +248 -0
- package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2-pool.js.map +1 -0
- package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2.d.ts +53 -0
- package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2.js +307 -0
- package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2.js.map +1 -0
- package/build/dex/trader-joe-v2-1-2/types.d.ts +82 -0
- package/build/dex/trader-joe-v2-1-2/types.js +9 -0
- package/build/dex/trader-joe-v2-1-2/types.js.map +1 -0
- package/build/dex/trader-joe-v2_1/config.d.ts +4 -0
- package/build/dex/trader-joe-v2_1/config.js +47 -0
- package/build/dex/trader-joe-v2_1/config.js.map +1 -0
- package/build/dex/trader-joe-v2_1/constants.d.ts +20 -0
- package/build/dex/trader-joe-v2_1/constants.js +22 -0
- package/build/dex/trader-joe-v2_1/constants.js.map +1 -0
- package/build/dex/trader-joe-v2_1/math/index.d.ts +37 -0
- package/build/dex/trader-joe-v2_1/math/index.js +291 -0
- package/build/dex/trader-joe-v2_1/math/index.js.map +1 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2.1.d.ts +0 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2.1.js +384 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2.1.js.map +1 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2_1-pool.d.ts +60 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2_1-pool.js +247 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2_1-pool.js.map +1 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2_1.d.ts +53 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2_1.js +307 -0
- package/build/dex/trader-joe-v2_1/trader-joe-v2_1.js.map +1 -0
- package/build/dex/trader-joe-v2_1/types.d.ts +82 -0
- package/build/dex/trader-joe-v2_1/types.js +9 -0
- package/build/dex/trader-joe-v2_1/types.js.map +1 -0
- package/build/dex/uniswap-v3/config.js +1 -1
- package/build/dex/uniswap-v3/config.js.map +1 -1
- package/build/dex/uniswap-v3/uniswap-v3.js +1 -1
- package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
- package/build/dex/wombat/wombat-pool-poller.d.ts +22 -0
- package/build/dex/wombat/wombat-pool-poller.js +164 -0
- package/build/dex/wombat/wombat-pool-poller.js.map +1 -0
- package/build/dex-helper/RedisBatcher.d.ts +20 -0
- package/build/dex-helper/RedisBatcher.js +75 -0
- package/build/dex-helper/RedisBatcher.js.map +1 -0
- package/package.json +1 -1
- package/src/dex/hashflow/constants.ts +32 -0
- package/src/dex/hashflow/hashflow.ts +131 -19
- package/src/dex/hashflow/types.ts +20 -2
- package/src/dex/index.ts +2 -0
- package/src/dex/solidly/config.ts +14 -0
- package/src/dex/solidly/forks-override/pharaohV1.ts +10 -0
- package/src/dex/solidly/solidly-e2e.test.ts +21 -0
- package/src/dex/solidly/solidly-integration.test.ts +143 -0
- package/src/dex/solidly/solidly.ts +1 -0
- package/src/dex/uniswap-v3/config.ts +1 -1
- package/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +2 -2
- package/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +2 -2
- package/src/dex/uniswap-v3/uniswap-v3.ts +1 -1
- package/tests/constants-e2e.ts +5 -0
- package/build/abi/algebra/AlgebraPool.abi.json +0 -727
- package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
- package/build/abi/uniswap-v3/UniswapV3Quoter.abi.json +0 -193
- package/build/dex/algebra/algebra-pool.d.ts +0 -46
- package/build/dex/algebra/algebra-pool.js +0 -336
- package/build/dex/algebra/algebra-pool.js.map +0 -1
- package/build/dex/quickswap/camelot-v3.d.ts +0 -6
- package/build/dex/quickswap/camelot-v3.js +0 -19
- package/build/dex/quickswap/camelot-v3.js.map +0 -1
- package/build/dex/quickswap/zyberswap-v3.d.ts +0 -6
- package/build/dex/quickswap/zyberswap-v3.js +0 -19
- package/build/dex/quickswap/zyberswap-v3.js.map +0 -1
- package/build/dex/uniswap-v2/rebase-tokens.json +0 -7
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -64
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
|
@@ -20,3 +20,35 @@ export const HASHFLOW_GAS_COST = 100_000;
|
|
|
20
20
|
|
|
21
21
|
export const HASHFLOW_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION =
|
|
22
22
|
new BigNumber('0.001');
|
|
23
|
+
|
|
24
|
+
export const RESTRICT_79_TTL_MS = 60 * 30 * 1000; // 30 mins
|
|
25
|
+
export const RESTRICT_SLIPPAGE_TTL_MS = 60 * 30 * 1000; // 30 mins
|
|
26
|
+
export const RESTRICT_84_TTL_MS = 60 * 10 * 1000; // 10 mins
|
|
27
|
+
export const RESTRICT_76_TTL_MS = 60 * 30 * 1000; // 30 mins
|
|
28
|
+
export const RESTRICT_82_TTL_MS = 60 * 30 * 1000; // 30 mins
|
|
29
|
+
export const RESTRICT_42_TTL_MS = 60 * 60 * 1000; // 60 mins
|
|
30
|
+
export const RESTRICT_85_TTL_MS = 60 * 20 * 1000; // 20 mins
|
|
31
|
+
export const RESTRICT_74_TTL_MS = 60 * 20 * 1000; // 20 mins
|
|
32
|
+
export const RESTRICT_UNKNOWN_TTL_MS = 60 * 60 * 1000; // 30 mins
|
|
33
|
+
export const RESTRICT_MISSING_QUOTE_DATA_TTL_MS = 60 * 10 * 1000; // 10 mins
|
|
34
|
+
export const RESTRICT_MISSING_SIGNATURE_TTL_MS = 60 * 10 * 1000; // 10 mins
|
|
35
|
+
|
|
36
|
+
export const UNKNOWN_ERROR_CODE = 'UNKNOWN';
|
|
37
|
+
|
|
38
|
+
export const ERROR_CODE_TO_RESTRICT_TTL = {
|
|
39
|
+
'79': RESTRICT_79_TTL_MS, // {"code":79,"message":"Below minimum amount"}
|
|
40
|
+
SLIPPAGE: RESTRICT_SLIPPAGE_TTL_MS, // Error: Hashflow-56: too much slippage on quote SELL quoteTokenAmount 800317519410129900 / destAmount 848781022570196154 < 0.995
|
|
41
|
+
'84': RESTRICT_84_TTL_MS, // {"code":84,"message":"Rate Limit"}
|
|
42
|
+
'76': RESTRICT_76_TTL_MS, // {"code":76,"message":"Exceeds supported amounts"}
|
|
43
|
+
'82': RESTRICT_82_TTL_MS, // {"code":82,"message":"No maker supports this request"}
|
|
44
|
+
'42': RESTRICT_42_TTL_MS, // {"code":42,"message":"Unknown error"}
|
|
45
|
+
'85': RESTRICT_85_TTL_MS, // {"code":85,"message":"Markets too volatile"}
|
|
46
|
+
'74': RESTRICT_74_TTL_MS, // {"code":74,"message":"No maker could quote"}
|
|
47
|
+
MISSING_QUOTE_DATA: RESTRICT_MISSING_QUOTE_DATA_TTL_MS, // missing quote data
|
|
48
|
+
MISSING_SIGNATURE_DATA: RESTRICT_MISSING_SIGNATURE_TTL_MS, // missing signature
|
|
49
|
+
[UNKNOWN_ERROR_CODE]: RESTRICT_UNKNOWN_TTL_MS, // unknown error
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// not actually consecutive, meaning is if the error appeared > CONSECUTIVE_ERROR_THRESHOLD times within CONSECUTIVE_ERROR_TIMESPAN_MS ms -> restrict mm for ERROR_CODE_TO_RESTRICT_TTL[errorCode] ms
|
|
53
|
+
export const CONSECUTIVE_ERROR_TIMESPAN_MS = 60 * 60 * 1000; // 1 hour
|
|
54
|
+
export const CONSECUTIVE_ERROR_THRESHOLD = 3;
|
|
@@ -33,11 +33,14 @@ import {
|
|
|
33
33
|
SimpleExchangeParam,
|
|
34
34
|
Token,
|
|
35
35
|
} from '../../types';
|
|
36
|
-
import { getDexKeysWithNetwork } from '../../utils';
|
|
36
|
+
import { getDexKeysWithNetwork, Utils } from '../../utils';
|
|
37
37
|
import { TooStrictSlippageCheckError } from '../generic-rfq/types';
|
|
38
38
|
import { SimpleExchange } from '../simple-exchange';
|
|
39
39
|
import { Adapters, HashflowConfig } from './config';
|
|
40
40
|
import {
|
|
41
|
+
CONSECUTIVE_ERROR_THRESHOLD,
|
|
42
|
+
CONSECUTIVE_ERROR_TIMESPAN_MS,
|
|
43
|
+
ERROR_CODE_TO_RESTRICT_TTL,
|
|
41
44
|
HASHFLOW_API_CLIENT_NAME,
|
|
42
45
|
HASHFLOW_API_MARKET_MAKERS_POLLING_INTERVAL_MS,
|
|
43
46
|
HASHFLOW_API_PRICES_POLLING_INTERVAL_MS,
|
|
@@ -48,9 +51,12 @@ import {
|
|
|
48
51
|
HASHFLOW_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION,
|
|
49
52
|
HASHFLOW_MM_RESTRICT_TTL_S,
|
|
50
53
|
HASHFLOW_PRICES_CACHES_TTL_S,
|
|
54
|
+
UNKNOWN_ERROR_CODE,
|
|
51
55
|
} from './constants';
|
|
52
56
|
import { RateFetcher } from './rate-fetcher';
|
|
53
57
|
import {
|
|
58
|
+
CacheErrorCodesData,
|
|
59
|
+
ErrorCode,
|
|
54
60
|
HashflowData,
|
|
55
61
|
PriceLevel,
|
|
56
62
|
RfqError,
|
|
@@ -69,6 +75,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
|
|
|
69
75
|
private hashFlowAuthToken: string;
|
|
70
76
|
private disabledMMs: Set<string>;
|
|
71
77
|
private runtimeMMsRestrictHashMapKey: string;
|
|
78
|
+
private runtimeMMsRestrictHashMapErrorCodesKey: string;
|
|
72
79
|
|
|
73
80
|
private pricesCacheKey: string;
|
|
74
81
|
private marketMakersCacheKey: string;
|
|
@@ -108,6 +115,8 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
|
|
|
108
115
|
this.disabledMMs = new Set(dexHelper.config.data.hashFlowDisabledMMs);
|
|
109
116
|
this.runtimeMMsRestrictHashMapKey =
|
|
110
117
|
`${CACHE_PREFIX}_${this.dexKey}_${this.network}_restricted_mms`.toLowerCase();
|
|
118
|
+
this.runtimeMMsRestrictHashMapErrorCodesKey =
|
|
119
|
+
`${CACHE_PREFIX}_${this.dexKey}_${this.network}_restricted_mms_error_codes`.toLowerCase();
|
|
111
120
|
|
|
112
121
|
this.rateFetcher = new RateFetcher(
|
|
113
122
|
this.dexHelper,
|
|
@@ -595,7 +604,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
|
|
|
595
604
|
normalizedDestToken.address,
|
|
596
605
|
)}: ${JSON.stringify(rfq)}`;
|
|
597
606
|
this.logger.warn(message);
|
|
598
|
-
throw new RfqError(message);
|
|
607
|
+
throw new RfqError(message, `${rfq?.error?.code}` as ErrorCode);
|
|
599
608
|
} else if (!rfq.quotes[0].quoteData) {
|
|
600
609
|
const message = `${this.dexKey}-${
|
|
601
610
|
this.network
|
|
@@ -604,7 +613,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
|
|
|
604
613
|
normalizedDestToken.address,
|
|
605
614
|
)}. Missing quote data`;
|
|
606
615
|
this.logger.warn(message);
|
|
607
|
-
throw new RfqError(message);
|
|
616
|
+
throw new RfqError(message, 'MISSING_QUOTE_DATA');
|
|
608
617
|
} else if (!rfq.quotes[0].signature) {
|
|
609
618
|
const message = `${this.dexKey}-${
|
|
610
619
|
this.network
|
|
@@ -613,7 +622,7 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
|
|
|
613
622
|
normalizedDestToken.address,
|
|
614
623
|
)}. Missing signature`;
|
|
615
624
|
this.logger.warn(message);
|
|
616
|
-
throw new RfqError(message);
|
|
625
|
+
throw new RfqError(message, 'MISSING_SIGNATURE_DATA');
|
|
617
626
|
}
|
|
618
627
|
|
|
619
628
|
assert(
|
|
@@ -729,7 +738,13 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
|
|
|
729
738
|
this.logger.warn(
|
|
730
739
|
`${this.dexKey}-${this.network} MM unknown preprocess transaction error: ${e}`,
|
|
731
740
|
);
|
|
732
|
-
|
|
741
|
+
const code =
|
|
742
|
+
e instanceof RfqError || e instanceof SlippageCheckError
|
|
743
|
+
? e?.code || UNKNOWN_ERROR_CODE
|
|
744
|
+
: UNKNOWN_ERROR_CODE;
|
|
745
|
+
await this.restrictMM(mm, code).catch(err =>
|
|
746
|
+
this.logger.warn(`Failed to restrict MM ${mm}: ${err}`),
|
|
747
|
+
);
|
|
733
748
|
}
|
|
734
749
|
}
|
|
735
750
|
|
|
@@ -737,24 +752,121 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
|
|
|
737
752
|
}
|
|
738
753
|
}
|
|
739
754
|
|
|
740
|
-
async restrictMM(mm: string): Promise<void> {
|
|
741
|
-
this.
|
|
742
|
-
|
|
743
|
-
);
|
|
744
|
-
|
|
745
|
-
// We use timestamp for creation date to later discern if it already expired or not
|
|
746
|
-
await this.dexHelper.cache.hset(
|
|
747
|
-
this.runtimeMMsRestrictHashMapKey,
|
|
755
|
+
async restrictMM(mm: string, errorCode: ErrorCode): Promise<void> {
|
|
756
|
+
const errorCodesRaw = await this.dexHelper.cache.hget(
|
|
757
|
+
this.runtimeMMsRestrictHashMapErrorCodesKey,
|
|
748
758
|
mm,
|
|
749
|
-
Date.now().toString(),
|
|
750
759
|
);
|
|
751
760
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
761
|
+
const errorCodes: CacheErrorCodesData = Utils.Parse(errorCodesRaw) || {};
|
|
762
|
+
|
|
763
|
+
const error = errorCodes?.[errorCode];
|
|
764
|
+
|
|
765
|
+
if (
|
|
766
|
+
!error ||
|
|
767
|
+
error.addedDatetimeMS + CONSECUTIVE_ERROR_TIMESPAN_MS < Date.now()
|
|
768
|
+
) {
|
|
769
|
+
this.logger.warn(
|
|
770
|
+
`${this.dexKey}-${this.network}: First encounter of error code=${errorCode} for ${mm} OR error ocurred outside of threshold, setting up counter`,
|
|
756
771
|
);
|
|
757
|
-
|
|
772
|
+
const data: CacheErrorCodesData = {
|
|
773
|
+
...errorCodes,
|
|
774
|
+
[errorCode]: {
|
|
775
|
+
count: 1,
|
|
776
|
+
addedDatetimeMS: Date.now(),
|
|
777
|
+
},
|
|
778
|
+
};
|
|
779
|
+
await this.dexHelper.cache.hset(
|
|
780
|
+
this.runtimeMMsRestrictHashMapErrorCodesKey,
|
|
781
|
+
mm,
|
|
782
|
+
Utils.Serialize(data),
|
|
783
|
+
);
|
|
784
|
+
return;
|
|
785
|
+
} else {
|
|
786
|
+
const restrictTTLMs =
|
|
787
|
+
ERROR_CODE_TO_RESTRICT_TTL[errorCode] ||
|
|
788
|
+
ERROR_CODE_TO_RESTRICT_TTL[UNKNOWN_ERROR_CODE];
|
|
789
|
+
|
|
790
|
+
if (error.count + 1 > CONSECUTIVE_ERROR_THRESHOLD) {
|
|
791
|
+
this.logger.warn(
|
|
792
|
+
`${this.dexKey}-${this.network}: ${mm} was restricted for ${
|
|
793
|
+
restrictTTLMs / 1000
|
|
794
|
+
} sec. due to ${errorCode} happening ${
|
|
795
|
+
error.count + 1
|
|
796
|
+
} times within last ${Math.floor(
|
|
797
|
+
CONSECUTIVE_ERROR_TIMESPAN_MS / 1000 / 60,
|
|
798
|
+
)} minutes`,
|
|
799
|
+
);
|
|
800
|
+
|
|
801
|
+
// date added is checked against HASHFLOW_MM_RESTRICT_TTL_S, as a hack we set a date so that it's checked against specific ttls based on error type to not change parsing logic for mms
|
|
802
|
+
// Example: ttl for a particular error is 20 minutes (< default 60 minutes)
|
|
803
|
+
//
|
|
804
|
+
// Meaning we need to set `addedDatetimeMS` for restrict hash as Date.now() + 40 minutes (diff between default restrict ttl=1h and particular error restrict ttl = 20 minutes). So the `addedDatetimeMS` is in the future, and after 20 minutes mm will not be considered as restricted
|
|
805
|
+
//
|
|
806
|
+
//
|
|
807
|
+
// Example 2: ttl for a particular error is 80 minutes (> default 60 minutes)
|
|
808
|
+
//
|
|
809
|
+
// Meaning we need to set `addedDatetimeMS` for restrict hash as Date.now() - 20 minutes, then after an hour (default) it'll still be 20 minutes left for restriction to be cleared
|
|
810
|
+
|
|
811
|
+
const defaultRestrictTTLMS = Math.floor(
|
|
812
|
+
HASHFLOW_MM_RESTRICT_TTL_S * 1000,
|
|
813
|
+
);
|
|
814
|
+
const dateModifierMS =
|
|
815
|
+
defaultRestrictTTLMS > restrictTTLMs
|
|
816
|
+
? defaultRestrictTTLMS - restrictTTLMs
|
|
817
|
+
: -(restrictTTLMs - defaultRestrictTTLMS);
|
|
818
|
+
|
|
819
|
+
const date = (Date.now() + dateModifierMS).toString();
|
|
820
|
+
|
|
821
|
+
// We use timestamp for creation date to later discern if it already expired or not
|
|
822
|
+
await this.dexHelper.cache.hset(
|
|
823
|
+
this.runtimeMMsRestrictHashMapKey,
|
|
824
|
+
mm,
|
|
825
|
+
date,
|
|
826
|
+
);
|
|
827
|
+
|
|
828
|
+
// resetting error count
|
|
829
|
+
const data: CacheErrorCodesData = {
|
|
830
|
+
...errorCodes,
|
|
831
|
+
[errorCode]: {
|
|
832
|
+
count: 1,
|
|
833
|
+
addedDatetimeMS: Date.now(),
|
|
834
|
+
},
|
|
835
|
+
};
|
|
836
|
+
await this.dexHelper.cache.hset(
|
|
837
|
+
this.runtimeMMsRestrictHashMapErrorCodesKey,
|
|
838
|
+
mm,
|
|
839
|
+
Utils.Serialize(data),
|
|
840
|
+
);
|
|
841
|
+
|
|
842
|
+
// Expiry cache because it has levels for blacklisted MM
|
|
843
|
+
await this.dexHelper.cache
|
|
844
|
+
.del(this.dexKey, this.network, 'levels')
|
|
845
|
+
.catch(e => {
|
|
846
|
+
this.logger.error(
|
|
847
|
+
`${this.dexKey}-${this.network}: Failed to delete levels cache: ${e.message}`,
|
|
848
|
+
);
|
|
849
|
+
});
|
|
850
|
+
return;
|
|
851
|
+
} else {
|
|
852
|
+
const newCount = +error.count + 1;
|
|
853
|
+
this.logger.warn(
|
|
854
|
+
`${this.dexKey}-${this.network}: ${mm} Error with code: ${errorCode} happened ${newCount} times (below or equal to the limit: ${CONSECUTIVE_ERROR_THRESHOLD}), updating counter`,
|
|
855
|
+
);
|
|
856
|
+
const data: CacheErrorCodesData = {
|
|
857
|
+
...errorCodes,
|
|
858
|
+
[errorCode]: {
|
|
859
|
+
count: newCount,
|
|
860
|
+
addedDatetimeMS: error.addedDatetimeMS, // initial date stays
|
|
861
|
+
},
|
|
862
|
+
};
|
|
863
|
+
await this.dexHelper.cache.hset(
|
|
864
|
+
this.runtimeMMsRestrictHashMapErrorCodesKey,
|
|
865
|
+
mm,
|
|
866
|
+
Utils.Serialize(data),
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
758
870
|
}
|
|
759
871
|
|
|
760
872
|
getCalldataGasCost(poolPrices: PoolPrices<HashflowData>): number | number[] {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Chain, QuoteData } from '@hashflow/taker-js/dist/types/common';
|
|
2
2
|
import { RequestHeaders } from '../../dex-helper';
|
|
3
|
+
import { ERROR_CODE_TO_RESTRICT_TTL, UNKNOWN_ERROR_CODE } from './constants';
|
|
3
4
|
|
|
4
5
|
export type HashflowData = {
|
|
5
6
|
mm: string;
|
|
@@ -16,14 +17,22 @@ export interface PriceLevel {
|
|
|
16
17
|
p: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export class RfqError extends Error {
|
|
20
|
+
export class RfqError extends Error {
|
|
21
|
+
code: ErrorCode;
|
|
22
|
+
constructor(message: string, code: ErrorCode = UNKNOWN_ERROR_CODE) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.code = code;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
20
27
|
|
|
21
28
|
export enum RFQType {
|
|
22
29
|
RFQT = 0,
|
|
23
30
|
RFQM = 1,
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
export class SlippageCheckError extends Error {
|
|
33
|
+
export class SlippageCheckError extends Error {
|
|
34
|
+
code: ErrorCode = 'SLIPPAGE';
|
|
35
|
+
}
|
|
27
36
|
|
|
28
37
|
export type HashflowRatesLevel = {
|
|
29
38
|
pair: Record<string, string>;
|
|
@@ -63,3 +72,12 @@ export type HashflowRateFetcherConfig = {
|
|
|
63
72
|
marketMakersCacheTTLSecs: number;
|
|
64
73
|
};
|
|
65
74
|
};
|
|
75
|
+
|
|
76
|
+
export type ErrorCode = keyof typeof ERROR_CODE_TO_RESTRICT_TTL;
|
|
77
|
+
|
|
78
|
+
export type CacheErrorCodesData = {
|
|
79
|
+
[code in ErrorCode]: {
|
|
80
|
+
addedDatetimeMS: number;
|
|
81
|
+
count: number;
|
|
82
|
+
} | null;
|
|
83
|
+
};
|
package/src/dex/index.ts
CHANGED
|
@@ -85,6 +85,7 @@ import { Dexalot } from './dexalot/dexalot';
|
|
|
85
85
|
import { Smardex } from './smardex/smardex';
|
|
86
86
|
import { Wombat } from './wombat/wombat';
|
|
87
87
|
import { Swell } from './swell/swell';
|
|
88
|
+
import { PharaohV1 } from './solidly/forks-override/pharaohV1';
|
|
88
89
|
import { EtherFi } from './etherfi';
|
|
89
90
|
|
|
90
91
|
const LegacyDexes = [
|
|
@@ -168,6 +169,7 @@ const Dexes = [
|
|
|
168
169
|
Smardex,
|
|
169
170
|
Wombat,
|
|
170
171
|
Swell,
|
|
172
|
+
PharaohV1,
|
|
171
173
|
];
|
|
172
174
|
|
|
173
175
|
export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder<
|
|
@@ -159,6 +159,20 @@ export const SolidlyConfig: DexConfigMap<DexParams> = {
|
|
|
159
159
|
feeCode: 0,
|
|
160
160
|
},
|
|
161
161
|
},
|
|
162
|
+
PharaohV1: {
|
|
163
|
+
[Network.AVALANCHE]: {
|
|
164
|
+
subgraphURL:
|
|
165
|
+
'https://api.studio.thegraph.com/query/66247/pharaoh-legacy/version/latest',
|
|
166
|
+
factoryAddress: '0xAAA16c016BF556fcD620328f0759252E29b1AB57',
|
|
167
|
+
router: '0x609AcD8Fc955Dd7E744c7DFFc9930a7A6654DE43',
|
|
168
|
+
initCode:
|
|
169
|
+
'0xbf2404274de2b11f05e5aebd49e508de933034cb5fa2d0ac3de8cbd4bcef47dc',
|
|
170
|
+
poolGasCost: 180 * 1000,
|
|
171
|
+
stableFee: 5,
|
|
172
|
+
volatileFee: 25,
|
|
173
|
+
feeCode: 0,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
162
176
|
Equalizer: {
|
|
163
177
|
[Network.FANTOM]: {
|
|
164
178
|
factoryAddress: '0xc6366EFD0AF1d09171fe0EBF32c7943BB310832a',
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Network } from '../../../constants';
|
|
2
|
+
import { getDexKeysWithNetwork } from '../../../utils';
|
|
3
|
+
import { SolidlyConfig } from '../config';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import { Ramses } from './ramses';
|
|
6
|
+
|
|
7
|
+
export class PharaohV1 extends Ramses {
|
|
8
|
+
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
9
|
+
getDexKeysWithNetwork(_.pick(SolidlyConfig, ['PharaohV1']));
|
|
10
|
+
}
|
|
@@ -1245,6 +1245,27 @@ describe('Solidly E2E', () => {
|
|
|
1245
1245
|
});
|
|
1246
1246
|
});
|
|
1247
1247
|
});
|
|
1248
|
+
|
|
1249
|
+
describe('PharaohV1', () => {
|
|
1250
|
+
const dexKey = 'PharaohV1';
|
|
1251
|
+
|
|
1252
|
+
const tokenASymbol: string = 'USDC';
|
|
1253
|
+
const tokenBSymbol: string = 'WAVAX';
|
|
1254
|
+
|
|
1255
|
+
const tokenAAmount: string = '100000';
|
|
1256
|
+
const tokenBAmount: string = '100000000000000000';
|
|
1257
|
+
const nativeTokenAmount = '100000000000000000';
|
|
1258
|
+
|
|
1259
|
+
testForNetwork(
|
|
1260
|
+
network,
|
|
1261
|
+
dexKey,
|
|
1262
|
+
tokenASymbol,
|
|
1263
|
+
tokenBSymbol,
|
|
1264
|
+
tokenAAmount,
|
|
1265
|
+
tokenBAmount,
|
|
1266
|
+
nativeTokenAmount,
|
|
1267
|
+
);
|
|
1268
|
+
});
|
|
1248
1269
|
});
|
|
1249
1270
|
|
|
1250
1271
|
describe('Arbitrum', () => {
|
|
@@ -19,6 +19,7 @@ import { VelodromeV2 } from './forks-override/velodromeV2';
|
|
|
19
19
|
import { Equalizer } from './forks-override/equalizer';
|
|
20
20
|
import { Velocimeter } from './forks-override/velocimeter';
|
|
21
21
|
import { Usdfi } from './forks-override/usdfi';
|
|
22
|
+
import { PharaohV1 } from './forks-override/pharaohV1';
|
|
22
23
|
|
|
23
24
|
const amounts18 = [0n, BI_POWS[18], 2000000000000000000n];
|
|
24
25
|
const amounts6 = [0n, BI_POWS[6], 2000000n];
|
|
@@ -1443,6 +1444,148 @@ describe('Solidly integration tests', () => {
|
|
|
1443
1444
|
});
|
|
1444
1445
|
});
|
|
1445
1446
|
|
|
1447
|
+
describe('Avalanche', () => {
|
|
1448
|
+
const network = Network.AVALANCHE;
|
|
1449
|
+
const dexHelper = new DummyDexHelper(network);
|
|
1450
|
+
const checkOnChainPricing = constructCheckOnChainPricing(dexHelper);
|
|
1451
|
+
|
|
1452
|
+
describe('PharaohV1', function () {
|
|
1453
|
+
const dexKey = 'PharaohV1';
|
|
1454
|
+
const pharaohV1 = new PharaohV1(network, dexKey, dexHelper);
|
|
1455
|
+
|
|
1456
|
+
describe('UniswapV2 like pool', function () {
|
|
1457
|
+
const TokenASymbol = 'USDC';
|
|
1458
|
+
const tokenA = Tokens[network][TokenASymbol];
|
|
1459
|
+
const TokenBSymbol = 'WAVAX';
|
|
1460
|
+
const tokenB = Tokens[network][TokenBSymbol];
|
|
1461
|
+
|
|
1462
|
+
const amounts = amounts18;
|
|
1463
|
+
|
|
1464
|
+
it('getPoolIdentifiers and getPricesVolume', async function () {
|
|
1465
|
+
const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
|
|
1466
|
+
const pools = await pharaohV1.getPoolIdentifiers(
|
|
1467
|
+
tokenA,
|
|
1468
|
+
tokenB,
|
|
1469
|
+
SwapSide.SELL,
|
|
1470
|
+
blocknumber,
|
|
1471
|
+
);
|
|
1472
|
+
console.log(
|
|
1473
|
+
`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `,
|
|
1474
|
+
pools,
|
|
1475
|
+
);
|
|
1476
|
+
|
|
1477
|
+
expect(pools.length).toBeGreaterThan(0);
|
|
1478
|
+
|
|
1479
|
+
console.log('AMOUNTS: ', amounts);
|
|
1480
|
+
|
|
1481
|
+
const poolPrices = await pharaohV1.getPricesVolume(
|
|
1482
|
+
tokenA,
|
|
1483
|
+
tokenB,
|
|
1484
|
+
amounts,
|
|
1485
|
+
SwapSide.SELL,
|
|
1486
|
+
blocknumber,
|
|
1487
|
+
pools,
|
|
1488
|
+
);
|
|
1489
|
+
console.log(
|
|
1490
|
+
`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `,
|
|
1491
|
+
util.inspect(poolPrices, false, null, true),
|
|
1492
|
+
);
|
|
1493
|
+
|
|
1494
|
+
expect(poolPrices).not.toBeNull();
|
|
1495
|
+
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);
|
|
1496
|
+
|
|
1497
|
+
// Check if onchain pricing equals to calculated ones
|
|
1498
|
+
|
|
1499
|
+
for (const poolPrice of poolPrices || []) {
|
|
1500
|
+
await checkOnChainPricing(
|
|
1501
|
+
pharaohV1,
|
|
1502
|
+
'getAmountOut',
|
|
1503
|
+
blocknumber,
|
|
1504
|
+
poolPrice.prices,
|
|
1505
|
+
poolPrice.poolAddresses![0],
|
|
1506
|
+
tokenA.address,
|
|
1507
|
+
amounts,
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1512
|
+
it('getTopPoolsForToken', async function () {
|
|
1513
|
+
const poolLiquidity = await pharaohV1.getTopPoolsForToken(
|
|
1514
|
+
tokenA.address,
|
|
1515
|
+
10,
|
|
1516
|
+
);
|
|
1517
|
+
console.log(`${TokenASymbol} Top Pools:`, poolLiquidity);
|
|
1518
|
+
|
|
1519
|
+
checkPoolsLiquidity(poolLiquidity, tokenA.address, dexKey);
|
|
1520
|
+
});
|
|
1521
|
+
});
|
|
1522
|
+
|
|
1523
|
+
describe('Curve like stable pool', function () {
|
|
1524
|
+
const TokenASymbol = 'USDT';
|
|
1525
|
+
const tokenA = Tokens[network][TokenASymbol];
|
|
1526
|
+
const TokenBSymbol = 'USDC';
|
|
1527
|
+
const tokenB = Tokens[network][TokenBSymbol];
|
|
1528
|
+
|
|
1529
|
+
const amounts = amounts6;
|
|
1530
|
+
|
|
1531
|
+
it('getPoolIdentifiers and getPricesVolume', async function () {
|
|
1532
|
+
const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
|
|
1533
|
+
const pools = await pharaohV1.getPoolIdentifiers(
|
|
1534
|
+
tokenA,
|
|
1535
|
+
tokenB,
|
|
1536
|
+
SwapSide.SELL,
|
|
1537
|
+
blocknumber,
|
|
1538
|
+
);
|
|
1539
|
+
console.log(
|
|
1540
|
+
`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `,
|
|
1541
|
+
pools,
|
|
1542
|
+
);
|
|
1543
|
+
|
|
1544
|
+
expect(pools.length).toBeGreaterThan(0);
|
|
1545
|
+
|
|
1546
|
+
const poolPrices = await pharaohV1.getPricesVolume(
|
|
1547
|
+
tokenA,
|
|
1548
|
+
tokenB,
|
|
1549
|
+
amounts,
|
|
1550
|
+
SwapSide.SELL,
|
|
1551
|
+
blocknumber,
|
|
1552
|
+
pools,
|
|
1553
|
+
);
|
|
1554
|
+
console.log(
|
|
1555
|
+
`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `,
|
|
1556
|
+
poolPrices,
|
|
1557
|
+
);
|
|
1558
|
+
|
|
1559
|
+
expect(poolPrices).not.toBeNull();
|
|
1560
|
+
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);
|
|
1561
|
+
|
|
1562
|
+
// Check if onchain pricing equals to calculated ones
|
|
1563
|
+
for (const poolPrice of poolPrices || []) {
|
|
1564
|
+
await checkOnChainPricing(
|
|
1565
|
+
pharaohV1,
|
|
1566
|
+
'getAmountOut',
|
|
1567
|
+
blocknumber,
|
|
1568
|
+
poolPrice.prices,
|
|
1569
|
+
poolPrice.poolAddresses![0],
|
|
1570
|
+
tokenA.address,
|
|
1571
|
+
amounts,
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
});
|
|
1575
|
+
|
|
1576
|
+
it('getTopPoolsForToken', async function () {
|
|
1577
|
+
const poolLiquidity = await pharaohV1.getTopPoolsForToken(
|
|
1578
|
+
tokenA.address,
|
|
1579
|
+
10,
|
|
1580
|
+
);
|
|
1581
|
+
console.log(`${TokenASymbol} Top Pools:`, poolLiquidity);
|
|
1582
|
+
|
|
1583
|
+
checkPoolsLiquidity(poolLiquidity, tokenA.address, dexKey);
|
|
1584
|
+
});
|
|
1585
|
+
});
|
|
1586
|
+
});
|
|
1587
|
+
});
|
|
1588
|
+
|
|
1446
1589
|
describe('Optimism', () => {
|
|
1447
1590
|
const network = Network.OPTIMISM;
|
|
1448
1591
|
const dexHelper = new DummyDexHelper(network);
|
|
@@ -261,7 +261,7 @@ export const UniswapV3Config: DexConfigMap<DexParams> = {
|
|
|
261
261
|
'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph',
|
|
262
262
|
},
|
|
263
263
|
},
|
|
264
|
-
|
|
264
|
+
PharaohV2: {
|
|
265
265
|
[Network.AVALANCHE]: {
|
|
266
266
|
factory: '0xAAA32926fcE6bE95ea2c51cB4Fcb60836D320C42',
|
|
267
267
|
deployer: '0x95120704f4E2D545Aea8b6B3c16d9Da1fa32E30F',
|
|
@@ -696,8 +696,8 @@ describe('UniswapV3 E2E', () => {
|
|
|
696
696
|
});
|
|
697
697
|
});
|
|
698
698
|
|
|
699
|
-
describe('
|
|
700
|
-
const dexKey = '
|
|
699
|
+
describe('PharaohV2', () => {
|
|
700
|
+
const dexKey = 'PharaohV2';
|
|
701
701
|
|
|
702
702
|
describe('Avalanche', () => {
|
|
703
703
|
const network = Network.AVALANCHE;
|
|
@@ -613,8 +613,8 @@ describe('RamsesV2', () => {
|
|
|
613
613
|
});
|
|
614
614
|
});
|
|
615
615
|
|
|
616
|
-
describe('
|
|
617
|
-
const dexKey = '
|
|
616
|
+
describe('PharaohV2', () => {
|
|
617
|
+
const dexKey = 'PharaohV2';
|
|
618
618
|
let blockNumber: number;
|
|
619
619
|
let uniswapV3: UniswapV3;
|
|
620
620
|
let uniswapV3Mainnet: UniswapV3;
|
package/tests/constants-e2e.ts
CHANGED
|
@@ -669,6 +669,10 @@ export const Tokens: {
|
|
|
669
669
|
},
|
|
670
670
|
},
|
|
671
671
|
[Network.AVALANCHE]: {
|
|
672
|
+
PHAR: {
|
|
673
|
+
address: '0xAAAB9D12A30504559b0C5a9A5977fEE4A6081c6b',
|
|
674
|
+
decimals: 18,
|
|
675
|
+
},
|
|
672
676
|
USDCe: {
|
|
673
677
|
address: '0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664',
|
|
674
678
|
decimals: 6,
|
|
@@ -1236,6 +1240,7 @@ export const Holders: {
|
|
|
1236
1240
|
YUSD: '0x6c1a5ef2acde1fd2fc68def440d2c1eb35bae24a',
|
|
1237
1241
|
BTCb: '0x84c06d3c27821d0136f66306f5028d43ceac268d',
|
|
1238
1242
|
AMPL: '0xfcaA5ea7F8eb0631BcA72C345025C0A5a6D93f0E',
|
|
1243
|
+
PHAR: '0x654296D56532f62B7d91d335791d3c364a9385b5',
|
|
1239
1244
|
},
|
|
1240
1245
|
[Network.ARBITRUM]: {
|
|
1241
1246
|
SEN: '0xcb19b6b4971bd4206bab176c75b1efe3e28ee5a8',
|