Turn sourcify intergration mode into a global config

This commit is contained in:
Willian Mitsuda 2021-09-23 18:25:52 -03:00
parent 5e982d3b55
commit bef7691d77
10 changed files with 129 additions and 76 deletions

View File

@ -31,8 +31,8 @@ import { useENSCache } from "./useReverseCache";
import { useFeeToggler } from "./search/useFeeToggler";
import { SelectionContext, useSelection } from "./useSelection";
import { useMultipleETHUSDOracle } from "./usePriceOracle";
import { useAppConfigContext } from "./useAppConfig";
import { useSourcify } from "./useSourcify";
import { SourcifySource } from "./url";
type BlockParams = {
addressOrName: string;
@ -180,9 +180,7 @@ const AddressTransactions: React.FC = () => {
const [feeDisplay, feeDisplayToggler] = useFeeToggler();
const selectionCtx = useSelection();
const [sourcifySource, setSourcifySource] = useState<SourcifySource>(
SourcifySource.IPFS_IPNS
);
const { sourcifySource } = useAppConfigContext();
const rawMetadata = useSourcify(
checksummedAddress,
provider?.network.chainId,
@ -316,8 +314,6 @@ const AddressTransactions: React.FC = () => {
<Contracts
checksummedAddress={checksummedAddress}
rawMetadata={rawMetadata}
sourcifySource={sourcifySource}
setSourcifySource={setSourcifySource}
/>
</Route>
</Switch>

View File

@ -1,4 +1,4 @@
import React, { Suspense } from "react";
import React, { Suspense, useMemo, useState } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import WarningHeader from "./WarningHeader";
import Home from "./Home";
@ -9,6 +9,8 @@ import London from "./special/london/London";
import Footer from "./Footer";
import { ConnectionStatus } from "./types";
import { RuntimeContext, useRuntime } from "./useRuntime";
import { AppConfig, AppConfigContext } from "./useAppConfig";
import { SourcifySource } from "./url";
const Block = React.lazy(() => import("./Block"));
const BlockTransactions = React.lazy(() => import("./BlockTransactions"));
@ -17,6 +19,15 @@ const Transaction = React.lazy(() => import("./Transaction"));
const App = () => {
const runtime = useRuntime();
const [sourcifySource, setSourcifySource] = useState<SourcifySource>(
SourcifySource.IPFS_IPNS
);
const appConfig = useMemo((): AppConfig => {
return {
sourcifySource,
setSourcifySource,
};
}, [sourcifySource, setSourcifySource]);
return (
<Suspense fallback={<>LOADING</>}>
@ -41,21 +52,23 @@ const App = () => {
<London />
</Route>
<Route>
<div className="mb-auto">
<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>
</div>
<AppConfigContext.Provider value={appConfig}>
<div className="mb-auto">
<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>
</div>
</AppConfigContext.Provider>
</Route>
</Switch>
</Router>

73
src/SourcifyMenu.tsx Normal file
View File

@ -0,0 +1,73 @@
import React from "react";
import { Menu } from "@headlessui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBars } from "@fortawesome/free-solid-svg-icons/faBars";
import { SourcifySource } from "./url";
import { useAppConfigContext } from "./useAppConfig";
const SourcifyMenu: React.FC = () => {
const { sourcifySource, setSourcifySource } = useAppConfigContext();
return (
<Menu>
<div className="relative self-stretch">
<Menu.Button className="w-full h-full flex justify-center items-center space-x-2 text-sm border rounded px-2 py-1">
<FontAwesomeIcon icon={faBars} size="1x" />
</Menu.Button>
<Menu.Items className="absolute right-0 mt-1 border p-1 rounded-b bg-white flex flex-col text-sm min-w-max">
<div className="px-2 py-1 text-xs border-b border-gray-300">
Sourcify Datasource
</div>
<SourcifyMenuItem
checked={sourcifySource === SourcifySource.IPFS_IPNS}
onClick={() => setSourcifySource(SourcifySource.IPFS_IPNS)}
>
Resolve IPNS
</SourcifyMenuItem>
<SourcifyMenuItem
checked={sourcifySource === SourcifySource.CENTRAL_SERVER}
onClick={() => setSourcifySource(SourcifySource.CENTRAL_SERVER)}
>
Sourcify Servers
</SourcifyMenuItem>
<SourcifyMenuItem
checked={sourcifySource === SourcifySource.CUSTOM_SNAPSHOT_SERVER}
onClick={() =>
setSourcifySource(SourcifySource.CUSTOM_SNAPSHOT_SERVER)
}
>
Local Snapshot
</SourcifyMenuItem>
</Menu.Items>
</div>
</Menu>
);
};
type SourcifyMenuItemProps = {
checked?: boolean;
onClick: () => void;
};
const SourcifyMenuItem: React.FC<SourcifyMenuItemProps> = ({
checked = false,
onClick,
children,
}) => (
<Menu.Item>
{({ active }) => (
<button
className={`text-sm text-left px-2 py-1 ${
active ? "border-orange-200 text-gray-500" : "text-gray-400"
} transition-transform transition-colors duration-75 ${
checked ? "text-gray-900" : ""
}`}
onClick={onClick}
>
{children}
</button>
)}
</Menu.Item>
);
export default React.memo(SourcifyMenu);

View File

@ -5,6 +5,7 @@ import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode";
import useKeyboardShortcut from "use-keyboard-shortcut";
import PriceBox from "./PriceBox";
import CameraScanner from "./search/CameraScanner";
import SourcifyMenu from "./SourcifyMenu";
import { RuntimeContext } from "./useRuntime";
const Title: React.FC = () => {
@ -82,6 +83,7 @@ const Title: React.FC = () => {
Search
</button>
</form>
<SourcifyMenu />
</div>
</div>
</>

View File

@ -11,8 +11,8 @@ import { RuntimeContext } from "./useRuntime";
import { SelectionContext, useSelection } from "./useSelection";
import { useInternalOperations, useTxData } from "./useErigonHooks";
import { useETHUSDOracle } from "./usePriceOracle";
import { useAppConfigContext } from "./useAppConfig";
import { useSourcify, useTransactionDescription } from "./useSourcify";
import { SourcifySource } from "./url";
type TransactionParams = {
txhash: string;
@ -46,10 +46,11 @@ const Transaction: React.FC = () => {
txData?.confirmedData?.blockNumber
);
const { sourcifySource } = useAppConfigContext();
const metadata = useSourcify(
txData?.to,
provider?.network.chainId,
SourcifySource.CENTRAL_SERVER // TODO: use dynamic selector
sourcifySource
);
const txDesc = useTransactionDescription(metadata, txData);

View File

@ -3,9 +3,9 @@ import { Light as SyntaxHighlighter } from "react-syntax-highlighter";
import hljs from "highlight.js";
import docco from "react-syntax-highlighter/dist/esm/styles/hljs/docco";
import { useContract } from "../useSourcify";
import { SourcifySource } from "../url";
import hljsDefineSolidity from "highlightjs-solidity";
import { useAppConfigContext } from "../useAppConfig";
hljsDefineSolidity(hljs);
type ContractProps = {
@ -13,7 +13,6 @@ type ContractProps = {
networkId: number;
filename: string;
source: any;
sourcifySource: SourcifySource;
};
const Contract: React.FC<ContractProps> = ({
@ -21,8 +20,8 @@ const Contract: React.FC<ContractProps> = ({
networkId,
filename,
source,
sourcifySource,
}) => {
const { sourcifySource } = useAppConfigContext();
const content = useContract(
checksummedAddress,
networkId,

View File

@ -1,6 +1,6 @@
import React, { useState, useEffect, useContext, Fragment } from "react";
import { commify } from "@ethersproject/units";
import { Menu, RadioGroup } from "@headlessui/react";
import { Menu } from "@headlessui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
import ContentFrame from "../ContentFrame";
@ -11,21 +11,16 @@ import Contract from "./Contract";
import { RuntimeContext } from "../useRuntime";
import { Metadata } from "../useSourcify";
import ExternalLink from "../components/ExternalLink";
import { openInRemixURL, SourcifySource } from "../url";
import RadioButton from "./RadioButton";
import { openInRemixURL } from "../url";
type ContractsProps = {
checksummedAddress: string;
rawMetadata: Metadata | null | undefined;
sourcifySource: SourcifySource;
setSourcifySource: (sourcifySource: SourcifySource) => void;
};
const Contracts: React.FC<ContractsProps> = ({
checksummedAddress,
rawMetadata,
sourcifySource,
setSourcifySource,
}) => {
const { provider } = useContext(RuntimeContext);
@ -39,21 +34,6 @@ const Contracts: React.FC<ContractsProps> = ({
return (
<ContentFrame tabs>
<InfoRow title="Sourcify integration">
<RadioGroup value={sourcifySource} onChange={setSourcifySource}>
<div className="flex space-x-2">
<RadioButton value={SourcifySource.IPFS_IPNS}>
Resolve IPNS @localhost:8080 gateway
</RadioButton>
<RadioButton value={SourcifySource.CENTRAL_SERVER}>
Sourcify Servers
</RadioButton>
<RadioButton value={SourcifySource.CUSTOM_SNAPSHOT_SERVER}>
Local Snapshot @localhost:3006
</RadioButton>
</div>
</RadioGroup>
</InfoRow>
{rawMetadata && (
<>
<InfoRow title="Language">
@ -145,7 +125,6 @@ const Contracts: React.FC<ContractsProps> = ({
networkId={provider!.network.chainId}
filename={selected}
source={rawMetadata.sources[selected]}
sourcifySource={sourcifySource}
/>
)}
</div>

View File

@ -1,24 +0,0 @@
import React from "react";
import { RadioGroup } from "@headlessui/react";
import { SourcifySource } from "../url";
type RadioButtonProps = {
value: SourcifySource;
};
const RadioButton: React.FC<RadioButtonProps> = ({ value, children }) => (
<RadioGroup.Option
className={({ checked }) =>
`border rounded px-2 py-1 cursor-pointer ${
checked
? "bg-blue-400 hover:bg-blue-500 text-white"
: "hover:bg-gray-200"
}`
}
value={value}
>
{children}
</RadioGroup.Option>
);
export default RadioButton;

View File

@ -3,8 +3,8 @@ import { Interface } from "@ethersproject/abi";
import ContentFrame from "../ContentFrame";
import LogEntry from "./LogEntry";
import { TransactionData } from "../types";
import { useAppConfigContext } from "../useAppConfig";
import { Metadata, useMultipleMetadata } from "../useSourcify";
import { SourcifySource } from "../url";
type LogsProps = {
txData: TransactionData;
@ -22,6 +22,7 @@ const Logs: React.FC<LogsProps> = ({ txData, metadata }) => {
return md;
}, [txData.to, metadata]);
const { sourcifySource } = useAppConfigContext();
const logAddresses = useMemo(
() => txData.confirmedData?.logs.map((l) => l.address) ?? [],
[txData]
@ -30,7 +31,7 @@ const Logs: React.FC<LogsProps> = ({ txData, metadata }) => {
baseMetadatas,
logAddresses,
1,
SourcifySource.CENTRAL_SERVER // TODO: use dynamic selector
sourcifySource
);
const logDesc = useMemo(() => {
if (!txData) {

13
src/useAppConfig.ts Normal file
View File

@ -0,0 +1,13 @@
import React, { useContext } from "react";
import { SourcifySource } from "./url";
export type AppConfig = {
sourcifySource: SourcifySource;
setSourcifySource: (newSourcifySource: SourcifySource) => void;
};
export const AppConfigContext = React.createContext<AppConfig>(undefined!);
export const useAppConfigContext = () => {
return useContext(AppConfigContext);
};