import Web3 from 'web3'; import { validateAndParseAddress } from './utils' import { DODO_SDK_DATA } from './data/constants'; import { Route } from './route'; import * as ERC20_ABI from './abi/erc20.json'; export class DODOExternal { public ZERO_ADDRESS: string = '0x0000000000000000000000000000000000000000' public ETH_ADDRESS: string = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' public WEB3_URL: string public WETH_TOKEN: { symbol: string; address: string; decimals: number, name: string, source: string } = DODO_SDK_DATA.WETH public DODO_PROXY: string = DODO_SDK_DATA.DODO_PROXY public DODO_APPROVE: string = DODO_SDK_DATA.DODO_APPROVE public DODO_SWAP_CALC_HELPER: string = DODO_SDK_DATA.DODO_SWAP_CALC_HELPER public constructor( _WEB3_URL?: string ) { this.WEB3_URL = _WEB3_URL || DODO_SDK_DATA.WEB3_URL } /** * @notice 查询路由,仅支持主网 * @param fromToken * @param toToken * @param fromAmount (需计算考虑Decimals) * @param slippage (0-50)(可不填) * @param assetTo (用户地址)(可不填) * @param deadline (交易超时时间,默认20分钟)(可不填) */ public async GetRoute( fromToken: { address: string; decimals: number; symbol: string; source: string; name: string; }, toToken: { address: string; decimals: number; symbol: string; source: string; name: string; }, fromAmount: string, slippage: number = 0, assetTo: string = "", deadline: number = Math.floor(new Date().getTime() / 1000 + 60 * 20) ) { //hacked DODO_V1_TOKENLIST.includes(validateAndParseAddress(fromToken.address)) ? fromToken.source = 'dodo' : fromToken.source = 'other' DODO_V1_TOKENLIST.includes(validateAndParseAddress(toToken.address)) ? toToken.source = 'dodo' : toToken.source = 'other' const route = new Route(1, this.WEB3_URL) const quote1 = route.GetAndMakeDODOAndUniRoute(fromToken, toToken, fromAmount, slippage, assetTo, deadline) const quote2 = route.GetOneInchRoute(fromToken, toToken, fromAmount) const quote3 = route.GetZeroXRoute(fromToken, toToken, fromAmount) const quote4 = route.GetDODORoute(fromToken, toToken, fromAmount) let res: any[] = await Promise.all([quote1, quote2, quote3, quote4]); res.sort(function (a, b) { return a.resAmount - b.resAmount; }); return res[res.length - 1] } /** * @notice 构造路由请求至合约 * @param fromToken * @param toToken * @param fromAmount (需计算考虑Decimals) * @param slippage (0-50) * @param assetTo (用户地址) * @param source (询价来源) * @param deadline (交易超时时间,默认20分钟)(可不填) */ public async MakeRoute( fromToken: { address: string; decimals: number; symbol: string; source: string; name?: string; }, toToken: { address: string; decimals: number; symbol: string; name: string; source: string }, fromAmount: string, slippage: number, assetTo: string, source: string, deadline: number = Math.floor(new Date().getTime() / 1000 + 60 * 20), ) { //hacked DODO_V1_TOKENLIST.includes(validateAndParseAddress(fromToken.address)) ? fromToken.source = 'dodo' : fromToken.source = 'other' DODO_V1_TOKENLIST.includes(validateAndParseAddress(toToken.address)) ? toToken.source = 'dodo' : toToken.source = 'other' const route = new Route(1, this.WEB3_URL) let res = await route.MakeRoute(fromToken, toToken, fromAmount, slippage, assetTo, deadline, source) return res } /** * @notice 判断Swap的token是否需要授权 * @param fromToken {"address"} * @param addr 用户地址 */ public async ApproveJudge( fromToken: { address: string; }, addr: string, targetAddr: string, web3Provider: any = null ) { const web3 = new Web3(web3Provider || new Web3.providers.HttpProvider(this.WEB3_URL)); if (fromToken.address == this.ETH_ADDRESS) return -1; const erc20Token = new web3.eth.Contract(ERC20_ABI['default'], fromToken.address); let allowanceAmount = await erc20Token.methods.allowance(addr, targetAddr).call(); return allowanceAmount; } /** * @notice ERC20 Token 交易前授权 * @param fromToken {"symbol","name","decimals","address"} * @param targetAddr 授权合约地址 * @param approveAmount hex 16进制字符串数值 */ public async ApproveHandle( fromToken: { address: string; }, targetAddr: string, approveAmount: string, web3Provider: any = null ) { const web3 = new Web3(web3Provider || new Web3.providers.HttpProvider(this.WEB3_URL)); const erc20Token = new web3.eth.Contract(ERC20_ABI['default'], fromToken.address); let data = await erc20Token.methods.approve(targetAddr, approveAmount).encodeABI(); return data; } } export const DODO_V1_TOKENLIST = [ "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", /*ETH*/ "0x43Dfc4159D86F3A37A5A4B3D4580b888ad7d4DDd", /*DODO*/ "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", /*WETH*/ "0xdAC17F958D2ee523a2206206994597C13D831ec7", /*USDT*/ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", /*USDC*/ "0xa0afAA285Ce85974c3C881256cB7F225e3A1178a", /*wCRES*/ "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", /*WBTC*/ "0x514910771AF9Ca656af840dff83E8264EcF986CA", /*LINK*/ "0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F", /*SNX*/ "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9", /*AAVE*/ "0xc00e94Cb662C3520282E6f5717214004A7f26888", /*COMP*/ "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e", /*YFI*/ "0x4691937a7508860F876c9c0a2a617E7d9E945D4B", /*WOO*/ "0x054f76beED60AB6dBEb23502178C52d6C5dEbE40", /*FIN*/ ]