linting issues
This commit is contained in:
@@ -18,7 +18,7 @@ export {
|
||||
export { SignedOrder } from '@0x/types';
|
||||
export { BigNumber } from '@0x/utils';
|
||||
|
||||
export { ForwarderSwapQuoteConsumer } from './quote_consumers/forwarder_swap_quote_consumer';
|
||||
export { DynamicSwapQuoteConsumer as SwapQuoteConsumer } from './quote_consumers/dynamic_swap_quote_consumer';
|
||||
export { SwapQuoter } from './swap_quoter';
|
||||
export { InsufficientAssetLiquidityError } from './errors';
|
||||
|
||||
@@ -29,7 +29,8 @@ export {
|
||||
SwapQuoterError,
|
||||
SwapQuoterOpts,
|
||||
SwapQuote,
|
||||
SwapQuoteExecutionOpts,
|
||||
DynamicSwapQuoteGetOutputOpts as SwapQuoteGetOutputOpts,
|
||||
DynamicSwapQuoteExecutionOpts as SwapQuoteExecutionOpts,
|
||||
SwapQuoteInfo,
|
||||
SwapQuoteRequestOpts,
|
||||
MarketBuySwapQuote,
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
import { ContractWrappers } from '@0x/contract-wrappers';
|
||||
import { BigNumber, providerUtils } from '@0x/utils';
|
||||
import { SupportedProvider, ZeroExProvider } from '@0x/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from '../constants';
|
||||
import {
|
||||
CalldataInfo,
|
||||
DynamicSwapQuoteExecutionOpts,
|
||||
DynamicSwapQuoteGetOutputOpts,
|
||||
ExchangeMarketBuySmartContractParams,
|
||||
ExchangeMarketSellSmartContractParams,
|
||||
ForwarderMarketBuySmartContractParams,
|
||||
ForwarderMarketSellSmartContractParams,
|
||||
SmartContractParamsInfo,
|
||||
SwapQuote,
|
||||
SwapQuoteConsumer,
|
||||
SwapQuoteConsumerOpts,
|
||||
} from '../types';
|
||||
import { assert } from '../utils/assert';
|
||||
import { assetDataUtils } from '../utils/asset_data_utils';
|
||||
import { swapQuoteConsumerUtils } from '../utils/swap_quote_consumer_utils';
|
||||
|
||||
import { ExchangeSwapQuoteConsumer } from './exchange_swap_quote_consumer';
|
||||
import { ForwarderSwapQuoteConsumer } from './forwarder_swap_quote_consumer';
|
||||
|
||||
type SmartContractParams = ExchangeMarketBuySmartContractParams | ExchangeMarketSellSmartContractParams | ForwarderMarketBuySmartContractParams | ForwarderMarketSellSmartContractParams;
|
||||
|
||||
type ValidSwapQuoteConsumer = ExchangeSwapQuoteConsumer | ForwarderSwapQuoteConsumer;
|
||||
|
||||
export class DynamicSwapQuoteConsumer
|
||||
implements SwapQuoteConsumer<SmartContractParams> {
|
||||
public readonly provider: ZeroExProvider;
|
||||
public readonly networkId: number;
|
||||
|
||||
private readonly _contractWrappers: ContractWrappers;
|
||||
private readonly _exchangeConsumer: ExchangeSwapQuoteConsumer;
|
||||
private readonly _forwarderConsumer: ForwarderSwapQuoteConsumer;
|
||||
|
||||
constructor(supportedProvider: SupportedProvider, options: Partial<SwapQuoteConsumerOpts> = {}) {
|
||||
const { networkId } = _.merge({}, constants.DEFAULT_SWAP_QUOTER_OPTS, options);
|
||||
assert.isNumber('networkId', networkId);
|
||||
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
this.provider = provider;
|
||||
this.networkId = networkId;
|
||||
this._contractWrappers = new ContractWrappers(this.provider, {
|
||||
networkId,
|
||||
});
|
||||
|
||||
this._exchangeConsumer = new ExchangeSwapQuoteConsumer(supportedProvider, options);
|
||||
this._forwarderConsumer = new ForwarderSwapQuoteConsumer(supportedProvider, options);
|
||||
}
|
||||
|
||||
public async getCalldataOrThrowAsync(
|
||||
quote: SwapQuote,
|
||||
opts: Partial<DynamicSwapQuoteGetOutputOpts>,
|
||||
): Promise<CalldataInfo> {
|
||||
assert.isValidSwapQuote('quote', quote);
|
||||
const consumer = await this._getConsumerForSwapQuoteAsync(quote, opts);
|
||||
return consumer.getCalldataOrThrowAsync(quote, opts);
|
||||
}
|
||||
|
||||
public async getSmartContractParamsOrThrowAsync(
|
||||
quote: SwapQuote,
|
||||
opts: Partial<DynamicSwapQuoteGetOutputOpts>,
|
||||
): Promise<SmartContractParamsInfo<SmartContractParams>> {
|
||||
assert.isValidSwapQuote('quote', quote);
|
||||
const consumer = await this._getConsumerForSwapQuoteAsync(quote, opts);
|
||||
return consumer.getSmartContractParamsOrThrowAsync(quote, opts);
|
||||
}
|
||||
|
||||
public async executeSwapQuoteOrThrowAsync(
|
||||
quote: SwapQuote,
|
||||
opts: Partial<DynamicSwapQuoteExecutionOpts>,
|
||||
): Promise<string> {
|
||||
assert.isValidSwapQuote('quote', quote);
|
||||
const consumer = await this._getConsumerForSwapQuoteAsync(quote, opts);
|
||||
return consumer.executeSwapQuoteOrThrowAsync(quote, opts);
|
||||
}
|
||||
|
||||
private async _getConsumerForSwapQuoteAsync(quote: SwapQuote, opts: Partial<DynamicSwapQuoteGetOutputOpts>): Promise<ValidSwapQuoteConsumer> {
|
||||
const wethAssetData = assetDataUtils.getEtherTokenAssetData(this._contractWrappers);
|
||||
if (swapQuoteConsumerUtils.isValidForwarderSwapQuote(quote, wethAssetData)) {
|
||||
if (opts.takerAddress !== undefined) {
|
||||
assert.isETHAddressHex('takerAddress', opts.takerAddress);
|
||||
}
|
||||
const ethAmount = opts.ethAmount || quote.worstCaseQuoteInfo.totalTakerTokenAmount;
|
||||
const takerAddress = await swapQuoteConsumerUtils.getTakerAddressOrThrowAsync(this.provider, opts);
|
||||
const takerEthAndWethBalance = await swapQuoteConsumerUtils.getEthAndWethBalanceAsync(this.provider, this._contractWrappers, takerAddress);
|
||||
// TODO(david): when considering if there is enough Eth balance, should account for gas costs.
|
||||
const isEnoughEthAndWethBalance = _.map(takerEthAndWethBalance, (balance: BigNumber) => balance.isGreaterThanOrEqualTo(ethAmount));
|
||||
if (isEnoughEthAndWethBalance[1]) { // should be more gas efficient to use exchange consumer, so if possible use it.
|
||||
return this._exchangeConsumer;
|
||||
} else if (isEnoughEthAndWethBalance[0] && !isEnoughEthAndWethBalance[1]) {
|
||||
return this._forwarderConsumer;
|
||||
}
|
||||
// Note: Should we default to a consumer if takerAddress has not enough Eth or Weth?
|
||||
return this._forwarderConsumer;
|
||||
} else {
|
||||
return this._exchangeConsumer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,6 +148,20 @@ export interface SwapQuoteExecutionOpts extends SwapQuoteGetOutputOpts {
|
||||
gasPrice?: BigNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* feePercentage: percentage (up to 5%) of the taker asset paid to feeRecipient
|
||||
* feeRecipient: address of the receiver of the feePercentage of taker asset
|
||||
* ethAmount: The amount of eth (in Wei) sent to the forwarder contract.
|
||||
*/
|
||||
export interface DynamicSwapQuoteGetOutputOpts extends SwapQuoteGetOutputOpts {
|
||||
takerAddress?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the options for executing a swap quote with ForwarderSwapQuoteConusmer
|
||||
*/
|
||||
export interface DynamicSwapQuoteExecutionOpts extends DynamicSwapQuoteGetOutputOpts, SwapQuoteExecutionOpts {}
|
||||
|
||||
/**
|
||||
* feePercentage: percentage (up to 5%) of the taker asset paid to feeRecipient
|
||||
* feeRecipient: address of the receiver of the feePercentage of taker asset
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { ContractWrappers } from '@0x/contract-wrappers';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { SupportedProvider, Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { SwapQuoteConsumerError, SwapQuoteExecutionOpts } from '../types';
|
||||
import { SwapQuote, SwapQuoteConsumerError, SwapQuoteExecutionOpts } from '../types';
|
||||
|
||||
export const swapQuoteConsumerUtils = {
|
||||
async getTakerAddressOrThrowAsync(
|
||||
@@ -21,4 +24,20 @@ export const swapQuoteConsumerUtils = {
|
||||
}
|
||||
}
|
||||
},
|
||||
async getEthAndWethBalanceAsync(provider: SupportedProvider, contractWrappers: ContractWrappers, takerAddress: string): Promise<[BigNumber, BigNumber]> {
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const wethAddress = contractWrappers.forwarder.etherTokenAddress;
|
||||
const ethBalance = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||
const wethBalance = await contractWrappers.erc20Token.getBalanceAsync(wethAddress, takerAddress);
|
||||
return [ethBalance, wethBalance];
|
||||
},
|
||||
isValidForwarderSwapQuote(swapQuote: SwapQuote, wethAssetData: string): boolean {
|
||||
return swapQuoteConsumerUtils.isValidForwarderSignedOrders(swapQuote.orders, wethAssetData) && swapQuoteConsumerUtils.isValidForwarderSignedOrders(swapQuote.feeOrders, wethAssetData);
|
||||
},
|
||||
isValidForwarderSignedOrders(orders: SignedOrder[], wethAssetData: string): boolean {
|
||||
return _.every(orders, order => swapQuoteConsumerUtils.isValidForwarderSignedOrder(order, wethAssetData));
|
||||
},
|
||||
isValidForwarderSignedOrder(order: SignedOrder, wethAssetData: string): boolean {
|
||||
return order.takerAssetData === wethAssetData;
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user