get rfq working

This commit is contained in:
Lawrence Forman
2021-11-30 22:47:08 -05:00
parent da240653f4
commit 5c57efe8a8
11 changed files with 198 additions and 223 deletions

View File

@@ -51,18 +51,6 @@ export interface SignedOrder<T> {
export type SignedRfqOrder = SignedOrder<RfqOrderFields>;
export type SignedLimitOrder = SignedOrder<LimitOrderFields>;
export type SignedNativeOrder = SignedLimitOrder | SignedRfqOrder;
export type NativeOrderWithFillableAmounts = SignedNativeOrder & NativeOrderFillableAmountFields;
/**
* fillableMakerAmount: Amount of makerAsset that is fillable
* fillableTakerAmount: Amount of takerAsset that is fillable
* fillableTakerFeeAmount: Amount of takerFee paid to fill fillableTakerAmount
*/
export interface NativeOrderFillableAmountFields {
fillableMakerAmount: BigNumber;
fillableTakerAmount: BigNumber;
fillableTakerFeeAmount: BigNumber;
}
/**
* Represents the metadata to call a smart contract with calldata.

View File

@@ -1,10 +1,11 @@
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
import { BigNumber, hexUtils } from '@0x/utils';
import { MarketOperation, NativeOrderWithFillableAmounts } from '../../types';
import { NativeOrderWithFillableAmounts } from '../native_orders';
import { MarketOperation } from '../../types';
import { POSITIVE_INF, SOURCE_FLAGS, ZERO_AMOUNT } from './constants';
import { DexSample, Fill } from './types';
import { DexSample, ERC20BridgeSource, Fill, GenericBridgeFill, NativeOrderFill } from './types';
// tslint:disable: prefer-for-of no-bitwise completed-docs
@@ -93,66 +94,76 @@ export function nativeOrdersToFills(
outputAmountPerEth: BigNumber,
inputAmountPerEth: BigNumber,
gasPrice: BigNumber,
): Fill[] {
): NativeOrderFill[] {
if (orders.length === 0) {
return [];
}
throw new Error(`Not implemented`);
// const sourcePathId = hexUtils.random();
// // Create a single path from all orders.
// let fills: Array<Fill & { adjustedRate: BigNumber }> = [];
// for (const o of orders) {
// const { fillableTakerAmount, fillableTakerFeeAmount, fillableMakerAmount, type } = o;
// const makerAmount = fillableMakerAmount;
// const takerAmount = fillableTakerAmount.plus(fillableTakerFeeAmount);
// const input = side === MarketOperation.Sell ? takerAmount : makerAmount;
// const output = side === MarketOperation.Sell ? makerAmount : takerAmount;
// const fee = fees[ERC20BridgeSource.Native] === undefined ? 0 : fees[ERC20BridgeSource.Native]!(o);
// const outputPenalty = ethToOutputAmount({
// input,
// output,
// inputAmountPerEth,
// outputAmountPerEth,
// ethAmount: fee,
// });
// // targetInput can be less than the order size
// // whilst the penalty is constant, it affects the adjusted output
// // only up until the target has been exhausted.
// // A large order and an order at the exact target should be penalized
// // the same.
// const clippedInput = BigNumber.min(targetInput, input);
// // scale the clipped output inline with the input
// const clippedOutput = clippedInput.dividedBy(input).times(output);
// const adjustedOutput =
// side === MarketOperation.Sell ? clippedOutput.minus(outputPenalty) : clippedOutput.plus(outputPenalty);
// const adjustedRate =
// side === MarketOperation.Sell ? adjustedOutput.div(clippedInput) : clippedInput.div(adjustedOutput);
// // Skip orders with rates that are <= 0.
// if (adjustedRate.lte(0)) {
// continue;
// }
// fills.push({
// sourcePathId,
// adjustedRate,
// adjustedOutput,
// input: clippedInput,
// output: clippedOutput,
// flags: SOURCE_FLAGS[type === FillQuoteTransformerOrderType.Rfq ? 'RfqOrder' : 'LimitOrder'],
// index: 0, // TBD
// parent: undefined, // TBD
// source: ERC20BridgeSource.Native,
// type,
// fillData: { ...o },
// });
// }
// // Sort by descending adjusted rate.
// fills = fills.sort((a, b) => b.adjustedRate.comparedTo(a.adjustedRate));
// // Re-index fills.
// for (let i = 0; i < fills.length; ++i) {
// fills[i].parent = i === 0 ? undefined : fills[i - 1];
// fills[i].index = i;
// }
// return fills;
const sourcePathId = hexUtils.random();
// Create a single path from all orders.
let fills: Array<NativeOrderFill & { adjustedRate: BigNumber }> = [];
for (const o of orders) {
const { fillableTakerAmount, fillableMakerAmount, type } = o;
// TODO(lawrence): handle taker fees.
if (o.fillableTakerFeeAmount.gt(0)) {
continue;
}
let input, output;
if (side === MarketOperation.Sell) {
input = fillableTakerAmount;
output = fillableMakerAmount;
} else {
input = fillableMakerAmount;
output = fillableTakerAmount;
}
const outputPenalty = ethToOutputAmount({
input,
output,
inputAmountPerEth,
outputAmountPerEth,
ethAmount: gasPrice.times(o.gasCost),
});
// targetInput can be less than the order size
// whilst the penalty is constant, it affects the adjusted output
// only up until the target has been exhausted.
// A large order and an order at the exact target should be penalized
// the same.
const clippedInput = BigNumber.min(targetInput, input);
// scale the clipped output inline with the input
const clippedOutput = clippedInput.dividedBy(input).times(output);
const adjustedOutput =
side === MarketOperation.Sell ? clippedOutput.minus(outputPenalty) : clippedOutput.plus(outputPenalty);
const adjustedRate =
side === MarketOperation.Sell ? adjustedOutput.div(clippedInput) : clippedInput.div(adjustedOutput);
// Skip orders with rates that are <= 0.
if (adjustedRate.lte(0)) {
continue;
}
fills.push({
type,
sourcePathId,
adjustedOutput,
adjustedRate,
input: clippedInput,
output: clippedOutput,
flags: SOURCE_FLAGS[type === FillQuoteTransformerOrderType.Rfq ? 'RfqOrder' : 'LimitOrder'],
index: 0, // TBD
parent: undefined, // TBD
source: ERC20BridgeSource.Native,
gasCost: o.gasCost,
data: {
order: o.order,
signature: o.signature,
},
});
}
// Sort by descending adjusted rate.
fills = fills.sort((a, b) => b.adjustedRate.comparedTo(a.adjustedRate));
// Re-index fills.
for (let i = 0; i < fills.length; ++i) {
fills[i].parent = i === 0 ? undefined : fills[i - 1];
fills[i].index = i;
}
return fills;
}
export function dexSamplesToFills(
@@ -161,9 +172,9 @@ export function dexSamplesToFills(
outputAmountPerEth: BigNumber,
inputAmountPerEth: BigNumber,
gasPrice: BigNumber,
): Fill[] {
): GenericBridgeFill[] {
const sourcePathId = hexUtils.random();
const fills: Fill[] = [];
const fills: GenericBridgeFill[] = [];
// Drop any non-zero entries. This can occur if the any fills on Kyber were UniswapReserves
// We need not worry about Kyber fills going to UniswapReserve as the input amount
// we fill is the same as we sampled. I.e we received [0,20,30] output from [1,2,3] input

View File

@@ -1,4 +1,4 @@
import { FillQuoteTransformerOrderType, RfqOrder, SignatureType } from '@0x/protocol-utils';
import { CommonOrderFields, FillQuoteTransformerOrderType, RfqOrder, SignatureType } from '@0x/protocol-utils';
import { V4RFQIndicativeQuote } from '@0x/quote-server';
import { BigNumber, NULL_ADDRESS } from '@0x/utils';
import * as _ from 'lodash';
@@ -8,16 +8,11 @@ import {
Address,
AssetSwapperContractAddresses,
MarketOperation,
NativeOrderWithFillableAmounts,
SignedNativeOrder,
SignedRfqOrder,
} from '../../types';
import { NativeOrderWithFillableAmounts } from '../native_orders';
import { QuoteRequestor } from '../quote_requestor';
import {
getNativeAdjustedFillableAmountsFromMakerAmount,
getNativeAdjustedFillableAmountsFromTakerAmount,
getNativeAdjustedMakerFillAmount,
} from '../utils';
import {
dexSampleToReportSource,
@@ -35,13 +30,12 @@ import {
FEE_QUOTE_SOURCES_BY_CHAIN_ID,
NATIVE_FEE_TOKEN_BY_CHAIN_ID,
SELL_SOURCE_FILTER_BY_CHAIN_ID,
SOURCE_FLAGS,
ZERO_AMOUNT,
} from './constants';
import { createFills } from './fills';
import { getIntermediateTokens } from './multihop_utils';
import { Path, PathPenaltyOpts } from './path';
import { fillsToSortedPaths, findOptimalPathJSAsync, findOptimalRustPathFromSamples } from './path_optimizer';
import { findOptimalPathJSAsync, findOptimalRustPathFromSamples } from './path_optimizer';
import { Sampler } from './sampler';
import { SourceFilters } from './source_filters';
import {
@@ -61,6 +55,7 @@ import {
} from './types';
const SHOULD_USE_RUST_ROUTER = process.env.RUST_ROUTER === 'true';
const RFQT_ORDER_GAS_COST = Number(process.env.RFQT_ORDER_GAS_COST || 0) || 100e3;
// tslint:disable:boolean-naming
@@ -671,6 +666,8 @@ export class MarketOperationUtils {
marketSideLiquidity.quotes,
side,
indicativeQuotes.map(indicativeRfqQuoteToSignedNativeOrder),
[],
RFQT_ORDER_GAS_COST,
);
optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, optimizerOpts);
}
@@ -700,7 +697,7 @@ export class MarketOperationUtils {
: await rfqt.firmQuoteValidator.getRfqtTakerFillableAmountsAsync(
firmQuotes.map(q => new RfqOrder(q.order)),
);
injectRfqLiquidity(marketSideLiquidity.quotes, side, firmQuotes, rfqTakerFillableAmounts);
injectRfqLiquidity(marketSideLiquidity.quotes, side, firmQuotes, rfqTakerFillableAmounts, RFQT_ORDER_GAS_COST);
// Re-run optimizer with the new firm quote. This is the second and last time
// we run the optimized in a block of code. In this case, we don't catch a potential `NoOptimalPath` exception
@@ -813,16 +810,6 @@ export class MarketOperationUtils {
exchangeProxyOverhead: ExchangeProxyOverhead;
runLimit?: number;
}): Promise<Path | undefined | null> {
const fills = createFills({
side: opts.side,
orders: opts.nativeOrders,
dexQuotes: opts.dexQuotes,
targetInput: opts.inputAmount,
outputAmountPerEth: opts.outputAmountPerEth,
inputAmountPerEth: opts.inputAmountPerEth,
gasPrice: opts.gasPrice,
});
// Find the optimal path.
const penaltyOpts: PathPenaltyOpts = {
outputAmountPerEth: opts.outputAmountPerEth,
@@ -843,6 +830,16 @@ export class MarketOperationUtils {
this._sampler.chainId,
);
};
const fills = createFills({
side: opts.side,
orders: opts.nativeOrders,
dexQuotes: opts.dexQuotes,
targetInput: opts.inputAmount,
outputAmountPerEth: opts.outputAmountPerEth,
inputAmountPerEth: opts.inputAmountPerEth,
gasPrice: opts.gasPrice,
});
return findOptimalPathJSAsync(opts.side, fills, opts.inputAmount, opts.runLimit, penaltyOpts);
}
@@ -1019,6 +1016,7 @@ function injectRfqLiquidity(
side: MarketOperation,
orders: SignedRfqOrder[],
orderFillableTakerAmounts: BigNumber[] = [],
gasCostPerOrder: number,
): void {
if (orders.length === 0) {
return;
@@ -1027,11 +1025,12 @@ function injectRfqLiquidity(
const fullOrders = orders.map((o, i) => ({
...o,
fillableTakerAmount: orderFillableTakerAmounts[i] || ZERO_AMOUNT,
fillableMakerAmount: getNativeAdjustedMakerFillAmount(
fillableMakerAmount: getNativeOrderMakerFillAmount(
o.order,
orderFillableTakerAmounts[i],
),
fillableTakerFeeAmount: ZERO_AMOUNT,
gasCost: gasCostPerOrder,
}));
const inputToken = side === MarketOperation.Sell ? takerToken : makerToken;
const outputToken = side === MarketOperation.Sell ? makerToken : takerToken;
@@ -1058,10 +1057,10 @@ function getTakerMakerTokenFromTokenPath(tokenPath: Address[]): [Address, Addres
return [tokenPath[0], tokenPath[tokenPath.length - 1]];
}
function getInputOutputTokenFromTokenPath(side: MarketOperation, tokenPath: Address[]): [Address, Address] {
const tokens = getTakerMakerTokenFromTokenPath(tokenPath);
if (side === MarketOperation.Buy) {
tokens.reverse();
}
return tokens;
function getNativeOrderMakerFillAmount(order: CommonOrderFields, takerFillAmount: BigNumber): BigNumber {
// Round down because exchange rate favors Maker
return takerFillAmount
.multipliedBy(order.makerAmount)
.div(order.takerAmount)
.integerValue(BigNumber.ROUND_DOWN);
}

View File

@@ -7,7 +7,6 @@ import { ethToOutputAmount } from './fills';
import { createBridgeOrder, createNativeOptimizedOrder } from './orders';
import { getCompleteRate, getRate } from './rate_utils';
import {
BridgeFill,
CollapsedGenericBridgeFill,
CollapsedFill,
CollapsedNativeOrderFill,

View File

@@ -6,7 +6,8 @@ import * as _ from 'lodash';
import { performance } from 'perf_hooks';
import { DEFAULT_INFO_LOGGER } from '../../constants';
import { MarketOperation, NativeOrderWithFillableAmounts } from '../../types';
import { NativeOrderWithFillableAmounts } from '../native_orders';
import { MarketOperation } from '../../types';
import { VIP_ERC20_BRIDGE_SOURCES_BY_CHAIN_ID } from '../market_operation_utils/constants';
import { dexSamplesToFills, ethToOutputAmount, nativeOrdersToFills } from './fills';
@@ -45,7 +46,7 @@ function calculateOuputFee(
gasPrice: BigNumber,
): BigNumber {
if (isDexSample(sampleOrNativeOrder)) {
const { input, output, source, encodedFillData } = sampleOrNativeOrder;
const { input, output } = sampleOrNativeOrder;
const fee = gasPrice.times(sampleOrNativeOrder.gasCost);
const outputFee = ethToOutputAmount({
input,
@@ -56,16 +57,15 @@ function calculateOuputFee(
});
return outputFee;
} else {
throw new Error(`No implementado`);
// const { input, output } = nativeOrderToNormalizedAmounts(side, sampleOrNativeOrder);
// const outputFee = ethToOutputAmount({
// input,
// output,
// inputAmountPerEth,
// outputAmountPerEth,
// ethAmount: fee,
// });
// return outputFee;
const { input, output } = nativeOrderToNormalizedAmounts(side, sampleOrNativeOrder);
const outputFee = ethToOutputAmount({
input,
output,
inputAmountPerEth,
outputAmountPerEth,
ethAmount: gasPrice.times((sampleOrNativeOrder as NativeOrderWithFillableAmounts).gasCost),
});
return outputFee;
}
}
@@ -381,7 +381,7 @@ export async function findOptimalPathJSAsync(
): Promise<Path | undefined> {
// Sort fill arrays by descending adjusted completed rate.
// Remove any paths which cannot impact the optimal path
const sortedPaths = reducePaths(fillsToSortedPaths(fills, side, targetInput, opts), side);
const sortedPaths = reducePaths(fillsToSortedPaths(fills, side, targetInput, opts));
if (sortedPaths.length === 0) {
return undefined;
}
@@ -420,7 +420,7 @@ export function fillsToSortedPaths(
}
// Remove paths which have no impact on the optimal path
export function reducePaths(sortedPaths: Path[], side: MarketOperation): Path[] {
export function reducePaths(sortedPaths: Path[]): Path[] {
// Any path which has a min rate that is less than the best adjusted completed rate has no chance of improving
// the overall route.
const bestNonNativeCompletePath = sortedPaths.filter(

View File

@@ -2,11 +2,15 @@ import {
FillQuoteTransformerLimitOrderInfo,
FillQuoteTransformerOrderType,
FillQuoteTransformerRfqOrderInfo,
LimitOrderFields,
RfqOrderFields,
Signature,
} from '@0x/protocol-utils';
import { MarketOperation } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { Address, Bytes, NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
import { Address, Bytes, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
import { NativeOrderWithFillableAmounts } from '../native_orders';
import { QuoteRequestor } from '../../utils/quote_requestor';
import { PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
@@ -200,8 +204,8 @@ export interface MooniswapFillData extends BridgeFillData {
}
export interface NativeOrderFillData {
type: FillQuoteTransformerOrderType.Limit | FillQuoteTransformerOrderType.Rfq;
orderInfo: FillQuoteTransformerLimitOrderInfo;
order: LimitOrderFields | RfqOrderFields;
signature: Signature;
}
/**

View File

@@ -0,0 +1,72 @@
import { BigNumber } from '@0x/utils';
import {
CommonOrderFields,
FillQuoteTransformerOrderType,
LimitOrderFields,
RfqOrderFields,
Signature,
} from '@0x/protocol-utils';
import { SignedNativeOrder } from '../types';
export interface SignedOrder<T> {
order: T;
type: FillQuoteTransformerOrderType.Limit | FillQuoteTransformerOrderType.Rfq;
signature: Signature;
}
export type NativeOrderWithFillableAmounts = SignedNativeOrder & NativeOrderFillableAmountFields & {
gasCost: number;
};
/**
* fillableMakerAmount: Amount of makerAsset that is fillable
* fillableTakerAmount: Amount of takerAsset that is fillable
* fillableTakerFeeAmount: Amount of takerFee paid to fill fillableTakerAmount
*/
export interface NativeOrderFillableAmountFields {
fillableMakerAmount: BigNumber;
fillableTakerAmount: BigNumber;
fillableTakerFeeAmount: BigNumber;
}
/**
* Given an amount of taker asset, calculate the the amount of maker asset
* @param order The order
* @param makerFillAmount the amount of taker asset
*/
export function getNativeMakerFillAmount(order: CommonOrderFields, takerFillAmount: BigNumber): BigNumber {
// Round down because exchange rate favors Maker
const makerFillAmount = takerFillAmount
.multipliedBy(order.makerAmount)
.div(order.takerAmount)
.integerValue(BigNumber.ROUND_FLOOR);
return makerFillAmount;
}
/**
* Given an amount of maker asset, calculate the equivalent amount in taker asset
* @param order The order
* @param makerFillAmount the amount of maker asset
*/
export function getNativeTakerFillAmount(order: CommonOrderFields, makerFillAmount: BigNumber): BigNumber {
// Round up because exchange rate favors Maker
const takerFillAmount = makerFillAmount
.multipliedBy(order.takerAmount)
.div(order.makerAmount)
.integerValue(BigNumber.ROUND_CEIL);
return takerFillAmount;
}
/**
* Given an amount of taker asset, calculate the fee amount required for the taker
* @param order The order
* @param takerFillAmount the amount of taker asset
*/
export function getNativeTakerFeeFillAmount(order: LimitOrderFields, takerFillAmount: BigNumber): BigNumber {
// Round down because Taker fee rate favors Taker
const takerFeeAmount = takerFillAmount
.multipliedBy(order.takerTokenFeeAmount)
.div(order.takerAmount)
.integerValue(BigNumber.ROUND_FLOOR);
return takerFeeAmount;
}

View File

@@ -2,7 +2,7 @@ import { FillQuoteTransformerOrderType, RfqOrderFields, Signature } from '@0x/pr
import { BigNumber } from '@0x/utils';
import _ = require('lodash');
import { MarketOperation, NativeOrderWithFillableAmounts } from '../types';
import { MarketOperation } from '../types';
import {
CollapsedFill,
@@ -10,6 +10,7 @@ import {
ERC20BridgeSource,
CollapsedNativeOrderFill,
} from './market_operation_utils/types';
import { NativeOrderWithFillableAmounts } from './native_orders';
import { QuoteRequestor } from './quote_requestor';
export interface QuoteReportEntryBase {

View File

@@ -1,10 +1,10 @@
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
import { FillQuoteTransformerOrderType, LimitOrderFields } from '@0x/protocol-utils';
import { BigNumber } from '@0x/utils';
import { constants } from '../constants';
import { MarketOperation, SwapQuoteLimitOrder, SwapQuoteOrder } from '../types';
import { getNativeAdjustedTakerFeeAmount } from './utils';
import { getNativeTakerFeeFillAmount } from './native_orders';
const { PROTOCOL_FEE_MULTIPLIER, ZERO_AMOUNT } = constants;
const { ROUND_DOWN, ROUND_UP } = BigNumber;
@@ -219,8 +219,8 @@ function createBestCaseFillOrderCalls(quoteInfo: QuoteFillInfo): QuoteFillOrderC
totalOrderOutput: o.makerAmount,
totalOrderInputFee:
o.type === FillQuoteTransformerOrderType.Limit
? getNativeAdjustedTakerFeeAmount(
(o as SwapQuoteLimitOrder).fillData.orderInfo.order,
? getNativeTakerFeeFillAmount(
((o as SwapQuoteLimitOrder).fillData.order as LimitOrderFields),
o.takerAmount,
)
: ZERO_AMOUNT,

View File

@@ -1,104 +1,4 @@
import { ChainId } from '@0x/contract-addresses';
import { CommonOrderFields, FillQuoteTransformerOrderType, LimitOrderFields } from '@0x/protocol-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { constants } from '../constants';
import { NativeOrderFillableAmountFields, SignedNativeOrder } from '../types';
import { ZERO_AMOUNT } from './market_operation_utils/constants';
// tslint:disable: no-unnecessary-type-assertion completed-docs
export function numberPercentageToEtherTokenAmountPercentage(percentage: number): BigNumber {
return Web3Wrapper.toBaseUnitAmount(constants.ONE_AMOUNT, constants.ETHER_TOKEN_DECIMALS).multipliedBy(percentage);
}
export function getAdjustedTakerAmountFromFees<T extends LimitOrderFields>(order: T): BigNumber {
return order.takerAmount.plus(order.takerTokenFeeAmount);
}
/**
* Given an amount of taker asset, calculate the the amount of maker asset
* @param order The order
* @param makerFillAmount the amount of taker asset
*/
export function getNativeAdjustedMakerFillAmount(order: CommonOrderFields, takerFillAmount: BigNumber): BigNumber {
// Round down because exchange rate favors Maker
const makerFillAmount = takerFillAmount
.multipliedBy(order.makerAmount)
.div(order.takerAmount)
.integerValue(BigNumber.ROUND_FLOOR);
return makerFillAmount;
}
/**
* Given an amount of maker asset, calculate the equivalent amount in taker asset
* @param order The order
* @param makerFillAmount the amount of maker asset
*/
export function getNativeAdjustedTakerFillAmount(order: CommonOrderFields, makerFillAmount: BigNumber): BigNumber {
// Round up because exchange rate favors Maker
const takerFillAmount = makerFillAmount
.multipliedBy(order.takerAmount)
.div(order.makerAmount)
.integerValue(BigNumber.ROUND_CEIL);
return takerFillAmount;
}
/**
* Given an amount of taker asset, calculate the fee amount required for the taker
* @param order The order
* @param takerFillAmount the amount of taker asset
*/
export function getNativeAdjustedTakerFeeAmount(order: LimitOrderFields, takerFillAmount: BigNumber): BigNumber {
// Round down because Taker fee rate favors Taker
const takerFeeAmount = takerFillAmount
.multipliedBy(order.takerTokenFeeAmount)
.div(order.takerAmount)
.integerValue(BigNumber.ROUND_FLOOR);
return takerFeeAmount;
}
const EMPTY_FILLABLE_AMOUNTS: NativeOrderFillableAmountFields = {
fillableMakerAmount: ZERO_AMOUNT,
fillableTakerAmount: ZERO_AMOUNT,
fillableTakerFeeAmount: ZERO_AMOUNT,
};
export function getNativeAdjustedFillableAmountsFromTakerAmount(
order: SignedNativeOrder,
takerFillableAmount: BigNumber,
): NativeOrderFillableAmountFields {
if (takerFillableAmount.isZero()) {
return EMPTY_FILLABLE_AMOUNTS;
}
return {
fillableTakerAmount: takerFillableAmount,
fillableMakerAmount: getNativeAdjustedMakerFillAmount(order.order, takerFillableAmount),
fillableTakerFeeAmount:
order.type === FillQuoteTransformerOrderType.Limit
? getNativeAdjustedTakerFeeAmount(order.order as LimitOrderFields, takerFillableAmount)
: ZERO_AMOUNT,
};
}
export function getNativeAdjustedFillableAmountsFromMakerAmount(
order: SignedNativeOrder,
makerFillableAmount: BigNumber,
): NativeOrderFillableAmountFields {
if (makerFillableAmount.isZero()) {
return EMPTY_FILLABLE_AMOUNTS;
}
const takerFillableAmount = getNativeAdjustedTakerFillAmount(order.order, makerFillableAmount);
return {
fillableMakerAmount: makerFillableAmount,
fillableTakerAmount: takerFillableAmount,
fillableTakerFeeAmount:
order.type === FillQuoteTransformerOrderType.Limit
? getNativeAdjustedTakerFeeAmount(order.order as LimitOrderFields, takerFillableAmount)
: ZERO_AMOUNT,
};
}
// TODO(kimpers): Consolidate this implementation with the one in @0x/token-metadata
export function valueByChainId<T>(rest: Partial<{ [key in ChainId]: T }>, defaultValue: T): { [key in ChainId]: T } {

View File

@@ -4,6 +4,7 @@
"max-file-line-count": false,
"binary-expression-operand-order": false,
"no-bitwise": false,
"completed-docs": false
},
"linterOptions": {
"exclude": ["src/artifacts.ts", "test/artifacts.ts"]