Compare commits

...

4 Commits

Author SHA1 Message Date
Github Actions
6aa582d140 Publish
- @0x/contracts-integrations@2.7.7
 - @0x/asset-swapper@5.0.3
2020-11-05 23:57:34 +00:00
Github Actions
534d92fa00 Updated CHANGELOGS & MD docs 2020-11-05 23:57:28 +00:00
Romain Butteaud
37aae134ab feat: adding Curve pools: PAX, hBTC, metapools: gUSD, hUSD, USDn, mUSD, tBTC (#26)
* feat: adding Curve pools: PAX, hbtc, metapools: gusd, husd, usdn, musd, tbtc

* feat: CHANGELOG

* fix: bad import

* fix: curve_y address downcase, use POOLS addresses for names

* feat: add metaToken attribute to disable metapools for non-metaTokens in Curve

* fix: CHANGELOG
2020-11-05 15:27:45 -08:00
Daniel Pyrathon
36bd8f68c9 adds amendments to the rollout feature flag. Rollout indicative quote… (#30)
* adds amendments to the rollout feature flag. Rollout indicative quotes indipendently from firm quotes.

* Updates based on Brandon's feedback
2020-11-05 12:46:06 -08:00
15 changed files with 240 additions and 71 deletions

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1604620645,
"version": "2.7.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1604385937,
"version": "2.7.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.7.7 - _November 5, 2020_
* Dependencies updated
## v2.7.6 - _November 3, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-integrations",
"version": "2.7.6",
"version": "2.7.7",
"engines": {
"node": ">=6.12"
},
@@ -91,7 +91,7 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/asset-swapper": "^5.0.2",
"@0x/asset-swapper": "^5.0.3",
"@0x/base-contract": "^6.2.11",
"@0x/contracts-asset-proxy": "^3.6.4",
"@0x/contracts-erc1155": "^2.1.13",

View File

@@ -1,10 +1,23 @@
[
{
"timestamp": 1604620645,
"version": "5.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1604385937,
"version": "5.0.2",
"changes": [
{
"note": "Dependencies updated"
},
{
"note": "adding Curve pools: PAX, hBTC, metapools: gUSD, hUSD, USDn, mUSD, tBTC",
"pr": 26
}
]
},

View File

@@ -5,9 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v5.0.3 - _November 5, 2020_
* Dependencies updated
## v5.0.2 - _November 3, 2020_
* Dependencies updated
* adding Curve pools: PAX, hBTC, metapools: gUSD, hUSD, USDn, mUSD, tBTC (#26)
## v5.0.1 - _November 3, 2020_

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/asset-swapper",
"version": "5.0.2",
"version": "5.0.3",
"engines": {
"node": ">=6.12"
},

View File

@@ -90,7 +90,10 @@ const DEFAULT_SWAP_QUOTE_REQUEST_OPTS: SwapQuoteRequestOpts = {
const DEFAULT_RFQT_REQUEST_OPTS: Partial<RfqtRequestOpts> = {
makerEndpointMaxResponseTimeMs: 1000,
isPriceAwareRFQEnabled: false,
priceAwareRFQFlag: {
isFirmPriceAwareEnabled: false,
isIndicativePriceAwareEnabled: false,
},
};
export const DEFAULT_INFO_LOGGER: LogFunction = (obj, msg) =>

View File

@@ -41,6 +41,7 @@ import { ProtocolFeeUtils } from './utils/protocol_fee_utils';
import { QuoteRequestor } from './utils/quote_requestor';
import { sortingUtils } from './utils/sorting_utils';
import { SwapQuoteCalculator } from './utils/swap_quote_calculator';
import { getPriceAwareRFQRolloutFlags } from './utils/utils';
import { ERC20BridgeSamplerContract } from './wrappers';
export class SwapQuoter {
@@ -700,7 +701,7 @@ export class SwapQuoter {
if (
opts.rfqt && // This is an RFQT-enabled API request
!opts.rfqt.isPriceAwareRFQEnabled && // If Price-aware RFQ is enabled, firm quotes are requested later on in the process.
!getPriceAwareRFQRolloutFlags(opts.rfqt.priceAwareRFQFlag).isFirmPriceAwareEnabled && // If Price-aware RFQ is enabled, firm quotes are requested later on in the process.
opts.rfqt.intentOnFilling && // The requestor is asking for a firm quote
opts.rfqt.apiKey &&
this._isApiKeyWhitelisted(opts.rfqt.apiKey) && // A valid API key was provided

View File

@@ -234,6 +234,11 @@ export type SwapQuoteOrdersBreakdown = Partial<
}
>;
export interface PriceAwareRFQFlags {
isIndicativePriceAwareEnabled: boolean;
isFirmPriceAwareEnabled: boolean;
}
/**
* nativeExclusivelyRFQT: if set to `true`, Swap quote will exclude Open Orderbook liquidity.
* If set to `true` and `ERC20BridgeSource.Native` is part of the `excludedSources`
@@ -256,7 +261,7 @@ export interface RfqtRequestOpts {
* the feature flag. When that time comes, follow this PR to "undo" the feature flag:
* https://github.com/0xProject/0x-monorepo/pull/2735
*/
isPriceAwareRFQEnabled?: boolean;
priceAwareRFQFlag?: PriceAwareRFQFlags;
}
/**

View File

@@ -98,29 +98,60 @@ export const TOKENS = {
USDC: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
USDT: '0xdac17f958d2ee523a2206206994597c13d831ec7',
sUSD: '0x57ab1ec28d129707052df4df418d58a2d46d5f51',
BUSD: '0x4fabb145d64652a948d72533023f6e7a623c7c53',
TUSD: '0x0000000000085d4780b73119b644ae5ecd22b376',
PAX: '0x8e870d67f660d95d5be530380d0ec0bd388289e1',
GUSD: '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd',
HUSD: '0xdf574c24545e5ffecb9a659c229253d4111d87e1',
mUSD: '0xe2f2a5c287993345a840db3b0845fbc70f5935a5',
USDN: '0x674c6ad92fd080e4004b2312b45f796a192d27a0',
// Bitcoins
WBTC: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599',
RenBTC: '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d',
sBTC: '0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6',
tBTC: '0x8daebade922df735c38c80c7ebd708af50815faa',
hBTC: '0x0316eb71485b0ab14103307bf65a021042c6d380',
// Other
MKR: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2',
};
export const POOLS = {
// following the same order in curve.fi:
curve_compound: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56',
// curve_USDT: '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c',
curve_PAX: '0x06364f10b501e868329afbc005b3492902d6c763',
curve_y: '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51',
curve_BUSD: '0x79a8c46dea5ada233abaffd40f3a0a2b1e5a4f27',
curve_sUSD: '0xa5407eae9ba41422680e2e00537571bcc53efbfd',
curve_renBTC: '0x93054188d876f558f4a66b2ef1d97d16edf0895b',
curve_sBTC: '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714',
curve_HBTC: '0x4ca9b3063ec5866a4b82e437059d2c43d1be596f',
curve_TRI: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
curve_GUSD: '0x4f062658eaaf2c1ccf8c8e36d6824cdf41167956',
curve_HUSD: '0x3ef6a01a0f81d6046290f3e2a8c5b843e738e604',
// 12.usdk is dead
curve_USDN: '0x0f9cb53ebe405d49a0bbdbd291a65ff571bc83e1',
// 14.linkusd is dead
curve_mUSD: '0x8474ddbe98f5aa3179b3b3f5942d724afcdec9f6',
// 16.rsv is dead
curve_tBTC: '0xc25099792e9349c7dd09759744ea681c7de2cb66',
};
/**
* Mainnet Curve configuration
* The tokens are in order of their index, which each curve defines
* I.e DaiUsdc curve has DAI as index 0 and USDC as index 1
*/
export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
DaiUsdc: {
[POOLS.curve_compound]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
poolAddress: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56',
poolAddress: POOLS.curve_compound,
tokens: [TOKENS.DAI, TOKENS.USDC],
metaToken: undefined,
},
// DaiUsdcUsdt: {
// USDT: {
// exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
// sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
@@ -131,53 +162,110 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
// TOKENS.USDT,
// ],
// },
DaiUsdcUsdtTusd: {
[POOLS.curve_PAX]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: POOLS.curve_PAX,
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.PAX],
metaToken: undefined,
},
[POOLS.curve_y]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
poolAddress: '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51',
poolAddress: POOLS.curve_y,
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.TUSD],
metaToken: undefined,
},
// Looks like it's dying.
DaiUsdcUsdtBusd: {
[POOLS.curve_BUSD]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
poolAddress: '0x79a8c46dea5ada233abaffd40f3a0a2b1e5a4f27',
tokens: [
TOKENS.DAI,
TOKENS.USDC,
TOKENS.USDT,
'0x4fabb145d64652a948d72533023f6e7a623c7c53', // bUSD
],
poolAddress: POOLS.curve_BUSD,
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.BUSD],
metaToken: undefined,
},
DaiUsdcUsdtSusd: {
[POOLS.curve_sUSD]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0xa5407eae9ba41422680e2e00537571bcc53efbfd',
poolAddress: POOLS.curve_sUSD,
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD],
metaToken: undefined,
},
RenbtcWbtc: {
[POOLS.curve_renBTC]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0x93054188d876f558f4a66b2ef1d97d16edf0895b',
poolAddress: POOLS.curve_renBTC,
tokens: [TOKENS.RenBTC, TOKENS.WBTC],
metaToken: undefined,
},
RenbtcWbtcSbtc: {
[POOLS.curve_sBTC]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714',
poolAddress: POOLS.curve_sBTC,
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
metaToken: undefined,
},
TriPool: {
[POOLS.curve_HBTC]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
poolAddress: POOLS.curve_HBTC,
tokens: [TOKENS.hBTC, TOKENS.WBTC],
metaToken: undefined,
},
[POOLS.curve_TRI]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: POOLS.curve_TRI,
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
metaToken: undefined,
},
// Metapools
[POOLS.curve_GUSD]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: POOLS.curve_GUSD,
tokens: [TOKENS.GUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
metaToken: TOKENS.GUSD,
},
[POOLS.curve_HUSD]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: POOLS.curve_HUSD,
tokens: [TOKENS.HUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
metaToken: TOKENS.HUSD,
},
[POOLS.curve_USDN]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: POOLS.curve_USDN,
tokens: [TOKENS.USDN, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
metaToken: TOKENS.USDN,
},
[POOLS.curve_mUSD]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: POOLS.curve_mUSD,
tokens: [TOKENS.mUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
metaToken: TOKENS.mUSD,
},
[POOLS.curve_tBTC]: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: POOLS.curve_tBTC,
tokens: [TOKENS.tBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
metaToken: TOKENS.tBTC,
},
};
@@ -188,6 +276,7 @@ export const MAINNET_SWERVE_INFOS: { [name: string]: CurveInfo } = {
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0x329239599afb305da0a2ec69c58f8a6697f9f88d', // _target: 0xa5407eae9ba41422680e2e00537571bcc53efbfd
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.TUSD],
metaToken: undefined,
},
};
@@ -201,6 +290,7 @@ export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
'0x5dbcf33d8c2e976c6b560249878e6f1491bca25c', // yUSD
'0x2994529c0652d127b7842094103715ec5299bbed', // ybCRV
],
metaToken: undefined,
},
yVaultCurveUnderlying: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
@@ -211,6 +301,7 @@ export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
'0xdf5e0e81dff6faf3a7e52ba697820c5e32d806a8', // yCRV
'0x3b3ac5386837dc563660fb6a0937dfaa5924333b', // bCRV
],
metaToken: undefined,
},
yVaultUSD: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
@@ -223,20 +314,8 @@ export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
'0x2f08119c6f07c006695e079aafc638b8789faf18', // yUSDT
'0x37d19d1c4e1fa9dc47bd1ea12f742a0887eda74a', // yTUSD
],
metaToken: undefined,
},
// Gas is too high for these underlying tokens (3M+)
// yVaultUSDUnderlying: {
// exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
// sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
// poolAddress: '0x4571753311e37ddb44faa8fb78a6df9a6e3c6c0b',
// tokens: [
// TOKENS.DAI,
// TOKENS.USDC,
// TOKENS.USDT,
// TOKENS.TUSD,
// ],
// },
};
export const MAINNET_KYBER_RESERVE_IDS: { [name: string]: string } = {
@@ -361,19 +440,25 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.Curve]: fillData => {
const poolAddress = (fillData as CurveFillData).pool.poolAddress.toLowerCase();
switch (poolAddress) {
case '0xa5407eae9ba41422680e2e00537571bcc53efbfd':
case '0x93054188d876f558f4a66b2ef1d97d16edf0895b':
case '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714':
case '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7':
case POOLS.curve_renBTC:
case POOLS.curve_sBTC:
case POOLS.curve_sUSD:
case POOLS.curve_HBTC:
case POOLS.curve_TRI:
return 150e3;
case '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56':
case POOLS.curve_compound:
return 750e3;
case '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51':
case POOLS.curve_PAX:
case POOLS.curve_y:
case POOLS.curve_BUSD:
return 850e3;
case '0x79a8c46dea5ada233abaffd40f3a0a2b1e5a4f27':
return 1e6;
case '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c':
return 600e3;
// Metapools
case POOLS.curve_GUSD:
case POOLS.curve_HUSD:
case POOLS.curve_USDN:
case POOLS.curve_mUSD:
case POOLS.curve_tBTC:
return 650e3;
default:
throw new Error(`Unrecognized Curve address: ${poolAddress}`);
}

View File

@@ -3,13 +3,31 @@ import { CurveInfo, SnowSwapInfo, SwerveInfo } from './types';
// tslint:disable completed-docs
export function getCurveInfosForPair(takerToken: string, makerToken: string): CurveInfo[] {
return Object.values(MAINNET_CURVE_INFOS).filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)));
return Object.values(MAINNET_CURVE_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
),
);
}
export function getSwerveInfosForPair(takerToken: string, makerToken: string): SwerveInfo[] {
return Object.values(MAINNET_SWERVE_INFOS).filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)));
return Object.values(MAINNET_SWERVE_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
),
);
}
export function getSnowSwapInfosForPair(takerToken: string, makerToken: string): SnowSwapInfo[] {
return Object.values(MAINNET_SNOWSWAP_INFOS).filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)));
return Object.values(MAINNET_SNOWSWAP_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaToken === undefined) ||
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
),
);
}

View File

@@ -6,6 +6,7 @@ import * as _ from 'lodash';
import { AssetSwapperContractAddresses, MarketOperation, Omit } from '../../types';
import { QuoteRequestor } from '../quote_requestor';
import { getPriceAwareRFQRolloutFlags } from '../utils';
import { generateQuoteReport, QuoteReport } from './../quote_report_generator';
import {
@@ -214,7 +215,8 @@ export class MarketOperationUtils {
),
);
const isPriceAwareRfqEnabled = _opts.rfqt && _opts.rfqt.isPriceAwareRFQEnabled;
const isPriceAwareRfqEnabled =
_opts.rfqt && getPriceAwareRFQRolloutFlags(_opts.rfqt.priceAwareRFQFlag).isIndicativePriceAwareEnabled;
const rfqtPromise =
!isPriceAwareRfqEnabled && quoteSourceFilters.isAllowed(ERC20BridgeSource.Native)
? getRfqtIndicativeQuotesAsync(
@@ -362,7 +364,8 @@ export class MarketOperationUtils {
this._liquidityProviderRegistry,
),
);
const isPriceAwareRfqEnabled = _opts.rfqt && _opts.rfqt.isPriceAwareRFQEnabled;
const isPriceAwareRfqEnabled =
_opts.rfqt && getPriceAwareRFQRolloutFlags(_opts.rfqt.priceAwareRFQFlag).isIndicativePriceAwareEnabled;
const rfqtPromise =
!isPriceAwareRfqEnabled && quoteSourceFilters.isAllowed(ERC20BridgeSource.Native)
? getRfqtIndicativeQuotesAsync(
@@ -677,12 +680,7 @@ export class MarketOperationUtils {
// If RFQ liquidity is enabled, make a request to check RFQ liquidity
let comparisonPrice: BigNumber | undefined;
const { rfqt } = _opts;
if (
rfqt &&
rfqt.isPriceAwareRFQEnabled &&
rfqt.quoteRequestor &&
marketSideLiquidity.quoteSourceFilters.isAllowed(ERC20BridgeSource.Native)
) {
if (rfqt && rfqt.quoteRequestor && marketSideLiquidity.quoteSourceFilters.isAllowed(ERC20BridgeSource.Native)) {
// Calculate a suggested price. For now, this is simply the overall price of the aggregation.
if (optimizerResult) {
const totalMakerAmount = BigNumber.sum(
@@ -706,8 +704,12 @@ export class MarketOperationUtils {
}
}
// If we are making an indicative quote, make the RFQT request and then re-run the sampler if new orders come back.
if (rfqt.isIndicative) {
const { isFirmPriceAwareEnabled, isIndicativePriceAwareEnabled } = getPriceAwareRFQRolloutFlags(
rfqt.priceAwareRFQFlag,
);
if (rfqt.isIndicative && isIndicativePriceAwareEnabled) {
// An indicative quote is beingh requested, and indicative quotes price-aware enabled. Make the RFQT request and then re-run the sampler if new orders come back.
const indicativeQuotes = await getRfqtIndicativeQuotesAsync(
nativeOrders[0].makerAssetData,
nativeOrders[0].takerAssetData,
@@ -726,8 +728,8 @@ export class MarketOperationUtils {
optimizerOpts,
);
}
} else {
// A firm quote is being requested. Ensure that `intentOnFilling` is enabled.
} else if (!rfqt.isIndicative && isFirmPriceAwareEnabled) {
// A firm quote is being requested, and firm quotes price-aware enabled. Ensure that `intentOnFilling` is enabled.
if (rfqt.intentOnFilling) {
// Extra validation happens when requesting a firm quote, such as ensuring that the takerAddress
// is indeed valid.

View File

@@ -75,6 +75,7 @@ export interface CurveInfo {
buyQuoteFunctionSelector: CurveFunctionSelectors;
poolAddress: string;
tokens: string[];
metaToken: string | undefined;
}
export interface SwerveInfo extends CurveInfo {}

View File

@@ -4,9 +4,27 @@ import { BigNumber, NULL_BYTES } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { constants } from '../constants';
import { PriceAwareRFQFlags } from '../types';
// tslint:disable: no-unnecessary-type-assertion completed-docs
/**
* Returns 2 flags (one for firm quotes and another for indicative quotes) that serve as rollout flags for the price-aware RFQ feature.
* By default, indicative quotes should *always* go through the new price-aware flow. This means that all indicative RFQ requests made to
* market makers will contain the new price-aware `suggestedPrice` field.
* The `isPriceAwareRFQEnabled` feature object that is passed in by the 0x API will then control whether firm quotes go through price-aware RFQ.
*
* @param isPriceAwareRFQEnabled the feature flag that is passed in by the 0x API.
*/
export function getPriceAwareRFQRolloutFlags(priceAwareRFQFlags?: PriceAwareRFQFlags): PriceAwareRFQFlags {
return priceAwareRFQFlags !== undefined
? priceAwareRFQFlags
: {
isFirmPriceAwareEnabled: false,
isIndicativePriceAwareEnabled: false,
};
}
export function isSupportedAssetDataInOrders(orders: SignedOrder[]): boolean {
const firstOrderMakerAssetData = !!orders[0]
? assetDataUtils.decodeAssetDataOrThrow(orders[0].makerAssetData)

View File

@@ -17,6 +17,7 @@ import * as _ from 'lodash';
import * as TypeMoq from 'typemoq';
import { MarketOperation, QuoteRequestor, RfqtRequestOpts, SignedOrderWithFillableAmounts } from '../src';
import { PriceAwareRFQFlags } from '../src/types';
import { getRfqtIndicativeQuotesAsync, MarketOperationUtils } from '../src/utils/market_operation_utils/';
import { BalancerPoolsCache } from '../src/utils/market_operation_utils/balancer_utils';
import {
@@ -66,6 +67,10 @@ const DEFAULT_EXCLUDED = [
const BUY_SOURCES = BUY_SOURCE_FILTER.sources;
const SELL_SOURCES = SELL_SOURCE_FILTER.sources;
const TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = {};
const PRICE_AWARE_RFQ_ENABLED: PriceAwareRFQFlags = {
isFirmPriceAwareEnabled: true,
isIndicativePriceAwareEnabled: true,
};
// tslint:disable: custom-no-magic-numbers promise-function-async
describe('MarketOperationUtils tests', () => {
@@ -891,7 +896,7 @@ describe('MarketOperationUtils tests', () => {
apiKey: 'foo',
takerAddress: randomAddress(),
intentOnFilling: true,
isPriceAwareRFQEnabled: true,
priceAwareRFQFlag: PRICE_AWARE_RFQ_ENABLED,
quoteRequestor: {
requestRfqtFirmQuotesAsync: mockedQuoteRequestor.object.requestRfqtFirmQuotesAsync,
} as any,
@@ -931,7 +936,7 @@ describe('MarketOperationUtils tests', () => {
apiKey: 'foo',
takerAddress: randomAddress(),
intentOnFilling: true,
isPriceAwareRFQEnabled: true,
priceAwareRFQFlag: PRICE_AWARE_RFQ_ENABLED,
quoteRequestor: {
requestRfqtFirmQuotesAsync: requestor.object.requestRfqtFirmQuotesAsync,
} as any,
@@ -974,7 +979,7 @@ describe('MarketOperationUtils tests', () => {
rfqt: {
isIndicative: true,
apiKey: 'foo',
isPriceAwareRFQEnabled: true,
priceAwareRFQFlag: PRICE_AWARE_RFQ_ENABLED,
takerAddress: randomAddress(),
intentOnFilling: true,
quoteRequestor: {
@@ -1033,7 +1038,7 @@ describe('MarketOperationUtils tests', () => {
apiKey: 'foo',
takerAddress: randomAddress(),
intentOnFilling: true,
isPriceAwareRFQEnabled: true,
priceAwareRFQFlag: PRICE_AWARE_RFQ_ENABLED,
quoteRequestor: {
requestRfqtFirmQuotesAsync: requestor.object.requestRfqtFirmQuotesAsync,
} as any,
@@ -1089,7 +1094,7 @@ describe('MarketOperationUtils tests', () => {
isIndicative: false,
apiKey: 'foo',
takerAddress: randomAddress(),
isPriceAwareRFQEnabled: true,
priceAwareRFQFlag: PRICE_AWARE_RFQ_ENABLED,
intentOnFilling: true,
quoteRequestor: {
requestRfqtFirmQuotesAsync: requestor.object.requestRfqtFirmQuotesAsync,