Turn sourcify intergration mode into a global config
This commit is contained in:
parent
5e982d3b55
commit
bef7691d77
|
@ -31,8 +31,8 @@ import { useENSCache } from "./useReverseCache";
|
||||||
import { useFeeToggler } from "./search/useFeeToggler";
|
import { useFeeToggler } from "./search/useFeeToggler";
|
||||||
import { SelectionContext, useSelection } from "./useSelection";
|
import { SelectionContext, useSelection } from "./useSelection";
|
||||||
import { useMultipleETHUSDOracle } from "./usePriceOracle";
|
import { useMultipleETHUSDOracle } from "./usePriceOracle";
|
||||||
|
import { useAppConfigContext } from "./useAppConfig";
|
||||||
import { useSourcify } from "./useSourcify";
|
import { useSourcify } from "./useSourcify";
|
||||||
import { SourcifySource } from "./url";
|
|
||||||
|
|
||||||
type BlockParams = {
|
type BlockParams = {
|
||||||
addressOrName: string;
|
addressOrName: string;
|
||||||
|
@ -180,9 +180,7 @@ const AddressTransactions: React.FC = () => {
|
||||||
const [feeDisplay, feeDisplayToggler] = useFeeToggler();
|
const [feeDisplay, feeDisplayToggler] = useFeeToggler();
|
||||||
|
|
||||||
const selectionCtx = useSelection();
|
const selectionCtx = useSelection();
|
||||||
const [sourcifySource, setSourcifySource] = useState<SourcifySource>(
|
const { sourcifySource } = useAppConfigContext();
|
||||||
SourcifySource.IPFS_IPNS
|
|
||||||
);
|
|
||||||
const rawMetadata = useSourcify(
|
const rawMetadata = useSourcify(
|
||||||
checksummedAddress,
|
checksummedAddress,
|
||||||
provider?.network.chainId,
|
provider?.network.chainId,
|
||||||
|
@ -316,8 +314,6 @@ const AddressTransactions: React.FC = () => {
|
||||||
<Contracts
|
<Contracts
|
||||||
checksummedAddress={checksummedAddress}
|
checksummedAddress={checksummedAddress}
|
||||||
rawMetadata={rawMetadata}
|
rawMetadata={rawMetadata}
|
||||||
sourcifySource={sourcifySource}
|
|
||||||
setSourcifySource={setSourcifySource}
|
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
15
src/App.tsx
15
src/App.tsx
|
@ -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 { BrowserRouter as Router, Switch, Route } from "react-router-dom";
|
||||||
import WarningHeader from "./WarningHeader";
|
import WarningHeader from "./WarningHeader";
|
||||||
import Home from "./Home";
|
import Home from "./Home";
|
||||||
|
@ -9,6 +9,8 @@ import London from "./special/london/London";
|
||||||
import Footer from "./Footer";
|
import Footer from "./Footer";
|
||||||
import { ConnectionStatus } from "./types";
|
import { ConnectionStatus } from "./types";
|
||||||
import { RuntimeContext, useRuntime } from "./useRuntime";
|
import { RuntimeContext, useRuntime } from "./useRuntime";
|
||||||
|
import { AppConfig, AppConfigContext } from "./useAppConfig";
|
||||||
|
import { SourcifySource } from "./url";
|
||||||
|
|
||||||
const Block = React.lazy(() => import("./Block"));
|
const Block = React.lazy(() => import("./Block"));
|
||||||
const BlockTransactions = React.lazy(() => import("./BlockTransactions"));
|
const BlockTransactions = React.lazy(() => import("./BlockTransactions"));
|
||||||
|
@ -17,6 +19,15 @@ const Transaction = React.lazy(() => import("./Transaction"));
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const runtime = useRuntime();
|
const runtime = useRuntime();
|
||||||
|
const [sourcifySource, setSourcifySource] = useState<SourcifySource>(
|
||||||
|
SourcifySource.IPFS_IPNS
|
||||||
|
);
|
||||||
|
const appConfig = useMemo((): AppConfig => {
|
||||||
|
return {
|
||||||
|
sourcifySource,
|
||||||
|
setSourcifySource,
|
||||||
|
};
|
||||||
|
}, [sourcifySource, setSourcifySource]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<>LOADING</>}>
|
<Suspense fallback={<>LOADING</>}>
|
||||||
|
@ -41,6 +52,7 @@ const App = () => {
|
||||||
<London />
|
<London />
|
||||||
</Route>
|
</Route>
|
||||||
<Route>
|
<Route>
|
||||||
|
<AppConfigContext.Provider value={appConfig}>
|
||||||
<div className="mb-auto">
|
<div className="mb-auto">
|
||||||
<Title />
|
<Title />
|
||||||
<Route path="/block/:blockNumberOrHash" exact>
|
<Route path="/block/:blockNumberOrHash" exact>
|
||||||
|
@ -56,6 +68,7 @@ const App = () => {
|
||||||
<AddressTransactions />
|
<AddressTransactions />
|
||||||
</Route>
|
</Route>
|
||||||
</div>
|
</div>
|
||||||
|
</AppConfigContext.Provider>
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
|
|
|
@ -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);
|
|
@ -5,6 +5,7 @@ import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode";
|
||||||
import useKeyboardShortcut from "use-keyboard-shortcut";
|
import useKeyboardShortcut from "use-keyboard-shortcut";
|
||||||
import PriceBox from "./PriceBox";
|
import PriceBox from "./PriceBox";
|
||||||
import CameraScanner from "./search/CameraScanner";
|
import CameraScanner from "./search/CameraScanner";
|
||||||
|
import SourcifyMenu from "./SourcifyMenu";
|
||||||
import { RuntimeContext } from "./useRuntime";
|
import { RuntimeContext } from "./useRuntime";
|
||||||
|
|
||||||
const Title: React.FC = () => {
|
const Title: React.FC = () => {
|
||||||
|
@ -82,6 +83,7 @@ const Title: React.FC = () => {
|
||||||
Search
|
Search
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
<SourcifyMenu />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -11,8 +11,8 @@ import { RuntimeContext } from "./useRuntime";
|
||||||
import { SelectionContext, useSelection } from "./useSelection";
|
import { SelectionContext, useSelection } from "./useSelection";
|
||||||
import { useInternalOperations, useTxData } from "./useErigonHooks";
|
import { useInternalOperations, useTxData } from "./useErigonHooks";
|
||||||
import { useETHUSDOracle } from "./usePriceOracle";
|
import { useETHUSDOracle } from "./usePriceOracle";
|
||||||
|
import { useAppConfigContext } from "./useAppConfig";
|
||||||
import { useSourcify, useTransactionDescription } from "./useSourcify";
|
import { useSourcify, useTransactionDescription } from "./useSourcify";
|
||||||
import { SourcifySource } from "./url";
|
|
||||||
|
|
||||||
type TransactionParams = {
|
type TransactionParams = {
|
||||||
txhash: string;
|
txhash: string;
|
||||||
|
@ -46,10 +46,11 @@ const Transaction: React.FC = () => {
|
||||||
txData?.confirmedData?.blockNumber
|
txData?.confirmedData?.blockNumber
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { sourcifySource } = useAppConfigContext();
|
||||||
const metadata = useSourcify(
|
const metadata = useSourcify(
|
||||||
txData?.to,
|
txData?.to,
|
||||||
provider?.network.chainId,
|
provider?.network.chainId,
|
||||||
SourcifySource.CENTRAL_SERVER // TODO: use dynamic selector
|
sourcifySource
|
||||||
);
|
);
|
||||||
const txDesc = useTransactionDescription(metadata, txData);
|
const txDesc = useTransactionDescription(metadata, txData);
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { Light as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
import hljs from "highlight.js";
|
import hljs from "highlight.js";
|
||||||
import docco from "react-syntax-highlighter/dist/esm/styles/hljs/docco";
|
import docco from "react-syntax-highlighter/dist/esm/styles/hljs/docco";
|
||||||
import { useContract } from "../useSourcify";
|
import { useContract } from "../useSourcify";
|
||||||
import { SourcifySource } from "../url";
|
|
||||||
|
|
||||||
import hljsDefineSolidity from "highlightjs-solidity";
|
import hljsDefineSolidity from "highlightjs-solidity";
|
||||||
|
import { useAppConfigContext } from "../useAppConfig";
|
||||||
hljsDefineSolidity(hljs);
|
hljsDefineSolidity(hljs);
|
||||||
|
|
||||||
type ContractProps = {
|
type ContractProps = {
|
||||||
|
@ -13,7 +13,6 @@ type ContractProps = {
|
||||||
networkId: number;
|
networkId: number;
|
||||||
filename: string;
|
filename: string;
|
||||||
source: any;
|
source: any;
|
||||||
sourcifySource: SourcifySource;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Contract: React.FC<ContractProps> = ({
|
const Contract: React.FC<ContractProps> = ({
|
||||||
|
@ -21,8 +20,8 @@ const Contract: React.FC<ContractProps> = ({
|
||||||
networkId,
|
networkId,
|
||||||
filename,
|
filename,
|
||||||
source,
|
source,
|
||||||
sourcifySource,
|
|
||||||
}) => {
|
}) => {
|
||||||
|
const { sourcifySource } = useAppConfigContext();
|
||||||
const content = useContract(
|
const content = useContract(
|
||||||
checksummedAddress,
|
checksummedAddress,
|
||||||
networkId,
|
networkId,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useState, useEffect, useContext, Fragment } from "react";
|
import React, { useState, useEffect, useContext, Fragment } from "react";
|
||||||
import { commify } from "@ethersproject/units";
|
import { commify } from "@ethersproject/units";
|
||||||
import { Menu, RadioGroup } from "@headlessui/react";
|
import { Menu } from "@headlessui/react";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
|
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
|
||||||
import ContentFrame from "../ContentFrame";
|
import ContentFrame from "../ContentFrame";
|
||||||
|
@ -11,21 +11,16 @@ import Contract from "./Contract";
|
||||||
import { RuntimeContext } from "../useRuntime";
|
import { RuntimeContext } from "../useRuntime";
|
||||||
import { Metadata } from "../useSourcify";
|
import { Metadata } from "../useSourcify";
|
||||||
import ExternalLink from "../components/ExternalLink";
|
import ExternalLink from "../components/ExternalLink";
|
||||||
import { openInRemixURL, SourcifySource } from "../url";
|
import { openInRemixURL } from "../url";
|
||||||
import RadioButton from "./RadioButton";
|
|
||||||
|
|
||||||
type ContractsProps = {
|
type ContractsProps = {
|
||||||
checksummedAddress: string;
|
checksummedAddress: string;
|
||||||
rawMetadata: Metadata | null | undefined;
|
rawMetadata: Metadata | null | undefined;
|
||||||
sourcifySource: SourcifySource;
|
|
||||||
setSourcifySource: (sourcifySource: SourcifySource) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Contracts: React.FC<ContractsProps> = ({
|
const Contracts: React.FC<ContractsProps> = ({
|
||||||
checksummedAddress,
|
checksummedAddress,
|
||||||
rawMetadata,
|
rawMetadata,
|
||||||
sourcifySource,
|
|
||||||
setSourcifySource,
|
|
||||||
}) => {
|
}) => {
|
||||||
const { provider } = useContext(RuntimeContext);
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
|
||||||
|
@ -39,21 +34,6 @@ const Contracts: React.FC<ContractsProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContentFrame tabs>
|
<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 && (
|
{rawMetadata && (
|
||||||
<>
|
<>
|
||||||
<InfoRow title="Language">
|
<InfoRow title="Language">
|
||||||
|
@ -145,7 +125,6 @@ const Contracts: React.FC<ContractsProps> = ({
|
||||||
networkId={provider!.network.chainId}
|
networkId={provider!.network.chainId}
|
||||||
filename={selected}
|
filename={selected}
|
||||||
source={rawMetadata.sources[selected]}
|
source={rawMetadata.sources[selected]}
|
||||||
sourcifySource={sourcifySource}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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;
|
|
|
@ -3,8 +3,8 @@ import { Interface } from "@ethersproject/abi";
|
||||||
import ContentFrame from "../ContentFrame";
|
import ContentFrame from "../ContentFrame";
|
||||||
import LogEntry from "./LogEntry";
|
import LogEntry from "./LogEntry";
|
||||||
import { TransactionData } from "../types";
|
import { TransactionData } from "../types";
|
||||||
|
import { useAppConfigContext } from "../useAppConfig";
|
||||||
import { Metadata, useMultipleMetadata } from "../useSourcify";
|
import { Metadata, useMultipleMetadata } from "../useSourcify";
|
||||||
import { SourcifySource } from "../url";
|
|
||||||
|
|
||||||
type LogsProps = {
|
type LogsProps = {
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
|
@ -22,6 +22,7 @@ const Logs: React.FC<LogsProps> = ({ txData, metadata }) => {
|
||||||
return md;
|
return md;
|
||||||
}, [txData.to, metadata]);
|
}, [txData.to, metadata]);
|
||||||
|
|
||||||
|
const { sourcifySource } = useAppConfigContext();
|
||||||
const logAddresses = useMemo(
|
const logAddresses = useMemo(
|
||||||
() => txData.confirmedData?.logs.map((l) => l.address) ?? [],
|
() => txData.confirmedData?.logs.map((l) => l.address) ?? [],
|
||||||
[txData]
|
[txData]
|
||||||
|
@ -30,7 +31,7 @@ const Logs: React.FC<LogsProps> = ({ txData, metadata }) => {
|
||||||
baseMetadatas,
|
baseMetadatas,
|
||||||
logAddresses,
|
logAddresses,
|
||||||
1,
|
1,
|
||||||
SourcifySource.CENTRAL_SERVER // TODO: use dynamic selector
|
sourcifySource
|
||||||
);
|
);
|
||||||
const logDesc = useMemo(() => {
|
const logDesc = useMemo(() => {
|
||||||
if (!txData) {
|
if (!txData) {
|
||||||
|
|
|
@ -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);
|
||||||
|
};
|
Loading…
Reference in New Issue