UNPKG

ufomarketplace-sdk-new

Version:

SDK to interact with set ufo marketplace contracts

416 lines (367 loc) 13.8 kB
import { RPCS, NETWORK_ID, USDT_ADDR, WBEAM_ADDR, ROUTER_ADDR, WETH_ADDR, USDC_ADDR, COIN_ADDR, } from './constants/constants'; import { ethers, ContractTransaction, Contract, Signer, BigNumber } from 'ethers'; import { BigNumber as DecimalBigNumber } from 'bignumber.js'; import { BaseProvider } from '@ethersproject/providers'; import { ChainId, WETH, Fetcher, Route, Token } from 'quickswap-sdk'; import ERC20 from './abis/ERC20.json'; import EVENTS from './abis/Events.json'; import ROUTER from './abis/UniswapV2Router02.json'; import axios from 'axios'; import _ from 'underscore'; const MAX_INT = BigNumber.from('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); const priceOracleUrl: string = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2'; const wethAddr: string = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'; const ufoAddr: string = '0x249e38ea4102d0cf8264d3701f1a0e39c4f2dc3b'; export async function getWBEAMPrice(): Promise<string> { let rpcAddr: string, usdtAddr: string, wBeamAddr: string; rpcAddr = RPCS[NETWORK_ID.BEAM]; usdtAddr = USDT_ADDR[NETWORK_ID.BEAM]; wBeamAddr = WBEAM_ADDR[NETWORK_ID.BEAM]; return getTokenPrice(rpcAddr, usdtAddr, 6, wBeamAddr, 18, NETWORK_ID.BEAM); } export async function getWETHPrice(): Promise<string> { return getWETHPriceFromUniswap(); } export async function getWETHPriceFromUniswap(): Promise<string> { let price = await getPrice(priceOracleUrl, wethAddr); return price.toString(); } export async function getUfoPrice(): Promise<string> { let ethUfoPrice = await getPriceETHUFO(priceOracleUrl, ufoAddr); let price = await getPrice(priceOracleUrl, wethAddr); return DecimalBigNumber(ethUfoPrice).multipliedBy(price).toFixed(9); } export async function getMaticPriceFromUniswap(): Promise<string> { let ufoAddr: string = '0x7c9f4c87d911613fe9ca58b579f737911aad2d43'; let price = await getPrice(priceOracleUrl, ufoAddr); return price.toString(); } async function fetchData(requestData: { url; body; headers }): Promise<any> { const { data } = await axios.post(requestData.url, requestData.body, { headers: requestData.headers }); return data; } async function getPriceETHUFO(url, address: string): Promise<DecimalBigNumber> { address = address.toLowerCase(); const data = JSON.stringify({ query: ` { price0: pairs(where:{ token0: "${address}", token1_in : [ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", ] }, orderBy: volumeUSD, orderDirection: desc, first: 1) { token1Price volumeUSD } price1: pairs(where:{ token1: "${address}", token0_in : [ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", ] }, orderBy: volumeUSD, orderDirection: desc, first: 1) { token0Price volumeUSD } } `, }); const options = { url, headers: { 'Content-Type': 'application/json' }, body: data, }; const result = await fetchData(options); if (!result) { throw new Error('Error while fetching data from subgraph'); } if (result.errors) { throw new Error('Error while fetching data from subgraph'); } let price: DecimalBigNumber = DecimalBigNumber(0); if (result.data.price0 && result.data.price0.length != 0) { price = result.data.price0[0].token1Price; } if (result.data.price1 && result.data.price1.length != 0) { price = result.data.price1[0].token0Price; } if (result.data.price0 && result.data.price1 && result.data.price0.length != 0 && result.data.price1.length != 0) { const volume0 = DecimalBigNumber(result.data.price0[0].volumeUSD); const volume1 = DecimalBigNumber(result.data.price1[0].volumeUSD); if (volume0.gt(volume1)) { price = result.data.price0[0].token1Price; } } return price; } async function getPrice(url, address: string): Promise<DecimalBigNumber> { address = address.toLowerCase(); const data = JSON.stringify({ query: ` { price0: pairs(where:{ token0: "${address}", token1_in : [ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "0xdac17f958d2ee523a2206206994597c13d831ec7", "0x6b175474e89094c44da98b954eedeac495271d0f" ] }, orderBy: volumeUSD, orderDirection: desc, first: 1) { token1Price volumeUSD } price1: pairs(where:{ token1: "${address}", token0_in : [ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "0xdac17f958d2ee523a2206206994597c13d831ec7", "0x6b175474e89094c44da98b954eedeac495271d0f" ] }, orderBy: volumeUSD, orderDirection: desc, first: 1) { token0Price volumeUSD } } `, }); const options = { url, headers: { 'Content-Type': 'application/json' }, body: data, }; const result = await fetchData(options); if (!result) { throw new Error('Error while fetching data from subgraph'); } if (result.errors) { throw new Error('Error while fetching data from subgraph'); } let price: DecimalBigNumber = DecimalBigNumber(0); if (result.data.price0 && result.data.price0.length != 0) { price = result.data.price0[0].token1Price; } if (result.data.price1 && result.data.price1.length != 0) { price = result.data.price1[0].token0Price; } if (result.data.price0 && result.data.price1 && result.data.price0.length != 0 && result.data.price1.length != 0) { const volume0 = DecimalBigNumber(result.data.price0[0].volumeUSD); const volume1 = DecimalBigNumber(result.data.price1[0].volumeUSD); if (volume0.gt(volume1)) { price = result.data.price0[0].token1Price; } } return price; } export async function getToken1Token2Rate(networkId: number, token1: string, token2: string): Promise<string> { let rpcAddr: string, token1Addr: string, token2Addr: string; rpcAddr = RPCS[networkId]; token1Addr = COIN_ADDR[token1][networkId]; token2Addr = COIN_ADDR[token2][networkId]; return getTokenPrice( rpcAddr, token2Addr, COIN_ADDR[token2]['decimal'], token1Addr, COIN_ADDR[token1]['decimal'], networkId ); } export async function getTokenBalance(networkId: number, token: string, wallet: string): Promise<string> { let rpcAddr: string, tokenAddr: string; rpcAddr = RPCS[networkId]; tokenAddr = COIN_ADDR[token][networkId]; const provider = ethers.providers.getDefaultProvider(rpcAddr); const cryptoContract = new Contract(tokenAddr, ERC20.abi, provider); try { const balance = await cryptoContract.balanceOf(wallet); return ethers.utils.formatUnits(balance.toString(), COIN_ADDR[token]['decimal']).toString(); } catch (e) { console.log(e); return '0'; } } async function getTokenPrice( rpcProvider, sourceAddr, sourceDecimal, destination, destDecimal, networkId ): Promise<string> { const provider = ethers.providers.getDefaultProvider(rpcProvider); const token1 = new Token(networkId, sourceAddr, sourceDecimal); const token2 = new Token(networkId, destination, destDecimal); try { const pair = await Fetcher.fetchPairData(token1, token2, provider); const route = new Route([pair], token2); return route.midPrice.toSignificant(6); } catch (e) { console.log('get Token price error', e); return '0'; } } export async function swapForExactOutput( amountOut: string, networkId: number, signer: Signer, inputTokenType: string, outputTokenType: string ): Promise<ContractTransaction> { let sourceTokenAddr, destTokenAddr; sourceTokenAddr = COIN_ADDR[inputTokenType][networkId]; destTokenAddr = COIN_ADDR[outputTokenType][networkId]; const routerContract = new Contract(ROUTER_ADDR[networkId], ROUTER.abi, signer); const address = await signer.getAddress(); return swapExactOutputTokens(sourceTokenAddr, destTokenAddr, amountOut, routerContract, address, signer); } export async function getAmountOut( amountIn: string, networkId: number, signer: Signer, inputTokenType: string, outputTokenType: string ): Promise<string> { let sourceTokenAddr, destTokenAddr; sourceTokenAddr = COIN_ADDR[inputTokenType][networkId]; destTokenAddr = COIN_ADDR[outputTokenType][networkId]; const routerContract = new Contract(ROUTER_ADDR[networkId], ROUTER.abi, signer); const tokens = [sourceTokenAddr, destTokenAddr]; const amountOut = await routerContract.callStatic.getAmountsOut(amountIn, tokens); return amountOut[1]; } export async function getAmountIn( amountOut: string, networkId: number, signer: Signer, inputTokenType: string, outputTokenType: string ): Promise<string> { let sourceTokenAddr, destTokenAddr; sourceTokenAddr = COIN_ADDR[inputTokenType][networkId]; destTokenAddr = COIN_ADDR[outputTokenType][networkId]; const routerContract = new Contract(ROUTER_ADDR[networkId], ROUTER.abi, signer); const tokens = [sourceTokenAddr, destTokenAddr]; const amountIn = await routerContract.callStatic.getAmountsIn(amountOut, tokens); return amountIn[1]; } export async function swapForExactInput( amountIn: string, networkId: number, signer: Signer, inputTokenType: string, outputTokenType: string ): Promise<ContractTransaction> { let sourceTokenAddr, destTokenAddr; sourceTokenAddr = COIN_ADDR[inputTokenType][networkId]; destTokenAddr = COIN_ADDR[outputTokenType][networkId]; const routerContract = new Contract(ROUTER_ADDR[networkId], ROUTER.abi, signer); const address = await signer.getAddress(); return swapExactInputTokens(sourceTokenAddr, destTokenAddr, amountIn, routerContract, address, signer); } export async function approveTokenToRouter( tokenType: string, networkId: number, signer: Signer ): Promise<ContractTransaction> { let tokenAddr = COIN_ADDR[tokenType][networkId]; const token1 = new Contract(tokenAddr, ERC20.abi, signer); return await token1.approve(ROUTER_ADDR[networkId], MAX_INT); } async function swapExactInputTokens( address1, address2, amountExactInput, routerContract, accountAddress, signer ): Promise<ContractTransaction> { const tokens = [address1, address2]; const time = Math.floor(Date.now() / 1000) + 200000; const deadline = ethers.BigNumber.from(time); const token1 = new Contract(address1, ERC20.abi, signer); const tokenDecimals = await getDecimals(token1); const amountIn = ethers.utils.parseUnits(amountExactInput, tokenDecimals); const amountOut = await routerContract.callStatic.getAmountsOut(amountIn, tokens); const wMaticAddress = await routerContract.WETH(); if (address1 === wMaticAddress) { // Eth -> Token return await routerContract.swapExactETHForTokens(amountOut[1], tokens, accountAddress, deadline, { value: amountIn, }); } else if (address2 === wMaticAddress) { // Token -> Eth return await routerContract.swapExactTokensForETH(amountIn, amountOut[1], tokens, accountAddress, deadline); } else { return await routerContract.swapExactTokensForTokens(amountIn, amountOut[1], tokens, accountAddress, deadline); } } async function swapExactOutputTokens( address1, address2, amountExactOut, routerContract, accountAddress, signer ): Promise<ContractTransaction> { const tokens = [address1, address2]; const time = Math.floor(Date.now() / 1000) + 200000; const deadline = ethers.BigNumber.from(time); const token2 = new Contract(address2, ERC20.abi, signer); const tokenDecimals = await getDecimals(token2); const amountOut = ethers.utils.parseUnits(amountExactOut, tokenDecimals); const amountIn = await routerContract.callStatic.getAmountsIn(amountOut, tokens); const wethAddress = await routerContract.WETH(); if (address1 === wethAddress) { // Eth -> Token return await routerContract.swapETHForExactTokens(amountOut, tokens, accountAddress, deadline, { value: amountIn[0], }); } else if (address2 === wethAddress) { // Token -> Eth return await routerContract.swapTokensForExactETH(amountIn[0], amountOut, tokens, accountAddress, deadline); } else { return await routerContract.swapTokensForExactTokens(amountIn[0], amountOut, tokens, accountAddress, deadline); } } async function getDecimals(token) { const decimals = await token .decimals() .then((result) => { return result; }) .catch((error) => { console.log('No tokenDecimals function for this token, set to 0'); return 0; }); return decimals; } export function getNftIdsFromTx(eventName: string, logs: ethers.Event[] | undefined): any[] { let ret = []; let iface = new ethers.utils.Interface(EVENTS); logs.forEach((log) => { try { let data = iface.parseLog(log); if (data) { if (data.name == eventName && eventName == 'purchaseLootEvent') { ret.push(data.args.tokenIds); }else if (data.name == eventName && eventName == 'purchaseAndSendGiftEvent') { ret.push(data.args.tokenIds); } else if (data.name == eventName && eventName == 'mintGensisNFT') { ret.push(data.args.nftId); } else if (data.name == eventName && eventName == 'mintRandomGensisNFT') { ret.push(log.address.substring(2) + '0x' + data.args.nftId); } } } catch (e) {} }); return _.flatten(ret); }