From b6b094acb3ec682538d04a465270e5e05a33078c Mon Sep 17 00:00:00 2001 From: Moody Salem Date: Thu, 7 May 2020 14:36:26 -0400 Subject: [PATCH] remove unused functions, typescript (#725) * TypeScript in the utils directory, README fixes * Remove unused methods * Added unnecessary space * Some env variable cleanup * Bug in change * Another file to ts --- .env.local.example | 3 +- README.md | 10 +- netlify.toml | 8 +- package.json | 10 +- src/components/ExchangePage/index.tsx | 2 +- src/connectors/index.js | 5 +- src/{i18n.js => i18n.ts} | 0 src/{index.js => index.tsx} | 21 ++-- src/utils/{index.js => index.ts} | 142 ++++++++++---------------- src/utils/math.js | 49 --------- src/utils/signer.js | 36 ------- src/utils/signer.ts | 44 ++++++++ yarn.lock | 8 +- 13 files changed, 129 insertions(+), 209 deletions(-) rename src/{i18n.js => i18n.ts} (100%) rename src/{index.js => index.tsx} (81%) rename src/utils/{index.js => index.ts} (60%) delete mode 100644 src/utils/math.js delete mode 100644 src/utils/signer.js create mode 100644 src/utils/signer.ts diff --git a/.env.local.example b/.env.local.example index 939ddb0fd8..c1d77bea00 100644 --- a/.env.local.example +++ b/.env.local.example @@ -1,5 +1,4 @@ REACT_APP_CHAIN_ID="1" REACT_APP_NETWORK_URL="" REACT_APP_PORTIS_ID="" -REACT_APP_FORTMATIC_KEY="" -REACT_APP_IS_PRODUCTION_DEPLOY="false" \ No newline at end of file +REACT_APP_FORTMATIC_KEY="" \ No newline at end of file diff --git a/README.md b/README.md index 1d7129e4c9..76f099cddc 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ This an an open source interface for Uniswap - a protocol for decentralized exchange of Ethereum tokens. -- Website: [uniswap.io](https://uniswap.io/) -- Docs: [docs.uniswap.io](https://docs.uniswap.io/) -- Twitter: [@UniswapExchange](https://twitter.com/UniswapExchange) -- Reddit: [/r/Uniswap](https://www.reddit.com/r/UniSwap/) -- Email: [contact@uniswap.io](mailto:contact@uniswap.io) +- Website: [uniswap.org](https://uniswap.org/) +- Docs: [uniswap.org/docs/](https://uniswap.org/docs/) +- Twitter: [@UniswapProtocol](https://twitter.com/UniswapProtocol) +- Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/) +- Email: [contact@uniswap.org](mailto:contact@uniswap.org) - Discord: [Uniswap](https://discord.gg/Y7TF6QA) - Whitepaper: [Link](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig) diff --git a/netlify.toml b/netlify.toml index 1b86a0b0aa..68c7fa6cfe 100644 --- a/netlify.toml +++ b/netlify.toml @@ -14,7 +14,11 @@ status = 200 [build.environment] - REACT_APP_IS_PRODUCTION_DEPLOY = "false" + REACT_APP_GOOGLE_ANALYTICS_ID = "UA-128182339-1" + REACT_APP_NETWORK_URL = "https://mainnet.infura.io/v3/b8800ce81b8c451698081d269b86692b" [context.production.environment] - REACT_APP_IS_PRODUCTION_DEPLOY = "true" + REACT_APP_CHAIN_ID = "1" + REACT_APP_NETWORK_URL = "https://mainnet.infura.io/v3/2acb2baa4c06402792e0c701a3697d10" + REACT_APP_FORTMATIC_KEY = "pk_live_F937DF033A1666BF" + REACT_APP_PORTIS_ID = "c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236" diff --git a/package.json b/package.json index 49c5770b5d..8a08a36e2f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@types/node": "^13.7.4", "@types/react": "^16.9.21", "@types/react-dom": "^16.9.5", - "@uniswap/sdk": "^2.0.1", + "@uniswap/sdk": "^2.0.3", "@uniswap/v2-core": "1.0.0", "@uniswap/v2-periphery": "1.0.0-beta.0", "@web3-react/core": "^6.0.2", @@ -32,6 +32,7 @@ "i18next-xhr-backend": "^2.0.1", "jazzicon": "^1.5.0", "polished": "^3.3.2", + "prettier": "^1.17.0", "qrcode.react": "^0.9.3", "react": "^16.8.6", "react-device-detect": "^1.6.2", @@ -78,8 +79,5 @@ "last 1 safari version" ] }, - "license": "GPL-3.0-or-later", - "devDependencies": { - "prettier": "^1.17.0" - } -} + "license": "GPL-3.0-or-later" +} \ No newline at end of file diff --git a/src/components/ExchangePage/index.tsx b/src/components/ExchangePage/index.tsx index 6cfbc6b437..1e401e21b3 100644 --- a/src/components/ExchangePage/index.tsx +++ b/src/components/ExchangePage/index.tsx @@ -595,7 +595,7 @@ function ExchangePage({ sendingInput = false, history, params }) { // get token contract if needed let estimate: Function, method: Function, args, value if (tokens[Field.INPUT] === WETH[chainId]) { - signer + (signer as any) .sendTransaction({ to: recipient.toString(), value: hex(parsedAmounts[Field.INPUT].raw) }) .then(response => { setTxHash(response.hash) diff --git a/src/connectors/index.js b/src/connectors/index.js index 9751486514..84286a31d5 100644 --- a/src/connectors/index.js +++ b/src/connectors/index.js @@ -7,10 +7,7 @@ import { NetworkConnector } from './Network' import { FortmaticConnector } from './Fortmatic' const POLLING_INTERVAL = 10000 -const NETWORK_URL = - process.env.REACT_APP_IS_PRODUCTION_DEPLOY === 'true' - ? process.env.REACT_APP_NETWORK_URL_PROD - : process.env.REACT_APP_NETWORK_URL +const NETWORK_URL = process.env.REACT_APP_NETWORK_URL export const network = new NetworkConnector({ urls: { [Number(process.env.REACT_APP_CHAIN_ID)]: NETWORK_URL }, diff --git a/src/i18n.js b/src/i18n.ts similarity index 100% rename from src/i18n.js rename to src/i18n.ts diff --git a/src/index.js b/src/index.tsx similarity index 81% rename from src/index.js rename to src/index.tsx index 2aea78d1fe..e1c74e2c4e 100644 --- a/src/index.js +++ b/src/index.tsx @@ -3,6 +3,7 @@ import ReactDOM from 'react-dom' import ReactGA from 'react-ga' import { Web3ReactProvider, createWeb3ReactRoot } from '@web3-react/core' import { ethers } from 'ethers' +import { Web3Provider } from 'ethers/providers' import { NetworkContextName } from './constants' import { isMobile } from 'react-device-detect' @@ -19,19 +20,19 @@ import './i18n' const Web3ProviderNetwork = createWeb3ReactRoot(NetworkContextName) -function getLibrary(provider) { +function getLibrary(provider): Web3Provider { const library = new ethers.providers.Web3Provider(provider) library.pollingInterval = 10000 return library } if (process.env.NODE_ENV === 'production') { - ReactGA.initialize('UA-128182339-1') + ReactGA.initialize(process.env.REACT_APP_GOOGLE_ANALYTICS_ID) ReactGA.set({ - customBrowserType: !isMobile ? 'desktop' : window.web3 || window.ethereum ? 'mobileWeb3' : 'mobileRegular' + customBrowserType: !isMobile ? 'desktop' : 'web3' in window || 'ethereum' in window ? 'mobileWeb3' : 'mobileRegular' }) } else { - ReactGA.initialize('test', { testMode: true }) + ReactGA.initialize('test', { testMode: true, debug: true }) } ReactGA.pageview(window.location.pathname + window.location.search) @@ -57,9 +58,9 @@ function ContextProviders({ children }) { function Updaters() { return ( <> - - - + + + ) } @@ -68,11 +69,11 @@ ReactDOM.render( - + <> - - + + diff --git a/src/utils/index.js b/src/utils/index.ts similarity index 60% rename from src/utils/index.js rename to src/utils/index.ts index b940f73150..413ef5809d 100644 --- a/src/utils/index.js +++ b/src/utils/index.ts @@ -1,30 +1,27 @@ -import { ethers } from 'ethers' - -import IUniswapV2Pair from '@uniswap/v2-core/build/IUniswapV2Pair.json' -import IUniswapV2Router01 from '@uniswap/v2-periphery/build/IUniswapV2Router01.json' - -import ERC20_ABI from '../constants/abis/erc20' -import ERC20_BYTES32_ABI from '../constants/abis/erc20_bytes32' -import { SUPPORTED_THEMES, ROUTER_ADDRESS } from '../constants' -import { bigNumberify, keccak256, defaultAbiCoder, toUtf8Bytes, solidityPack } from 'ethers/utils' - -import UncheckedJsonRpcSigner from './signer' import { WETH } from '@uniswap/sdk' -export const ERROR_CODES = ['TOKEN_NAME', 'TOKEN_SYMBOL', 'TOKEN_DECIMALS'].reduce( - (accumulator, currentValue, currentIndex) => { - accumulator[currentValue] = currentIndex - return accumulator - }, - {} -) +import {abi as IUniswapV2PairABI} from '@uniswap/v2-core/build/IUniswapV2Pair.json' +import { abi as IUniswapV2Router01ABI } from '@uniswap/v2-periphery/build/IUniswapV2Router01.json' +import { Contract, ethers, Signer } from 'ethers' +import { JsonRpcProvider, Provider } from 'ethers/providers' +import { ROUTER_ADDRESS, SUPPORTED_THEMES } from '../constants' + +import ERC20_ABI from '../constants/abis/erc20.json' +import ERC20_BYTES32_ABI from '../constants/abis/erc20_bytes32.json' + +import UncheckedJsonRpcSigner from './signer' + +export enum ERROR_CODES { + TOKEN_SYMBOL = 1, + TOKEN_DECIMALS = 2 +} export function safeAccess(object, path) { return object ? path.reduce( - (accumulator, currentValue) => (accumulator && accumulator[currentValue] ? accumulator[currentValue] : null), - object - ) + (accumulator, currentValue) => (accumulator && accumulator[currentValue] ? accumulator[currentValue] : null), + object + ) : null } @@ -55,26 +52,36 @@ export function getQueryParam(windowLocation, name) { return q && q[1] } -export function getAllQueryParams() { - let params = {} +function parseUrlAddress(param: string): string { + const addr = isAddress(getQueryParam(window.location, param)) + if (addr === false) { + return '' + } + return addr +} - params.inputTokenAddress = isAddress(getQueryParam(window.location, 'inputTokenAddress')) - ? isAddress(getQueryParam(window.location, 'inputTokenAddress')) - : '' +function parseUrlTokenAmount(paramName: string): string { + const value = getQueryParam(window.location, paramName) + if (!isNaN(Number(value))) { + return '' + } + return value +} - params.outputTokenAddress = isAddress(getQueryParam(window.location, 'outputTokenAddress')) - ? isAddress(getQueryParam(window.location, 'outputTokenAddress')) - : '' +interface QueryParams { + readonly inputTokenAddress: string + readonly outputTokenAddress: string + readonly inputTokenAmount: string + readonly outputTokenAmount: string +} - params.inputTokenAmount = !isNaN(Number(getQueryParam(window.location, 'inputTokenAmount'))) - ? getQueryParam(window.location, 'inputTokenAmount') - : '' - - params.outputTokenAmount = !isNaN(Number(getQueryParam(window.location, 'outputTokenAmount'))) - ? getQueryParam(window.location, 'outputTokenAmount') - : '' - - return params +export function getAllQueryParams(): QueryParams { + return { + inputTokenAddress: parseUrlAddress('inputTokenAddress'), + outputTokenAddress: parseUrlAddress('outputTokenAddress'), + inputTokenAmount: parseUrlTokenAmount('inputTokenAmount'), + outputTokenAmount: parseUrlTokenAmount('outputTokenAmount'), + } } export function checkSupportedTheme(themeName) { @@ -118,7 +125,7 @@ export function shortenTransactionHash(hash, digits = 4) { return `${hash.substring(0, digits + 2)}...${hash.substring(66 - digits)}` } -export function isAddress(value) { +export function isAddress(value): string | false { try { return ethers.utils.getAddress(value.toLowerCase()) } catch { @@ -135,12 +142,12 @@ export function calculateGasMargin(value, margin) { } // account is optional -export function getProviderOrSigner(library, account) { +export function getProviderOrSigner(library: JsonRpcProvider, account?: string): Signer | Provider { return account ? new UncheckedJsonRpcSigner(library.getSigner(account)) : library } // account is optional -export function getContract(address, ABI, library, account) { +export function getContract(address: string, ABI: any, library: JsonRpcProvider, account?: string): Contract { if (!isAddress(address) || address === ethers.constants.AddressZero) { throw Error(`Invalid 'address' parameter '${address}'.`) } @@ -150,13 +157,12 @@ export function getContract(address, ABI, library, account) { // account is optional export function getRouterContract(chainId, library, account) { - const router = getContract(ROUTER_ADDRESS, IUniswapV2Router01.abi, library, account) - return router + return getContract(ROUTER_ADDRESS, IUniswapV2Router01ABI, library, account) } // account is optional export function getExchangeContract(pairAddress, library, account) { - return getContract(pairAddress, IUniswapV2Pair.abi, library, account) + return getContract(pairAddress, IUniswapV2PairABI, library, account) } // get token name @@ -231,58 +237,14 @@ export async function getTokenBalance(tokenAddress, address, library) { export async function getTokenAllowance(address, tokenAddress, spenderAddress, library) { if (!isAddress(address) || !isAddress(tokenAddress) || !isAddress(spenderAddress)) { throw Error( - "Invalid 'address' or 'tokenAddress' or 'spenderAddress' parameter" + - `'${address}' or '${tokenAddress}' or '${spenderAddress}'.` + 'Invalid \'address\' or \'tokenAddress\' or \'spenderAddress\' parameter' + + `'${address}' or '${tokenAddress}' or '${spenderAddress}'.` ) } return getContract(tokenAddress, ERC20_ABI, library).allowance(address, spenderAddress) } -const PERMIT_TYPEHASH = keccak256( - toUtf8Bytes('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)') -) - -export function expandTo18Decimals(n) { - return bigNumberify(n).mul(bigNumberify(10).pow(18)) -} - -function getDomainSeparator(name, tokenAddress) { - return keccak256( - defaultAbiCoder.encode( - ['bytes32', 'bytes32', 'bytes32', 'uint256', 'address'], - [ - keccak256(toUtf8Bytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')), - keccak256(toUtf8Bytes(name)), - keccak256(toUtf8Bytes('1')), - 1, - tokenAddress - ] - ) - ) -} - -export async function getApprovalDigest(token, approve, nonce, deadline) { - const name = await token.name() - const DOMAIN_SEPARATOR = getDomainSeparator(name, token.address) - return keccak256( - solidityPack( - ['bytes1', 'bytes1', 'bytes32', 'bytes32'], - [ - '0x19', - '0x01', - DOMAIN_SEPARATOR, - keccak256( - defaultAbiCoder.encode( - ['bytes32', 'address', 'address', 'uint256', 'uint256', 'uint256'], - [PERMIT_TYPEHASH, approve.owner, approve.spender, approve.value, nonce, deadline] - ) - ) - ] - ) - ) -} - export function isWETH(token) { if (token && token.address === WETH[token.chainId].address) { return true diff --git a/src/utils/math.js b/src/utils/math.js deleted file mode 100644 index ba709c8238..0000000000 --- a/src/utils/math.js +++ /dev/null @@ -1,49 +0,0 @@ -import { BigNumber } from '@uniswap/sdk' - -// returns a deep copied + sorted list of values, as well as a sortmap -export function sortBigNumbers(values) { - const valueMap = values.map((value, i) => ({ value, i })) - - valueMap.sort((a, b) => { - if (a.value.isGreaterThan(b.value)) { - return 1 - } else if (a.value.isLessThan(b.value)) { - return -1 - } else { - return 0 - } - }) - - return [ - valueMap.map(element => values[element.i]), - values.map((_, i) => valueMap.findIndex(element => element.i === i)) - ] -} - -export function getMedian(values) { - const [sortedValues, sortMap] = sortBigNumbers(values) - if (values.length % 2 === 0) { - const middle = values.length / 2 - const indices = [middle - 1, middle] - return [ - sortedValues[middle - 1].plus(sortedValues[middle]).dividedBy(2), - sortMap.map(element => (indices.includes(element) ? new BigNumber(0.5) : new BigNumber(0))) - ] - } else { - const middle = Math.floor(values.length / 2) - return [sortedValues[middle], sortMap.map(element => (element === middle ? new BigNumber(1) : new BigNumber(0)))] - } -} - -export function getMean(values, _weights) { - const weights = _weights ? _weights : values.map(() => new BigNumber(1)) - - const weightedValues = values.map((value, i) => value.multipliedBy(weights[i])) - const numerator = weightedValues.reduce( - (accumulator, currentValue) => accumulator.plus(currentValue), - new BigNumber(0) - ) - const denominator = weights.reduce((accumulator, currentValue) => accumulator.plus(currentValue), new BigNumber(0)) - - return [numerator.dividedBy(denominator), weights.map(weight => weight.dividedBy(denominator))] -} diff --git a/src/utils/signer.js b/src/utils/signer.js deleted file mode 100644 index 738b6e797c..0000000000 --- a/src/utils/signer.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as ethers from 'ethers' - -export default class UncheckedJsonRpcSigner extends ethers.Signer { - constructor(signer) { - super() - ethers.utils.defineReadOnly(this, 'signer', signer) - ethers.utils.defineReadOnly(this, 'provider', signer.provider) - } - - getAddress() { - return this.signer.getAddress() - } - - sendTransaction(transaction) { - return this.signer.sendUncheckedTransaction(transaction).then(hash => { - return { - hash: hash, - nonce: null, - gasLimit: null, - gasPrice: null, - data: null, - value: null, - chainId: null, - confirmations: 0, - from: null, - wait: confirmations => { - return this.signer.provider.waitForTransaction(hash, confirmations) - } - } - }) - } - - signMessage(message) { - return this.signer.signMessage(message) - } -} diff --git a/src/utils/signer.ts b/src/utils/signer.ts new file mode 100644 index 0000000000..de078c4e82 --- /dev/null +++ b/src/utils/signer.ts @@ -0,0 +1,44 @@ +import { Signer } from 'ethers' +import { JsonRpcSigner, Provider } from 'ethers/providers' +import { TransactionResponse } from 'ethers/providers/abstract-provider' + +/** + * Wraps a JsonRpcSigner and replaces `sendTransaction` with `sendUncheckedTransaction` + */ +export default class UncheckedJsonRpcSigner extends Signer { + private readonly signer: JsonRpcSigner + public readonly provider: Provider + + constructor(signer: JsonRpcSigner) { + super() + this.signer = signer + this.provider = signer.provider + } + + getAddress(): Promise { + return this.signer.getAddress() + } + + sendTransaction(transaction): Promise { + return this.signer.sendUncheckedTransaction(transaction).then(hash => { + return { + hash, + nonce: null, + gasLimit: null, + gasPrice: null, + data: null, + value: null, + chainId: null, + confirmations: 0, + from: null, + wait: confirmations => { + return this.signer.provider.waitForTransaction(hash, confirmations) + } + } + }) + } + + signMessage(message) { + return this.signer.signMessage(message) + } +} diff --git a/yarn.lock b/yarn.lock index 607d57c46b..c2933dbe3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2455,10 +2455,10 @@ resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-1.1.1.tgz#0afd29601846c16e5d082866cbb24a9e0758e6bc" integrity sha512-2yK7sLpKIT91TiS5sewHtOa7YuM8IuBXVl4GZv2jZFys4D2sY7K5vZh6MqD25TPA95Od+0YzCVq6cTF2IKrOmg== -"@uniswap/sdk@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@uniswap/sdk/-/sdk-2.0.1.tgz#191fdf0a49bc31c44ae429a1757380b83e22dd5f" - integrity sha512-F5SAWhGPPi4tgFTL0Gl3mtLSFkR/Tz/w35Aib5jpC1ti4AHwPWt4ReXMm7ucrvtXZlWmiBHPplNxsIIm1Z5aqQ== +"@uniswap/sdk@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@uniswap/sdk/-/sdk-2.0.3.tgz#a9ec8059d40d8ccd49183938bec5f194018336af" + integrity sha512-Re2fFehHtA8KBAD+PxUEah94Rgtm4A516jP+AcGiJ5dVUp8MzkR59RMqoEW6NX4lR8calwl9YwKOhnmLiUY9jQ== dependencies: "@ethersproject/address" "^5.0.0-beta.134" "@ethersproject/contracts" "^5.0.0-beta.143"