@0x/asset-swapper
: Add gasSchedule
option to SwapQuoter
.
`@0x/asset-swapper`: Rename `fees` `SwapQuoter` option to `feeSchedule`.
This commit is contained in:
parent
cc12ad8d86
commit
05bf55dca8
@ -169,6 +169,7 @@ export interface MarketBuySwapQuote extends SwapQuoteBase {
|
||||
* totalTakerAssetAmount: The total amount of takerAsset required to complete the swap (filling orders, and paying takerFees).
|
||||
* makerAssetAmount: The amount of makerAsset that will be acquired through the swap.
|
||||
* protocolFeeInWeiAmount: The amount of ETH to pay (in WEI) as protocol fee to perform the swap for desired asset.
|
||||
* gas: Amount of estimated gas needed to fill the quote.
|
||||
*/
|
||||
export interface SwapQuoteInfo {
|
||||
feeTakerAssetAmount: BigNumber;
|
||||
@ -176,6 +177,7 @@ export interface SwapQuoteInfo {
|
||||
totalTakerAssetAmount: BigNumber;
|
||||
makerAssetAmount: BigNumber;
|
||||
protocolFeeInWeiAmount: BigNumber;
|
||||
gas: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,6 +82,7 @@ export const assert = {
|
||||
);
|
||||
},
|
||||
isValidSwapQuoteInfo(variableName: string, swapQuoteInfo: SwapQuoteInfo): void {
|
||||
sharedAssert.isNumber(`${variableName}.gas`, swapQuoteInfo.gas);
|
||||
sharedAssert.isBigNumber(`${variableName}.feeTakerAssetAmount`, swapQuoteInfo.feeTakerAssetAmount);
|
||||
sharedAssert.isBigNumber(`${variableName}.totalTakerAssetAmount`, swapQuoteInfo.totalTakerAssetAmount);
|
||||
sharedAssert.isBigNumber(`${variableName}.takerAssetAmount`, swapQuoteInfo.takerAssetAmount);
|
||||
|
@ -30,7 +30,8 @@ export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
|
||||
bridgeSlippage: 0.005,
|
||||
numSamples: 20,
|
||||
sampleDistributionBase: 1.05,
|
||||
fees: {},
|
||||
feeSchedule: {},
|
||||
gasSchedule: {},
|
||||
allowFallback: true,
|
||||
};
|
||||
|
||||
|
@ -26,18 +26,18 @@ export function createFillPaths(opts: {
|
||||
targetInput?: BigNumber;
|
||||
ethToOutputRate?: BigNumber;
|
||||
excludedSources?: ERC20BridgeSource[];
|
||||
fees?: { [source: string]: BigNumber };
|
||||
feeSchedule?: { [source: string]: BigNumber };
|
||||
}): Fill[][] {
|
||||
const { side } = opts;
|
||||
const excludedSources = opts.excludedSources || [];
|
||||
const fees = opts.fees || {};
|
||||
const feeSchedule = opts.feeSchedule || {};
|
||||
const orders = opts.orders || [];
|
||||
const dexQuotes = opts.dexQuotes || [];
|
||||
const ethToOutputRate = opts.ethToOutputRate || ZERO_AMOUNT;
|
||||
// Create native fill paths.
|
||||
const nativePath = nativeOrdersToPath(side, orders, ethToOutputRate, fees);
|
||||
const nativePath = nativeOrdersToPath(side, orders, ethToOutputRate, feeSchedule);
|
||||
// Create DEX fill paths.
|
||||
const dexPaths = dexQuotesToPaths(side, dexQuotes, ethToOutputRate, fees);
|
||||
const dexPaths = dexQuotesToPaths(side, dexQuotes, ethToOutputRate, feeSchedule);
|
||||
return filterPaths([...dexPaths, nativePath].map(p => clipPathToInput(p, opts.targetInput)), excludedSources);
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ export class MarketOperationUtils {
|
||||
ethToOutputRate: ethToMakerAssetRate,
|
||||
bridgeSlippage: _opts.bridgeSlippage,
|
||||
excludedSources: _opts.excludedSources,
|
||||
fees: _opts.fees,
|
||||
feeSchedule: _opts.feeSchedule,
|
||||
allowFallback: _opts.allowFallback,
|
||||
});
|
||||
}
|
||||
@ -170,7 +170,7 @@ export class MarketOperationUtils {
|
||||
ethToOutputRate: ethToTakerAssetRate,
|
||||
bridgeSlippage: _opts.bridgeSlippage,
|
||||
excludedSources: _opts.excludedSources,
|
||||
fees: _opts.fees,
|
||||
feeSchedule: _opts.feeSchedule,
|
||||
allowFallback: _opts.allowFallback,
|
||||
});
|
||||
}
|
||||
@ -242,7 +242,7 @@ export class MarketOperationUtils {
|
||||
ethToOutputRate: ethToTakerAssetRate,
|
||||
bridgeSlippage: _opts.bridgeSlippage,
|
||||
excludedSources: _opts.excludedSources,
|
||||
fees: _opts.fees,
|
||||
feeSchedule: _opts.feeSchedule,
|
||||
allowFallback: _opts.allowFallback,
|
||||
});
|
||||
});
|
||||
@ -260,7 +260,7 @@ export class MarketOperationUtils {
|
||||
ethToOutputRate?: BigNumber;
|
||||
bridgeSlippage?: number;
|
||||
excludedSources?: ERC20BridgeSource[];
|
||||
fees?: { [source: string]: BigNumber };
|
||||
feeSchedule?: { [source: string]: BigNumber };
|
||||
allowFallback?: boolean;
|
||||
liquidityProviderAddress?: string;
|
||||
}): OptimizedMarketOrder[] {
|
||||
@ -274,7 +274,7 @@ export class MarketOperationUtils {
|
||||
targetInput: inputAmount,
|
||||
ethToOutputRate: opts.ethToOutputRate,
|
||||
excludedSources: opts.excludedSources,
|
||||
fees: opts.fees,
|
||||
feeSchedule: opts.feeSchedule,
|
||||
});
|
||||
// Find the optimal path.
|
||||
const optimalPath = findOptimalPath(side, paths, inputAmount, opts.runLimit);
|
||||
|
@ -167,7 +167,11 @@ export interface GetMarketOrdersOpts {
|
||||
/**
|
||||
* Fees for each liquidity source, expressed in gas.
|
||||
*/
|
||||
fees: { [source: string]: BigNumber };
|
||||
feeSchedule: { [source: string]: BigNumber };
|
||||
/**
|
||||
* Estimated gas consumed by each liquidity source.
|
||||
*/
|
||||
gasSchedule: { [source: string]: number };
|
||||
/**
|
||||
* Whether to pad the quote with a redundant fallback quote using different
|
||||
* sources.
|
||||
|
@ -106,6 +106,7 @@ export class SwapQuoteCalculator {
|
||||
operation,
|
||||
assetFillAmounts[i],
|
||||
gasPrice,
|
||||
opts.gasSchedule,
|
||||
);
|
||||
} else {
|
||||
return undefined;
|
||||
@ -133,7 +134,7 @@ export class SwapQuoteCalculator {
|
||||
// Scale fees by gas price.
|
||||
const _opts = {
|
||||
...opts,
|
||||
fees: _.mapValues(opts.fees, (v, k) => v.times(gasPrice)),
|
||||
fees: _.mapValues(opts.feeSchedule, v => v.times(gasPrice)),
|
||||
};
|
||||
|
||||
const firstOrderMakerAssetData = !!prunedOrders[0]
|
||||
@ -169,6 +170,7 @@ export class SwapQuoteCalculator {
|
||||
operation,
|
||||
assetFillAmount,
|
||||
gasPrice,
|
||||
opts.gasSchedule,
|
||||
);
|
||||
}
|
||||
private async _createSwapQuoteAsync(
|
||||
@ -178,17 +180,20 @@ export class SwapQuoteCalculator {
|
||||
operation: MarketOperation,
|
||||
assetFillAmount: BigNumber,
|
||||
gasPrice: BigNumber,
|
||||
gasSchedule: { [source: string]: number },
|
||||
): Promise<SwapQuote> {
|
||||
const bestCaseQuoteInfo = await this._calculateQuoteInfoAsync(
|
||||
resultOrders,
|
||||
assetFillAmount,
|
||||
gasPrice,
|
||||
gasSchedule,
|
||||
operation,
|
||||
);
|
||||
const worstCaseQuoteInfo = await this._calculateQuoteInfoAsync(
|
||||
resultOrders,
|
||||
assetFillAmount,
|
||||
gasPrice,
|
||||
gasSchedule,
|
||||
operation,
|
||||
true,
|
||||
);
|
||||
@ -226,14 +231,16 @@ export class SwapQuoteCalculator {
|
||||
orders: OptimizedMarketOrder[],
|
||||
assetFillAmount: BigNumber,
|
||||
gasPrice: BigNumber,
|
||||
gasSchedule: { [source: string]: number },
|
||||
operation: MarketOperation,
|
||||
worstCase: boolean = false,
|
||||
): Promise<SwapQuoteInfo> {
|
||||
if (operation === MarketOperation.Buy) {
|
||||
return this._calculateMarketBuyQuoteInfoAsync(orders, assetFillAmount, gasPrice, worstCase);
|
||||
} else {
|
||||
return this._calculateMarketSellQuoteInfoAsync(orders, assetFillAmount, gasPrice, worstCase);
|
||||
}
|
||||
return {
|
||||
...(operation === MarketOperation.Buy
|
||||
? await this._calculateMarketBuyQuoteInfoAsync(orders, assetFillAmount, gasPrice, worstCase)
|
||||
: await this._calculateMarketSellQuoteInfoAsync(orders, assetFillAmount, gasPrice, worstCase)),
|
||||
gas: getGasUsedByOrders(orders, gasSchedule),
|
||||
};
|
||||
}
|
||||
|
||||
private async _calculateMarketSellQuoteInfoAsync(
|
||||
@ -327,6 +334,7 @@ export class SwapQuoteCalculator {
|
||||
totalTakerAssetAmount: totalFeeTakerAssetAmount.plus(totalTakerAssetAmount),
|
||||
makerAssetAmount: totalMakerAssetAmount,
|
||||
protocolFeeInWeiAmount,
|
||||
gas: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -416,6 +424,7 @@ export class SwapQuoteCalculator {
|
||||
totalTakerAssetAmount: totalFeeTakerAssetAmount.plus(totalTakerAssetAmount),
|
||||
makerAssetAmount: totalMakerAssetAmount,
|
||||
protocolFeeInWeiAmount,
|
||||
gas: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -485,3 +494,12 @@ function getTakerAssetAmountBreakDown(
|
||||
takerAssetAmount: takerAssetAmountWithFees,
|
||||
};
|
||||
}
|
||||
|
||||
function getGasUsedByOrders(orders: OptimizedMarketOrder[], gasSchedule: { [source: string]: number }): number {
|
||||
let totalUsage = 0;
|
||||
for (const order of orders) {
|
||||
totalUsage += gasSchedule[order.fill.source] || 0;
|
||||
}
|
||||
return totalUsage;
|
||||
}
|
||||
// tslint:disable: max-file-line-count
|
||||
|
@ -486,7 +486,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
[ERC20BridgeSource.Eth2Dai]: [0.95, 0.1, 0.1, 0.1],
|
||||
[ERC20BridgeSource.Kyber]: [0.1, 0.1, 0.1, 0.1],
|
||||
};
|
||||
const fees = {
|
||||
const feeSchedule = {
|
||||
[ERC20BridgeSource.Native]: FILL_AMOUNT.div(4)
|
||||
.times(nativeFeeRate)
|
||||
.dividedToIntegerBy(ETH_TO_MAKER_RATE),
|
||||
@ -498,7 +498,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
const improvedOrders = await marketOperationUtils.getMarketSellOrdersAsync(
|
||||
createOrdersFromSellRates(FILL_AMOUNT, rates[ERC20BridgeSource.Native]),
|
||||
FILL_AMOUNT,
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, fees },
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, feeSchedule },
|
||||
);
|
||||
const orderSources = improvedOrders.map(o => o.fill.source);
|
||||
const expectedSources = [
|
||||
@ -521,7 +521,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
// Effectively [0.8, ~0.5, ~0, ~0]
|
||||
[ERC20BridgeSource.Uniswap]: [1, 0.7, 0.2, 0.2],
|
||||
};
|
||||
const fees = {
|
||||
const feeSchedule = {
|
||||
[ERC20BridgeSource.Uniswap]: FILL_AMOUNT.div(4)
|
||||
.times(uniswapFeeRate)
|
||||
.dividedToIntegerBy(ETH_TO_MAKER_RATE),
|
||||
@ -533,7 +533,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
const improvedOrders = await marketOperationUtils.getMarketSellOrdersAsync(
|
||||
createOrdersFromSellRates(FILL_AMOUNT, rates[ERC20BridgeSource.Native]),
|
||||
FILL_AMOUNT,
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, fees },
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, feeSchedule },
|
||||
);
|
||||
const orderSources = improvedOrders.map(o => o.fill.source);
|
||||
const expectedSources = [
|
||||
@ -828,7 +828,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
[ERC20BridgeSource.Eth2Dai]: [0.95, 0.1, 0.1, 0.1],
|
||||
[ERC20BridgeSource.Kyber]: [0.1, 0.1, 0.1, 0.1],
|
||||
};
|
||||
const fees = {
|
||||
const feeSchedule = {
|
||||
[ERC20BridgeSource.Native]: FILL_AMOUNT.div(4)
|
||||
.times(nativeFeeRate)
|
||||
.dividedToIntegerBy(ETH_TO_TAKER_RATE),
|
||||
@ -840,7 +840,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
const improvedOrders = await marketOperationUtils.getMarketBuyOrdersAsync(
|
||||
createOrdersFromBuyRates(FILL_AMOUNT, rates[ERC20BridgeSource.Native]),
|
||||
FILL_AMOUNT,
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, fees },
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, feeSchedule },
|
||||
);
|
||||
const orderSources = improvedOrders.map(o => o.fill.source);
|
||||
const expectedSources = [
|
||||
@ -862,7 +862,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
[ERC20BridgeSource.Uniswap]: [1, 0.7, 0.2, 0.2],
|
||||
[ERC20BridgeSource.Eth2Dai]: [0.92, 0.1, 0.1, 0.1],
|
||||
};
|
||||
const fees = {
|
||||
const feeSchedule = {
|
||||
[ERC20BridgeSource.Uniswap]: FILL_AMOUNT.div(4)
|
||||
.times(uniswapFeeRate)
|
||||
.dividedToIntegerBy(ETH_TO_TAKER_RATE),
|
||||
@ -874,7 +874,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
const improvedOrders = await marketOperationUtils.getMarketBuyOrdersAsync(
|
||||
createOrdersFromBuyRates(FILL_AMOUNT, rates[ERC20BridgeSource.Native]),
|
||||
FILL_AMOUNT,
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, fees },
|
||||
{ ...DEFAULT_OPTS, numSamples: 4, feeSchedule },
|
||||
);
|
||||
const orderSources = improvedOrders.map(o => o.fill.source);
|
||||
const expectedSources = [
|
||||
|
@ -25,6 +25,7 @@ export async function getFullyFillableSwapQuoteWithNoFeesAsync(
|
||||
takerAssetAmount: totalTakerAssetAmount,
|
||||
totalTakerAssetAmount,
|
||||
protocolFeeInWeiAmount: await protocolFeeUtils.calculateWorstCaseProtocolFeeAsync(orders, gasPrice),
|
||||
gas: 200e3,
|
||||
};
|
||||
|
||||
const breakdown = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user