From 71cd332fb50caf4e3ea3fc07f099d861645daa2a Mon Sep 17 00:00:00 2001 From: Richard Watts Date: Mon, 30 Sep 2024 14:56:50 +0100 Subject: [PATCH 1/5] (feat) Search instructions --- README.zilliqa.md | 10 ++++++ src/Header.tsx | 64 ++++++++++++++++++++++++++++++++++- src/components/InlineCode.tsx | 14 ++++++++ src/search/search.ts | 9 ++++- 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/components/InlineCode.tsx diff --git a/README.zilliqa.md b/README.zilliqa.md index f3b97d6a..8a3a0051 100644 --- a/README.zilliqa.md +++ b/README.zilliqa.md @@ -14,3 +14,13 @@ ignore changes to them, they are generated by `npm start` as well as Be warned! If you use `vite` directly, you may end up with analysis errors due to their absence. + +## Starting for development + +.. because I keep forgetting! + +``` +export VITE_ERIGON_URL= +npm run assets-start +npm start +``` diff --git a/src/Header.tsx b/src/Header.tsx index 4867fdad..27b9916a 100644 --- a/src/Header.tsx +++ b/src/Header.tsx @@ -1,4 +1,4 @@ -import { faQrcode } from "@fortawesome/free-solid-svg-icons"; +import { faQrcode, faQuestionCircle } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FC, lazy, memo, useContext, useState } from "react"; import { Link } from "react-router-dom"; @@ -6,16 +6,20 @@ import PriceBox from "./PriceBox"; import SourcifyMenu from "./SourcifyMenu"; import { useGenericSearch } from "./search/search"; import { RuntimeContext } from "./useRuntime"; +import InlineCode from "./components/InlineCode"; // @ts-expect-error import Otter from "./otter.png?w=128&h=128&webp"; const CameraScanner = lazy(() => import("./search/CameraScanner")); type HeaderProps = { sourcifyPresent: boolean }; +// Should really move out to utils + const Header: FC = ({ sourcifyPresent }) => { const { config, provider } = useContext(RuntimeContext); const [searchRef, handleChange, handleSubmit] = useGenericSearch(); const [isScanning, setScanning] = useState(false); + const [isHelpOpen, setHelpOpen] = useState(false); return ( <> @@ -79,6 +83,14 @@ const Header: FC = ({ sourcifyPresent }) => { > + + + + + + )} + ); }; diff --git a/src/components/InlineCode.tsx b/src/components/InlineCode.tsx new file mode 100644 index 00000000..857d2cd2 --- /dev/null +++ b/src/components/InlineCode.tsx @@ -0,0 +1,14 @@ +import React from 'react'; + +type InlineCodeProps = React.PropsWithChildren<{ + children: React.RectNode; +}>; + +const InlineCode: React.FC = ({children}) => ( + + {children} + +); + +export default React.memo(InlineCode); + diff --git a/src/search/search.ts b/src/search/search.ts index 7ed82130..5aede7a9 100644 --- a/src/search/search.ts +++ b/src/search/search.ts @@ -266,6 +266,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { // Plain address? if (isAddress(maybeAddress)) { + console.log(`maybeAddress ${maybeAddress} is an address ..`); navigate( `/address/${maybeAddress}${ maybeIndex !== "" ? `?nonce=${maybeIndex}` : "" @@ -276,6 +277,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { // Tx hash? if (isHexString(q, 32)) { + console.log(`This looks like a txn hash - ${q}`); navigate(`/tx/${q}`); return; } else if (isHexString(`0x${q}`, 32)) { @@ -288,6 +290,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { // will cause errors, so .. try { const blockNumber = BigInt(q); + console.log(`Parses as a block number ${blockNumber}`); navigate(`/block/${blockNumber.toString()}`); return; } catch (e) { @@ -298,6 +301,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { if (q.charAt(0) === "#") { const dsBlockNumber = parseInt(q.substring(1)); if (!isNaN(dsBlockNumber)) { + console.log(`# ${dsBlockNumber} - it's a ds block number`); navigate(`/dsblock/${dsBlockNumber}`); return; } @@ -308,6 +312,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { const mayBeEpoch = q.substring(6); const epoch = parseInt(mayBeEpoch); if (!isNaN(epoch)) { + console.log(`epoch: ${epoch}`); navigate(`/epoch/${epoch}`); return; } @@ -318,6 +323,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { const mayBeSlot = q.substring(5); const slot = parseInt(mayBeSlot); if (!isNaN(slot)) { + console.log(`slot: ${slot}`); navigate(`/slot/${slot}`); return; } @@ -326,9 +332,9 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { // Validator? if (q.startsWith("validator:")) { const mayBeValidator = q.substring(10); - // Validator by index if (mayBeValidator.match(/^\d+$/)) { + console.log(`validator: ${validator}`); const validatorIndex = parseInt(mayBeValidator); navigate(`/validator/${validatorIndex}`); return; @@ -342,6 +348,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { } // Assume it is an ENS name + console.log(`no match: assuming ${maybeAddress} is an ENS name`); navigate( `/address/${maybeAddress}${ maybeIndex !== "" ? `?nonce=${maybeIndex}` : "" From 3ad59199f6e86703a40a4c532a6aae981f8f390c Mon Sep 17 00:00:00 2001 From: Richard Watts Date: Mon, 30 Sep 2024 16:10:26 +0100 Subject: [PATCH 2/5] (fix) Search now works again (erm, I think) (feat) A help box for search. (feat) Search by bech32 address --- src/search/search.ts | 46 ++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/search/search.ts b/src/search/search.ts index 5aede7a9..9793b908 100644 --- a/src/search/search.ts +++ b/src/search/search.ts @@ -21,6 +21,7 @@ import { import { PAGE_SIZE } from "../params"; import { ProcessedTransaction, TransactionChunk } from "../types"; import { formatter } from "../utils/formatter"; +import { fromBech32Address } from "@zilliqa-js/crypto"; export const rawToProcessed = (provider: JsonRpcApiProvider, _rawRes: any) => { const _res: TransactionResponse[] = _rawRes.txs.map( @@ -247,6 +248,24 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { maybeIndex = q.substring(sepIndex + 1); } + // Tx hash? + if (isHexString(q, 32)) { + console.log(`search: this looks like a txn hash - ${q}`); + navigate(`/tx/${q}`); + return; + } else if (isHexString(`0x${q}`, 32)) { + navigate(`/tx/0x${q}`); + return; + } + + // Zilliqa address? + try { + maybeAddress = fromBech32Address(maybeAddress); + console.log(`search: bech32 address to base16 - ${maybeAddress}`); + } catch (e) { + console.log(`search: Not a bech32 address`); + } + // The type checker is convinced that ethers:isAddress() will never say that a string > 40 characters // long is not an address. I'm not sure why... if (!isAddress(maybeAddress)) { @@ -266,7 +285,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { // Plain address? if (isAddress(maybeAddress)) { - console.log(`maybeAddress ${maybeAddress} is an address ..`); + console.log(`search: maybeAddress ${maybeAddress} is an address ..`); navigate( `/address/${maybeAddress}${ maybeIndex !== "" ? `?nonce=${maybeIndex}` : "" @@ -275,22 +294,15 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { return; } - // Tx hash? - if (isHexString(q, 32)) { - console.log(`This looks like a txn hash - ${q}`); - navigate(`/tx/${q}`); - return; - } else if (isHexString(`0x${q}`, 32)) { - navigate(`/tx/0x${q}`); - return; - } // Block number? // If the number here is very large, parseInt() will return an fp number which // will cause errors, so .. try { - const blockNumber = BigInt(q); - console.log(`Parses as a block number ${blockNumber}`); + let toParse = q; + console.log(`search: try to parse ${toParse} as a block number`); + const blockNumber = BigInt(toParse); + console.log(`search: ${toParse} Parses as a block number ${blockNumber}`); navigate(`/block/${blockNumber.toString()}`); return; } catch (e) { @@ -301,7 +313,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { if (q.charAt(0) === "#") { const dsBlockNumber = parseInt(q.substring(1)); if (!isNaN(dsBlockNumber)) { - console.log(`# ${dsBlockNumber} - it's a ds block number`); + console.log(`search: # ${dsBlockNumber} - it's a ds block number`); navigate(`/dsblock/${dsBlockNumber}`); return; } @@ -312,7 +324,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { const mayBeEpoch = q.substring(6); const epoch = parseInt(mayBeEpoch); if (!isNaN(epoch)) { - console.log(`epoch: ${epoch}`); + console.log(`search: epoch: ${epoch}`); navigate(`/epoch/${epoch}`); return; } @@ -323,14 +335,14 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { const mayBeSlot = q.substring(5); const slot = parseInt(mayBeSlot); if (!isNaN(slot)) { - console.log(`slot: ${slot}`); + console.log(`search: slot: ${slot}`); navigate(`/slot/${slot}`); return; } } // Validator? - if (q.startsWith("validator:")) { + if (q.startsWith("search - validator:")) { const mayBeValidator = q.substring(10); // Validator by index if (mayBeValidator.match(/^\d+$/)) { @@ -348,7 +360,7 @@ const doSearch = async (q: string, navigate: NavigateFunction) => { } // Assume it is an ENS name - console.log(`no match: assuming ${maybeAddress} is an ENS name`); + console.log(`search: no match: assuming ${maybeAddress} is an ENS name`); navigate( `/address/${maybeAddress}${ maybeIndex !== "" ? `?nonce=${maybeIndex}` : "" From 148aefd2eee01832a4d853c8657e15b314da6496 Mon Sep 17 00:00:00 2001 From: Richard Watts Date: Mon, 30 Sep 2024 16:11:50 +0100 Subject: [PATCH 3/5] (fix) Fix search box --- src/Header.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Header.tsx b/src/Header.tsx index 27b9916a..732267dd 100644 --- a/src/Header.tsx +++ b/src/Header.tsx @@ -124,6 +124,7 @@ const Header: FC = ({ sourcifyPresent }) => {


    +
  • A bech32 address if it is in the right format.
  • An address if we can (right length, starts with 0x or zil1).
  • If a 32-character hex string we'll try to search as a transaction id
  • If a > 40 character hex string, we'll think it's probably an address with leading 0s.
  • From d45bec1d502d880dda72d32c5eb0503dc12b5416 Mon Sep 17 00:00:00 2001 From: Richard Watts Date: Mon, 30 Sep 2024 16:12:30 +0100 Subject: [PATCH 4/5] (fix ) prettier --- src/Header.tsx | 122 ++++++++++++++++++++++++---------- src/components/InlineCode.tsx | 5 +- src/search/search.ts | 3 +- 3 files changed, 90 insertions(+), 40 deletions(-) diff --git a/src/Header.tsx b/src/Header.tsx index 732267dd..6b17c61a 100644 --- a/src/Header.tsx +++ b/src/Header.tsx @@ -4,9 +4,9 @@ import { FC, lazy, memo, useContext, useState } from "react"; import { Link } from "react-router-dom"; import PriceBox from "./PriceBox"; import SourcifyMenu from "./SourcifyMenu"; +import InlineCode from "./components/InlineCode"; import { useGenericSearch } from "./search/search"; import { RuntimeContext } from "./useRuntime"; -import InlineCode from "./components/InlineCode"; // @ts-expect-error import Otter from "./otter.png?w=128&h=128&webp"; @@ -84,13 +84,13 @@ const Header: FC = ({ sourcifyPresent }) => { + className="border bg-skin-button-fill px-2 py-1 text-sm text-skin-button hover:bg-skin-button-hover-fill focus:outline-none" + type="button" + onClick={() => setHelpOpen(true)} + title="Help with searching" + > + +