diff --git a/jest.config.js b/jest.config.js index dd748e9226..f72369feda 100644 --- a/jest.config.js +++ b/jest.config.js @@ -21,7 +21,6 @@ module.exports = { 'src/connectors/uniswap/uniswap.config.ts', 'src/connectors/uniswap/uniswap.ts', 'src/connectors/uniswap/uniswap.lp.helper.ts', - 'src/connectors/defikingdoms/defikingdoms.ts', 'src/connectors/defira/defira.ts', 'src/connectors/openocean/openocean.ts', 'src/connectors/pangolin/pangolin.ts', diff --git a/package.json b/package.json index c4c0e1ec69..e00ed8c06a 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "@pangolindex/sdk": "^1.1.0", "@perp/sdk-curie": "^1.16.0", "@sushiswap/sdk": "^5.0.0-canary.116", - "@switchboard-xyz/defikingdoms-sdk": "^1.0.7", "@tinymanorg/tinyman-js-sdk": "^3.0.0", "@traderjoe-xyz/sdk-v2": "^2.0.5", "@types/fs-extra": "^9.0.13", diff --git a/src/amm/amm.controllers.ts b/src/amm/amm.controllers.ts index 74f3d927ab..23c0d434b2 100644 --- a/src/amm/amm.controllers.ts +++ b/src/amm/amm.controllers.ts @@ -65,12 +65,7 @@ import { RefAMMish, Uniswapish, UniswapLPish, - ZigZagish, } from '../services/common-interfaces'; -import { - price as zigzagPrice, - trade as zigzagTrade, -} from '../connectors/zigzag/zigzag.controllers'; import { Algorand } from '../chains/algorand/algorand'; import { Tinyman } from '../connectors/tinyman/tinyman'; @@ -79,8 +74,8 @@ export async function price(req: PriceRequest): Promise { req.chain, req.network ); - const connector: Uniswapish | RefAMMish | Tinyman | ZigZagish = - await getConnector( + const connector: Uniswapish | RefAMMish | Tinyman = + await getConnector( req.chain, req.network, req.connector @@ -89,8 +84,6 @@ export async function price(req: PriceRequest): Promise { // we currently use the presence of routerAbi to distinguish Uniswapish from RefAMMish if ('routerAbi' in connector) { return uniswapPrice(chain, connector, req); - } else if ('estimate' in connector) { - return zigzagPrice(chain, connector as any, req); } else if (connector instanceof Tinyman) { return tinymanPrice(chain as unknown as Algorand, connector, req); } else { @@ -103,8 +96,8 @@ export async function trade(req: TradeRequest): Promise { req.chain, req.network ); - const connector: Uniswapish | RefAMMish | Tinyman | ZigZagish = - await getConnector( + const connector: Uniswapish | RefAMMish | Tinyman = + await getConnector( req.chain, req.network, req.connector @@ -113,8 +106,6 @@ export async function trade(req: TradeRequest): Promise { // we currently use the presence of routerAbi to distinguish Uniswapish from RefAMMish if ('routerAbi' in connector) { return uniswapTrade(chain, connector, req); - } else if ('estimate' in connector) { - return zigzagTrade(chain, connector as any, req); } else if (connector instanceof Tinyman) { return tinymanTrade(chain as unknown as Algorand, connector, req); } else { diff --git a/src/chains/ethereum/ethereum.ts b/src/chains/ethereum/ethereum.ts index 915d6dfddb..383299a613 100644 --- a/src/chains/ethereum/ethereum.ts +++ b/src/chains/ethereum/ethereum.ts @@ -13,7 +13,6 @@ import { UniswapConfig } from '../../connectors/uniswap/uniswap.config'; import { Perp } from '../../connectors/perp/perp'; import { SushiswapConfig } from '../../connectors/sushiswap/sushiswap.config'; import { OpenoceanConfig } from '../../connectors/openocean/openocean.config'; -import { ZigZagConfig } from '../../connectors/zigzag/zigzag.config'; // MKR does not match the ERC20 perfectly so we need to use a separate ABI. const MKR_ADDRESS = '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2'; @@ -197,8 +196,6 @@ export class Ethereum extends EthereumBase implements Ethereumish { spender = perp.perp.contracts.vault.address; } else if (reqSpender === 'openocean') { spender = OpenoceanConfig.config.routerAddress('ethereum', this._chain); - } else if (reqSpender === 'zigzag') { - spender = ZigZagConfig.config.contractAddress(this._chain); } else { spender = reqSpender; } diff --git a/src/chains/ethereum/ethereum.validators.ts b/src/chains/ethereum/ethereum.validators.ts index d8d8e9f672..78d7df8454 100644 --- a/src/chains/ethereum/ethereum.validators.ts +++ b/src/chains/ethereum/ethereum.validators.ts @@ -57,13 +57,11 @@ export const validateSpender: Validator = mkValidator( val === 'viperswap' || val === 'openocean' || val === 'quickswap' || - val === 'defikingdoms' || val === 'defira' || val === 'mad_meerkat' || val === 'vvs' || val === 'pancakeswap' || val === 'xsswap' || - val === 'zigzag' || isAddress(val)) ); diff --git a/src/chains/harmony/harmony.ts b/src/chains/harmony/harmony.ts index fb994ca795..9a1288cde9 100644 --- a/src/chains/harmony/harmony.ts +++ b/src/chains/harmony/harmony.ts @@ -146,9 +146,7 @@ export class Harmony extends EthereumBase implements Ethereumish { getSpender(reqSpender: string): string { let spender: string; - if (reqSpender === 'defikingdoms') { - spender = '0x24ad62502d1C652Cc7684081169D04896aC20f30'; - } else if (reqSpender === 'defira') { + if (reqSpender === 'defira') { spender = '0x3C8BF7e25EbfAaFb863256A4380A8a93490d8065'; } else if (reqSpender === 'openocean') { spender = OpenoceanConfig.config.routerAddress('ethereum', this._chain); diff --git a/src/chains/harmony/harmony.validators.ts b/src/chains/harmony/harmony.validators.ts index 44ac944a5d..c3111bd5e5 100644 --- a/src/chains/harmony/harmony.validators.ts +++ b/src/chains/harmony/harmony.validators.ts @@ -43,8 +43,6 @@ export const validateSpender: Validator = mkValidator( (val) => typeof val === 'string' && (val === 'sushiswap' || - val === 'viperswap' || - val === 'defikingdoms' || val === 'defira' || val === 'openocean' || isValidAddress(val)) diff --git a/src/connectors/connectors.routes.ts b/src/connectors/connectors.routes.ts index 7cf67624c0..2c3244cd7a 100644 --- a/src/connectors/connectors.routes.ts +++ b/src/connectors/connectors.routes.ts @@ -3,7 +3,6 @@ import { Router, Response } from 'express'; import { asyncHandler } from '../services/error-handler'; import { DefiraConfig } from './defira/defira.config'; -import { DefikingdomsConfig } from './defikingdoms/defikingdoms.config'; import { MadMeerkatConfig } from './mad_meerkat/mad_meerkat.config'; import { OpenoceanConfig } from './openocean/openocean.config'; import { PangolinConfig } from './pangolin/pangolin.config'; @@ -19,7 +18,6 @@ import { InjectiveCLOBConfig } from './injective/injective.clob.config'; import { XsswapConfig } from './xsswap/xsswap.config'; import { ConnectorsResponse } from './connectors.request'; import { DexalotCLOBConfig } from './dexalot/dexalot.clob.config'; -import { ZigZagConfig } from './zigzag/zigzag.config'; import { TinymanConfig } from './tinyman/tinyman.config'; export namespace ConnectorsRoutes { @@ -81,12 +79,6 @@ export namespace ConnectorsRoutes { chain_type: TraderjoeConfig.config.chainType, available_networks: TraderjoeConfig.config.availableNetworks, }, - { - name: 'defikingdoms', - trading_type: DefikingdomsConfig.config.tradingTypes, - chain_type: DefikingdomsConfig.config.chainType, - available_networks: DefikingdomsConfig.config.availableNetworks, - }, { name: 'defira', trading_type: DefiraConfig.config.tradingTypes, @@ -153,12 +145,6 @@ export namespace ConnectorsRoutes { 'Enter a Dexalot API Key if you have one, otherwise hit return >>> ', }, }, - { - name: 'zigzag', - trading_type: ZigZagConfig.config.tradingTypes, - chain_type: ZigZagConfig.config.chainType, - available_networks: ZigZagConfig.config.availableNetworks, - }, { name: 'tinyman', trading_type: TinymanConfig.config.tradingTypes, diff --git a/src/connectors/defikingdoms/defikingdoms.config.ts b/src/connectors/defikingdoms/defikingdoms.config.ts deleted file mode 100644 index cd6ffd041c..0000000000 --- a/src/connectors/defikingdoms/defikingdoms.config.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ConfigManagerV2 } from '../../services/config-manager-v2'; -import { AvailableNetworks } from '../../services/config-manager-types'; -export namespace DefikingdomsConfig { - export interface NetworkConfig { - allowedSlippage: string; - gasLimit: number; - ttl: number; - routerAddress: (network: string) => string; - tradingTypes: Array; - chainType: string; - availableNetworks: Array; - } - - export const config: NetworkConfig = { - allowedSlippage: ConfigManagerV2.getInstance().get( - `defikingdoms.allowedSlippage` - ), - gasLimit: ConfigManagerV2.getInstance().get(`defikingdoms.gasLimit`), - ttl: ConfigManagerV2.getInstance().get(`defikingdoms.ttl`), - routerAddress: (network: string) => - ConfigManagerV2.getInstance().get( - `defikingdoms.contractAddresses.${network}.routerAddress` - ), - tradingTypes: ['AMM'], - chainType: 'EVM', - availableNetworks: [ - { - chain: 'harmony', - networks: ['mainnet'], - }, - ], - }; -} diff --git a/src/connectors/defikingdoms/defikingdoms.ts b/src/connectors/defikingdoms/defikingdoms.ts deleted file mode 100644 index a1d2460b07..0000000000 --- a/src/connectors/defikingdoms/defikingdoms.ts +++ /dev/null @@ -1,291 +0,0 @@ -import { UniswapishPriceError } from '../../services/error-handler'; -import { isFractionString } from '../../services/validators'; -import { DefikingdomsConfig } from './defikingdoms.config'; -import routerAbi from './defikingdoms_router_abi.json'; -import { - Contract, - ContractInterface, - ContractTransaction, -} from '@ethersproject/contracts'; -import { - Fetcher, - Percent, - Router, - Token, - TokenAmount, - Trade, - Pair, - SwapParameters, - // } from '@defikingdoms/sdk'; -} from '@switchboard-xyz/defikingdoms-sdk'; -import { BigNumber, Transaction, Wallet } from 'ethers'; -import { logger } from '../../services/logger'; -import { percentRegexp } from '../../services/config-manager-v2'; -// import { Ethereum } from '../../chains/ethereum/ethereum'; -import { ExpectedTrade, Uniswapish } from '../../services/common-interfaces'; -import { Harmony } from '../../chains/harmony/harmony'; - -export class Defikingdoms implements Uniswapish { - private static _instances: { [name: string]: Defikingdoms }; - private harmony: Harmony; - private _router: string; - private _routerAbi: ContractInterface; - private _gasLimitEstimate: number; - private _ttl: number; - private chainId; - private tokenList: Record = {}; - private _ready: boolean = false; - - private constructor(network: string) { - const config = DefikingdomsConfig.config; - this.harmony = Harmony.getInstance(network); - this.chainId = this.harmony.chainId; - this._ttl = DefikingdomsConfig.config.ttl; - this._routerAbi = routerAbi.abi; - this._gasLimitEstimate = DefikingdomsConfig.config.gasLimit; - this._router = config.routerAddress(network); - } - - public static getInstance(chain: string, network: string): Defikingdoms { - if (Defikingdoms._instances === undefined) { - Defikingdoms._instances = {}; - } - if (!(chain + network in Defikingdoms._instances)) { - // eslint-disable-next-line prettier/prettier - Defikingdoms._instances[chain + network] = new Defikingdoms(network); - } - - return Defikingdoms._instances[chain + network]; - } - - /** - * Given a token's address, return the connector's native representation of - * the token. - * - * @param address Token address - */ - public getTokenByAddress(address: string): Token { - return this.tokenList[address]; - } - - public async init() { - if (!this.harmony.ready()) { - await this.harmony.init(); - } - for (const token of this.harmony.storedTokenList) { - this.tokenList[token.address] = new Token( - this.chainId, - token.address, - token.decimals, - token.symbol, - token.name - ); - } - this._ready = true; - } - - public ready(): boolean { - return this._ready; - } - - /** - * Router address. - */ - public get router(): string { - return this._router; - } - - /** - * Router smart contract ABI. - */ - public get routerAbi(): ContractInterface { - return this._routerAbi; - } - - /** - * Default gas limit for swap transactions. - */ - public get gasLimitEstimate(): number { - return this._gasLimitEstimate; - } - - /** - * Default time-to-live for swap transactions, in seconds. - */ - public get ttl(): number { - return this._ttl; - } - - /** - * Gets the allowed slippage percent from the optional parameter or the value - * in the configuration. - * - * @param allowedSlippageStr (Optional) should be of the form '1/10'. - */ - public getAllowedSlippage(allowedSlippageStr?: string): Percent { - if (allowedSlippageStr != null && isFractionString(allowedSlippageStr)) { - const fractionSplit = allowedSlippageStr.split('/'); - return new Percent(fractionSplit[0], fractionSplit[1]); - } - - const allowedSlippage = DefikingdomsConfig.config.allowedSlippage; - const nd = allowedSlippage.match(percentRegexp); - if (nd) return new Percent(nd[1], nd[2]); - throw new Error( - 'Encountered a malformed percent string in the config for ALLOWED_SLIPPAGE.' - ); - } - - /** - * Given the amount of `baseToken` to put into a transaction, calculate the - * amount of `quoteToken` that can be expected from the transaction. - * - * This is typically used for calculating token sell prices. - * - * @param baseToken Token input for the transaction - * @param quoteToken Output from the transaction - * @param amount Amount of `baseToken` to put into the transaction - */ - async estimateSellTrade( - baseToken: Token, - quoteToken: Token, - amount: BigNumber, - allowedSlippage?: string - ): Promise { - const nativeTokenAmount: TokenAmount = new TokenAmount( - baseToken, - amount.toString() - ); - logger.info( - `Fetching pair data for ${baseToken.address}-${quoteToken.address}.` - ); - - const pair: Pair = await this.fetchPairData(baseToken, quoteToken); - const trades: Trade[] = Trade.bestTradeExactIn( - [pair], - nativeTokenAmount, - quoteToken, - { maxHops: 1 } - ); - if (!trades || trades.length === 0) { - throw new UniswapishPriceError( - `priceSwapIn: no trade pair found for ${baseToken} to ${quoteToken}.` - ); - } - logger.info( - `Best trade for ${baseToken.address}-${quoteToken.address}: ` + - `${trades[0].executionPrice.toFixed(6)}` + - `${baseToken.name}.` - ); - const expectedAmount = trades[0].minimumAmountOut( - this.getAllowedSlippage(allowedSlippage) - ); - return { trade: trades[0], expectedAmount }; - } - - /** - * Given the amount of `baseToken` desired to acquire from a transaction, - * calculate the amount of `quoteToken` needed for the transaction. - * - * This is typically used for calculating token buy prices. - * - * @param quoteToken Token input for the transaction - * @param baseToken Token output from the transaction - * @param amount Amount of `baseToken` desired from the transaction - */ - async estimateBuyTrade( - quoteToken: Token, - baseToken: Token, - amount: BigNumber, - allowedSlippage?: string - ): Promise { - const nativeTokenAmount: TokenAmount = new TokenAmount( - baseToken, - amount.toString() - ); - logger.info( - `Fetching pair data for ${quoteToken.address}-${baseToken.address}.` - ); - logger.info( - JSON.stringify({ quoteToken, baseToken, provider: this.harmony.provider }) - ); - const pair: Pair = await this.fetchPairData(quoteToken, baseToken); - const trades: Trade[] = Trade.bestTradeExactOut( - [pair], - quoteToken, - nativeTokenAmount, - { maxHops: 1 } - ); - if (!trades || trades.length === 0) { - throw new UniswapishPriceError( - `priceSwapOut: no trade pair found for ${quoteToken.address} to ${baseToken.address}.` - ); - } - logger.info( - `Best trade for ${quoteToken.address}-${baseToken.address}: ` + - `${trades[0].executionPrice.invert().toFixed(6)} ` + - `${baseToken.name}.` - ); - - const expectedAmount = trades[0].maximumAmountIn( - this.getAllowedSlippage(allowedSlippage) - ); - return { trade: trades[0], expectedAmount }; - } - - /** - * Given a wallet and a Defikingdoms trade, try to execute it on blockchain. - * - * @param wallet Wallet - * @param trade Expected trade - * @param gasPrice Base gas price, for pre-EIP1559 transactions - * @param defikingdomsRouter Router smart contract address - * @param ttl How long the swap is valid before expiry, in seconds - * @param abi Router contract ABI - * @param gasLimit Gas limit - * @param nonce (Optional) EVM transaction nonce - */ - async executeTrade( - wallet: Wallet, - trade: Trade, - gasPrice: number, - defikingdomsRouter: string, - ttl: number, - abi: ContractInterface, - gasLimit: number, - nonce?: number, - _1?: BigNumber, - _2?: BigNumber, - allowedSlippage?: string - ): Promise { - const result: SwapParameters = Router.swapCallParameters(trade, { - ttl, - recipient: wallet.address, - allowedSlippage: this.getAllowedSlippage(allowedSlippage), - }); - - const contract: Contract = new Contract(defikingdomsRouter, abi, wallet); - return this.harmony.nonceManager.provideNonce( - nonce, - wallet.address, - async (nextNonce) => { - const tx: ContractTransaction = await contract[result.methodName]( - ...result.args, - { - gasPrice: (gasPrice * 1e9).toFixed(0), - gasLimit: gasLimit.toFixed(0), - value: result.value, - nonce: nextNonce, - } - ); - - logger.info(JSON.stringify(tx)); - return tx; - } - ); - } - - async fetchPairData(tokenA: Token, tokenB: Token): Promise { - return await Fetcher.fetchPairData(tokenA, tokenB, this.harmony.provider); - } -} diff --git a/src/connectors/defikingdoms/defikingdoms_router_abi.json b/src/connectors/defikingdoms/defikingdoms_router_abi.json deleted file mode 100644 index 5a0d96a6f1..0000000000 --- a/src/connectors/defikingdoms/defikingdoms_router_abi.json +++ /dev/null @@ -1,1625 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "name": "WETH", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenA", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenB", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountADesired", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountBDesired", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountAMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountBMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "addLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "amountA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountB", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountTokenDesired", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountTokenMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETHMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "addLiquidityETH", - "outputs": [ - { - "internalType": "uint256", - "name": "amountToken", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETH", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" - } - ], - "name": "getAmountIn", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" - } - ], - "name": "getAmountOut", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsIn", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsOut", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveB", - "type": "uint256" - } - ], - "name": "quote", - "outputs": [ - { - "internalType": "uint256", - "name": "amountB", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenA", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenB", - "type": "address" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountAMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountBMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "removeLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "amountA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountB", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountTokenMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETHMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "removeLiquidityETH", - "outputs": [ - { - "internalType": "uint256", - "name": "amountToken", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETH", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountTokenMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETHMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "removeLiquidityETHSupportingFeeOnTransferTokens", - "outputs": [ - { - "internalType": "uint256", - "name": "amountETH", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountTokenMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETHMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "approveMax", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "removeLiquidityETHWithPermit", - "outputs": [ - { - "internalType": "uint256", - "name": "amountToken", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETH", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountTokenMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountETHMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "approveMax", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "removeLiquidityETHWithPermitSupportingFeeOnTransferTokens", - "outputs": [ - { - "internalType": "uint256", - "name": "amountETH", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenA", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenB", - "type": "address" - }, - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountAMin", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountBMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "approveMax", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "removeLiquidityWithPermit", - "outputs": [ - { - "internalType": "uint256", - "name": "amountA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountB", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapETHForExactTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactETHForTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactETHForTokensSupportingFeeOnTransferTokens", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactTokensForETH", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactTokensForETHSupportingFeeOnTransferTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactTokensForTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactTokensForTokensSupportingFeeOnTransferTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapTokensForExactETH", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapTokensForExactTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "", - "opcodes": "", - "sourceMap": "" - }, - "deployedBytecode": { - "immutableReferences": {}, - "linkReferences": {}, - "object": "", - "opcodes": "", - "sourceMap": "" - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0In\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1In\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0Out\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1Out\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"Swap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint112\",\"name\":\"reserve0\",\"type\":\"uint112\"},{\"indexed\":false,\"internalType\":\"uint112\",\"name\":\"reserve1\",\"type\":\"uint112\"}],\"name\":\"Sync\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_LIQUIDITY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PERMIT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"burn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"reserve0\",\"type\":\"uint112\"},{\"internalType\":\"uint112\",\"name\":\"reserve1\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"blockTimestampLast\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"price0CumulativeLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"price1CumulativeLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"skim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0Out\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Out\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"swap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sync\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/interfaces/IUniswapV2Pair.sol\":\"IUniswapV2Pair\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IUniswapV2Pair.sol\":{\"keccak256\":\"0x3368b1700fc4a77b780967cdd03c731da787a99f054f69f4b404d3cd3691712d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://47521585cb5e7f2a8a1586b7d4f09e5ffc80929af8f9ed18012a1b4a82920b9f\",\"dweb:/ipfs/QmdHmVCdnyDq9GFDuRKXe69ATcY4ABXehHzoKRnzxtWNFv\"]}},\"version\":1}", - "interface": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount0", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount1", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "Burn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount0", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount1", - "type": "uint256" - } - ], - "name": "Mint", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount0In", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount1In", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount0Out", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount1Out", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "Swap", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint112", - "name": "reserve0", - "type": "uint112" - }, - { - "indexed": false, - "internalType": "uint112", - "name": "reserve1", - "type": "uint112" - } - ], - "name": "Sync", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MINIMUM_LIQUIDITY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "PERMIT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "burn", - "outputs": [ - { - "internalType": "uint256", - "name": "amount0", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getReserves", - "outputs": [ - { - "internalType": "uint112", - "name": "reserve0", - "type": "uint112" - }, - { - "internalType": "uint112", - "name": "reserve1", - "type": "uint112" - }, - { - "internalType": "uint32", - "name": "blockTimestampLast", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "kLast", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "mint", - "outputs": [ - { - "internalType": "uint256", - "name": "liquidity", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "price0CumulativeLast", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "price1CumulativeLast", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "skim", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount0Out", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1Out", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "swap", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "sync", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "token0", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "token1", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "" -} diff --git a/src/connectors/zigzag/zigzag.config.ts b/src/connectors/zigzag/zigzag.config.ts deleted file mode 100644 index f6f7f465d9..0000000000 --- a/src/connectors/zigzag/zigzag.config.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { AvailableNetworks } from '../../services/config-manager-types'; -import { ConfigManagerV2 } from '../../services/config-manager-v2'; - -export namespace ZigZagConfig { - export interface NetworkConfig { - contractAddress: (network: string) => string; - tradingTypes: Array; - chainType: string; - availableNetworks: Array; - } - - export const config: NetworkConfig = { - contractAddress: (network: string) => - ConfigManagerV2.getInstance().get( - `zigzag.networks.${network}.contractAddress` - ), - tradingTypes: ['AMM'], - chainType: 'EVM', - availableNetworks: [ - { - chain: 'ethereum', - networks: Object.keys( - ConfigManagerV2.getInstance().get('zigzag.networks') - ).filter((network) => - Object.keys( - ConfigManagerV2.getInstance().get('ethereum.networks') - ).includes(network) - ), - }, - ], - }; -} diff --git a/src/connectors/zigzag/zigzag.controllers.ts b/src/connectors/zigzag/zigzag.controllers.ts deleted file mode 100644 index f0bb95c994..0000000000 --- a/src/connectors/zigzag/zigzag.controllers.ts +++ /dev/null @@ -1,233 +0,0 @@ -import { ZigZagish, ZigZagTrade } from '../../services/common-interfaces'; -import { Ethereumish, Tokenish } from '../../services/common-interfaces'; -import { Token } from '@uniswap/sdk-core'; -import { TokenInfo } from '../../chains/ethereum/ethereum-base'; -import Decimal from 'decimal.js-light'; -import { Transaction, utils, Wallet } from 'ethers'; -import { - HttpException, - TOKEN_NOT_SUPPORTED_ERROR_CODE, - TOKEN_NOT_SUPPORTED_ERROR_MESSAGE, - PRICE_FAILED_ERROR_CODE, - PRICE_FAILED_ERROR_MESSAGE, - UNKNOWN_ERROR_ERROR_CODE, - UNKNOWN_ERROR_MESSAGE, - SWAP_PRICE_LOWER_THAN_LIMIT_PRICE_ERROR_MESSAGE, - SWAP_PRICE_LOWER_THAN_LIMIT_PRICE_ERROR_CODE, - SWAP_PRICE_EXCEEDS_LIMIT_PRICE_ERROR_CODE, - SWAP_PRICE_EXCEEDS_LIMIT_PRICE_ERROR_MESSAGE, - LOAD_WALLET_ERROR_MESSAGE, - LOAD_WALLET_ERROR_CODE, -} from '../../services/error-handler'; -import { latency, gasCostInEthString } from '../../services/base'; -import { - PriceRequest, - PriceResponse, - TradeRequest, - TradeResponse, -} from '../../amm/amm.requests'; -import { logger } from '../../services/logger'; - -export function getFullTokenFromSymbol( - ethereumish: Ethereumish, - zigzagish: ZigZagish, - tokenSymbol: string -): Tokenish | Token { - const tokenInfo: TokenInfo | undefined = - ethereumish.getTokenBySymbol(tokenSymbol); - let fullToken: Tokenish | Token | undefined; - if (tokenInfo) { - fullToken = zigzagish.getTokenByAddress(tokenInfo.address); - } - if (!fullToken) - throw new HttpException( - 500, - TOKEN_NOT_SUPPORTED_ERROR_MESSAGE + tokenSymbol, - TOKEN_NOT_SUPPORTED_ERROR_CODE - ); - return fullToken; -} - -export async function price( - ethereumish: Ethereumish, - zigzagish: ZigZagish, - req: PriceRequest -): Promise { - const startTimestamp: number = Date.now(); - let baseToken, quoteToken, rawAmount; - if (req.side === 'SELL') { - baseToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.base); - quoteToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.quote); - rawAmount = utils.parseUnits(req.amount, baseToken.decimals); - } else { - baseToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.quote); - quoteToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.base); - rawAmount = utils.parseUnits(req.amount, quoteToken.decimals); - } - - let tradePrice; - - try { - const tradeInfo = await zigzagish.estimate( - baseToken, - quoteToken, - rawAmount, - req.side.toLowerCase() - ); - tradePrice = tradeInfo.newSwapPrice; - } catch (e) { - if (e instanceof Error) { - throw new HttpException( - 500, - PRICE_FAILED_ERROR_MESSAGE + e.message, - PRICE_FAILED_ERROR_CODE - ); - } else { - throw new HttpException( - 500, - UNKNOWN_ERROR_MESSAGE, - UNKNOWN_ERROR_ERROR_CODE - ); - } - } - - const gasLimitTransaction = ethereumish.gasLimitTransaction; - const gasPrice = ethereumish.gasPrice; - const gasLimitEstimate = 150688; - return { - network: ethereumish.chain, - timestamp: startTimestamp, - latency: latency(startTimestamp, Date.now()), - base: baseToken.address, - quote: quoteToken.address, - amount: req.amount, - rawAmount: rawAmount.toString(), - expectedAmount: String(tradePrice * Number(req.amount)), - price: String(tradePrice), - gasPrice: gasPrice, - gasPriceToken: ethereumish.nativeTokenSymbol, - gasLimit: gasLimitTransaction, - gasCost: gasCostInEthString(gasPrice, gasLimitEstimate), - }; -} - -export async function trade( - ethereumish: Ethereumish, - zigzagish: ZigZagish, - req: TradeRequest -): Promise { - const startTimestamp: number = Date.now(); - let baseToken, quoteToken, rawAmount; - if (req.side === 'SELL') { - baseToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.base); - quoteToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.quote); - rawAmount = utils.parseUnits(req.amount, baseToken.decimals); - } else { - baseToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.quote); - quoteToken = getFullTokenFromSymbol(ethereumish, zigzagish, req.base); - rawAmount = utils.parseUnits(req.amount, quoteToken.decimals); - } - - const limitPrice = req.limitPrice; - - // Get wallet - let wallet: Wallet; - try { - wallet = await ethereumish.getWallet(req.address); - } catch (err) { - logger.error(`Wallet ${req.address} not available.`); - throw new HttpException( - 500, - LOAD_WALLET_ERROR_MESSAGE + err, - LOAD_WALLET_ERROR_CODE - ); - } - - // Get route data - const tradeInfo: ZigZagTrade = await zigzagish.estimate( - baseToken, - quoteToken, - rawAmount, - req.side.toLowerCase() - ); - const price: number = tradeInfo.newSwapPrice; - - // Basic price check - if ( - req.side === 'BUY' && - limitPrice && - new Decimal(price.toString()).gt(new Decimal(limitPrice)) - ) { - logger.error('Swap price exceeded limit price.'); - throw new HttpException( - 500, - SWAP_PRICE_EXCEEDS_LIMIT_PRICE_ERROR_MESSAGE( - price.toString(), - limitPrice - ), - SWAP_PRICE_EXCEEDS_LIMIT_PRICE_ERROR_CODE - ); - } else if ( - req.side === 'SELL' && - limitPrice && - new Decimal(price.toString()).lt(new Decimal(limitPrice)) - ) { - logger.error('Swap price lower than limit price.'); - throw new HttpException( - 500, - SWAP_PRICE_LOWER_THAN_LIMIT_PRICE_ERROR_MESSAGE( - price.toString(), - limitPrice - ), - SWAP_PRICE_LOWER_THAN_LIMIT_PRICE_ERROR_CODE - ); - } - - // Price info log - logger.info( - `Expected execution price is ${price.toString()}, ` + - `limit price is ${limitPrice}.` - ); - - // Execute trade - const tx: Transaction = await zigzagish.executeTrade( - wallet.address, - tradeInfo, - rawAmount, - req.side === 'BUY' - ); - - const gasPrice: number = ethereumish.gasPrice; - - // Save Tx - if (tx.hash) { - await ethereumish.txStorage.saveTx( - ethereumish.chain, - ethereumish.chainId, - tx.hash, - new Date(), - gasPrice - ); - } - - logger.info( - `Trade has been executed, txHash is ${tx.hash}, nonce is ${tx.nonce}, gasPrice is ${gasPrice}.` - ); - - return { - network: ethereumish.chain, - timestamp: startTimestamp, - latency: latency(startTimestamp, Date.now()), - base: baseToken.address, - quote: quoteToken.address, - amount: new Decimal(req.amount).toFixed(baseToken.decimals), - rawAmount: rawAmount.toString(), - price: price.toString(), - gasPrice: gasPrice, - gasPriceToken: ethereumish.nativeTokenSymbol, - gasLimit: ethereumish.gasLimitTransaction, - gasCost: gasCostInEthString(gasPrice, ethereumish.gasLimitTransaction), - nonce: tx.nonce, - txHash: tx.hash, - }; -} diff --git a/src/connectors/zigzag/zigzag.exchange.abi.json b/src/connectors/zigzag/zigzag.exchange.abi.json deleted file mode 100644 index ee63dbaffd..0000000000 --- a/src/connectors/zigzag/zigzag.exchange.abi.json +++ /dev/null @@ -1,725 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "address", - "name": "fee_address", - "type": "address" - }, - { - "internalType": "address", - "name": "weth_address", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "orderHash", - "type": "bytes32" - } - ], - "name": "CancelOrder", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "orderHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "filled", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remaining", - "type": "uint256" - } - ], - "name": "OrderStatus", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "maker", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "taker", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "makerSellToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "takerSellToken", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "makerSellAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "takerSellAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "makerVolumeFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "takerVolumeFee", - "type": "uint256" - } - ], - "name": "Swap", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order", - "name": "order", - "type": "tuple" - } - ], - "name": "cancelOrder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "cancelled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order", - "name": "makerOrder", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "makerSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "takerSellAmount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fillAvailable", - "type": "bool" - } - ], - "name": "fillOrderExactInput", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order", - "name": "makerOrder", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "makerSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "takerSellAmount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fillAvailable", - "type": "bool" - } - ], - "name": "fillOrderExactInputETH", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order", - "name": "makerOrder", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "makerSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "takerBuyAmount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fillAvailable", - "type": "bool" - } - ], - "name": "fillOrderExactOutput", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order", - "name": "makerOrder", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "makerSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "takerBuyAmount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fillAvailable", - "type": "bool" - } - ], - "name": "fillOrderExactOutputETH", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order[]", - "name": "makerOrder", - "type": "tuple[]" - }, - { - "internalType": "bytes[]", - "name": "makerSignature", - "type": "bytes[]" - }, - { - "internalType": "uint256", - "name": "takerAmount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fillAvailable", - "type": "bool" - } - ], - "name": "fillOrderRoute", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order[]", - "name": "makerOrder", - "type": "tuple[]" - }, - { - "internalType": "bytes[]", - "name": "makerSignature", - "type": "bytes[]" - }, - { - "internalType": "uint256", - "name": "takerAmount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fillAvailable", - "type": "bool" - } - ], - "name": "fillOrderRouteETH", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "filled", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order", - "name": "order", - "type": "tuple" - } - ], - "name": "getOpenOrder", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "orderHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "orderSellFilledAmount", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.OrderInfo", - "name": "orderInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "address", - "name": "sellToken", - "type": "address" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "sellAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "buyAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expirationTimeSeconds", - "type": "uint256" - } - ], - "internalType": "struct LibOrder.Order", - "name": "order", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "isValidOrderSignature", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] -} \ No newline at end of file diff --git a/src/connectors/zigzag/zigzag.ts b/src/connectors/zigzag/zigzag.ts deleted file mode 100644 index b45595a640..0000000000 --- a/src/connectors/zigzag/zigzag.ts +++ /dev/null @@ -1,410 +0,0 @@ -import { BigNumber, Contract, Transaction } from 'ethers'; -import { ethers } from 'ethers'; -import LRUCache from 'lru-cache'; -import { ZigZagConfig } from './zigzag.config'; -import axios from 'axios'; -import { Ethereum } from '../../chains/ethereum/ethereum'; -import { Token } from '@uniswap/sdk-core'; -import { ZigZagTrade } from '../../services/common-interfaces'; -import { ZigZagish } from '../../services/common-interfaces'; -import { logger } from '../../services/logger'; -import { EVMTxBroadcaster } from '../../chains/ethereum/evm.broadcaster'; -import { abi } from './zigzag.exchange.abi.json'; - -// https://api.arbitrum.zigzag.exchange/v1/info - -// https://zigzag-exchange.herokuapp.com/api/coingecko/v1/pairs/42161 -// https://zigzag-exchange.herokuapp.com/api/coingecko/v1/tickers/42161 -// https://zigzag-exchange.herokuapp.com/api/coingecko/v1/orderbook/42161/?ticker_id=eth-ust -// https://zigzag-exchange.herokuapp.com/api/coingecko/v1/historical_trades/42161?ticker_id=eth-ust&type=b - -export type ZigZagMarket = { - buyToken: string; - sellToken: string; - verified: boolean; -}; - -export type ZigZagToken = { - address: string; - symbol: string; - decimals: number; - name: string; -}; - -export type ZigZagInfo = { - markets: Array; - verifiedTokens: Array; - exchange: { - exchangeAddress: string; - makerVolumeFee: number; - takerVolumeFee: number; - // domain: EIP712DomainInfo; - // types: EIP712TypeInfo; - }; -}; - -export interface Market { - market: string; - baseSymbol: string; - quoteSymbol: string; - lastPrice: number; - lowestAsk: number; - highestBid: number; - baseVolume: number; - quoteVolume: number; - priceChange: number; - priceChangePercent_24h: number; - highestPrice_24h: number; - lowestPrice_24h: number; - numberOfTrades_24h: number; -} - -export type RouteMarket = { - buyTokenAddress: string; - sellTokenAddress: string; -}; - -export type ZigZagOrder = { - order: { - user: string; - buyToken: string; - sellToken: string; - buyAmount: string; - sellAmount: string; - expirationTimeSeconds: string; - }; - signature: string; -}; - -export class ZigZag implements ZigZagish { - private static _instances: LRUCache; - private _ready = false; - private _chain: Ethereum; - private _network: string; - private _router: Contract; - private tokenList: Record = {}; // keep track of tokens that are in a ZigZag market - // public markets: Array = []; // keep track of ZigZag markets, ZZ-USDT - public markets: Array = []; // keep track of ZigZag markets, 0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9-0xf4037f59c92c9893c43c2372286699430310cfe7 - public config; - gasLimitEstimate: number; - - private constructor(network: string) { - this._chain = Ethereum.getInstance(network); - this.config = ZigZagConfig.config; - this._network = network; - this._router = new Contract( - this.config.contractAddress(this._network), - abi, - this._chain.provider - ); - this.gasLimitEstimate = this._chain.gasLimitTransaction; - } - - public static getInstance(network: string): ZigZag { - if (ZigZag._instances === undefined) { - ZigZag._instances = new LRUCache({ - max: 2, - }); - } - const instanceKey = network; - if (!ZigZag._instances.has(instanceKey)) { - ZigZag._instances.set(instanceKey, new ZigZag(network)); - } - - return ZigZag._instances.get(instanceKey) as ZigZag; - } - - // public async loadMarkets() { - // this.parsedMarkets = await axios.get( - // 'https://zigzag-exchange.herokuapp.com/api/v1/markets' - // ); - // } - - public getTokenByAddress(address: string): Token { - return this.tokenList[address.toLowerCase()]; - } - - public async init() { - await this._chain.init(); - const response = await axios.get( - 'https://api.arbitrum.zigzag.exchange/v1/info' - ); - if (response.status === 200) { - const zigZagData: ZigZagInfo = response.data; - for (const token of zigZagData.verifiedTokens) { - this.tokenList[token.address.toLowerCase()] = new Token( - this._chain.chainId, - token.address.toLowerCase(), - token.decimals, - token.symbol, - token.name - ); - } - for (const market of zigZagData.markets) { - const base = this.tokenList[market.buyToken]; - const quote = this.tokenList[market.sellToken]; - // this.markets.push(base.symbol + '-' + quote.symbol); - this.markets.push( - base.address.toLowerCase() + '-' + quote.address.toLowerCase() - ); - } - } - - this._ready = true; - } - - public ready(): boolean { - return this._ready; - } - - public async getMarketOrders( - buyTokenAddress: string, - sellTokenAddress: string, - minExpires: string - ): Promise> { - const response = await axios.get( - `https://api.arbitrum.zigzag.exchange/v1/orders?buyToken=${buyTokenAddress}&sellToken=${sellTokenAddress}&minExpires=${minExpires}` - ); - - return response.data.orders; - } - - // For an array of possible routes, get recent orders for the corresponding markets - public async getOrderBook( - possibleRoutes: Array> - ): Promise<{ [key: string]: Array }> { - const minExpires = (Date.now() / 1000 + 11).toFixed(0); - const minTimeStamp: number = Date.now() / 1000 + 10; - const newOrderBook: { [key: string]: Array } = {}; - - const promise0 = possibleRoutes.map(async (routes: Array) => { - const promise1 = routes.map(async (market: RouteMarket) => { - const requestSellTokenAddress = market.sellTokenAddress; - const requestBuyTokenAddress = market.buyTokenAddress; - const orders = await this.getMarketOrders( - requestBuyTokenAddress, - requestSellTokenAddress, - minExpires - ); - const goodOrders = orders.filter( - (order: ZigZagOrder) => - minTimeStamp < Number(order.order.expirationTimeSeconds) - ); - const key = `${requestBuyTokenAddress}-${requestSellTokenAddress}`; - newOrderBook[key] = goodOrders; - }); - await Promise.all(promise1); - }); - await Promise.all(promise0); - - return newOrderBook; - } - - // if a direct market between two pairs exists, use it. Otherwise generate - // routes using stable coins. - public getPossibleRoutes( - sellToken: Token, - buyToken: Token - ): Array> { - const newRoute: Array> = []; - const tradeMarket = `${sellToken.address.toLowerCase()}-${buyToken.address.toLowerCase()}`; - - // check for a direct route between pairs, if this exists, use it. - if (this.markets.includes(tradeMarket)) { - newRoute.push([ - { - buyTokenAddress: sellToken.address.toLowerCase(), - sellTokenAddress: buyToken.address.toLowerCase(), - }, - ]); - } - - // check routes via other tokens - if (newRoute.length === 0) { - const possibleRoutes = [ - '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', // WETH - '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', // USDC - '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', // USDT - ]; - possibleRoutes.forEach((routeTokenAddress) => { - const firstTradeMarket = `${sellToken.address.toLowerCase()}-${routeTokenAddress.toLowerCase()}`; - const secondTradeMarket = `${routeTokenAddress.toLowerCase()}-${buyToken.address.toLowerCase()}`; - if ( - this.markets.includes(firstTradeMarket) && - this.markets.includes(secondTradeMarket) - ) { - newRoute.push([ - { - buyTokenAddress: sellToken.address.toLowerCase(), - sellTokenAddress: routeTokenAddress.toLowerCase(), - }, - { - buyTokenAddress: routeTokenAddress.toLowerCase(), - sellTokenAddress: buyToken.address.toLowerCase(), - }, - ]); - } - }); - } - - return newRoute; - } - - // estimate trade details between two tokens - public async estimate( - sellToken: Token, - buyToken: Token, - buyAmount: BigNumber, - side: string - ): Promise { - let newQuoteOrderArray: Array = []; - const minTimeStamp: number = Date.now() / 1000 + 5; - let newSwapPrice: number = 0; - let bestSwapRoute: Array = []; - - const possibleRoutes = this.getPossibleRoutes(sellToken, buyToken); - const orderBook = await this.getOrderBook(possibleRoutes); - - possibleRoutes.forEach((route: Array) => { - let routeSwapPrice = 0; - const routeQuoteOrderArray: Array = []; - const stepBuyAmount = buyAmount; - route.forEach((market: RouteMarket) => { - let marketSwapPrice = 0; - let marketQuoteOrder: ZigZagOrder | undefined; - const key = `${market.buyTokenAddress}-${market.sellTokenAddress}`; - const currentOrderBook = orderBook[key]; - if (!currentOrderBook) return; - - for (let i = 0; i < currentOrderBook.length; i++) { - const { order } = currentOrderBook[i]; - if (minTimeStamp > Number(order.expirationTimeSeconds)) return; - - const quoteSellAmount = ethers.BigNumber.from(order.sellAmount); - const quoteBuyAmount = ethers.BigNumber.from(order.buyAmount); - if (side === 'buy' && quoteSellAmount.lt(stepBuyAmount)) return; - - const quoteSellToken = this.tokenList[order.sellToken]; - const quoteBuyToken = this.tokenList[order.buyToken]; - if (!quoteSellToken || !quoteBuyToken) return; - - const quoteSellAmountFormated = Number( - ethers.utils.formatUnits(quoteSellAmount, quoteSellToken.decimals) - ); - const quoteBuyAmountFormated = Number( - ethers.utils.formatUnits(quoteBuyAmount, quoteBuyToken.decimals) - ); - - const thisPrice = quoteSellAmountFormated / quoteBuyAmountFormated; - if (thisPrice > marketSwapPrice) { - marketSwapPrice = thisPrice; - marketQuoteOrder = currentOrderBook[i]; - } - } - routeSwapPrice = routeSwapPrice - ? routeSwapPrice * marketSwapPrice - : marketSwapPrice; - if (marketQuoteOrder) { - routeQuoteOrderArray.push(marketQuoteOrder); - stepBuyAmount - .mul(marketQuoteOrder.order.buyAmount) - .div(marketQuoteOrder.order.sellAmount); - } - }); - - if (routeSwapPrice > newSwapPrice) { - newSwapPrice = routeSwapPrice; - newQuoteOrderArray = routeQuoteOrderArray; - bestSwapRoute = route; - } - - if (bestSwapRoute.length === 0) bestSwapRoute = route; - }); - - return { - newSwapPrice: side === 'sell' ? newSwapPrice : 1 / newSwapPrice, - newQuoteOrderArray: newQuoteOrderArray, - bestSwapRoute: bestSwapRoute, - }; - } - - /** - * Given a wallet and a Uniswap-ish trade, try to execute it on blockchain. - * - * @param wallet Wallet - * @param trade Expected trade - */ - async executeTrade( - walletAddress: string, - trade: ZigZagTrade, - rawAmount: BigNumber, - is_buy: boolean - ): Promise { - let txData; - if (trade.newQuoteOrderArray.length === 0) - throw new Error('No route available.'); - else if (trade.newQuoteOrderArray.length === 1) { - if (is_buy === true) { - // buy - txData = await this._router.populateTransaction.fillOrderExactOutput( - [ - trade.newQuoteOrderArray[0].order.user, - trade.newQuoteOrderArray[0].order.sellToken, - trade.newQuoteOrderArray[0].order.buyToken, - trade.newQuoteOrderArray[0].order.sellAmount, - trade.newQuoteOrderArray[0].order.buyAmount, - trade.newQuoteOrderArray[0].order.expirationTimeSeconds, - ], - trade.newQuoteOrderArray[0].signature, - rawAmount.toString(), - false - ); - } else { - // sell - txData = await this._router.populateTransaction.fillOrderExactInput( - [ - trade.newQuoteOrderArray[0].order.user, - trade.newQuoteOrderArray[0].order.sellToken, - trade.newQuoteOrderArray[0].order.buyToken, - trade.newQuoteOrderArray[0].order.sellAmount, - trade.newQuoteOrderArray[0].order.buyAmount, - trade.newQuoteOrderArray[0].order.expirationTimeSeconds, - ], - trade.newQuoteOrderArray[0].signature, - rawAmount.toString(), - false - ); - } - } else { - const quoteOrderCalldataArray = trade.newQuoteOrderArray.map( - (quoteOrder: ZigZagOrder) => { - return [ - quoteOrder.order.user, - quoteOrder.order.sellToken, - quoteOrder.order.buyToken, - quoteOrder.order.sellAmount, - quoteOrder.order.buyAmount, - quoteOrder.order.expirationTimeSeconds, - ]; - } - ); - const signatureCalldataArray = trade.newQuoteOrderArray.map( - (quoteOrder: ZigZagOrder) => quoteOrder.signature - ); - txData = await this._router.populateTransaction.fillOrderRoute( - Object.values(quoteOrderCalldataArray), - Object.values(signatureCalldataArray), - rawAmount.toString(), - false - ); - } - txData.gasLimit = BigNumber.from(String(this._chain.gasLimitTransaction)); - const txResponse = await EVMTxBroadcaster.getInstance( - this._chain, - walletAddress - ).broadcast(txData); - - logger.info(txResponse); - return txResponse; - } -} diff --git a/src/services/common-interfaces.ts b/src/services/common-interfaces.ts index 4fdd31a7f2..332409ccb6 100644 --- a/src/services/common-interfaces.ts +++ b/src/services/common-interfaces.ts @@ -26,13 +26,6 @@ import { Token as UniswapCoreToken, Fraction as UniswapFraction, } from '@uniswap/sdk-core'; -import { - Token as TokenDefikingdoms, - CurrencyAmount as CurrencyAmountDefikingdoms, - Trade as TradeDefikingdoms, - Fraction as DefikingdomsFraction, - // } from '@defikingdoms/sdk'; -} from '@switchboard-xyz/defikingdoms-sdk'; import { Token as TokenPangolin, CurrencyAmount as CurrencyAmountPangolin, @@ -114,7 +107,6 @@ import { ClobTickerRequest, } from '../clob/clob.requests'; import { BalanceRequest } from '../network/network.requests'; -import { RouteMarket, ZigZagOrder } from '../connectors/zigzag/zigzag'; import { TradeV2 } from '@traderjoe-xyz/sdk-v2'; // TODO Check the possibility to have clob/solana/serum equivalents here @@ -127,7 +119,6 @@ export type Tokenish = | TokenTraderjoe | UniswapCoreToken | SushiToken - | TokenDefikingdoms | PancakeSwapToken | MMFToken | VVSToken @@ -149,7 +140,6 @@ export type UniswapishTrade = | TradeTraderjoe | SushiswapTrade | TradeUniswap - | TradeDefikingdoms | DefiraTrade | PancakeSwapTrade | MMFTrade @@ -172,7 +162,6 @@ export type UniswapishAmount = | UniswapCoreCurrencyAmount | CurrencyAmountTraderjoe | SushiCurrencyAmount - | CurrencyAmountDefikingdoms | PancakeSwapCurrencyAmount | CurrencyAmountMMF | CurrencyAmountVVS @@ -184,7 +173,6 @@ export type Fractionish = | QuickswapFraction | TraderjoeFraction | SushiFraction - | DefikingdomsFraction | PancakeSwapFraction | FractionMMF | FractionVVS @@ -310,34 +298,6 @@ export interface Uniswapish { ): Promise; } -export interface ZigZagTrade { - newSwapPrice: number; - bestSwapRoute: RouteMarket[]; - newQuoteOrderArray: ZigZagOrder[]; -} - -export interface ZigZagish { - init(): Promise; - - ready(): boolean; - - getTokenByAddress(address: string): Tokenish; - - estimate( - sellToken: Tokenish, - buyToken: Tokenish, - buyAmount: BigNumber, - side: string - ): Promise; - - executeTrade( - walletAddress: string, - trade: ZigZagTrade, - rawAmount: BigNumber, - is_buy: boolean - ): Promise; -} - export interface RefAMMish { /** * Router address. diff --git a/src/services/connection-manager.ts b/src/services/connection-manager.ts index 37af1d8411..82a78d2503 100644 --- a/src/services/connection-manager.ts +++ b/src/services/connection-manager.ts @@ -17,7 +17,6 @@ import { VVSConnector } from '../connectors/vvs/vvs'; import { InjectiveCLOB } from '../connectors/injective/injective'; import { InjectiveClobPerp } from '../connectors/injective_perpetual/injective.perp'; import { Injective } from '../chains/injective/injective'; -import { ZigZag } from '../connectors/zigzag/zigzag'; import { CLOBish, Ethereumish, @@ -30,7 +29,6 @@ import { } from './common-interfaces'; import { Traderjoe } from '../connectors/traderjoe/traderjoe'; import { Sushiswap } from '../connectors/sushiswap/sushiswap'; -import { Defikingdoms } from '../connectors/defikingdoms/defikingdoms'; import { Defira } from '../connectors/defira/defira'; import { Near } from '../chains/near/near'; import { Ref } from '../connectors/ref/ref'; @@ -132,7 +130,6 @@ export type ConnectorUnion = | Perpish | RefAMMish | CLOBish - | ZigZag | InjectiveClobPerp | Tinyman; @@ -146,8 +143,6 @@ export type Connector = T extends Uniswapish ? RefAMMish : T extends CLOBish ? CLOBish - : T extends ZigZag - ? ZigZag : T extends InjectiveClobPerp ? InjectiveClobPerp : T extends Tinyman @@ -182,8 +177,6 @@ export async function getConnector( connectorInstance = Openocean.getInstance(chain, network); } else if (chain === 'avalanche' && connector === 'traderjoe') { connectorInstance = Traderjoe.getInstance(chain, network); - } else if (chain === 'harmony' && connector === 'defikingdoms') { - connectorInstance = Defikingdoms.getInstance(chain, network); } else if (chain === 'harmony' && connector === 'defira') { connectorInstance = Defira.getInstance(chain, network); } else if (chain === 'cronos' && connector === 'mad_meerkat') { @@ -204,8 +197,6 @@ export async function getConnector( connectorInstance = InjectiveCLOB.getInstance(chain, network); } else if (chain === 'avalanche' && connector === 'dexalot') { connectorInstance = DexalotCLOB.getInstance(network); - } else if (chain === 'ethereum' && connector === 'zigzag') { - connectorInstance = ZigZag.getInstance(network); } else if (chain == 'algorand' && connector == 'tinyman') { connectorInstance = Tinyman.getInstance(network); } else { diff --git a/src/services/schema/defikingdoms-schema.json b/src/services/schema/defikingdoms-schema.json deleted file mode 100644 index 1f5a967e68..0000000000 --- a/src/services/schema/defikingdoms-schema.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "allowedSlippage": { "type": "string" }, - "gasLimit": { "type": "integer" }, - "ttl": { "type": "integer" }, - "contractAddresses": { - "type": "object", - "patternProperties": { - "^\\w+$": { - "type": "object", - "properties": { - "routerAddress": { "type": "string" } - }, - "required": ["routerAddress"], - "additionalProperties": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": ["allowedSlippage", "gasLimit", "ttl", "contractAddresses"] -} diff --git a/src/services/schema/zigzag-schema.json b/src/services/schema/zigzag-schema.json deleted file mode 100644 index c6008f96a2..0000000000 --- a/src/services/schema/zigzag-schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "networks": { - "type": "object", - "patternProperties": { - "^\\w+$": { - "type": "object", - "properties": { - "contractAddress": { "type": "string" }, - "exchangeApiUrl": { "type": "string" } - }, - "required": ["contractAddress", "exchangeApiUrl"], - "additionalProperties": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": ["networks"] -} diff --git a/src/templates/defikingdoms.yml b/src/templates/defikingdoms.yml deleted file mode 100644 index 86956e6323..0000000000 --- a/src/templates/defikingdoms.yml +++ /dev/null @@ -1,14 +0,0 @@ -# how much the execution price is allowed to move unfavorably from the trade -# execution price. It uses a rational number for precision. -allowedSlippage: '2/100' - -# the maximum gas allowed for a defikingdoms trade. -gasLimit: 2000000 - -# how long a trade is valid in seconds. After time passes defikingdoms will not -# perform the trade, but the gas will still be spent. -ttl: 300 - -contractAddresses: - mainnet: - routerAddress: '0x24ad62502d1C652Cc7684081169D04896aC20f30' diff --git a/src/templates/root.yml b/src/templates/root.yml index ea919906ec..1d4ada5601 100644 --- a/src/templates/root.yml +++ b/src/templates/root.yml @@ -72,10 +72,6 @@ configurations: configurationPath: openocean.yml schemaPath: openocean-schema.json - $namespace defikingdoms: - configurationPath: defikingdoms.yml - schemaPath: defikingdoms-schema.json - $namespace cosmos: configurationPath: cosmos.yml schemaPath: cosmos-schema.json @@ -111,7 +107,3 @@ configurations: $namespace xsswap: configurationPath: xsswap.yml schemaPath: xsswap-schema.json - - $namespace zigzag: - configurationPath: zigzag.yml - schemaPath: zigzag-schema.json diff --git a/src/templates/zigzag.yml b/src/templates/zigzag.yml deleted file mode 100644 index abd6cb70e9..0000000000 --- a/src/templates/zigzag.yml +++ /dev/null @@ -1,4 +0,0 @@ -networks: - arbitrum_one: - exchangeApiUrl: https://zigzag-exchange.herokuapp.com - contractAddress: '0x6fCdBD2Aa4cBd9d01741EFC152a7fFB833dd9A47' diff --git a/test-helpers/curl/curl.sh b/test-helpers/curl/curl.sh index 1941928397..426368a956 100644 --- a/test-helpers/curl/curl.sh +++ b/test-helpers/curl/curl.sh @@ -108,8 +108,6 @@ curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: app curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/price_traderjoe.json)" https://localhost:15888/amm/price | jq -curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/price_dfk.json)" https://localhost:15888/amm/price - curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/price_defira.json)" https://localhost:15888/amm/price | jq curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/price_mad_meerkat.json)" https://localhost:15888/amm/price | jq @@ -128,8 +126,6 @@ curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: app curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/price_xdc_xsswap.json)" https://localhost:15888/amm/price | jq -curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/price_zigzag.json)" https://localhost:15888/amm/price | jq - curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/price_tinyman.json)" https://localhost:15888/amm/price | jq ## trade @@ -138,8 +134,6 @@ curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: app curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/avalanche_traderjoe_trade.json)" https://localhost:15888/amm/trade | jq -curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/harmony_dfk_trade.json)" https://localhost:15888/amm/trade | jq - curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/harmony_testnet_defira_trade.json)" https://localhost:15888/amm/trade | jq curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/cronos_mmf_trade.json)" https://localhost:15888/amm/trade | jq @@ -156,8 +150,6 @@ curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: app curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/polygon_sushiswap_trade_sell.json)" https://localhost:15888/amm/trade | jq -curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/eth_zigzag_trade.json)" https://localhost:15888/amm/trade | jq - curl -s -X POST -k --key $GATEWAY_KEY --cert $GATEWAY_CERT -H "Content-Type: application/json" -d "$(envsubst < ./requests/algorand_tinyman_trade.json)" https://localhost:15888/amm/trade | jq ## Perp - curie diff --git a/test-helpers/curl/requests/eth_zigzag_trade.json b/test-helpers/curl/requests/eth_zigzag_trade.json deleted file mode 100644 index 95d3386b75..0000000000 --- a/test-helpers/curl/requests/eth_zigzag_trade.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "address": "$ETH_ADDRESS", - "quote": "USDC", - "base": "WETH", - "amount": "1", - "side": "SELL", - "chain": "ethereum", - "network": "arbitrum_one", - "connector": "zigzag" -} diff --git a/test-helpers/curl/requests/harmony_dfk_trade.json b/test-helpers/curl/requests/harmony_dfk_trade.json deleted file mode 100644 index debdd0374b..0000000000 --- a/test-helpers/curl/requests/harmony_dfk_trade.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "address": "$ETH_ADDRESS", - "quote": "WONE", - "base": "ETH", - "amount": "0.01", - "side": "SELL", - "chain": "harmony", - "network": "mainnet", - "connector": "defikingdoms" -} diff --git a/test-helpers/curl/requests/price_dfk.json b/test-helpers/curl/requests/price_dfk.json deleted file mode 100644 index f35328cf06..0000000000 --- a/test-helpers/curl/requests/price_dfk.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "connector": "defikingdoms", - "chain": "harmony", - "network": "mainnet", - "quote": "USDC", - "base": "ETH", - "amount": "0.01", - "side": "SELL" -} diff --git a/test-helpers/curl/requests/price_zigzag.json b/test-helpers/curl/requests/price_zigzag.json deleted file mode 100644 index cf0ba81299..0000000000 --- a/test-helpers/curl/requests/price_zigzag.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "connector": "zigzag", - "chain": "ethereum", - "network": "arbitrum_one", - "quote": "USDC", - "base": "WETH", - "amount": "2", - "side": "SELL" -} diff --git a/test/chains/harmony/harmony.test.ts b/test/chains/harmony/harmony.test.ts index 441eba300c..13aea00305 100644 --- a/test/chains/harmony/harmony.test.ts +++ b/test/chains/harmony/harmony.test.ts @@ -1,6 +1,5 @@ import { Harmony } from '../../../src/chains/harmony/harmony'; import { patchEVMNonceManager } from '../../evm.nonce.mock'; -import { DefikingdomsConfig } from '../../../src/connectors/defikingdoms/defikingdoms.config'; import { DefiraConfig } from '../../../src/connectors/defira/defira.config'; let harmony: Harmony; @@ -24,14 +23,6 @@ describe('getSpender', () => { ); }); }); - describe('get defikingdoms', () => { - it('returns defikingdoms mainnet router address', () => { - const dfkAddress = harmony.getSpender('defikingdoms'); - expect(dfkAddress.toLowerCase()).toEqual( - DefikingdomsConfig.config.routerAddress('mainnet').toLowerCase() - ); - }); - }); describe('get defira', () => { it('returns defira mainnet router address', () => { const dfkAddress = harmony.getSpender('defira'); diff --git a/test/connectors/defikingdoms/defikingdoms.routes.test.ts b/test/connectors/defikingdoms/defikingdoms.routes.test.ts deleted file mode 100644 index 3f14cec6f8..0000000000 --- a/test/connectors/defikingdoms/defikingdoms.routes.test.ts +++ /dev/null @@ -1,669 +0,0 @@ -import express from 'express'; -import { Express } from 'express-serve-static-core'; -import request from 'supertest'; -import { Harmony } from '../../../src/chains/harmony/harmony'; -import { Defikingdoms } from '../../../src/connectors/defikingdoms/defikingdoms'; -import { AmmRoutes } from '../../../src/amm/amm.routes'; -import { patch, unpatch } from '../../services/patch'; -import { gasCostInEthString } from '../../../src/services/base'; -let app: Express; -let harmony: Harmony; -let defikingdoms: Defikingdoms; - -beforeAll(async () => { - app = express(); - app.use(express.json()); - harmony = Harmony.getInstance('testnet'); - await harmony.init(); - defikingdoms = Defikingdoms.getInstance('harmony', 'testnet'); - await defikingdoms.init(); - app.use('/amm', AmmRoutes.router); -}); - -afterEach(() => { - unpatch(); -}); - -afterAll(async () => { - await harmony.close(); -}); - -const address: string = '0xFaA12FD102FE8623C9299c72B03E45107F2772B5'; - -const patchGetWallet = () => { - patch(harmony, 'getWallet', () => { - return { - address: '0xFaA12FD102FE8623C9299c72B03E45107F2772B5', - }; - }); -}; - -const patchInit = () => { - patch(defikingdoms, 'init', async () => { - return; - }); -}; - -const patchStoredTokenList = () => { - patch(harmony, 'tokenList', () => { - return [ - { - chainId: 1666700000, - name: 'WONE74', - symbol: 'WONE74', - address: '0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa', - decimals: 18, - }, - { - chainId: 1666700000, - name: 'OneETH', - symbol: '1ETH', - address: '0x1E120B3b4aF96e7F394ECAF84375b1C661830013', - decimals: 18, - }, - ]; - }); -}; - -const patchGetTokenBySymbol = () => { - patch(harmony, 'getTokenBySymbol', (symbol: string) => { - if (symbol === 'WONE74') { - return { - chainId: 1666700000, - name: 'WONE74', - symbol: 'WONE74', - address: '0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa', - decimals: 18, - }; - } else { - return { - chainId: 1666700000, - name: 'OneETH', - symbol: '1ETH', - address: '0x1E120B3b4aF96e7F394ECAF84375b1C661830013', - decimals: 18, - }; - } - }); -}; - -const patchGetTokenByAddress = () => { - patch(defikingdoms, 'getTokenByAddress', () => { - return { - chainId: 1666700000, - name: 'WONE74', - symbol: 'WONE74', - address: '0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa', - decimals: 18, - }; - }); -}; - -const patchGasPrice = () => { - patch(harmony, 'gasPrice', () => 100); -}; - -const patchEstimateBuyTrade = () => { - patch(defikingdoms, 'estimateBuyTrade', () => { - return { - expectedAmount: { - toSignificant: () => 100, - }, - trade: { - executionPrice: { - invert: jest.fn().mockReturnValue({ - toSignificant: () => 100, - toFixed: () => '100', - }), - }, - }, - }; - }); -}; - -const patchEstimateSellTrade = () => { - patch(defikingdoms, 'estimateSellTrade', () => { - return { - expectedAmount: { - toSignificant: () => 100, - }, - trade: { - executionPrice: { - toSignificant: () => 100, - toFixed: () => '100', - }, - }, - }; - }); -}; - -const patchGetNonce = () => { - patch(harmony.nonceManager, 'getNonce', () => 21); -}; - -const patchExecuteTrade = () => { - patch(defikingdoms, 'executeTrade', () => { - return { nonce: 21, hash: '000000000000000' }; - }); -}; - -describe('POST /amm/price', () => { - it('should return 200 for BUY', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patchGasPrice(); - patchEstimateBuyTrade(); - patchGetNonce(); - patchExecuteTrade(); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - side: 'BUY', - }) - .set('Accept', 'application/json') - .expect(200) - .then((res: any) => { - expect(res.body.amount).toEqual('10000.000000000000000000'); - expect(res.body.rawAmount).toEqual('10000000000000000000000'); - }); - }); - - it('should return 200 for SELL', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patchGasPrice(); - patchEstimateSellTrade(); - patchGetNonce(); - patchExecuteTrade(); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - side: 'SELL', - }) - .set('Accept', 'application/json') - .expect(200) - .then((res: any) => { - expect(res.body.amount).toEqual('10000.000000000000000000'); - expect(res.body.rawAmount).toEqual('10000000000000000000000'); - }); - }); - - it('should return 500 for unrecognized quote symbol', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: 'DOGE', - base: 'WONE74', - amount: '10000', - side: 'SELL', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 500 for unrecognized base symbol', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'SHIBA', - amount: '10000', - side: 'SELL', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 500 for unrecognized base symbol with decimals in the amount and SELL', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'SHIBA', - amount: '10.000', - side: 'SELL', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 500 for unrecognized base symbol with decimals in the amount and BUY', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'SHIBA', - amount: '10.000', - side: 'BUY', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 500 when the priceSwapIn operation fails', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patch(defikingdoms, 'priceSwapIn', () => { - return 'error'; - }); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: 'DOGE', - base: 'WONE74', - amount: '10000', - side: 'SELL', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 500 when the priceSwapOut operation fails', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patch(defikingdoms, 'priceSwapOut', () => { - return 'error'; - }); - - await request(app) - .post(`/amm/price`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: 'DOGE', - base: 'WONE74', - amount: '10000', - side: 'BUY', - }) - .set('Accept', 'application/json') - .expect(500); - }); -}); - -describe('POST /amm/trade', () => { - const patchForBuy = () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patchGasPrice(); - patchEstimateBuyTrade(); - patchGetNonce(); - patchExecuteTrade(); - }; - it('should return 200 for BUY', async () => { - patchForBuy(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'BUY', - nonce: 21, - }) - .set('Accept', 'application/json') - .expect(200) - .then((res: any) => { - expect(res.body.nonce).toEqual(21); - }); - }); - - it('should return 200 for BUY without nonce parameter', async () => { - patchForBuy(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'BUY', - }) - .set('Accept', 'application/json') - .expect(200); - }); - - it('should return 200 for BUY with maxFeePerGas and maxPriorityFeePerGas', async () => { - patchForBuy(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'BUY', - nonce: 21, - maxFeePerGas: '5000000000', - maxPriorityFeePerGas: '5000000000', - }) - .set('Accept', 'application/json') - .expect(200); - }); - - const patchForSell = () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patchGasPrice(); - patchEstimateSellTrade(); - patchGetNonce(); - patchExecuteTrade(); - }; - it('should return 200 for SELL', async () => { - patchForSell(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'SELL', - nonce: 21, - }) - .set('Accept', 'application/json') - .expect(200) - .then((res: any) => { - expect(res.body.nonce).toEqual(21); - }); - }); - - it('should return 200 for SELL with maxFeePerGas and maxPriorityFeePerGas', async () => { - patchForSell(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'SELL', - nonce: 21, - maxFeePerGas: '5000000000', - maxPriorityFeePerGas: '5000000000', - }) - .set('Accept', 'application/json') - .expect(200); - }); - - it('should return 200 for SELL with limitPrice', async () => { - patchForSell(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'SELL', - nonce: 21, - limitPrice: '9', - }) - .set('Accept', 'application/json') - .expect(200); - }); - - it('should return 200 for BUY with limitPrice', async () => { - patchForBuy(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'BUY', - nonce: 21, - limitPrice: '999999999999999999999', - }) - .set('Accept', 'application/json') - .expect(200); - }); - - it('should return 500 for BUY with price smaller than limitPrice', async () => { - patchForBuy(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'BUY', - nonce: 21, - limitPrice: '9', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 500 for SELL with price higher than limitPrice', async () => { - patchForSell(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'SELL', - nonce: 21, - limitPrice: '99999999999', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 404 when parameters are incorrect', async () => { - patchInit(); - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: 10000, - address: 'da8', - side: 'comprar', - }) - .set('Accept', 'application/json') - .expect(404); - }); - it('should return 500 when the priceSwapIn operation fails', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patch(defikingdoms, 'priceSwapIn', () => { - return 'error'; - }); - - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'SELL', - nonce: 21, - maxFeePerGas: '5000000000', - maxPriorityFeePerGas: '5000000000', - }) - .set('Accept', 'application/json') - .expect(500); - }); - - it('should return 500 when the priceSwapOut operation fails', async () => { - patchGetWallet(); - patchInit(); - patchStoredTokenList(); - patchGetTokenBySymbol(); - patchGetTokenByAddress(); - patch(defikingdoms, 'priceSwapOut', () => { - return 'error'; - }); - - await request(app) - .post(`/amm/trade`) - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - quote: '1ETH', - base: 'WONE74', - amount: '10000', - address, - side: 'BUY', - nonce: 21, - maxFeePerGas: '5000000000', - maxPriorityFeePerGas: '5000000000', - }) - .set('Accept', 'application/json') - .expect(500); - }); -}); - -describe('POST /amm/estimateGas', () => { - it('should return 200 for valid connector', async () => { - patchInit(); - patchGasPrice(); - - await request(app) - .post('/amm/estimateGas') - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'defikingdoms', - }) - .set('Accept', 'application/json') - .expect(200) - .then((res: any) => { - expect(res.body.network).toEqual('testnet'); - expect(res.body.gasPrice).toEqual(100); - expect(res.body.gasCost).toEqual( - gasCostInEthString(100, defikingdoms.gasLimitEstimate) - ); - }); - }); - - it('should return 500 for invalid connector', async () => { - patchInit(); - patchGasPrice(); - - await request(app) - .post('/amm/estimateGas') - .send({ - chain: 'harmony', - network: 'testnet', - connector: 'pangolin', - }) - .set('Accept', 'application/json') - .expect(500); - }); -}); diff --git a/test/connectors/defikingdoms/defikingdoms.test.ts b/test/connectors/defikingdoms/defikingdoms.test.ts deleted file mode 100644 index ce95a4fee7..0000000000 --- a/test/connectors/defikingdoms/defikingdoms.test.ts +++ /dev/null @@ -1,151 +0,0 @@ -jest.useFakeTimers(); -import { Defikingdoms } from '../../../src/connectors/defikingdoms/defikingdoms'; -import { patch, unpatch } from '../../services/patch'; -import { UniswapishPriceError } from '../../../src/services/error-handler'; -import { - Token, - TokenAmount, - TradeType, - Trade, - Pair, - Route, - Percent, -} from '@switchboard-xyz/defikingdoms-sdk'; -import { BigNumber } from 'ethers'; -import { Harmony } from '../../../src/chains/harmony/harmony'; -import { patchEVMNonceManager } from '../../evm.nonce.mock'; -import { DefikingdomsConfig } from '../../../src/connectors/defikingdoms/defikingdoms.config'; - -let harmony: Harmony; -let defikingdoms: Defikingdoms; - -const WONE = new Token( - 1666700000, - '0x7466d7d0C21Fa05F32F5a0Fa27e12bdC06348Ce2', - 18, - 'WONE' -); -const ETH = new Token( - 1666700000, - '0x1E120B3b4aF96e7F394ECAF84375b1C661830013', - 18, - 'ETH' -); - -beforeAll(async () => { - harmony = Harmony.getInstance('testnet'); - patchEVMNonceManager(harmony.nonceManager); - - defikingdoms = Defikingdoms.getInstance('harmony', 'testnet'); - await defikingdoms.init(); -}); - -beforeEach(() => { - patchEVMNonceManager(harmony.nonceManager); -}); - -afterEach(() => { - unpatch(); -}); - -afterAll(async () => { - await harmony.close(); -}); - -const patchFetchData = () => { - patch(defikingdoms, 'fetchPairData', () => { - return new Pair( - new TokenAmount(WONE, '2000000000000000000'), - new TokenAmount(ETH, '1000000000000000000') - ); - }); -}; - -const patchTrade = (key: string, error?: Error) => { - patch(Trade, key, () => { - if (error) return []; - const WONE_ETH = new Pair( - new TokenAmount(WONE, '2000000000000000000'), - new TokenAmount(ETH, '1000000000000000000') - ); - const ETH_TO_WONE = new Route([WONE_ETH], ETH, WONE); - return [ - new Trade( - ETH_TO_WONE, - new TokenAmount(ETH, '1000000000000000'), - TradeType.EXACT_INPUT - ), - ]; - }); -}; - -describe('verify defikingdoms gasLimit', () => { - it('Should initially match the config for mainnet', () => { - expect(defikingdoms.gasLimitEstimate).toEqual( - DefikingdomsConfig.config.gasLimit - ); - }); -}); - -describe('verify defikingdoms getAllowedSlippage', () => { - it('Should parse simple fractions', () => { - expect(defikingdoms.getAllowedSlippage('3/100')).toEqual( - new Percent('3', '100') - ); - }); -}); - -describe('verify defikingdoms estimateSellTrade', () => { - it('Should return an ExpectedTrade when available', async () => { - patchFetchData(); - patchTrade('bestTradeExactIn'); - - const expectedTrade = await defikingdoms.estimateSellTrade( - WONE, - ETH, - BigNumber.from(1) - ); - expect(expectedTrade).toHaveProperty('trade'); - expect(expectedTrade).toHaveProperty('expectedAmount'); - }); - - it('Should throw an error if no pair is available', async () => { - patchFetchData(); - patchTrade('bestTradeExactIn', new Error('error getting trade')); - - await expect(async () => { - await defikingdoms.estimateSellTrade(WONE, ETH, BigNumber.from(1)); - }).rejects.toThrow(UniswapishPriceError); - }); -}); - -describe('verify defikingdoms estimateBuyTrade', () => { - it('Should return an ExpectedTrade when available', async () => { - patchFetchData(); - patchTrade('bestTradeExactOut'); - - const expectedTrade = await defikingdoms.estimateBuyTrade( - WONE, - ETH, - BigNumber.from(1) - ); - expect(expectedTrade).toHaveProperty('trade'); - expect(expectedTrade).toHaveProperty('expectedAmount'); - }); - - it('Should return an error if no pair is available', async () => { - patchFetchData(); - patchTrade('bestTradeExactOut', new Error('error getting trade')); - - await expect(async () => { - await defikingdoms.estimateBuyTrade(WONE, ETH, BigNumber.from(1)); - }).rejects.toThrow(UniswapishPriceError); - }); -}); - -describe('verify defikingdoms Token List', () => { - it('Should return a token by address', async () => { - const token = defikingdoms.getTokenByAddress(ETH.address); - expect(token).toBeInstanceOf(Token); - }); -}); diff --git a/test/connectors/zigzag/zigzag.test.ts b/test/connectors/zigzag/zigzag.test.ts deleted file mode 100644 index a7c2876e6d..0000000000 --- a/test/connectors/zigzag/zigzag.test.ts +++ /dev/null @@ -1,435 +0,0 @@ -import { ZigZag, ZigZagOrder } from '../../../src/connectors/zigzag/zigzag'; -import { patch, unpatch } from '../../services/patch'; -import { Ethereum } from '../../../src/chains/ethereum/ethereum'; -import { patchEVMNonceManager } from '../../evm.nonce.mock'; -import { BigNumber } from 'ethers'; -import { floatStringWithDecimalToBigNumber } from '../../../src/services/base'; -import { Token } from '@uniswap/sdk-core'; -import { EVMTxBroadcaster } from '../../../src/chains/ethereum/evm.broadcaster'; -import { - price, - trade, -} from '../../../src/connectors/zigzag/zigzag.controllers'; - -let ethereum: Ethereum; -let zigzag: ZigZag; - -const TX_HASH = - '0xf6f81a37796bd06a797484467302e4d6f72832409545e2e01feb86dd8b22e4b2'; // noqa: mock - -const address: string = '0xFaA12FD102FE8623C9299c72B03E45107F2772B5'; - -const ORDERS = { - orders: [ - // ZZ-USDT orders, never expire - { - hash: '0x4bc2e2e8af7378069c16635d29172f32d2afd080f6b138b0660e56d6de19c263', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0xada42bb73b42e0472a994218fb3799dfcda21237', - sellToken: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '1234567890123456789', - }, - signature: - '0x3fcf8822dcfa2eac24f5dd68aabf30cff06348da93cc9e1af5824acff8e36795431a6ec8654384c4f0da10d769feb563b325d9c10bb7db4930a4647c14b816df1c', - }, - { - hash: '0xdfda8ce96d129bf219cfa4e1700a355946d95ef0f0a891c3e5e463e5f66561e6', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0xada42bb73b42e0472a994218fb3799dfcda21237', - sellToken: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '1234567890123456789', - }, - signature: - '0xc59491ac88ea0322053934616e209d7d891c2329a46aab34c9b55c2beaeda614477bdf5ec388bdced0df6c5febc2d3ead10b3576df3a57ed0030d055850902401b', - }, - // WETH-USDT orders, never expire - { - hash: '0x4bc2e2e8af7378069c16635d29172f32d2afd080f6b138b0660e56d6de19c263', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', - sellToken: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '1234567890123456789', - }, - signature: - '0x3fcf8822dcfa2eac24f5dd68aabf30cff06348da93cc9e1af5824acff8e36795431a6ec8654384c4f0da10d769feb563b325d9c10bb7db4930a4647c14b816df1c', - }, - { - hash: '0xdfda8ce96d129bf219cfa4e1700a355946d95ef0f0a891c3e5e463e5f66561e6', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', - sellToken: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '1234567890123456789', - }, - signature: - '0xc59491ac88ea0322053934616e209d7d891c2329a46aab34c9b55c2beaeda614477bdf5ec388bdced0df6c5febc2d3ead10b3576df3a57ed0030d055850902401b', - }, - // USDT-ZZLP orders, never expire - { - hash: '0x4bc2e2e8af7378069c16635d29172f32d2afd080f6b138b0660e56d6de19c263', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - sellToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '1234567890123456789', - }, - signature: - '0x3fcf8822dcfa2eac24f5dd68aabf30cff06348da93cc9e1af5824acff8e36795431a6ec8654384c4f0da10d769feb563b325d9c10bb7db4930a4647c14b816df1c', - }, - { - hash: '0xdfda8ce96d129bf219cfa4e1700a355946d95ef0f0a891c3e5e463e5f66561e6', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - sellToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '1234567890123456789', - }, - signature: - '0xc59491ac88ea0322053934616e209d7d891c2329a46aab34c9b55c2beaeda614477bdf5ec388bdced0df6c5febc2d3ead10b3576df3a57ed0030d055850902401b', - }, - // ZZ-WETH orders, expired - { - hash: '0x4bc2e2e8af7378069c16635d29172f32d2afd080f6b138b0660e56d6de19c263', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0xada42bb73b42e0472a994218fb3799dfcda21237', - sellToken: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '0', - }, - signature: - '0x3fcf8822dcfa2eac24f5dd68aabf30cff06348da93cc9e1af5824acff8e36795431a6ec8654384c4f0da10d769feb563b325d9c10bb7db4930a4647c14b816df1c', - }, - { - hash: '0xdfda8ce96d129bf219cfa4e1700a355946d95ef0f0a891c3e5e463e5f66561e6', - order: { - user: '0x27a2c7121e287478375Ec8c64FDfA31E97038c03', - buyToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - sellToken: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', - buyAmount: '1666018405396825073694', - sellAmount: '500507844', - expirationTimeSeconds: '0', - }, - signature: - '0xc59491ac88ea0322053934616e209d7d891c2329a46aab34c9b55c2beaeda614477bdf5ec388bdced0df6c5febc2d3ead10b3576df3a57ed0030d055850902401b', - }, - ], -}; - -const WETH = new Token( - 0, - '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', - 18, - 'WETH', - - 'Wrapped Ether' -); - -const ZZ = new Token( - 0, - '0xada42bb73b42e0472a994218fb3799dfcda21237', - 18, - 'ZZ', - 'ZigZag' -); - -const ZZLP = new Token( - 0, - '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - 18, - 'ZZLP', - 'ZigZag LP' -); - -const USDT = new Token( - 0, - '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - 6, - 'USDT', - 'Tether USD' -); - -const patchInit = () => { - patch(zigzag, 'init', async () => { - return; - }); -}; - -const patchStoredTokenList = () => { - patch(zigzag, 'tokenList', { - [WETH.address.toLowerCase()]: WETH, - [ZZ.address.toLowerCase()]: ZZ, - [ZZLP.address.toLowerCase()]: ZZLP, - [USDT.address.toLowerCase()]: USDT, - }); -}; - -const patchMarkets = () => { - patch(zigzag, 'markets', [ - ZZ.address.toLowerCase() + '-' + WETH.address.toLowerCase(), - ZZ.address.toLowerCase() + '-' + USDT.address.toLowerCase(), - USDT.address.toLowerCase() + '-' + ZZLP.address.toLowerCase(), - WETH.address.toLowerCase() + '-' + ZZLP.address.toLowerCase(), - WETH.address.toLowerCase() + '-' + USDT.address.toLowerCase(), - ]); -}; - -const patchGetMarketOrders = () => { - patch( - zigzag, - 'getMarketOrders', - ( - buyTokenAddress: string, - sellTokenAddress: string, - _minExpires: number - ) => { - return ORDERS.orders.filter( - (order: ZigZagOrder) => - order.order.buyToken === buyTokenAddress && - order.order.sellToken === sellTokenAddress - ); - } - ); -}; - -const patchMsgBroadcaster = () => { - patch(EVMTxBroadcaster, 'getInstance', () => { - return { - broadcast() { - return { - hash: TX_HASH, - }; - }, - }; - }); -}; - -const patchGetWallet = () => { - patch(ethereum, 'getWallet', () => { - return { - address, - }; - }); -}; - -beforeAll(async () => { - ethereum = Ethereum.getInstance('arbitrum_one'); - patchEVMNonceManager(ethereum.nonceManager); - await ethereum.init(); - - zigzag = ZigZag.getInstance('arbitrum_one'); - patchInit(); - await zigzag.init(); -}); - -beforeEach(() => { - patchInit(); - patchStoredTokenList(); - patchMarkets(); - patchEVMNonceManager(ethereum.nonceManager); -}); - -afterEach(() => { - unpatch(); -}); - -afterAll(async () => { - await ethereum.close(); -}); - -describe('getPossibleRoutes', () => { - it('ZZ-WETH has a direct route', async () => { - const routes = zigzag.getPossibleRoutes(ZZ, WETH); - expect(routes).toEqual([ - [ - { - buyTokenAddress: ZZ.address.toLowerCase(), - sellTokenAddress: WETH.address.toLowerCase(), - }, - ], - ]); - }); - - it('ZZ-ZZLP has two indirect routes', async () => { - const routes = zigzag.getPossibleRoutes(ZZ, ZZLP); - expect(routes).toEqual([ - [ - { - buyTokenAddress: ZZ.address.toLowerCase(), - sellTokenAddress: WETH.address.toLowerCase(), - }, - { - buyTokenAddress: WETH.address.toLowerCase(), - sellTokenAddress: ZZLP.address.toLowerCase(), - }, - ], - [ - { - buyTokenAddress: ZZ.address.toLowerCase(), - sellTokenAddress: USDT.address.toLowerCase(), - }, - { - buyTokenAddress: USDT.address.toLowerCase(), - sellTokenAddress: ZZLP.address.toLowerCase(), - }, - ], - ]); - }); -}); - -describe('getOrderBook', () => { - it('ZZ-WETH return no orders, they are expired', async () => { - patchGetMarketOrders(); - const orders = await zigzag.getOrderBook([ - [{ buyTokenAddress: ZZ.address, sellTokenAddress: WETH.address }], - ]); - const result: { [key: string]: Array } = {}; - result[ZZ.address + '-' + WETH.address] = []; - expect(orders).toEqual(result); - }); - - it('ZZ-USDT returns two orders, they never expire', async () => { - patchGetMarketOrders(); - const orders = await zigzag.getOrderBook([ - [{ buyTokenAddress: ZZ.address, sellTokenAddress: USDT.address }], - ]); - const result: { [key: string]: Array } = {}; - result[ZZ.address + '-' + USDT.address] = ORDERS.orders.filter( - (order: ZigZagOrder) => - order.order.buyToken === ZZ.address && - order.order.sellToken === USDT.address - ); - expect(orders).toEqual(result); - }); -}); - -describe('estimate', () => { - it('Estimate ZZ-USDT sell', async () => { - patchGetMarketOrders(); - const one = floatStringWithDecimalToBigNumber('1', ZZ.decimals); - const estimate = await zigzag.estimate(ZZ, USDT, one, 'sell'); - expect(estimate.newSwapPrice).toEqual(0.30042155739617127); - }); - - it('Estimate ZZ-USDT buy', async () => { - patchGetMarketOrders(); - const one = floatStringWithDecimalToBigNumber('1', USDT.decimals); - const estimate = await zigzag.estimate(ZZ, USDT, one, 'buy'); - expect(estimate.newSwapPrice).toEqual(3.3286559349044387); - }); -}); - -describe('executeTrade', () => { - it('Execute ZZ-USDT sell trade', async () => { - patchGetMarketOrders(); - patchMsgBroadcaster(); - const one = floatStringWithDecimalToBigNumber('1', ZZ.decimals); - const estimate = await zigzag.estimate(ZZ, USDT, one, 'sell'); - const trade = await zigzag.executeTrade( - '', - estimate, - one, - false - ); - expect(estimate.newSwapPrice).toEqual(0.30042155739617127); - expect(trade.hash).toEqual(TX_HASH); - }); - - it('Execute ZZ-USDT buy trade', async () => { - patchGetMarketOrders(); - patchMsgBroadcaster(); - const one = floatStringWithDecimalToBigNumber('1', USDT.decimals); - const estimate = await zigzag.estimate(ZZ, USDT, one, 'buy'); - const trade = await zigzag.executeTrade('', estimate, one, true); - expect(estimate.newSwapPrice).toEqual(3.3286559349044387); - expect(trade.hash).toEqual(TX_HASH); - }); - - it('Execute ZZ-ZZLP sell trade(multi-order)', async () => { - patchGetMarketOrders(); - patchMsgBroadcaster(); - const one = floatStringWithDecimalToBigNumber('1', 1); - const estimate = await zigzag.estimate(ZZ, ZZLP, one, 'sell'); - const trade = await zigzag.executeTrade( - '', - estimate, - one, - false - ); - expect(estimate.newSwapPrice).toEqual(9.025311214834104e-26); - expect(trade.hash).toEqual(TX_HASH); - }); - - it('Execute ZZ-ZZLP buy trade(multi-order)', async () => { - patchGetMarketOrders(); - patchMsgBroadcaster(); - const one = floatStringWithDecimalToBigNumber('1', 1); - const estimate = await zigzag.estimate(ZZ, ZZLP, one, 'buy'); - const trade = await zigzag.executeTrade('', estimate, one, true); - expect(estimate.newSwapPrice).toEqual(1.1079950332974543e25); - expect(trade.hash).toEqual(TX_HASH); - }); -}); - -describe('controller tests', () => { - it('price test', async () => { - patchGetMarketOrders(); - const priceResult = await price(ethereum, zigzag, { - connector: 'zigzag', - chain: 'ethereum', - network: 'arbitrum_one', - quote: 'USDT', - base: 'WETH', - amount: '2', - side: 'SELL', - }); - expect(priceResult.base).toEqual( - '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1' - ); - expect(priceResult.quote).toEqual( - '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9' - ); - expect(priceResult.rawAmount).toEqual('2000000000000000000'); - expect(priceResult.price).toEqual('0.30042155739617127'); - }); - - it('trade test', async () => { - patchGetMarketOrders(); - patchGetWallet(); - patchMsgBroadcaster(); - const tradeResult = await trade(ethereum, zigzag, { - address: address, - quote: 'USDT', - base: 'WETH', - amount: '1', - side: 'SELL', - chain: 'ethereum', - network: 'arbitrum_one', - connector: 'zigzag', - }); - expect(tradeResult.base).toEqual( - '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1' - ); - expect(tradeResult.quote).toEqual( - '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9' - ); - expect(tradeResult.rawAmount).toEqual('1000000000000000000'); - expect(tradeResult.txHash).toEqual(TX_HASH); - }); -});