Merge branch 'feature/better-abi-ui' into develop
This commit is contained in:
commit
c411900c67
92
package-lock.json
generated
92
package-lock.json
generated
@ -30,7 +30,6 @@
|
||||
"@types/react": "^17.0.31",
|
||||
"@types/react-blockies": "^1.4.1",
|
||||
"@types/react-dom": "^17.0.10",
|
||||
"@types/react-helmet": "^6.1.4",
|
||||
"@types/react-highlight": "^0.12.5",
|
||||
"@types/react-router-dom": "^5.3.1",
|
||||
"@types/react-syntax-highlighter": "^13.5.2",
|
||||
@ -43,7 +42,7 @@
|
||||
"react-chartjs-2": "^3.2.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-error-boundary": "^3.1.3",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-helmet-async": "^1.1.2",
|
||||
"react-image": "^4.0.3",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-scripts": "4.0.3",
|
||||
@ -3119,14 +3118,6 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-helmet": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.4.tgz",
|
||||
"integrity": "sha512-jyx50RNZXVaTGHY3MsoRPNpeiVk8b0XTPgD/O6KHF6COTDnG/+lRjPYvTK5nfWtR3xDOux0w6bHLAsaHo2ZLTA==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-highlight": {
|
||||
"version": "0.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-highlight/-/react-highlight-0.12.5.tgz",
|
||||
@ -9839,6 +9830,14 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ip": {
|
||||
"version": "1.1.5",
|
||||
"license": "MIT"
|
||||
@ -14588,18 +14587,20 @@
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
},
|
||||
"node_modules/react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||
"node_modules/react-helmet-async": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.1.2.tgz",
|
||||
"integrity": "sha512-LTTzDDkyIleT/JJ6T/uqx7Y8qi1EuPPSiJawQY/nHHz0h7SPDT6HxP1YDDQx/fzcVxCqpWEEMS3QdrSrNkJYhg==",
|
||||
"dependencies": {
|
||||
"object-assign": "^4.1.1",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.1.1",
|
||||
"react-side-effect": "^2.1.0"
|
||||
"react-fast-compare": "^3.2.0",
|
||||
"shallowequal": "^1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.3.0"
|
||||
"react": "^16.6.0 || ^17.0.0",
|
||||
"react-dom": "^16.6.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-image": {
|
||||
@ -14949,14 +14950,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-side-effect": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz",
|
||||
"integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-syntax-highlighter": {
|
||||
"version": "15.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.4.tgz",
|
||||
@ -16314,6 +16307,11 @@
|
||||
"sha.js": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/shallowequal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
|
||||
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
@ -21703,14 +21701,6 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-helmet": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.4.tgz",
|
||||
"integrity": "sha512-jyx50RNZXVaTGHY3MsoRPNpeiVk8b0XTPgD/O6KHF6COTDnG/+lRjPYvTK5nfWtR3xDOux0w6bHLAsaHo2ZLTA==",
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-highlight": {
|
||||
"version": "0.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-highlight/-/react-highlight-0.12.5.tgz",
|
||||
@ -26271,6 +26261,14 @@
|
||||
"side-channel": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ip": {
|
||||
"version": "1.1.5"
|
||||
},
|
||||
@ -29420,15 +29418,16 @@
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
},
|
||||
"react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||
"react-helmet-async": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.1.2.tgz",
|
||||
"integrity": "sha512-LTTzDDkyIleT/JJ6T/uqx7Y8qi1EuPPSiJawQY/nHHz0h7SPDT6HxP1YDDQx/fzcVxCqpWEEMS3QdrSrNkJYhg==",
|
||||
"requires": {
|
||||
"object-assign": "^4.1.1",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.1.1",
|
||||
"react-side-effect": "^2.1.0"
|
||||
"react-fast-compare": "^3.2.0",
|
||||
"shallowequal": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"react-image": {
|
||||
@ -29675,12 +29674,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz",
|
||||
"integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-syntax-highlighter": {
|
||||
"version": "15.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.4.tgz",
|
||||
@ -30615,6 +30608,11 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"shallowequal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
|
||||
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"requires": {
|
||||
|
@ -25,7 +25,6 @@
|
||||
"@types/react": "^17.0.31",
|
||||
"@types/react-blockies": "^1.4.1",
|
||||
"@types/react-dom": "^17.0.10",
|
||||
"@types/react-helmet": "^6.1.4",
|
||||
"@types/react-highlight": "^0.12.5",
|
||||
"@types/react-router-dom": "^5.3.1",
|
||||
"@types/react-syntax-highlighter": "^13.5.2",
|
||||
@ -38,7 +37,7 @@
|
||||
"react-chartjs-2": "^3.2.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-error-boundary": "^3.1.3",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-helmet-async": "^1.1.2",
|
||||
"react-image": "^4.0.3",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-scripts": "4.0.3",
|
||||
|
35
src/address/ContractABI.tsx
Normal file
35
src/address/ContractABI.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import React from "react";
|
||||
import { Tab } from "@headlessui/react";
|
||||
import ModeTab from "../components/ModeTab";
|
||||
import Copy from "../components/Copy";
|
||||
import DecodedABI from "./DecodedABI";
|
||||
import RawABI from "./RawABI";
|
||||
|
||||
type ContractABIProps = {
|
||||
abi: any[];
|
||||
};
|
||||
|
||||
const ContractABI: React.FC<ContractABIProps> = ({ abi }) => (
|
||||
<div className="mb-3">
|
||||
<Tab.Group>
|
||||
<Tab.List className="flex items-baseline space-x-1 mb-1">
|
||||
<div className="flex items-baseline space-x-2 text-sm pr-2 py-1">
|
||||
<span>ABI</span>
|
||||
<Copy value={JSON.stringify(abi)} />
|
||||
</div>
|
||||
<ModeTab>Decoded</ModeTab>
|
||||
<ModeTab>Raw</ModeTab>
|
||||
</Tab.List>
|
||||
<Tab.Panels>
|
||||
<Tab.Panel>
|
||||
<DecodedABI abi={abi} />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<RawABI abi={abi} />
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default React.memo(ContractABI);
|
@ -5,13 +5,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
|
||||
import ContentFrame from "../ContentFrame";
|
||||
import InfoRow from "../components/InfoRow";
|
||||
import Copy from "../components/Copy";
|
||||
import ABI from "./ABI";
|
||||
import Contract from "./Contract";
|
||||
import { RuntimeContext } from "../useRuntime";
|
||||
import { Metadata } from "../useSourcify";
|
||||
import ExternalLink from "../components/ExternalLink";
|
||||
import { openInRemixURL } from "../url";
|
||||
import ContractABI from "./ContractABI";
|
||||
|
||||
type ContractsProps = {
|
||||
checksummedAddress: string;
|
||||
@ -70,13 +69,7 @@ const Contracts: React.FC<ContractsProps> = ({
|
||||
{rawMetadata !== undefined && rawMetadata !== null && (
|
||||
<>
|
||||
{rawMetadata.output.abi && (
|
||||
<div className="mb-3">
|
||||
<div className="flex space-x-2 text-sm border-l border-r border-t rounded-t px-2 py-1">
|
||||
<span>ABI</span>
|
||||
<Copy value={JSON.stringify(rawMetadata.output.abi)} />
|
||||
</div>
|
||||
<ABI abi={rawMetadata.output.abi} />
|
||||
</div>
|
||||
<ContractABI abi={rawMetadata.output.abi} />
|
||||
)}
|
||||
<div>
|
||||
<Menu>
|
||||
|
20
src/address/DecodedABI.tsx
Normal file
20
src/address/DecodedABI.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { Interface } from "@ethersproject/abi";
|
||||
import React from "react";
|
||||
import DecodedFragment from "./DecodedFragment";
|
||||
|
||||
type DecodedABIProps = {
|
||||
abi: any[];
|
||||
};
|
||||
|
||||
const DecodedABI: React.FC<DecodedABIProps> = ({ abi }) => {
|
||||
const intf = new Interface(abi);
|
||||
return (
|
||||
<div className="border overflow-x-auto">
|
||||
{intf.fragments.map((f, i) => (
|
||||
<DecodedFragment key={i} intf={intf} fragment={f} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(DecodedABI);
|
78
src/address/DecodedFragment.tsx
Normal file
78
src/address/DecodedFragment.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import React from "react";
|
||||
import {
|
||||
ConstructorFragment,
|
||||
EventFragment,
|
||||
Fragment,
|
||||
FunctionFragment,
|
||||
Interface,
|
||||
} from "@ethersproject/abi";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCaretRight } from "@fortawesome/free-solid-svg-icons/faCaretRight";
|
||||
|
||||
type DecodedFragmentProps = {
|
||||
intf: Interface;
|
||||
fragment: Fragment;
|
||||
};
|
||||
|
||||
const DecodedFragment: React.FC<DecodedFragmentProps> = ({
|
||||
intf,
|
||||
fragment,
|
||||
}) => {
|
||||
let fragmentType: "constructor" | "event" | "function" | undefined;
|
||||
let sig: string | undefined;
|
||||
let letter: string | undefined;
|
||||
let letterBg: string | undefined;
|
||||
let hashBg: string | undefined;
|
||||
|
||||
if (FunctionFragment.isFunctionFragment(fragment)) {
|
||||
fragmentType = "function";
|
||||
sig = intf.getSighash(fragment);
|
||||
letter = "F";
|
||||
letterBg = "bg-purple-500";
|
||||
hashBg = "bg-purple-50";
|
||||
} else if (EventFragment.isEventFragment(fragment)) {
|
||||
fragmentType = "event";
|
||||
sig = intf.getEventTopic(fragment);
|
||||
letter = "E";
|
||||
letterBg = "bg-green-300";
|
||||
hashBg = "bg-green-50";
|
||||
} else if (ConstructorFragment.isConstructorFragment(fragment)) {
|
||||
fragmentType = "constructor";
|
||||
letter = "C";
|
||||
letterBg = "bg-blue-500";
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap items-baseline space-x-2 px-2 py-1 hover:bg-gray-100">
|
||||
<span className="text-gray-500">
|
||||
<FontAwesomeIcon icon={faCaretRight} size="1x" />
|
||||
</span>
|
||||
{letter && (
|
||||
<span
|
||||
className={`flex-shrink-0 text-xs font-code border border-gray-300 rounded-full w-5 h-5 self-center flex items-center justify-center text-white font-bold ${letterBg}`}
|
||||
>
|
||||
{letter}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-sm font-code whitespace-nowrap">
|
||||
{fragment.format("full")}
|
||||
</span>
|
||||
{sig && (
|
||||
<span
|
||||
className={`text-xs border rounded-xl px-2 pt-1 font-code text-gray-600 ${hashBg}`}
|
||||
title={
|
||||
fragmentType === "function"
|
||||
? "Method Selector"
|
||||
: fragmentType === "event"
|
||||
? "Topic Hash"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
{sig}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(DecodedFragment);
|
@ -1,11 +1,11 @@
|
||||
import React from "react";
|
||||
import { SyntaxHighlighter, docco } from "../highlight-init";
|
||||
|
||||
type ABIProps = {
|
||||
type RawABIProps = {
|
||||
abi: any[];
|
||||
};
|
||||
|
||||
const ABI: React.FC<ABIProps> = ({ abi }) => (
|
||||
const RawABI: React.FC<RawABIProps> = ({ abi }) => (
|
||||
<SyntaxHighlighter
|
||||
className="w-full h-60 border font-code text-base"
|
||||
language="json"
|
||||
@ -16,4 +16,4 @@ const ABI: React.FC<ABIProps> = ({ abi }) => (
|
||||
</SyntaxHighlighter>
|
||||
);
|
||||
|
||||
export default React.memo(ABI);
|
||||
export default React.memo(RawABI);
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { HelmetProvider, Helmet } from "react-helmet-async";
|
||||
import "@fontsource/space-grotesk/index.css";
|
||||
import "@fontsource/roboto/index.css";
|
||||
import "@fontsource/roboto-mono/index.css";
|
||||
@ -11,16 +11,18 @@ import reportWebVitals from "./reportWebVitals";
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<Helmet>
|
||||
<link
|
||||
rel="preload"
|
||||
href={spaceGrotesk}
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="true"
|
||||
/>
|
||||
</Helmet>
|
||||
<App />
|
||||
<HelmetProvider>
|
||||
<Helmet>
|
||||
<link
|
||||
rel="preload"
|
||||
href={spaceGrotesk}
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="true"
|
||||
/>
|
||||
</Helmet>
|
||||
<App />
|
||||
</HelmetProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user