fix: [asset-swapper] Rework Bancor to only use paths and sample best path (#88)
* Rework Bancor to only use paths and sample best path * Deployed address * Clean up and pin bancor sdk * CHANGELOGs
This commit is contained in:
parent
437a3b048d
commit
d7bea98075
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "3.7.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fix Bancor support of ETH",
|
||||
"pr": 88
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "3.6.9",
|
||||
|
@ -21,6 +21,7 @@ pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
@ -36,6 +37,20 @@ contract BancorBridge is
|
||||
struct TransferState {
|
||||
address bancorNetworkAddress;
|
||||
address[] path;
|
||||
IEtherToken weth;
|
||||
}
|
||||
|
||||
/// @dev Bancor ETH pseudo-address.
|
||||
address constant public BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from Bancor/WETH.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{
|
||||
// Poor man's receive in 0.5.9
|
||||
require(msg.data.length == 0);
|
||||
}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
@ -60,7 +75,6 @@ contract BancorBridge is
|
||||
{
|
||||
// hold variables to get around stack depth limitations
|
||||
TransferState memory state;
|
||||
|
||||
// Decode the bridge data.
|
||||
(
|
||||
state.path,
|
||||
@ -68,34 +82,42 @@ contract BancorBridge is
|
||||
// solhint-disable indent
|
||||
) = abi.decode(bridgeData, (address[], address));
|
||||
// solhint-enable indent
|
||||
state.weth = IEtherToken(_getWethAddress());
|
||||
|
||||
require(state.path.length > 0, "BancorBridge/PATH_MUST_EXIST");
|
||||
// Just transfer the tokens if they're the same.
|
||||
if (state.path[0] == toTokenAddress) {
|
||||
LibERC20Token.transfer(state.path[0], to, amount);
|
||||
return BRIDGE_SUCCESS;
|
||||
require(state.path.length >= 2, "BancorBridge/PATH_LENGTH_MUST_BE_GREATER_THAN_TWO");
|
||||
|
||||
// Grant an allowance to the Bancor Network to spend `fromTokenAddress` token.
|
||||
uint256 fromTokenBalance;
|
||||
uint256 payableAmount = 0;
|
||||
// If it's ETH in the path then withdraw from WETH
|
||||
// The Bancor path will have ETH as the 0xeee address
|
||||
// Bancor expects to be paid in ETH not WETH
|
||||
if (state.path[0] == BANCOR_ETH_ADDRESS) {
|
||||
fromTokenBalance = state.weth.balanceOf(address(this));
|
||||
state.weth.withdraw(fromTokenBalance);
|
||||
payableAmount = fromTokenBalance;
|
||||
} else {
|
||||
fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
LibERC20Token.approveIfBelow(state.path[0], state.bancorNetworkAddress, fromTokenBalance);
|
||||
}
|
||||
|
||||
// Otherwise use Bancor to convert
|
||||
require(state.path.length > 2, "BancorBridge/PATH_LENGTH_MUST_BE_GREATER_THAN_TWO");
|
||||
require(state.path[state.path.length - 1] == toTokenAddress, "BancorBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
|
||||
|
||||
// // Grant an allowance to the Bancor Network to spend `fromTokenAddress` token.
|
||||
uint256 fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
LibERC20Token.approveIfBelow(state.path[0], state.bancorNetworkAddress, fromTokenBalance);
|
||||
|
||||
// Convert the tokens
|
||||
uint256 boughtAmount = IBancorNetwork(state.bancorNetworkAddress).convertByPath(
|
||||
uint256 boughtAmount = IBancorNetwork(state.bancorNetworkAddress).convertByPath.value(payableAmount)(
|
||||
state.path, // path originating with source token and terminating in destination token
|
||||
fromTokenBalance, // amount of source token to trade
|
||||
amount, // minimum amount of destination token expected to receive
|
||||
to, // beneficiary
|
||||
state.path[state.path.length-1] == BANCOR_ETH_ADDRESS ? address(this) : to, // beneficiary
|
||||
address(0), // affiliateAccount; no fee paid
|
||||
0 // affiliateFee; no fee paid
|
||||
);
|
||||
|
||||
if (state.path[state.path.length-1] == BANCOR_ETH_ADDRESS) {
|
||||
state.weth.deposit.value(boughtAmount)();
|
||||
state.weth.transfer(to, boughtAmount);
|
||||
}
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
state.path[0], // fromTokenAddress
|
||||
state.path[0] == BANCOR_ETH_ADDRESS ? address(state.weth) : state.path[0],
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
@ -118,5 +140,5 @@ contract BancorBridge is
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -56,11 +56,14 @@ contract KyberBridge is
|
||||
uint256 constant private KYBER_RATE_BASE = 10 ** 18;
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from Kyber.
|
||||
/// @dev Payable fallback to receive ETH from Kyber/WETH.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{}
|
||||
{
|
||||
// Poor man's receive in 0.5.9
|
||||
require(msg.data.length == 0);
|
||||
}
|
||||
|
||||
/// @dev Callback for `IKyberBridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||
|
@ -12,13 +12,11 @@ import { DecodedLogs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
|
||||
import { TestBancorBridgeContract } from './generated-wrappers/test_bancor_bridge';
|
||||
import {
|
||||
TestBancorBridgeConvertByPathInputEventArgs as ConvertByPathArgs,
|
||||
TestBancorBridgeEvents as ContractEvents,
|
||||
TestBancorBridgeTokenApproveEventArgs as TokenApproveArgs,
|
||||
TestBancorBridgeTokenTransferEventArgs as TokenTransferArgs,
|
||||
} from './wrappers';
|
||||
|
||||
blockchainTests.resets('Bancor unit tests', env => {
|
||||
@ -128,24 +126,6 @@ blockchainTests.resets('Bancor unit tests', env => {
|
||||
expect(result).to.eq(AssetProxyId.ERC20Bridge);
|
||||
});
|
||||
|
||||
it('performs transfer when both tokens are the same', async () => {
|
||||
const createTokenFn = testContract.createToken(constants.NULL_ADDRESS);
|
||||
const tokenAddress = await createTokenFn.callAsync();
|
||||
await createTokenFn.awaitTransactionSuccessAsync();
|
||||
|
||||
const { opts, result, logs } = await transferFromAsync({
|
||||
tokenAddressesPath: [tokenAddress, tokenAddress],
|
||||
});
|
||||
expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
|
||||
const transfers = filterLogsToArguments<TokenTransferArgs>(logs, ContractEvents.TokenTransfer);
|
||||
|
||||
expect(transfers.length).to.eq(1);
|
||||
expect(transfers[0].token).to.eq(tokenAddress, 'input token address');
|
||||
expect(transfers[0].from).to.eq(testContract.address);
|
||||
expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
|
||||
expect(transfers[0].amount).to.bignumber.eq(opts.amount, 'amount');
|
||||
});
|
||||
|
||||
describe('token -> token', async () => {
|
||||
it('calls BancorNetwork.convertByPath()', async () => {
|
||||
const { opts, result, logs } = await transferFromAsync();
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "5.5.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Bancor now supported in all pairs",
|
||||
"pr": 88
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "5.4.2",
|
||||
|
131
packages/asset-swapper/contracts/src/BancorSampler.sol
Normal file
131
packages/asset-swapper/contracts/src/BancorSampler.sol
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./DeploymentConstants.sol";
|
||||
import "./interfaces/IBancor.sol";
|
||||
|
||||
|
||||
|
||||
contract BancorSampler is
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
/// @dev Base gas limit for Bancor calls.
|
||||
uint256 constant private BANCOR_CALL_GAS = 300e3; // 300k
|
||||
address constant private BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
|
||||
/// @dev Sample sell quotes from Bancor.
|
||||
/// @param paths The paths to check for Bancor. Only the best is used
|
||||
/// @param takerToken Address of the taker token (what to sell).
|
||||
/// @param makerToken Address of the maker token (what to buy).
|
||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||
/// @return bancorNetwork the Bancor Network address
|
||||
/// @return path the selected conversion path from bancor
|
||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||
/// amount.
|
||||
function sampleSellsFromBancor(
|
||||
address[][] memory paths,
|
||||
address takerToken,
|
||||
address makerToken,
|
||||
uint256[] memory takerTokenAmounts
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (address bancorNetwork, address[] memory path, uint256[] memory makerTokenAmounts)
|
||||
{
|
||||
bancorNetwork = _getBancorNetwork();
|
||||
if (paths.length == 0) {
|
||||
return (bancorNetwork, path, makerTokenAmounts);
|
||||
}
|
||||
uint256 maxBoughtAmount = 0;
|
||||
// Find the best path by selling the largest taker amount
|
||||
for (uint256 i = 0; i < paths.length; i++) {
|
||||
if (paths[i].length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
IBancorNetwork(bancorNetwork)
|
||||
.rateByPath
|
||||
{gas: BANCOR_CALL_GAS}
|
||||
(paths[i], takerTokenAmounts[takerTokenAmounts.length-1])
|
||||
returns (uint256 amount)
|
||||
{
|
||||
if (amount > maxBoughtAmount) {
|
||||
maxBoughtAmount = amount;
|
||||
path = paths[i];
|
||||
}
|
||||
} catch {
|
||||
// Swallow failures, leaving all results as zero.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
uint256 numSamples = takerTokenAmounts.length;
|
||||
makerTokenAmounts = new uint256[](numSamples);
|
||||
|
||||
for (uint256 i = 0; i < numSamples; i++) {
|
||||
try
|
||||
IBancorNetwork(bancorNetwork)
|
||||
.rateByPath
|
||||
{gas: BANCOR_CALL_GAS}
|
||||
(path, takerTokenAmounts[i])
|
||||
returns (uint256 amount)
|
||||
{
|
||||
makerTokenAmounts[i] = amount;
|
||||
} catch {
|
||||
// Swallow failures, leaving all results as zero.
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (bancorNetwork, path, makerTokenAmounts);
|
||||
}
|
||||
|
||||
/// @dev Sample buy quotes from Bancor. Unimplemented
|
||||
/// @param paths The paths to check for Bancor. Only the best is used
|
||||
/// @param takerToken Address of the taker token (what to sell).
|
||||
/// @param makerToken Address of the maker token (what to buy).
|
||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
||||
/// @return bancorNetwork the Bancor Network address
|
||||
/// @return path the selected conversion path from bancor
|
||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||
/// amount.
|
||||
function sampleBuysFromBancor(
|
||||
address[][] memory paths,
|
||||
address takerToken,
|
||||
address makerToken,
|
||||
uint256[] memory makerTokenAmounts
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (address bancorNetwork, address[] memory path, uint256[] memory takerTokenAmounts)
|
||||
{
|
||||
}
|
||||
|
||||
function _getBancorNetwork()
|
||||
private
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
IBancorRegistry registry = IBancorRegistry(_getBancorRegistryAddress());
|
||||
return registry.getAddress(registry.BANCOR_NETWORK());
|
||||
}
|
||||
}
|
@ -62,6 +62,8 @@ contract DeploymentConstants {
|
||||
address constant private DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
|
||||
/// @dev Mainnet address of the DODO Helper contract
|
||||
address constant private DODO_HELPER = 0x533dA777aeDCE766CEAe696bf90f8541A4bA80Eb;
|
||||
/// @dev Mainnet address of the Bancor Registry contract
|
||||
address constant private BANCOR_REGISTRY = 0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4;
|
||||
|
||||
// // Ropsten addresses ///////////////////////////////////////////////////////
|
||||
// /// @dev Mainnet address of the WETH contract.
|
||||
@ -337,4 +339,14 @@ contract DeploymentConstants {
|
||||
{
|
||||
return DODO_HELPER;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the Bancor Registry contract address.
|
||||
/// @return registry The Bancor registry contract address.
|
||||
function _getBancorRegistryAddress()
|
||||
internal
|
||||
view
|
||||
returns (address registry)
|
||||
{
|
||||
return BANCOR_REGISTRY;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ pragma solidity ^0.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./BalancerSampler.sol";
|
||||
import "./BancorSampler.sol";
|
||||
import "./CurveSampler.sol";
|
||||
import "./DODOSampler.sol";
|
||||
import "./Eth2DaiSampler.sol";
|
||||
@ -38,6 +39,7 @@ import "./UniswapV2Sampler.sol";
|
||||
|
||||
contract ERC20BridgeSampler is
|
||||
BalancerSampler,
|
||||
BancorSampler,
|
||||
CurveSampler,
|
||||
DODOSampler,
|
||||
Eth2DaiSampler,
|
||||
|
32
packages/asset-swapper/contracts/src/interfaces/IBancor.sol
Normal file
32
packages/asset-swapper/contracts/src/interfaces/IBancor.sol
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6;
|
||||
|
||||
|
||||
interface IBancor {}
|
||||
|
||||
interface IBancorNetwork {
|
||||
function conversionPath(address _sourceToken, address _targetToken) external view returns (address[] memory);
|
||||
function rateByPath(address[] memory _path, uint256 _amount) external view returns (uint256);
|
||||
}
|
||||
|
||||
interface IBancorRegistry {
|
||||
function getAddress(bytes32 _contractName) external view returns (address);
|
||||
function BANCOR_NETWORK() external view returns (bytes32);
|
||||
}
|
@ -38,7 +38,7 @@
|
||||
"config": {
|
||||
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|CurveSampler|DODOSampler|DeploymentConstants|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
|
||||
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BancorSampler|CurveSampler|DODOSampler|DeploymentConstants|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
|
||||
"postpublish": {
|
||||
"assets": []
|
||||
}
|
||||
@ -71,7 +71,7 @@
|
||||
"@0x/utils": "^6.1.1",
|
||||
"@0x/web3-wrapper": "^7.3.0",
|
||||
"@balancer-labs/sor": "0.3.2",
|
||||
"@bancor/sdk": "^0.2.9",
|
||||
"@bancor/sdk": "0.2.9",
|
||||
"@ethersproject/abi": "^5.0.1",
|
||||
"@ethersproject/address": "^5.0.1",
|
||||
"@ethersproject/contracts": "^5.0.1",
|
||||
|
@ -213,9 +213,8 @@ export class SwapQuoter {
|
||||
samplerContract,
|
||||
samplerOverrides,
|
||||
provider,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined, // balancer pool cache
|
||||
undefined, // cream pool cache
|
||||
tokenAdjacencyGraph,
|
||||
liquidityProviderRegistry,
|
||||
),
|
||||
|
@ -1,26 +1,17 @@
|
||||
import { SupportedProvider } from '@0x/dev-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { SDK } from '@bancor/sdk';
|
||||
import { Ethereum, getDecimals } from '@bancor/sdk/dist/blockchains/ethereum';
|
||||
import { fromWei, toWei } from '@bancor/sdk/dist/helpers';
|
||||
import { BlockchainType, Token } from '@bancor/sdk/dist/types';
|
||||
import { Ethereum } from '@bancor/sdk/dist/blockchains/ethereum';
|
||||
import { BlockchainType } from '@bancor/sdk/dist/types';
|
||||
|
||||
import { BancorFillData, Quote } from './types';
|
||||
import { TOKENS } from './constants';
|
||||
|
||||
/**
|
||||
* Converts an address to a Bancor Token type
|
||||
*/
|
||||
export function token(address: string, blockchainType: BlockchainType = BlockchainType.Ethereum): Token {
|
||||
return {
|
||||
blockchainType,
|
||||
blockchainId: address,
|
||||
};
|
||||
}
|
||||
const findToken = (tokenAddress: string, graph: object): string =>
|
||||
// If we're looking for WETH it is stored by Bancor as the 0xeee address
|
||||
tokenAddress.toLowerCase() === TOKENS.WETH.toLowerCase()
|
||||
? '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
|
||||
: Object.keys(graph).filter(k => k.toLowerCase() === tokenAddress.toLowerCase())[0];
|
||||
|
||||
export class BancorService {
|
||||
// Bancor recommends setting this value to 2% under the expected return amount
|
||||
public minReturnAmountBufferPercentage = 0.99;
|
||||
|
||||
public static async createAsync(provider: SupportedProvider): Promise<BancorService> {
|
||||
const sdk = await SDK.create({ ethereumNodeEndpoint: provider });
|
||||
const service = new BancorService(sdk);
|
||||
@ -28,38 +19,16 @@ export class BancorService {
|
||||
}
|
||||
|
||||
constructor(public sdk: SDK) {}
|
||||
|
||||
public async getQuotesAsync(
|
||||
fromToken: string,
|
||||
toToken: string,
|
||||
amounts: BigNumber[],
|
||||
): Promise<Array<Quote<BancorFillData>>> {
|
||||
const sdk = this.sdk;
|
||||
const blockchain = sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
const sourceDecimals = await getDecimals(blockchain, fromToken);
|
||||
const quotes = await sdk.pricing.getPathAndRates(
|
||||
token(fromToken),
|
||||
token(toToken),
|
||||
amounts.map(amt => fromWei(amt.toString(), sourceDecimals)),
|
||||
);
|
||||
const targetDecimals = await getDecimals(blockchain, toToken);
|
||||
const networkAddress = this.getBancorNetworkAddress();
|
||||
|
||||
return quotes.map(quote => {
|
||||
const { path, rate } = quote;
|
||||
const output = toWei(rate, targetDecimals);
|
||||
return {
|
||||
amount: new BigNumber(output).multipliedBy(this.minReturnAmountBufferPercentage).dp(0),
|
||||
fillData: {
|
||||
path: path.map(p => p.blockchainId),
|
||||
networkAddress,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public getBancorNetworkAddress(): string {
|
||||
const blockchain = this.sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
return blockchain.bancorNetwork._address;
|
||||
public getPaths(_fromToken: string, _toToken: string): string[][] {
|
||||
// HACK: We reach into the blockchain object and pull in it's cache of tokens
|
||||
// and we use it's internal non-async getPathsFunc
|
||||
try {
|
||||
const blockchain = this.sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
const fromToken = findToken(_fromToken, blockchain.graph);
|
||||
const toToken = findToken(_toToken, blockchain.graph);
|
||||
return blockchain.getPathsFunc.bind(blockchain)(fromToken, toToken);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { BridgeContractAddresses } from '../../types';
|
||||
|
||||
import { SourceFilters } from './source_filters';
|
||||
import {
|
||||
BancorFillData,
|
||||
CurveFillData,
|
||||
CurveFunctionSelectors,
|
||||
CurveInfo,
|
||||
@ -34,8 +35,7 @@ export const SELL_SOURCE_FILTER = new SourceFilters([
|
||||
ERC20BridgeSource.Kyber,
|
||||
ERC20BridgeSource.Curve,
|
||||
ERC20BridgeSource.Balancer,
|
||||
// Bancor is sampled off-chain, but this list should only include on-chain sources (used in ERC20BridgeSampler)
|
||||
// ERC20BridgeSource.Bancor,
|
||||
ERC20BridgeSource.Bancor,
|
||||
ERC20BridgeSource.MStable,
|
||||
ERC20BridgeSource.Mooniswap,
|
||||
ERC20BridgeSource.Swerve,
|
||||
@ -60,7 +60,7 @@ export const BUY_SOURCE_FILTER = new SourceFilters([
|
||||
ERC20BridgeSource.Kyber,
|
||||
ERC20BridgeSource.Curve,
|
||||
ERC20BridgeSource.Balancer,
|
||||
// ERC20BridgeSource.Bancor, // FIXME: Disabled until Bancor SDK supports buy quotes
|
||||
// ERC20BridgeSource.Bancor, // FIXME: Bancor Buys not implemented in Sampler
|
||||
ERC20BridgeSource.MStable,
|
||||
ERC20BridgeSource.Mooniswap,
|
||||
ERC20BridgeSource.Shell,
|
||||
@ -410,7 +410,7 @@ export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAd
|
||||
curveBridge: '0x1796cd592d19e3bcd744fbb025bb61a6d8cb2c09',
|
||||
multiBridge: '0xc03117a8c9bde203f70aa911cb64a7a0df5ba1e1',
|
||||
balancerBridge: '0xfe01821ca163844203220cd08e4f2b2fb43ae4e4',
|
||||
bancorBridge: '0x259897d9699553edbdf8538599242354e957fb94',
|
||||
bancorBridge: '0xc880c252db7c51f74161633338a3bdafa8e65276',
|
||||
mStableBridge: '0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3',
|
||||
mooniswapBridge: '0x02b7eca484ad960fca3f7709e0b2ac81eec3069c',
|
||||
sushiswapBridge: '0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5',
|
||||
@ -539,7 +539,14 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
||||
throw new Error('Unrecognized SnowSwap address');
|
||||
}
|
||||
},
|
||||
[ERC20BridgeSource.Bancor]: () => 300e3,
|
||||
[ERC20BridgeSource.Bancor]: (fillData?: FillData) => {
|
||||
let gas = 200e3;
|
||||
const path = (fillData as BancorFillData).path;
|
||||
if (path.length > 2) {
|
||||
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
||||
}
|
||||
return gas;
|
||||
},
|
||||
};
|
||||
|
||||
export const DEFAULT_FEE_SCHEDULE: Required<FeeSchedule> = Object.assign(
|
||||
|
@ -203,23 +203,12 @@ export class MarketOperationUtils {
|
||||
? this._sampler.getCreamSellQuotesOffChainAsync(makerToken, takerToken, sampleAmounts)
|
||||
: Promise.resolve([]);
|
||||
|
||||
const offChainBancorPromise = quoteSourceFilters.isAllowed(ERC20BridgeSource.Bancor)
|
||||
? this._sampler.getBancorSellQuotesOffChainAsync(makerToken, takerToken, [takerAmount])
|
||||
: Promise.resolve([]);
|
||||
|
||||
const [
|
||||
[tokenDecimals, orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes],
|
||||
rfqtIndicativeQuotes,
|
||||
offChainBalancerQuotes,
|
||||
offChainCreamQuotes,
|
||||
offChainBancorQuotes,
|
||||
] = await Promise.all([
|
||||
samplerPromise,
|
||||
rfqtPromise,
|
||||
offChainBalancerPromise,
|
||||
offChainCreamPromise,
|
||||
offChainBancorPromise,
|
||||
]);
|
||||
] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainCreamPromise]);
|
||||
|
||||
const [makerTokenDecimals, takerTokenDecimals] = tokenDecimals;
|
||||
return {
|
||||
@ -227,7 +216,7 @@ export class MarketOperationUtils {
|
||||
inputAmount: takerAmount,
|
||||
inputToken: takerToken,
|
||||
outputToken: makerToken,
|
||||
dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, ...offChainCreamQuotes, offChainBancorQuotes]),
|
||||
dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, ...offChainCreamQuotes]),
|
||||
nativeOrders,
|
||||
orderFillableAmounts,
|
||||
ethToOutputRate: ethToMakerAssetRate,
|
||||
|
@ -5,7 +5,6 @@ import { SamplerOverrides } from '../../types';
|
||||
import { ERC20BridgeSamplerContract } from '../../wrappers';
|
||||
|
||||
import { BalancerPoolsCache } from './balancer_utils';
|
||||
import { BancorService } from './bancor_service';
|
||||
import { CreamPoolsCache } from './cream_utils';
|
||||
import { SamplerOperations } from './sampler_operations';
|
||||
import { BatchedOperation, LiquidityProviderRegistry, TokenAdjacencyGraph } from './types';
|
||||
@ -39,7 +38,6 @@ export class DexOrderSampler extends SamplerOperations {
|
||||
provider?: SupportedProvider,
|
||||
balancerPoolsCache?: BalancerPoolsCache,
|
||||
creamPoolsCache?: CreamPoolsCache,
|
||||
getBancorServiceFn?: () => BancorService,
|
||||
tokenAdjacencyGraph?: TokenAdjacencyGraph,
|
||||
liquidityProviderRegistry?: LiquidityProviderRegistry,
|
||||
) {
|
||||
@ -48,7 +46,6 @@ export class DexOrderSampler extends SamplerOperations {
|
||||
provider,
|
||||
balancerPoolsCache,
|
||||
creamPoolsCache,
|
||||
getBancorServiceFn,
|
||||
tokenAdjacencyGraph,
|
||||
liquidityProviderRegistry,
|
||||
);
|
||||
|
@ -84,22 +84,20 @@ export class SamplerOperations {
|
||||
public readonly provider?: SupportedProvider,
|
||||
public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
|
||||
public readonly creamPoolsCache: CreamPoolsCache = new CreamPoolsCache(),
|
||||
protected readonly getBancorServiceFn?: () => BancorService, // for dependency injection in tests
|
||||
protected readonly tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [] },
|
||||
public readonly liquidityProviderRegistry: LiquidityProviderRegistry = LIQUIDITY_PROVIDER_REGISTRY,
|
||||
) {}
|
||||
) {
|
||||
// Initialize the Bancor service, fetching paths in the background
|
||||
this.initBancorServiceAsync().catch(/* do nothing */);
|
||||
}
|
||||
|
||||
public async getBancorServiceAsync(): Promise<BancorService> {
|
||||
if (this.getBancorServiceFn !== undefined) {
|
||||
return this.getBancorServiceFn();
|
||||
}
|
||||
public async initBancorServiceAsync(): Promise<void> {
|
||||
if (this.provider === undefined) {
|
||||
throw new Error('Cannot sample liquidity from Bancor; no provider supplied.');
|
||||
return;
|
||||
}
|
||||
if (this._bancorService === undefined) {
|
||||
this._bancorService = await BancorService.createAsync(this.provider);
|
||||
}
|
||||
return this._bancorService;
|
||||
}
|
||||
|
||||
public getTokenDecimals(makerTokenAddress: string, takerTokenAddress: string): BatchedOperation<BigNumber[]> {
|
||||
@ -588,28 +586,48 @@ export class SamplerOperations {
|
||||
});
|
||||
}
|
||||
|
||||
public async getBancorSellQuotesOffChainAsync(
|
||||
public getBancorSellQuotes(
|
||||
makerToken: string,
|
||||
takerToken: string,
|
||||
takerFillAmounts: BigNumber[],
|
||||
): Promise<Array<DexSample<BancorFillData>>> {
|
||||
const bancorService = await this.getBancorServiceAsync();
|
||||
try {
|
||||
const quotes = await bancorService.getQuotesAsync(takerToken, makerToken, takerFillAmounts);
|
||||
return quotes.map((quote, i) => ({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
output: quote.amount,
|
||||
input: takerFillAmounts[i],
|
||||
fillData: quote.fillData,
|
||||
}));
|
||||
} catch (e) {
|
||||
return takerFillAmounts.map(input => ({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
output: ZERO_AMOUNT,
|
||||
input,
|
||||
fillData: { path: [], networkAddress: '' },
|
||||
}));
|
||||
}
|
||||
): SourceQuoteOperation<BancorFillData> {
|
||||
const paths = this._bancorService ? this._bancorService.getPaths(takerToken, makerToken) : [];
|
||||
return new SamplerContractOperation({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
contract: this._samplerContract,
|
||||
function: this._samplerContract.sampleSellsFromBancor,
|
||||
params: [paths, takerToken, makerToken, takerFillAmounts],
|
||||
callback: (callResults: string, fillData: BancorFillData): BigNumber[] => {
|
||||
const [networkAddress, path, samples] = this._samplerContract.getABIDecodedReturnData<
|
||||
[string, string[], BigNumber[]]
|
||||
>('sampleSellsFromBancor', callResults);
|
||||
fillData.networkAddress = networkAddress;
|
||||
fillData.path = path;
|
||||
return samples;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Unimplemented
|
||||
public getBancorBuyQuotes(
|
||||
makerToken: string,
|
||||
takerToken: string,
|
||||
makerFillAmounts: BigNumber[],
|
||||
): SourceQuoteOperation<BancorFillData> {
|
||||
return new SamplerContractOperation({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
contract: this._samplerContract,
|
||||
function: this._samplerContract.sampleBuysFromBancor,
|
||||
params: [[], takerToken, makerToken, makerFillAmounts],
|
||||
callback: (callResults: string, fillData: BancorFillData): BigNumber[] => {
|
||||
const [networkAddress, path, samples] = this._samplerContract.getABIDecodedReturnData<
|
||||
[string, string[], BigNumber[]]
|
||||
>('sampleSellsFromBancor', callResults);
|
||||
fillData.networkAddress = networkAddress;
|
||||
fillData.path = path;
|
||||
return samples;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public getMooniswapSellQuotes(
|
||||
@ -1114,6 +1132,8 @@ export class SamplerOperations {
|
||||
);
|
||||
case ERC20BridgeSource.Dodo:
|
||||
return this.getDODOSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||
case ERC20BridgeSource.Bancor:
|
||||
return this.getBancorSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||
default:
|
||||
throw new Error(`Unsupported sell sample source: ${source}`);
|
||||
}
|
||||
@ -1237,6 +1257,8 @@ export class SamplerOperations {
|
||||
);
|
||||
case ERC20BridgeSource.Dodo:
|
||||
return this.getDODOBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||
case ERC20BridgeSource.Bancor:
|
||||
return this.getBancorBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||
default:
|
||||
throw new Error(`Unsupported buy sample source: ${source}`);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { ContractArtifact } from 'ethereum-types';
|
||||
import * as ApproximateBuys from '../test/generated-artifacts/ApproximateBuys.json';
|
||||
import * as BalanceChecker from '../test/generated-artifacts/BalanceChecker.json';
|
||||
import * as BalancerSampler from '../test/generated-artifacts/BalancerSampler.json';
|
||||
import * as BancorSampler from '../test/generated-artifacts/BancorSampler.json';
|
||||
import * as CurveSampler from '../test/generated-artifacts/CurveSampler.json';
|
||||
import * as DeploymentConstants from '../test/generated-artifacts/DeploymentConstants.json';
|
||||
import * as DODOSampler from '../test/generated-artifacts/DODOSampler.json';
|
||||
@ -15,6 +16,7 @@ import * as DummyLiquidityProvider from '../test/generated-artifacts/DummyLiquid
|
||||
import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json';
|
||||
import * as Eth2DaiSampler from '../test/generated-artifacts/Eth2DaiSampler.json';
|
||||
import * as IBalancer from '../test/generated-artifacts/IBalancer.json';
|
||||
import * as IBancor from '../test/generated-artifacts/IBancor.json';
|
||||
import * as ICurve from '../test/generated-artifacts/ICurve.json';
|
||||
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
|
||||
import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
|
||||
@ -42,6 +44,7 @@ export const artifacts = {
|
||||
ApproximateBuys: ApproximateBuys as ContractArtifact,
|
||||
BalanceChecker: BalanceChecker as ContractArtifact,
|
||||
BalancerSampler: BalancerSampler as ContractArtifact,
|
||||
BancorSampler: BancorSampler as ContractArtifact,
|
||||
CurveSampler: CurveSampler as ContractArtifact,
|
||||
DODOSampler: DODOSampler as ContractArtifact,
|
||||
DeploymentConstants: DeploymentConstants as ContractArtifact,
|
||||
@ -60,6 +63,7 @@ export const artifacts = {
|
||||
UniswapSampler: UniswapSampler as ContractArtifact,
|
||||
UniswapV2Sampler: UniswapV2Sampler as ContractArtifact,
|
||||
IBalancer: IBalancer as ContractArtifact,
|
||||
IBancor: IBancor as ContractArtifact,
|
||||
ICurve: ICurve as ContractArtifact,
|
||||
IEth2Dai: IEth2Dai as ContractArtifact,
|
||||
IKyberNetwork: IKyberNetwork as ContractArtifact,
|
||||
|
@ -1,72 +0,0 @@
|
||||
import { web3Factory, Web3ProviderEngine } from '@0x/dev-utils';
|
||||
import { Ethereum, getDecimals } from '@bancor/sdk/dist/blockchains/ethereum';
|
||||
import { fromWei, toWei } from '@bancor/sdk/dist/helpers';
|
||||
import { BlockchainType } from '@bancor/sdk/dist/types';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
|
||||
import { BancorFillData, BigNumber } from '../src';
|
||||
import { BancorService, token } from '../src/utils/market_operation_utils/bancor_service';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const ADDRESS_REGEX = /^(0x)?[0-9a-f]{40}$/i;
|
||||
const RPC_URL = `https://mainnet.infura.io/v3/${process.env.INFURA_PROJECT_ID}`;
|
||||
|
||||
const provider: Web3ProviderEngine = web3Factory.getRpcProvider({ rpcUrl: RPC_URL });
|
||||
// tslint:disable:custom-no-magic-numbers
|
||||
|
||||
let bancorService: BancorService;
|
||||
|
||||
// These tests test the bancor SDK against mainnet
|
||||
// TODO (xianny): After we move asset-swapper out of the monorepo, we should add an env variable to circle CI to run this test
|
||||
describe.skip('Bancor Service', () => {
|
||||
const eth = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
|
||||
const bnt = '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c';
|
||||
it('should retrieve the bancor network address', async () => {
|
||||
bancorService = await BancorService.createAsync(provider);
|
||||
const networkAddress = bancorService.getBancorNetworkAddress();
|
||||
expect(networkAddress).to.match(ADDRESS_REGEX);
|
||||
});
|
||||
it('should retrieve a quote', async () => {
|
||||
const amt = new BigNumber(10e18);
|
||||
const quotes = await bancorService.getQuotesAsync(eth, bnt, [amt]);
|
||||
const fillData = quotes[0].fillData as BancorFillData;
|
||||
|
||||
// get rate from the bancor sdk
|
||||
const blockchain = bancorService.sdk._core.blockchains[BlockchainType.Ethereum] as Ethereum;
|
||||
const sourceDecimals = await getDecimals(blockchain, token(eth));
|
||||
const rate = await bancorService.sdk.pricing.getRateByPath(
|
||||
fillData.path.map(p => token(p)),
|
||||
fromWei(amt.toString(), sourceDecimals),
|
||||
);
|
||||
const expectedRate = toWei(rate, await getDecimals(blockchain, token(bnt)));
|
||||
|
||||
expect(fillData.networkAddress).to.match(ADDRESS_REGEX);
|
||||
expect(fillData.path[0].toLowerCase()).to.eq(eth);
|
||||
expect(fillData.path[2].toLowerCase()).to.eq(bnt);
|
||||
expect(fillData.path.length).to.eq(3); // eth -> bnt should be single hop!
|
||||
expect(quotes[0].amount.dp(0)).to.bignumber.eq(
|
||||
new BigNumber(expectedRate).multipliedBy(bancorService.minReturnAmountBufferPercentage).dp(0),
|
||||
);
|
||||
});
|
||||
// HACK (xianny): for exploring SDK results
|
||||
it('should retrieve multiple quotes', async () => {
|
||||
const amts = [1, 10, 100, 1000].map(a => new BigNumber(a).multipliedBy(10e18));
|
||||
const quotes = await bancorService.getQuotesAsync(eth, bnt, amts);
|
||||
quotes.map((q, i) => {
|
||||
// tslint:disable:no-console
|
||||
const fillData = q.fillData as BancorFillData;
|
||||
console.log(
|
||||
`Input ${amts[i].toExponential()}; Output: ${q.amount}; Ratio: ${q.amount.dividedBy(amts[i])}, Path: ${
|
||||
fillData.path.length
|
||||
}\nPath: ${JSON.stringify(fillData.path)}`,
|
||||
);
|
||||
// tslint:enable:no-console
|
||||
});
|
||||
});
|
||||
});
|
@ -17,9 +17,7 @@ import { DexOrderSampler, getSampleAmounts } from '../src/utils/market_operation
|
||||
import { ERC20BridgeSource, TokenAdjacencyGraph } from '../src/utils/market_operation_utils/types';
|
||||
|
||||
import { MockBalancerPoolsCache } from './utils/mock_balancer_pools_cache';
|
||||
import { MockBancorService } from './utils/mock_bancor_service';
|
||||
import { MockSamplerContract } from './utils/mock_sampler_contract';
|
||||
import { provider } from './utils/web3_wrapper';
|
||||
|
||||
const CHAIN_ID = 1;
|
||||
// tslint:disable: custom-no-magic-numbers
|
||||
@ -172,7 +170,6 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{ [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } },
|
||||
);
|
||||
const [result] = await dexOrderSampler.executeAsync(
|
||||
@ -215,7 +212,6 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{ [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } },
|
||||
);
|
||||
const [result] = await dexOrderSampler.executeAsync(
|
||||
@ -386,7 +382,6 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
tokenAdjacencyGraph,
|
||||
);
|
||||
const [quotes] = await dexOrderSampler.executeAsync(
|
||||
@ -451,45 +446,6 @@ describe('DexSampler tests', () => {
|
||||
);
|
||||
expect(quotes).to.have.lengthOf(0);
|
||||
});
|
||||
it('getSellQuotes() uses samples from Bancor', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const networkAddress = randomAddress();
|
||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
||||
const rate = getRandomFloat(0, 100);
|
||||
const bancorService = await MockBancorService.createMockAsync({
|
||||
getQuotesAsync: async (fromToken: string, toToken: string, amounts: BigNumber[]) => {
|
||||
expect(fromToken).equal(expectedTakerToken);
|
||||
expect(toToken).equal(expectedMakerToken);
|
||||
return Promise.resolve(
|
||||
amounts.map(a => ({
|
||||
fillData: { path: [fromToken, toToken], networkAddress },
|
||||
amount: a.multipliedBy(rate),
|
||||
})),
|
||||
);
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
new MockSamplerContract({}),
|
||||
undefined, // sampler overrides
|
||||
provider,
|
||||
undefined, // balancer cache
|
||||
undefined, // cream cache
|
||||
() => bancorService,
|
||||
);
|
||||
const quotes = await dexOrderSampler.getBancorSellQuotesOffChainAsync(
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
expectedTakerFillAmounts,
|
||||
);
|
||||
const expectedQuotes = expectedTakerFillAmounts.map(a => ({
|
||||
source: ERC20BridgeSource.Bancor,
|
||||
input: a,
|
||||
output: a.multipliedBy(rate),
|
||||
fillData: { path: [expectedTakerToken, expectedMakerToken], networkAddress },
|
||||
}));
|
||||
expect(quotes).to.deep.eq(expectedQuotes);
|
||||
});
|
||||
it('getBuyQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
@ -531,7 +487,6 @@ describe('DexSampler tests', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
tokenAdjacencyGraph,
|
||||
);
|
||||
const [quotes] = await dexOrderSampler.executeAsync(
|
||||
|
@ -1,33 +0,0 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { SDK } from '@bancor/sdk';
|
||||
|
||||
import { BancorService } from '../../src/utils/market_operation_utils/bancor_service';
|
||||
import { BancorFillData, Quote } from '../../src/utils/market_operation_utils/types';
|
||||
|
||||
export interface Handlers {
|
||||
getQuotesAsync: (fromToken: string, toToken: string, amount: BigNumber[]) => Promise<Array<Quote<BancorFillData>>>;
|
||||
}
|
||||
|
||||
export class MockBancorService extends BancorService {
|
||||
// Bancor recommends setting this value to 2% under the expected return amount
|
||||
public minReturnAmountBufferPercentage = 0.98;
|
||||
|
||||
public static async createMockAsync(handlers: Partial<Handlers>): Promise<MockBancorService> {
|
||||
const sdk = new SDK();
|
||||
return new MockBancorService(sdk, handlers);
|
||||
}
|
||||
|
||||
constructor(sdk: SDK, public handlers: Partial<Handlers>) {
|
||||
super(sdk);
|
||||
}
|
||||
|
||||
public async getQuotesAsync(
|
||||
fromToken: string,
|
||||
toToken: string,
|
||||
amounts: BigNumber[],
|
||||
): Promise<Array<Quote<BancorFillData>>> {
|
||||
return this.handlers.getQuotesAsync
|
||||
? this.handlers.getQuotesAsync(fromToken, toToken, amounts)
|
||||
: super.getQuotesAsync(fromToken, toToken, amounts);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
export * from '../test/generated-wrappers/approximate_buys';
|
||||
export * from '../test/generated-wrappers/balance_checker';
|
||||
export * from '../test/generated-wrappers/balancer_sampler';
|
||||
export * from '../test/generated-wrappers/bancor_sampler';
|
||||
export * from '../test/generated-wrappers/curve_sampler';
|
||||
export * from '../test/generated-wrappers/d_o_d_o_sampler';
|
||||
export * from '../test/generated-wrappers/deployment_constants';
|
||||
@ -13,6 +14,7 @@ export * from '../test/generated-wrappers/dummy_liquidity_provider';
|
||||
export * from '../test/generated-wrappers/erc20_bridge_sampler';
|
||||
export * from '../test/generated-wrappers/eth2_dai_sampler';
|
||||
export * from '../test/generated-wrappers/i_balancer';
|
||||
export * from '../test/generated-wrappers/i_bancor';
|
||||
export * from '../test/generated-wrappers/i_curve';
|
||||
export * from '../test/generated-wrappers/i_eth2_dai';
|
||||
export * from '../test/generated-wrappers/i_kyber_network';
|
||||
|
@ -8,6 +8,7 @@
|
||||
"test/generated-artifacts/ApproximateBuys.json",
|
||||
"test/generated-artifacts/BalanceChecker.json",
|
||||
"test/generated-artifacts/BalancerSampler.json",
|
||||
"test/generated-artifacts/BancorSampler.json",
|
||||
"test/generated-artifacts/CurveSampler.json",
|
||||
"test/generated-artifacts/DODOSampler.json",
|
||||
"test/generated-artifacts/DeploymentConstants.json",
|
||||
@ -15,6 +16,7 @@
|
||||
"test/generated-artifacts/ERC20BridgeSampler.json",
|
||||
"test/generated-artifacts/Eth2DaiSampler.json",
|
||||
"test/generated-artifacts/IBalancer.json",
|
||||
"test/generated-artifacts/IBancor.json",
|
||||
"test/generated-artifacts/ICurve.json",
|
||||
"test/generated-artifacts/IEth2Dai.json",
|
||||
"test/generated-artifacts/IKyberNetwork.json",
|
||||
|
Loading…
x
Reference in New Issue
Block a user