From c2e37470e178789f167bdf510b1dca8d6aa0edb8 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Fri, 2 Jul 2021 01:13:00 -0300 Subject: [PATCH 01/78] Improve install docs --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c65f0de..abb4fb5 100644 --- a/README.md +++ b/README.md @@ -76,11 +76,15 @@ Add our forked Erigon git tree as an additional remote and checkout the correspo git remote add otterscan git@github.com:wmitsuda/erigon.git ``` -Checkout the `otterscan-develop` branch (be sure to check from which tag it is branched from to be sure it is a compatible branch). +Checkout the tag corresponding to the stable version you are running. For each supported Erigon version, there should be a corresponding tag containing Otterscan patches. + +For example, if you are running Erigon from `v2021.07.01` tag, checkout the tag `v2021.07.01-otterscan` and rebuild `rpcdaemon`. + +We intend to release a compatible rebased version containig our changes every week just after Erigon's weekly release, as time permits. ``` git fetch --all -git checkout otterscan-develop +git checkout ``` Build the patched `rpcdaemon` binary. @@ -107,11 +111,12 @@ Now you should have an Erigon node with Otterscan jsonrpc APIs enabled, running Make sure you have a working node 12/npm installation. -Clone Otterscan repo and its submodules. For now, only the default `develop` branch is available (it is alpha...). +Clone Otterscan repo and its submodules. Checkout the tag corresponding to your Erigon + Otterscan patches. It uses the same version tag from Erigon + Otterscan repo, i.e., if you built the `v2021.07.01-otterscan`, you should build the `v2021.07.01-otterscan` of Otterscan. ``` git clone --recurse-submodules git@github.com:wmitsuda/otterscan.git cd otterscan +git checkout npm install npm run build ``` From 62df32b82f0462f07ab799eef9566fb2fb62a194 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Fri, 2 Jul 2021 16:05:18 -0300 Subject: [PATCH 02/78] Initial ENS support for resolving names -> address on search --- src/AddressTransactions.tsx | 66 ++++++++++++++++++++++++++++--------- src/App.tsx | 2 +- src/Search.tsx | 3 +- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/AddressTransactions.tsx b/src/AddressTransactions.tsx index a598cc8..762356f 100644 --- a/src/AddressTransactions.tsx +++ b/src/AddressTransactions.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useMemo } from "react"; import { useParams, useLocation, useHistory } from "react-router-dom"; +import { ethers } from "ethers"; import queryString from "query-string"; import Blockies from "react-blockies"; import StandardFrame from "./StandardFrame"; @@ -12,10 +13,10 @@ import PendingResults from "./search/PendingResults"; import TransactionItem from "./search/TransactionItem"; import { SearchController } from "./search/search"; import { useFeeToggler } from "./search/useFeeToggler"; -import { ethers } from "ethers"; +import { provider } from "./ethersconfig"; type BlockParams = { - address: string; + addressOrName: string; direction?: string; }; @@ -33,13 +34,33 @@ const AddressTransactions: React.FC = () => { hash = qs.h as string; } - // Normalize to checksummed address - const checksummedAddress = useMemo( - () => ethers.utils.getAddress(params.address), - [params.address] - ); - if (params.address !== checksummedAddress) { - console.log("NORMALIZE"); + const [checksummedAddress, setChecksummedAddress] = useState(); + const [isENS, setENS] = useState(); + + // If it looks like it is an ENS name, try to resolve it + useEffect(() => { + if (ethers.utils.isAddress(params.addressOrName)) { + // Normalize to checksummed address + setChecksummedAddress(ethers.utils.getAddress(params.addressOrName)); + return; + } + + const resolveName = async () => { + const resolvedAddress = await provider.resolveName(params.addressOrName); + if (resolvedAddress !== null) { + setENS(true); + setChecksummedAddress(resolvedAddress); + } + }; + resolveName(); + }, [params.addressOrName]); + + // Request came with a non-checksummed address; fix the URL + if ( + !isENS && + checksummedAddress && + params.addressOrName !== checksummedAddress + ) { history.replace( `/address/${checksummedAddress}${ params.direction ? "/" + params.direction : "" @@ -49,6 +70,10 @@ const AddressTransactions: React.FC = () => { const [controller, setController] = useState(); useEffect(() => { + if (!checksummedAddress) { + return; + } + const readFirstPage = async () => { const _controller = await SearchController.firstPage(checksummedAddress); setController(_controller); @@ -100,24 +125,33 @@ const AddressTransactions: React.FC = () => { const page = useMemo(() => controller?.getPage(), [controller]); - document.title = `Address ${params.address} | Otterscan`; + document.title = `Address ${params.addressOrName} | Otterscan`; const [feeDisplay, feeDisplayToggler] = useFeeToggler(); + if (!checksummedAddress) { + return <>; + } + return (
Address - {params.address} + {checksummedAddress} - + + {isENS && ( + + ENS: {params.addressOrName} + + )}
@@ -130,7 +164,7 @@ const AddressTransactions: React.FC = () => { )} { ))} @@ -159,7 +193,7 @@ const AddressTransactions: React.FC = () => { )} ( - + diff --git a/src/Search.tsx b/src/Search.tsx index 1fe081b..7b5adc3 100644 --- a/src/Search.tsx +++ b/src/Search.tsx @@ -27,7 +27,8 @@ const Search: React.FC = () => { return <>; } - history.replace("/"); + // Assume it is an ENS name + history.replace(`/address/${q}`); return <>; }; From 0c7cc1fc646c0ceec1c13ab0138f71d1d18da5dc Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Fri, 2 Jul 2021 16:20:50 -0300 Subject: [PATCH 03/78] Fix error handling --- src/AddressTransactions.tsx | 148 +++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 69 deletions(-) diff --git a/src/AddressTransactions.tsx b/src/AddressTransactions.tsx index 762356f..b7985fa 100644 --- a/src/AddressTransactions.tsx +++ b/src/AddressTransactions.tsx @@ -36,6 +36,7 @@ const AddressTransactions: React.FC = () => { const [checksummedAddress, setChecksummedAddress] = useState(); const [isENS, setENS] = useState(); + const [error, setError] = useState(); // If it looks like it is an ENS name, try to resolve it useEffect(() => { @@ -50,6 +51,9 @@ const AddressTransactions: React.FC = () => { if (resolvedAddress !== null) { setENS(true); setChecksummedAddress(resolvedAddress); + setError(false); + } else { + setError(true); } }; resolveName(); @@ -129,82 +133,88 @@ const AddressTransactions: React.FC = () => { const [feeDisplay, feeDisplayToggler] = useFeeToggler(); - if (!checksummedAddress) { - return <>; - } - return ( - -
- - Address - - {checksummedAddress} - - - {isENS && ( - - ENS: {params.addressOrName} - - )} -
-
- -
-
- {page === undefined ? ( - <>Waiting for search results... - ) : ( - <>{page.length} transactions on this page - )} -
- -
- - {controller ? ( + {error ? ( + + "{params.addressOrName}" is not an ETH address or ENS name. + + ) : ( + checksummedAddress && ( <> - {controller.getPage().map((tx) => ( - - ))} -
-
- {page !== undefined && ( - <>{page.length} transactions on this page + +
+ + Address + + {checksummedAddress} + + + {isENS && ( + + ENS: {params.addressOrName} + )}
- + +
+
+ {page === undefined ? ( + <>Waiting for search results... + ) : ( + <>{page.length} transactions on this page + )} +
+ +
+ -
+ {controller ? ( + <> + {controller.getPage().map((tx) => ( + + ))} +
+
+ {page !== undefined && ( + <>{page.length} transactions on this page + )} +
+ +
+ + ) : ( + + )} + - ) : ( - - )} - + ) + )} ); }; From 1965b8d3a6c7edc8ac39668c59da4ab2921ad6de Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Fri, 2 Jul 2021 16:22:43 -0300 Subject: [PATCH 04/78] Turn on autofocus in homepage --- src/Home.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Home.tsx b/src/Home.tsx index a67796a..ca99185 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -66,6 +66,7 @@ const Home: React.FC = () => { size={50} placeholder="Search by address / txn hash / block number" onChange={handleChange} + autoFocus >
diff --git a/src/ethersconfig.ts b/src/ethersconfig.ts index e0a9fd5..6b24d6d 100644 --- a/src/ethersconfig.ts +++ b/src/ethersconfig.ts @@ -1,6 +1,8 @@ import { ethers } from "ethers"; +export const ERIGON_NODE = "http://127.0.0.1:8545"; + export const provider = new ethers.providers.JsonRpcProvider( - "http://127.0.0.1:8545", + ERIGON_NODE, "mainnet" ); From 5ed8b96061fb8ff4b102ca59f1fba514ee4eda40 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 3 Jul 2021 23:04:30 -0300 Subject: [PATCH 21/78] Fix manifest error --- public/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/manifest.json b/public/manifest.json index af3a56e..e3828a9 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -6,10 +6,10 @@ "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" - }, + } ], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" -} +} \ No newline at end of file From dbde5c6aef7b1e8aaf94a9f9434765598aa98e76 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sun, 4 Jul 2021 01:54:03 -0300 Subject: [PATCH 22/78] Allow overriding Erigons's rpcdaemon URL fixes#8 --- README.md | 8 ++++++++ src/ethersconfig.ts | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 64b0e78..b0b0429 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,14 @@ npm install npm run build ``` +By default, it assumes your Erigon `rpcdaemon` processs is serving requests at http://127.0.0.1:8545. You can customize this URL by specifying the `REACT_APP_ERIGON_URL` environment variable at build time (it needs to be done at build time because the build process generates a static website). + +To do that, export the variable before running `npm run build`: + +``` +export REACT_APP_ERIGON_URL= +``` + ### Run it from the source First, a brief explanation about the app: diff --git a/src/ethersconfig.ts b/src/ethersconfig.ts index 6b24d6d..a7a98a1 100644 --- a/src/ethersconfig.ts +++ b/src/ethersconfig.ts @@ -1,6 +1,7 @@ import { ethers } from "ethers"; -export const ERIGON_NODE = "http://127.0.0.1:8545"; +export const ERIGON_NODE = + process.env.REACT_APP_ERIGON_URL || "http://127.0.0.1:8545"; export const provider = new ethers.providers.JsonRpcProvider( ERIGON_NODE, From f80b5526e831eebbca5d4052753f0774216179ad Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sun, 4 Jul 2021 02:17:21 -0300 Subject: [PATCH 23/78] Doc fixes --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index b0b0429..9b9a523 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Checkout the tag corresponding to the stable version you are running. For each s For example, if you are running Erigon from `v2021.07.01` tag, checkout the tag `v2021.07.01-otterscan` and rebuild `rpcdaemon`. -We intend to release a compatible rebased version containig our changes every week just after Erigon's weekly release, as time permits. +We intend to release a compatible rebased version containing our changes every week just after Erigon's weekly release, as time permits. ``` git fetch --all @@ -161,8 +161,6 @@ npm run serve Otterscan should now be running at http://localhost:5000/. -For now, it assumes the `rpcdaemon` is running on 127.0.0.1:8545. If for some reason your installation is running in another host/port, change it in the `src/ethersconfig.ts` file (patches to make it parameterized are welcome). - **You can make sure it is working correctly if the homepage is able to show the latest block/timestamp your Erigon node is at just bellow the search button.** ## Kudos From c254ebed2d029824e478f9c888cf39f8ca572bfe Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sun, 4 Jul 2021 19:39:14 -0300 Subject: [PATCH 24/78] Parsing fixes --- src/BlockTransactions.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index ef81025..d0bb9b8 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -60,10 +60,12 @@ const BlockTransactions: React.FC = () => { from: t.from, to: t.to, value: t.value, - fee: t.gasLimit.mul(t.gasPrice!), + fee: provider.formatter + .bigNumber(_receipts[i].gasUsed) + .mul(t.gasPrice!), gasPrice: t.gasPrice!, data: t.data, - status: _receipts[i].status, + status: provider.formatter.number(_receipts[i].status), }; }) .reverse() From 6dc6e63b9559e8542532d21878f160b0d5f98c13 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:03:01 -0300 Subject: [PATCH 25/78] Signal miner address on transaction page and blokc ktransaction list --- src/BlockTransactions.tsx | 1 + src/Transaction.tsx | 76 ++++++----------------------- src/components/InternalTransfer.tsx | 57 ++++++++++++++++++++++ src/search/TransactionItem.tsx | 22 ++++++--- src/types.ts | 54 +++++++++++++++++++- 5 files changed, 141 insertions(+), 69 deletions(-) create mode 100644 src/components/InternalTransfer.tsx diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index d0bb9b8..47be1a8 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -55,6 +55,7 @@ const BlockTransactions: React.FC = () => { return { blockNumber: blockNumber.toNumber(), timestamp: _block.timestamp, + miner: _block.miner, idx: i, hash: t.hash, from: t.from, diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 2d95833..da0d33d 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -5,7 +5,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheckCircle, faTimesCircle, - faAngleRight, faCaretRight, } from "@fortawesome/free-solid-svg-icons"; import { provider } from "./ethersconfig"; @@ -17,10 +16,18 @@ import BlockLink from "./components/BlockLink"; import AddressLink from "./components/AddressLink"; import Copy from "./components/Copy"; import Timestamp from "./components/Timestamp"; +import InternalTransfer from "./components/InternalTransfer"; import TokenLogo from "./components/TokenLogo"; import GasValue from "./components/GasValue"; import FormattedBalance from "./components/FormattedBalance"; import erc20 from "./erc20.json"; +import { + From, + TokenMetas, + TokenTransfer, + TransactionData, + Transfer, +} from "./types"; const USE_OTS = true; @@ -31,56 +38,6 @@ type TransactionParams = { txhash: string; }; -type TransactionData = { - transactionHash: string; - status: boolean; - blockNumber: number; - transactionIndex: number; - confirmations: number; - timestamp: number; - from: string; - to: string; - value: BigNumber; - tokenTransfers: TokenTransfer[]; - tokenMetas: TokenMetas; - fee: BigNumber; - gasPrice: BigNumber; - gasLimit: BigNumber; - gasUsed: BigNumber; - gasUsedPerc: number; - nonce: number; - data: string; - logs: ethers.providers.Log[]; -}; - -type From = { - current: string; - depth: number; -}; - -type Transfer = { - from: string; - to: string; - value: BigNumber; -}; - -type TokenTransfer = { - token: string; - from: string; - to: string; - value: BigNumber; -}; - -type TokenMeta = { - name: string; - symbol: string; - decimals: number; -}; - -type TokenMetas = { - [tokenAddress: string]: TokenMeta; -}; - const Transaction: React.FC = () => { const params = useParams(); const { txhash } = params; @@ -142,6 +99,7 @@ const Transaction: React.FC = () => { transactionIndex: _receipt.transactionIndex, confirmations: _receipt.confirmations, timestamp: _block.timestamp, + miner: _block.miner, from: _receipt.from, to: _receipt.to, value: _response.value, @@ -289,17 +247,11 @@ const Transaction: React.FC = () => { {transfers ? (
{transfers.map((t, i) => ( -
- - {" "} - TRANSFER - - {ethers.utils.formatEther(t.value)} Ether - From - - To - -
+ ))}
) : ( diff --git a/src/components/InternalTransfer.tsx b/src/components/InternalTransfer.tsx new file mode 100644 index 0000000..ac8f7d7 --- /dev/null +++ b/src/components/InternalTransfer.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { ethers } from "ethers"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faAngleRight, faCoins } from "@fortawesome/free-solid-svg-icons"; +import AddressLink from "./AddressLink"; +import { TransactionData, Transfer } from "../types"; + +type InternalTransferProps = { + txData: TransactionData; + transfer: Transfer; +}; + +const InternalTransfer: React.FC = ({ + txData, + transfer, +}) => { + const fromMiner = + txData.miner !== undefined && transfer.from === txData.miner; + const toMiner = txData.miner !== undefined && transfer.to === txData.miner; + + return ( +
+ + TRANSFER + + {ethers.utils.formatEther(transfer.value)} Ether + From +
+ {fromMiner && ( + + + + )} + +
+ To +
+ {toMiner && ( + + + + )} + +
+
+ ); +}; + +export default React.memo(InternalTransfer); diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index 4e74b35..b901f16 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -1,6 +1,9 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons"; +import { + faExclamationCircle, + faCoins, +} from "@fortawesome/free-solid-svg-icons"; import MethodName from "../components/MethodName"; import BlockLink from "../components/BlockLink"; import TransactionLink from "../components/TransactionLink"; @@ -63,11 +66,18 @@ const TransactionItem: React.FC = ({ {tx.from && ( - +
+ {tx.miner && tx.miner === tx.from && ( + + + + )} + +
)}
diff --git a/src/types.ts b/src/types.ts index 170fe58..404721d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,9 @@ -import { BigNumber } from "ethers"; +import { ethers, BigNumber } from "ethers"; export type ProcessedTransaction = { blockNumber: number; timestamp: number; + miner?: string; idx: number; hash: string; from?: string; @@ -23,3 +24,54 @@ export type TransactionChunk = { export type ENSReverseCache = { [address: string]: string; }; + +export type TransactionData = { + transactionHash: string; + status: boolean; + blockNumber: number; + transactionIndex: number; + confirmations: number; + timestamp: number; + miner?: string; + from: string; + to: string; + value: BigNumber; + tokenTransfers: TokenTransfer[]; + tokenMetas: TokenMetas; + fee: BigNumber; + gasPrice: BigNumber; + gasLimit: BigNumber; + gasUsed: BigNumber; + gasUsedPerc: number; + nonce: number; + data: string; + logs: ethers.providers.Log[]; +}; + +export type From = { + current: string; + depth: number; +}; + +export type Transfer = { + from: string; + to: string; + value: BigNumber; +}; + +export type TokenTransfer = { + token: string; + from: string; + to: string; + value: BigNumber; +}; + +export type TokenMeta = { + name: string; + symbol: string; + decimals: number; +}; + +export type TokenMetas = { + [tokenAddress: string]: TokenMeta; +}; From 1b32f4e8886a533d65fc9e88402ec78d1abfbd75 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:34:40 -0300 Subject: [PATCH 26/78] Highlight flashbot-like txs inside blocks --- src/BlockTransactions.tsx | 67 +++++++++++++++++-------- src/components/TransactionDirection.tsx | 28 +++++++++-- src/search/TransactionItem.tsx | 13 ++++- src/types.ts | 1 + 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index 47be1a8..87e73de 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -11,7 +11,7 @@ import ResultHeader from "./search/ResultHeader"; import PendingResults from "./search/PendingResults"; import TransactionItem from "./search/TransactionItem"; import BlockLink from "./components/BlockLink"; -import { ProcessedTransaction } from "./types"; +import { ProcessedTransaction, Transfer } from "./types"; import { PAGE_SIZE } from "./params"; import { useFeeToggler } from "./search/useFeeToggler"; import { useENSCache } from "./useReverseCache"; @@ -49,28 +49,51 @@ const BlockTransactions: React.FC = () => { ]); document.title = `Block #${_block.number} Transactions | Otterscan`; - setTxs( - _block.transactions - .map((t, i) => { - return { - blockNumber: blockNumber.toNumber(), - timestamp: _block.timestamp, - miner: _block.miner, - idx: i, - hash: t.hash, - from: t.from, - to: t.to, - value: t.value, - fee: provider.formatter - .bigNumber(_receipts[i].gasUsed) - .mul(t.gasPrice!), - gasPrice: t.gasPrice!, - data: t.data, - status: provider.formatter.number(_receipts[i].status), - }; - }) - .reverse() + const responses = _block.transactions + .map((t, i): ProcessedTransaction => { + return { + blockNumber: blockNumber.toNumber(), + timestamp: _block.timestamp, + miner: _block.miner, + idx: i, + hash: t.hash, + from: t.from, + to: t.to, + value: t.value, + fee: provider.formatter + .bigNumber(_receipts[i].gasUsed) + .mul(t.gasPrice!), + gasPrice: t.gasPrice!, + data: t.data, + status: provider.formatter.number(_receipts[i].status), + }; + }) + .reverse(); + + const internalChecks = await Promise.all( + responses.map(async (res) => { + const r = await provider.send("ots_getTransactionTransfers", [ + res.hash, + ]); + for (const t of r) { + if ( + res.miner && + (res.miner === ethers.utils.getAddress(t.from) || + res.miner === ethers.utils.getAddress(t.to)) + ) { + return true; + } + } + return false; + }) ); + for (let i = 0; i < responses.length; i++) { + if (internalChecks[i]) { + responses[i].internalMinerInteraction = true; + } + } + + setTxs(responses); }; readBlock(); }, [blockNumber]); diff --git a/src/components/TransactionDirection.tsx b/src/components/TransactionDirection.tsx index ee22e12..927bda1 100644 --- a/src/components/TransactionDirection.tsx +++ b/src/components/TransactionDirection.tsx @@ -1,6 +1,9 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faLongArrowAltRight } from "@fortawesome/free-solid-svg-icons"; +import { + faCoins, + faLongArrowAltRight, +} from "@fortawesome/free-solid-svg-icons"; export enum Direction { IN, @@ -9,12 +12,18 @@ export enum Direction { INTERNAL, } +export enum Flags { + MINER, +} + type TransactionDirectionProps = { direction?: Direction; + flags?: Flags; }; const TransactionDirection: React.FC = ({ direction, + flags, }) => { let bgColor = "bg-green-50"; let fgColor = "text-green-500"; @@ -34,6 +43,11 @@ const TransactionDirection: React.FC = ({ msg = "INT"; } + if (flags === Flags.MINER) { + bgColor = "bg-yellow-50"; + fgColor = "text-yellow-400"; + } + return ( = ({ : "w-5 h-5 rounded-full flex justify-center items-center" } text-xs font-bold`} > - {msg ?? ( - - - + {flags === Flags.MINER ? ( + + ) : ( + msg ?? ( + + + + ) )} ); diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index b901f16..57ce084 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -11,6 +11,7 @@ import AddressOrENSName from "../components/AddressOrENSName"; import TimestampAge from "../components/TimestampAge"; import TransactionDirection, { Direction, + Flags, } from "../components/TransactionDirection"; import TransactionValue from "../components/TransactionValue"; import { ENSReverseCache, ProcessedTransaction } from "../types"; @@ -45,9 +46,14 @@ const TransactionItem: React.FC = ({ const ensFrom = ensCache && tx.from && ensCache[tx.from]; const ensTo = ensCache && tx.to && ensCache[tx.to]; + const flash = tx.gasPrice.isZero() && tx.internalMinerInteraction; return ( -
+
{tx.status === 0 && ( @@ -81,7 +87,10 @@ const TransactionItem: React.FC = ({ )} - + diff --git a/src/types.ts b/src/types.ts index 404721d..36537f8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -8,6 +8,7 @@ export type ProcessedTransaction = { hash: string; from?: string; to?: string; + internalMinerInteraction?: boolean; value: BigNumber; fee: BigNumber; gasPrice: BigNumber; From 8ebc07806462cbb7d900da8a45829d8407665c27 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:37:05 -0300 Subject: [PATCH 27/78] Darken internal transactions --- src/components/TransactionDirection.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/TransactionDirection.tsx b/src/components/TransactionDirection.tsx index 927bda1..3695a77 100644 --- a/src/components/TransactionDirection.tsx +++ b/src/components/TransactionDirection.tsx @@ -41,6 +41,7 @@ const TransactionDirection: React.FC = ({ msg = "SELF"; } else if (direction === Direction.INTERNAL) { msg = "INT"; + bgColor = "bg-green-100" } if (flags === Flags.MINER) { From 560e47ed17a5b4e0b7dd45caa8069f449ef51bd9 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:46:25 -0300 Subject: [PATCH 28/78] Remove unused import --- src/BlockTransactions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index 87e73de..c780485 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -11,7 +11,7 @@ import ResultHeader from "./search/ResultHeader"; import PendingResults from "./search/PendingResults"; import TransactionItem from "./search/TransactionItem"; import BlockLink from "./components/BlockLink"; -import { ProcessedTransaction, Transfer } from "./types"; +import { ProcessedTransaction } from "./types"; import { PAGE_SIZE } from "./params"; import { useFeeToggler } from "./search/useFeeToggler"; import { useENSCache } from "./useReverseCache"; From 1b26e6be27e0be5e4bfc56059389228079252242 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 17:44:57 -0300 Subject: [PATCH 29/78] Dark yellow highlight --- src/search/TransactionItem.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index 57ce084..73fc211 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -50,8 +50,8 @@ const TransactionItem: React.FC = ({ return (
From 754369578f1025d471e01706b3f153002e5e4ab8 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 17:52:20 -0300 Subject: [PATCH 30/78] Lazy load flashbot tx checking --- src/BlockTransactions.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index c780485..e5712c0 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -69,6 +69,7 @@ const BlockTransactions: React.FC = () => { }; }) .reverse(); + setTxs(responses); const internalChecks = await Promise.all( responses.map(async (res) => { @@ -87,13 +88,10 @@ const BlockTransactions: React.FC = () => { return false; }) ); - for (let i = 0; i < responses.length; i++) { - if (internalChecks[i]) { - responses[i].internalMinerInteraction = true; - } - } - - setTxs(responses); + const processedResponses = responses.map((r, i): ProcessedTransaction => { + return { ...r, internalMinerInteraction: internalChecks[i] }; + }); + setTxs(processedResponses); }; readBlock(); }, [blockNumber]); From 36a69db5d8df75b444a02f8dd6bbee3e44f23ae6 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 17:59:39 -0300 Subject: [PATCH 31/78] Remove dead code --- src/Transaction.tsx | 68 ++------------------------------------------- 1 file changed, 3 insertions(+), 65 deletions(-) diff --git a/src/Transaction.tsx b/src/Transaction.tsx index da0d33d..c233f0d 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -21,15 +21,7 @@ import TokenLogo from "./components/TokenLogo"; import GasValue from "./components/GasValue"; import FormattedBalance from "./components/FormattedBalance"; import erc20 from "./erc20.json"; -import { - From, - TokenMetas, - TokenTransfer, - TransactionData, - Transfer, -} from "./types"; - -const USE_OTS = true; +import { TokenMetas, TokenTransfer, TransactionData, Transfer } from "./types"; const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; @@ -121,49 +113,6 @@ const Transaction: React.FC = () => { const [transfers, setTransfers] = useState(); - const traceTransfersUsingDebugTrace = async () => { - const r = await provider.send("debug_traceTransaction", [ - txData?.transactionHash, - { disableStorage: true, disableMemory: true }, - ]); - const fromStack: From[] = [ - { - current: txData!.to, - depth: 0, - }, - ]; - const _transfers: Transfer[] = []; - for (const l of r.structLogs) { - if (l.op !== "CALL") { - if (parseInt(l.depth) === fromStack[fromStack.length - 1].depth) { - fromStack.pop(); - } - continue; - } - - const { stack } = l; - const addr = stack[stack.length - 2].slice(24); - const value = BigNumber.from("0x" + stack[stack.length - 3]); - if (!value.isZero()) { - const t: Transfer = { - from: ethers.utils.getAddress( - fromStack[fromStack.length - 1].current - ), - to: ethers.utils.getAddress(addr), - value, - }; - _transfers.push(t); - } - - fromStack.push({ - current: addr, - depth: parseInt(l.depth), - }); - } - - setTransfers(_transfers); - }; - const traceTransfersUsingOtsTrace = useCallback(async () => { if (!txData) { return; @@ -184,9 +133,7 @@ const Transaction: React.FC = () => { setTransfers(_transfers); }, [txData]); useEffect(() => { - if (USE_OTS) { - traceTransfersUsingOtsTrace(); - } + traceTransfersUsingOtsTrace(); }, [traceTransfersUsingOtsTrace]); return ( @@ -244,7 +191,7 @@ const Transaction: React.FC = () => {
- {transfers ? ( + {transfers && (
{transfers.map((t, i) => ( { /> ))}
- ) : ( - !USE_OTS && ( - - ) )} From 24ae87a092d801f1976e75a7a369d55efab34141 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 18:08:52 -0300 Subject: [PATCH 32/78] Add flashbot classification --- src/Transaction.tsx | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Transaction.tsx b/src/Transaction.tsx index c233f0d..c538bc4 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from "react"; +import React, { useState, useEffect, useCallback, useMemo } from "react"; import { Route, Switch, useParams } from "react-router-dom"; import { BigNumber, ethers } from "ethers"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -112,6 +112,18 @@ const Transaction: React.FC = () => { }, [txhash]); const [transfers, setTransfers] = useState(); + const sendsEthToMiner = useMemo(() => { + if (!txData || !transfers) { + return false; + } + + for (const t of transfers) { + if (t.to === txData.miner) { + return true; + } + } + return false; + }, [txData, transfers]); const traceTransfersUsingOtsTrace = useCallback(async () => { if (!txData) { @@ -263,9 +275,17 @@ const Transaction: React.FC = () => { Ether - Ether ( - {" "} - Gwei) +
+ + Ether ( + {" "} + Gwei) + + {sendsEthToMiner && Flashbots} +
N/A From ac389429339646fb3fbab515e086eeb3173e1bc5 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 20:55:07 -0300 Subject: [PATCH 33/78] Apply miner icon directly on AddressOrENSName component --- src/Block.tsx | 9 +++--- src/Transaction.tsx | 17 ++++++++-- src/components/AddressOrENSName.tsx | 49 ++++++++++++++++++----------- src/search/TransactionItem.tsx | 24 +++++--------- 4 files changed, 57 insertions(+), 42 deletions(-) diff --git a/src/Block.tsx b/src/Block.tsx index bcffc27..9fd6e25 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -14,7 +14,7 @@ import NavButton from "./components/NavButton"; import Timestamp from "./components/Timestamp"; import GasValue from "./components/GasValue"; import BlockLink from "./components/BlockLink"; -import AddressLink from "./components/AddressLink"; +import AddressOrENSName from "./components/AddressOrENSName"; import TransactionValue from "./components/TransactionValue"; import HexValue from "./components/HexValue"; import { useLatestBlockNumber } from "./useLatestBlock"; @@ -154,9 +154,10 @@ const Block: React.FC = () => { in this block -
- -
+
diff --git a/src/Transaction.tsx b/src/Transaction.tsx index c538bc4..2041b2b 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -13,6 +13,7 @@ import StandardSubtitle from "./StandardSubtitle"; import Tab from "./components/Tab"; import ContentFrame from "./ContentFrame"; import BlockLink from "./components/BlockLink"; +import AddressOrENSName from "./components/AddressOrENSName"; import AddressLink from "./components/AddressLink"; import Copy from "./components/Copy"; import Timestamp from "./components/Timestamp"; @@ -194,13 +195,19 @@ const Transaction: React.FC = () => {
- +
- +
{transfers && ( @@ -284,7 +291,11 @@ const Transaction: React.FC = () => { />{" "} Gwei) - {sendsEthToMiner && Flashbots} + {sendsEthToMiner && ( + + Flashbots + + )}
N/A diff --git a/src/components/AddressOrENSName.tsx b/src/components/AddressOrENSName.tsx index e3cfdb9..8bcf024 100644 --- a/src/components/AddressOrENSName.tsx +++ b/src/components/AddressOrENSName.tsx @@ -1,4 +1,6 @@ import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faCoins } from "@fortawesome/free-solid-svg-icons"; import Address from "./Address"; import AddressLink from "./AddressLink"; import ENSName from "./ENSName"; @@ -8,30 +10,39 @@ type AddressOrENSNameProps = { address: string; ensName?: string; selectedAddress?: string; + minerAddress?: string; }; const AddressOrENSName: React.FC = ({ address, ensName, selectedAddress, -}) => { - return address === selectedAddress ? ( - <> - {ensName ? ( - - ) : ( -
- )} - - ) : ( - <> - {ensName ? ( - - ) : ( - - )} - - ); -}; + minerAddress, +}) => ( +
+ {minerAddress !== undefined && minerAddress === address && ( + + + + )} + {address === selectedAddress ? ( + <> + {ensName ? ( + + ) : ( +
+ )} + + ) : ( + <> + {ensName ? ( + + ) : ( + + )} + + )} +
+); export default React.memo(AddressOrENSName); diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index 73fc211..7cfaf76 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -1,9 +1,6 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faExclamationCircle, - faCoins, -} from "@fortawesome/free-solid-svg-icons"; +import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons"; import MethodName from "../components/MethodName"; import BlockLink from "../components/BlockLink"; import TransactionLink from "../components/TransactionLink"; @@ -72,18 +69,12 @@ const TransactionItem: React.FC = ({ {tx.from && ( -
- {tx.miner && tx.miner === tx.from && ( - - - - )} - -
+ )}
@@ -99,6 +90,7 @@ const TransactionItem: React.FC = ({ address={tx.to} ensName={ensTo} selectedAddress={selectedAddress} + minerAddress={tx.miner} /> )} From 3a1fa13c442ee6c9a2fc570627b17a866c93d7cd Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 21:08:58 -0300 Subject: [PATCH 34/78] Extract TokenTransferItem component --- src/TokenTransferItem.tsx | 51 ++++++++++++++++++++++++++++++++++++++ src/Transaction.tsx | 52 ++++++--------------------------------- 2 files changed, 59 insertions(+), 44 deletions(-) create mode 100644 src/TokenTransferItem.tsx diff --git a/src/TokenTransferItem.tsx b/src/TokenTransferItem.tsx new file mode 100644 index 0000000..bbdd45b --- /dev/null +++ b/src/TokenTransferItem.tsx @@ -0,0 +1,51 @@ +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faCaretRight } from "@fortawesome/free-solid-svg-icons"; +import AddressLink from "./components/AddressLink"; +import TokenLogo from "./components/TokenLogo"; +import FormattedBalance from "./components/FormattedBalance"; +import { TokenMetas, TokenTransfer } from "./types"; + +type TokenTransferItemProps = { + t: TokenTransfer; + tokenMetas: TokenMetas; +}; + +const TokenTransferItem: React.FC = ({ + t, + tokenMetas, +}) => ( +
+ + + + From + + To + + For + + + + + {tokenMetas[t.token] ? ( + <> +
+ +
+ + + ) : ( + + )} +
+
+); + +export default React.memo(TokenTransferItem); diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 2041b2b..a461501 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -5,7 +5,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheckCircle, faTimesCircle, - faCaretRight, } from "@fortawesome/free-solid-svg-icons"; import { provider } from "./ethersconfig"; import StandardFrame from "./StandardFrame"; @@ -18,9 +17,9 @@ import AddressLink from "./components/AddressLink"; import Copy from "./components/Copy"; import Timestamp from "./components/Timestamp"; import InternalTransfer from "./components/InternalTransfer"; -import TokenLogo from "./components/TokenLogo"; import GasValue from "./components/GasValue"; import FormattedBalance from "./components/FormattedBalance"; +import TokenTransferItem from "./TokenTransferItem"; import erc20 from "./erc20.json"; import { TokenMetas, TokenTransfer, TransactionData, Transfer } from "./types"; @@ -228,48 +227,13 @@ const Transaction: React.FC = () => { title={`Tokens Transferred (${txData.tokenTransfers.length})`} >
- {txData.tokenTransfers && - txData.tokenTransfers.map((t, i) => ( -
- - - - From - - To - - For - - - - - {txData.tokenMetas[t.token] ? ( - <> -
- -
- - - ) : ( - - )} -
-
- ))} + {txData.tokenTransfers.map((t, i) => ( + + ))}
)} From b6c176fb0e7fd347ec6d7f791e79d5bba7712873 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 21:12:16 -0300 Subject: [PATCH 35/78] Fix truncation --- src/TokenTransferItem.tsx | 7 ++++--- src/components/AddressOrENSName.tsx | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/TokenTransferItem.tsx b/src/TokenTransferItem.tsx index bbdd45b..64351ee 100644 --- a/src/TokenTransferItem.tsx +++ b/src/TokenTransferItem.tsx @@ -2,6 +2,7 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCaretRight } from "@fortawesome/free-solid-svg-icons"; import AddressLink from "./components/AddressLink"; +import AddressOrENSName from "./components/AddressOrENSName"; import TokenLogo from "./components/TokenLogo"; import FormattedBalance from "./components/FormattedBalance"; import { TokenMetas, TokenTransfer } from "./types"; @@ -20,9 +21,9 @@ const TokenTransferItem: React.FC = ({
From - + To - + For = ({ /> ) : ( - + )}
diff --git a/src/components/AddressOrENSName.tsx b/src/components/AddressOrENSName.tsx index 8bcf024..ce1ec8a 100644 --- a/src/components/AddressOrENSName.tsx +++ b/src/components/AddressOrENSName.tsx @@ -19,7 +19,7 @@ const AddressOrENSName: React.FC = ({ selectedAddress, minerAddress, }) => ( -
+
{minerAddress !== undefined && minerAddress === address && ( From 31d2983f94f2c474088c70a70e646382090688dc Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 6 Jul 2021 02:00:54 -0300 Subject: [PATCH 36/78] Fix truncation --- src/TokenTransferItem.tsx | 60 +++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/src/TokenTransferItem.tsx b/src/TokenTransferItem.tsx index 64351ee..64a42f6 100644 --- a/src/TokenTransferItem.tsx +++ b/src/TokenTransferItem.tsx @@ -20,32 +20,42 @@ const TokenTransferItem: React.FC = ({ - From - - To - - For - - - - - {tokenMetas[t.token] ? ( - <> -
- -
- +
+ From + +
+
+ To + +
+
+ For + + - - ) : ( - - )} - + + + {tokenMetas[t.token] ? ( + <> +
+ +
+ + + ) : ( + + )} +
+
+
); From 0d01cbef1d2ea8484f6b746d79bc7d0f7f437012 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 6 Jul 2021 02:04:46 -0300 Subject: [PATCH 37/78] Fix title fallback --- src/components/AddressLink.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddressLink.tsx b/src/components/AddressLink.tsx index f70b0ab..36acac6 100644 --- a/src/components/AddressLink.tsx +++ b/src/components/AddressLink.tsx @@ -11,7 +11,7 @@ const AddressLink: React.FC = ({ address, text }) => ( className="text-link-blue hover:text-link-blue-hover font-address truncate" to={`/address/${address}`} > -

+

{text ?? address}

From b28774330d12806f217c02f18e7c8c7d5a4cf8fe Mon Sep 17 00:00:00 2001 From: Marius Date: Tue, 6 Jul 2021 14:57:53 +0200 Subject: [PATCH 38/78] Use https instead of git URLs for submodules. --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 52aa546..b1d1263 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "4bytes"] path = 4bytes - url = git@github.com:ethereum-lists/4bytes.git + url = https://github.com/ethereum-lists/4bytes.git [submodule "trustwallet"] path = trustwallet - url = git@github.com:trustwallet/assets.git + url = https://github.com/trustwallet/assets.git From 41bfa05be4ef35035b63d1868493a1a623a59ade Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jul 2021 00:52:58 +0000 Subject: [PATCH 39/78] Bump ethers from 5.4.0 to 5.4.1 (#16) --- package-lock.json | 46 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index b24af1c..ad4da0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.8", "@types/react-router-dom": "^5.1.7", - "ethers": "^5.4.0", + "ethers": "^5.4.1", "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", @@ -1627,9 +1627,9 @@ ] }, "node_modules/@ethersproject/networks": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.4.0.tgz", - "integrity": "sha512-5fywtKRDcnaVeA5SjxXH3DOQqe/IbeD/plwydi94SdPps1fbDUrnO6SzDExaruBZXxpxJcO9upG9UComsei4bg==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.4.1.tgz", + "integrity": "sha512-8SvowCKz9Uf4xC5DTKI8+il8lWqOr78kmiqAVLYT9lzB8aSmJHQMD1GSuJI0CW4hMAnzocpGpZLgiMdzsNSPig==", "funding": [ { "type": "individual", @@ -1682,9 +1682,9 @@ } }, "node_modules/@ethersproject/providers": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.4.0.tgz", - "integrity": "sha512-XRmI9syLnkNdLA8ikEeg0duxmwSWTTt9S+xabnTOyI51JPJyhQ0QUNT+wvmod218ebb7rLupHDPQ7UVe2/+Tjg==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.4.1.tgz", + "integrity": "sha512-p06eiFKz8nu/5Ju0kIX024gzEQIgE5pvvGrBCngpyVjpuLtUIWT3097Agw4mTn9/dEA0FMcfByzFqacBMSgCVg==", "funding": [ { "type": "individual", @@ -8010,9 +8010,9 @@ } }, "node_modules/ethers": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.0.tgz", - "integrity": "sha512-hqN1x0CV8VMpQ25WnNEjaMqtB3nA4DRAb2FSmmNaUbD1dF6kWbHs8YaXbVvD37FCg3GTEyc4rV9Pxafk1ByHKw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.1.tgz", + "integrity": "sha512-SrcddMdCgP1hukDvCPd87Aipbf4NWjQvdfAbZ65XSZGbfyuYPtIrUJPDH5B1SBRsdlfiEgX3eoz28DdBDzMNFg==", "funding": [ { "type": "individual", @@ -8039,10 +8039,10 @@ "@ethersproject/json-wallets": "5.4.0", "@ethersproject/keccak256": "5.4.0", "@ethersproject/logger": "5.4.0", - "@ethersproject/networks": "5.4.0", + "@ethersproject/networks": "5.4.1", "@ethersproject/pbkdf2": "5.4.0", "@ethersproject/properties": "5.4.0", - "@ethersproject/providers": "5.4.0", + "@ethersproject/providers": "5.4.1", "@ethersproject/random": "5.4.0", "@ethersproject/rlp": "5.4.0", "@ethersproject/sha2": "5.4.0", @@ -20239,9 +20239,9 @@ "integrity": "sha512-xYdWGGQ9P2cxBayt64d8LC8aPFJk6yWCawQi/4eJ4+oJdMMjEBMrIcIMZ9AxhwpPVmnBPrsB10PcXGmGAqgUEQ==" }, "@ethersproject/networks": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.4.0.tgz", - "integrity": "sha512-5fywtKRDcnaVeA5SjxXH3DOQqe/IbeD/plwydi94SdPps1fbDUrnO6SzDExaruBZXxpxJcO9upG9UComsei4bg==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.4.1.tgz", + "integrity": "sha512-8SvowCKz9Uf4xC5DTKI8+il8lWqOr78kmiqAVLYT9lzB8aSmJHQMD1GSuJI0CW4hMAnzocpGpZLgiMdzsNSPig==", "requires": { "@ethersproject/logger": "^5.4.0" } @@ -20264,9 +20264,9 @@ } }, "@ethersproject/providers": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.4.0.tgz", - "integrity": "sha512-XRmI9syLnkNdLA8ikEeg0duxmwSWTTt9S+xabnTOyI51JPJyhQ0QUNT+wvmod218ebb7rLupHDPQ7UVe2/+Tjg==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.4.1.tgz", + "integrity": "sha512-p06eiFKz8nu/5Ju0kIX024gzEQIgE5pvvGrBCngpyVjpuLtUIWT3097Agw4mTn9/dEA0FMcfByzFqacBMSgCVg==", "requires": { "@ethersproject/abstract-provider": "^5.4.0", "@ethersproject/abstract-signer": "^5.4.0", @@ -24518,9 +24518,9 @@ "version": "1.8.1" }, "ethers": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.0.tgz", - "integrity": "sha512-hqN1x0CV8VMpQ25WnNEjaMqtB3nA4DRAb2FSmmNaUbD1dF6kWbHs8YaXbVvD37FCg3GTEyc4rV9Pxafk1ByHKw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.1.tgz", + "integrity": "sha512-SrcddMdCgP1hukDvCPd87Aipbf4NWjQvdfAbZ65XSZGbfyuYPtIrUJPDH5B1SBRsdlfiEgX3eoz28DdBDzMNFg==", "requires": { "@ethersproject/abi": "5.4.0", "@ethersproject/abstract-provider": "5.4.0", @@ -24537,10 +24537,10 @@ "@ethersproject/json-wallets": "5.4.0", "@ethersproject/keccak256": "5.4.0", "@ethersproject/logger": "5.4.0", - "@ethersproject/networks": "5.4.0", + "@ethersproject/networks": "5.4.1", "@ethersproject/pbkdf2": "5.4.0", "@ethersproject/properties": "5.4.0", - "@ethersproject/providers": "5.4.0", + "@ethersproject/providers": "5.4.1", "@ethersproject/random": "5.4.0", "@ethersproject/rlp": "5.4.0", "@ethersproject/sha2": "5.4.0", diff --git a/package.json b/package.json index 8de8a53..c4d0b9b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.8", "@types/react-router-dom": "^5.1.7", - "ethers": "^5.4.0", + "ethers": "^5.4.1", "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", From 3b28e32fd9cf7630adb879e97b0dd428ec14e2b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jul 2021 00:54:10 +0000 Subject: [PATCH 40/78] Bump @craco/craco from 6.1.2 to 6.2.0 (#15) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ad4da0a..6c74859 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "@craco/craco": "^6.1.2", + "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.4.5", "@fontsource/roboto": "^4.4.5", "@fontsource/roboto-mono": "^4.4.5", @@ -1218,9 +1218,9 @@ } }, "node_modules/@craco/craco": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.1.2.tgz", - "integrity": "sha512-GlQZn+g+yNlaDvIL5m6mcCoBGyFDwO4kkNx3fNFf98wuldkdWyBFoQbtOFOIb4gvkTh4VntOOxtJEoZfKs7XXw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.2.0.tgz", + "integrity": "sha512-kLc4GSdgR9D5JiZmSxtzbvBKcUFSJqMXImRjjYf5pacwiyAs3XfQwai7T+pExfLQNUnytgkL8jRFUJeYrkVr7g==", "dependencies": { "cross-spawn": "^7.0.0", "lodash": "^4.17.15", @@ -20007,9 +20007,9 @@ } }, "@craco/craco": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.1.2.tgz", - "integrity": "sha512-GlQZn+g+yNlaDvIL5m6mcCoBGyFDwO4kkNx3fNFf98wuldkdWyBFoQbtOFOIb4gvkTh4VntOOxtJEoZfKs7XXw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.2.0.tgz", + "integrity": "sha512-kLc4GSdgR9D5JiZmSxtzbvBKcUFSJqMXImRjjYf5pacwiyAs3XfQwai7T+pExfLQNUnytgkL8jRFUJeYrkVr7g==", "requires": { "cross-spawn": "^7.0.0", "lodash": "^4.17.15", diff --git a/package.json b/package.json index c4d0b9b..7d6d582 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "license": "MIT", "dependencies": { - "@craco/craco": "^6.1.2", + "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.4.5", "@fontsource/roboto": "^4.4.5", "@fontsource/roboto-mono": "^4.4.5", From 47e863a20c1e0eaa26aed683bf26a0379a20ef52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jul 2021 00:55:59 +0000 Subject: [PATCH 41/78] Bump @types/jest from 26.0.23 to 26.0.24 (#19) --- package-lock.json | 11 +++++++---- package.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6c74859..38cf2e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", - "@types/jest": "^26.0.15", + "@types/jest": "^26.0.24", "@types/node": "^12.0.0", "@types/react": "^17.0.13", "@types/react-blockies": "^1.4.0", @@ -3032,8 +3032,9 @@ } }, "node_modules/@types/jest": { - "version": "26.0.23", - "license": "MIT", + "version": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", "dependencies": { "jest-diff": "^26.0.0", "pretty-format": "^26.0.0" @@ -21130,7 +21131,9 @@ } }, "@types/jest": { - "version": "26.0.23", + "version": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", "requires": { "jest-diff": "^26.0.0", "pretty-format": "^26.0.0" diff --git a/package.json b/package.json index 7d6d582..841d6f1 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", - "@types/jest": "^26.0.15", + "@types/jest": "^26.0.24", "@types/node": "^12.0.0", "@types/react": "^17.0.13", "@types/react-blockies": "^1.4.0", From 3a2f55905a2bd90502bb2c3d79fbd8e9128b99b2 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 6 Jul 2021 22:06:13 -0300 Subject: [PATCH 42/78] Replace chaindata with datadir --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9b9a523..8852ea2 100644 --- a/README.md +++ b/README.md @@ -98,10 +98,10 @@ Run it paying attention to enable the `erigon`, `ots`, `eth` apis to whatever cl `ots` stands for Otterscan and it is the namespace we use for our own custom APIs. ``` -./build/bin/rpcdaemon --http.api "eth,erigon,ots," --private.api.addr 127.0.0.1:9090 --chaindata --http.corsdomain "*" +./build/bin/rpcdaemon --http.api "eth,erigon,ots," --private.api.addr 127.0.0.1:9090 --datadir --http.corsdomain "*" ``` -Be sure to include both `--private.api.addr` and `--chaindata` parameter so you run it in dual mode, otherwise the performance will be much worse. +Be sure to include both `--private.api.addr` and `--datadir` parameter so you run it in dual mode, otherwise the performance will be much worse. Also pay attention to the `--http.corsdomain` parameter, CORS is required for the browser to call the node directly. From 850bf088334553420eaa2d3ccf2d078ecefae5a0 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 16:47:44 -0300 Subject: [PATCH 43/78] First attempt at replacing serve-4bytes with a nginx docker container drop-in --- Dockerfile-4bytes | 3 +++ nginx-4bytes.conf | 50 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 ++++-- 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 Dockerfile-4bytes create mode 100644 nginx-4bytes.conf diff --git a/Dockerfile-4bytes b/Dockerfile-4bytes new file mode 100644 index 0000000..9d308d9 --- /dev/null +++ b/Dockerfile-4bytes @@ -0,0 +1,3 @@ +FROM nginx:1.21.1-alpine +COPY 4bytes/signatures /usr/share/nginx/html/ +COPY nginx-4bytes.conf /etc/nginx/conf.d/default.conf diff --git a/nginx-4bytes.conf b/nginx-4bytes.conf new file mode 100644 index 0000000..6060f2b --- /dev/null +++ b/nginx-4bytes.conf @@ -0,0 +1,50 @@ +server { + listen 80; + server_name localhost; + + #access_log /var/log/nginx/host.access.log main; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + + # Base on: https://michielkalkman.com/snippets/nginx-cors-open-configuration/ + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*'; + # + # Om nom nom cookies + # + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; + + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + + # + # Tell client that this pre-flight info is valid for 20 days + # + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + add_header 'Content-Length' 0; + return 204; + } + if ($request_method = 'GET') { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + } + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + +} \ No newline at end of file diff --git a/package.json b/package.json index 841d6f1..7191a55 100644 --- a/package.json +++ b/package.json @@ -42,9 +42,11 @@ "build": "craco build", "test": "craco test", "eject": "react-scripts eject", - "serve-4bytes": "serve -p 3001 -C -c serve-4bytes.json", + "start-4bytes": "docker run --rm -p 3001:80 --name otterscan-4bytes -d otterscan/4bytes", + "stop-4bytes": "docker stop otterscan-4bytes", "serve-trustwallet-assets": "serve -p 3002 -C -c serve-trustwallet-assets.json", - "serve": "serve -s build" + "serve": "serve -s build", + "build-docker-4bytes": "docker build -t otterscan/4bytes -f Dockerfile-4bytes ." }, "eslintConfig": { "extends": [ From 97e542f51e9061f293de633e9a825926623e6f39 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 16:51:52 -0300 Subject: [PATCH 44/78] Change 4bytes subdirectory in preparation for adding trustwallet asset to the same image --- Dockerfile-4bytes | 2 +- src/components/MethodName.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile-4bytes b/Dockerfile-4bytes index 9d308d9..651cb25 100644 --- a/Dockerfile-4bytes +++ b/Dockerfile-4bytes @@ -1,3 +1,3 @@ FROM nginx:1.21.1-alpine -COPY 4bytes/signatures /usr/share/nginx/html/ +COPY 4bytes/signatures /usr/share/nginx/html/signatures/ COPY nginx-4bytes.conf /etc/nginx/conf.d/default.conf diff --git a/src/components/MethodName.tsx b/src/components/MethodName.tsx index 70742e0..27ad8ca 100644 --- a/src/components/MethodName.tsx +++ b/src/components/MethodName.tsx @@ -16,7 +16,7 @@ const MethodName: React.FC = ({ data }) => { // Try to resolve 4bytes name const fourBytes = _name.slice(2); - const signatureURL = `http://localhost:3001/${fourBytes}`; + const signatureURL = `http://localhost:3001/signatures/${fourBytes}`; fetch(signatureURL) .then(async (res) => { if (!res.ok) { From cf581e1ab565eaab438804176f64b86206f437ca Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 16:59:49 -0300 Subject: [PATCH 45/78] Merge trustwallet assets to the same docker image --- Dockerfile | 4 ++++ Dockerfile-4bytes | 3 --- nginx-4bytes.conf => nginx.conf | 0 package.json | 7 +++---- serve-4bytes.json | 15 --------------- serve-trustwallet-assets.json | 15 --------------- src/components/TokenLogo.tsx | 2 +- 7 files changed, 8 insertions(+), 38 deletions(-) create mode 100644 Dockerfile delete mode 100644 Dockerfile-4bytes rename nginx-4bytes.conf => nginx.conf (100%) delete mode 100644 serve-4bytes.json delete mode 100644 serve-trustwallet-assets.json diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8e0062e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM nginx:1.21.1-alpine +COPY 4bytes/signatures /usr/share/nginx/html/signatures/ +COPY trustwallet/blockchains/ethereum/assets /usr/share/nginx/html/assets/ +COPY nginx.conf /etc/nginx/conf.d/default.conf diff --git a/Dockerfile-4bytes b/Dockerfile-4bytes deleted file mode 100644 index 651cb25..0000000 --- a/Dockerfile-4bytes +++ /dev/null @@ -1,3 +0,0 @@ -FROM nginx:1.21.1-alpine -COPY 4bytes/signatures /usr/share/nginx/html/signatures/ -COPY nginx-4bytes.conf /etc/nginx/conf.d/default.conf diff --git a/nginx-4bytes.conf b/nginx.conf similarity index 100% rename from nginx-4bytes.conf rename to nginx.conf diff --git a/package.json b/package.json index 7191a55..8e8031c 100644 --- a/package.json +++ b/package.json @@ -42,11 +42,10 @@ "build": "craco build", "test": "craco test", "eject": "react-scripts eject", - "start-4bytes": "docker run --rm -p 3001:80 --name otterscan-4bytes -d otterscan/4bytes", - "stop-4bytes": "docker stop otterscan-4bytes", - "serve-trustwallet-assets": "serve -p 3002 -C -c serve-trustwallet-assets.json", + "start-docker": "docker run --rm -p 3001:80 --name otterscan -d otterscan", + "stop-docker": "docker stop otterscan", "serve": "serve -s build", - "build-docker-4bytes": "docker build -t otterscan/4bytes -f Dockerfile-4bytes ." + "build-docker": "docker build -t otterscan -f Dockerfile ." }, "eslintConfig": { "extends": [ diff --git a/serve-4bytes.json b/serve-4bytes.json deleted file mode 100644 index 3d0abde..0000000 --- a/serve-4bytes.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "public": "4bytes/signatures", - "headers": [ - { - "source": "**", - "headers": [ - { - "key": "Cache-Control", - "value": "max-age=600" - } - ] - } - ], - "directoryListing": false -} \ No newline at end of file diff --git a/serve-trustwallet-assets.json b/serve-trustwallet-assets.json deleted file mode 100644 index 967698d..0000000 --- a/serve-trustwallet-assets.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "public": "trustwallet/blockchains/ethereum/assets", - "headers": [ - { - "source": "**", - "headers": [ - { - "key": "Cache-Control", - "value": "max-age=600" - } - ] - } - ], - "directoryListing": false -} \ No newline at end of file diff --git a/src/components/TokenLogo.tsx b/src/components/TokenLogo.tsx index 7905185..738de1c 100644 --- a/src/components/TokenLogo.tsx +++ b/src/components/TokenLogo.tsx @@ -15,7 +15,7 @@ const TokenLogo: React.FC = (props) => ( const InternalTokenLogo: React.FC = ({ address, name }) => { const { src } = useImage({ srcList: [ - `http://localhost:3002/${address}/logo.png`, + `http://localhost:3001/assets/${address}/logo.png`, "/eth-diamond-black.png", ], }); From 73779426c508cb2af405825eb0fa79d73f850d5f Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 17:45:37 -0300 Subject: [PATCH 46/78] Merge the entire distribution into one unique docker image --- .dockerignore | 1 + Dockerfile | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +node_modules diff --git a/Dockerfile b/Dockerfile index 8e0062e..b6c325f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,13 @@ +FROM node:12.22.3-alpine AS builder +WORKDIR /otterscan-build +COPY ["package*.json", "tsconfig.json", "craco.config.js", "tailwind.config.js", "/otterscan-build"] +COPY ["src", "/otterscan-build/src"] +COPY ["public", "/otterscan-build/public"] +RUN npm install +RUN npm run build + FROM nginx:1.21.1-alpine COPY 4bytes/signatures /usr/share/nginx/html/signatures/ COPY trustwallet/blockchains/ethereum/assets /usr/share/nginx/html/assets/ COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /otterscan-build/build /usr/share/nginx/html/ From d8c100371ea4f3e476a1794d6f1bf86fecc30d48 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 18:09:22 -0300 Subject: [PATCH 47/78] Change production build run port --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 8e8031c..3c596f7 100644 --- a/package.json +++ b/package.json @@ -42,9 +42,8 @@ "build": "craco build", "test": "craco test", "eject": "react-scripts eject", - "start-docker": "docker run --rm -p 3001:80 --name otterscan -d otterscan", + "start-docker": "docker run --rm -p 5000:80 --name otterscan -d otterscan", "stop-docker": "docker stop otterscan", - "serve": "serve -s build", "build-docker": "docker build -t otterscan -f Dockerfile ." }, "eslintConfig": { From 8b2e8abbf45fc835003a4d63e9091e4d33f7297b Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 18:55:54 -0300 Subject: [PATCH 48/78] Update dockerized instructions --- README.md | 63 +++++++++++++++++++++++++++++++++++++++------------- package.json | 4 +++- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 8852ea2..b049ba5 100644 --- a/README.md +++ b/README.md @@ -107,9 +107,29 @@ Also pay attention to the `--http.corsdomain` parameter, CORS is required for th Now you should have an Erigon node with Otterscan jsonrpc APIs enabled, running in dual mode with CORS enabled. -### Clone Otterscan repository and build the project +### Run Otterscan docker image from Docker Hub -Make sure you have a working node 12/npm installation. +TODO: publish Otterscan official images as soon as it is validated. + +``` +docker run --rm -p 5000:80 --name otterscan -d otterscan/otterscan: +``` + +This will download the Otterscan image from Docker Hub, run it locally using the default parameters, binding it to port 5000 (see the `-p` docker run parameter). + +To stop Otterscan service, run: + +``` +docker stop otterscan +``` + +### (Alternative) Build Otterscan docker image locally and run it + +If you don't want to download from Docker Hub, you can build the docker image from the sources and run it. + +If you just want to build the image locally, there is no need to install the development toolchain, just make sure you have a recent working Docker installation. + +The entire build process will take place inside the docker multi-stage build. Clone Otterscan repo and its submodules. Checkout the tag corresponding to your Erigon + Otterscan patches. It uses the same version tag from Erigon + Otterscan repo, i.e., if you built the `v2021.07.01-otterscan`, you should build the `v2021.07.01-otterscan` of Otterscan. @@ -117,19 +137,19 @@ Clone Otterscan repo and its submodules. Checkout the tag corresponding to your git clone --recurse-submodules git@github.com:wmitsuda/otterscan.git cd otterscan git checkout -npm install -npm run build +docker build -t otterscan -f Dockerfile . ``` -By default, it assumes your Erigon `rpcdaemon` processs is serving requests at http://127.0.0.1:8545. You can customize this URL by specifying the `REACT_APP_ERIGON_URL` environment variable at build time (it needs to be done at build time because the build process generates a static website). +This will run the entire build process inside a build container, merge the production build of the React app with the 4bytes and trustwallet assets into the same image format it is published in Docker Hub, but locally under the name `otterscan`. -To do that, export the variable before running `npm run build`: +Then you can start/stop it using the commands: ``` -export REACT_APP_ERIGON_URL= +docker run --rm -p 5000:80 --name otterscan -d otterscan +docker stop otterscan ``` -### Run it from the source +### Run a development build from the source First, a brief explanation about the app: @@ -141,25 +161,38 @@ First, a brief explanation about the app: These instructions are subjected to changes in future for the sake of simplification. -Open a new terminal and start the 4bytes method decoding service: +Make sure you have a working node 12/npm installation. + +By default, it assumes your Erigon `rpcdaemon` processs is serving requests at http://127.0.0.1:8545. You can customize this URL by specifying the `REACT_APP_ERIGON_URL` environment variable at build time (it needs to be done at build time because the build process generates a static website). + +To do that, export the variable before running `npm run build`: ``` -npm run serve-4bytes +export REACT_APP_ERIGON_URL= ``` -Open another terminal and start the trustwallet assets service: +Start serving 4bytes and trustwallet assets at `localhost:3001` using a dockerized nginx: ``` -npm run serve-trustwallet-assets +npm run start-assets ``` -In another terminal start the Otterscan app: +To stop it, run: ``` -npm run serve +npm run stop-assets ``` -Otterscan should now be running at http://localhost:5000/. +To run Otterscan development build: + +``` +npm install +npm start +``` + +Otterscan should now be running at http://localhost:3000/. + +## Validating the installation (all methods) **You can make sure it is working correctly if the homepage is able to show the latest block/timestamp your Erigon node is at just bellow the search button.** diff --git a/package.json b/package.json index 3c596f7..80a67b1 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,9 @@ "eject": "react-scripts eject", "start-docker": "docker run --rm -p 5000:80 --name otterscan -d otterscan", "stop-docker": "docker stop otterscan", - "build-docker": "docker build -t otterscan -f Dockerfile ." + "build-docker": "docker build -t otterscan -f Dockerfile .", + "start-assets": "docker run --rm -p 3001:80 --name otterscan-assets -d -v$(pwd)/4bytes/signatures:/usr/share/nginx/html/signatures/ -v$(pwd)/trustwallet/blockchains/ethereum/assets:/usr/share/nginx/html/assets nginx:1.21.1-alpine", + "stop-assets": "docker stop otterscan-assets" }, "eslintConfig": { "extends": [ From 7eb91be28676d868647b8dd2241ea507696178b4 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 19:44:17 -0300 Subject: [PATCH 49/78] Small doc fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b049ba5..3fcf9e2 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ To stop Otterscan service, run: docker stop otterscan ``` -### (Alternative) Build Otterscan docker image locally and run it +### (Alternative 1) Build Otterscan docker image locally and run it If you don't want to download from Docker Hub, you can build the docker image from the sources and run it. @@ -149,7 +149,7 @@ docker run --rm -p 5000:80 --name otterscan -d otterscan docker stop otterscan ``` -### Run a development build from the source +### (Alternative 2) Run a development build from the source First, a brief explanation about the app: From d5d5407eee14b1df8d2a07a0d030297a762a7cfe Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 7 Jul 2021 21:57:03 -0300 Subject: [PATCH 50/78] Add hack to write params on container start --- .dockerignore | 2 ++ Dockerfile | 7 ++++++- run-nginx.sh | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100755 run-nginx.sh diff --git a/.dockerignore b/.dockerignore index 3c3629e..996deec 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,3 @@ node_modules +trustwallet +!trustwallet/blockchains/ethereum/assets diff --git a/Dockerfile b/Dockerfile index b6c325f..5062957 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,18 @@ FROM node:12.22.3-alpine AS builder WORKDIR /otterscan-build -COPY ["package*.json", "tsconfig.json", "craco.config.js", "tailwind.config.js", "/otterscan-build"] +COPY ["run-nginx.sh", "package*.json", "tsconfig.json", "craco.config.js", "tailwind.config.js", "/otterscan-build"] COPY ["src", "/otterscan-build/src"] COPY ["public", "/otterscan-build/public"] RUN npm install RUN npm run build FROM nginx:1.21.1-alpine +RUN apk add jq COPY 4bytes/signatures /usr/share/nginx/html/signatures/ COPY trustwallet/blockchains/ethereum/assets /usr/share/nginx/html/assets/ COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=builder /otterscan-build/build /usr/share/nginx/html/ +COPY --from=builder /otterscan-build/run-nginx.sh / +WORKDIR / + +CMD ["/run-nginx.sh"] diff --git a/run-nginx.sh b/run-nginx.sh new file mode 100755 index 0000000..57cf41d --- /dev/null +++ b/run-nginx.sh @@ -0,0 +1,4 @@ +#!/bin/sh +PARAMS=`echo "{\"erigonURL\": \"$ERIGON_URL\"}" | jq -aRs .` +echo $PARAMS > /usr/share/nginx/html/config.json +nginx -g "daemon off;" From 5ee5df4f02345c204409db6a3feb34b538dacc6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 02:54:43 +0000 Subject: [PATCH 51/78] Bump @fontsource/roboto from 4.4.5 to 4.5.0 (#23) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38cf2e7..19286a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.4.5", - "@fontsource/roboto": "^4.4.5", + "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.4.5", "@fontsource/space-grotesk": "^4.4.5", "@fortawesome/fontawesome-svg-core": "^1.2.35", @@ -1988,9 +1988,9 @@ "integrity": "sha512-ap1UKABzbPrUTgIB376n8CSJ7mbJYxGm52A60BHnGHjU2cSDBqNUAColdERgFWgLHfybWXQT13ZrNhAdynf9rg==" }, "node_modules/@fontsource/roboto": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.4.5.tgz", - "integrity": "sha512-e3s7BF8MDBLpkA2r6lnl5PMnllF0McVvpolK9h2zzvVJw2WPexP1GTgMKHISlglYZRij2lKg/ZjQcIUUYDsAXg==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.0.tgz", + "integrity": "sha512-ja4XYw/9kNRFM5Ndk9vwzHWsdBMXczyBazFkTXJQ74QQBnT0BbSsHn0pF60AU0Iznig1Wt9x3rADfG8LANvMpw==" }, "node_modules/@fontsource/roboto-mono": { "version": "4.4.5", @@ -20439,9 +20439,9 @@ "integrity": "sha512-ap1UKABzbPrUTgIB376n8CSJ7mbJYxGm52A60BHnGHjU2cSDBqNUAColdERgFWgLHfybWXQT13ZrNhAdynf9rg==" }, "@fontsource/roboto": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.4.5.tgz", - "integrity": "sha512-e3s7BF8MDBLpkA2r6lnl5PMnllF0McVvpolK9h2zzvVJw2WPexP1GTgMKHISlglYZRij2lKg/ZjQcIUUYDsAXg==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.0.tgz", + "integrity": "sha512-ja4XYw/9kNRFM5Ndk9vwzHWsdBMXczyBazFkTXJQ74QQBnT0BbSsHn0pF60AU0Iznig1Wt9x3rADfG8LANvMpw==" }, "@fontsource/roboto-mono": { "version": "4.4.5", diff --git a/package.json b/package.json index 841d6f1..aa3e939 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dependencies": { "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.4.5", - "@fontsource/roboto": "^4.4.5", + "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.4.5", "@fontsource/space-grotesk": "^4.4.5", "@fortawesome/fontawesome-svg-core": "^1.2.35", From 214d9c19b217767b223497ff0e5cd94296c53ca2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 02:56:53 +0000 Subject: [PATCH 52/78] Bump @fontsource/space-grotesk from 4.4.5 to 4.5.0 (#22) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19286a7..77f05ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@fontsource/fira-code": "^4.4.5", "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.4.5", - "@fontsource/space-grotesk": "^4.4.5", + "@fontsource/space-grotesk": "^4.5.0", "@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/free-brands-svg-icons": "^5.15.3", "@fortawesome/free-regular-svg-icons": "^5.15.3", @@ -1998,9 +1998,9 @@ "integrity": "sha512-y9fbKH1eCCkcqtRGhevFlmR5schCRz1GiTT/VYz6z8Ij0WHW0tS26BhMyXhmSgEIiFt+254yS8teqP+cc7Xq0w==" }, "node_modules/@fontsource/space-grotesk": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/space-grotesk/-/space-grotesk-4.4.5.tgz", - "integrity": "sha512-9gD8j+uxTggMdPStZi4SLjwWBpmKQteuP1NMtdegPzbbnfVsjzg4++w+KnpkRp2PMWECcGzyNkW8uNXqP+H6+w==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/space-grotesk/-/space-grotesk-4.5.0.tgz", + "integrity": "sha512-Kdnq5m31DsJ8l/VCpZGz4QpIxLLvNVh4MyVGY0PmDh7aY9aM5rmO2NF49dJ0749gLPgMW6Moc/xjgW95G0MbMg==" }, "node_modules/@fortawesome/fontawesome-common-types": { "version": "0.2.35", @@ -20449,9 +20449,9 @@ "integrity": "sha512-y9fbKH1eCCkcqtRGhevFlmR5schCRz1GiTT/VYz6z8Ij0WHW0tS26BhMyXhmSgEIiFt+254yS8teqP+cc7Xq0w==" }, "@fontsource/space-grotesk": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/space-grotesk/-/space-grotesk-4.4.5.tgz", - "integrity": "sha512-9gD8j+uxTggMdPStZi4SLjwWBpmKQteuP1NMtdegPzbbnfVsjzg4++w+KnpkRp2PMWECcGzyNkW8uNXqP+H6+w==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/space-grotesk/-/space-grotesk-4.5.0.tgz", + "integrity": "sha512-Kdnq5m31DsJ8l/VCpZGz4QpIxLLvNVh4MyVGY0PmDh7aY9aM5rmO2NF49dJ0749gLPgMW6Moc/xjgW95G0MbMg==" }, "@fortawesome/fontawesome-common-types": { "version": "0.2.35", diff --git a/package.json b/package.json index aa3e939..b8dd28e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "@fontsource/fira-code": "^4.4.5", "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.4.5", - "@fontsource/space-grotesk": "^4.4.5", + "@fontsource/space-grotesk": "^4.5.0", "@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/free-brands-svg-icons": "^5.15.3", "@fortawesome/free-regular-svg-icons": "^5.15.3", From 97350a07bc13ccd4f23bc1116f4824bcadd7d695 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 02:58:38 +0000 Subject: [PATCH 53/78] Bump @types/react from 17.0.13 to 17.0.14 (#27) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77f05ba..bbc256a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^12.0.0", - "@types/react": "^17.0.13", + "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.8", "@types/react-router-dom": "^5.1.7", @@ -3077,9 +3077,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.13.tgz", - "integrity": "sha512-D/G3PiuqTfE3IMNjLn/DCp6umjVCSvtZTPdtAFy5+Ved6CsdRvivfKeCzw79W4AatShtU4nGqgvOv5Gro534vQ==", + "version": "17.0.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.14.tgz", + "integrity": "sha512-0WwKHUbWuQWOce61UexYuWTGuGY/8JvtUe/dtQ6lR4sZ3UiylHotJeWpf3ArP9+DSGUoLY3wbU59VyMrJps5VQ==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -21167,9 +21167,9 @@ "version": "1.5.4" }, "@types/react": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.13.tgz", - "integrity": "sha512-D/G3PiuqTfE3IMNjLn/DCp6umjVCSvtZTPdtAFy5+Ved6CsdRvivfKeCzw79W4AatShtU4nGqgvOv5Gro534vQ==", + "version": "17.0.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.14.tgz", + "integrity": "sha512-0WwKHUbWuQWOce61UexYuWTGuGY/8JvtUe/dtQ6lR4sZ3UiylHotJeWpf3ArP9+DSGUoLY3wbU59VyMrJps5VQ==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", diff --git a/package.json b/package.json index b8dd28e..233a9fa 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^12.0.0", - "@types/react": "^17.0.13", + "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.8", "@types/react-router-dom": "^5.1.7", From d303ab30a0c3a51d668694461dedf3e6f41fa872 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 02:59:19 +0000 Subject: [PATCH 54/78] Bump @fontsource/fira-code from 4.4.5 to 4.5.0 (#26) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index bbc256a..7facac3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "license": "MIT", "dependencies": { "@craco/craco": "^6.2.0", - "@fontsource/fira-code": "^4.4.5", + "@fontsource/fira-code": "^4.5.0", "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.4.5", "@fontsource/space-grotesk": "^4.5.0", @@ -1983,9 +1983,9 @@ } }, "node_modules/@fontsource/fira-code": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.4.5.tgz", - "integrity": "sha512-ap1UKABzbPrUTgIB376n8CSJ7mbJYxGm52A60BHnGHjU2cSDBqNUAColdERgFWgLHfybWXQT13ZrNhAdynf9rg==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.0.tgz", + "integrity": "sha512-fxRV3qt0eJaIXZvICXZMhXVR0lSyxZTC0cnM+1Ma/1JShGrIjCQ3yJ0W05rwaEoF3cAbpU2lKMrXfE7Of/zpIA==" }, "node_modules/@fontsource/roboto": { "version": "4.5.0", @@ -20434,9 +20434,9 @@ } }, "@fontsource/fira-code": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.4.5.tgz", - "integrity": "sha512-ap1UKABzbPrUTgIB376n8CSJ7mbJYxGm52A60BHnGHjU2cSDBqNUAColdERgFWgLHfybWXQT13ZrNhAdynf9rg==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.0.tgz", + "integrity": "sha512-fxRV3qt0eJaIXZvICXZMhXVR0lSyxZTC0cnM+1Ma/1JShGrIjCQ3yJ0W05rwaEoF3cAbpU2lKMrXfE7Of/zpIA==" }, "@fontsource/roboto": { "version": "4.5.0", diff --git a/package.json b/package.json index 233a9fa..ec7de98 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "license": "MIT", "dependencies": { "@craco/craco": "^6.2.0", - "@fontsource/fira-code": "^4.4.5", + "@fontsource/fira-code": "^4.5.0", "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.4.5", "@fontsource/space-grotesk": "^4.5.0", From 3cbb6e698a59ac20180334622c260937380e5aac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 03:01:42 +0000 Subject: [PATCH 55/78] Bump @fontsource/roboto-mono from 4.4.5 to 4.5.0 (#28) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7facac3..1bc36ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.5.0", "@fontsource/roboto": "^4.5.0", - "@fontsource/roboto-mono": "^4.4.5", + "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", "@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/free-brands-svg-icons": "^5.15.3", @@ -1993,9 +1993,9 @@ "integrity": "sha512-ja4XYw/9kNRFM5Ndk9vwzHWsdBMXczyBazFkTXJQ74QQBnT0BbSsHn0pF60AU0Iznig1Wt9x3rADfG8LANvMpw==" }, "node_modules/@fontsource/roboto-mono": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-mono/-/roboto-mono-4.4.5.tgz", - "integrity": "sha512-y9fbKH1eCCkcqtRGhevFlmR5schCRz1GiTT/VYz6z8Ij0WHW0tS26BhMyXhmSgEIiFt+254yS8teqP+cc7Xq0w==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-mono/-/roboto-mono-4.5.0.tgz", + "integrity": "sha512-/6Gm6fJjBHZiFNyvzIKGJkVuyifoc1aoTel+pkzdhxNh7yNhFyokCoChdbbqZEpGKpqs5uld74G5TJthUVFyjw==" }, "node_modules/@fontsource/space-grotesk": { "version": "4.5.0", @@ -20444,9 +20444,9 @@ "integrity": "sha512-ja4XYw/9kNRFM5Ndk9vwzHWsdBMXczyBazFkTXJQ74QQBnT0BbSsHn0pF60AU0Iznig1Wt9x3rADfG8LANvMpw==" }, "@fontsource/roboto-mono": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-mono/-/roboto-mono-4.4.5.tgz", - "integrity": "sha512-y9fbKH1eCCkcqtRGhevFlmR5schCRz1GiTT/VYz6z8Ij0WHW0tS26BhMyXhmSgEIiFt+254yS8teqP+cc7Xq0w==" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-mono/-/roboto-mono-4.5.0.tgz", + "integrity": "sha512-/6Gm6fJjBHZiFNyvzIKGJkVuyifoc1aoTel+pkzdhxNh7yNhFyokCoChdbbqZEpGKpqs5uld74G5TJthUVFyjw==" }, "@fontsource/space-grotesk": { "version": "4.5.0", diff --git a/package.json b/package.json index ec7de98..f8bb788 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.5.0", "@fontsource/roboto": "^4.5.0", - "@fontsource/roboto-mono": "^4.4.5", + "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", "@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/free-brands-svg-icons": "^5.15.3", From 29b6201c9bdf105f199c96aa15d51a345b0f95a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 03:04:23 +0000 Subject: [PATCH 56/78] Bump @types/node from 12.20.15 to 12.20.16 (#29) --- package-lock.json | 203 ++-------------------------------------------- package.json | 2 +- 2 files changed, 8 insertions(+), 197 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1bc36ee..910a7de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", - "@types/node": "^12.0.0", + "@types/node": "^12.20.16", "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.8", @@ -2152,10 +2152,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/console/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@jest/core": { "version": "26.6.3", "license": "MIT", @@ -2193,10 +2189,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/core/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@jest/core/node_modules/rimraf": { "version": "3.0.2", "license": "ISC", @@ -2223,10 +2215,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/environment/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@jest/fake-timers": { "version": "26.6.2", "license": "MIT", @@ -2242,10 +2230,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/fake-timers/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@jest/globals": { "version": "26.6.2", "license": "MIT", @@ -2371,10 +2355,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/types/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.4", "license": "MIT", @@ -2989,10 +2969,6 @@ "@types/node": "*" } }, - "node_modules/@types/glob/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "license": "MIT", @@ -3000,10 +2976,6 @@ "@types/node": "*" } }, - "node_modules/@types/graceful-fs/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@types/history": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz", @@ -3053,8 +3025,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "12.20.15", - "license": "MIT" + "version": "12.20.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.16.tgz", + "integrity": "sha512-6CLxw83vQf6DKqXxMPwl8qpF8I7THFZuIwLt4TnNsumxkp1VsRZWT8txQxncT/Rl2UojTsFzWgDG4FRMwafrlA==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.0", @@ -3128,10 +3101,6 @@ "@types/node": "*" } }, - "node_modules/@types/resolve/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@types/scheduler": { "version": "0.16.1", "license": "MIT" @@ -3183,10 +3152,6 @@ "source-map": "^0.7.3" } }, - "node_modules/@types/webpack-sources/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@types/webpack-sources/node_modules/source-map": { "version": "0.7.3", "license": "BSD-3-Clause", @@ -3194,10 +3159,6 @@ "node": ">= 8" } }, - "node_modules/@types/webpack/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/@types/yargs": { "version": "15.0.13", "license": "MIT", @@ -10207,10 +10168,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-circus/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-cli": { "version": "26.6.3", "license": "MIT", @@ -10324,10 +10281,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-environment-jsdom/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-environment-node": { "version": "26.6.2", "license": "MIT", @@ -10343,10 +10296,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-environment-node/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-get-type": { "version": "26.3.0", "license": "MIT", @@ -10379,10 +10328,6 @@ "fsevents": "^2.1.2" } }, - "node_modules/jest-haste-map/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-haste-map/node_modules/anymatch": { "version": "3.1.1", "license": "ISC", @@ -10421,10 +10366,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-jasmine2/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-leak-detector": { "version": "26.6.2", "license": "MIT", @@ -10478,10 +10419,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-mock/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-pnp-resolver": { "version": "1.2.2", "license": "MIT", @@ -10562,10 +10499,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-runner/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-runtime": { "version": "26.6.3", "license": "MIT", @@ -10623,10 +10556,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-serializer/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-snapshot": { "version": "26.6.2", "license": "MIT", @@ -10680,10 +10609,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-util/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-validate": { "version": "26.6.2", "license": "MIT", @@ -10744,10 +10669,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-watcher/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/jest-worker": { "version": "26.6.2", "license": "MIT", @@ -10760,10 +10681,6 @@ "node": ">= 10.13.0" } }, - "node_modules/jest-worker/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/js-sha3": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", @@ -15358,10 +15275,6 @@ "estree-walker": "^0.6.1" } }, - "node_modules/rollup/node_modules/@types/node": { - "version": "14.14.31", - "license": "MIT" - }, "node_modules/rsvp": { "version": "4.8.5", "license": "MIT", @@ -20558,11 +20471,6 @@ "jest-message-util": "^26.6.2", "jest-util": "^26.6.2", "slash": "^3.0.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@jest/core": { @@ -20598,9 +20506,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "@types/node": { - "version": "14.14.31" - }, "rimraf": { "version": "3.0.2", "requires": { @@ -20616,11 +20521,6 @@ "@jest/types": "^26.6.2", "@types/node": "*", "jest-mock": "^26.6.2" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@jest/fake-timers": { @@ -20632,11 +20532,6 @@ "jest-message-util": "^26.6.2", "jest-mock": "^26.6.2", "jest-util": "^26.6.2" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@jest/globals": { @@ -20732,11 +20627,6 @@ "@types/node": "*", "@types/yargs": "^15.0.0", "chalk": "^4.0.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@nodelib/fs.scandir": { @@ -21089,22 +20979,12 @@ "requires": { "@types/minimatch": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@types/graceful-fs": { "version": "4.1.5", "requires": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@types/history": { @@ -21149,7 +21029,9 @@ "version": "3.0.3" }, "@types/node": { - "version": "12.20.15" + "version": "12.20.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.16.tgz", + "integrity": "sha512-6CLxw83vQf6DKqXxMPwl8qpF8I7THFZuIwLt4TnNsumxkp1VsRZWT8txQxncT/Rl2UojTsFzWgDG4FRMwafrlA==" }, "@types/normalize-package-data": { "version": "2.4.0" @@ -21215,11 +21097,6 @@ "version": "0.0.8", "requires": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@types/scheduler": { @@ -21255,11 +21132,6 @@ "@types/uglify-js": "*", "@types/webpack-sources": "*", "source-map": "^0.6.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "@types/webpack-sources": { @@ -21270,9 +21142,6 @@ "source-map": "^0.7.3" }, "dependencies": { - "@types/node": { - "version": "14.14.31" - }, "source-map": { "version": "0.7.3" } @@ -25944,11 +25813,6 @@ "pretty-format": "^26.6.0", "stack-utils": "^2.0.2", "throat": "^5.0.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-cli": { @@ -26027,11 +25891,6 @@ "jest-mock": "^26.6.2", "jest-util": "^26.6.2", "jsdom": "^16.4.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-environment-node": { @@ -26043,11 +25902,6 @@ "@types/node": "*", "jest-mock": "^26.6.2", "jest-util": "^26.6.2" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-get-type": { @@ -26072,9 +25926,6 @@ "walker": "^1.0.7" }, "dependencies": { - "@types/node": { - "version": "14.14.31" - }, "anymatch": { "version": "3.1.1", "requires": { @@ -26105,11 +25956,6 @@ "jest-util": "^26.6.2", "pretty-format": "^26.6.2", "throat": "^5.0.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-leak-detector": { @@ -26147,11 +25993,6 @@ "requires": { "@jest/types": "^26.6.2", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-pnp-resolver": { @@ -26205,11 +26046,6 @@ "jest-worker": "^26.6.2", "source-map-support": "^0.5.6", "throat": "^5.0.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-runtime": { @@ -26254,11 +26090,6 @@ "requires": { "@types/node": "*", "graceful-fs": "^4.2.4" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-snapshot": { @@ -26299,11 +26130,6 @@ "graceful-fs": "^4.2.4", "is-ci": "^2.0.0", "micromatch": "^4.0.2" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-validate": { @@ -26344,11 +26170,6 @@ "chalk": "^4.0.0", "jest-util": "^26.6.2", "string-length": "^4.0.1" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "jest-worker": { @@ -26357,11 +26178,6 @@ "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^7.0.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "js-sha3": { @@ -29418,11 +29234,6 @@ "@types/estree": "*", "@types/node": "*", "acorn": "^7.1.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.31" - } } }, "rollup-plugin-babel": { diff --git a/package.json b/package.json index f8bb788..41d670f 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", - "@types/node": "^12.0.0", + "@types/node": "^12.20.16", "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.8", From ad09c2bb1eff5facd7012bb6685d7312746986d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 03:12:18 +0000 Subject: [PATCH 57/78] Bump @types/react-dom from 17.0.8 to 17.0.9 (#30) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 910a7de..1f31e29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "@types/node": "^12.20.16", "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", - "@types/react-dom": "^17.0.8", + "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.7", "ethers": "^5.4.1", "query-string": "^7.0.1", @@ -3068,9 +3068,9 @@ } }, "node_modules/@types/react-dom": { - "version": "17.0.8", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.8.tgz", - "integrity": "sha512-0ohAiJAx1DAUEcY9UopnfwCE9sSMDGnY/oXjWMax6g3RpzmTt2GMyMVAXcbn0mo8XAff0SbQJl2/SBU+hjSZ1A==", + "version": "17.0.9", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz", + "integrity": "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==", "dependencies": { "@types/react": "*" } @@ -21067,9 +21067,9 @@ } }, "@types/react-dom": { - "version": "17.0.8", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.8.tgz", - "integrity": "sha512-0ohAiJAx1DAUEcY9UopnfwCE9sSMDGnY/oXjWMax6g3RpzmTt2GMyMVAXcbn0mo8XAff0SbQJl2/SBU+hjSZ1A==", + "version": "17.0.9", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz", + "integrity": "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==", "requires": { "@types/react": "*" } diff --git a/package.json b/package.json index 41d670f..af8898e 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@types/node": "^12.20.16", "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", - "@types/react-dom": "^17.0.8", + "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.7", "ethers": "^5.4.1", "query-string": "^7.0.1", From c377f6dd29c3af521214ba32925e644c70725187 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 03:19:47 +0000 Subject: [PATCH 58/78] Bump @types/react-router-dom from 5.1.7 to 5.1.8 (#31) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f31e29..d66ad35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.9", - "@types/react-router-dom": "^5.1.7", + "@types/react-router-dom": "^5.1.8", "ethers": "^5.4.1", "query-string": "^7.0.1", "react": "^17.0.2", @@ -3085,9 +3085,9 @@ } }, "node_modules/@types/react-router-dom": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz", - "integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz", + "integrity": "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==", "dependencies": { "@types/history": "*", "@types/react": "*", @@ -21084,9 +21084,9 @@ } }, "@types/react-router-dom": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz", - "integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz", + "integrity": "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==", "requires": { "@types/history": "*", "@types/react": "*", diff --git a/package.json b/package.json index af8898e..5addd4d 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@types/react": "^17.0.14", "@types/react-blockies": "^1.4.0", "@types/react-dom": "^17.0.9", - "@types/react-router-dom": "^5.1.7", + "@types/react-router-dom": "^5.1.8", "ethers": "^5.4.1", "query-string": "^7.0.1", "react": "^17.0.2", From 2b19e1e4f72aa6ab8a9049a2ca82189c618acdea Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 00:46:34 -0300 Subject: [PATCH 59/78] Updated 4bytes repo --- 4bytes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/4bytes b/4bytes index bea447b..3fde3a1 160000 --- a/4bytes +++ b/4bytes @@ -1 +1 @@ -Subproject commit bea447b61551c329215bf11dcf4c57b62210de8a +Subproject commit 3fde3a1b2e002736e9a5e0c35df5bbe386a18d55 From 8b373d3718e3a92bd2a21fca7d46ff1d653c83f2 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 00:46:34 -0300 Subject: [PATCH 60/78] Updated 4bytes repo --- 4bytes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/4bytes b/4bytes index bea447b..3fde3a1 160000 --- a/4bytes +++ b/4bytes @@ -1 +1 @@ -Subproject commit bea447b61551c329215bf11dcf4c57b62210de8a +Subproject commit 3fde3a1b2e002736e9a5e0c35df5bbe386a18d55 From 3d4f743e4d3d82b117b1763b9a80787d4890374f Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 01:02:16 -0300 Subject: [PATCH 61/78] Reorder scripts --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 80a67b1..78a0af0 100644 --- a/package.json +++ b/package.json @@ -42,11 +42,11 @@ "build": "craco build", "test": "craco test", "eject": "react-scripts eject", - "start-docker": "docker run --rm -p 5000:80 --name otterscan -d otterscan", - "stop-docker": "docker stop otterscan", - "build-docker": "docker build -t otterscan -f Dockerfile .", "start-assets": "docker run --rm -p 3001:80 --name otterscan-assets -d -v$(pwd)/4bytes/signatures:/usr/share/nginx/html/signatures/ -v$(pwd)/trustwallet/blockchains/ethereum/assets:/usr/share/nginx/html/assets nginx:1.21.1-alpine", - "stop-assets": "docker stop otterscan-assets" + "stop-assets": "docker stop otterscan-assets", + "build-docker": "docker build -t otterscan -f Dockerfile .", + "start-docker": "docker run --rm -p 5000:80 --name otterscan -d otterscan", + "stop-docker": "docker stop otterscan" }, "eslintConfig": { "extends": [ From f905561dc4fc93b8ee195d5352c31156414cd163 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 01:50:39 -0300 Subject: [PATCH 62/78] Ignore more patterns --- .dockerignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.dockerignore b/.dockerignore index 996deec..df120e1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,6 @@ +.git node_modules +4bytes +!4bytes/signatures trustwallet !trustwallet/blockchains/ethereum/assets From 1a14f4fc9d6f51a08e18f3edcaf2e0110f8c0bf7 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 01:50:55 -0300 Subject: [PATCH 63/78] Deprecate backticks --- run-nginx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run-nginx.sh b/run-nginx.sh index 57cf41d..9cb8352 100755 --- a/run-nginx.sh +++ b/run-nginx.sh @@ -1,4 +1,4 @@ #!/bin/sh -PARAMS=`echo "{\"erigonURL\": \"$ERIGON_URL\"}" | jq -aRs .` +PARAMS=$(echo "{\"erigonURL\": \"$ERIGON_URL\"}" | jq -aRs .) echo $PARAMS > /usr/share/nginx/html/config.json nginx -g "daemon off;" From 3a185057538a14850bd94fbdbab5a7c187f28750 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 02:14:33 -0300 Subject: [PATCH 64/78] Reorder commands to better exploit docker build cache --- Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5062957..eecfd43 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,10 @@ FROM node:12.22.3-alpine AS builder WORKDIR /otterscan-build -COPY ["run-nginx.sh", "package*.json", "tsconfig.json", "craco.config.js", "tailwind.config.js", "/otterscan-build"] -COPY ["src", "/otterscan-build/src"] -COPY ["public", "/otterscan-build/public"] +COPY ["package.json", "package-lock.json", "/otterscan-build"] RUN npm install +COPY ["run-nginx.sh", "tsconfig.json", "craco.config.js", "tailwind.config.js", "/otterscan-build"] +COPY ["public", "/otterscan-build/public"] +COPY ["src", "/otterscan-build/src"] RUN npm run build FROM nginx:1.21.1-alpine From 3e58030a43560f93d22190010dd3f0400f358eca Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 15:05:56 -0300 Subject: [PATCH 65/78] Fix cors for local run --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78a0af0..e069e95 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "build": "craco build", "test": "craco test", "eject": "react-scripts eject", - "start-assets": "docker run --rm -p 3001:80 --name otterscan-assets -d -v$(pwd)/4bytes/signatures:/usr/share/nginx/html/signatures/ -v$(pwd)/trustwallet/blockchains/ethereum/assets:/usr/share/nginx/html/assets nginx:1.21.1-alpine", + "start-assets": "docker run --rm -p 3001:80 --name otterscan-assets -d -v$(pwd)/4bytes/signatures:/usr/share/nginx/html/signatures/ -v$(pwd)/trustwallet/blockchains/ethereum/assets:/usr/share/nginx/html/assets -v$(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf nginx:1.21.1-alpine", "stop-assets": "docker stop otterscan-assets", "build-docker": "docker build -t otterscan -f Dockerfile .", "start-docker": "docker run --rm -p 5000:80 --name otterscan -d otterscan", From da16ce8ad69312db8f3cc34a3cd8e3ab8c9f18b6 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 8 Jul 2021 16:02:42 -0300 Subject: [PATCH 66/78] Parameterize erigon node url --- public/config.json | 3 ++ src/AddressTransactions.tsx | 37 +++++++++++++++------ src/App.tsx | 65 ++++++++++++++++++++----------------- src/Block.tsx | 13 +++++--- src/BlockTransactions.tsx | 13 +++++--- src/Home.tsx | 13 +++++--- src/Transaction.tsx | 21 +++++++++--- src/ethersconfig.ts | 9 ----- src/search/search.ts | 47 ++++++++++++++++++++------- src/useErigon.ts | 25 ++++++++++++++ src/useLatestBlock.ts | 19 ++++++++--- src/useProvider.ts | 26 +++++++++++++++ src/useReverseCache.ts | 11 ++++--- 13 files changed, 216 insertions(+), 86 deletions(-) create mode 100644 public/config.json delete mode 100644 src/ethersconfig.ts create mode 100644 src/useErigon.ts create mode 100644 src/useProvider.ts diff --git a/public/config.json b/public/config.json new file mode 100644 index 0000000..d602ced --- /dev/null +++ b/public/config.json @@ -0,0 +1,3 @@ +{ + "erigonURL": "http://localhost:8545" +} \ No newline at end of file diff --git a/src/AddressTransactions.tsx b/src/AddressTransactions.tsx index 03011cf..f080b96 100644 --- a/src/AddressTransactions.tsx +++ b/src/AddressTransactions.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useMemo } from "react"; +import React, { useState, useEffect, useMemo, useContext } from "react"; import { useParams, useLocation, useHistory } from "react-router-dom"; import { ethers } from "ethers"; import queryString from "query-string"; @@ -12,9 +12,9 @@ import ResultHeader from "./search/ResultHeader"; import PendingResults from "./search/PendingResults"; import TransactionItem from "./search/TransactionItem"; import { SearchController } from "./search/search"; +import { ProviderContext } from "./useProvider"; import { useENSCache } from "./useReverseCache"; import { useFeeToggler } from "./search/useFeeToggler"; -import { provider } from "./ethersconfig"; type BlockParams = { addressOrName: string; @@ -26,6 +26,7 @@ type PageParams = { }; const AddressTransactions: React.FC = () => { + const provider = useContext(ProviderContext); const params = useParams(); const location = useLocation(); const history = useHistory(); @@ -59,6 +60,9 @@ const AddressTransactions: React.FC = () => { return; } + if (!provider) { + return; + } const resolveName = async () => { const resolvedAddress = await provider.resolveName(params.addressOrName); if (resolvedAddress !== null) { @@ -72,20 +76,30 @@ const AddressTransactions: React.FC = () => { } }; resolveName(); - }, [params.addressOrName, history, params.direction, location.search]); + }, [ + provider, + params.addressOrName, + history, + params.direction, + location.search, + ]); const [controller, setController] = useState(); useEffect(() => { - if (!checksummedAddress) { + if (!provider || !checksummedAddress) { return; } const readFirstPage = async () => { - const _controller = await SearchController.firstPage(checksummedAddress); + const _controller = await SearchController.firstPage( + provider, + checksummedAddress + ); setController(_controller); }; const readMiddlePage = async (next: boolean) => { const _controller = await SearchController.middlePage( + provider, checksummedAddress, hash!, next @@ -93,15 +107,18 @@ const AddressTransactions: React.FC = () => { setController(_controller); }; const readLastPage = async () => { - const _controller = await SearchController.lastPage(checksummedAddress); + const _controller = await SearchController.lastPage( + provider, + checksummedAddress + ); setController(_controller); }; const prevPage = async () => { - const _controller = await controller!.prevPage(hash!); + const _controller = await controller!.prevPage(provider, hash!); setController(_controller); }; const nextPage = async () => { - const _controller = await controller!.nextPage(hash!); + const _controller = await controller!.nextPage(provider, hash!); setController(_controller); }; @@ -127,10 +144,10 @@ const AddressTransactions: React.FC = () => { readLastPage(); } } - }, [checksummedAddress, params.direction, hash, controller]); + }, [provider, checksummedAddress, params.direction, hash, controller]); const page = useMemo(() => controller?.getPage(), [controller]); - const reverseCache = useENSCache(page); + const reverseCache = useENSCache(provider, page); document.title = `Address ${params.addressOrName} | Otterscan`; diff --git a/src/App.tsx b/src/App.tsx index 9082f6f..122081c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,40 +3,47 @@ import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; import Home from "./Home"; import Search from "./Search"; import Title from "./Title"; +import { useProvider, ProviderContext } from "./useProvider"; const Block = React.lazy(() => import("./Block")); const BlockTransactions = React.lazy(() => import("./BlockTransactions")); const AddressTransactions = React.lazy(() => import("./AddressTransactions")); const Transaction = React.lazy(() => import("./Transaction")); -const App = () => ( - LOADING}> - - - - - - - - - - - <Route path="/block/:blockNumberOrHash" exact> - <Block /> - </Route> - <Route path="/block/:blockNumber/txs" exact> - <BlockTransactions /> - </Route> - <Route path="/tx/:txhash"> - <Transaction /> - </Route> - <Route path="/address/:addressOrName/:direction?"> - <AddressTransactions /> - </Route> - </Route> - </Switch> - </Router> - </Suspense> -); +const App = () => { + const provider = useProvider(); + + return ( + <Suspense fallback={<>LOADING</>}> + <ProviderContext.Provider value={provider}> + <Router> + <Switch> + <Route path="/" exact> + <Home /> + </Route> + <Route path="/search" exact> + <Search /> + </Route> + <Route> + <Title /> + <Route path="/block/:blockNumberOrHash" exact> + <Block /> + </Route> + <Route path="/block/:blockNumber/txs" exact> + <BlockTransactions /> + </Route> + <Route path="/tx/:txhash"> + <Transaction /> + </Route> + <Route path="/address/:addressOrName/:direction?"> + <AddressTransactions /> + </Route> + </Route> + </Switch> + </Router> + </ProviderContext.Provider> + </Suspense> + ); +}; export default React.memo(App); diff --git a/src/Block.tsx b/src/Block.tsx index 9fd6e25..6f9ab22 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useMemo } from "react"; +import React, { useEffect, useState, useMemo, useContext } from "react"; import { useParams, NavLink } from "react-router-dom"; import { ethers, BigNumber } from "ethers"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -6,7 +6,6 @@ import { faChevronLeft, faChevronRight, } from "@fortawesome/free-solid-svg-icons"; -import { provider } from "./ethersconfig"; import StandardFrame from "./StandardFrame"; import StandardSubtitle from "./StandardSubtitle"; import ContentFrame from "./ContentFrame"; @@ -17,6 +16,7 @@ import BlockLink from "./components/BlockLink"; import AddressOrENSName from "./components/AddressOrENSName"; import TransactionValue from "./components/TransactionValue"; import HexValue from "./components/HexValue"; +import { ProviderContext } from "./useProvider"; import { useLatestBlockNumber } from "./useLatestBlock"; type BlockParams = { @@ -34,10 +34,15 @@ interface ExtendedBlock extends ethers.providers.Block { } const Block: React.FC = () => { + const provider = useContext(ProviderContext); const params = useParams<BlockParams>(); const [block, setBlock] = useState<ExtendedBlock>(); useEffect(() => { + if (!provider) { + return; + } + const readBlock = async () => { let blockPromise: Promise<any>; if (ethers.utils.isHexString(params.blockNumberOrHash, 32)) { @@ -80,7 +85,7 @@ const Block: React.FC = () => { setBlock(extBlock); }; readBlock(); - }, [params.blockNumberOrHash]); + }, [provider, params.blockNumberOrHash]); useEffect(() => { if (block) { @@ -97,7 +102,7 @@ const Block: React.FC = () => { } }, [block]); - const latestBlockNumber = useLatestBlockNumber(); + const latestBlockNumber = useLatestBlockNumber(provider); return ( <StandardFrame> diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index e5712c0..5e6d4ad 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -1,8 +1,7 @@ -import React, { useEffect, useState, useMemo } from "react"; +import React, { useEffect, useState, useMemo, useContext } from "react"; import { useParams, useLocation } from "react-router"; import { ethers } from "ethers"; import queryString from "query-string"; -import { provider } from "./ethersconfig"; import StandardFrame from "./StandardFrame"; import StandardSubtitle from "./StandardSubtitle"; import ContentFrame from "./ContentFrame"; @@ -14,6 +13,7 @@ import BlockLink from "./components/BlockLink"; import { ProcessedTransaction } from "./types"; import { PAGE_SIZE } from "./params"; import { useFeeToggler } from "./search/useFeeToggler"; +import { ProviderContext } from "./useProvider"; import { useENSCache } from "./useReverseCache"; type BlockParams = { @@ -25,6 +25,7 @@ type PageParams = { }; const BlockTransactions: React.FC = () => { + const provider = useContext(ProviderContext); const params = useParams<BlockParams>(); const location = useLocation<PageParams>(); const qs = queryString.parse(location.search); @@ -42,6 +43,10 @@ const BlockTransactions: React.FC = () => { const [txs, setTxs] = useState<ProcessedTransaction[]>(); useEffect(() => { + if (!provider) { + return; + } + const readBlock = async () => { const [_block, _receipts] = await Promise.all([ provider.getBlockWithTransactions(blockNumber.toNumber()), @@ -94,7 +99,7 @@ const BlockTransactions: React.FC = () => { setTxs(processedResponses); }; readBlock(); - }, [blockNumber]); + }, [provider, blockNumber]); const page = useMemo(() => { if (!txs) { @@ -105,7 +110,7 @@ const BlockTransactions: React.FC = () => { }, [txs, pageNumber]); const total = useMemo(() => txs?.length ?? 0, [txs]); - const reverseCache = useENSCache(page); + const reverseCache = useENSCache(provider, page); document.title = `Block #${blockNumber} Txns | Otterscan`; diff --git a/src/Home.tsx b/src/Home.tsx index 82c3cdb..9cc40fc 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,12 +1,13 @@ -import React, { useState } from "react"; +import React, { useState, useContext } from "react"; import { NavLink, useHistory } from "react-router-dom"; import { ethers } from "ethers"; import Logo from "./Logo"; import Timestamp from "./components/Timestamp"; +import { ProviderContext } from "./useProvider"; import { useLatestBlock } from "./useLatestBlock"; -import { ERIGON_NODE } from "./ethersconfig"; const Home: React.FC = () => { + const provider = useContext(ProviderContext); const [search, setSearch] = useState<string>(); const [canSubmit, setCanSubmit] = useState<boolean>(false); const history = useHistory(); @@ -25,7 +26,7 @@ const Home: React.FC = () => { history.push(`/search?q=${search}`); }; - const latestBlock = useLatestBlock(); + const latestBlock = useLatestBlock(provider); document.title = "Home | Otterscan"; @@ -65,7 +66,11 @@ const Home: React.FC = () => { </NavLink> )} <span className="mx-auto mt-5 text-xs text-gray-500"> - Using Erigon node at {ERIGON_NODE} + {provider ? ( + <>Using Erigon node at {provider.connection.url}</> + ) : ( + <>Waiting for the provider...</> + )} </span> </form> </div> diff --git a/src/Transaction.tsx b/src/Transaction.tsx index a461501..724fb31 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -1,4 +1,10 @@ -import React, { useState, useEffect, useCallback, useMemo } from "react"; +import React, { + useState, + useEffect, + useCallback, + useMemo, + useContext, +} from "react"; import { Route, Switch, useParams } from "react-router-dom"; import { BigNumber, ethers } from "ethers"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -6,7 +12,6 @@ import { faCheckCircle, faTimesCircle, } from "@fortawesome/free-solid-svg-icons"; -import { provider } from "./ethersconfig"; import StandardFrame from "./StandardFrame"; import StandardSubtitle from "./StandardSubtitle"; import Tab from "./components/Tab"; @@ -22,6 +27,7 @@ import FormattedBalance from "./components/FormattedBalance"; import TokenTransferItem from "./TokenTransferItem"; import erc20 from "./erc20.json"; import { TokenMetas, TokenTransfer, TransactionData, Transfer } from "./types"; +import { ProviderContext } from "./useProvider"; const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; @@ -31,11 +37,16 @@ type TransactionParams = { }; const Transaction: React.FC = () => { + const provider = useContext(ProviderContext); const params = useParams<TransactionParams>(); const { txhash } = params; const [txData, setTxData] = useState<TransactionData>(); useEffect(() => { + if (!provider) { + return; + } + const readBlock = async () => { const [_response, _receipt] = await Promise.all([ provider.getTransaction(txhash), @@ -109,7 +120,7 @@ const Transaction: React.FC = () => { }); }; readBlock(); - }, [txhash]); + }, [provider, txhash]); const [transfers, setTransfers] = useState<Transfer[]>(); const sendsEthToMiner = useMemo(() => { @@ -126,7 +137,7 @@ const Transaction: React.FC = () => { }, [txData, transfers]); const traceTransfersUsingOtsTrace = useCallback(async () => { - if (!txData) { + if (!provider || !txData) { return; } @@ -143,7 +154,7 @@ const Transaction: React.FC = () => { } setTransfers(_transfers); - }, [txData]); + }, [provider, txData]); useEffect(() => { traceTransfersUsingOtsTrace(); }, [traceTransfersUsingOtsTrace]); diff --git a/src/ethersconfig.ts b/src/ethersconfig.ts deleted file mode 100644 index a7a98a1..0000000 --- a/src/ethersconfig.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ethers } from "ethers"; - -export const ERIGON_NODE = - process.env.REACT_APP_ERIGON_URL || "http://127.0.0.1:8545"; - -export const provider = new ethers.providers.JsonRpcProvider( - ERIGON_NODE, - "mainnet" -); diff --git a/src/search/search.ts b/src/search/search.ts index 3fbcb3e..a78eb81 100644 --- a/src/search/search.ts +++ b/src/search/search.ts @@ -1,5 +1,4 @@ import { ethers } from "ethers"; -import { provider } from "../ethersconfig"; import { PAGE_SIZE } from "../params"; import { ProcessedTransaction, TransactionChunk } from "../types"; @@ -27,7 +26,10 @@ export class SearchController { } } - private static rawToProcessed = (_rawRes: any) => { + private static rawToProcessed = ( + provider: ethers.providers.JsonRpcProvider, + _rawRes: any + ) => { const _res: ethers.providers.TransactionResponse[] = _rawRes.txs.map( (t: any) => provider.formatter.transactionResponse(t) ); @@ -56,6 +58,7 @@ export class SearchController { }; private static async readBackPage( + provider: ethers.providers.JsonRpcProvider, address: string, baseBlock: number ): Promise<TransactionChunk> { @@ -64,10 +67,11 @@ export class SearchController { baseBlock, PAGE_SIZE, ]); - return this.rawToProcessed(_rawRes); + return this.rawToProcessed(provider, _rawRes); } private static async readForwardPage( + provider: ethers.providers.JsonRpcProvider, address: string, baseBlock: number ): Promise<TransactionChunk> { @@ -76,11 +80,14 @@ export class SearchController { baseBlock, PAGE_SIZE, ]); - return this.rawToProcessed(_rawRes); + return this.rawToProcessed(provider, _rawRes); } - static async firstPage(address: string): Promise<SearchController> { - const newTxs = await SearchController.readBackPage(address, 0); + static async firstPage( + provider: ethers.providers.JsonRpcProvider, + address: string + ): Promise<SearchController> { + const newTxs = await SearchController.readBackPage(provider, address, 0); return new SearchController( address, newTxs.txs, @@ -91,14 +98,19 @@ export class SearchController { } static async middlePage( + provider: ethers.providers.JsonRpcProvider, address: string, hash: string, next: boolean ): Promise<SearchController> { const tx = await provider.getTransaction(hash); const newTxs = next - ? await SearchController.readBackPage(address, tx.blockNumber!) - : await SearchController.readForwardPage(address, tx.blockNumber!); + ? await SearchController.readBackPage(provider, address, tx.blockNumber!) + : await SearchController.readForwardPage( + provider, + address, + tx.blockNumber! + ); return new SearchController( address, newTxs.txs, @@ -108,8 +120,11 @@ export class SearchController { ); } - static async lastPage(address: string): Promise<SearchController> { - const newTxs = await SearchController.readForwardPage(address, 0); + static async lastPage( + provider: ethers.providers.JsonRpcProvider, + address: string + ): Promise<SearchController> { + const newTxs = await SearchController.readForwardPage(provider, address, 0); return new SearchController( address, newTxs.txs, @@ -123,7 +138,10 @@ export class SearchController { return this.txs.slice(this.pageStart, this.pageEnd); } - async prevPage(hash: string): Promise<SearchController> { + async prevPage( + provider: ethers.providers.JsonRpcProvider, + hash: string + ): Promise<SearchController> { // Already on this page if (this.txs[this.pageEnd - 1].hash === hash) { return this; @@ -133,6 +151,7 @@ export class SearchController { const overflowPage = this.txs.slice(0, this.pageStart); const baseBlock = this.txs[0].blockNumber; const prevPage = await SearchController.readForwardPage( + provider, this.address, baseBlock ); @@ -148,7 +167,10 @@ export class SearchController { return this; } - async nextPage(hash: string): Promise<SearchController> { + async nextPage( + provider: ethers.providers.JsonRpcProvider, + hash: string + ): Promise<SearchController> { // Already on this page if (this.txs[this.pageStart].hash === hash) { return this; @@ -158,6 +180,7 @@ export class SearchController { const overflowPage = this.txs.slice(this.pageEnd); const baseBlock = this.txs[this.txs.length - 1].blockNumber; const nextPage = await SearchController.readBackPage( + provider, this.address, baseBlock ); diff --git a/src/useErigon.ts b/src/useErigon.ts new file mode 100644 index 0000000..bd64364 --- /dev/null +++ b/src/useErigon.ts @@ -0,0 +1,25 @@ +import { useState, useEffect } from "react"; + +export type OtterscanConfig = { + erigonURL: string; +}; + +export const useErigon = (): [boolean?, OtterscanConfig?] => { + const [configOK, setConfigOK] = useState<boolean>(); + const [config, setConfig] = useState<OtterscanConfig>(); + + useEffect(() => { + const readConfig = async () => { + const res = await fetch("/config.json"); + + if (res.ok) { + const _config: OtterscanConfig = await res.json(); + setConfig(_config); + setConfigOK(res.ok); + } + }; + readConfig(); + }, []); + + return [configOK, config]; +}; diff --git a/src/useLatestBlock.ts b/src/useLatestBlock.ts index fba4011..5ed444b 100644 --- a/src/useLatestBlock.ts +++ b/src/useLatestBlock.ts @@ -1,11 +1,14 @@ import { useState, useEffect } from "react"; import { ethers } from "ethers"; -import { provider } from "./ethersconfig"; -export const useLatestBlock = () => { +export const useLatestBlock = (provider?: ethers.providers.JsonRpcProvider) => { const [latestBlock, setLatestBlock] = useState<ethers.providers.Block>(); useEffect(() => { + if (!provider) { + return; + } + const readLatestBlock = async () => { const blockNum = await provider.getBlockNumber(); const _raw = await provider.send("erigon_getHeaderByNumber", [blockNum]); @@ -26,15 +29,21 @@ export const useLatestBlock = () => { return () => { provider.removeListener("block", listener); }; - }, []); + }, [provider]); return latestBlock; }; -export const useLatestBlockNumber = () => { +export const useLatestBlockNumber = ( + provider?: ethers.providers.JsonRpcProvider +) => { const [latestBlock, setLatestBlock] = useState<number>(); useEffect(() => { + if (!provider) { + return; + } + const readLatestBlock = async () => { const blockNum = await provider.getBlockNumber(); setLatestBlock(blockNum); @@ -49,7 +58,7 @@ export const useLatestBlockNumber = () => { return () => { provider.removeListener("block", listener); }; - }, []); + }, [provider]); return latestBlock; }; diff --git a/src/useProvider.ts b/src/useProvider.ts new file mode 100644 index 0000000..895c16d --- /dev/null +++ b/src/useProvider.ts @@ -0,0 +1,26 @@ +import React from "react"; +import { ethers } from "ethers"; +import { useErigon } from "./useErigon"; + +export const DEFAULT_ERIGON_URL = "http://127.0.0.1:8545"; + +export const useProvider = (): ethers.providers.JsonRpcProvider | undefined => { + const [configOK, config] = useErigon(); + if (!configOK) { + return undefined; + } + + let erigonURL = config?.erigonURL; + if (erigonURL === "") { + console.info(`Using default erigon URL: ${DEFAULT_ERIGON_URL}`); + erigonURL = DEFAULT_ERIGON_URL; + } else { + console.log(`Using configured erigon URL: ${erigonURL}`); + } + + return new ethers.providers.JsonRpcProvider(erigonURL, "mainnet"); +}; + +export const ProviderContext = React.createContext< + ethers.providers.JsonRpcProvider | undefined +>(undefined); diff --git a/src/useReverseCache.ts b/src/useReverseCache.ts index 9451d88..4188904 100644 --- a/src/useReverseCache.ts +++ b/src/useReverseCache.ts @@ -1,12 +1,15 @@ import { useState, useEffect } from "react"; +import { ethers } from "ethers"; import { ENSReverseCache, ProcessedTransaction } from "./types"; -import { provider } from "./ethersconfig"; -export const useENSCache = (page?: ProcessedTransaction[]) => { +export const useENSCache = ( + provider?: ethers.providers.JsonRpcProvider, + page?: ProcessedTransaction[] +) => { const [reverseCache, setReverseCache] = useState<ENSReverseCache>(); useEffect(() => { - if (!page) { + if (!provider || !page) { return; } @@ -38,7 +41,7 @@ export const useENSCache = (page?: ProcessedTransaction[]) => { setReverseCache(cache); }; reverseResolve(); - }, [page]); + }, [provider, page]); return reverseCache; }; From b6b33812c99a0bc5e5e8cb3b9a661587f8a62eab Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Thu, 8 Jul 2021 16:20:22 -0300 Subject: [PATCH 67/78] Fix dynamic config generation --- run-nginx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run-nginx.sh b/run-nginx.sh index 9cb8352..7d83028 100755 --- a/run-nginx.sh +++ b/run-nginx.sh @@ -1,4 +1,4 @@ #!/bin/sh -PARAMS=$(echo "{\"erigonURL\": \"$ERIGON_URL\"}" | jq -aRs .) +PARAMS="{\"erigonURL\": $(echo $ERIGON_URL | jq -aR .)}" echo $PARAMS > /usr/share/nginx/html/config.json nginx -g "daemon off;" From f8cc3fee6d3b019109ee200946c5702bdf4290f0 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Thu, 8 Jul 2021 16:26:09 -0300 Subject: [PATCH 68/78] Add instructions to run otterscan with a custom erigon url --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 3fcf9e2..8de2e32 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,12 @@ To stop Otterscan service, run: docker stop otterscan ``` +By default it assumes your Erigon node is at http://127.0.0.1:8545. You can override the URL by setting the `ERIGON_URL` env variable on `docker run`: + +``` +docker run --rm -p 5000:80 --name otterscan -d --env ERIGON_URL="<your-erigon-node-url>" otterscan/otterscan:<versiontag> +``` + ### (Alternative 1) Build Otterscan docker image locally and run it If you don't want to download from Docker Hub, you can build the docker image from the sources and run it. From dae5111258f43737209a5736b52da1b6934e1eb9 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Thu, 8 Jul 2021 17:57:45 -0300 Subject: [PATCH 69/78] Make docker run the default run method; move alternative methods to their own page --- README.md | 73 ++--------------------------- docs/other-ways-to-run-otterscan.md | 66 ++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 70 deletions(-) create mode 100644 docs/other-ways-to-run-otterscan.md diff --git a/README.md b/README.md index 8de2e32..1b23385 100644 --- a/README.md +++ b/README.md @@ -123,84 +123,17 @@ To stop Otterscan service, run: docker stop otterscan ``` -By default it assumes your Erigon node is at http://127.0.0.1:8545. You can override the URL by setting the `ERIGON_URL` env variable on `docker run`: +By default it assumes your Erigon node is at `http://127.0.0.1:8545`. You can override the URL by setting the `ERIGON_URL` env variable on `docker run`: ``` docker run --rm -p 5000:80 --name otterscan -d --env ERIGON_URL="<your-erigon-node-url>" otterscan/otterscan:<versiontag> ``` -### (Alternative 1) Build Otterscan docker image locally and run it - -If you don't want to download from Docker Hub, you can build the docker image from the sources and run it. - -If you just want to build the image locally, there is no need to install the development toolchain, just make sure you have a recent working Docker installation. - -The entire build process will take place inside the docker multi-stage build. - -Clone Otterscan repo and its submodules. Checkout the tag corresponding to your Erigon + Otterscan patches. It uses the same version tag from Erigon + Otterscan repo, i.e., if you built the `v2021.07.01-otterscan`, you should build the `v2021.07.01-otterscan` of Otterscan. - -``` -git clone --recurse-submodules git@github.com:wmitsuda/otterscan.git -cd otterscan -git checkout <version-tag-otterscan> -docker build -t otterscan -f Dockerfile . -``` - -This will run the entire build process inside a build container, merge the production build of the React app with the 4bytes and trustwallet assets into the same image format it is published in Docker Hub, but locally under the name `otterscan`. - -Then you can start/stop it using the commands: - -``` -docker run --rm -p 5000:80 --name otterscan -d otterscan -docker stop otterscan -``` - -### (Alternative 2) Run a development build from the source - -First, a brief explanation about the app: - -- The app itself is a simple React app which will be run locally and communicates with your Erigon node. -- The app makes use of two sources of external databases for cosmetic reasons: - - Token icons come from the trustwallet public assets repository. - - Method names come from the 4bytes database. -- These 2 repositories were cloned as submodules and are made available to the app through separate http services. They are accessed at browser level and are optional, if the service is down the result will be broken icons and default 4bytes method selectors instead of human-readable names. - -These instructions are subjected to changes in future for the sake of simplification. - -Make sure you have a working node 12/npm installation. - -By default, it assumes your Erigon `rpcdaemon` processs is serving requests at http://127.0.0.1:8545. You can customize this URL by specifying the `REACT_APP_ERIGON_URL` environment variable at build time (it needs to be done at build time because the build process generates a static website). - -To do that, export the variable before running `npm run build`: - -``` -export REACT_APP_ERIGON_URL=<rpcdaemon-url> -``` - -Start serving 4bytes and trustwallet assets at `localhost:3001` using a dockerized nginx: - -``` -npm run start-assets -``` - -To stop it, run: - -``` -npm run stop-assets -``` - -To run Otterscan development build: - -``` -npm install -npm start -``` - -Otterscan should now be running at http://localhost:3000/. +This is the preferred way to run Otterscan. You can read about other ways [here](docs/other-ways-to-run-otterscan.md). ## Validating the installation (all methods) -**You can make sure it is working correctly if the homepage is able to show the latest block/timestamp your Erigon node is at just bellow the search button.** +You can make sure it is working correctly if the homepage is able to show the latest block/timestamp your Erigon node is at just bellow the search button. ## Kudos diff --git a/docs/other-ways-to-run-otterscan.md b/docs/other-ways-to-run-otterscan.md new file mode 100644 index 0000000..0ebd85c --- /dev/null +++ b/docs/other-ways-to-run-otterscan.md @@ -0,0 +1,66 @@ +# Running Otterscan (other methods) + +## (Alternative 1) Build Otterscan docker image locally and run it + +If you don't want to download from Docker Hub, you can build the docker image from the sources and run it. + +If you just want to build the image locally, there is no need to install the development toolchain, just make sure you have a recent working Docker installation. + +This method requires only `git` and `docker`. + +The entire build process will take place inside the docker multi-stage build. + +Clone Otterscan repo and its submodules. Checkout the tag corresponding to your Erigon + Otterscan patches. It uses the same version tag from Erigon + Otterscan repo, i.e., if you built the `v2021.07.01-otterscan`, you should build the `v2021.07.01-otterscan` of Otterscan. + +``` +git clone --recurse-submodules git@github.com:wmitsuda/otterscan.git +cd otterscan +git checkout <version-tag-otterscan> +docker build -t otterscan -f Dockerfile . +``` + +This will run the entire build process inside a build container, merge the production build of the React app with the 4bytes and trustwallet assets into the same image format it is published in Docker Hub, but locally under the name `otterscan`. + +Then you can start/stop it using the commands: + +``` +docker run --rm -p 5000:80 --name otterscan -d otterscan +docker stop otterscan +``` + +## (Alternative 2) Run a development build from the source + +First, a brief explanation about the app: + +- The app itself is a simple React app which will be run locally and communicates with your Erigon node. +- The app makes use of two sources of external databases for cosmetic reasons: + - Token icons come from the trustwallet public assets repository. + - Method names come from the 4bytes database. +- These 2 repositories were cloned as submodules and are made available to the app through separate http services. They are accessed at browser level and are optional, if the service is down the result will be broken icons and default 4bytes method selectors instead of human-readable names. + +These instructions are subjected to changes in future for the sake of simplification. + +Make sure you have a working node 12/npm installation. + +By default, it assumes your Erigon `rpcdaemon` processs is serving requests at `http://localhost:8545`. You can customize this URL by changing the `public/config.json` file. + +Start serving 4bytes and trustwallet assets at `localhost:3001` using a dockerized nginx: + +``` +npm run start-assets +``` + +To stop it, run: + +``` +npm run stop-assets +``` + +To run Otterscan development build: + +``` +npm install +npm start +``` + +Otterscan should now be running at `http://localhost:3000/`. \ No newline at end of file From a50a003ecd15d3dac48d526d5e6d51643ee993da Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Thu, 8 Jul 2021 18:28:26 -0300 Subject: [PATCH 70/78] Add patched erigon repo --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1b23385..9e03faf 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,8 @@ They have weekly stable releases, make sure you are running on of them, not deve Add our forked Erigon git tree as an additional remote and checkout the corresponding branch. +The repository with Otterscan patches is [here](https://github.com/wmitsuda/erigon). + ``` git remote add otterscan git@github.com:wmitsuda/erigon.git ``` From 5d5eaddd6e98e7b3c1d8555e59b3384a8a878d72 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Thu, 8 Jul 2021 18:53:08 -0300 Subject: [PATCH 71/78] Add official docker hub link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e03faf..f9398a7 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ Now you should have an Erigon node with Otterscan jsonrpc APIs enabled, running ### Run Otterscan docker image from Docker Hub -TODO: publish Otterscan official images as soon as it is validated. +The Otterscan official repo on Docker Hub is [here](https://hub.docker.com/orgs/otterscan/repositories). ``` docker run --rm -p 5000:80 --name otterscan -d otterscan/otterscan:<versiontag> From 20b6b98881953b09337110c9c9d56fea4551eecd Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Thu, 8 Jul 2021 21:00:15 -0300 Subject: [PATCH 72/78] nginx config fixes for production image --- nginx.conf | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/nginx.conf b/nginx.conf index 6060f2b..43ebd4a 100644 --- a/nginx.conf +++ b/nginx.conf @@ -4,10 +4,9 @@ server { #access_log /var/log/nginx/host.access.log main; - location / { + location /signatures { root /usr/share/nginx/html; - index index.html index.htm; - + # Base on: https://michielkalkman.com/snippets/nginx-cors-open-configuration/ if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; @@ -38,6 +37,45 @@ server { } } + location /assets { + root /usr/share/nginx/html; + + # Base on: https://michielkalkman.com/snippets/nginx-cors-open-configuration/ + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*'; + # + # Om nom nom cookies + # + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; + + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + + # + # Tell client that this pre-flight info is valid for 20 days + # + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + add_header 'Content-Length' 0; + return 204; + } + if ($request_method = 'GET') { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + } + } + + location / { + root /usr/share/nginx/html; + index index.html; + try_files $uri /index.html; + } + #error_page 404 /404.html; # redirect server error pages to the static page /50x.html From 83d64fc5221d50dbcc0ba8837787b985d272e011 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Fri, 9 Jul 2021 02:07:20 -0300 Subject: [PATCH 73/78] Extract runtime context object --- src/AddressTransactions.tsx | 4 ++-- src/App.tsx | 8 ++++---- src/Block.tsx | 4 ++-- src/BlockTransactions.tsx | 4 ++-- src/Home.tsx | 4 ++-- src/Transaction.tsx | 4 ++-- src/{useErigon.ts => useConfig.ts} | 2 +- src/useProvider.ts | 14 +++++--------- src/useRuntime.ts | 22 ++++++++++++++++++++++ 9 files changed, 42 insertions(+), 24 deletions(-) rename src/{useErigon.ts => useConfig.ts} (89%) create mode 100644 src/useRuntime.ts diff --git a/src/AddressTransactions.tsx b/src/AddressTransactions.tsx index f080b96..e671087 100644 --- a/src/AddressTransactions.tsx +++ b/src/AddressTransactions.tsx @@ -12,7 +12,7 @@ import ResultHeader from "./search/ResultHeader"; import PendingResults from "./search/PendingResults"; import TransactionItem from "./search/TransactionItem"; import { SearchController } from "./search/search"; -import { ProviderContext } from "./useProvider"; +import { RuntimeContext } from "./useRuntime"; import { useENSCache } from "./useReverseCache"; import { useFeeToggler } from "./search/useFeeToggler"; @@ -26,7 +26,7 @@ type PageParams = { }; const AddressTransactions: React.FC = () => { - const provider = useContext(ProviderContext); + const { provider } = useContext(RuntimeContext); const params = useParams<BlockParams>(); const location = useLocation<PageParams>(); const history = useHistory(); diff --git a/src/App.tsx b/src/App.tsx index 122081c..2bf5e2a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; import Home from "./Home"; import Search from "./Search"; import Title from "./Title"; -import { useProvider, ProviderContext } from "./useProvider"; +import { RuntimeContext, useRuntime } from "./useRuntime"; const Block = React.lazy(() => import("./Block")); const BlockTransactions = React.lazy(() => import("./BlockTransactions")); @@ -11,11 +11,11 @@ const AddressTransactions = React.lazy(() => import("./AddressTransactions")); const Transaction = React.lazy(() => import("./Transaction")); const App = () => { - const provider = useProvider(); + const runtime = useRuntime(); return ( <Suspense fallback={<>LOADING</>}> - <ProviderContext.Provider value={provider}> + <RuntimeContext.Provider value={runtime}> <Router> <Switch> <Route path="/" exact> @@ -41,7 +41,7 @@ const App = () => { </Route> </Switch> </Router> - </ProviderContext.Provider> + </RuntimeContext.Provider> </Suspense> ); }; diff --git a/src/Block.tsx b/src/Block.tsx index 6f9ab22..963f2f9 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -16,7 +16,7 @@ import BlockLink from "./components/BlockLink"; import AddressOrENSName from "./components/AddressOrENSName"; import TransactionValue from "./components/TransactionValue"; import HexValue from "./components/HexValue"; -import { ProviderContext } from "./useProvider"; +import { RuntimeContext } from "./useRuntime"; import { useLatestBlockNumber } from "./useLatestBlock"; type BlockParams = { @@ -34,7 +34,7 @@ interface ExtendedBlock extends ethers.providers.Block { } const Block: React.FC = () => { - const provider = useContext(ProviderContext); + const { provider } = useContext(RuntimeContext); const params = useParams<BlockParams>(); const [block, setBlock] = useState<ExtendedBlock>(); diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index 5e6d4ad..8f8f474 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -13,7 +13,7 @@ import BlockLink from "./components/BlockLink"; import { ProcessedTransaction } from "./types"; import { PAGE_SIZE } from "./params"; import { useFeeToggler } from "./search/useFeeToggler"; -import { ProviderContext } from "./useProvider"; +import { RuntimeContext } from "./useRuntime"; import { useENSCache } from "./useReverseCache"; type BlockParams = { @@ -25,7 +25,7 @@ type PageParams = { }; const BlockTransactions: React.FC = () => { - const provider = useContext(ProviderContext); + const { provider } = useContext(RuntimeContext); const params = useParams<BlockParams>(); const location = useLocation<PageParams>(); const qs = queryString.parse(location.search); diff --git a/src/Home.tsx b/src/Home.tsx index 9cc40fc..8626dce 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -3,11 +3,11 @@ import { NavLink, useHistory } from "react-router-dom"; import { ethers } from "ethers"; import Logo from "./Logo"; import Timestamp from "./components/Timestamp"; -import { ProviderContext } from "./useProvider"; +import { RuntimeContext } from "./useRuntime"; import { useLatestBlock } from "./useLatestBlock"; const Home: React.FC = () => { - const provider = useContext(ProviderContext); + const { provider } = useContext(RuntimeContext); const [search, setSearch] = useState<string>(); const [canSubmit, setCanSubmit] = useState<boolean>(false); const history = useHistory(); diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 724fb31..4f8c312 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -27,7 +27,7 @@ import FormattedBalance from "./components/FormattedBalance"; import TokenTransferItem from "./TokenTransferItem"; import erc20 from "./erc20.json"; import { TokenMetas, TokenTransfer, TransactionData, Transfer } from "./types"; -import { ProviderContext } from "./useProvider"; +import { RuntimeContext } from "./useRuntime"; const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; @@ -37,7 +37,7 @@ type TransactionParams = { }; const Transaction: React.FC = () => { - const provider = useContext(ProviderContext); + const { provider } = useContext(RuntimeContext); const params = useParams<TransactionParams>(); const { txhash } = params; diff --git a/src/useErigon.ts b/src/useConfig.ts similarity index 89% rename from src/useErigon.ts rename to src/useConfig.ts index bd64364..df8deb2 100644 --- a/src/useErigon.ts +++ b/src/useConfig.ts @@ -4,7 +4,7 @@ export type OtterscanConfig = { erigonURL: string; }; -export const useErigon = (): [boolean?, OtterscanConfig?] => { +export const useConfig = (): [boolean?, OtterscanConfig?] => { const [configOK, setConfigOK] = useState<boolean>(); const [config, setConfig] = useState<OtterscanConfig>(); diff --git a/src/useProvider.ts b/src/useProvider.ts index 895c16d..08208cf 100644 --- a/src/useProvider.ts +++ b/src/useProvider.ts @@ -1,12 +1,12 @@ -import React from "react"; import { ethers } from "ethers"; -import { useErigon } from "./useErigon"; +import { OtterscanConfig } from "./useConfig"; export const DEFAULT_ERIGON_URL = "http://127.0.0.1:8545"; -export const useProvider = (): ethers.providers.JsonRpcProvider | undefined => { - const [configOK, config] = useErigon(); - if (!configOK) { +export const useProvider = ( + config?: OtterscanConfig +): ethers.providers.JsonRpcProvider | undefined => { + if (!config) { return undefined; } @@ -20,7 +20,3 @@ export const useProvider = (): ethers.providers.JsonRpcProvider | undefined => { return new ethers.providers.JsonRpcProvider(erigonURL, "mainnet"); }; - -export const ProviderContext = React.createContext< - ethers.providers.JsonRpcProvider | undefined ->(undefined); diff --git a/src/useRuntime.ts b/src/useRuntime.ts new file mode 100644 index 0000000..2ebb766 --- /dev/null +++ b/src/useRuntime.ts @@ -0,0 +1,22 @@ +import React from "react"; +import { ethers } from "ethers"; +import { OtterscanConfig, useConfig } from "./useConfig"; +import { useProvider } from "./useProvider"; + +export type OtterscanRuntime = { + config?: OtterscanConfig; + provider?: ethers.providers.JsonRpcProvider; +}; + +export const useRuntime = (): OtterscanRuntime => { + const [configOK, config] = useConfig(); + const provider = useProvider(config); + + if (!configOK) { + return {}; + } + + return { config, provider }; +}; + +export const RuntimeContext = React.createContext<OtterscanRuntime>(null!); From ea7b7a9f75d877d2ecd2e127e0dae9fcb7a3a547 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Fri, 9 Jul 2021 13:54:59 -0300 Subject: [PATCH 74/78] Externalize url prefixes --- public/config.json | 3 ++- src/components/MethodName.tsx | 14 ++++++++++++-- src/components/TokenLogo.tsx | 16 ++++++++++------ src/url.ts | 9 +++++++++ src/useConfig.ts | 3 +++ src/useProvider.ts | 18 ++++++++++-------- src/useRuntime.ts | 12 ++++++++---- 7 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 src/url.ts diff --git a/public/config.json b/public/config.json index d602ced..1db5aa7 100644 --- a/public/config.json +++ b/public/config.json @@ -1,3 +1,4 @@ { - "erigonURL": "http://localhost:8545" + "erigonURL": "http://localhost:8545", + "assetsURLPrefix": "http://localhost:3001" } \ No newline at end of file diff --git a/src/components/MethodName.tsx b/src/components/MethodName.tsx index 27ad8ca..974e69e 100644 --- a/src/components/MethodName.tsx +++ b/src/components/MethodName.tsx @@ -1,10 +1,14 @@ import React, { useState, useEffect } from "react"; +import { fourBytesURL } from "../url"; +import { useRuntime } from "../useRuntime"; type MethodNameProps = { data: string; }; const MethodName: React.FC<MethodNameProps> = ({ data }) => { + const runtime = useRuntime(); + const [name, setName] = useState<string>(); useEffect(() => { if (data === "0x") { @@ -16,7 +20,13 @@ const MethodName: React.FC<MethodNameProps> = ({ data }) => { // Try to resolve 4bytes name const fourBytes = _name.slice(2); - const signatureURL = `http://localhost:3001/signatures/${fourBytes}`; + const { config } = runtime; + if (!config) { + setName(_name); + return; + } + + const signatureURL = fourBytesURL(config.assetsURLPrefix, fourBytes); fetch(signatureURL) .then(async (res) => { if (!res.ok) { @@ -37,7 +47,7 @@ const MethodName: React.FC<MethodNameProps> = ({ data }) => { // Use the default 4 bytes as name setName(_name); - }, [data]); + }, [runtime, data]); return ( <div className="bg-blue-50 rounded-lg px-3 py-1 min-h-full flex items-baseline text-xs max-w-max"> diff --git a/src/components/TokenLogo.tsx b/src/components/TokenLogo.tsx index 738de1c..fab9e2c 100644 --- a/src/components/TokenLogo.tsx +++ b/src/components/TokenLogo.tsx @@ -1,5 +1,7 @@ import React, { Suspense } from "react"; import { useImage } from "react-image"; +import { tokenLogoURL } from "../url"; +import { useRuntime } from "../useRuntime"; type TokenLogoProps = { address: string; @@ -13,12 +15,14 @@ const TokenLogo: React.FC<TokenLogoProps> = (props) => ( ); const InternalTokenLogo: React.FC<TokenLogoProps> = ({ address, name }) => { - const { src } = useImage({ - srcList: [ - `http://localhost:3001/assets/${address}/logo.png`, - "/eth-diamond-black.png", - ], - }); + const { config } = useRuntime(); + + const srcList: string[] = []; + if (config) { + srcList.push(tokenLogoURL(config.assetsURLPrefix, address)); + } + srcList.push("/eth-diamond-black.png"); + const { src } = useImage({ srcList }); return ( <div className="flex items-center justify-center w-5 h-5"> diff --git a/src/url.ts b/src/url.ts new file mode 100644 index 0000000..0586dbe --- /dev/null +++ b/src/url.ts @@ -0,0 +1,9 @@ +export const fourBytesURL = ( + assetsURLPrefix: string, + fourBytes: string +): string => `${assetsURLPrefix}/signatures/${fourBytes}`; + +export const tokenLogoURL = ( + assetsURLPrefix: string, + address: string +): string => `${assetsURLPrefix}/assets/${address}/logo.png`; diff --git a/src/useConfig.ts b/src/useConfig.ts index df8deb2..4e53fb6 100644 --- a/src/useConfig.ts +++ b/src/useConfig.ts @@ -2,6 +2,7 @@ import { useState, useEffect } from "react"; export type OtterscanConfig = { erigonURL: string; + assetsURLPrefix: string; }; export const useConfig = (): [boolean?, OtterscanConfig?] => { @@ -14,6 +15,8 @@ export const useConfig = (): [boolean?, OtterscanConfig?] => { if (res.ok) { const _config: OtterscanConfig = await res.json(); + console.info("Loaded app config"); + console.info(_config); setConfig(_config); setConfigOK(res.ok); } diff --git a/src/useProvider.ts b/src/useProvider.ts index 08208cf..cd4024d 100644 --- a/src/useProvider.ts +++ b/src/useProvider.ts @@ -1,16 +1,11 @@ +import { useMemo } from "react"; import { ethers } from "ethers"; -import { OtterscanConfig } from "./useConfig"; export const DEFAULT_ERIGON_URL = "http://127.0.0.1:8545"; export const useProvider = ( - config?: OtterscanConfig + erigonURL?: string ): ethers.providers.JsonRpcProvider | undefined => { - if (!config) { - return undefined; - } - - let erigonURL = config?.erigonURL; if (erigonURL === "") { console.info(`Using default erigon URL: ${DEFAULT_ERIGON_URL}`); erigonURL = DEFAULT_ERIGON_URL; @@ -18,5 +13,12 @@ export const useProvider = ( console.log(`Using configured erigon URL: ${erigonURL}`); } - return new ethers.providers.JsonRpcProvider(erigonURL, "mainnet"); + const provider = useMemo( + () => new ethers.providers.JsonRpcProvider(erigonURL, "mainnet"), + [erigonURL] + ); + if (!erigonURL) { + return undefined; + } + return provider; }; diff --git a/src/useRuntime.ts b/src/useRuntime.ts index 2ebb766..ed2bcc9 100644 --- a/src/useRuntime.ts +++ b/src/useRuntime.ts @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useMemo } from "react"; import { ethers } from "ethers"; import { OtterscanConfig, useConfig } from "./useConfig"; import { useProvider } from "./useProvider"; @@ -10,13 +10,17 @@ export type OtterscanRuntime = { export const useRuntime = (): OtterscanRuntime => { const [configOK, config] = useConfig(); - const provider = useProvider(config); + const provider = useProvider(configOK ? config?.erigonURL : undefined); + + const runtime = useMemo( + (): OtterscanRuntime => ({ config, provider }), + [config, provider] + ); if (!configOK) { return {}; } - - return { config, provider }; + return runtime; }; export const RuntimeContext = React.createContext<OtterscanRuntime>(null!); From 052b2f61e0196f558dbbba23a4119ef595632b3b Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Fri, 9 Jul 2021 14:13:31 -0300 Subject: [PATCH 75/78] Fixes for the production docker image --- src/components/MethodName.tsx | 2 +- src/components/TokenLogo.tsx | 2 +- src/useConfig.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/MethodName.tsx b/src/components/MethodName.tsx index 974e69e..3a4d710 100644 --- a/src/components/MethodName.tsx +++ b/src/components/MethodName.tsx @@ -26,7 +26,7 @@ const MethodName: React.FC<MethodNameProps> = ({ data }) => { return; } - const signatureURL = fourBytesURL(config.assetsURLPrefix, fourBytes); + const signatureURL = fourBytesURL(config.assetsURLPrefix ?? "", fourBytes); fetch(signatureURL) .then(async (res) => { if (!res.ok) { diff --git a/src/components/TokenLogo.tsx b/src/components/TokenLogo.tsx index fab9e2c..cc2e756 100644 --- a/src/components/TokenLogo.tsx +++ b/src/components/TokenLogo.tsx @@ -19,7 +19,7 @@ const InternalTokenLogo: React.FC<TokenLogoProps> = ({ address, name }) => { const srcList: string[] = []; if (config) { - srcList.push(tokenLogoURL(config.assetsURLPrefix, address)); + srcList.push(tokenLogoURL(config.assetsURLPrefix ?? "", address)); } srcList.push("/eth-diamond-black.png"); const { src } = useImage({ srcList }); diff --git a/src/useConfig.ts b/src/useConfig.ts index 4e53fb6..3bb4858 100644 --- a/src/useConfig.ts +++ b/src/useConfig.ts @@ -1,8 +1,8 @@ import { useState, useEffect } from "react"; export type OtterscanConfig = { - erigonURL: string; - assetsURLPrefix: string; + erigonURL?: string; + assetsURLPrefix?: string; }; export const useConfig = (): [boolean?, OtterscanConfig?] => { From 7b2bdce2105c2eb52c3c9687d712d8e449a52ddd Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Fri, 9 Jul 2021 14:22:25 -0300 Subject: [PATCH 76/78] Fix context use --- src/components/MethodName.tsx | 6 +++--- src/components/TokenLogo.tsx | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/MethodName.tsx b/src/components/MethodName.tsx index 3a4d710..55ff909 100644 --- a/src/components/MethodName.tsx +++ b/src/components/MethodName.tsx @@ -1,13 +1,13 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useContext } from "react"; import { fourBytesURL } from "../url"; -import { useRuntime } from "../useRuntime"; +import { RuntimeContext } from "../useRuntime"; type MethodNameProps = { data: string; }; const MethodName: React.FC<MethodNameProps> = ({ data }) => { - const runtime = useRuntime(); + const runtime = useContext(RuntimeContext); const [name, setName] = useState<string>(); useEffect(() => { diff --git a/src/components/TokenLogo.tsx b/src/components/TokenLogo.tsx index cc2e756..c6f5b8b 100644 --- a/src/components/TokenLogo.tsx +++ b/src/components/TokenLogo.tsx @@ -1,7 +1,7 @@ -import React, { Suspense } from "react"; +import React, { Suspense, useContext } from "react"; import { useImage } from "react-image"; import { tokenLogoURL } from "../url"; -import { useRuntime } from "../useRuntime"; +import { RuntimeContext } from "../useRuntime"; type TokenLogoProps = { address: string; @@ -15,7 +15,7 @@ const TokenLogo: React.FC<TokenLogoProps> = (props) => ( ); const InternalTokenLogo: React.FC<TokenLogoProps> = ({ address, name }) => { - const { config } = useRuntime(); + const { config } = useContext(RuntimeContext); const srcList: string[] = []; if (config) { From 38b6988d103f7bd64e95db16c0ed9c1226ea0979 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda <wmitsuda@gmail.com> Date: Fri, 9 Jul 2021 14:41:48 -0300 Subject: [PATCH 77/78] Caching fixes --- nginx.conf | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/nginx.conf b/nginx.conf index 43ebd4a..029fb69 100644 --- a/nginx.conf +++ b/nginx.conf @@ -6,6 +6,7 @@ server { location /signatures { root /usr/share/nginx/html; + expires 30d; # Base on: https://michielkalkman.com/snippets/nginx-cors-open-configuration/ if ($request_method = 'OPTIONS') { @@ -30,15 +31,16 @@ server { return 204; } if ($request_method = 'GET') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Credentials' 'true' always; + add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always; } } location /assets { root /usr/share/nginx/html; + expires 30d; # Base on: https://michielkalkman.com/snippets/nginx-cors-open-configuration/ if ($request_method = 'OPTIONS') { @@ -63,10 +65,10 @@ server { return 204; } if ($request_method = 'GET') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Credentials' 'true' always; + add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always; } } From 7765f97d1d311aa94eb7b942304da7475dceb46b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Jul 2021 18:19:38 +0000 Subject: [PATCH 78/78] Bump @types/react-blockies from 1.4.0 to 1.4.1 (#32) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index d66ad35..9fe273e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "@types/jest": "^26.0.24", "@types/node": "^12.20.16", "@types/react": "^17.0.14", - "@types/react-blockies": "^1.4.0", + "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.8", "ethers": "^5.4.1", @@ -3060,9 +3060,9 @@ } }, "node_modules/@types/react-blockies": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@types/react-blockies/-/react-blockies-1.4.0.tgz", - "integrity": "sha512-Bw0CraHz5XE61yu64KqfyQ6D9XaPlZo96E2+D2mCE2ZiCeaj5rCRhalHeQ2R684qIInkHACTyAw2BZNWd73PeQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@types/react-blockies/-/react-blockies-1.4.1.tgz", + "integrity": "sha512-aDX0g0hwzdodkGLSDNUQr6gXxwclGjnhS8jhsR8uQhAfe/7i3GZD/NDcSlQ2SiQiLhfRxX3NlY+nvBwf5Y0tTg==", "dependencies": { "@types/react": "*" } @@ -21059,9 +21059,9 @@ } }, "@types/react-blockies": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@types/react-blockies/-/react-blockies-1.4.0.tgz", - "integrity": "sha512-Bw0CraHz5XE61yu64KqfyQ6D9XaPlZo96E2+D2mCE2ZiCeaj5rCRhalHeQ2R684qIInkHACTyAw2BZNWd73PeQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@types/react-blockies/-/react-blockies-1.4.1.tgz", + "integrity": "sha512-aDX0g0hwzdodkGLSDNUQr6gXxwclGjnhS8jhsR8uQhAfe/7i3GZD/NDcSlQ2SiQiLhfRxX3NlY+nvBwf5Y0tTg==", "requires": { "@types/react": "*" } diff --git a/package.json b/package.json index 467f4e9..669bde3 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@types/jest": "^26.0.24", "@types/node": "^12.20.16", "@types/react": "^17.0.14", - "@types/react-blockies": "^1.4.0", + "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.8", "ethers": "^5.4.1",