feat: asset-swapper market depth (#2641)
* feat: asset-swapper market depth * split promises into 2 * fix lint and docs * chore: refactor * rebase off development * CHANGELOG
This commit is contained in:
parent
72c869649a
commit
5afe2616a4
@ -17,6 +17,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Support more varied curves",
|
"note": "Support more varied curves",
|
||||||
"pr": 2633
|
"pr": 2633
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Adds `getBidAskLiquidityForMakerTakerAssetPairAsync` to return more detailed sample information",
|
||||||
|
"pr": 2641
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -64,30 +64,31 @@ export {
|
|||||||
SwapQuoteInfo,
|
SwapQuoteInfo,
|
||||||
SwapQuoteOrdersBreakdown,
|
SwapQuoteOrdersBreakdown,
|
||||||
SwapQuoteRequestOpts,
|
SwapQuoteRequestOpts,
|
||||||
SwapQuoterRfqtOpts,
|
|
||||||
SwapQuoterError,
|
SwapQuoterError,
|
||||||
SwapQuoterOpts,
|
SwapQuoterOpts,
|
||||||
|
SwapQuoterRfqtOpts,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { ERC20BridgeSource } from './utils/market_operation_utils/types';
|
|
||||||
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
|
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
|
||||||
export {
|
export {
|
||||||
BalancerFillData,
|
BalancerFillData,
|
||||||
CollapsedFill,
|
CollapsedFill,
|
||||||
CurveFillData,
|
CurveFillData,
|
||||||
|
CurveFunctionSelectors,
|
||||||
CurveInfo,
|
CurveInfo,
|
||||||
ERC20BridgeSource,
|
ERC20BridgeSource,
|
||||||
FeeSchedule,
|
FeeSchedule,
|
||||||
FillData,
|
FillData,
|
||||||
GetMarketOrdersRfqtOpts,
|
GetMarketOrdersRfqtOpts,
|
||||||
|
LiquidityProviderFillData,
|
||||||
|
MarketDepth,
|
||||||
|
MarketDepthSide,
|
||||||
|
MultiBridgeFillData,
|
||||||
NativeCollapsedFill,
|
NativeCollapsedFill,
|
||||||
NativeFillData,
|
NativeFillData,
|
||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
CurveFunctionSelectors,
|
|
||||||
} from './utils/market_operation_utils/types';
|
} from './utils/market_operation_utils/types';
|
||||||
export { ProtocolFeeUtils } from './utils/protocol_fee_utils';
|
export { ProtocolFeeUtils } from './utils/protocol_fee_utils';
|
||||||
export { QuoteRequestor } from './utils/quote_requestor';
|
|
||||||
export { rfqtMocker } from './utils/rfqt_mocker';
|
|
||||||
export {
|
export {
|
||||||
BridgeReportSource,
|
BridgeReportSource,
|
||||||
NativeOrderbookReportSource,
|
NativeOrderbookReportSource,
|
||||||
@ -95,4 +96,7 @@ export {
|
|||||||
QuoteReport,
|
QuoteReport,
|
||||||
QuoteReportSource,
|
QuoteReportSource,
|
||||||
} from './utils/quote_report_generator';
|
} from './utils/quote_report_generator';
|
||||||
|
export { QuoteRequestor } from './utils/quote_requestor';
|
||||||
|
export { rfqtMocker } from './utils/rfqt_mocker';
|
||||||
|
import { ERC20BridgeSource } from './utils/market_operation_utils/types';
|
||||||
export type Native = ERC20BridgeSource.Native;
|
export type Native = ERC20BridgeSource.Native;
|
||||||
|
@ -27,7 +27,12 @@ import { calculateLiquidity } from './utils/calculate_liquidity';
|
|||||||
import { MarketOperationUtils } from './utils/market_operation_utils';
|
import { MarketOperationUtils } from './utils/market_operation_utils';
|
||||||
import { createDummyOrderForSampler } from './utils/market_operation_utils/orders';
|
import { createDummyOrderForSampler } from './utils/market_operation_utils/orders';
|
||||||
import { DexOrderSampler } from './utils/market_operation_utils/sampler';
|
import { DexOrderSampler } from './utils/market_operation_utils/sampler';
|
||||||
import { ERC20BridgeSource } from './utils/market_operation_utils/types';
|
import {
|
||||||
|
ERC20BridgeSource,
|
||||||
|
MarketDepth,
|
||||||
|
MarketDepthSide,
|
||||||
|
MarketSideLiquidity,
|
||||||
|
} from './utils/market_operation_utils/types';
|
||||||
import { orderPrunerUtils } from './utils/order_prune_utils';
|
import { orderPrunerUtils } from './utils/order_prune_utils';
|
||||||
import { OrderStateUtils } from './utils/order_state_utils';
|
import { OrderStateUtils } from './utils/order_state_utils';
|
||||||
import { ProtocolFeeUtils } from './utils/protocol_fee_utils';
|
import { ProtocolFeeUtils } from './utils/protocol_fee_utils';
|
||||||
@ -393,6 +398,94 @@ export class SwapQuoter {
|
|||||||
return calculateLiquidity(ordersWithFillableAmounts);
|
return calculateLiquidity(ordersWithFillableAmounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bids and asks liquidity for the entire market.
|
||||||
|
* For certain sources (like AMM's) it is recommended to provide a practical maximum takerAssetAmount.
|
||||||
|
* @param makerTokenAddress The address of the maker asset
|
||||||
|
* @param takerTokenAddress The address of the taker asset
|
||||||
|
* @param takerAssetAmount The amount to sell and buy for the bids and asks.
|
||||||
|
*
|
||||||
|
* @return An object that conforms to MarketDepth that contains all of the samples and liquidity
|
||||||
|
* information for the source.
|
||||||
|
*/
|
||||||
|
public async getBidAskLiquidityForMakerTakerAssetPairAsync(
|
||||||
|
makerTokenAddress: string,
|
||||||
|
takerTokenAddress: string,
|
||||||
|
takerAssetAmount: BigNumber,
|
||||||
|
options: Partial<SwapQuoteRequestOpts> = {},
|
||||||
|
): Promise<MarketDepth> {
|
||||||
|
assert.isString('makerTokenAddress', makerTokenAddress);
|
||||||
|
assert.isString('takerTokenAddress', takerTokenAddress);
|
||||||
|
const makerAssetData = assetDataUtils.encodeERC20AssetData(makerTokenAddress);
|
||||||
|
const takerAssetData = assetDataUtils.encodeERC20AssetData(takerTokenAddress);
|
||||||
|
let [sellOrders, buyOrders] =
|
||||||
|
options.excludedSources && options.excludedSources.includes(ERC20BridgeSource.Native)
|
||||||
|
? Promise.resolve([[], []])
|
||||||
|
: await Promise.all([
|
||||||
|
this.orderbook.getOrdersAsync(makerAssetData, takerAssetData),
|
||||||
|
this.orderbook.getOrdersAsync(takerAssetData, makerAssetData),
|
||||||
|
]);
|
||||||
|
if (!sellOrders || sellOrders.length === 0) {
|
||||||
|
sellOrders = [
|
||||||
|
{
|
||||||
|
metaData: {},
|
||||||
|
order: createDummyOrderForSampler(
|
||||||
|
makerAssetData,
|
||||||
|
takerAssetData,
|
||||||
|
this._contractAddresses.uniswapBridge,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (!buyOrders || buyOrders.length === 0) {
|
||||||
|
buyOrders = [
|
||||||
|
{
|
||||||
|
metaData: {},
|
||||||
|
order: createDummyOrderForSampler(
|
||||||
|
takerAssetData,
|
||||||
|
makerAssetData,
|
||||||
|
this._contractAddresses.uniswapBridge,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const getMarketDepthSide = (marketSideLiquidity: MarketSideLiquidity): MarketDepthSide => {
|
||||||
|
const { dexQuotes, nativeOrders, orderFillableAmounts, side } = marketSideLiquidity;
|
||||||
|
return [
|
||||||
|
...dexQuotes,
|
||||||
|
nativeOrders.map((o, i) => {
|
||||||
|
const scaleFactor = orderFillableAmounts[i].div(o.takerAssetAmount);
|
||||||
|
return {
|
||||||
|
input: (side === MarketOperation.Sell ? o.takerAssetAmount : o.makerAssetAmount)
|
||||||
|
.times(scaleFactor)
|
||||||
|
.integerValue(),
|
||||||
|
output: (side === MarketOperation.Sell ? o.makerAssetAmount : o.takerAssetAmount)
|
||||||
|
.times(scaleFactor)
|
||||||
|
.integerValue(),
|
||||||
|
fillData: o,
|
||||||
|
source: ERC20BridgeSource.Native,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
const [bids, asks] = await Promise.all([
|
||||||
|
this._marketOperationUtils.getMarketBuyLiquidityAsync(
|
||||||
|
(buyOrders || []).map(o => o.order),
|
||||||
|
takerAssetAmount,
|
||||||
|
options,
|
||||||
|
),
|
||||||
|
this._marketOperationUtils.getMarketSellLiquidityAsync(
|
||||||
|
(sellOrders || []).map(o => o.order),
|
||||||
|
takerAssetAmount,
|
||||||
|
options,
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
return {
|
||||||
|
bids: getMarketDepthSide(bids),
|
||||||
|
asks: getMarketDepthSide(asks),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the asset data of all assets that can be used to purchase makerAssetData in the order provider passed in at init.
|
* Get the asset data of all assets that can be used to purchase makerAssetData in the order provider passed in at init.
|
||||||
*
|
*
|
||||||
|
@ -25,6 +25,7 @@ import {
|
|||||||
ERC20BridgeSource,
|
ERC20BridgeSource,
|
||||||
FeeSchedule,
|
FeeSchedule,
|
||||||
GetMarketOrdersOpts,
|
GetMarketOrdersOpts,
|
||||||
|
MarketSideLiquidity,
|
||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
OptimizedOrdersAndQuoteReport,
|
OptimizedOrdersAndQuoteReport,
|
||||||
OrderDomain,
|
OrderDomain,
|
||||||
@ -74,18 +75,17 @@ export class MarketOperationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the orders required for a market sell operation by (potentially) merging native orders with
|
* Gets the liquidity available for a market sell operation
|
||||||
* generated bridge orders.
|
|
||||||
* @param nativeOrders Native orders.
|
* @param nativeOrders Native orders.
|
||||||
* @param takerAmount Amount of taker asset to sell.
|
* @param takerAmount Amount of taker asset to sell.
|
||||||
* @param opts Options object.
|
* @param opts Options object.
|
||||||
* @return orders.
|
* @return MarketSideLiquidity.
|
||||||
*/
|
*/
|
||||||
public async getMarketSellOrdersAsync(
|
public async getMarketSellLiquidityAsync(
|
||||||
nativeOrders: SignedOrder[],
|
nativeOrders: SignedOrder[],
|
||||||
takerAmount: BigNumber,
|
takerAmount: BigNumber,
|
||||||
opts?: Partial<GetMarketOrdersOpts>,
|
opts?: Partial<GetMarketOrdersOpts>,
|
||||||
): Promise<OptimizedOrdersAndQuoteReport> {
|
): Promise<MarketSideLiquidity> {
|
||||||
if (nativeOrders.length === 0) {
|
if (nativeOrders.length === 0) {
|
||||||
throw new Error(AggregationError.EmptyOrders);
|
throw new Error(AggregationError.EmptyOrders);
|
||||||
}
|
}
|
||||||
@ -156,41 +156,40 @@ export class MarketOperationUtils {
|
|||||||
rfqtIndicativeQuotes,
|
rfqtIndicativeQuotes,
|
||||||
[balancerQuotes],
|
[balancerQuotes],
|
||||||
] = await Promise.all([samplerPromise, rfqtPromise, balancerPromise]);
|
] = await Promise.all([samplerPromise, rfqtPromise, balancerPromise]);
|
||||||
return this._generateOptimizedOrdersAsync({
|
|
||||||
orderFillableAmounts,
|
// Attach the LiquidityProvider address to the sample fillData
|
||||||
nativeOrders,
|
(dexQuotes.find(quotes => quotes[0] && quotes[0].source === ERC20BridgeSource.LiquidityProvider) || []).forEach(
|
||||||
dexQuotes: dexQuotes.concat(balancerQuotes),
|
q => (q.fillData = { poolAddress: liquidityProviderAddress }),
|
||||||
rfqtIndicativeQuotes,
|
);
|
||||||
liquidityProviderAddress,
|
// Attach the MultiBridge address to the sample fillData
|
||||||
multiBridgeAddress: this._multiBridge,
|
(dexQuotes.find(quotes => quotes[0] && quotes[0].source === ERC20BridgeSource.MultiBridge) || []).forEach(
|
||||||
inputToken: takerToken,
|
q => (q.fillData = { poolAddress: this._multiBridge }),
|
||||||
outputToken: makerToken,
|
);
|
||||||
|
return {
|
||||||
side: MarketOperation.Sell,
|
side: MarketOperation.Sell,
|
||||||
inputAmount: takerAmount,
|
inputAmount: takerAmount,
|
||||||
|
inputToken: takerToken,
|
||||||
|
outputToken: makerToken,
|
||||||
|
dexQuotes: dexQuotes.concat(balancerQuotes),
|
||||||
|
nativeOrders,
|
||||||
|
orderFillableAmounts,
|
||||||
ethToOutputRate: ethToMakerAssetRate,
|
ethToOutputRate: ethToMakerAssetRate,
|
||||||
bridgeSlippage: _opts.bridgeSlippage,
|
rfqtIndicativeQuotes,
|
||||||
maxFallbackSlippage: _opts.maxFallbackSlippage,
|
};
|
||||||
excludedSources: _opts.excludedSources,
|
|
||||||
feeSchedule: _opts.feeSchedule,
|
|
||||||
allowFallback: _opts.allowFallback,
|
|
||||||
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
|
|
||||||
quoteRequestor: _opts.rfqt ? _opts.rfqt.quoteRequestor : undefined,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the orders required for a market buy operation by (potentially) merging native orders with
|
* Gets the liquidity available for a market buy operation
|
||||||
* generated bridge orders.
|
|
||||||
* @param nativeOrders Native orders.
|
* @param nativeOrders Native orders.
|
||||||
* @param makerAmount Amount of maker asset to buy.
|
* @param makerAmount Amount of maker asset to buy.
|
||||||
* @param opts Options object.
|
* @param opts Options object.
|
||||||
* @return object with optimized orders and a QuoteReport
|
* @return MarketSideLiquidity.
|
||||||
*/
|
*/
|
||||||
public async getMarketBuyOrdersAsync(
|
public async getMarketBuyLiquidityAsync(
|
||||||
nativeOrders: SignedOrder[],
|
nativeOrders: SignedOrder[],
|
||||||
makerAmount: BigNumber,
|
makerAmount: BigNumber,
|
||||||
opts?: Partial<GetMarketOrdersOpts>,
|
opts?: Partial<GetMarketOrdersOpts>,
|
||||||
): Promise<OptimizedOrdersAndQuoteReport> {
|
): Promise<MarketSideLiquidity> {
|
||||||
if (nativeOrders.length === 0) {
|
if (nativeOrders.length === 0) {
|
||||||
throw new Error(AggregationError.EmptyOrders);
|
throw new Error(AggregationError.EmptyOrders);
|
||||||
}
|
}
|
||||||
@ -260,19 +259,68 @@ export class MarketOperationUtils {
|
|||||||
rfqtIndicativeQuotes,
|
rfqtIndicativeQuotes,
|
||||||
[balancerQuotes],
|
[balancerQuotes],
|
||||||
] = await Promise.all([samplerPromise, rfqtPromise, balancerPromise]);
|
] = await Promise.all([samplerPromise, rfqtPromise, balancerPromise]);
|
||||||
|
// Attach the LiquidityProvider address to the sample fillData
|
||||||
return this._generateOptimizedOrdersAsync({
|
(dexQuotes.find(quotes => quotes[0] && quotes[0].source === ERC20BridgeSource.LiquidityProvider) || []).forEach(
|
||||||
orderFillableAmounts,
|
q => (q.fillData = { poolAddress: liquidityProviderAddress }),
|
||||||
nativeOrders,
|
);
|
||||||
dexQuotes: dexQuotes.concat(balancerQuotes),
|
// Attach the MultiBridge address to the sample fillData
|
||||||
rfqtIndicativeQuotes,
|
(dexQuotes.find(quotes => quotes[0] && quotes[0].source === ERC20BridgeSource.MultiBridge) || []).forEach(
|
||||||
liquidityProviderAddress,
|
q => (q.fillData = { poolAddress: this._multiBridge }),
|
||||||
multiBridgeAddress: this._multiBridge,
|
);
|
||||||
inputToken: makerToken,
|
return {
|
||||||
outputToken: takerToken,
|
|
||||||
side: MarketOperation.Buy,
|
side: MarketOperation.Buy,
|
||||||
inputAmount: makerAmount,
|
inputAmount: makerAmount,
|
||||||
|
inputToken: makerToken,
|
||||||
|
outputToken: takerToken,
|
||||||
|
dexQuotes: dexQuotes.concat(balancerQuotes),
|
||||||
|
nativeOrders,
|
||||||
|
orderFillableAmounts,
|
||||||
ethToOutputRate: ethToTakerAssetRate,
|
ethToOutputRate: ethToTakerAssetRate,
|
||||||
|
rfqtIndicativeQuotes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the orders required for a market sell operation by (potentially) merging native orders with
|
||||||
|
* generated bridge orders.
|
||||||
|
* @param nativeOrders Native orders.
|
||||||
|
* @param takerAmount Amount of taker asset to sell.
|
||||||
|
* @param opts Options object.
|
||||||
|
* @return object with optimized orders and a QuoteReport
|
||||||
|
*/
|
||||||
|
public async getMarketSellOrdersAsync(
|
||||||
|
nativeOrders: SignedOrder[],
|
||||||
|
takerAmount: BigNumber,
|
||||||
|
opts?: Partial<GetMarketOrdersOpts>,
|
||||||
|
): Promise<OptimizedOrdersAndQuoteReport> {
|
||||||
|
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
|
||||||
|
const marketSideLiquidity = await this.getMarketSellLiquidityAsync(nativeOrders, takerAmount, _opts);
|
||||||
|
return this._generateOptimizedOrdersAsync(marketSideLiquidity, {
|
||||||
|
bridgeSlippage: _opts.bridgeSlippage,
|
||||||
|
maxFallbackSlippage: _opts.maxFallbackSlippage,
|
||||||
|
excludedSources: _opts.excludedSources,
|
||||||
|
feeSchedule: _opts.feeSchedule,
|
||||||
|
allowFallback: _opts.allowFallback,
|
||||||
|
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the orders required for a market buy operation by (potentially) merging native orders with
|
||||||
|
* generated bridge orders.
|
||||||
|
* @param nativeOrders Native orders.
|
||||||
|
* @param makerAmount Amount of maker asset to buy.
|
||||||
|
* @param opts Options object.
|
||||||
|
* @return object with optimized orders and a QuoteReport
|
||||||
|
*/
|
||||||
|
public async getMarketBuyOrdersAsync(
|
||||||
|
nativeOrders: SignedOrder[],
|
||||||
|
makerAmount: BigNumber,
|
||||||
|
opts?: Partial<GetMarketOrdersOpts>,
|
||||||
|
): Promise<OptimizedOrdersAndQuoteReport> {
|
||||||
|
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
|
||||||
|
const marketSideLiquidity = await this.getMarketBuyLiquidityAsync(nativeOrders, makerAmount, _opts);
|
||||||
|
return this._generateOptimizedOrdersAsync(marketSideLiquidity, {
|
||||||
bridgeSlippage: _opts.bridgeSlippage,
|
bridgeSlippage: _opts.bridgeSlippage,
|
||||||
maxFallbackSlippage: _opts.maxFallbackSlippage,
|
maxFallbackSlippage: _opts.maxFallbackSlippage,
|
||||||
excludedSources: _opts.excludedSources,
|
excludedSources: _opts.excludedSources,
|
||||||
@ -351,23 +399,28 @@ export class MarketOperationUtils {
|
|||||||
const dexQuotes = batchDexQuotes[i];
|
const dexQuotes = batchDexQuotes[i];
|
||||||
const makerAmount = makerAmounts[i];
|
const makerAmount = makerAmounts[i];
|
||||||
try {
|
try {
|
||||||
return (await this._generateOptimizedOrdersAsync({
|
const { optimizedOrders } = await this._generateOptimizedOrdersAsync(
|
||||||
orderFillableAmounts,
|
{
|
||||||
|
side: MarketOperation.Buy,
|
||||||
nativeOrders,
|
nativeOrders,
|
||||||
|
orderFillableAmounts,
|
||||||
dexQuotes,
|
dexQuotes,
|
||||||
|
inputAmount: makerAmount,
|
||||||
|
ethToOutputRate: ethToTakerAssetRate,
|
||||||
rfqtIndicativeQuotes: [],
|
rfqtIndicativeQuotes: [],
|
||||||
inputToken: makerToken,
|
inputToken: makerToken,
|
||||||
outputToken: takerToken,
|
outputToken: takerToken,
|
||||||
side: MarketOperation.Buy,
|
},
|
||||||
inputAmount: makerAmount,
|
{
|
||||||
ethToOutputRate: ethToTakerAssetRate,
|
|
||||||
bridgeSlippage: _opts.bridgeSlippage,
|
bridgeSlippage: _opts.bridgeSlippage,
|
||||||
maxFallbackSlippage: _opts.maxFallbackSlippage,
|
maxFallbackSlippage: _opts.maxFallbackSlippage,
|
||||||
excludedSources: _opts.excludedSources,
|
excludedSources: _opts.excludedSources,
|
||||||
feeSchedule: _opts.feeSchedule,
|
feeSchedule: _opts.feeSchedule,
|
||||||
allowFallback: _opts.allowFallback,
|
allowFallback: _opts.allowFallback,
|
||||||
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
|
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
|
||||||
})).optimizedOrders;
|
},
|
||||||
|
);
|
||||||
|
return optimizedOrders;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// It's possible for one of the pairs to have no path
|
// It's possible for one of the pairs to have no path
|
||||||
// rather than throw NO_OPTIMAL_PATH we return undefined
|
// rather than throw NO_OPTIMAL_PATH we return undefined
|
||||||
@ -377,40 +430,42 @@ export class MarketOperationUtils {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _generateOptimizedOrdersAsync(opts: {
|
private async _generateOptimizedOrdersAsync(
|
||||||
side: MarketOperation;
|
marketSideLiquidity: MarketSideLiquidity,
|
||||||
inputToken: string;
|
opts: {
|
||||||
outputToken: string;
|
|
||||||
inputAmount: BigNumber;
|
|
||||||
nativeOrders: SignedOrder[];
|
|
||||||
orderFillableAmounts: BigNumber[];
|
|
||||||
dexQuotes: DexSample[][];
|
|
||||||
rfqtIndicativeQuotes: RFQTIndicativeQuote[];
|
|
||||||
runLimit?: number;
|
runLimit?: number;
|
||||||
ethToOutputRate?: BigNumber;
|
|
||||||
bridgeSlippage?: number;
|
bridgeSlippage?: number;
|
||||||
maxFallbackSlippage?: number;
|
maxFallbackSlippage?: number;
|
||||||
excludedSources?: ERC20BridgeSource[];
|
excludedSources?: ERC20BridgeSource[];
|
||||||
feeSchedule?: FeeSchedule;
|
feeSchedule?: FeeSchedule;
|
||||||
allowFallback?: boolean;
|
allowFallback?: boolean;
|
||||||
shouldBatchBridgeOrders?: boolean;
|
shouldBatchBridgeOrders?: boolean;
|
||||||
liquidityProviderAddress?: string;
|
|
||||||
multiBridgeAddress?: string;
|
|
||||||
quoteRequestor?: QuoteRequestor;
|
quoteRequestor?: QuoteRequestor;
|
||||||
}): Promise<OptimizedOrdersAndQuoteReport> {
|
},
|
||||||
const { inputToken, outputToken, side, inputAmount } = opts;
|
): Promise<OptimizedOrdersAndQuoteReport> {
|
||||||
|
const {
|
||||||
|
inputToken,
|
||||||
|
outputToken,
|
||||||
|
side,
|
||||||
|
inputAmount,
|
||||||
|
nativeOrders,
|
||||||
|
orderFillableAmounts,
|
||||||
|
rfqtIndicativeQuotes,
|
||||||
|
dexQuotes,
|
||||||
|
ethToOutputRate,
|
||||||
|
} = marketSideLiquidity;
|
||||||
const maxFallbackSlippage = opts.maxFallbackSlippage || 0;
|
const maxFallbackSlippage = opts.maxFallbackSlippage || 0;
|
||||||
// Convert native orders and dex quotes into fill paths.
|
// Convert native orders and dex quotes into fill paths.
|
||||||
const paths = createFillPaths({
|
const paths = createFillPaths({
|
||||||
side,
|
side,
|
||||||
// Augment native orders with their fillable amounts.
|
// Augment native orders with their fillable amounts.
|
||||||
orders: [
|
orders: [
|
||||||
...createSignedOrdersWithFillableAmounts(side, opts.nativeOrders, opts.orderFillableAmounts),
|
...createSignedOrdersWithFillableAmounts(side, nativeOrders, orderFillableAmounts),
|
||||||
...createSignedOrdersFromRfqtIndicativeQuotes(opts.rfqtIndicativeQuotes),
|
...createSignedOrdersFromRfqtIndicativeQuotes(rfqtIndicativeQuotes),
|
||||||
],
|
],
|
||||||
dexQuotes: opts.dexQuotes,
|
dexQuotes,
|
||||||
targetInput: inputAmount,
|
targetInput: inputAmount,
|
||||||
ethToOutputRate: opts.ethToOutputRate,
|
ethToOutputRate,
|
||||||
excludedSources: opts.excludedSources,
|
excludedSources: opts.excludedSources,
|
||||||
feeSchedule: opts.feeSchedule,
|
feeSchedule: opts.feeSchedule,
|
||||||
});
|
});
|
||||||
@ -458,15 +513,13 @@ export class MarketOperationUtils {
|
|||||||
orderDomain: this._orderDomain,
|
orderDomain: this._orderDomain,
|
||||||
contractAddresses: this.contractAddresses,
|
contractAddresses: this.contractAddresses,
|
||||||
bridgeSlippage: opts.bridgeSlippage || 0,
|
bridgeSlippage: opts.bridgeSlippage || 0,
|
||||||
liquidityProviderAddress: opts.liquidityProviderAddress,
|
|
||||||
multiBridgeAddress: opts.multiBridgeAddress,
|
|
||||||
shouldBatchBridgeOrders: !!opts.shouldBatchBridgeOrders,
|
shouldBatchBridgeOrders: !!opts.shouldBatchBridgeOrders,
|
||||||
});
|
});
|
||||||
const quoteReport = new QuoteReportGenerator(
|
const quoteReport = new QuoteReportGenerator(
|
||||||
opts.side,
|
side,
|
||||||
_.flatten(opts.dexQuotes),
|
_.flatten(dexQuotes),
|
||||||
opts.nativeOrders,
|
nativeOrders,
|
||||||
opts.orderFillableAmounts,
|
orderFillableAmounts,
|
||||||
_.flatten(optimizedOrders.map(o => o.fills)),
|
_.flatten(optimizedOrders.map(o => o.fills)),
|
||||||
opts.quoteRequestor,
|
opts.quoteRequestor,
|
||||||
).generateReport();
|
).generateReport();
|
||||||
|
@ -24,6 +24,8 @@ import {
|
|||||||
CurveFillData,
|
CurveFillData,
|
||||||
ERC20BridgeSource,
|
ERC20BridgeSource,
|
||||||
Fill,
|
Fill,
|
||||||
|
LiquidityProviderFillData,
|
||||||
|
MultiBridgeFillData,
|
||||||
NativeCollapsedFill,
|
NativeCollapsedFill,
|
||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
OrderDomain,
|
OrderDomain,
|
||||||
@ -143,8 +145,6 @@ export interface CreateOrderFromPathOpts {
|
|||||||
contractAddresses: ContractAddresses;
|
contractAddresses: ContractAddresses;
|
||||||
bridgeSlippage: number;
|
bridgeSlippage: number;
|
||||||
shouldBatchBridgeOrders: boolean;
|
shouldBatchBridgeOrders: boolean;
|
||||||
liquidityProviderAddress?: string;
|
|
||||||
multiBridgeAddress?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert sell fills into orders.
|
// Convert sell fills into orders.
|
||||||
@ -177,7 +177,8 @@ export function createOrdersFromPath(path: Fill[], opts: CreateOrderFromPathOpts
|
|||||||
return orders;
|
return orders;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBridgeAddressFromSource(source: ERC20BridgeSource, opts: CreateOrderFromPathOpts): string {
|
function getBridgeAddressFromFill(fill: CollapsedFill, opts: CreateOrderFromPathOpts): string {
|
||||||
|
const source = fill.source;
|
||||||
switch (source) {
|
switch (source) {
|
||||||
case ERC20BridgeSource.Eth2Dai:
|
case ERC20BridgeSource.Eth2Dai:
|
||||||
return opts.contractAddresses.eth2DaiBridge;
|
return opts.contractAddresses.eth2DaiBridge;
|
||||||
@ -192,15 +193,9 @@ function getBridgeAddressFromSource(source: ERC20BridgeSource, opts: CreateOrder
|
|||||||
case ERC20BridgeSource.Balancer:
|
case ERC20BridgeSource.Balancer:
|
||||||
return opts.contractAddresses.balancerBridge;
|
return opts.contractAddresses.balancerBridge;
|
||||||
case ERC20BridgeSource.LiquidityProvider:
|
case ERC20BridgeSource.LiquidityProvider:
|
||||||
if (opts.liquidityProviderAddress === undefined) {
|
return (fill.fillData as LiquidityProviderFillData).poolAddress;
|
||||||
throw new Error('Cannot create a LiquidityProvider order without a LiquidityProvider pool address.');
|
|
||||||
}
|
|
||||||
return opts.liquidityProviderAddress;
|
|
||||||
case ERC20BridgeSource.MultiBridge:
|
case ERC20BridgeSource.MultiBridge:
|
||||||
if (opts.multiBridgeAddress === undefined) {
|
return (fill.fillData as MultiBridgeFillData).poolAddress;
|
||||||
throw new Error('Cannot create a MultiBridge order without a MultiBridge address.');
|
|
||||||
}
|
|
||||||
return opts.multiBridgeAddress;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -209,7 +204,7 @@ function getBridgeAddressFromSource(source: ERC20BridgeSource, opts: CreateOrder
|
|||||||
|
|
||||||
function createBridgeOrder(fill: CollapsedFill, opts: CreateOrderFromPathOpts): OptimizedMarketOrder {
|
function createBridgeOrder(fill: CollapsedFill, opts: CreateOrderFromPathOpts): OptimizedMarketOrder {
|
||||||
const [makerToken, takerToken] = getMakerTakerTokens(opts);
|
const [makerToken, takerToken] = getMakerTakerTokens(opts);
|
||||||
const bridgeAddress = getBridgeAddressFromSource(fill.source, opts);
|
const bridgeAddress = getBridgeAddressFromFill(fill, opts);
|
||||||
|
|
||||||
let makerAssetData;
|
let makerAssetData;
|
||||||
switch (fill.source) {
|
switch (fill.source) {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers';
|
import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers';
|
||||||
|
import { RFQTIndicativeQuote } from '@0x/quote-server';
|
||||||
|
import { MarketOperation, SignedOrder } from '@0x/types';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
import { RfqtRequestOpts, SignedOrderWithFillableAmounts } from '../../types';
|
import { RfqtRequestOpts, SignedOrderWithFillableAmounts } from '../../types';
|
||||||
@ -86,6 +88,14 @@ export interface UniswapV2FillData extends FillData {
|
|||||||
tokenAddressPath: string[];
|
tokenAddressPath: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LiquidityProviderFillData extends FillData {
|
||||||
|
poolAddress: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MultiBridgeFillData extends FillData {
|
||||||
|
poolAddress: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an individual DEX sample from the sampler contract.
|
* Represents an individual DEX sample from the sampler contract.
|
||||||
*/
|
*/
|
||||||
@ -256,16 +266,26 @@ export interface SourceQuoteOperation<TFillData extends FillData = FillData> ext
|
|||||||
fillData?: TFillData;
|
fillData?: TFillData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used in the ERC20BridgeSampler when a source does not natively
|
|
||||||
* support sampling via a specific buy amount.
|
|
||||||
*/
|
|
||||||
export interface FakeBuyOpts {
|
|
||||||
targetSlippageBps: BigNumber;
|
|
||||||
maxIterations: BigNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OptimizedOrdersAndQuoteReport {
|
export interface OptimizedOrdersAndQuoteReport {
|
||||||
optimizedOrders: OptimizedMarketOrder[];
|
optimizedOrders: OptimizedMarketOrder[];
|
||||||
quoteReport: QuoteReport;
|
quoteReport: QuoteReport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MarketDepthSide = Array<Array<DexSample<FillData>>>;
|
||||||
|
|
||||||
|
export interface MarketDepth {
|
||||||
|
bids: MarketDepthSide;
|
||||||
|
asks: MarketDepthSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketSideLiquidity {
|
||||||
|
side: MarketOperation;
|
||||||
|
inputAmount: BigNumber;
|
||||||
|
inputToken: string;
|
||||||
|
outputToken: string;
|
||||||
|
dexQuotes: Array<Array<DexSample<FillData>>>;
|
||||||
|
nativeOrders: SignedOrder[];
|
||||||
|
orderFillableAmounts: BigNumber[];
|
||||||
|
ethToOutputRate: BigNumber;
|
||||||
|
rfqtIndicativeQuotes: RFQTIndicativeQuote[];
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user