Apply SWR to Sourcify contract source code fetching

This commit is contained in:
Willian Mitsuda 2022-08-10 04:47:26 -03:00
parent 49abfbda2f
commit 5ab336041e
No known key found for this signature in database
4 changed files with 81 additions and 69 deletions

View File

@ -1,31 +1,11 @@
import React from "react"; import React from "react";
import { SyntaxHighlighter, docco } from "../highlight-init"; import { SyntaxHighlighter, docco } from "../highlight-init";
import { useContract } from "../sourcify/useSourcify";
import { useAppConfigContext } from "../useAppConfig";
type ContractProps = { type ContractProps = {
checksummedAddress: string; content: any;
networkId: number;
filename: string;
source: any;
}; };
const Contract: React.FC<ContractProps> = ({ const Contract: React.FC<ContractProps> = ({ content }) => (
checksummedAddress,
networkId,
filename,
source,
}) => {
const { sourcifySource } = useAppConfigContext();
const content = useContract(
checksummedAddress,
networkId,
filename,
source,
sourcifySource
);
return (
<SyntaxHighlighter <SyntaxHighlighter
className="w-full h-full border font-code text-base" className="w-full h-full border font-code text-base"
language="solidity" language="solidity"
@ -34,7 +14,6 @@ const Contract: React.FC<ContractProps> = ({
> >
{content ?? ""} {content ?? ""}
</SyntaxHighlighter> </SyntaxHighlighter>
); );
};
export default React.memo(Contract); export default React.memo(Contract);

View File

@ -0,0 +1,37 @@
import React from "react";
import { SyntaxHighlighter, docco } from "../highlight-init";
import { useContract } from "../sourcify/useSourcify";
import { useAppConfigContext } from "../useAppConfig";
type ContractFromRepoProps = {
checksummedAddress: string;
networkId: number;
filename: string;
};
const ContractFromRepo: React.FC<ContractFromRepoProps> = ({
checksummedAddress,
networkId,
filename,
}) => {
const { sourcifySource } = useAppConfigContext();
const content = useContract(
checksummedAddress,
networkId,
filename,
sourcifySource
);
return (
<SyntaxHighlighter
className="w-full h-full border font-code text-base"
language="solidity"
style={docco}
showLineNumbers
>
{content ?? ""}
</SyntaxHighlighter>
);
};
export default React.memo(ContractFromRepo);

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useContext, Fragment } from "react"; import React, { useState, useEffect, useContext } from "react";
import { commify } from "@ethersproject/units"; import { commify } from "@ethersproject/units";
import { Menu } from "@headlessui/react"; import { Menu } from "@headlessui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -6,6 +6,7 @@ import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
import ContentFrame from "../ContentFrame"; import ContentFrame from "../ContentFrame";
import InfoRow from "../components/InfoRow"; import InfoRow from "../components/InfoRow";
import Contract from "./Contract"; import Contract from "./Contract";
import ContractFromRepo from "./ContractFromRepo";
import { RuntimeContext } from "../useRuntime"; import { RuntimeContext } from "../useRuntime";
import { Metadata } from "../sourcify/useSourcify"; import { Metadata } from "../sourcify/useSourcify";
import ExternalLink from "../components/ExternalLink"; import ExternalLink from "../components/ExternalLink";
@ -113,13 +114,18 @@ const Contracts: React.FC<ContractsProps> = ({
</div> </div>
</Menu> </Menu>
{selected && ( {selected && (
<Contract <>
{rawMetadata.sources[selected].content ? (
<Contract content={rawMetadata.sources[selected].content} />
) : (
<ContractFromRepo
checksummedAddress={checksummedAddress} checksummedAddress={checksummedAddress}
networkId={provider!.network.chainId} networkId={provider!.network.chainId}
filename={selected} filename={selected}
source={rawMetadata.sources[selected]}
/> />
)} )}
</>
)}
</div> </div>
</> </>
)} )}

View File

@ -115,22 +115,20 @@ export const useSourcifyMetadata = (
return data; return data;
}; };
const contractFetcher = async (url: string): Promise<string | null> => {
const res = await fetch(url);
if (res.ok) {
return await res.text();
}
return null;
};
export const useContract = ( export const useContract = (
checksummedAddress: string, checksummedAddress: string,
networkId: number, networkId: number,
filename: string, filename: string,
source: any,
sourcifySource: SourcifySource sourcifySource: SourcifySource
) => { ) => {
const [content, setContent] = useState<string>(source.content);
useEffect(() => {
if (source.content) {
return;
}
const abortController = new AbortController();
const readContent = async () => {
const normalizedFilename = filename.replaceAll(/[@:]/g, "_"); const normalizedFilename = filename.replaceAll(/[@:]/g, "_");
const url = sourcifySourceFile( const url = sourcifySourceFile(
checksummedAddress, checksummedAddress,
@ -138,20 +136,12 @@ export const useContract = (
normalizedFilename, normalizedFilename,
sourcifySource sourcifySource
); );
const res = await fetch(url, { signal: abortController.signal });
if (res.ok) { const { data, error } = useSWRImmutable(url, contractFetcher);
const _content = await res.text(); if (error) {
setContent(_content); return undefined;
} }
}; return data;
readContent();
return () => {
abortController.abort();
};
}, [checksummedAddress, networkId, filename, source.content, sourcifySource]);
return content;
}; };
export const useTransactionDescription = ( export const useTransactionDescription = (