diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index 220f102276..5cb99b3977 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "16.35.0", + "changes": [ + { + "note": "Add Beethoven X, MorpheusSwap and JetSwap to Fantom", + "pr": 370 + } + ] + }, { "version": "16.34.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 1ebbbfa32e..c4d7cdde13 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 @@ -30,6 +30,7 @@ import { KYBER_BRIDGED_LIQUIDITY_PREFIX, MAX_DODOV2_POOLS_QUERIED, MAX_KYBER_RESERVES_QUERIED, + MORPHEUSSWAP_ROUTER_BY_CHAIN_ID, MSTABLE_POOLS_BY_CHAIN_ID, NERVE_BSC_INFOS, NULL_ADDRESS, @@ -488,6 +489,7 @@ export function uniswapV2LikeRouterAddress( | ERC20BridgeSource.TraderJoe | ERC20BridgeSource.Pangolin | ERC20BridgeSource.UbeSwap + | ERC20BridgeSource.MorpheusSwap | ERC20BridgeSource.SpookySwap | ERC20BridgeSource.SpiritSwap, ): string { @@ -532,6 +534,8 @@ export function uniswapV2LikeRouterAddress( return TRADER_JOE_ROUTER_BY_CHAIN_ID[chainId]; case ERC20BridgeSource.UbeSwap: return UBESWAP_ROUTER_BY_CHAIN_ID[chainId]; + case ERC20BridgeSource.MorpheusSwap: + return MORPHEUSSWAP_ROUTER_BY_CHAIN_ID[chainId]; case ERC20BridgeSource.SpookySwap: return SPOOKYSWAP_ROUTER_BY_CHAIN_ID[chainId]; case ERC20BridgeSource.SpiritSwap: 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 34cbddf791..85e17bf449 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -171,8 +171,11 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId( ]), [ChainId.Fantom]: new SourceFilters([ ERC20BridgeSource.MultiHop, + ERC20BridgeSource.Beethovenx, ERC20BridgeSource.Curve, ERC20BridgeSource.CurveV2, + ERC20BridgeSource.JetSwap, + ERC20BridgeSource.MorpheusSwap, ERC20BridgeSource.SpiritSwap, ERC20BridgeSource.SpookySwap, ERC20BridgeSource.SushiSwap, @@ -294,8 +297,11 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId( ]), [ChainId.Fantom]: new SourceFilters([ ERC20BridgeSource.MultiHop, + ERC20BridgeSource.Beethovenx, ERC20BridgeSource.Curve, ERC20BridgeSource.CurveV2, + ERC20BridgeSource.JetSwap, + ERC20BridgeSource.MorpheusSwap, ERC20BridgeSource.SpiritSwap, ERC20BridgeSource.SpookySwap, ERC20BridgeSource.SushiSwap, @@ -1618,6 +1624,13 @@ export const BALANCER_V2_VAULT_ADDRESS_BY_CHAIN = valueByChainId( NULL_ADDRESS, ); +export const BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN = valueByChainId( + { + [ChainId.Fantom]: '0x20dd72ed959b6147912c2e529f0a0c651c33c9ce', + }, + NULL_ADDRESS, +); + export const LIDO_INFO_BY_CHAIN = valueByChainId( { [ChainId.Mainnet]: { @@ -1642,6 +1655,13 @@ export const BALANCER_V2_SUBGRAPH_URL_BY_CHAIN = valueByChainId( 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2', ); +export const BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN = valueByChainId( + { + [ChainId.Fantom]: 'https://graph-node.beets-ftm-node.com/subgraphs/name/beethovenx-v4', + }, + 'https://graph-node.beets-ftm-node.com/subgraphs/name/beethovenx-v4', +); + export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId( { [ChainId.Mainnet]: { @@ -1752,6 +1772,7 @@ export const JETSWAP_ROUTER_BY_CHAIN_ID = valueByChainId( { [ChainId.BSC]: '0xbe65b8f75b9f20f4c522e0067a3887fada714800', [ChainId.Polygon]: '0x5c6ec38fb0e2609672bdf628b1fd605a523e5923', + [ChainId.Fantom]: '0x845e76a8691423fbc4ecb8dd77556cb61c09ee25', }, NULL_ADDRESS, ); @@ -1777,6 +1798,13 @@ export const UBESWAP_ROUTER_BY_CHAIN_ID = valueByChainId( NULL_ADDRESS, ); +export const MORPHEUSSWAP_ROUTER_BY_CHAIN_ID = valueByChainId( + { + [ChainId.Fantom]: '0x8ac868293d97761a1fed6d4a01e9ff17c5594aa3', + }, + NULL_ADDRESS, +); + export const SPIRITSWAP_ROUTER_BY_CHAIN_ID = valueByChainId( { [ChainId.Fantom]: '0x16327e3fbdaca3bcf7e38f5af2599d2ddc33ae52', @@ -1950,8 +1978,10 @@ export const DEFAULT_GAS_SCHEDULE: Required = { // // Fantom // + [ERC20BridgeSource.MorpheusSwap]: uniswapV2CloneGasSchedule, [ERC20BridgeSource.SpiritSwap]: uniswapV2CloneGasSchedule, [ERC20BridgeSource.SpookySwap]: uniswapV2CloneGasSchedule, + [ERC20BridgeSource.Beethovenx]: () => 100e3, }; export const DEFAULT_FEE_SCHEDULE: Required = { ...DEFAULT_GAS_SCHEDULE }; 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 7eb0d888e7..fedca1c258 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -186,10 +186,14 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'TraderJoe'); case ERC20BridgeSource.UbeSwap: return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'UbeSwap'); + case ERC20BridgeSource.Beethovenx: + return encodeBridgeSourceId(BridgeProtocol.BalancerV2, 'Beethovenx'); case ERC20BridgeSource.SpiritSwap: return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SpiritSwap'); case ERC20BridgeSource.SpookySwap: return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SpookySwap'); + case ERC20BridgeSource.MorpheusSwap: + return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MorpheusSwap'); default: throw new Error(AggregationError.NoBridgeForSource); } @@ -238,6 +242,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder bridgeData = encoder.encode([balancerFillData.poolAddress]); break; case ERC20BridgeSource.BalancerV2: + case ERC20BridgeSource.Beethovenx: const balancerV2FillData = (order as OptimizedMarketBridgeOrder).fillData; const { vault, poolId } = balancerV2FillData; bridgeData = encoder.encode([vault, poolId]); @@ -269,6 +274,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder case ERC20BridgeSource.UbeSwap: case ERC20BridgeSource.SpiritSwap: case ERC20BridgeSource.SpookySwap: + case ERC20BridgeSource.MorpheusSwap: const uniswapV2FillData = (order as OptimizedMarketBridgeOrder).fillData; bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]); break; @@ -461,6 +467,7 @@ export const BRIDGE_ENCODERS: { [ERC20BridgeSource.TraderJoe]: routerAddressPathEncoder, [ERC20BridgeSource.SpiritSwap]: routerAddressPathEncoder, [ERC20BridgeSource.SpookySwap]: routerAddressPathEncoder, + [ERC20BridgeSource.MorpheusSwap]: routerAddressPathEncoder, // Celo [ERC20BridgeSource.UbeSwap]: routerAddressPathEncoder, // BSC @@ -490,6 +497,7 @@ export const BRIDGE_ENCODERS: { // Custom integrations [ERC20BridgeSource.MakerPsm]: makerPsmEncoder, [ERC20BridgeSource.BalancerV2]: balancerV2Encoder, + [ERC20BridgeSource.Beethovenx]: balancerV2Encoder, [ERC20BridgeSource.UniswapV3]: AbiEncoder.create([ { name: 'router', type: 'address' }, { name: 'path', type: 'bytes' }, 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 3a468070fc..da51b1ebd3 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 @@ -20,6 +20,8 @@ import { import { BALANCER_V2_VAULT_ADDRESS_BY_CHAIN, BANCOR_REGISTRY_BY_CHAIN_ID, + BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN, + BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN, DODOV1_CONFIG_BY_CHAIN_ID, DODOV2_FACTORIES_BY_CHAIN_ID, KYBER_CONFIG_BY_CHAIN_ID, @@ -122,6 +124,10 @@ export class SamplerOperations { ? poolsCaches : { [ERC20BridgeSource.BalancerV2]: new BalancerV2PoolsCache(chainId), + [ERC20BridgeSource.Beethovenx]: new BalancerV2PoolsCache( + chainId, + BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN[chainId], + ), [ERC20BridgeSource.Balancer]: new BalancerPoolsCache(), [ERC20BridgeSource.Cream]: new CreamPoolsCache(), }; @@ -1200,6 +1206,7 @@ export class SamplerOperations { case ERC20BridgeSource.UbeSwap: case ERC20BridgeSource.SpiritSwap: case ERC20BridgeSource.SpookySwap: + case ERC20BridgeSource.MorpheusSwap: const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); if (!isValidAddress(uniLikeRouter)) { return []; @@ -1301,13 +1308,14 @@ export class SamplerOperations { ), ); case ERC20BridgeSource.BalancerV2: + case ERC20BridgeSource.Beethovenx: const poolIds = - this.poolsCaches[ERC20BridgeSource.BalancerV2].getCachedPoolAddressesForPair( - takerToken, - makerToken, - ) || []; + this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || []; - const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]; + const vault = + source === ERC20BridgeSource.BalancerV2 + ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId] + : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; if (vault === NULL_ADDRESS) { return []; } @@ -1317,10 +1325,9 @@ export class SamplerOperations { makerToken, takerToken, takerFillAmounts, - ERC20BridgeSource.BalancerV2, + source, ), ); - case ERC20BridgeSource.Cream: return ( this.poolsCaches[ERC20BridgeSource.Cream].getCachedPoolAddressesForPair( @@ -1472,6 +1479,7 @@ export class SamplerOperations { case ERC20BridgeSource.UbeSwap: case ERC20BridgeSource.SpiritSwap: case ERC20BridgeSource.SpookySwap: + case ERC20BridgeSource.MorpheusSwap: const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); if (!isValidAddress(uniLikeRouter)) { return []; @@ -1573,13 +1581,14 @@ export class SamplerOperations { ), ); case ERC20BridgeSource.BalancerV2: + case ERC20BridgeSource.Beethovenx: const poolIds = - this.poolsCaches[ERC20BridgeSource.BalancerV2].getCachedPoolAddressesForPair( - takerToken, - makerToken, - ) || []; + this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || []; - const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]; + const vault = + source === ERC20BridgeSource.BalancerV2 + ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId] + : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; if (vault === NULL_ADDRESS) { return []; } @@ -1589,7 +1598,7 @@ export class SamplerOperations { makerToken, takerToken, makerFillAmounts, - ERC20BridgeSource.BalancerV2, + source, ), ); case ERC20BridgeSource.Cream: 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 f3e0f50be2..a05fbedc49 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -97,8 +97,14 @@ export enum ERC20BridgeSource { // Fantom SpiritSwap = 'SpiritSwap', SpookySwap = 'SpookySwap', + Beethovenx = 'Beethovenx', + MorpheusSwap = 'MorpheusSwap', } -export type SourcesWithPoolsCache = ERC20BridgeSource.Balancer | ERC20BridgeSource.BalancerV2 | ERC20BridgeSource.Cream; +export type SourcesWithPoolsCache = + | ERC20BridgeSource.Balancer + | ERC20BridgeSource.BalancerV2 + | ERC20BridgeSource.Beethovenx + | ERC20BridgeSource.Cream; // tslint:disable: enum-naming /**