feat: [asset-swapper] Add Crypto.com as a source (#43)
* feat: [asset-swapper] Add Crypto.com as a source * Exclude in tests * Disable hop sources to avoid excess inaccuracy * Added CryptoCom Bridge and FQT rollup * update test * Deploy CryptoCom bridge * Update package.json * CHANGELOGs
This commit is contained in:
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "5.3.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added Crypto.com",
|
||||
"pr": 43
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "5.2.0",
|
||||
"changes": [
|
||||
|
@@ -426,4 +426,5 @@ export interface BridgeContractAddresses {
|
||||
creamBridge: string;
|
||||
swerveBridge: string;
|
||||
snowswapBridge: string;
|
||||
cryptoComBridge: string;
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ export const SELL_SOURCE_FILTER = new SourceFilters([
|
||||
ERC20BridgeSource.Dodo,
|
||||
ERC20BridgeSource.Cream,
|
||||
ERC20BridgeSource.LiquidityProvider,
|
||||
ERC20BridgeSource.CryptoCom,
|
||||
]);
|
||||
|
||||
/**
|
||||
@@ -69,6 +70,7 @@ export const BUY_SOURCE_FILTER = new SourceFilters([
|
||||
ERC20BridgeSource.Dodo,
|
||||
ERC20BridgeSource.Cream,
|
||||
ERC20BridgeSource.LiquidityProvider,
|
||||
ERC20BridgeSource.CryptoCom,
|
||||
]);
|
||||
|
||||
/**
|
||||
@@ -352,6 +354,7 @@ export const MAINNET_KYBER_TOKEN_RESERVE_IDS: { [token: string]: string } = {
|
||||
export const LIQUIDITY_PROVIDER_REGISTRY: LiquidityProviderRegistry = {};
|
||||
|
||||
export const MAINNET_SUSHI_SWAP_ROUTER = '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F';
|
||||
export const MAINNET_CRYPTO_COM_ROUTER = '0xCeB90E4C17d626BE0fACd78b79c9c87d7ca181b3';
|
||||
|
||||
export const MAINNET_SHELL_POOLS = {
|
||||
StableCoins: {
|
||||
@@ -394,6 +397,7 @@ const EMPTY_BRIDGE_ADDRESSES: BridgeContractAddresses = {
|
||||
creamBridge: NULL_ADDRESS,
|
||||
snowswapBridge: NULL_ADDRESS,
|
||||
swerveBridge: NULL_ADDRESS,
|
||||
cryptoComBridge: NULL_ADDRESS,
|
||||
};
|
||||
|
||||
export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAddresses } = {
|
||||
@@ -414,6 +418,7 @@ export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAd
|
||||
creamBridge: '0xb9d4bf2c8dab828f4ffb656acdb6c2b497d44f25',
|
||||
swerveBridge: '0xf9786d5eb1de47fa56a8f7bb387653c6d410bfee',
|
||||
snowswapBridge: '0xb1dbe83d15236ec10fdb214c6b89774b454754fd',
|
||||
cryptoComBridge: '0x015850307f6aab4ac6631923ceefe71b57492c9b',
|
||||
},
|
||||
[ChainId.Kovan]: {
|
||||
...EMPTY_BRIDGE_ADDRESSES,
|
||||
@@ -483,7 +488,16 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
||||
},
|
||||
[ERC20BridgeSource.SushiSwap]: (fillData?: FillData) => {
|
||||
// TODO: Different base cost if to/from ETH.
|
||||
let gas = 95e3;
|
||||
let gas = 90e3;
|
||||
const path = (fillData as SushiSwapFillData).tokenAddressPath;
|
||||
if (path.length > 2) {
|
||||
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
||||
}
|
||||
return gas;
|
||||
},
|
||||
[ERC20BridgeSource.CryptoCom]: (fillData?: FillData) => {
|
||||
// TODO: Different base cost if to/from ETH.
|
||||
let gas = 90e3 + 20e3 + 60e3; // temporary allowance diff, unrolled FQT
|
||||
const path = (fillData as SushiSwapFillData).tokenAddressPath;
|
||||
if (path.length > 2) {
|
||||
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
||||
|
@@ -199,6 +199,8 @@ function getBridgeAddressFromFill(fill: CollapsedFill, opts: CreateOrderFromPath
|
||||
return opts.contractAddresses.shellBridge;
|
||||
case ERC20BridgeSource.Dodo:
|
||||
return opts.contractAddresses.dodoBridge;
|
||||
case ERC20BridgeSource.CryptoCom:
|
||||
return opts.contractAddresses.cryptoComBridge;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -297,6 +299,14 @@ export function createBridgeOrder(
|
||||
createSushiSwapBridgeData(sushiSwapFillData.tokenAddressPath, sushiSwapFillData.router),
|
||||
);
|
||||
break;
|
||||
case ERC20BridgeSource.CryptoCom:
|
||||
const cryptoComFillData = (fill as CollapsedFill<SushiSwapFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
|
||||
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||
makerToken,
|
||||
bridgeAddress,
|
||||
createSushiSwapBridgeData(cryptoComFillData.tokenAddressPath, cryptoComFillData.router),
|
||||
);
|
||||
break;
|
||||
case ERC20BridgeSource.Kyber:
|
||||
const kyberFillData = (fill as CollapsedFill<KyberFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
|
||||
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||
|
@@ -7,7 +7,13 @@ import { ERC20BridgeSamplerContract } from '../../wrappers';
|
||||
|
||||
import { BalancerPoolsCache } from './balancer_utils';
|
||||
import { BancorService } from './bancor_service';
|
||||
import { LIQUIDITY_PROVIDER_REGISTRY, MAINNET_SUSHI_SWAP_ROUTER, MAX_UINT256, ZERO_AMOUNT } from './constants';
|
||||
import {
|
||||
LIQUIDITY_PROVIDER_REGISTRY,
|
||||
MAINNET_CRYPTO_COM_ROUTER,
|
||||
MAINNET_SUSHI_SWAP_ROUTER,
|
||||
MAX_UINT256,
|
||||
ZERO_AMOUNT,
|
||||
} from './constants';
|
||||
import { CreamPoolsCache } from './cream_utils';
|
||||
import { getCurveInfosForPair, getSnowSwapInfosForPair, getSwerveInfosForPair } from './curve_utils';
|
||||
import { getKyberReserveIdsForPair } from './kyber_utils';
|
||||
@@ -789,6 +795,32 @@ export class SamplerOperations {
|
||||
});
|
||||
}
|
||||
|
||||
public getCryptoComSellQuotes(
|
||||
tokenAddressPath: string[],
|
||||
takerFillAmounts: BigNumber[],
|
||||
): SourceQuoteOperation<SushiSwapFillData> {
|
||||
return new SamplerContractOperation({
|
||||
source: ERC20BridgeSource.CryptoCom,
|
||||
fillData: { tokenAddressPath, router: MAINNET_CRYPTO_COM_ROUTER },
|
||||
contract: this._samplerContract,
|
||||
function: this._samplerContract.sampleSellsFromSushiSwap,
|
||||
params: [MAINNET_CRYPTO_COM_ROUTER, tokenAddressPath, takerFillAmounts],
|
||||
});
|
||||
}
|
||||
|
||||
public getCryptoComBuyQuotes(
|
||||
tokenAddressPath: string[],
|
||||
makerFillAmounts: BigNumber[],
|
||||
): SourceQuoteOperation<SushiSwapFillData> {
|
||||
return new SamplerContractOperation({
|
||||
source: ERC20BridgeSource.CryptoCom,
|
||||
fillData: { tokenAddressPath, router: MAINNET_CRYPTO_COM_ROUTER },
|
||||
contract: this._samplerContract,
|
||||
function: this._samplerContract.sampleBuysFromSushiSwap,
|
||||
params: [MAINNET_CRYPTO_COM_ROUTER, tokenAddressPath, makerFillAmounts],
|
||||
});
|
||||
}
|
||||
|
||||
public getShellSellQuotes(
|
||||
poolAddress: string,
|
||||
makerToken: string,
|
||||
@@ -993,6 +1025,16 @@ export class SamplerOperations {
|
||||
);
|
||||
});
|
||||
return sushiOps;
|
||||
case ERC20BridgeSource.CryptoCom:
|
||||
const cryptoComOps = [
|
||||
this.getCryptoComSellQuotes([takerToken, makerToken], takerFillAmounts),
|
||||
];
|
||||
intermediateTokens.forEach(t => {
|
||||
cryptoComOps.push(
|
||||
this.getCryptoComSellQuotes([takerToken, t, makerToken], takerFillAmounts),
|
||||
);
|
||||
});
|
||||
return cryptoComOps;
|
||||
case ERC20BridgeSource.Kyber:
|
||||
return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId =>
|
||||
this.getKyberSellQuotes(reserveId, makerToken, takerToken, takerFillAmounts),
|
||||
@@ -1106,6 +1148,16 @@ export class SamplerOperations {
|
||||
);
|
||||
});
|
||||
return sushiOps;
|
||||
case ERC20BridgeSource.CryptoCom:
|
||||
const cryptoComOps = [
|
||||
this.getCryptoComBuyQuotes([takerToken, makerToken], makerFillAmounts),
|
||||
];
|
||||
intermediateTokens.forEach(t => {
|
||||
cryptoComOps.push(
|
||||
this.getCryptoComBuyQuotes([takerToken, t, makerToken], makerFillAmounts),
|
||||
);
|
||||
});
|
||||
return cryptoComOps;
|
||||
case ERC20BridgeSource.Kyber:
|
||||
return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId =>
|
||||
this.getKyberBuyQuotes(reserveId, makerToken, takerToken, makerFillAmounts),
|
||||
|
@@ -49,6 +49,7 @@ export enum ERC20BridgeSource {
|
||||
SnowSwap = 'SnowSwap',
|
||||
SushiSwap = 'SushiSwap',
|
||||
Dodo = 'DODO',
|
||||
CryptoCom = 'CryptoCom',
|
||||
}
|
||||
|
||||
// tslint:disable: enum-naming
|
||||
|
@@ -64,6 +64,7 @@ const DEFAULT_EXCLUDED = [
|
||||
ERC20BridgeSource.Cream,
|
||||
ERC20BridgeSource.Dodo,
|
||||
ERC20BridgeSource.LiquidityProvider,
|
||||
ERC20BridgeSource.CryptoCom,
|
||||
];
|
||||
const BUY_SOURCES = BUY_SOURCE_FILTER.sources;
|
||||
const SELL_SOURCES = SELL_SOURCE_FILTER.sources;
|
||||
@@ -312,6 +313,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
[ERC20BridgeSource.Shell]: _.times(NUM_SAMPLES, () => 0),
|
||||
[ERC20BridgeSource.Cream]: _.times(NUM_SAMPLES, () => 0),
|
||||
[ERC20BridgeSource.Dodo]: _.times(NUM_SAMPLES, () => 0),
|
||||
[ERC20BridgeSource.CryptoCom]: _.times(NUM_SAMPLES, () => 0),
|
||||
};
|
||||
|
||||
const DEFAULT_RATES: RatesBySource = {
|
||||
@@ -371,6 +373,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
[ERC20BridgeSource.Shell]: { poolAddress: randomAddress() },
|
||||
[ERC20BridgeSource.Cream]: { poolAddress: randomAddress() },
|
||||
[ERC20BridgeSource.Dodo]: {},
|
||||
[ERC20BridgeSource.CryptoCom]: { tokenAddressPath: [] },
|
||||
};
|
||||
|
||||
const DEFAULT_OPS = {
|
||||
|
Reference in New Issue
Block a user