feat: asset-swapper tweak the gas schedule + return decimals (#34)

* feat: asset-swapper Return decimals from sampler in quote

* feat: asset-swapper tweak the gas schedule

* fix lint

* CHANGELOG
This commit is contained in:
Jacob Evans 2020-11-17 11:36:53 +10:00 committed by GitHub
parent 3133c509f9
commit 4f82543bdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 97 additions and 2010 deletions

View File

@ -1,4 +1,17 @@
[ [
{
"version": "5.2.0",
"changes": [
{
"note": "Update Gas schedules",
"pr": 34
},
{
"note": "Return the maker/taker token decimals from the sampler as part of the `SwapQuote`",
"pr": 34
}
]
},
{ {
"version": "5.1.1", "version": "5.1.1",
"changes": [ "changes": [

View File

@ -64,7 +64,7 @@
"@0x/dev-utils": "^4.0.1", "@0x/dev-utils": "^4.0.1",
"@0x/json-schemas": "^5.3.3", "@0x/json-schemas": "^5.3.3",
"@0x/order-utils": "^10.4.6", "@0x/order-utils": "^10.4.6",
"@0x/orderbook": "^2.2.7", "@0x/orderbook": "0xProject/gitpkg-registry#0x-orderbook-v2.2.7-e10a81023",
"@0x/quote-server": "^3.1.0", "@0x/quote-server": "^3.1.0",
"@0x/types": "^3.3.0", "@0x/types": "^3.3.0",
"@0x/typescript-typings": "^5.1.5", "@0x/typescript-typings": "^5.1.5",

View File

@ -503,6 +503,8 @@ export class SwapQuoter {
return { return {
bids: getMarketDepthSide(bids), bids: getMarketDepthSide(bids),
asks: getMarketDepthSide(asks), asks: getMarketDepthSide(asks),
makerTokenDecimals: asks.makerTokenDecimals,
takerTokenDecimals: asks.takerTokenDecimals,
}; };
} }

View File

@ -188,6 +188,8 @@ export interface SwapQuoteBase {
sourceBreakdown: SwapQuoteOrdersBreakdown; sourceBreakdown: SwapQuoteOrdersBreakdown;
quoteReport?: QuoteReport; quoteReport?: QuoteReport;
isTwoHop: boolean; isTwoHop: boolean;
makerTokenDecimals: number;
takerTokenDecimals: number;
} }
/** /**

View File

@ -429,13 +429,20 @@ export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAd
[ChainId.Ganache]: EMPTY_BRIDGE_ADDRESSES, [ChainId.Ganache]: EMPTY_BRIDGE_ADDRESSES,
}; };
/**
* Calculated gross gas cost of the underlying exchange.
* The cost of switching from one source to another, assuming
* we are in the middle of a transaction.
* I.e remove the overhead cost of ExchangeProxy (130k) and
* the ethereum transaction cost (21k)
*/
// tslint:disable:custom-no-magic-numbers // tslint:disable:custom-no-magic-numbers
export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = { export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.Native]: () => 150e3, [ERC20BridgeSource.Native]: () => 150e3,
[ERC20BridgeSource.Uniswap]: () => 90e3, [ERC20BridgeSource.Uniswap]: () => 90e3,
[ERC20BridgeSource.LiquidityProvider]: () => 140e3, [ERC20BridgeSource.LiquidityProvider]: () => 140e3,
[ERC20BridgeSource.Eth2Dai]: () => 400e3, [ERC20BridgeSource.Eth2Dai]: () => 400e3,
[ERC20BridgeSource.Kyber]: () => 500e3, [ERC20BridgeSource.Kyber]: () => 450e3,
[ERC20BridgeSource.Curve]: fillData => { [ERC20BridgeSource.Curve]: fillData => {
const poolAddress = (fillData as CurveFillData).pool.poolAddress.toLowerCase(); const poolAddress = (fillData as CurveFillData).pool.poolAddress.toLowerCase();
switch (poolAddress) { switch (poolAddress) {
@ -452,12 +459,14 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
case POOLS.curve_BUSD: case POOLS.curve_BUSD:
return 850e3; return 850e3;
// Metapools // Metapools
case POOLS.curve_GUSD:
case POOLS.curve_HUSD:
case POOLS.curve_USDN: case POOLS.curve_USDN:
case POOLS.curve_mUSD: case POOLS.curve_mUSD:
return 300e3;
case POOLS.curve_GUSD:
case POOLS.curve_HUSD:
return 310e3;
case POOLS.curve_tBTC: case POOLS.curve_tBTC:
return 650e3; return 370e3;
default: default:
throw new Error(`Unrecognized Curve address: ${poolAddress}`); throw new Error(`Unrecognized Curve address: ${poolAddress}`);
} }
@ -482,11 +491,11 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
return gas; return gas;
}, },
[ERC20BridgeSource.Balancer]: () => 120e3, [ERC20BridgeSource.Balancer]: () => 120e3,
[ERC20BridgeSource.Cream]: () => 300e3, [ERC20BridgeSource.Cream]: () => 120e3,
[ERC20BridgeSource.MStable]: () => 700e3, [ERC20BridgeSource.MStable]: () => 700e3,
[ERC20BridgeSource.Mooniswap]: () => 220e3, [ERC20BridgeSource.Mooniswap]: () => 130e3,
[ERC20BridgeSource.Swerve]: () => 150e3, [ERC20BridgeSource.Swerve]: () => 150e3,
[ERC20BridgeSource.Shell]: () => 300e3, [ERC20BridgeSource.Shell]: () => 170e3,
[ERC20BridgeSource.MultiHop]: (fillData?: FillData) => { [ERC20BridgeSource.MultiHop]: (fillData?: FillData) => {
const firstHop = (fillData as MultiHopFillData).firstHopSource; const firstHop = (fillData as MultiHopFillData).firstHopSource;
const secondHop = (fillData as MultiHopFillData).secondHopSource; const secondHop = (fillData as MultiHopFillData).secondHopSource;
@ -501,7 +510,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
const isSellBase = (fillData as DODOFillData).isSellBase; const isSellBase = (fillData as DODOFillData).isSellBase;
// Sell base is cheaper as it is natively supported // Sell base is cheaper as it is natively supported
// sell quote requires additional calculation and overhead // sell quote requires additional calculation and overhead
return isSellBase ? 440e3 : 540e3; return isSellBase ? 180e3 : 300e3;
}, },
[ERC20BridgeSource.SnowSwap]: fillData => { [ERC20BridgeSource.SnowSwap]: fillData => {
switch ((fillData as SnowSwapFillData).pool.poolAddress.toLowerCase()) { switch ((fillData as SnowSwapFillData).pool.poolAddress.toLowerCase()) {

View File

@ -4,7 +4,7 @@ import { BigNumber, NULL_ADDRESS } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { AssetSwapperContractAddresses, MarketOperation, Omit } from '../../types'; import { AssetSwapperContractAddresses, MarketOperation } from '../../types';
import { QuoteRequestor } from '../quote_requestor'; import { QuoteRequestor } from '../quote_requestor';
import { getPriceAwareRFQRolloutFlags } from '../utils'; import { getPriceAwareRFQRolloutFlags } from '../utils';
@ -38,7 +38,6 @@ import {
GenerateOptimizedOrdersOpts, GenerateOptimizedOrdersOpts,
GetMarketOrdersOpts, GetMarketOrdersOpts,
MarketSideLiquidity, MarketSideLiquidity,
OptimizedMarketOrder,
OptimizerResult, OptimizerResult,
OptimizerResultWithReport, OptimizerResultWithReport,
OrderDomain, OrderDomain,
@ -406,7 +405,7 @@ export class MarketOperationUtils {
batchNativeOrders: SignedOrder[][], batchNativeOrders: SignedOrder[][],
makerAmounts: BigNumber[], makerAmounts: BigNumber[],
opts?: Partial<GetMarketOrdersOpts>, opts?: Partial<GetMarketOrdersOpts>,
): Promise<Array<OptimizedMarketOrder[] | undefined>> { ): Promise<Array<OptimizerResult | undefined>> {
if (batchNativeOrders.length === 0) { if (batchNativeOrders.length === 0) {
throw new Error(AggregationError.EmptyOrders); throw new Error(AggregationError.EmptyOrders);
} }
@ -437,12 +436,16 @@ export class MarketOperationUtils {
[makerAmounts[i]], [makerAmounts[i]],
), ),
), ),
...batchNativeOrders.map(orders =>
this._sampler.getTokenDecimals(getNativeOrderTokens(orders[0])[0], getNativeOrderTokens(orders[0])[1]),
),
]; ];
const executeResults = await this._sampler.executeBatchAsync(ops); const executeResults = await this._sampler.executeBatchAsync(ops);
const batchOrderFillableAmounts = executeResults.splice(0, batchNativeOrders.length) as BigNumber[][]; const batchOrderFillableAmounts = executeResults.splice(0, batchNativeOrders.length) as BigNumber[][];
const batchEthToTakerAssetRate = executeResults.splice(0, batchNativeOrders.length) as BigNumber[]; const batchEthToTakerAssetRate = executeResults.splice(0, batchNativeOrders.length) as BigNumber[];
const batchDexQuotes = executeResults.splice(0, batchNativeOrders.length) as DexSample[][][]; const batchDexQuotes = executeResults.splice(0, batchNativeOrders.length) as DexSample[][][];
const batchTokenDecimals = executeResults.splice(0, batchNativeOrders.length) as number[][];
const ethToInputRate = ZERO_AMOUNT; const ethToInputRate = ZERO_AMOUNT;
return Promise.all( return Promise.all(
@ -456,7 +459,7 @@ export class MarketOperationUtils {
const dexQuotes = batchDexQuotes[i]; const dexQuotes = batchDexQuotes[i];
const makerAmount = makerAmounts[i]; const makerAmount = makerAmounts[i];
try { try {
const { optimizedOrders } = await this._generateOptimizedOrdersAsync( const optimizerResult = await this._generateOptimizedOrdersAsync(
{ {
side: MarketOperation.Buy, side: MarketOperation.Buy,
nativeOrders, nativeOrders,
@ -470,6 +473,8 @@ export class MarketOperationUtils {
outputToken: takerToken, outputToken: takerToken,
twoHopQuotes: [], twoHopQuotes: [],
quoteSourceFilters, quoteSourceFilters,
makerTokenDecimals: batchTokenDecimals[i][0],
takerTokenDecimals: batchTokenDecimals[i][1],
}, },
{ {
bridgeSlippage: _opts.bridgeSlippage, bridgeSlippage: _opts.bridgeSlippage,
@ -479,7 +484,7 @@ export class MarketOperationUtils {
allowFallback: _opts.allowFallback, allowFallback: _opts.allowFallback,
}, },
); );
return optimizedOrders; return optimizerResult;
} 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
@ -490,7 +495,7 @@ export class MarketOperationUtils {
} }
public async _generateOptimizedOrdersAsync( public async _generateOptimizedOrdersAsync(
marketSideLiquidity: Omit<MarketSideLiquidity, 'makerTokenDecimals' | 'takerTokenDecimals'>, marketSideLiquidity: MarketSideLiquidity,
opts: GenerateOptimizedOrdersOpts, opts: GenerateOptimizedOrdersOpts,
): Promise<OptimizerResult> { ): Promise<OptimizerResult> {
const { const {
@ -553,6 +558,7 @@ export class MarketOperationUtils {
optimizedOrders: twoHopOrders, optimizedOrders: twoHopOrders,
liquidityDelivered: bestTwoHopQuote, liquidityDelivered: bestTwoHopQuote,
sourceFlags: SOURCE_FLAGS[ERC20BridgeSource.MultiHop], sourceFlags: SOURCE_FLAGS[ERC20BridgeSource.MultiHop],
marketSideLiquidity,
}; };
} }
@ -582,6 +588,7 @@ export class MarketOperationUtils {
optimizedOrders: collapsedPath.orders, optimizedOrders: collapsedPath.orders,
liquidityDelivered: collapsedPath.collapsedFills as CollapsedFill[], liquidityDelivered: collapsedPath.collapsedFills as CollapsedFill[],
sourceFlags: collapsedPath.sourceFlags, sourceFlags: collapsedPath.sourceFlags,
marketSideLiquidity,
}; };
} }
@ -606,7 +613,7 @@ export class MarketOperationUtils {
side === MarketOperation.Sell side === MarketOperation.Sell
? this.getMarketSellLiquidityAsync.bind(this) ? this.getMarketSellLiquidityAsync.bind(this)
: this.getMarketBuyLiquidityAsync.bind(this); : this.getMarketBuyLiquidityAsync.bind(this);
const marketSideLiquidity = await marketLiquidityFnAsync(nativeOrders, amount, _opts); const marketSideLiquidity: MarketSideLiquidity = await marketLiquidityFnAsync(nativeOrders, amount, _opts);
let optimizerResult: OptimizerResult | undefined; let optimizerResult: OptimizerResult | undefined;
try { try {
optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, optimizerOpts); optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, optimizerOpts);

View File

@ -339,6 +339,7 @@ export interface OptimizerResult {
optimizedOrders: OptimizedMarketOrder[]; optimizedOrders: OptimizedMarketOrder[];
sourceFlags: number; sourceFlags: number;
liquidityDelivered: CollapsedFill[] | DexSample<MultiHopFillData>; liquidityDelivered: CollapsedFill[] | DexSample<MultiHopFillData>;
marketSideLiquidity: MarketSideLiquidity;
} }
export interface OptimizerResultWithReport extends OptimizerResult { export interface OptimizerResultWithReport extends OptimizerResult {
@ -350,6 +351,8 @@ export type MarketDepthSide = Array<Array<DexSample<FillData>>>;
export interface MarketDepth { export interface MarketDepth {
bids: MarketDepthSide; bids: MarketDepthSide;
asks: MarketDepthSide; asks: MarketDepthSide;
makerTokenDecimals: number;
takerTokenDecimals: number;
} }
export interface MarketSideLiquidity { export interface MarketSideLiquidity {

View File

@ -1,5 +1,4 @@
import { assetDataUtils } from '@0x/order-utils'; import { SignedOrder } from '@0x/types';
import { AssetProxyId, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -17,7 +16,6 @@ import {
import { MarketOperationUtils } from './market_operation_utils'; import { MarketOperationUtils } from './market_operation_utils';
import { SOURCE_FLAGS } from './market_operation_utils/constants'; import { SOURCE_FLAGS } from './market_operation_utils/constants';
import { convertNativeOrderToFullyFillableOptimizedOrders } from './market_operation_utils/orders';
import { import {
ERC20BridgeSource, ERC20BridgeSource,
FeeSchedule, FeeSchedule,
@ -89,24 +87,26 @@ export class SwapQuoteCalculator {
operation: MarketOperation, operation: MarketOperation,
opts: CalculateSwapQuoteOpts, opts: CalculateSwapQuoteOpts,
): Promise<Array<SwapQuote | undefined>> { ): Promise<Array<SwapQuote | undefined>> {
const batchSignedOrders = await this._marketOperationUtils.getBatchMarketBuyOrdersAsync( const optimizerResults = await this._marketOperationUtils.getBatchMarketBuyOrdersAsync(
batchPrunedOrders, batchPrunedOrders,
assetFillAmounts, assetFillAmounts,
opts, opts,
); );
const batchSwapQuotes = await Promise.all( const batchSwapQuotes = await Promise.all(
batchSignedOrders.map(async (orders, i) => { optimizerResults.map(async (result, i) => {
if (orders) { if (result) {
const { makerAssetData, takerAssetData } = batchPrunedOrders[i][0]; const { makerAssetData, takerAssetData } = batchPrunedOrders[i][0];
return createSwapQuote( return createSwapQuote(
makerAssetData, makerAssetData,
takerAssetData, takerAssetData,
orders, result.optimizedOrders,
operation, operation,
assetFillAmounts[i], assetFillAmounts[i],
gasPrice, gasPrice,
opts.gasSchedule, opts.gasSchedule,
result.marketSideLiquidity.makerTokenDecimals,
result.marketSideLiquidity.takerTokenDecimals,
); );
} else { } else {
return undefined; return undefined;
@ -122,7 +122,7 @@ export class SwapQuoteCalculator {
operation: MarketOperation, operation: MarketOperation,
opts: CalculateSwapQuoteOpts, opts: CalculateSwapQuoteOpts,
): Promise<SwapQuote> { ): Promise<SwapQuote> {
// checks if maker asset is ERC721 or ERC20 and taker asset is ERC20 // checks if maker asset is ERC20 and taker asset is ERC20
if (!isSupportedAssetDataInOrders(prunedOrders)) { if (!isSupportedAssetDataInOrders(prunedOrders)) {
throw Error(SwapQuoterError.AssetDataUnsupported); throw Error(SwapQuoterError.AssetDataUnsupported);
} }
@ -131,6 +131,8 @@ export class SwapQuoteCalculator {
let optimizedOrders: OptimizedMarketOrder[]; let optimizedOrders: OptimizedMarketOrder[];
let quoteReport: QuoteReport | undefined; let quoteReport: QuoteReport | undefined;
let sourceFlags: number = 0; let sourceFlags: number = 0;
let makerTokenDecimals: number;
let takerTokenDecimals: number;
// Scale fees by gas price. // Scale fees by gas price.
const _opts: GetMarketOrdersOpts = { const _opts: GetMarketOrdersOpts = {
@ -141,34 +143,16 @@ export class SwapQuoteCalculator {
exchangeProxyOverhead: flags => gasPrice.times(opts.exchangeProxyOverhead(flags)), exchangeProxyOverhead: flags => gasPrice.times(opts.exchangeProxyOverhead(flags)),
}; };
const firstOrderMakerAssetData = !!prunedOrders[0] const result =
? assetDataUtils.decodeAssetDataOrThrow(prunedOrders[0].makerAssetData) operation === MarketOperation.Buy
: { assetProxyId: '' }; ? await this._marketOperationUtils.getMarketBuyOrdersAsync(prunedOrders, assetFillAmount, _opts)
: await this._marketOperationUtils.getMarketSellOrdersAsync(prunedOrders, assetFillAmount, _opts);
if (firstOrderMakerAssetData.assetProxyId === AssetProxyId.ERC721) { optimizedOrders = result.optimizedOrders;
// HACK: to conform ERC721 orders to the output of market operation utils, assumes complete fillable quoteReport = result.quoteReport;
optimizedOrders = prunedOrders.map(o => convertNativeOrderToFullyFillableOptimizedOrders(o)); sourceFlags = result.sourceFlags;
} else { makerTokenDecimals = result.marketSideLiquidity.makerTokenDecimals;
if (operation === MarketOperation.Buy) { takerTokenDecimals = result.marketSideLiquidity.takerTokenDecimals;
const buyResult = await this._marketOperationUtils.getMarketBuyOrdersAsync(
prunedOrders,
assetFillAmount,
_opts,
);
optimizedOrders = buyResult.optimizedOrders;
quoteReport = buyResult.quoteReport;
sourceFlags = buyResult.sourceFlags;
} else {
const sellResult = await this._marketOperationUtils.getMarketSellOrdersAsync(
prunedOrders,
assetFillAmount,
_opts,
);
optimizedOrders = sellResult.optimizedOrders;
quoteReport = sellResult.quoteReport;
sourceFlags = sellResult.sourceFlags;
}
}
// assetData information for the result // assetData information for the result
const { makerAssetData, takerAssetData } = prunedOrders[0]; const { makerAssetData, takerAssetData } = prunedOrders[0];
@ -182,6 +166,8 @@ export class SwapQuoteCalculator {
assetFillAmount, assetFillAmount,
gasPrice, gasPrice,
opts.gasSchedule, opts.gasSchedule,
makerTokenDecimals,
takerTokenDecimals,
quoteReport, quoteReport,
) )
: createSwapQuote( : createSwapQuote(
@ -192,6 +178,8 @@ export class SwapQuoteCalculator {
assetFillAmount, assetFillAmount,
gasPrice, gasPrice,
opts.gasSchedule, opts.gasSchedule,
makerTokenDecimals,
takerTokenDecimals,
quoteReport, quoteReport,
); );
// Use the raw gas, not scaled by gas price // Use the raw gas, not scaled by gas price
@ -210,6 +198,8 @@ function createSwapQuote(
assetFillAmount: BigNumber, assetFillAmount: BigNumber,
gasPrice: BigNumber, gasPrice: BigNumber,
gasSchedule: FeeSchedule, gasSchedule: FeeSchedule,
makerTokenDecimals: number,
takerTokenDecimals: number,
quoteReport?: QuoteReport, quoteReport?: QuoteReport,
): SwapQuote { ): SwapQuote {
const bestCaseFillResult = simulateBestCaseFill({ const bestCaseFillResult = simulateBestCaseFill({
@ -245,12 +235,16 @@ function createSwapQuote(
...quoteBase, ...quoteBase,
type: MarketOperation.Buy, type: MarketOperation.Buy,
makerAssetFillAmount: assetFillAmount, makerAssetFillAmount: assetFillAmount,
makerTokenDecimals,
takerTokenDecimals,
}; };
} else { } else {
return { return {
...quoteBase, ...quoteBase,
type: MarketOperation.Sell, type: MarketOperation.Sell,
takerAssetFillAmount: assetFillAmount, takerAssetFillAmount: assetFillAmount,
makerTokenDecimals,
takerTokenDecimals,
}; };
} }
} }
@ -263,6 +257,8 @@ function createTwoHopSwapQuote(
assetFillAmount: BigNumber, assetFillAmount: BigNumber,
gasPrice: BigNumber, gasPrice: BigNumber,
gasSchedule: FeeSchedule, gasSchedule: FeeSchedule,
makerTokenDecimals: number,
takerTokenDecimals: number,
quoteReport?: QuoteReport, quoteReport?: QuoteReport,
): SwapQuote { ): SwapQuote {
const [firstHopOrder, secondHopOrder] = optimizedOrders; const [firstHopOrder, secondHopOrder] = optimizedOrders;
@ -312,12 +308,16 @@ function createTwoHopSwapQuote(
...quoteBase, ...quoteBase,
type: MarketOperation.Buy, type: MarketOperation.Buy,
makerAssetFillAmount: assetFillAmount, makerAssetFillAmount: assetFillAmount,
makerTokenDecimals,
takerTokenDecimals,
}; };
} else { } else {
return { return {
...quoteBase, ...quoteBase,
type: MarketOperation.Sell, type: MarketOperation.Sell,
takerAssetFillAmount: assetFillAmount, takerAssetFillAmount: assetFillAmount,
makerTokenDecimals,
takerTokenDecimals,
}; };
} }
} }

View File

@ -33,8 +33,7 @@ export function isSupportedAssetDataInOrders(orders: SignedOrder[]): boolean {
const takerAssetData = assetDataUtils.decodeAssetDataOrThrow(o.takerAssetData); const takerAssetData = assetDataUtils.decodeAssetDataOrThrow(o.takerAssetData);
const makerAssetData = assetDataUtils.decodeAssetDataOrThrow(o.makerAssetData); const makerAssetData = assetDataUtils.decodeAssetDataOrThrow(o.makerAssetData);
return ( return (
(makerAssetData.assetProxyId === AssetProxyId.ERC20 || makerAssetData.assetProxyId === AssetProxyId.ERC20 &&
makerAssetData.assetProxyId === AssetProxyId.ERC721) &&
takerAssetData.assetProxyId === AssetProxyId.ERC20 && takerAssetData.assetProxyId === AssetProxyId.ERC20 &&
firstOrderMakerAssetData.assetProxyId === makerAssetData.assetProxyId firstOrderMakerAssetData.assetProxyId === makerAssetData.assetProxyId
); // checks that all native order maker assets are of the same type ); // checks that all native order maker assets are of the same type

View File

@ -1,5 +1,4 @@
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { ERC20BridgeSource } from '../../src'; import { ERC20BridgeSource } from '../../src';
import { constants } from '../../src/constants'; import { constants } from '../../src/constants';
@ -47,12 +46,16 @@ export async function getFullyFillableSwapQuoteWithNoFeesAsync(
...quoteBase, ...quoteBase,
type: MarketOperation.Buy, type: MarketOperation.Buy,
makerAssetFillAmount, makerAssetFillAmount,
makerTokenDecimals: 18,
takerTokenDecimals: 18,
}; };
} else { } else {
return { return {
...quoteBase, ...quoteBase,
type: MarketOperation.Sell, type: MarketOperation.Sell,
takerAssetFillAmount: totalTakerAssetAmount, takerAssetFillAmount: totalTakerAssetAmount,
makerTokenDecimals: 18,
takerTokenDecimals: 18,
}; };
} }
} }

1961
yarn.lock

File diff suppressed because it is too large Load Diff