WIP: add quoteReport response

This commit is contained in:
Steve Klebanoff
2020-07-06 21:06:43 -07:00
parent 406d2cefc5
commit 8ec44b63b1
5 changed files with 33 additions and 20 deletions

View File

@@ -155,6 +155,7 @@ export interface SwapQuoteBase {
bestCaseQuoteInfo: SwapQuoteInfo;
worstCaseQuoteInfo: SwapQuoteInfo;
sourceBreakdown: SwapQuoteOrdersBreakdown;
quoteReport: string;
}
/**
@@ -218,7 +219,7 @@ export interface SwapQuoteRequestOpts extends CalculateSwapQuoteOpts {
/**
* Opts required to generate a SwapQuote with SwapQuoteCalculator
*/
export interface CalculateSwapQuoteOpts extends GetMarketOrdersOpts {}
export interface CalculateSwapQuoteOpts extends GetMarketOrdersOpts { }
/**
* A mapping from RFQ-T quote provider URLs to the trading pairs they support.

View File

@@ -22,6 +22,7 @@ import {
ERC20BridgeSource,
GetMarketOrdersOpts,
OptimizedMarketOrder,
OptimizedOrdersAndQuoteReport,
OrderDomain,
} from './types';
@@ -71,7 +72,7 @@ export class MarketOperationUtils {
nativeOrders: SignedOrder[],
takerAmount: BigNumber,
opts?: Partial<GetMarketOrdersOpts>,
): Promise<OptimizedMarketOrder[]> {
): Promise<OptimizedOrdersAndQuoteReport> {
if (nativeOrders.length === 0) {
throw new Error(AggregationError.EmptyOrders);
}
@@ -153,7 +154,7 @@ export class MarketOperationUtils {
nativeOrders: SignedOrder[],
makerAmount: BigNumber,
opts?: Partial<GetMarketOrdersOpts>,
): Promise<OptimizedMarketOrder[]> {
): Promise<OptimizedOrdersAndQuoteReport> {
if (nativeOrders.length === 0) {
throw new Error(AggregationError.EmptyOrders);
}
@@ -238,6 +239,7 @@ export class MarketOperationUtils {
* @param opts Options object.
* @return orders.
*/
// TODO: can we delete?
public async getBatchMarketBuyOrdersAsync(
batchNativeOrders: SignedOrder[][],
makerAmounts: BigNumber[],
@@ -302,7 +304,7 @@ export class MarketOperationUtils {
feeSchedule: _opts.feeSchedule,
allowFallback: _opts.allowFallback,
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
});
}).optimizedOrders;
} catch (e) {
// It's possible for one of the pairs to have no path
// rather than throw NO_OPTIMAL_PATH we return undefined
@@ -330,7 +332,7 @@ export class MarketOperationUtils {
shouldBatchBridgeOrders?: boolean;
liquidityProviderAddress?: string;
multiBridgeAddress?: string;
}): OptimizedMarketOrder[] {
}): OptimizedOrdersAndQuoteReport {
const { inputToken, outputToken, side, inputAmount } = opts;
const maxFallbackSlippage = opts.maxFallbackSlippage || 0;
// Convert native orders and dex quotes into fill paths.
@@ -373,8 +375,8 @@ export class MarketOperationUtils {
const [last, penultimateIfExists] = optimalPath.slice().reverse();
const lastNativeFillIfExists =
last.source === ERC20BridgeSource.Native &&
penultimateIfExists &&
penultimateIfExists.source !== ERC20BridgeSource.Native
penultimateIfExists &&
penultimateIfExists.source !== ERC20BridgeSource.Native
? last
: undefined;
// By prepending native paths to the front they cannot split on-chain sources and incur
@@ -383,7 +385,7 @@ export class MarketOperationUtils {
optimalPath = [...nativeSubPath.filter(f => f !== lastNativeFillIfExists), ...nonNativeOptimalPath];
}
}
return createOrdersFromPath(optimalPath, {
const optimizedOrders = createOrdersFromPath(optimalPath, {
side,
inputToken,
outputToken,
@@ -394,6 +396,7 @@ export class MarketOperationUtils {
multiBridgeAddress: opts.multiBridgeAddress,
shouldBatchBridgeOrders: !!opts.shouldBatchBridgeOrders,
});
return { optimizedOrders, quoteReport: 'TODO' };
}
private _optionalSources(): ERC20BridgeSource[] {

View File

@@ -42,7 +42,7 @@ export enum ERC20BridgeSource {
}
// Internal `fillData` field for `Fill` objects.
export interface FillData {}
export interface FillData { }
// `FillData` for native fills.
export interface NativeFillData extends FillData {
@@ -218,3 +218,8 @@ export interface FakeBuyOpts {
targetSlippageBps: BigNumber;
maxIterations: BigNumber;
}
export interface OptimizedOrdersAndQuoteReport {
optimizedOrders: OptimizedMarketOrder[];
quoteReport: string;
}

View File

@@ -93,7 +93,7 @@ export class QuoteRequestor {
private readonly _infoLogger: LogFunction = (obj, msg) =>
logUtils.log(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`),
private readonly _expiryBufferMs: number = constants.DEFAULT_SWAP_QUOTER_OPTS.expiryBufferMs,
) {}
) { }
public async requestRfqtFirmQuotesAsync(
makerAssetData: string,
@@ -344,7 +344,7 @@ export class QuoteRequestor {
this._warningLogger(
convertIfAxiosError(err),
`Failed to get RFQ-T ${quoteType} quote from market maker endpoint ${url} for API key ${
options.apiKey
options.apiKey
} for taker address ${options.takerAddress}`,
);
return undefined;

View File

@@ -17,7 +17,7 @@ import {
import { MarketOperationUtils } from './market_operation_utils';
import { convertNativeOrderToFullyFillableOptimizedOrders } from './market_operation_utils/orders';
import { GetMarketOrdersOpts, OptimizedMarketOrder } from './market_operation_utils/types';
import { GetMarketOrdersOpts, OptimizedMarketOrder, OptimizedOrdersAndQuoteReport } from './market_operation_utils/types';
import { isSupportedAssetDataInOrders } from './utils';
import { QuoteFillResult, simulateBestCaseFill, simulateWorstCaseFill } from './quote_simulation';
@@ -94,7 +94,7 @@ export class SwapQuoteCalculator {
return createSwapQuote(
makerAssetData,
takerAssetData,
orders,
{ optimizedOrders: orders, quoteReport: 'TODO' },
operation,
assetFillAmounts[i],
gasPrice,
@@ -120,7 +120,7 @@ export class SwapQuoteCalculator {
}
// since prunedOrders do not have fillState, we will add a buffer of fillable orders to consider that some native are orders are partially filled
let resultOrders: OptimizedMarketOrder[] = [];
let result: OptimizedOrdersAndQuoteReport | undefined;
{
// Scale fees by gas price.
@@ -135,16 +135,16 @@ export class SwapQuoteCalculator {
if (firstOrderMakerAssetData.assetProxyId === AssetProxyId.ERC721) {
// HACK: to conform ERC721 orders to the output of market operation utils, assumes complete fillable
resultOrders = prunedOrders.map(o => convertNativeOrderToFullyFillableOptimizedOrders(o));
result = { optimizedOrders: prunedOrders.map(o => convertNativeOrderToFullyFillableOptimizedOrders(o)), quoteReport: 'TODO' };
} else {
if (operation === MarketOperation.Buy) {
resultOrders = await this._marketOperationUtils.getMarketBuyOrdersAsync(
result = await this._marketOperationUtils.getMarketBuyOrdersAsync(
prunedOrders,
assetFillAmount,
_opts,
);
} else {
resultOrders = await this._marketOperationUtils.getMarketSellOrdersAsync(
result = await this._marketOperationUtils.getMarketSellOrdersAsync(
prunedOrders,
assetFillAmount,
_opts,
@@ -158,7 +158,7 @@ export class SwapQuoteCalculator {
return createSwapQuote(
makerAssetData,
takerAssetData,
resultOrders,
result,
operation,
assetFillAmount,
gasPrice,
@@ -170,12 +170,14 @@ export class SwapQuoteCalculator {
function createSwapQuote(
makerAssetData: string,
takerAssetData: string,
resultOrders: OptimizedMarketOrder[],
result: OptimizedOrdersAndQuoteReport,
operation: MarketOperation,
assetFillAmount: BigNumber,
gasPrice: BigNumber,
gasSchedule: { [source: string]: number },
): SwapQuote {
const resultOrders = result.optimizedOrders;
const bestCaseFillResult = simulateBestCaseFill({
gasPrice,
orders: resultOrders,
@@ -192,7 +194,7 @@ function createSwapQuote(
opts: { gasSchedule },
});
const quoteBase: SwapQuoteBase = {
const quoteBase = {
takerAssetData,
makerAssetData,
gasPrice,
@@ -207,12 +209,14 @@ function createSwapQuote(
...quoteBase,
type: MarketOperation.Buy,
makerAssetFillAmount: assetFillAmount,
quoteReport: result.quoteReport,
};
} else {
return {
...quoteBase,
type: MarketOperation.Sell,
takerAssetFillAmount: assetFillAmount,
quoteReport: result.quoteReport,
};
}
}