Integrated CREAM into asset-swapper
This commit is contained in:
parent
c6b9ea5723
commit
c72aa653e8
@ -65,6 +65,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Added `Shell` into FQT",
|
"note": "Added `Shell` into FQT",
|
||||||
"pr": 2722
|
"pr": 2722
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `CREAM` into FQT",
|
||||||
|
"pr": 2715
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -46,6 +46,7 @@ contract BridgeAdapter is
|
|||||||
{
|
{
|
||||||
|
|
||||||
address private immutable BALANCER_BRIDGE_ADDRESS;
|
address private immutable BALANCER_BRIDGE_ADDRESS;
|
||||||
|
address private immutable CREAM_BRIDGE_ADDRESS;
|
||||||
address private immutable CURVE_BRIDGE_ADDRESS;
|
address private immutable CURVE_BRIDGE_ADDRESS;
|
||||||
address private immutable KYBER_BRIDGE_ADDRESS;
|
address private immutable KYBER_BRIDGE_ADDRESS;
|
||||||
address private immutable MOONISWAP_BRIDGE_ADDRESS;
|
address private immutable MOONISWAP_BRIDGE_ADDRESS;
|
||||||
@ -93,6 +94,7 @@ contract BridgeAdapter is
|
|||||||
SHELL_BRIDGE_ADDRESS = addresses.shellBridge;
|
SHELL_BRIDGE_ADDRESS = addresses.shellBridge;
|
||||||
UNISWAP_BRIDGE_ADDRESS = addresses.uniswapBridge;
|
UNISWAP_BRIDGE_ADDRESS = addresses.uniswapBridge;
|
||||||
UNISWAP_V2_BRIDGE_ADDRESS = addresses.uniswapV2Bridge;
|
UNISWAP_V2_BRIDGE_ADDRESS = addresses.uniswapV2Bridge;
|
||||||
|
CREAM_BRIDGE_ADDRESS = addresses.creamBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
function trade(
|
function trade(
|
||||||
@ -170,6 +172,12 @@ contract BridgeAdapter is
|
|||||||
sellAmount,
|
sellAmount,
|
||||||
bridgeData
|
bridgeData
|
||||||
);
|
);
|
||||||
|
} else if (bridgeAddress == CREAM_BRIDGE_ADDRESS) {
|
||||||
|
boughtAmount = _tradeBalancer(
|
||||||
|
buyToken,
|
||||||
|
sellAmount,
|
||||||
|
bridgeData
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
boughtAmount = _tradeZeroExBridge(
|
boughtAmount = _tradeZeroExBridge(
|
||||||
bridgeAddress,
|
bridgeAddress,
|
||||||
|
@ -24,6 +24,7 @@ contract MixinAdapterAddresses
|
|||||||
struct AdapterAddresses {
|
struct AdapterAddresses {
|
||||||
// Bridges
|
// Bridges
|
||||||
address balancerBridge;
|
address balancerBridge;
|
||||||
|
address creamBridge;
|
||||||
address curveBridge;
|
address curveBridge;
|
||||||
address kyberBridge;
|
address kyberBridge;
|
||||||
address mooniswapBridge;
|
address mooniswapBridge;
|
||||||
|
@ -75,6 +75,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
|
|||||||
weth: NULL_ADDRESS,
|
weth: NULL_ADDRESS,
|
||||||
shellBridge: NULL_ADDRESS,
|
shellBridge: NULL_ADDRESS,
|
||||||
shell: NULL_ADDRESS,
|
shell: NULL_ADDRESS,
|
||||||
|
creamBridge: NULL_ADDRESS,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
transformer = await FillQuoteTransformerContract.deployFrom0xArtifactAsync(
|
transformer = await FillQuoteTransformerContract.deployFrom0xArtifactAsync(
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
"@bancor/sdk": "^0.2.9",
|
"@bancor/sdk": "^0.2.9",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"axios-mock-adapter": "^1.18.1",
|
"axios-mock-adapter": "^1.18.1",
|
||||||
|
"cream-sor": "^0.3.3",
|
||||||
"decimal.js": "^10.2.0",
|
"decimal.js": "^10.2.0",
|
||||||
"ethereum-types": "^3.2.0",
|
"ethereum-types": "^3.2.0",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
import { getPoolsWithTokens, parsePoolData } from 'cream-sor';
|
||||||
|
|
||||||
|
import { BalancerPool } from './balancer_utils';
|
||||||
|
|
||||||
|
// tslint:disable:boolean-naming
|
||||||
|
|
||||||
|
interface CacheValue {
|
||||||
|
timestamp: number;
|
||||||
|
pools: BalancerPool[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable:custom-no-magic-numbers
|
||||||
|
const FIVE_SECONDS_MS = 5 * 1000;
|
||||||
|
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
||||||
|
const DEFAULT_TIMEOUT_MS = 1000;
|
||||||
|
const MAX_POOLS_FETCHED = 3;
|
||||||
|
// tslint:enable:custom-no-magic-numbers
|
||||||
|
|
||||||
|
export class CreamPoolsCache {
|
||||||
|
constructor(
|
||||||
|
private readonly _cache: { [key: string]: CacheValue } = {},
|
||||||
|
private readonly maxPoolsFetched: number = MAX_POOLS_FETCHED,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async getPoolsForPairAsync(
|
||||||
|
takerToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
timeoutMs: number = DEFAULT_TIMEOUT_MS,
|
||||||
|
): Promise<BalancerPool[]> {
|
||||||
|
const timeout = new Promise<BalancerPool[]>(resolve => setTimeout(resolve, timeoutMs, []));
|
||||||
|
return Promise.race([this._getPoolsForPairAsync(takerToken, makerToken), timeout]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCachedPoolAddressesForPair(
|
||||||
|
takerToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
cacheExpiryMs?: number,
|
||||||
|
): string[] | undefined {
|
||||||
|
const key = JSON.stringify([takerToken, makerToken]);
|
||||||
|
const value = this._cache[key];
|
||||||
|
if (cacheExpiryMs === undefined) {
|
||||||
|
return value === undefined ? [] : value.pools.map(pool => pool.id);
|
||||||
|
}
|
||||||
|
const minTimestamp = Date.now() - cacheExpiryMs;
|
||||||
|
if (value === undefined || value.timestamp < minTimestamp) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return value.pools.map(pool => pool.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public howToSampleCream(
|
||||||
|
takerToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
isAllowedSource: boolean,
|
||||||
|
): { onChain: boolean; offChain: boolean } {
|
||||||
|
// If Balancer is excluded as a source, do not sample.
|
||||||
|
if (!isAllowedSource) {
|
||||||
|
return { onChain: false, offChain: false };
|
||||||
|
}
|
||||||
|
const cachedCreamPools = this.getCachedPoolAddressesForPair(takerToken, makerToken, ONE_DAY_MS);
|
||||||
|
// Sample CREAM on-chain (i.e. via the ERC20BridgeSampler contract) if:
|
||||||
|
// - Cached values are not stale
|
||||||
|
// - There is at least one CREAM pool for this pair
|
||||||
|
const onChain = cachedCreamPools !== undefined && cachedCreamPools.length > 0;
|
||||||
|
// Sample Balancer off-chain (i.e. via GraphQL query + `computeCreamBuy/SellQuote`)
|
||||||
|
// if cached values are stale
|
||||||
|
const offChain = cachedCreamPools === undefined;
|
||||||
|
return { onChain, offChain };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async _getPoolsForPairAsync(
|
||||||
|
takerToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
cacheExpiryMs: number = FIVE_SECONDS_MS,
|
||||||
|
): Promise<BalancerPool[]> {
|
||||||
|
const key = JSON.stringify([takerToken, makerToken]);
|
||||||
|
const value = this._cache[key];
|
||||||
|
const minTimestamp = Date.now() - cacheExpiryMs;
|
||||||
|
if (value === undefined || value.timestamp < minTimestamp) {
|
||||||
|
const pools = await this._fetchPoolsForPairAsync(takerToken, makerToken);
|
||||||
|
const timestamp = Date.now();
|
||||||
|
this._cache[key] = {
|
||||||
|
pools,
|
||||||
|
timestamp,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this._cache[key].pools;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
|
protected async _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise<BalancerPool[]> {
|
||||||
|
try {
|
||||||
|
const poolData = (await getPoolsWithTokens(takerToken, makerToken)).pools;
|
||||||
|
// Sort by maker token balance (descending)
|
||||||
|
const pools = parsePoolData(poolData, takerToken, makerToken).sort((a, b) =>
|
||||||
|
b.balanceOut.minus(a.balanceOut).toNumber(),
|
||||||
|
);
|
||||||
|
return pools.length > this.maxPoolsFetched ? pools.slice(0, this.maxPoolsFetched) : pools;
|
||||||
|
} catch (err) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -150,6 +150,23 @@ export class MarketOperationUtils {
|
|||||||
quoteSourceFilters.isAllowed(ERC20BridgeSource.Balancer),
|
quoteSourceFilters.isAllowed(ERC20BridgeSource.Balancer),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
onChain: sampleCreamOnChain,
|
||||||
|
offChain: sampleCreamOffChain,
|
||||||
|
} = this._sampler.creamPoolsCache.howToSampleCream(
|
||||||
|
takerToken,
|
||||||
|
makerToken,
|
||||||
|
quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream),
|
||||||
|
);
|
||||||
|
|
||||||
|
let excludedSources: ERC20BridgeSource[] = [];
|
||||||
|
if (!sampleCreamOnChain) {
|
||||||
|
excludedSources = excludedSources.concat(ERC20BridgeSource.Cream);
|
||||||
|
}
|
||||||
|
if (!sampleBalancerOnChain) {
|
||||||
|
excludedSources = excludedSources.concat(ERC20BridgeSource.Balancer);
|
||||||
|
}
|
||||||
|
|
||||||
// Call the sampler contract.
|
// Call the sampler contract.
|
||||||
const samplerPromise = this._sampler.executeAsync(
|
const samplerPromise = this._sampler.executeAsync(
|
||||||
// Get native order fillable amounts.
|
// Get native order fillable amounts.
|
||||||
@ -176,7 +193,7 @@ export class MarketOperationUtils {
|
|||||||
),
|
),
|
||||||
// Get sell quotes for taker -> maker.
|
// Get sell quotes for taker -> maker.
|
||||||
this._sampler.getSellQuotes(
|
this._sampler.getSellQuotes(
|
||||||
quoteSourceFilters.exclude(sampleBalancerOnChain ? [] : ERC20BridgeSource.Balancer).sources,
|
quoteSourceFilters.exclude(excludedSources).sources,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
sampleAmounts,
|
sampleAmounts,
|
||||||
@ -209,6 +226,10 @@ export class MarketOperationUtils {
|
|||||||
? this._sampler.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
? this._sampler.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
||||||
: Promise.resolve([]);
|
: Promise.resolve([]);
|
||||||
|
|
||||||
|
const offChainCreamPromise = sampleCreamOffChain
|
||||||
|
? this._sampler.getCreamSellQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
||||||
|
: Promise.resolve([]);
|
||||||
|
|
||||||
const offChainBancorPromise = quoteSourceFilters.isAllowed(ERC20BridgeSource.Bancor)
|
const offChainBancorPromise = quoteSourceFilters.isAllowed(ERC20BridgeSource.Bancor)
|
||||||
? this._sampler.getBancorSellQuotesOffChainAsync(makerToken, takerToken, [takerAmount])
|
? this._sampler.getBancorSellQuotesOffChainAsync(makerToken, takerToken, [takerAmount])
|
||||||
: Promise.resolve([]);
|
: Promise.resolve([]);
|
||||||
@ -217,15 +238,16 @@ export class MarketOperationUtils {
|
|||||||
[orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes],
|
[orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes],
|
||||||
rfqtIndicativeQuotes,
|
rfqtIndicativeQuotes,
|
||||||
offChainBalancerQuotes,
|
offChainBalancerQuotes,
|
||||||
|
offChainCreamQuotes,
|
||||||
offChainBancorQuotes,
|
offChainBancorQuotes,
|
||||||
] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainBancorPromise]);
|
] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainCreamPromise, offChainBancorPromise]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
side: MarketOperation.Sell,
|
side: MarketOperation.Sell,
|
||||||
inputAmount: takerAmount,
|
inputAmount: takerAmount,
|
||||||
inputToken: takerToken,
|
inputToken: takerToken,
|
||||||
outputToken: makerToken,
|
outputToken: makerToken,
|
||||||
dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, offChainBancorQuotes]),
|
dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, ...offChainCreamQuotes, offChainBancorQuotes]),
|
||||||
nativeOrders,
|
nativeOrders,
|
||||||
orderFillableAmounts,
|
orderFillableAmounts,
|
||||||
ethToOutputRate: ethToMakerAssetRate,
|
ethToOutputRate: ethToMakerAssetRate,
|
||||||
@ -266,6 +288,23 @@ export class MarketOperationUtils {
|
|||||||
quoteSourceFilters.isAllowed(ERC20BridgeSource.Balancer),
|
quoteSourceFilters.isAllowed(ERC20BridgeSource.Balancer),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
onChain: sampleCreamOnChain,
|
||||||
|
offChain: sampleCreamOffChain,
|
||||||
|
} = this._sampler.creamPoolsCache.howToSampleCream(
|
||||||
|
takerToken,
|
||||||
|
makerToken,
|
||||||
|
quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream),
|
||||||
|
);
|
||||||
|
|
||||||
|
let excludedSources: ERC20BridgeSource[] = [];
|
||||||
|
if (!sampleCreamOnChain) {
|
||||||
|
excludedSources = excludedSources.concat(ERC20BridgeSource.Cream);
|
||||||
|
}
|
||||||
|
if (!sampleBalancerOnChain) {
|
||||||
|
excludedSources = excludedSources.concat(ERC20BridgeSource.Balancer);
|
||||||
|
}
|
||||||
|
|
||||||
// Call the sampler contract.
|
// Call the sampler contract.
|
||||||
const samplerPromise = this._sampler.executeAsync(
|
const samplerPromise = this._sampler.executeAsync(
|
||||||
// Get native order fillable amounts.
|
// Get native order fillable amounts.
|
||||||
@ -292,7 +331,7 @@ export class MarketOperationUtils {
|
|||||||
),
|
),
|
||||||
// Get buy quotes for taker -> maker.
|
// Get buy quotes for taker -> maker.
|
||||||
this._sampler.getBuyQuotes(
|
this._sampler.getBuyQuotes(
|
||||||
quoteSourceFilters.exclude(sampleBalancerOnChain ? [] : ERC20BridgeSource.Balancer).sources,
|
quoteSourceFilters.exclude(excludedSources).sources,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
sampleAmounts,
|
sampleAmounts,
|
||||||
@ -324,11 +363,16 @@ export class MarketOperationUtils {
|
|||||||
? this._sampler.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
? this._sampler.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
||||||
: Promise.resolve([]);
|
: Promise.resolve([]);
|
||||||
|
|
||||||
|
const offChainCreamPromise = sampleCreamOffChain
|
||||||
|
? this._sampler.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
||||||
|
: Promise.resolve([]);
|
||||||
|
|
||||||
const [
|
const [
|
||||||
[orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes],
|
[orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes],
|
||||||
rfqtIndicativeQuotes,
|
rfqtIndicativeQuotes,
|
||||||
offChainBalancerQuotes,
|
offChainBalancerQuotes,
|
||||||
] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise]);
|
offChainCreamQuotes,
|
||||||
|
] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainCreamPromise]);
|
||||||
// Attach the MultiBridge address to the sample fillData
|
// Attach the MultiBridge address to the sample fillData
|
||||||
(dexQuotes.find(quotes => quotes[0] && quotes[0].source === ERC20BridgeSource.MultiBridge) || []).forEach(
|
(dexQuotes.find(quotes => quotes[0] && quotes[0].source === ERC20BridgeSource.MultiBridge) || []).forEach(
|
||||||
q => (q.fillData = { poolAddress: this._multiBridge }),
|
q => (q.fillData = { poolAddress: this._multiBridge }),
|
||||||
@ -338,7 +382,7 @@ export class MarketOperationUtils {
|
|||||||
inputAmount: makerAmount,
|
inputAmount: makerAmount,
|
||||||
inputToken: makerToken,
|
inputToken: makerToken,
|
||||||
outputToken: takerToken,
|
outputToken: takerToken,
|
||||||
dexQuotes: dexQuotes.concat(offChainBalancerQuotes),
|
dexQuotes: dexQuotes.concat(offChainBalancerQuotes, offChainCreamQuotes),
|
||||||
nativeOrders,
|
nativeOrders,
|
||||||
orderFillableAmounts,
|
orderFillableAmounts,
|
||||||
ethToOutputRate: ethToTakerAssetRate,
|
ethToOutputRate: ethToTakerAssetRate,
|
||||||
|
@ -6,6 +6,7 @@ import { ERC20BridgeSamplerContract } from '../../wrappers';
|
|||||||
|
|
||||||
import { BalancerPoolsCache } from './balancer_utils';
|
import { BalancerPoolsCache } from './balancer_utils';
|
||||||
import { BancorService } from './bancor_service';
|
import { BancorService } from './bancor_service';
|
||||||
|
import { CreamPoolsCache } from './cream_utils';
|
||||||
import { SamplerOperations } from './sampler_operations';
|
import { SamplerOperations } from './sampler_operations';
|
||||||
import { BatchedOperation } from './types';
|
import { BatchedOperation } from './types';
|
||||||
|
|
||||||
@ -37,9 +38,10 @@ export class DexOrderSampler extends SamplerOperations {
|
|||||||
private readonly _samplerOverrides?: SamplerOverrides,
|
private readonly _samplerOverrides?: SamplerOverrides,
|
||||||
provider?: SupportedProvider,
|
provider?: SupportedProvider,
|
||||||
balancerPoolsCache?: BalancerPoolsCache,
|
balancerPoolsCache?: BalancerPoolsCache,
|
||||||
|
creamPoolsCache?: CreamPoolsCache,
|
||||||
getBancorServiceFn?: () => BancorService,
|
getBancorServiceFn?: () => BancorService,
|
||||||
) {
|
) {
|
||||||
super(_samplerContract, provider, balancerPoolsCache, getBancorServiceFn);
|
super(_samplerContract, provider, balancerPoolsCache, creamPoolsCache, getBancorServiceFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Type overloads for `executeAsync()`. Could skip this if we would upgrade TS. */
|
/* Type overloads for `executeAsync()`. Could skip this if we would upgrade TS. */
|
||||||
|
@ -8,6 +8,7 @@ import { ERC20BridgeSamplerContract } from '../../wrappers';
|
|||||||
import { BalancerPoolsCache, computeBalancerBuyQuote, computeBalancerSellQuote } from './balancer_utils';
|
import { BalancerPoolsCache, computeBalancerBuyQuote, computeBalancerSellQuote } from './balancer_utils';
|
||||||
import { BancorService } from './bancor_service';
|
import { BancorService } from './bancor_service';
|
||||||
import { MAINNET_SUSHI_SWAP_ROUTER, MAX_UINT256, NULL_BYTES, ZERO_AMOUNT } from './constants';
|
import { MAINNET_SUSHI_SWAP_ROUTER, MAX_UINT256, NULL_BYTES, ZERO_AMOUNT } from './constants';
|
||||||
|
import { CreamPoolsCache } from './cream_utils';
|
||||||
import { getCurveInfosForPair, getSwerveInfosForPair } from './curve_utils';
|
import { getCurveInfosForPair, getSwerveInfosForPair } from './curve_utils';
|
||||||
import { getKyberReserveIdsForPair } from './kyber_utils';
|
import { getKyberReserveIdsForPair } from './kyber_utils';
|
||||||
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
||||||
@ -18,6 +19,7 @@ import {
|
|||||||
BalancerFillData,
|
BalancerFillData,
|
||||||
BancorFillData,
|
BancorFillData,
|
||||||
BatchedOperation,
|
BatchedOperation,
|
||||||
|
CreamFillData,
|
||||||
CurveFillData,
|
CurveFillData,
|
||||||
CurveInfo,
|
CurveInfo,
|
||||||
DexSample,
|
DexSample,
|
||||||
@ -72,6 +74,7 @@ export class SamplerOperations {
|
|||||||
protected readonly _samplerContract: ERC20BridgeSamplerContract,
|
protected readonly _samplerContract: ERC20BridgeSamplerContract,
|
||||||
public readonly provider?: SupportedProvider,
|
public readonly provider?: SupportedProvider,
|
||||||
public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
|
public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
|
||||||
|
public readonly creamPoolsCache: CreamPoolsCache = new CreamPoolsCache(),
|
||||||
protected readonly getBancorServiceFn?: () => BancorService, // for dependency injection in tests
|
protected readonly getBancorServiceFn?: () => BancorService, // for dependency injection in tests
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -466,6 +469,68 @@ export class SamplerOperations {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getCreamSellQuotes(
|
||||||
|
poolAddress: string,
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): SourceQuoteOperation<CreamFillData> {
|
||||||
|
return new SamplerContractOperation({
|
||||||
|
source: ERC20BridgeSource.Cream,
|
||||||
|
fillData: { poolAddress },
|
||||||
|
contract: this._samplerContract,
|
||||||
|
function: this._samplerContract.sampleSellsFromBalancer,
|
||||||
|
params: [poolAddress, takerToken, makerToken, takerFillAmounts],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCreamBuyQuotes(
|
||||||
|
poolAddress: string,
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
): SourceQuoteOperation<CreamFillData> {
|
||||||
|
return new SamplerContractOperation({
|
||||||
|
source: ERC20BridgeSource.Cream,
|
||||||
|
fillData: { poolAddress },
|
||||||
|
contract: this._samplerContract,
|
||||||
|
function: this._samplerContract.sampleBuysFromBalancer,
|
||||||
|
params: [poolAddress, takerToken, makerToken, makerFillAmounts],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getCreamSellQuotesOffChainAsync(
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): Promise<Array<Array<DexSample<CreamFillData>>>> {
|
||||||
|
const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken);
|
||||||
|
return pools.map(pool =>
|
||||||
|
takerFillAmounts.map(amount => ({
|
||||||
|
source: ERC20BridgeSource.Balancer,
|
||||||
|
output: computeBalancerSellQuote(pool, amount),
|
||||||
|
input: amount,
|
||||||
|
fillData: { poolAddress: pool.id },
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getCreamBuyQuotesOffChainAsync(
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
): Promise<Array<Array<DexSample<BalancerFillData>>>> {
|
||||||
|
const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken);
|
||||||
|
return pools.map(pool =>
|
||||||
|
makerFillAmounts.map(amount => ({
|
||||||
|
source: ERC20BridgeSource.Balancer,
|
||||||
|
output: computeBalancerBuyQuote(pool, amount),
|
||||||
|
input: amount,
|
||||||
|
fillData: { poolAddress: pool.id },
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public getMStableSellQuotes(
|
public getMStableSellQuotes(
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
@ -997,6 +1062,12 @@ export class SamplerOperations {
|
|||||||
.map(poolAddress =>
|
.map(poolAddress =>
|
||||||
this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts),
|
this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts),
|
||||||
);
|
);
|
||||||
|
case ERC20BridgeSource.Cream:
|
||||||
|
return this.creamPoolsCache
|
||||||
|
.getCachedPoolAddressesForPair(takerToken, makerToken)!
|
||||||
|
.map(poolAddress =>
|
||||||
|
this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts),
|
||||||
|
);
|
||||||
case ERC20BridgeSource.Shell:
|
case ERC20BridgeSource.Shell:
|
||||||
return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts);
|
return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||||
default:
|
default:
|
||||||
@ -1086,6 +1157,12 @@ export class SamplerOperations {
|
|||||||
.map(poolAddress =>
|
.map(poolAddress =>
|
||||||
this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts),
|
this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts),
|
||||||
);
|
);
|
||||||
|
case ERC20BridgeSource.Cream:
|
||||||
|
return this.creamPoolsCache
|
||||||
|
.getCachedPoolAddressesForPair(takerToken, makerToken)!
|
||||||
|
.map(poolAddress =>
|
||||||
|
this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts),
|
||||||
|
);
|
||||||
case ERC20BridgeSource.Shell:
|
case ERC20BridgeSource.Shell:
|
||||||
return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||||
default:
|
default:
|
||||||
|
@ -37,6 +37,7 @@ export enum ERC20BridgeSource {
|
|||||||
LiquidityProvider = 'LiquidityProvider',
|
LiquidityProvider = 'LiquidityProvider',
|
||||||
MultiBridge = 'MultiBridge',
|
MultiBridge = 'MultiBridge',
|
||||||
Balancer = 'Balancer',
|
Balancer = 'Balancer',
|
||||||
|
Cream = 'CREAM',
|
||||||
Bancor = 'Bancor',
|
Bancor = 'Bancor',
|
||||||
MStable = 'mStable',
|
MStable = 'mStable',
|
||||||
Mooniswap = 'Mooniswap',
|
Mooniswap = 'Mooniswap',
|
||||||
@ -103,6 +104,10 @@ export interface BalancerFillData extends FillData {
|
|||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CreamFillData extends FillData {
|
||||||
|
poolAddress: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface UniswapV2FillData extends FillData {
|
export interface UniswapV2FillData extends FillData {
|
||||||
tokenAddressPath: string[];
|
tokenAddressPath: string[];
|
||||||
}
|
}
|
||||||
|
@ -504,6 +504,7 @@ describe('DexSampler tests', () => {
|
|||||||
undefined, // sampler overrides
|
undefined, // sampler overrides
|
||||||
provider,
|
provider,
|
||||||
undefined, // balancer cache
|
undefined, // balancer cache
|
||||||
|
undefined, // cream cache
|
||||||
() => bancorService,
|
() => bancorService,
|
||||||
);
|
);
|
||||||
const quotes = await dexOrderSampler.getBancorSellQuotesOffChainAsync(
|
const quotes = await dexOrderSampler.getBancorSellQuotesOffChainAsync(
|
||||||
|
@ -25,6 +25,7 @@ import {
|
|||||||
SOURCE_FLAGS,
|
SOURCE_FLAGS,
|
||||||
ZERO_AMOUNT,
|
ZERO_AMOUNT,
|
||||||
} from '../src/utils/market_operation_utils/constants';
|
} from '../src/utils/market_operation_utils/constants';
|
||||||
|
import { CreamPoolsCache } from '../src/utils/market_operation_utils/cream_utils';
|
||||||
import { createFills } from '../src/utils/market_operation_utils/fills';
|
import { createFills } from '../src/utils/market_operation_utils/fills';
|
||||||
import { DexOrderSampler } from '../src/utils/market_operation_utils/sampler';
|
import { DexOrderSampler } from '../src/utils/market_operation_utils/sampler';
|
||||||
import { BATCH_SOURCE_FILTERS } from '../src/utils/market_operation_utils/sampler_operations';
|
import { BATCH_SOURCE_FILTERS } from '../src/utils/market_operation_utils/sampler_operations';
|
||||||
@ -51,6 +52,7 @@ const DEFAULT_EXCLUDED = [
|
|||||||
ERC20BridgeSource.SushiSwap,
|
ERC20BridgeSource.SushiSwap,
|
||||||
ERC20BridgeSource.MultiHop,
|
ERC20BridgeSource.MultiHop,
|
||||||
ERC20BridgeSource.Shell,
|
ERC20BridgeSource.Shell,
|
||||||
|
ERC20BridgeSource.Cream,
|
||||||
];
|
];
|
||||||
const BUY_SOURCES = BUY_SOURCE_FILTER.sources;
|
const BUY_SOURCES = BUY_SOURCE_FILTER.sources;
|
||||||
const SELL_SOURCES = SELL_SOURCE_FILTER.sources;
|
const SELL_SOURCES = SELL_SOURCE_FILTER.sources;
|
||||||
@ -288,6 +290,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.SushiSwap]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.SushiSwap]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.MultiHop]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.MultiHop]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Shell]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.Shell]: _.times(NUM_SAMPLES, () => 0),
|
||||||
|
[ERC20BridgeSource.Cream]: _.times(NUM_SAMPLES, () => 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_RATES: RatesBySource = {
|
const DEFAULT_RATES: RatesBySource = {
|
||||||
@ -334,6 +337,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.Native]: { order: createOrder() },
|
[ERC20BridgeSource.Native]: { order: createOrder() },
|
||||||
[ERC20BridgeSource.MultiHop]: {},
|
[ERC20BridgeSource.MultiHop]: {},
|
||||||
[ERC20BridgeSource.Shell]: {},
|
[ERC20BridgeSource.Shell]: {},
|
||||||
|
[ERC20BridgeSource.Cream]: { poolAddress: randomAddress() },
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_OPS = {
|
const DEFAULT_OPS = {
|
||||||
@ -370,6 +374,30 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
DEFAULT_FILL_DATA[ERC20BridgeSource.Balancer],
|
DEFAULT_FILL_DATA[ERC20BridgeSource.Balancer],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
getCreamSellQuotesOffChainAsync: (
|
||||||
|
_makerToken: string,
|
||||||
|
_takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
) => [
|
||||||
|
createSamplesFromRates(
|
||||||
|
ERC20BridgeSource.Cream,
|
||||||
|
takerFillAmounts,
|
||||||
|
createDecreasingRates(takerFillAmounts.length),
|
||||||
|
DEFAULT_FILL_DATA[ERC20BridgeSource.Cream],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
getCreamBuyQuotesOffChainAsync: (
|
||||||
|
_makerToken: string,
|
||||||
|
_takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
) => [
|
||||||
|
createSamplesFromRates(
|
||||||
|
ERC20BridgeSource.Cream,
|
||||||
|
makerFillAmounts,
|
||||||
|
createDecreasingRates(makerFillAmounts.length).map(r => new BigNumber(1).div(r)),
|
||||||
|
DEFAULT_FILL_DATA[ERC20BridgeSource.Cream],
|
||||||
|
),
|
||||||
|
],
|
||||||
getBancorSellQuotesOffChainAsync: (_makerToken: string, _takerToken: string, takerFillAmounts: BigNumber[]) =>
|
getBancorSellQuotesOffChainAsync: (_makerToken: string, _takerToken: string, takerFillAmounts: BigNumber[]) =>
|
||||||
createSamplesFromRates(
|
createSamplesFromRates(
|
||||||
ERC20BridgeSource.Bancor,
|
ERC20BridgeSource.Bancor,
|
||||||
@ -389,6 +417,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
return ops;
|
return ops;
|
||||||
},
|
},
|
||||||
balancerPoolsCache: new BalancerPoolsCache(),
|
balancerPoolsCache: new BalancerPoolsCache(),
|
||||||
|
creamPoolsCache: new CreamPoolsCache(),
|
||||||
} as any) as DexOrderSampler;
|
} as any) as DexOrderSampler;
|
||||||
|
|
||||||
function replaceSamplerOps(ops: Partial<typeof DEFAULT_OPS> = {}): void {
|
function replaceSamplerOps(ops: Partial<typeof DEFAULT_OPS> = {}): void {
|
||||||
@ -492,6 +521,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamSellQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, {
|
await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, {
|
||||||
...DEFAULT_OPTS,
|
...DEFAULT_OPTS,
|
||||||
@ -522,6 +559,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
args.sources = args.sources.concat(ERC20BridgeSource.Balancer);
|
args.sources = args.sources.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamSellQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
args.sources = args.sources.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const registryAddress = randomAddress();
|
const registryAddress = randomAddress();
|
||||||
const newMarketOperationUtils = new MarketOperationUtils(
|
const newMarketOperationUtils = new MarketOperationUtils(
|
||||||
@ -563,6 +608,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamSellQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, {
|
await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, {
|
||||||
...DEFAULT_OPTS,
|
...DEFAULT_OPTS,
|
||||||
@ -594,6 +647,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamSellQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, {
|
await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, {
|
||||||
...DEFAULT_OPTS,
|
...DEFAULT_OPTS,
|
||||||
@ -984,6 +1045,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamBuyQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, {
|
await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, {
|
||||||
...DEFAULT_OPTS,
|
...DEFAULT_OPTS,
|
||||||
@ -1014,6 +1083,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
args.sources = args.sources.concat(ERC20BridgeSource.Balancer);
|
args.sources = args.sources.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamBuyQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
args.sources = args.sources.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const registryAddress = randomAddress();
|
const registryAddress = randomAddress();
|
||||||
const newMarketOperationUtils = new MarketOperationUtils(
|
const newMarketOperationUtils = new MarketOperationUtils(
|
||||||
@ -1055,6 +1132,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamBuyQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, {
|
await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, {
|
||||||
...DEFAULT_OPTS,
|
...DEFAULT_OPTS,
|
||||||
@ -1086,6 +1171,14 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer);
|
||||||
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
},
|
},
|
||||||
|
getCreamBuyQuotesOffChainAsync: (
|
||||||
|
makerToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
) => {
|
||||||
|
sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream);
|
||||||
|
return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, {
|
await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, {
|
||||||
...DEFAULT_OPTS,
|
...DEFAULT_OPTS,
|
||||||
|
@ -325,6 +325,7 @@ export async function runMigrationsAsync(
|
|||||||
uniswapExchangeFactory: NULL_ADDRESS,
|
uniswapExchangeFactory: NULL_ADDRESS,
|
||||||
mStable: NULL_ADDRESS,
|
mStable: NULL_ADDRESS,
|
||||||
shellBridge: NULL_ADDRESS,
|
shellBridge: NULL_ADDRESS,
|
||||||
|
creamBridge: NULL_ADDRESS,
|
||||||
shell: NULL_ADDRESS,
|
shell: NULL_ADDRESS,
|
||||||
weth: etherToken.address,
|
weth: etherToken.address,
|
||||||
},
|
},
|
||||||
|
@ -5510,6 +5510,14 @@ coveralls@^3.0.0:
|
|||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
request "^2.79.0"
|
request "^2.79.0"
|
||||||
|
|
||||||
|
cream-sor@^0.3.3:
|
||||||
|
version "0.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/cream-sor/-/cream-sor-0.3.3.tgz#ae7ab50c68cfd36a89e2101187ceebbb79e1b14c"
|
||||||
|
integrity sha512-taQSvCUunPhwyebwbjxh1l9NDp39lsre+Q2oRMK+gqzbu+Wlbg5GAquwoV2/GLgzia70gi4x1rJCJsUmc5Kygg==
|
||||||
|
dependencies:
|
||||||
|
bignumber.js "^9.0.0"
|
||||||
|
isomorphic-fetch "^2.2.1"
|
||||||
|
|
||||||
create-ecdh@^4.0.0:
|
create-ecdh@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.1.tgz#44223dfed533193ba5ba54e0df5709b89acf1f82"
|
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.1.tgz#44223dfed533193ba5ba54e0df5709b89acf1f82"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user