diff --git a/packages/asset-swapper/src/constants.ts b/packages/asset-swapper/src/constants.ts index 3f536b70fa..79fbb4a640 100644 --- a/packages/asset-swapper/src/constants.ts +++ b/packages/asset-swapper/src/constants.ts @@ -1,6 +1,7 @@ import { BigNumber } from '@0x/utils'; import { + ExtensionContractType, ForwarderExtensionContractOpts, OrderPrunerOpts, OrderPrunerPermittedFeeTypes, @@ -8,7 +9,6 @@ import { SwapQuoteGetOutputOpts, SwapQuoteRequestOpts, SwapQuoterOpts, - ExtensionContractType, } from './types'; const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info'; @@ -18,7 +18,6 @@ const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; const MAINNET_CHAIN_ID = 1; const ONE_SECOND_MS = 1000; const DEFAULT_PER_PAGE = 1000; -const PROTOCOL_FEE_MULTIPLIER = 150000; const DEFAULT_ORDER_PRUNER_OPTS: OrderPrunerOpts = { expiryBufferMs: 120000, // 2 minutes @@ -68,6 +67,5 @@ export const constants = { DEFAULT_FORWARDER_SWAP_QUOTE_EXECUTE_OPTS, DEFAULT_SWAP_QUOTE_REQUEST_OPTS, DEFAULT_PER_PAGE, - PROTOCOL_FEE_MULTIPLIER, NULL_ERC20_ASSET_DATA, }; diff --git a/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts b/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts index 41edc3f35c..aec674c5aa 100644 --- a/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts +++ b/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts @@ -9,7 +9,6 @@ import * as _ from 'lodash'; import { constants } from '../constants'; import { CalldataInfo, - ForwarderExtensionContractOpts, ForwarderSmartContractParams, MarketOperation, SmartContractParamsInfo, diff --git a/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts b/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts index cde57cb9f8..be95ad4d53 100644 --- a/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts +++ b/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts @@ -20,9 +20,10 @@ import { MarketSellSwapQuote, PrunedSignedOrder, } from '../src/types'; +import { ProtocolFeeUtils } from '../src/utils/protocol_fee_utils'; import { chaiSetup } from './utils/chai_setup'; -import { getFullyFillableSwapQuoteWithNoFees } from './utils/swap_quote'; +import { getFullyFillableSwapQuoteWithNoFeesAsync } from './utils/swap_quote'; import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -67,6 +68,8 @@ const expectMakerAndTakerBalancesAsyncFactory = ( }; describe('ExchangeSwapQuoteConsumer', () => { + let contractWrappers: ContractWrappers; + let protocolFeeUtils: ProtocolFeeUtils; let userAddresses: string[]; let erc20MakerTokenContract: ERC20TokenContract; let erc20TakerTokenContract: ERC20TokenContract; @@ -130,6 +133,7 @@ describe('ExchangeSwapQuoteConsumer', () => { }; const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); + protocolFeeUtils = new ProtocolFeeUtils(contractWrappers.exchange); expectMakerAndTakerBalancesForTakerAssetAsync = expectMakerAndTakerBalancesAsyncFactory( erc20TakerTokenContract, makerAddress, @@ -156,20 +160,22 @@ describe('ExchangeSwapQuoteConsumer', () => { orders.push(prunedOrder as PrunedSignedOrder); } - marketSellSwapQuote = getFullyFillableSwapQuoteWithNoFees( + marketSellSwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, takerAssetData, orders, MarketOperation.Sell, GAS_PRICE, + protocolFeeUtils, ); - marketBuySwapQuote = getFullyFillableSwapQuoteWithNoFees( + marketBuySwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, takerAssetData, orders, MarketOperation.Buy, GAS_PRICE, + protocolFeeUtils, ); swapQuoteConsumer = new ExchangeSwapQuoteConsumer(provider, contractAddresses, { @@ -212,7 +218,6 @@ describe('ExchangeSwapQuoteConsumer', () => { ); await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, { takerAddress, - gasPrice: GAS_PRICE, gasLimit: 4000000, }); await expectMakerAndTakerBalancesForMakerAssetAsync( @@ -235,7 +240,6 @@ describe('ExchangeSwapQuoteConsumer', () => { ); await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, { takerAddress, - gasPrice: GAS_PRICE, gasLimit: 4000000, }); await expectMakerAndTakerBalancesForMakerAssetAsync( diff --git a/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts b/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts index f65f67a0b1..ab4c49d9a6 100644 --- a/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts +++ b/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts @@ -19,9 +19,10 @@ import { MarketOperation, PrunedSignedOrder, } from '../src/types'; +import { ProtocolFeeUtils } from '../src/utils/protocol_fee_utils'; import { chaiSetup } from './utils/chai_setup'; -import { getFullyFillableSwapQuoteWithNoFees } from './utils/swap_quote'; +import { getFullyFillableSwapQuoteWithNoFeesAsync } from './utils/swap_quote'; import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -33,7 +34,7 @@ const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000); const TESTRPC_CHAIN_ID = devConstants.TESTRPC_CHAIN_ID; const UNLIMITED_ALLOWANCE_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); // tslint:disable-line:custom-no-magic-numbers - +const FEE_PERCENTAGE = 0.05; const PARTIAL_PRUNED_SIGNED_ORDERS_FEELESS: Array> = [ { takerAssetAmount: new BigNumber(2).multipliedBy(ONE_ETH_IN_WEI), @@ -67,7 +68,9 @@ const expectMakerAndTakerBalancesAsyncFactory = ( }; describe('ForwarderSwapQuoteConsumer', () => { - const FEE_PERCENTAGE = 0.05; + let contractWrappers: ContractWrappers; + let protocolFeeUtils: ProtocolFeeUtils; + let erc20Token: ERC20TokenContract; let userAddresses: string[]; let coinbaseAddress: string; let makerAddress: string; @@ -133,6 +136,7 @@ describe('ForwarderSwapQuoteConsumer', () => { }; const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); + protocolFeeUtils = new ProtocolFeeUtils(contractWrappers.exchange); expectMakerAndTakerBalancesAsync = expectMakerAndTakerBalancesAsyncFactory( erc20TokenContract, makerAddress, @@ -179,28 +183,31 @@ describe('ForwarderSwapQuoteConsumer', () => { invalidOrders.push(prunedOrder as PrunedSignedOrder); } - marketSellSwapQuote = getFullyFillableSwapQuoteWithNoFees( + marketSellSwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, wethAssetData, orders, MarketOperation.Sell, GAS_PRICE, + protocolFeeUtils, ); - marketBuySwapQuote = getFullyFillableSwapQuoteWithNoFees( + marketBuySwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, wethAssetData, orders, MarketOperation.Buy, GAS_PRICE, + protocolFeeUtils, ); - invalidMarketBuySwapQuote = getFullyFillableSwapQuoteWithNoFees( + invalidMarketBuySwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, takerAssetData, invalidOrders, MarketOperation.Buy, GAS_PRICE, + protocolFeeUtils, ); swapQuoteConsumer = new ForwarderSwapQuoteConsumer(provider, contractAddresses, { @@ -234,7 +241,6 @@ describe('ForwarderSwapQuoteConsumer', () => { ); await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, { takerAddress, - gasPrice: GAS_PRICE, gasLimit: 4000000, ethAmount: new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI), }); diff --git a/packages/asset-swapper/test/swap_quote_calculator_test.ts b/packages/asset-swapper/test/swap_quote_calculator_test.ts index 013aad277f..f996f6cf04 100644 --- a/packages/asset-swapper/test/swap_quote_calculator_test.ts +++ b/packages/asset-swapper/test/swap_quote_calculator_test.ts @@ -1,21 +1,28 @@ +import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers'; import { constants as devConstants } from '@0x/contracts-test-utils'; +import { BlockchainLifecycle } from '@0x/dev-utils'; import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; +import { ProtocolFeeUtils } from '../src/utils/protocol_fee_utils'; import { swapQuoteCalculator } from '../src/utils/swap_quote_calculator'; import { chaiSetup } from './utils/chai_setup'; +import { migrateOnceAsync } from './utils/migrate'; import { testHelpers } from './utils/test_helpers'; import { testOrders } from './utils/test_orders'; import { baseUnitAmount } from './utils/utils'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const GAS_PRICE = new BigNumber(devConstants.DEFAULT_GAS_PRICE); const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000); +const TESTRPC_CHAIN_ID = 1337; const MIXED_TEST_ORDERS = _.concat( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, @@ -25,105 +32,130 @@ const MIXED_TEST_ORDERS = _.concat( // tslint:disable:max-file-line-count // tslint:disable:custom-no-magic-numbers describe('swapQuoteCalculator', () => { + let contractWrappers: ContractWrappers; + let protocolFeeUtils: ProtocolFeeUtils; + let contractAddresses: ContractAddresses; + const chainId = TESTRPC_CHAIN_ID; + + before(async () => { + const config = { + chainId, + contractAddresses, + }; + contractAddresses = await migrateOnceAsync(); + await blockchainLifecycle.startAsync(); + contractWrappers = new ContractWrappers(provider, config); + protocolFeeUtils = new ProtocolFeeUtils(contractWrappers.exchange); + }); + describe('#calculateMarketSellSwapQuote', () => { describe('InsufficientLiquidityError', () => { it('should throw if not enough taker asset liquidity (multiple feeless orders)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, baseUnitAmount(10), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(9)); }); it('should throw if not enough taker asset liquidity (multiple feeless orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, baseUnitAmount(10), 0.2, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(7.5)); }); it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with no slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, baseUnitAmount(20), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(15)); }); it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, baseUnitAmount(20), 0.2, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(12.5)); }); it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with no slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, baseUnitAmount(10), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(9)); }); it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, baseUnitAmount(10), 0.2, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(7.5)); }); it('should throw if not enough taker asset liquidity (multiple mixed feeType orders with no slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( MIXED_TEST_ORDERS, baseUnitAmount(40), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(33)); }); it('should throw if not enough taker asset liquidity (multiple mixed feeTyoe orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketSellSwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( MIXED_TEST_ORDERS, baseUnitAmount(40), 0.2, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(27.5)); }); }); - it('calculates a correct swapQuote with no slippage (feeless orders)', () => { + it('calculates a correct swapQuote with no slippage (feeless orders)', async () => { const assetSellAmount = baseUnitAmount(0.5); const slippagePercentage = 0; - const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, assetSellAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEELESS[0]]); @@ -144,14 +176,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(15, 4), }); }); - it('calculates a correct swapQuote with slippage (feeless orders)', () => { + it('calculates a correct swapQuote with slippage (feeless orders)', async () => { const assetSellAmount = baseUnitAmount(1); const slippagePercentage = 0.2; - const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, assetSellAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([ @@ -175,14 +208,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(30, 4), }); }); - it('calculates a correct swapQuote with no slippage (takerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with no slippage (takerAsset denominated fee orders)', async () => { const assetSellAmount = baseUnitAmount(4); const slippagePercentage = 0; - const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, assetSellAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[0]]); @@ -203,14 +237,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(15, 4), }); }); - it('calculates a correct swapQuote with slippage (takerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with slippage (takerAsset denominated fee orders)', async () => { const assetSellAmount = baseUnitAmount(3); const slippagePercentage = 0.5; - const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, assetSellAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([ @@ -234,14 +269,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(30, 4), }); }); - it('calculates a correct swapQuote with no slippage (makerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with no slippage (makerAsset denominated fee orders)', async () => { const assetSellAmount = baseUnitAmount(4); const slippagePercentage = 0; - const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, assetSellAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[0]]); @@ -262,14 +298,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(15, 4), }); }); - it('calculates a correct swapQuote with slippage (makerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with slippage (makerAsset denominated fee orders)', async () => { const assetSellAmount = baseUnitAmount(4); const slippagePercentage = 0.5; - const swapQuote = swapQuoteCalculator.calculateMarketSellSwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketSellSwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, assetSellAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([ @@ -295,105 +332,114 @@ describe('swapQuoteCalculator', () => { }); }); }); - describe('#calculateMarketBuySwapQuote', () => { + describe('#calculateMarketBuySwapQuoteAsync', () => { describe('InsufficientLiquidityError', () => { it('should throw if not enough maker asset liquidity (multiple feeless orders)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, baseUnitAmount(12), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(10)); }); it('should throw if not enough taker asset liquidity (multiple feeless orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, baseUnitAmount(10), 0.6, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(6.25)); }); it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with no slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, baseUnitAmount(12), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(10)); }); it('should throw if not enough taker asset liquidity (multiple takerAsset denominated fee orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, baseUnitAmount(12), 0.6, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(6.25)); }); it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with no slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, baseUnitAmount(6), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(5)); }); it('should throw if not enough taker asset liquidity (multiple makerAsset denominated fee orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, baseUnitAmount(6), 0.6, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(3.125)); }); it('should throw if not enough taker asset liquidity (multiple mixed feeType orders with no slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( MIXED_TEST_ORDERS, baseUnitAmount(40), 0, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(25)); }); it('should throw if not enough taker asset liquidity (multiple mixed feeTyoe orders with 20% slippage)', () => { - const errorFunction = () => { - swapQuoteCalculator.calculateMarketBuySwapQuote( + const errorFunction = async () => { + await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( MIXED_TEST_ORDERS, baseUnitAmount(40), 0.6, GAS_PRICE, + protocolFeeUtils, ); }; testHelpers.expectInsufficientLiquidityError(expect, errorFunction, baseUnitAmount(15.625)); }); }); - it('calculates a correct swapQuote with no slippage (feeless orders)', () => { + it('calculates a correct swapQuote with no slippage (feeless orders)', async () => { const assetBuyAmount = baseUnitAmount(3); const slippagePercentage = 0; - const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, assetBuyAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEELESS[0]]); @@ -414,14 +460,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(15, 4), }); }); - it('calculates a correct swapQuote with slippage (feeless orders)', () => { + it('calculates a correct swapQuote with slippage (feeless orders)', async () => { const assetBuyAmount = baseUnitAmount(5); const slippagePercentage = 0.5; - const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEELESS, assetBuyAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([ @@ -450,14 +497,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(30, 4), }); }); - it('calculates a correct swapQuote with no slippage (takerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with no slippage (takerAsset denominated fee orders)', async () => { const assetBuyAmount = baseUnitAmount(3); const slippagePercentage = 0; - const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, assetBuyAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET[0]]); @@ -478,14 +526,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(15, 4), }); }); - it('calculates a correct swapQuote with slippage (takerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with slippage (takerAsset denominated fee orders)', async () => { const assetBuyAmount = baseUnitAmount(5); const slippagePercentage = 0.5; - const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_TAKER_ASSET, assetBuyAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); const fiveSixthEthInWei = new BigNumber(5) .div(new BigNumber(6)) @@ -513,14 +562,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(30, 4), }); }); - it('calculates a correct swapQuote with no slippage (makerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with no slippage (makerAsset denominated fee orders)', async () => { const assetBuyAmount = baseUnitAmount(1); const slippagePercentage = 0; - const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, assetBuyAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET[0]]); @@ -541,14 +591,15 @@ describe('swapQuoteCalculator', () => { protocolFeeInEthAmount: baseUnitAmount(15, 4), }); }); - it('calculates a correct swapQuote with slippage (makerAsset denominated fee orders)', () => { + it('calculates a correct swapQuote with slippage (makerAsset denominated fee orders)', async () => { const assetBuyAmount = baseUnitAmount(2.5); const slippagePercentage = 0.5; - const swapQuote = swapQuoteCalculator.calculateMarketBuySwapQuote( + const swapQuote = await swapQuoteCalculator.calculateMarketBuySwapQuoteAsync( testOrders.PRUNED_SIGNED_ORDERS_FEE_IN_MAKER_ASSET, assetBuyAmount, slippagePercentage, GAS_PRICE, + protocolFeeUtils, ); const totalTakerAssetAmount = new BigNumber(5) .div(new BigNumber(6)) diff --git a/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts b/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts index 6781f265f6..4cc5183f5f 100644 --- a/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts +++ b/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts @@ -11,9 +11,11 @@ import 'mocha'; import { SwapQuote, SwapQuoteConsumer } from '../src'; import { constants } from '../src/constants'; import { ExtensionContractType, MarketOperation, PrunedSignedOrder } from '../src/types'; +import { ProtocolFeeUtils } from '../src/utils/protocol_fee_utils'; import { chaiSetup } from './utils/chai_setup'; -import { getFullyFillableSwapQuoteWithNoFees } from './utils/swap_quote'; +import { getFullyFillableSwapQuoteWithNoFeesAsync } from './utils/swap_quote'; + import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -68,6 +70,8 @@ const PARTIAL_LARGE_PRUNED_SIGNED_ORDERS: Array> = [ describe('swapQuoteConsumerUtils', () => { let wethContract: WETH9Contract; + let contractWrappers: ContractWrappers; + let protocolFeeUtils: ProtocolFeeUtils; let userAddresses: string[]; let makerAddress: string; let takerAddress: string; @@ -118,6 +122,7 @@ describe('swapQuoteConsumerUtils', () => { }; const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); + protocolFeeUtils = new ProtocolFeeUtils(contractWrappers.exchange); forwarderOrderFactory = new OrderFactory(privateKey, defaultForwarderOrderParams); swapQuoteConsumer = new SwapQuoteConsumer(provider, { @@ -173,28 +178,31 @@ describe('swapQuoteConsumerUtils', () => { largeForwarderOrders.push(prunedOrder as PrunedSignedOrder); } - forwarderSwapQuote = getFullyFillableSwapQuoteWithNoFees( + forwarderSwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, wethAssetData, forwarderOrders, MarketOperation.Sell, GAS_PRICE, + protocolFeeUtils, ); - largeForwarderSwapQuote = getFullyFillableSwapQuoteWithNoFees( + largeForwarderSwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, wethAssetData, largeForwarderOrders, MarketOperation.Sell, GAS_PRICE, + protocolFeeUtils, ); - exchangeSwapQuote = getFullyFillableSwapQuoteWithNoFees( + exchangeSwapQuote = await getFullyFillableSwapQuoteWithNoFeesAsync( makerAssetData, takerAssetData, exchangeOrders, MarketOperation.Sell, GAS_PRICE, + protocolFeeUtils, ); }); diff --git a/packages/asset-swapper/test/utils/mocks.ts b/packages/asset-swapper/test/utils/mocks.ts index 6aa6ec724f..eea3661450 100644 --- a/packages/asset-swapper/test/utils/mocks.ts +++ b/packages/asset-swapper/test/utils/mocks.ts @@ -1,10 +1,17 @@ +import { constants as devConstants } from '@0x/contracts-test-utils'; import { AcceptedRejectedOrders, Orderbook } from '@0x/orderbook'; import { Web3ProviderEngine } from '@0x/subproviders'; import { APIOrder, AssetPairsItem, SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; import * as TypeMoq from 'typemoq'; import { SwapQuoter } from '../../src/swap_quoter'; import { PrunedSignedOrder } from '../../src/types'; +import { ProtocolFeeUtils } from '../../src/utils/protocol_fee_utils'; + +const PROTOCOL_FEE_MULTIPLIER = 150000; + +// tslint:disable: max-classes-per-file class OrderbookClass extends Orderbook { // tslint:disable-next-line:prefer-function-over-method @@ -49,6 +56,21 @@ const partiallyMockedSwapQuoter = (provider: Web3ProviderEngine, orderbook: Orde return mockedSwapQuoter; }; +class ProtocolFeeUtilsClass extends ProtocolFeeUtils { + // tslint:disable-next-line:prefer-function-over-method + public async getProtocolFeeMultiplierAsync(): Promise { + return Promise.resolve(new BigNumber(PROTOCOL_FEE_MULTIPLIER)); + } + // tslint:disable-next-line:prefer-function-over-method + public async getGasPriceEstimationOrThrowAsync(): Promise { + return Promise.resolve(new BigNumber(devConstants.DEFAULT_GAS_PRICE)); + } +} + +export const protocolFeeUtilsMock = (): TypeMoq.IMock => { + return TypeMoq.Mock.ofType(ProtocolFeeUtilsClass, TypeMoq.MockBehavior.Strict); +}; + const mockGetPrunedSignedOrdersAsync = ( mockedSwapQuoter: TypeMoq.IMock, makerAssetData: string, diff --git a/packages/asset-swapper/test/utils/swap_quote.ts b/packages/asset-swapper/test/utils/swap_quote.ts index 1aab941a95..4f00a65d45 100644 --- a/packages/asset-swapper/test/utils/swap_quote.ts +++ b/packages/asset-swapper/test/utils/swap_quote.ts @@ -4,15 +4,16 @@ import * as _ from 'lodash'; import { constants } from '../../src/constants'; import { MarketOperation, PrunedSignedOrder, SwapQuote } from '../../src/types'; -import { protocolFeeUtils } from '../../src/utils/protocol_fee_utils'; +import { ProtocolFeeUtils } from '../../src/utils/protocol_fee_utils'; -export const getFullyFillableSwapQuoteWithNoFees = ( +export const getFullyFillableSwapQuoteWithNoFeesAsync = async ( makerAssetData: string, takerAssetData: string, orders: PrunedSignedOrder[], operation: MarketOperation, gasPrice: BigNumber, -): SwapQuote => { + protocolFeeUtils: ProtocolFeeUtils, +): Promise => { const makerAssetFillAmount = _.reduce( orders, (a: BigNumber, c: SignedOrder) => a.plus(c.makerAssetAmount), @@ -28,13 +29,14 @@ export const getFullyFillableSwapQuoteWithNoFees = ( feeTakerAssetAmount: constants.ZERO_AMOUNT, takerAssetAmount: totalTakerAssetAmount, totalTakerAssetAmount, - protocolFeeInEthAmount: protocolFeeUtils.calculateWorstCaseProtocolFee(orders, gasPrice), + protocolFeeInEthAmount: await protocolFeeUtils.calculateWorstCaseProtocolFeeAsync(orders, gasPrice), }; const quoteBase = { makerAssetData, takerAssetData, orders, + gasPrice, bestCaseQuoteInfo: quoteInfo, worstCaseQuoteInfo: quoteInfo, };