Compare commits

..

17 Commits

Author SHA1 Message Date
Github Actions
6b2856424a Publish
- @0x/asset-swapper@16.59.0
2022-05-13 00:07:18 +00:00
Github Actions
da757c4700 Updated CHANGELOGS & MD docs 2022-05-13 00:07:16 +00:00
Kyu
75e6654884 Fix a lint issue (#475) 2022-05-12 16:49:10 -07:00
Cece Z
87308e7693 Update saddle mainnet pools (#450)
* Add saddle v2 pools

* remove outdated pools

* add two saddle meta pools

* forgot changelog

* remove saddle metapools

* changelog update
2022-05-12 18:59:55 -04:00
phil-ociraptor
d5eef93a76 add message to changelog for #467 (#474) 2022-05-11 22:17:17 -05:00
phil-ociraptor
a7f23a982e feat: add IRfqClient (#467) 2022-05-11 12:35:05 -05:00
Kyu
9eadc5fc28 chore: Offboard Eth2Dai [TKR-356] (#470)
* Offboard Eth2Dai

* Update CHANGELOG.json
2022-05-10 13:54:28 -07:00
Kyu
92ad1a612e chore: Offboard Swerve Finance and LinkSwap [TKR-356] (#469)
* Offboard swerve

* Update CHANGELOG.json

* Offboard LinkSwap

* Remove unused import

* Fix CHANGELOG.json
2022-05-10 13:13:18 -07:00
Kyu
09413c0e12 chore: Decomission SnowSwap [TKR-356] (#468)
* Decomission SnowSwap

* SnowSwap doesn't have much liquidity anymore (the largest pool has ~$50k)

* Update CHANGELOG.json

* Update CHANGELOG.json
2022-05-10 09:55:43 -07:00
Github Actions
23788b41d5 Publish
- @0x/asset-swapper@16.57.3
2022-05-10 01:41:10 +00:00
Github Actions
ccf999a495 Updated CHANGELOGS & MD docs 2022-05-10 01:41:06 +00:00
Kyu
aa1016ee5f Do not initialize BalancerV2SwapInfoCache on unsupported chains [TKR-365] (#472)
* Do not initialize BalancerV2SwapInfoCache on unsupported chains
* Update CHANGELOG.json
2022-05-09 18:21:04 -07:00
Github Actions
423ef57344 Publish
- @0x/asset-swapper@16.57.2
2022-05-02 21:22:37 +00:00
Github Actions
c18149e82f Updated CHANGELOGS & MD docs 2022-05-02 21:22:33 +00:00
Jorge Pérez
d14aebf724 Fix the filter for considered sources on indicative sells for Quote Report (#466) 2022-05-02 15:45:15 -05:00
Kyu
ba719a9631 Add cvxfxs-fxs curve pool on Ethereum mainnet (#465)
* Add cvxfxs-fxs curve pool on Ethereum mainnet

* Update CHANGELOG.json

* Fix an existing formatting issue

* Adjust gasSchedule and merge the change under 16.57.1
2022-04-27 17:07:36 -07:00
eobbad
d36034d958 chore/ANY-QUICK on polygon MAG-MIM on avax (#464)
* Added ANY/QUICK pair on Polygon

* Updated changelog.json

* Update CHANGELOG.json
2022-04-26 10:55:03 -04:00
18 changed files with 343 additions and 264 deletions

View File

@@ -1,4 +1,68 @@
[
{
"version": "16.59.0",
"changes": [
{
"note": "Remove SnowSwap on mainnet",
"pr": 468
},
{
"note": "Offboard Swerve Finance and LinkSwap",
"pr": 469
},
{
"note": "Offboard Eth2Dai",
"pr": 470
},
{
"note": "Add an optional IRfqClient for SwapQuoter#getSwapQuoteAsync",
"pr": 467
}
],
"timestamp": 1652400434
},
{
"version": "16.58.0",
"changes": [
{
"note": "Update Saddle pools on Mainnet",
"pr": 450
}
]
},
{
"version": "16.57.3",
"changes": [
{
"note": "Fix a runtime error related to BalancerV2SwapInfoCache",
"pr": 472
}
],
"timestamp": 1652146864
},
{
"version": "16.57.2",
"changes": [
{
"note": "Fix missing AMM quotes on indicative Quote Reports",
"pr": 466
}
],
"timestamp": 1651526551
},
{
"version": "16.57.1",
"changes": [
{
"note": "Added QUICK/ANY pair on Polygon",
"pr": 464
},
{
"note": "Added cvxFXS/FXS curve pool on mainnet",
"pr": 465
}
]
},
{
"version": "16.57.0",
"changes": [

View File

@@ -5,6 +5,30 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v16.59.0 - _May 13, 2022_
* Remove SnowSwap on mainnet (#468)
* Offboard Swerve Finance and LinkSwap (#469)
* Offboard Eth2Dai (#470)
* Add an optional IRfqClient for SwapQuoter#getSwapQuoteAsync (#467)
## v16.58.0 - _Invalid date_
* Update Saddle pools on Mainnet (#450)
## v16.57.3 - _May 10, 2022_
* Fix a runtime error related to BalancerV2SwapInfoCache (#472)
## v16.57.2 - _May 2, 2022_
* Fix missing AMM quotes on indicative Quote Reports (#466)
## v16.57.1 - _Invalid date_
* Added QUICK/ANY pair on Polygon (#464)
* Added cvxFXS/FXS curve pool on mainnet (#465)
## v16.57.0 - _April 22, 2022_
* Add BalancerV2 batch swap support (#462)

View File

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

View File

@@ -116,6 +116,15 @@ export {
SamplerMetrics,
} from './types';
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
export {
IRfqClient,
RfqClientV1Price,
RfqClientV1PriceRequest,
RfqClientV1PriceResponse,
RfqClientV1Quote,
RfqClientV1QuoteRequest,
RfqClientV1QuoteResponse,
} from './utils/irfq_client';
export {
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
DEFAULT_GAS_SCHEDULE,

View File

@@ -280,7 +280,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
if (
this.chainId === ChainId.Mainnet &&
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Curve, ERC20BridgeSource.Swerve]) &&
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Curve]) &&
// Curve VIP cannot currently support WETH buy/sell as the functionality needs to WITHDRAW or DEPOSIT
// into WETH prior/post the trade.
// ETH buy/sell is supported

View File

@@ -25,6 +25,7 @@ import {
SwapQuoterRfqOpts,
} from './types';
import { assert } from './utils/assert';
import { IRfqClient } from './utils/irfq_client';
import { MarketOperationUtils } from './utils/market_operation_utils';
import { BancorService } from './utils/market_operation_utils/bancor_service';
import { SAMPLER_ADDRESS, SOURCE_FLAGS, ZERO_AMOUNT } from './utils/market_operation_utils/constants';
@@ -327,6 +328,7 @@ export class SwapQuoter {
assetFillAmount: BigNumber,
marketOperation: MarketOperation,
options: Partial<SwapQuoteRequestOpts>,
rfqClient?: IRfqClient | undefined,
): Promise<SwapQuote> {
assert.isETHAddressHex('makerToken', makerToken);
assert.isETHAddressHex('takerToken', takerToken);
@@ -381,6 +383,7 @@ export class SwapQuoter {
this.expiryBufferMs,
rfqtOptions?.metricsProxy,
);
calcOpts.rfqt.rfqClient = rfqClient;
}
const result: OptimizerResultWithReport = await this._marketOperationUtils.getOptimizerResultAsync(

View File

@@ -17,7 +17,10 @@ import {
const SUCCESS_CODE = 201;
function getAltMarketInfo(
/**
* Returns the AltOffering if it exists for a given pair
*/
export function getAltMarketInfo(
offerings: AltOffering[],
buyTokenAddress: string,
sellTokenAddress: string,

View File

@@ -0,0 +1,59 @@
import { RfqOrder, Signature } from '@0x/protocol-utils';
import { BigNumber } from '@0x/utils';
import { AltRfqMakerAssetOfferings } from '../types';
export interface RfqClientV1PriceRequest {
altRfqAssetOfferings: AltRfqMakerAssetOfferings | undefined;
assetFillAmount: BigNumber;
chainId: number;
comparisonPrice: BigNumber | undefined;
integratorId: string;
intentOnFilling: boolean;
makerToken: string;
marketOperation: 'Sell' | 'Buy';
takerAddress: string;
takerToken: string;
txOrigin: string;
}
export interface RfqClientV1QuoteRequest extends RfqClientV1PriceRequest {}
export interface RfqClientV1Price {
expiry: BigNumber;
kind: 'rfq' | 'otc';
makerAmount: BigNumber;
makerToken: string;
makerUri: string;
takerAmount: BigNumber;
takerToken: string;
}
export interface RfqClientV1PriceResponse {
prices: RfqClientV1Price[];
}
export interface RfqClientV1Quote {
makerUri: string;
order: RfqOrder;
signature: Signature;
}
export interface RfqClientV1QuoteResponse {
quotes: RfqClientV1Quote[];
}
/**
* IRfqClient is an interface that defines how to connect with an Rfq system.
*/
export interface IRfqClient {
/**
* Fetches a list of "indicative quotes" or prices from a remote Rfq server
*/
getV1PricesAsync(request: RfqClientV1PriceRequest): Promise<RfqClientV1PriceResponse>;
/**
* Fetches a list of "firm quotes" or signed quotes from a remote Rfq server.
*/
getV1QuotesAsync(request: RfqClientV1QuoteRequest): Promise<RfqClientV1QuoteResponse>;
}

View File

@@ -46,11 +46,9 @@ import {
SHIBASWAP_ROUTER_BY_CHAIN_ID,
SMOOTHY_BSC_INFOS,
SMOOTHY_MAINNET_INFOS,
SNOWSWAP_MAINNET_INFOS,
SPIRITSWAP_ROUTER_BY_CHAIN_ID,
SPOOKYSWAP_ROUTER_BY_CHAIN_ID,
SUSHISWAP_ROUTER_BY_CHAIN_ID,
SWERVE_MAINNET_INFOS,
SYNAPSE_AVALANCHE_INFOS,
SYNAPSE_BSC_INFOS,
SYNAPSE_FANTOM_INFOS,
@@ -225,32 +223,6 @@ export function getCurveV2InfosForPair(chainId: ChainId, takerToken: string, mak
}
}
export function getSwerveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(SWERVE_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaTokens === undefined) ||
(c.tokens.includes(t) && [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
),
);
}
export function getSnowSwapInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.Mainnet) {
return [];
}
return Object.values(SNOWSWAP_MAINNET_INFOS).filter(c =>
[makerToken, takerToken].every(
t =>
(c.tokens.includes(t) && c.metaTokens === undefined) ||
(c.tokens.includes(t) && [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
),
);
}
export function getNerveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
if (chainId !== ChainId.BSC) {
return [];
@@ -493,8 +465,6 @@ export function getCurveLikeInfosForPair(
source:
| ERC20BridgeSource.Curve
| ERC20BridgeSource.CurveV2
| ERC20BridgeSource.Swerve
| ERC20BridgeSource.SnowSwap
| ERC20BridgeSource.Nerve
| ERC20BridgeSource.Synapse
| ERC20BridgeSource.Belt
@@ -515,12 +485,6 @@ export function getCurveLikeInfosForPair(
case ERC20BridgeSource.CurveV2:
pools = getCurveV2InfosForPair(chainId, takerToken, makerToken);
break;
case ERC20BridgeSource.Swerve:
pools = getSwerveInfosForPair(chainId, takerToken, makerToken);
break;
case ERC20BridgeSource.SnowSwap:
pools = getSnowSwapInfosForPair(chainId, takerToken, makerToken);
break;
case ERC20BridgeSource.Nerve:
pools = getNerveInfosForPair(chainId, takerToken, makerToken);
break;

View File

@@ -79,7 +79,6 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Native,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.UniswapV2,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.Kyber,
ERC20BridgeSource.Curve,
ERC20BridgeSource.Balancer,
@@ -87,8 +86,6 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Bancor,
ERC20BridgeSource.MStable,
ERC20BridgeSource.Mooniswap,
ERC20BridgeSource.Swerve,
ERC20BridgeSource.SnowSwap,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Shell,
ERC20BridgeSource.MultiHop,
@@ -97,7 +94,6 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Cream,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.CryptoCom,
ERC20BridgeSource.Linkswap,
ERC20BridgeSource.Lido,
ERC20BridgeSource.MakerPsm,
ERC20BridgeSource.KyberDmm,
@@ -225,7 +221,6 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Native,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.UniswapV2,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.Kyber,
ERC20BridgeSource.Curve,
ERC20BridgeSource.Balancer,
@@ -234,8 +229,6 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.MStable,
ERC20BridgeSource.Mooniswap,
ERC20BridgeSource.Shell,
ERC20BridgeSource.Swerve,
ERC20BridgeSource.SnowSwap,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.Dodo,
@@ -244,7 +237,6 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Lido,
ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.CryptoCom,
ERC20BridgeSource.Linkswap,
ERC20BridgeSource.MakerPsm,
ERC20BridgeSource.KyberDmm,
ERC20BridgeSource.Smoothy,
@@ -437,6 +429,7 @@ export const MAINNET_TOKENS = {
RenBTC: '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d',
sBTC: '0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6',
tBTC: '0x8daebade922df735c38c80c7ebd708af50815faa',
tBTCv2: '0x18084fbA666a33d37592fA2633fD49a74DD93a88',
hBTC: '0x0316eb71485b0ab14103307bf65a021042c6d380',
pBTC: '0x5228a22e72ccc52d415ecfd199f99d0665e7733b',
bBTC: '0x9be89d2a4cd102d8fecc6bf9da793be995c22541',
@@ -479,6 +472,7 @@ export const MAINNET_TOKENS = {
alUSD: '0xbc6da0fe9ad5f3b0d58160288917aa56653660e9',
// Frax ecosystem
FRAX: '0x853d955acef822db058eb8505911ed77f175b99e',
cvxFXS: '0xfeef77d3f69374f66429c91d732a244f074bdf74',
FXS: '0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0',
OHM: '0x383518188c0c6d7730d91b2c03a03c837814a899',
OHMV2: '0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5',
@@ -542,6 +536,7 @@ export const POLYGON_TOKENS = {
BANANA: '0x5d47baba0d66083c52009271faf3f50dcc01023c',
WEXPOLY: '0x4c4bf319237d98a30a929a96112effa8da3510eb',
nUSD: '0xb6c473756050de474286bed418b77aeac39b02af',
ANY: '0x6aB6d61428fde76768D7b45D8BFeec19c6eF91A8',
};
export const AVALANCHE_TOKENS = {
@@ -561,6 +556,7 @@ export const AVALANCHE_TOKENS = {
nUSD: '0xcfc37a6ab183dd4aed08c204d1c2773c0b1bdf46',
aWETH: '0x53f7c5869a859f0aec3d334ee8b4cf01e3492f21',
MIM: '0x130966628846bfd36ff31a822705796e8cb8c18d',
MAG: '0x1d60109178C48E4A937D8AB71699D8eBb6F7c5dE',
};
export const CELO_TOKENS = {
@@ -680,6 +676,7 @@ export const CURVE_POOLS = {
BUSD: '0x4807862aa8b2bf68830e4c8dc86d0e9a998e085a',
DSU3CRV: '0x6ec80df362d7042c50d4469bcfbc174c9dd9109a',
cvxcrv: '0x9d0464996170c6b9e75eed71c68b99ddedf279e8',
cvxfxs: '0xd658a338613198204dca1143ac3f01a722b5d94a',
mim: '0x5a6a4d54456819380173272a5e8e9b9904bdf41b',
eurt: '0xfd5db7463a3ab53fd211b4af195c5bccc1a03890',
ethcrv: '0x8301ae4fc9c624d1d396cbdaa1ed877821d7c511',
@@ -737,28 +734,13 @@ export const CURVE_OPTIMISM_POOLS = {
tri: '0x1337bedc9d22ecbe766df105c9623922a27963ec',
};
export const SWERVE_POOLS = {
y: '0x329239599afb305da0a2ec69c58f8a6697f9f88d',
};
export const SNOWSWAP_POOLS = {
yUSD: '0xbf7ccd6c446acfcc5df023043f2167b62e81899b',
yVault: '0x4571753311e37ddb44faa8fb78a6df9a6e3c6c0b',
// POOL Disabled as it uses WETH over ETH
// There is a conflict with Curve and SnowSwap
// where Curve uses ETH and SnowSwap uses WETH
// To re-enable this we need to flag an WETH
// unwrap or not
// eth: '0x16bea2e63adade5984298d53a4d4d9c09e278192',
};
export const SMOOTHY_POOLS = {
syUSD: '0xe5859f4efc09027a9b718781dcb2c6910cac6e91',
};
export const SADDLE_POOLS = {
stables: '0x3911f80530595fbd01ab1516ab61255d75aeb066',
bitcoins: '0x4f6a43ad7cba042606decaca730d4ce0a57ac62e',
stablesV2: '0xaCb83E0633d6605c5001e2Ab59EF3C745547C8C7',
bitcoinsV2: '0xdf3309771d2BF82cb2B6C56F9f5365C8bD97c4f2',
alETH: '0xa6018520eaacc06c30ff2e1b3ee2c7c22e64196a',
d4: '0xc69ddcd4dfef25d8a793241834d4cc4b3668ead6',
};
@@ -878,6 +860,7 @@ export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
AVALANCHE_TOKENS.nUSD,
AVALANCHE_TOKENS.nETH,
AVALANCHE_TOKENS.aWETH,
AVALANCHE_TOKENS.MIM,
],
[ChainId.Fantom]: [
FANTOM_TOKENS.WFTM,
@@ -919,6 +902,8 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID = valueByChainId<TokenAdj
builder.add(MAINNET_TOKENS.MIR, MAINNET_TOKENS.UST);
// Convex and Curve
builder.add(MAINNET_TOKENS.cvxCRV, MAINNET_TOKENS.CRV).add(MAINNET_TOKENS.CRV, MAINNET_TOKENS.cvxCRV);
// Convex and FXS
builder.add(MAINNET_TOKENS.cvxFXS, MAINNET_TOKENS.FXS).add(MAINNET_TOKENS.FXS, MAINNET_TOKENS.cvxFXS);
// FEI TRIBE liquid in UniV2
builder.add(MAINNET_TOKENS.FEI, MAINNET_TOKENS.TRIBE).add(MAINNET_TOKENS.TRIBE, MAINNET_TOKENS.FEI);
// FRAX ecosystem
@@ -936,15 +921,21 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID = valueByChainId<TokenAdj
}).build(),
[ChainId.Polygon]: new TokenAdjacencyGraphBuilder({
default: DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.Polygon],
}).build(),
})
.tap(builder => {
builder.add(POLYGON_TOKENS.QUICK, POLYGON_TOKENS.ANY).add(POLYGON_TOKENS.ANY, POLYGON_TOKENS.QUICK);
})
.build(),
[ChainId.Avalanche]: new TokenAdjacencyGraphBuilder({
default: DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.Avalanche],
})
.tap(builder => {
// Synape nETH/aWETH pool
// Synapse nETH/aWETH pool
builder
.add(AVALANCHE_TOKENS.aWETH, AVALANCHE_TOKENS.nETH)
.add(AVALANCHE_TOKENS.nETH, AVALANCHE_TOKENS.aWETH);
// Trader Joe MAG/MIM pool
builder.add(AVALANCHE_TOKENS.MIM, AVALANCHE_TOKENS.MAG).add(AVALANCHE_TOKENS.MAG, AVALANCHE_TOKENS.MIM);
})
.build(),
[ChainId.Fantom]: new TokenAdjacencyGraphBuilder({
@@ -1359,6 +1350,11 @@ export const CURVE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
pool: CURVE_POOLS.stgusdc,
gasSchedule: 250e3,
}),
[CURVE_POOLS.cvxfxs]: createCurveFactoryCryptoExchangePool({
tokens: [MAINNET_TOKENS.FXS, MAINNET_TOKENS.cvxFXS],
pool: CURVE_POOLS.cvxfxs,
gasSchedule: 390e3,
}),
};
export const CURVE_V2_MAINNET_INFOS: { [name: string]: CurveInfo } = {
@@ -1496,38 +1492,6 @@ export const CURVE_OPTIMISM_INFOS: { [name: string]: CurveInfo } = {
}),
};
export const SWERVE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[SWERVE_POOLS.y]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT, MAINNET_TOKENS.TUSD],
pool: SWERVE_POOLS.y,
gasSchedule: 140e3,
}),
};
export const SNOWSWAP_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[SNOWSWAP_POOLS.yUSD]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.yUSD, MAINNET_TOKENS.ybCRV],
pool: SNOWSWAP_POOLS.yUSD,
gasSchedule: 990e3,
}),
[SNOWSWAP_POOLS.yUSD]: createCurveExchangeUnderlyingPool({
tokens: [MAINNET_TOKENS.yCRV, MAINNET_TOKENS.bCRV],
pool: SNOWSWAP_POOLS.yUSD,
gasSchedule: 990e3,
}),
[SNOWSWAP_POOLS.yVault]: createCurveExchangePool({
tokens: [MAINNET_TOKENS.yDAI, MAINNET_TOKENS.yUSDC, MAINNET_TOKENS.yUSDT, MAINNET_TOKENS.yTUSD],
pool: SNOWSWAP_POOLS.yVault,
gasSchedule: 1490e3,
}),
// Unsupported due to collision with WETH and ETH with execution using MixinCurve
// [SNOWSWAP_POOLS.eth]: createCurveExchangePool({
// tokens: [MAINNET_TOKENS.WETH, MAINNET_TOKENS.vETH, MAINNET_TOKENS.ankrETH, MAINNET_TOKENS.crETH],
// pool: SNOWSWAP_POOLS.eth,
// gasSchedule: 990e3,
// }),
};
export const BELT_BSC_INFOS: { [name: string]: CurveInfo } = {
[BELT_POOLS.vPool]: createCurveExchangeUnderlyingPool({
tokens: [BSC_TOKENS.DAI, BSC_TOKENS.USDC, BSC_TOKENS.USDT, BSC_TOKENS.BUSD],
@@ -1554,21 +1518,21 @@ export const XSIGMA_MAINNET_INFOS: { [name: string]: CurveInfo } = {
// Curve-like sources using custom selectors
export const SADDLE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
[SADDLE_POOLS.stables]: {
[SADDLE_POOLS.stablesV2]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: SADDLE_POOLS.stables,
poolAddress: SADDLE_POOLS.stablesV2,
tokens: [MAINNET_TOKENS.DAI, MAINNET_TOKENS.USDC, MAINNET_TOKENS.USDT],
metaTokens: undefined,
gasSchedule: 150e3,
},
[SADDLE_POOLS.bitcoins]: {
[SADDLE_POOLS.bitcoinsV2]: {
exchangeFunctionSelector: CurveFunctionSelectors.swap,
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: SADDLE_POOLS.bitcoins,
tokens: [MAINNET_TOKENS.tBTC, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.sBTC],
poolAddress: SADDLE_POOLS.bitcoinsV2,
tokens: [MAINNET_TOKENS.WBTC, MAINNET_TOKENS.RenBTC, MAINNET_TOKENS.sBTC],
metaTokens: undefined,
gasSchedule: 150e3,
},
@@ -1916,11 +1880,6 @@ export const CRYPTO_COM_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
NULL_ADDRESS,
);
export const LINKSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{ [ChainId.Mainnet]: '0xa7ece0911fe8c60bff9e99f8fafcdbe56e07aff1' },
NULL_ADDRESS,
);
export const SHIBASWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.Mainnet]: '0x03f7724180aa6b939894b5ca4314783b0b36b329',
@@ -2412,12 +2371,9 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.LiquidityProvider]: fillData => {
return (fillData as LiquidityProviderFillData).gasCost || 100e3;
},
[ERC20BridgeSource.Eth2Dai]: () => 400e3,
[ERC20BridgeSource.Kyber]: () => 450e3,
[ERC20BridgeSource.Curve]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.CurveV2]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Swerve]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.SnowSwap]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Nerve]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Synapse]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.Belt]: fillData => (fillData as CurveFillData).pool.gasSchedule,
@@ -2432,7 +2388,6 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.UniswapV2]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.SushiSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.CryptoCom]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.Linkswap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.ShibaSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.Balancer]: () => 120e3,
[ERC20BridgeSource.BalancerV2]: (fillData?: FillData) => {

View File

@@ -4,12 +4,15 @@ import * as _ from 'lodash';
import { DEFAULT_INFO_LOGGER, INVALID_SIGNATURE } from '../../constants';
import {
AltRfqMakerAssetOfferings,
AssetSwapperContractAddresses,
MarketOperation,
NativeOrderWithFillableAmounts,
SignedNativeOrder,
} from '../../types';
import { QuoteRequestor } from '../quote_requestor';
import { getAltMarketInfo } from '../alt_mm_implementation_utils';
import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../quote_requestor';
import { toSignedNativeOrder } from '../rfq_client_mappers';
import {
getNativeAdjustedFillableAmountsFromMakerAmount,
getNativeAdjustedFillableAmountsFromTakerAmount,
@@ -663,17 +666,49 @@ export class MarketOperationUtils {
// Timing of RFQT lifecycle
const timeStart = new Date().getTime();
const { makerToken, takerToken } = nativeOrders[0].order;
// Filter Alt Rfq Maker Asset Offerings to the current pair
const filteredOfferings: AltRfqMakerAssetOfferings = {};
if (rfqt.altRfqAssetOfferings) {
const endpoints = Object.keys(rfqt.altRfqAssetOfferings);
for (const endpoint of endpoints) {
// Get the current pair if being offered
const offering = getAltMarketInfo(rfqt.altRfqAssetOfferings[endpoint], makerToken, takerToken);
if (offering) {
filteredOfferings[endpoint] = [offering];
}
}
}
if (rfqt.isIndicative) {
// An indicative quote is being 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 rfqt.quoteRequestor.requestRfqtIndicativeQuotesAsync(
makerToken,
takerToken,
amount,
side,
wholeOrderPrice,
rfqt,
);
const indicativeQuotes =
rfqt.rfqClient !== undefined
? ((
await rfqt.rfqClient.getV1PricesAsync({
altRfqAssetOfferings: filteredOfferings,
assetFillAmount: amount,
chainId: this._sampler.chainId,
comparisonPrice: wholeOrderPrice,
integratorId: rfqt.integrator.integratorId,
intentOnFilling: rfqt.intentOnFilling,
makerToken,
marketOperation: side,
takerAddress: rfqt.takerAddress,
takerToken,
txOrigin: rfqt.txOrigin,
})
).prices as V4RFQIndicativeQuoteMM[])
: await rfqt.quoteRequestor.requestRfqtIndicativeQuotesAsync(
makerToken,
takerToken,
amount,
side,
wholeOrderPrice,
rfqt,
);
const deltaTime = new Date().getTime() - timeStart;
DEFAULT_INFO_LOGGER({
rfqQuoteType: 'indicative',
@@ -687,14 +722,31 @@ export class MarketOperationUtils {
} else {
// A firm quote is being requested, and firm quotes price-aware enabled.
// Ensure that `intentOnFilling` is enabled and make the request.
const firmQuotes = await rfqt.quoteRequestor.requestRfqtFirmQuotesAsync(
makerToken,
takerToken,
amount,
side,
wholeOrderPrice,
rfqt,
);
const firmQuotes =
rfqt.rfqClient !== undefined
? (
await rfqt.rfqClient.getV1QuotesAsync({
altRfqAssetOfferings: filteredOfferings,
assetFillAmount: amount,
chainId: this._sampler.chainId,
comparisonPrice: wholeOrderPrice,
integratorId: rfqt.integrator.integratorId,
intentOnFilling: rfqt.intentOnFilling,
makerToken,
marketOperation: side,
takerAddress: rfqt.takerAddress,
takerToken,
txOrigin: rfqt.txOrigin,
})
).quotes.map(toSignedNativeOrder)
: await rfqt.quoteRequestor.requestRfqtFirmQuotesAsync(
makerToken,
takerToken,
amount,
side,
wholeOrderPrice,
rfqt,
);
const deltaTime = new Date().getTime() - timeStart;
DEFAULT_INFO_LOGGER({
rfqQuoteType: 'firm',
@@ -777,7 +829,7 @@ export class MarketOperationUtils {
private async _refreshPoolCacheIfRequiredAsync(takerToken: string, makerToken: string): Promise<void> {
void Promise.all(
Object.values(this._sampler.poolsCaches).map(async cache => {
if (cache.isFresh(takerToken, makerToken)) {
if (!cache || cache.isFresh(takerToken, makerToken)) {
return Promise.resolve([]);
}
return cache.getFreshPoolsForPairAsync(takerToken, makerToken);

View File

@@ -111,24 +111,16 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Mooniswap, 'Mooniswap');
case ERC20BridgeSource.MStable:
return encodeBridgeSourceId(BridgeProtocol.MStable, 'MStable');
case ERC20BridgeSource.Eth2Dai:
return encodeBridgeSourceId(BridgeProtocol.Oasis, 'Eth2Dai');
case ERC20BridgeSource.Shell:
return encodeBridgeSourceId(BridgeProtocol.Shell, 'Shell');
case ERC20BridgeSource.SnowSwap:
return encodeBridgeSourceId(BridgeProtocol.Curve, 'SnowSwap');
case ERC20BridgeSource.SushiSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SushiSwap');
case ERC20BridgeSource.Swerve:
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Swerve');
case ERC20BridgeSource.Uniswap:
return encodeBridgeSourceId(BridgeProtocol.Uniswap, 'Uniswap');
case ERC20BridgeSource.UniswapV2:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'UniswapV2');
case ERC20BridgeSource.DodoV2:
return encodeBridgeSourceId(BridgeProtocol.DodoV2, 'DodoV2');
case ERC20BridgeSource.Linkswap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Linkswap');
case ERC20BridgeSource.PancakeSwap:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwap');
case ERC20BridgeSource.PancakeSwapV2:
@@ -232,8 +224,6 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
switch (order.source) {
case ERC20BridgeSource.Curve:
case ERC20BridgeSource.CurveV2:
case ERC20BridgeSource.Swerve:
case ERC20BridgeSource.SnowSwap:
case ERC20BridgeSource.Nerve:
case ERC20BridgeSource.Synapse:
case ERC20BridgeSource.Belt:
@@ -280,7 +270,6 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.UniswapV2:
case ERC20BridgeSource.SushiSwap:
case ERC20BridgeSource.CryptoCom:
case ERC20BridgeSource.Linkswap:
case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.BakerySwap:
@@ -337,10 +326,6 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
const uniFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData;
bridgeData = encoder.encode([uniFillData.router]);
break;
case ERC20BridgeSource.Eth2Dai:
const oasisFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData;
bridgeData = encoder.encode([oasisFillData.router]);
break;
case ERC20BridgeSource.MStable:
const mStableFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData;
bridgeData = encoder.encode([mStableFillData.router]);
@@ -490,8 +475,6 @@ export const BRIDGE_ENCODERS: {
// Curve like
[ERC20BridgeSource.Curve]: curveEncoder,
[ERC20BridgeSource.CurveV2]: curveEncoder,
[ERC20BridgeSource.Swerve]: curveEncoder,
[ERC20BridgeSource.SnowSwap]: curveEncoder,
[ERC20BridgeSource.Nerve]: curveEncoder,
[ERC20BridgeSource.Synapse]: curveEncoder,
[ERC20BridgeSource.Belt]: curveEncoder,
@@ -508,7 +491,6 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.UniswapV2]: routerAddressPathEncoder,
[ERC20BridgeSource.SushiSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder,
[ERC20BridgeSource.Linkswap]: routerAddressPathEncoder,
[ERC20BridgeSource.ShibaSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.Pangolin]: routerAddressPathEncoder,
[ERC20BridgeSource.TraderJoe]: routerAddressPathEncoder,
@@ -536,7 +518,6 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Shell]: poolEncoder,
[ERC20BridgeSource.Component]: poolEncoder,
[ERC20BridgeSource.Mooniswap]: poolEncoder,
[ERC20BridgeSource.Eth2Dai]: poolEncoder,
[ERC20BridgeSource.MStable]: poolEncoder,
[ERC20BridgeSource.Balancer]: poolEncoder,
[ERC20BridgeSource.Cream]: poolEncoder,

View File

@@ -33,9 +33,7 @@ import {
KYBER_CONFIG_BY_CHAIN_ID,
KYBER_DMM_ROUTER_BY_CHAIN_ID,
LIDO_INFO_BY_CHAIN,
LINKSWAP_ROUTER_BY_CHAIN_ID,
LIQUIDITY_PROVIDER_REGISTRY_BY_CHAIN_ID,
MAINNET_TOKENS,
MAKER_PSM_INFO_BY_CHAIN_ID,
MAX_UINT256,
MOONISWAP_REGISTRIES_BY_CHAIN_ID,
@@ -107,7 +105,7 @@ export const TWO_HOP_SOURCE_FILTERS = SourceFilters.all().exclude([
export const BATCH_SOURCE_FILTERS = SourceFilters.all().exclude([ERC20BridgeSource.MultiHop, ERC20BridgeSource.Native]);
export type PoolsCacheMap = { [key in Exclude<SourcesWithPoolsCache, ERC20BridgeSource.BalancerV2>]: PoolsCache } & {
[ERC20BridgeSource.BalancerV2]: BalancerV2SwapInfoCache;
[ERC20BridgeSource.BalancerV2]: BalancerV2SwapInfoCache | undefined;
};
// tslint:disable:no-inferred-empty-object-type no-unbound-method
@@ -151,7 +149,10 @@ export class SamplerOperations {
),
[ERC20BridgeSource.Balancer]: new BalancerPoolsCache(),
[ERC20BridgeSource.Cream]: new CreamPoolsCache(),
[ERC20BridgeSource.BalancerV2]: new BalancerV2SwapInfoCache(chainId),
[ERC20BridgeSource.BalancerV2]:
BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[chainId] === NULL_ADDRESS
? undefined
: new BalancerV2SwapInfoCache(chainId),
};
const aaveSubgraphUrl = AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID[chainId];
@@ -571,7 +572,7 @@ export class SamplerOperations {
});
}
public getBalancerV2MulthopSellQuotes(
public getBalancerV2MultihopSellQuotes(
vault: string,
quoteSwaps: BalancerSwapInfo, // Should always be sell swap steps.
fillSwaps: BalancerSwapInfo, // Should always be sell swap steps.
@@ -592,7 +593,7 @@ export class SamplerOperations {
});
}
public getBalancerV2MulthopBuyQuotes(
public getBalancerV2MultihopBuyQuotes(
vault: string,
quoteSwaps: BalancerSwapInfo, // Should always be buy swap steps.
fillSwaps: BalancerSwapInfo, // Should always be a sell quote.
@@ -1349,7 +1350,7 @@ export class SamplerOperations {
takerFillAmounts: BigNumber[],
tokenAdjacencyGraph: TokenAdjacencyGraph = this.tokenAdjacencyGraph,
): SourceQuoteOperation[] {
// Find the adjacent tokens in the provided tooken adjacency graph,
// Find the adjacent tokens in the provided token adjacency graph,
// e.g if this is DAI->USDC we may check for DAI->WETH->USDC
const intermediateTokens = getIntermediateTokens(makerToken, takerToken, tokenAdjacencyGraph);
// Drop out MultiHop and Native as we do not query those here.
@@ -1362,8 +1363,6 @@ export class SamplerOperations {
return [];
}
switch (source) {
case ERC20BridgeSource.Eth2Dai:
return [];
case ERC20BridgeSource.Uniswap:
return isValidAddress(UNISWAPV1_ROUTER_BY_CHAIN_ID[this.chainId])
? this.getUniswapSellQuotes(
@@ -1422,8 +1421,6 @@ export class SamplerOperations {
);
case ERC20BridgeSource.Curve:
case ERC20BridgeSource.CurveV2:
case ERC20BridgeSource.Swerve:
case ERC20BridgeSource.SnowSwap:
case ERC20BridgeSource.Nerve:
case ERC20BridgeSource.Synapse:
case ERC20BridgeSource.Belt:
@@ -1499,15 +1496,19 @@ export class SamplerOperations {
),
);
case ERC20BridgeSource.BalancerV2: {
const swaps = this.poolsCaches[source].getCachedSwapInfoForPair(takerToken, makerToken);
const cache = this.poolsCaches[source];
if (!cache) {
return [];
}
const swaps = cache.getCachedSwapInfoForPair(takerToken, makerToken);
const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId];
if (!swaps || vault === NULL_ADDRESS) {
return [];
}
// Changed to retrieve queryBatchSwap for swap steps > 1 of length
return swaps.swapInfoExactIn.map(swapInfo =>
this.getBalancerV2MulthopSellQuotes(vault, swapInfo, swapInfo, takerFillAmounts, source),
this.getBalancerV2MultihopSellQuotes(vault, swapInfo, swapInfo, takerFillAmounts, source),
);
}
case ERC20BridgeSource.Beethovenx: {
@@ -1579,23 +1580,6 @@ export class SamplerOperations {
takerToken,
takerFillAmounts,
);
case ERC20BridgeSource.Linkswap:
if (!isValidAddress(LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId])) {
return [];
}
return [
[takerToken, makerToken],
...getIntermediateTokens(makerToken, takerToken, {
default: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.WETH],
}).map(t => [takerToken, t, makerToken]),
].map(path =>
this.getUniswapV2SellQuotes(
LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId],
path,
takerFillAmounts,
ERC20BridgeSource.Linkswap,
),
);
case ERC20BridgeSource.MakerPsm:
const psmInfo = MAKER_PSM_INFO_BY_CHAIN_ID[this.chainId];
if (!isValidAddress(psmInfo.psmAddress)) {
@@ -1685,8 +1669,6 @@ export class SamplerOperations {
return _.flatten(
_sources.map((source): SourceQuoteOperation | SourceQuoteOperation[] => {
switch (source) {
case ERC20BridgeSource.Eth2Dai:
return [];
case ERC20BridgeSource.Uniswap:
return isValidAddress(UNISWAPV1_ROUTER_BY_CHAIN_ID[this.chainId])
? this.getUniswapBuyQuotes(
@@ -1745,8 +1727,6 @@ export class SamplerOperations {
);
case ERC20BridgeSource.Curve:
case ERC20BridgeSource.CurveV2:
case ERC20BridgeSource.Swerve:
case ERC20BridgeSource.SnowSwap:
case ERC20BridgeSource.Nerve:
case ERC20BridgeSource.Synapse:
case ERC20BridgeSource.Belt:
@@ -1822,15 +1802,19 @@ export class SamplerOperations {
),
);
case ERC20BridgeSource.BalancerV2: {
const swaps = this.poolsCaches[source].getCachedSwapInfoForPair(takerToken, makerToken);
const cache = this.poolsCaches[source];
if (!cache) {
return [];
}
const swaps = cache.getCachedSwapInfoForPair(takerToken, makerToken);
const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId];
if (!swaps || vault === NULL_ADDRESS) {
return [];
}
// Changed to retrieve queryBatchSwap for swap steps > 1 of length
return swaps.swapInfoExactOut.map((quoteSwapInfo, i) =>
this.getBalancerV2MulthopBuyQuotes(
this.getBalancerV2MultihopBuyQuotes(
vault,
quoteSwapInfo,
swaps.swapInfoExactIn[i],
@@ -1902,24 +1886,6 @@ export class SamplerOperations {
// Unimplemented
// return this.getBancorBuyQuotes(makerToken, takerToken, makerFillAmounts);
return [];
case ERC20BridgeSource.Linkswap:
if (!isValidAddress(LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId])) {
return [];
}
return [
[takerToken, makerToken],
// LINK is the base asset in many of the pools on Linkswap
...getIntermediateTokens(makerToken, takerToken, {
default: [MAINNET_TOKENS.LINK, MAINNET_TOKENS.WETH],
}).map(t => [takerToken, t, makerToken]),
].map(path =>
this.getUniswapV2BuyQuotes(
LINKSWAP_ROUTER_BY_CHAIN_ID[this.chainId],
path,
makerFillAmounts,
ERC20BridgeSource.Linkswap,
),
);
case ERC20BridgeSource.MakerPsm:
const psmInfo = MAKER_PSM_INFO_BY_CHAIN_ID[this.chainId];
if (!isValidAddress(psmInfo.psmAddress)) {

View File

@@ -8,6 +8,7 @@ import { BigNumber } from '@0x/utils';
import { NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../../utils/quote_requestor';
import { IRfqClient } from '../irfq_client';
import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
import { SourceFilters } from './source_filters';
@@ -37,7 +38,6 @@ export enum ERC20BridgeSource {
Native = 'Native',
Uniswap = 'Uniswap',
UniswapV2 = 'Uniswap_V2',
Eth2Dai = 'Eth2Dai',
Kyber = 'Kyber',
Curve = 'Curve',
LiquidityProvider = 'LiquidityProvider',
@@ -51,13 +51,10 @@ export enum ERC20BridgeSource {
Mooniswap = 'Mooniswap',
MultiHop = 'MultiHop',
Shell = 'Shell',
Swerve = 'Swerve',
SnowSwap = 'SnowSwap',
SushiSwap = 'SushiSwap',
Dodo = 'DODO',
DodoV2 = 'DODO_V2',
CryptoCom = 'CryptoCom',
Linkswap = 'Linkswap',
KyberDmm = 'KyberDMM',
Smoothy = 'Smoothy',
Component = 'Component',
@@ -450,6 +447,7 @@ export type OptimizedMarketOrder =
| OptimizedMarketOrderBase<NativeRfqOrderFillData>;
export interface GetMarketOrdersRfqOpts extends RfqRequestOpts {
rfqClient?: IRfqClient;
quoteRequestor?: QuoteRequestor;
firmQuoteValidator?: RfqFirmQuoteValidator;
}

View File

@@ -207,7 +207,7 @@ export function generateExtendedQuoteReportSources(
..._.flatten(
quotes.dexQuotes.map(dex =>
dex
.filter(quote => isDexSampleForTotalAmount(quote, marketOperation, amount))
.filter(quote => isDexSampleForTotalAmount(quote, amount))
.map(quote => dexSampleToReportSource(quote, marketOperation)),
),
),
@@ -306,16 +306,8 @@ export function dexSampleToReportSource(ds: DexSample, marketOperation: MarketOp
* Checks if a DEX sample is the one that represents the whole amount requested by taker
* NOTE: this is used for the QuoteReport to filter samples
*/
function isDexSampleForTotalAmount(ds: DexSample, marketOperation: MarketOperation, amount: BigNumber): boolean {
// input and output map to different values
// based on the market operation
if (marketOperation === MarketOperation.Buy) {
return ds.input === amount;
} else if (marketOperation === MarketOperation.Sell) {
return ds.output === amount;
} else {
throw new Error(`Unexpected marketOperation ${marketOperation}`);
}
function isDexSampleForTotalAmount(ds: DexSample, amount: BigNumber): boolean {
return ds.input.eq(amount);
}
/**

View File

@@ -0,0 +1,16 @@
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
import { SignedNativeOrder } from '../types';
import { RfqClientV1Quote } from './irfq_client';
/**
* Converts a RfqClientRfqOrderFirmQuote to a SignedNativeOrder
*/
export const toSignedNativeOrder = (quote: RfqClientV1Quote): SignedNativeOrder => {
return {
type: FillQuoteTransformerOrderType.Rfq,
order: quote.order,
signature: quote.signature,
};
};

View File

@@ -49,7 +49,7 @@ const MAKER_TOKEN = randomAddress();
const TAKER_TOKEN = randomAddress();
const DEFAULT_INCLUDED = [
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Kyber,
ERC20BridgeSource.Native,
ERC20BridgeSource.Uniswap,
@@ -319,7 +319,7 @@ describe('MarketOperationUtils tests', () => {
const DEFAULT_RATES: RatesBySource = {
...ZERO_RATES,
[ERC20BridgeSource.Native]: createDecreasingRates(NUM_SAMPLES),
[ERC20BridgeSource.Eth2Dai]: createDecreasingRates(NUM_SAMPLES),
[ERC20BridgeSource.SushiSwap]: createDecreasingRates(NUM_SAMPLES),
[ERC20BridgeSource.Uniswap]: createDecreasingRates(NUM_SAMPLES),
[ERC20BridgeSource.Kyber]: createDecreasingRates(NUM_SAMPLES),
};
@@ -349,28 +349,6 @@ describe('MarketOperationUtils tests', () => {
fromTokenIdx: 0,
toTokenIdx: 1,
},
[ERC20BridgeSource.Swerve]: {
pool: {
poolAddress: randomAddress(),
tokens: [TAKER_TOKEN, MAKER_TOKEN],
exchangeFunctionSelector: hexUtils.random(4),
sellQuoteFunctionSelector: hexUtils.random(4),
buyQuoteFunctionSelector: hexUtils.random(4),
},
fromTokenIdx: 0,
toTokenIdx: 1,
},
[ERC20BridgeSource.SnowSwap]: {
pool: {
poolAddress: randomAddress(),
tokens: [TAKER_TOKEN, MAKER_TOKEN],
exchangeFunctionSelector: hexUtils.random(4),
sellQuoteFunctionSelector: hexUtils.random(4),
buyQuoteFunctionSelector: hexUtils.random(4),
},
fromTokenIdx: 0,
toTokenIdx: 1,
},
[ERC20BridgeSource.Smoothy]: {
pool: {
poolAddress: randomAddress(),
@@ -404,9 +382,7 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Dodo]: {},
[ERC20BridgeSource.DodoV2]: {},
[ERC20BridgeSource.CryptoCom]: { tokenAddressPath: [] },
[ERC20BridgeSource.Linkswap]: { tokenAddressPath: [] },
[ERC20BridgeSource.Uniswap]: { router: randomAddress() },
[ERC20BridgeSource.Eth2Dai]: { router: randomAddress() },
[ERC20BridgeSource.MakerPsm]: {},
[ERC20BridgeSource.KyberDmm]: { tokenAddressPath: [], router: randomAddress(), poolsPath: [] },
};
@@ -534,7 +510,7 @@ describe('MarketOperationUtils tests', () => {
});
it('does not poll DEXes in `excludedSources`', async () => {
const excludedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Dai];
const excludedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.SushiSwap];
let sourcesPolled: ERC20BridgeSource[] = [];
replaceSamplerOps({
getSellQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => {
@@ -564,7 +540,7 @@ describe('MarketOperationUtils tests', () => {
});
it('only polls DEXes in `includedSources`', async () => {
const includedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Dai];
const includedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.SushiSwap];
let sourcesPolled: ERC20BridgeSource[] = [];
replaceSamplerOps({
getSellQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => {
@@ -1057,7 +1033,7 @@ describe('MarketOperationUtils tests', () => {
const rates: RatesBySource = { ...DEFAULT_RATES };
rates[ERC20BridgeSource.Native] = [0.4, 0.3, 0.2, 0.1];
rates[ERC20BridgeSource.Uniswap] = [0.5, 0.05, 0.05, 0.05];
rates[ERC20BridgeSource.Eth2Dai] = [0.6, 0.05, 0.05, 0.05];
rates[ERC20BridgeSource.SushiSwap] = [0.6, 0.05, 0.05, 0.05];
rates[ERC20BridgeSource.Kyber] = [0, 0, 0, 0]; // unused
replaceSamplerOps({
getSellQuotes: createGetMultipleSellQuotesOperationFromRates(rates),
@@ -1071,7 +1047,7 @@ describe('MarketOperationUtils tests', () => {
const improvedOrders = improvedOrdersResponse.optimizedOrders;
const orderSources = improvedOrders.map(o => o.fills[0].source);
const expectedSources = [
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.Native,
ERC20BridgeSource.Native,
@@ -1089,7 +1065,7 @@ describe('MarketOperationUtils tests', () => {
const rates: RatesBySource = {
[ERC20BridgeSource.Native]: [1, 0.99, 0.98, 0.97], // Effectively [0.94, 0.93, 0.92, 0.91]
[ERC20BridgeSource.Uniswap]: [0.96, 0.1, 0.1, 0.1],
[ERC20BridgeSource.Eth2Dai]: [0.95, 0.1, 0.1, 0.1],
[ERC20BridgeSource.SushiSwap]: [0.95, 0.1, 0.1, 0.1],
[ERC20BridgeSource.Kyber]: [0.1, 0.1, 0.1, 0.1],
};
const feeSchedule = {
@@ -1114,7 +1090,7 @@ describe('MarketOperationUtils tests', () => {
const expectedSources = [
ERC20BridgeSource.Native,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Native,
];
expect(orderSources.sort()).to.deep.eq(expectedSources.sort());
@@ -1127,7 +1103,7 @@ describe('MarketOperationUtils tests', () => {
const rates: RatesBySource = {
[ERC20BridgeSource.Native]: [0.95, 0.1, 0.1, 0.1],
[ERC20BridgeSource.Kyber]: [0.1, 0.1, 0.1, 0.1],
[ERC20BridgeSource.Eth2Dai]: [0.92, 0.1, 0.1, 0.1],
[ERC20BridgeSource.SushiSwap]: [0.92, 0.1, 0.1, 0.1],
// Effectively [0.8, ~0.5, ~0, ~0]
[ERC20BridgeSource.Uniswap]: [1, 0.7, 0.2, 0.2],
};
@@ -1152,7 +1128,7 @@ describe('MarketOperationUtils tests', () => {
const orderSources = improvedOrders.map(o => o.fills[0].source);
const expectedSources = [
ERC20BridgeSource.Native,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Uniswap,
];
expect(orderSources.sort()).to.deep.eq(expectedSources.sort());
@@ -1161,7 +1137,7 @@ describe('MarketOperationUtils tests', () => {
it('can mix one concave source', async () => {
const rates: RatesBySource = {
[ERC20BridgeSource.Kyber]: [0, 0, 0, 0], // Won't use
[ERC20BridgeSource.Eth2Dai]: [0.5, 0.85, 0.75, 0.75], // Concave
[ERC20BridgeSource.SushiSwap]: [0.5, 0.85, 0.75, 0.75], // Concave
[ERC20BridgeSource.Uniswap]: [0.96, 0.2, 0.1, 0.1],
[ERC20BridgeSource.Native]: [0.95, 0.2, 0.2, 0.1],
};
@@ -1178,7 +1154,7 @@ describe('MarketOperationUtils tests', () => {
const improvedOrders = improvedOrdersResponse.optimizedOrders;
const orderSources = improvedOrders.map(o => o.fills[0].source);
const expectedSources = [
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.Native,
];
@@ -1191,7 +1167,7 @@ describe('MarketOperationUtils tests', () => {
const rates: RatesBySource = {};
rates[ERC20BridgeSource.Native] = [1, 1, 0.01, 0.01];
rates[ERC20BridgeSource.Uniswap] = [1, 1, 0.01, 0.01];
rates[ERC20BridgeSource.Eth2Dai] = [0.49, 0.49, 0.49, 0.49];
rates[ERC20BridgeSource.SushiSwap] = [0.49, 0.49, 0.49, 0.49];
rates[ERC20BridgeSource.Kyber] = [0.35, 0.2, 0.01, 0.01];
replaceSamplerOps({
getSellQuotes: createGetMultipleSellQuotesOperationFromRates(rates),
@@ -1386,7 +1362,7 @@ describe('MarketOperationUtils tests', () => {
});
it('does not poll DEXes in `excludedSources`', async () => {
const excludedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Dai];
const excludedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.SushiSwap];
let sourcesPolled: ERC20BridgeSource[] = [];
replaceSamplerOps({
getBuyQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => {
@@ -1416,7 +1392,7 @@ describe('MarketOperationUtils tests', () => {
});
it('only polls DEXes in `includedSources`', async () => {
const includedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Dai];
const includedSources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.SushiSwap];
let sourcesPolled: ERC20BridgeSource[] = [];
replaceSamplerOps({
getBuyQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => {
@@ -1508,7 +1484,7 @@ describe('MarketOperationUtils tests', () => {
const rates: RatesBySource = { ...ZERO_RATES };
rates[ERC20BridgeSource.Native] = [0.4, 0.3, 0.2, 0.1];
rates[ERC20BridgeSource.Uniswap] = [0.5, 0.05, 0.05, 0.05];
rates[ERC20BridgeSource.Eth2Dai] = [0.6, 0.05, 0.05, 0.05];
rates[ERC20BridgeSource.SushiSwap] = [0.6, 0.05, 0.05, 0.05];
replaceSamplerOps({
getBuyQuotes: createGetMultipleBuyQuotesOperationFromRates(rates),
});
@@ -1521,7 +1497,7 @@ describe('MarketOperationUtils tests', () => {
const improvedOrders = improvedOrdersResponse.optimizedOrders;
const orderSources = improvedOrders.map(o => o.fills[0].source);
const expectedSources = [
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.Native,
ERC20BridgeSource.Native,
@@ -1540,7 +1516,7 @@ describe('MarketOperationUtils tests', () => {
...ZERO_RATES,
[ERC20BridgeSource.Native]: [1, 0.99, 0.98, 0.97], // Effectively [0.94, ~0.93, ~0.92, ~0.91]
[ERC20BridgeSource.Uniswap]: [0.96, 0.1, 0.1, 0.1],
[ERC20BridgeSource.Eth2Dai]: [0.95, 0.1, 0.1, 0.1],
[ERC20BridgeSource.SushiSwap]: [0.95, 0.1, 0.1, 0.1],
[ERC20BridgeSource.Kyber]: [0.1, 0.1, 0.1, 0.1],
};
const feeSchedule = {
@@ -1564,7 +1540,7 @@ describe('MarketOperationUtils tests', () => {
const orderSources = improvedOrders.map(o => o.fills[0].source);
const expectedSources = [
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Native,
ERC20BridgeSource.Native,
];
@@ -1580,7 +1556,7 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Native]: [0.95, 0.1, 0.1, 0.1],
// Effectively [0.8, ~0.5, ~0, ~0]
[ERC20BridgeSource.Uniswap]: [1, 0.7, 0.2, 0.2],
[ERC20BridgeSource.Eth2Dai]: [0.92, 0.1, 0.1, 0.1],
[ERC20BridgeSource.SushiSwap]: [0.92, 0.1, 0.1, 0.1],
};
const feeSchedule = {
[ERC20BridgeSource.Uniswap]: _.constant(
@@ -1603,7 +1579,7 @@ describe('MarketOperationUtils tests', () => {
const orderSources = improvedOrders.map(o => o.fills[0].source);
const expectedSources = [
ERC20BridgeSource.Native,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Uniswap,
];
expect(orderSources.sort()).to.deep.eq(expectedSources.sort());
@@ -1615,7 +1591,7 @@ describe('MarketOperationUtils tests', () => {
const rates: RatesBySource = { ...ZERO_RATES };
rates[ERC20BridgeSource.Native] = [1, 1, 0.01, 0.01];
rates[ERC20BridgeSource.Uniswap] = [1, 1, 0.01, 0.01];
rates[ERC20BridgeSource.Eth2Dai] = [0.49, 0.49, 0.49, 0.49];
rates[ERC20BridgeSource.SushiSwap] = [0.49, 0.49, 0.49, 0.49];
replaceSamplerOps({
getBuyQuotes: createGetMultipleBuyQuotesOperationFromRates(rates),
});

View File

@@ -980,6 +980,23 @@
ethers "~4.0.4"
lodash "^4.17.11"
"@0x/protocol-utils@^1.0.1":
version "1.11.2"
resolved "https://registry.yarnpkg.com/@0x/protocol-utils/-/protocol-utils-1.11.2.tgz#c27ccf3410b99d8c364550bc18dc8b04dc2e967e"
integrity sha512-DmYCWb3fB1NSBbR7JV2Tr4oXr/3rDzVpECWUvntCyIwdohHSM7ytjYbL9ilvlH3vuDK85CSyFWNrbSP6xZfTpA==
dependencies:
"@0x/assert" "^3.0.34"
"@0x/contract-addresses" "^6.12.1"
"@0x/contract-wrappers" "^13.20.0"
"@0x/json-schemas" "^6.4.4"
"@0x/subproviders" "^6.6.5"
"@0x/utils" "^6.5.3"
"@0x/web3-wrapper" "^7.6.5"
chai "^4.0.1"
ethereumjs-util "^7.0.10"
ethers "~4.0.4"
lodash "^4.17.11"
"@0x/quote-server@^6.0.6":
version "6.0.6"
resolved "https://registry.yarnpkg.com/@0x/quote-server/-/quote-server-6.0.6.tgz#0f0bf50647efc4bff039a491689974af7e8c5776"