diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index be9eb13a05..db1daf1b5a 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "6.5.0", + "changes": [ + { + "note": "Add Kyber DMM to Ethereum mainnet", + "pr": 194 + } + ] + }, { "version": "6.4.0", "changes": [ diff --git a/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts b/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts index 33b97a09a3..8c7252bc32 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/bridge_source_utils.ts @@ -7,6 +7,7 @@ import { CRYPTO_COM_ROUTER_BY_CHAIN_ID, ELLIPSIS_BSC_INFOS, KYBER_BRIDGED_LIQUIDITY_PREFIX, + KYBER_DMM_ROUTER_BY_CHAIN_ID, MAINNET_CURVE_INFOS, MAINNET_SNOWSWAP_INFOS, MAINNET_SWERVE_INFOS, @@ -176,7 +177,8 @@ export function uniswapV2LikeRouterAddress( | ERC20BridgeSource.SushiSwap | ERC20BridgeSource.CryptoCom | ERC20BridgeSource.PancakeSwap - | ERC20BridgeSource.BakerySwap, + | ERC20BridgeSource.BakerySwap + | ERC20BridgeSource.KyberDmm, ): string { switch (source) { case ERC20BridgeSource.UniswapV2: @@ -189,6 +191,8 @@ export function uniswapV2LikeRouterAddress( return PANCAKESWAP_ROUTER_BY_CHAIN_ID[chainId]; case ERC20BridgeSource.BakerySwap: return BAKERYSWAP_ROUTER_BY_CHAIN_ID[chainId]; + case ERC20BridgeSource.KyberDmm: + return KYBER_DMM_ROUTER_BY_CHAIN_ID[chainId]; default: throw new Error(`Unknown UniswapV2 like source ${source}`); } diff --git a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts index 780571ff44..e823455908 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -82,6 +82,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId( ERC20BridgeSource.CryptoCom, ERC20BridgeSource.Linkswap, ERC20BridgeSource.MakerPsm, + ERC20BridgeSource.KyberDmm, ]), [ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]), [ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]), @@ -132,6 +133,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId( ERC20BridgeSource.CryptoCom, ERC20BridgeSource.Linkswap, ERC20BridgeSource.MakerPsm, + ERC20BridgeSource.KyberDmm, ]), [ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]), [ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]), @@ -163,7 +165,7 @@ export const PROTOCOL_FEE_MULTIPLIER = new BigNumber(70000); */ export const FEE_QUOTE_SOURCES_BY_CHAIN_ID = valueByChainId( { - [ChainId.Mainnet]: [ERC20BridgeSource.Uniswap, ERC20BridgeSource.UniswapV2], + [ChainId.Mainnet]: [ERC20BridgeSource.UniswapV2, ERC20BridgeSource.SushiSwap], [ChainId.BSC]: [ERC20BridgeSource.PancakeSwap, ERC20BridgeSource.Mooniswap, ERC20BridgeSource.SushiSwap], }, [], @@ -660,6 +662,13 @@ export const OASIS_ROUTER_BY_CHAIN_ID = valueByChainId( NULL_ADDRESS, ); +export const KYBER_DMM_ROUTER_BY_CHAIN_ID = valueByChainId( + { + [ChainId.Mainnet]: '0x12807818B584a3Fa65D38B6C25B13983fE888D6E', + }, + NULL_ADDRESS, +); + export const MOONISWAP_REGISTRIES_BY_CHAIN_ID = valueByChainId( { [ChainId.Mainnet]: [ @@ -933,6 +942,15 @@ export const DEFAULT_GAS_SCHEDULE: Required = { } return gas; }, + [ERC20BridgeSource.KyberDmm]: (fillData?: FillData) => { + // TODO: Different base cost if to/from ETH. + let gas = 95e3; + const path = (fillData as UniswapV2FillData).tokenAddressPath; + if (path.length > 2) { + gas += (path.length - 2) * 65e3; // +65k for each hop. + } + return gas; + }, // // BSC // diff --git a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts index 2d3e26d39b..790e4fd6be 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -89,6 +89,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s return encodeBridgeSourceId(BridgeProtocol.Dodo, 'Dodo'); case ERC20BridgeSource.Kyber: return encodeBridgeSourceId(BridgeProtocol.Kyber, 'Kyber'); + case ERC20BridgeSource.KyberDmm: + return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'KyberDmm'); case ERC20BridgeSource.LiquidityProvider: // "LiquidityProvider" is too long to encode (17 characters). return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP'); @@ -176,6 +178,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder case ERC20BridgeSource.Linkswap: case ERC20BridgeSource.PancakeSwap: case ERC20BridgeSource.BakerySwap: + case ERC20BridgeSource.KyberDmm: const uniswapV2FillData = (order as OptimizedMarketBridgeOrder).fillData; bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]); break; @@ -305,6 +308,7 @@ export const BRIDGE_ENCODERS: { [ERC20BridgeSource.SushiSwap]: routerAddressPathEncoder, [ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder, [ERC20BridgeSource.Linkswap]: routerAddressPathEncoder, + [ERC20BridgeSource.KyberDmm]: routerAddressPathEncoder, // Generic pools [ERC20BridgeSource.Shell]: poolEncoder, [ERC20BridgeSource.Mooniswap]: poolEncoder, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index c6423afb63..6032fb2b03 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -1022,6 +1022,7 @@ export class SamplerOperations { case ERC20BridgeSource.CryptoCom: case ERC20BridgeSource.PancakeSwap: case ERC20BridgeSource.BakerySwap: + case ERC20BridgeSource.KyberDmm: const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); if (!isValidAddress(uniLikeRouter)) { return []; @@ -1213,6 +1214,7 @@ export class SamplerOperations { case ERC20BridgeSource.CryptoCom: case ERC20BridgeSource.PancakeSwap: case ERC20BridgeSource.BakerySwap: + case ERC20BridgeSource.KyberDmm: const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); if (!isValidAddress(uniLikeRouter)) { return []; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/types.ts b/packages/asset-swapper/src/utils/market_operation_utils/types.ts index f992f95d6c..816d3e640b 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -59,6 +59,7 @@ export enum ERC20BridgeSource { DodoV2 = 'DODO_V2', CryptoCom = 'CryptoCom', Linkswap = 'Linkswap', + KyberDmm = 'KyberDMM', // Other PancakeSwap = 'PancakeSwap', BakerySwap = 'BakerySwap', diff --git a/packages/asset-swapper/test/market_operation_utils_test.ts b/packages/asset-swapper/test/market_operation_utils_test.ts index 81659ff193..6a3e9e8e21 100644 --- a/packages/asset-swapper/test/market_operation_utils_test.ts +++ b/packages/asset-swapper/test/market_operation_utils_test.ts @@ -68,6 +68,7 @@ const DEFAULT_EXCLUDED = [ ERC20BridgeSource.PancakeSwap, ERC20BridgeSource.BakerySwap, ERC20BridgeSource.MakerPsm, + ERC20BridgeSource.KyberDmm, ]; const BUY_SOURCES = BUY_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources; const SELL_SOURCES = SELL_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources; @@ -282,32 +283,12 @@ describe('MarketOperationUtils tests', () => { [source: string]: Numberish[]; } - const ZERO_RATES: RatesBySource = { - [ERC20BridgeSource.Native]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Eth2Dai]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Uniswap]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Kyber]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.UniswapV2]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Balancer]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Bancor]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Curve]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.LiquidityProvider]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.MStable]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Mooniswap]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Swerve]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.SnowSwap]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.SushiSwap]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.MultiHop]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Shell]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Cream]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Dodo]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.DodoV2]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.CryptoCom]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.Linkswap]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.PancakeSwap]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.BakerySwap]: _.times(NUM_SAMPLES, () => 0), - [ERC20BridgeSource.MakerPsm]: _.times(NUM_SAMPLES, () => 0), - }; + const ZERO_RATES: RatesBySource = Object.assign( + {}, + ...Object.values(ERC20BridgeSource).map(source => ({ + [source]: _.times(NUM_SAMPLES, () => 0), + })), + ); const DEFAULT_RATES: RatesBySource = { ...ZERO_RATES, @@ -372,6 +353,7 @@ describe('MarketOperationUtils tests', () => { [ERC20BridgeSource.Uniswap]: { router: randomAddress() }, [ERC20BridgeSource.Eth2Dai]: { router: randomAddress() }, [ERC20BridgeSource.MakerPsm]: {}, + [ERC20BridgeSource.KyberDmm]: { tokenAddressPath: [] }, }; const DEFAULT_OPS = {