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:
Jacob Evans 2020-07-27 15:07:52 +10:00 committed by GitHub
parent 72c869649a
commit 5afe2616a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 282 additions and 113 deletions

View File

@ -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
} }
] ]
}, },

View File

@ -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;

View File

@ -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.
* *

View File

@ -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();

View File

@ -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) {

View File

@ -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[];
}