Skip to content

Commit

Permalink
Merge branch 'main' into ui/heimdallrs-steps
Browse files Browse the repository at this point in the history
  • Loading branch information
portdeveloper authored Apr 13, 2024
2 parents fc63d46 + 5cd6219 commit 280a9fc
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ export const ContractReadMethods = ({
if (!functionsToDisplay.length) {
return (
<div className="py-5">
<span className="font-light text-gray-500 my-5">Please select read methods from the sidebar.</span>
<span className="font-light text-gray-500 my-5">
Please select read methods from the <span className="sm:hidden">hamburger menu</span>
<span className="hidden sm:inline">sidebar</span>.
</span>
</div>
);
}
Expand Down
15 changes: 12 additions & 3 deletions packages/nextjs/components/scaffold-eth/Contract/ContractUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ const mainNetworks = getTargetNetworks();
**/
export const ContractUI = ({ className = "", initialContractData }: ContractUIProps) => {
const [refreshDisplayVariables, triggerRefreshDisplayVariables] = useReducer(value => !value, false);
const mainChainId = useAbiNinjaState(state => state.mainChainId);
const mainNetwork = mainNetworks.find(network => network.id === mainChainId);
const { implementationAddress, chainId } = useAbiNinjaState(state => ({
chainId: state.mainChainId,
implementationAddress: state.implementationAddress,
}));
const mainNetwork = mainNetworks.find(network => network.id === chainId);
const networkColor = useNetworkColor(mainNetwork);
const router = useRouter();
const { network } = router.query as { network?: string };
Expand Down Expand Up @@ -123,7 +126,7 @@ export const ContractUI = ({ className = "", initialContractData }: ContractUIPr
const { data: contractNameData, isLoading: isContractNameLoading } = useContractRead({
address: initialContractData.address,
abi: initialContractData.abi,
chainId: mainChainId,
chainId: chainId,
functionName: "name",
});

Expand Down Expand Up @@ -197,6 +200,12 @@ export const ContractUI = ({ className = "", initialContractData }: ContractUIPr
<span className="font-medium text-base mr-4"> {displayContractName} </span>
<Address address={initialContractData.address} />
</div>
{implementationAddress && (
<div className="flex items-center gap-1">
<span className="font-medium text-base mr-4 text-green-600">Implementation Address</span>
<Address address={implementationAddress} />
</div>
)}
<div className="flex items-center gap-1">
<span className="text-sm font-bold">Balance:</span>
<Balance address={initialContractData.address} className="h-1.5 min-h-[0.375rem] px-0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ export const ContractWriteMethods = ({
if (!functionsToDisplay.length) {
return (
<div className="py-5">
<span className="font-light text-gray-500">Please select write methods from the sidebar.</span>
<span className="font-light text-gray-500">
Please select read methods from the <span className="sm:hidden">hamburger menu</span>
<span className="hidden sm:inline">sidebar</span>.
</span>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export const WriteOnlyFunctionForm = ({
wrongNetwork &&
"tooltip before:content-[attr(data-tip)] before:right-[-10px] before:left-auto before:transform-none"
}`}
data-tip={`${wrongNetwork && "Wrong netowrk"}`}
data-tip={`${wrongNetwork && "Wrong network"}`}
>
<button className="btn btn-secondary btn-sm" disabled={wrongNetwork || isLoading} onClick={handleWrite}>
{isLoading && <span className="loading loading-spinner loading-xs"></span>}
Expand Down
1 change: 1 addition & 0 deletions packages/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@uniswap/v2-sdk": "^3.0.1",
"blo": "^1.0.1",
"daisyui": "^4.4.19",
"evm-proxy-detection": "^1.2.0",
"next": "13.3.4",
"next-plausible": "^3.12.0",
"nextjs-progressbar": "^0.0.16",
Expand Down
33 changes: 30 additions & 3 deletions packages/nextjs/pages/[contractAddress]/[network].tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { useEffect, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import { JsonRpcProvider } from "@ethersproject/providers";
import detectProxyTarget from "evm-proxy-detection";
import { ParsedUrlQuery } from "querystring";
import { Abi, isAddress } from "viem";
import { Abi, extractChain, isAddress } from "viem";
import * as chains from "viem/chains";
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
import { MetaHeader } from "~~/components/MetaHeader";
import { MiniHeader } from "~~/components/MiniHeader";
import { ContractUI } from "~~/components/scaffold-eth";
import scaffoldConfig from "~~/scaffold.config";
import { useAbiNinjaState } from "~~/services/store/store";
import { fetchContractABIFromAnyABI, fetchContractABIFromEtherscan } from "~~/utils/abi";

Expand All @@ -21,6 +24,8 @@ type ContractData = {
address: string;
};

type AllowedNetwork = (typeof scaffoldConfig.targetNetworks)[number]["id"];

const ContractDetailPage = () => {
const router = useRouter();
const { contractAddress, network } = router.query as ParsedQueryContractDetailsPage;
Expand All @@ -32,10 +37,12 @@ const ContractDetailPage = () => {
contractAbi: storedAbi,
setMainChainId,
chainId,
setImplementationAddress,
} = useAbiNinjaState(state => ({
contractAbi: state.contractAbi,
setMainChainId: state.setMainChainId,
chainId: state.mainChainId,
setImplementationAddress: state.setImplementationAddress,
}));

const getNetworkName = (chainId: number) => {
Expand Down Expand Up @@ -72,7 +79,27 @@ const ContractDetailPage = () => {
}

try {
const abi = await fetchContractABIFromAnyABI(contractAddress, parsedNetworkId);
const chain = extractChain({
id: parseInt(network) as AllowedNetwork,
chains: Object.values(scaffoldConfig.targetNetworks),
});
// @ts-expect-error this might be present or might not be
const alchmeyRPCURL = chain.rpcUrls?.alchemy?.http[0];
let implementationAddress = undefined;
if (alchmeyRPCURL) {
const alchemyProvider = new JsonRpcProvider(
`${alchmeyRPCURL}/${scaffoldConfig.alchemyApiKey}`,
parseInt(network),
);
const requestFunc = ({ method, params }: { method: string; params: any }) =>
alchemyProvider.send(method, params);
implementationAddress = await detectProxyTarget(contractAddress, requestFunc);
}

if (implementationAddress) {
setImplementationAddress(implementationAddress);
}
const abi = await fetchContractABIFromAnyABI(implementationAddress || contractAddress, parsedNetworkId);
if (!abi) throw new Error("Got empty or undefined ABI from AnyABI");
setContractData({ abi, address: contractAddress });
setError(null);
Expand Down Expand Up @@ -102,7 +129,7 @@ const ContractDetailPage = () => {
}
}
}
}, [contractAddress, network, storedAbi, setMainChainId]);
}, [contractAddress, network, storedAbi, setMainChainId, setImplementationAddress]);

return (
<>
Expand Down
38 changes: 34 additions & 4 deletions packages/nextjs/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { JsonRpcProvider } from "@ethersproject/providers";
import detectProxyTarget from "evm-proxy-detection";
import type { NextPage } from "next";
import { Address, isAddress } from "viem";
import { Address, extractChain, isAddress } from "viem";
import { usePublicClient } from "wagmi";
import { ChevronLeftIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { MetaHeader } from "~~/components/MetaHeader";
Expand All @@ -19,6 +21,8 @@ enum TabName {
addressAbi,
}

type AllowedNetwork = (typeof scaffoldConfig.targetNetworks)[number]["id"];

const tabValues = Object.values(TabName) as TabName[];

const networks = getTargetNetworks();
Expand All @@ -35,9 +39,10 @@ const Home: NextPage = () => {
chainId: parseInt(network),
});

const { setContractAbi, setAbiContractAddress } = useAbiNinjaState(state => ({
const { setContractAbi, setAbiContractAddress, setImplementationAddress } = useAbiNinjaState(state => ({
setContractAbi: state.setContractAbi,
setAbiContractAddress: state.setAbiContractAddress,
setImplementationAddress: state.setImplementationAddress,
}));

const [isAbiAvailable, setIsAbiAvailable] = useState(false);
Expand All @@ -48,7 +53,30 @@ const Home: NextPage = () => {
const fetchContractAbi = async () => {
setIsFetchingAbi(true);
try {
const abi = await fetchContractABIFromAnyABI(verifiedContractAddress, parseInt(network));
const chain = extractChain({
id: parseInt(network) as AllowedNetwork,
chains: Object.values(scaffoldConfig.targetNetworks),
});
// @ts-expect-error this might be present or might not be
const alchmeyRPCURL = chain.rpcUrls?.alchemy?.http[0];
let implementationAddress = undefined;
if (alchmeyRPCURL) {
const alchemyProvider = new JsonRpcProvider(
`${alchmeyRPCURL}/${scaffoldConfig.alchemyApiKey}`,
parseInt(network),
);
const requestFunc = ({ method, params }: { method: string; params: any }) =>
alchemyProvider.send(method, params);
implementationAddress = await detectProxyTarget(verifiedContractAddress, requestFunc);
}

if (implementationAddress) {
setImplementationAddress(implementationAddress);
}
const abi = await fetchContractABIFromAnyABI(
implementationAddress || verifiedContractAddress,
parseInt(network),
);
if (!abi) throw new Error("Got empty or undefined ABI from AnyABI");
setContractAbi(abi);
setIsAbiAvailable(true);
Expand Down Expand Up @@ -92,11 +120,13 @@ const Home: NextPage = () => {
}
}, [verifiedContractAddress, network, setContractAbi, publicClient]);


useEffect(() => {
if (router.pathname === "/") {
setContractAbi([]);
setImplementationAddress("");
}
}, [router.pathname, setContractAbi]);
}, [router.pathname, setContractAbi, setImplementationAddress]);

const handleLoadContract = () => {
if (isAbiAvailable) {
Expand Down
4 changes: 4 additions & 0 deletions packages/nextjs/services/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ type AbiNinjaState = {
setContractAbi: (newAbi: Abi) => void;
abiContractAddress: Address;
setAbiContractAddress: (newAbiContractAddress: Address) => void;
implementationAddress: Address;
setImplementationAddress: (newImplementationAddress: Address) => void;
};

export const useGlobalState = create<GlobalState>(set => ({
Expand All @@ -33,4 +35,6 @@ export const useAbiNinjaState = create<AbiNinjaState>(set => ({
setContractAbi: (newAbi: Abi): void => set({ contractAbi: newAbi }),
abiContractAddress: "",
setAbiContractAddress: (newAddress: Address): void => set({ abiContractAddress: newAddress }),
implementationAddress: "",
setImplementationAddress: (newAddress: Address): void => set({ implementationAddress: newAddress }),
}));
2 changes: 1 addition & 1 deletion packages/nextjs/services/web3/wagmiConnectors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const wallets = [
}),
]
: []),
safeWallet({ ...walletsOptions, debug: false, allowedDomains: [/gnosis-safe.io$/, /app.safe.global$/] }),
safeWallet({ ...walletsOptions }),
];

/**
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,7 @@ __metadata:
eslint-config-next: ^13.1.6
eslint-config-prettier: ^8.5.0
eslint-plugin-prettier: ^4.2.1
evm-proxy-detection: ^1.2.0
next: 13.3.4
next-plausible: ^3.12.0
nextjs-progressbar: ^0.0.16
Expand Down Expand Up @@ -4876,6 +4877,13 @@ __metadata:
languageName: node
linkType: hard

"evm-proxy-detection@npm:^1.2.0":
version: 1.2.0
resolution: "evm-proxy-detection@npm:1.2.0"
checksum: d9996cbcd22eadd0b1209116d1f5c90ebf063edfe08c71c2f92372040dc004248ab280887a2f6d968d3e4963f40909f7f4cece584992e8e1f6ea136d6e18f2ee
languageName: node
linkType: hard

"execa@npm:^6.1.0":
version: 6.1.0
resolution: "execa@npm:6.1.0"
Expand Down

0 comments on commit 280a9fc

Please sign in to comment.