create-stylus 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/issue_template.md +7 -0
- package/.github/pull_request_template.md +11 -0
- package/.github/workflows/release-alpha.yml +32 -0
- package/.yarnrc.yml +1 -0
- package/CONTRIBUTING.md +42 -0
- package/README.md +66 -0
- package/bin/create-dapp-ss.js +4 -0
- package/dist/cli.js +656 -0
- package/dist/cli.js.map +1 -0
- package/package.json +46 -0
- package/rollup.config.js +22 -0
- package/src/cli.ts +14 -0
- package/src/extensions.json +14 -0
- package/src/main.ts +70 -0
- package/src/tasks/copy-extension-file.ts +227 -0
- package/src/tasks/copy-template-files.ts +252 -0
- package/src/tasks/create-first-git-commit.ts +35 -0
- package/src/tasks/create-project-directory.ts +34 -0
- package/src/tasks/index.ts +5 -0
- package/src/tasks/install-packages.ts +15 -0
- package/src/tasks/prettier-format.ts +17 -0
- package/src/types.ts +31 -0
- package/src/utils/consts.ts +1 -0
- package/src/utils/find-files-recursively.ts +19 -0
- package/src/utils/link.ts +44 -0
- package/src/utils/load-extensions.ts +10 -0
- package/src/utils/merge-package-json.ts +33 -0
- package/src/utils/parse-arguments-into-options.ts +38 -0
- package/src/utils/prompt-for-missing-options.ts +53 -0
- package/src/utils/render-intro-message.ts +11 -0
- package/src/utils/render-outro-message.ts +34 -0
- package/templates/base/.github/ISSUE_TEMPLATE/bug_report.yml +58 -0
- package/templates/base/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/templates/base/.github/pull_request_template.md +16 -0
- package/templates/base/.github/workflows/lint.yaml +300 -0
- package/templates/base/.gitignore.template.mjs +19 -0
- package/templates/base/.gitmodules +0 -0
- package/templates/base/.husky/pre-commit +4 -0
- package/templates/base/.lintstagedrc.js +21 -0
- package/templates/base/.vscode/settings.json +7 -0
- package/templates/base/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
- package/templates/base/.yarn/releases/yarn-3.2.3.cjs +783 -0
- package/templates/base/.yarnrc.yml +11 -0
- package/templates/base/CONTRIBUTING.md +86 -0
- package/templates/base/LICENCE +21 -0
- package/templates/base/nitro-devnode/LICENSE +201 -0
- package/templates/base/nitro-devnode/README.md +70 -0
- package/templates/base/nitro-devnode/run-dev-node.sh +132 -0
- package/templates/base/nitro-devnode/start-chain-with-cors.sh +150 -0
- package/templates/base/nitro-devnode/stylus-deployer-bytecode.txt +1 -0
- package/templates/base/nitro-devnode/stylus-dev/Dockerfile +10 -0
- package/templates/base/package.json +43 -0
- package/templates/base/packages/nextjs/.env.example +13 -0
- package/templates/base/packages/nextjs/.eslintignore +11 -0
- package/templates/base/packages/nextjs/.eslintrc.json +15 -0
- package/templates/base/packages/nextjs/.gitignore.template.mjs +42 -0
- package/templates/base/packages/nextjs/.prettierrc.js +9 -0
- package/templates/base/packages/nextjs/.prettierrc.json +8 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressCodeTab.tsx +27 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressComponent.tsx +36 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressLogsTab.tsx +21 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressStorageTab.tsx +61 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/BackButton.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/ContractTabs.tsx +102 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/PaginationButton.tsx +39 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/SearchBar.tsx +49 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionHash.tsx +28 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionsTable.tsx +71 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/index.tsx +7 -0
- package/templates/base/packages/nextjs/app/blockexplorer/address/[address]/page.tsx +101 -0
- package/templates/base/packages/nextjs/app/blockexplorer/layout.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/page.tsx +83 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/[txHash]/page.tsx +23 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/_components/TransactionComp.tsx +152 -0
- package/templates/base/packages/nextjs/app/debug/_components/DebugContracts.tsx +73 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractInput.tsx +84 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractReadMethods.tsx +43 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +164 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractVariables.tsx +50 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractWriteMethods.tsx +49 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +85 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/InheritanceTooltip.tsx +14 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +102 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/Tuple.tsx +44 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TupleArray.tsx +142 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +42 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/WriteOnlyFunctionForm.tsx +144 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/index.tsx +8 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsContract.tsx +166 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +114 -0
- package/templates/base/packages/nextjs/app/debug/page.tsx +14 -0
- package/templates/base/packages/nextjs/app/layout.tsx +67 -0
- package/templates/base/packages/nextjs/app/not-found.tsx +16 -0
- package/templates/base/packages/nextjs/app/page.tsx +94 -0
- package/templates/base/packages/nextjs/components/Background.tsx +37 -0
- package/templates/base/packages/nextjs/components/Card.tsx +40 -0
- package/templates/base/packages/nextjs/components/Footer.tsx +93 -0
- package/templates/base/packages/nextjs/components/Header.tsx +114 -0
- package/templates/base/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx +77 -0
- package/templates/base/packages/nextjs/components/SwitchTheme.tsx +41 -0
- package/templates/base/packages/nextjs/components/ThemeProvider.tsx +13 -0
- package/templates/base/packages/nextjs/components/assets/BuidlGuidlLogo.tsx +18 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/Address.tsx +187 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressCopyIcon.tsx +23 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressLinkWrapper.tsx +29 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Balance.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/BlockieAvatar.tsx +17 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Faucet.tsx +131 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/FaucetButton.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx +120 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/Bytes32Input.tsx +31 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/BytesInput.tsx +28 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/EtherInput.tsx +128 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx +66 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/index.ts +9 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/utils.ts +109 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressInfoDropdown.tsx +121 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressQRCodeModal.tsx +33 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/BurnerWalletModal.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/NetworkOptions.tsx +48 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/WrongNetworkDropdown.tsx +32 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/index.tsx +89 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/index.tsx +7 -0
- package/templates/base/packages/nextjs/contracts/deployedContracts.ts +9 -0
- package/templates/base/packages/nextjs/contracts/externalContracts.ts +16 -0
- package/templates/base/packages/nextjs/eslint.config.mjs +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/index.ts +17 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useAnimationConfig.ts +20 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useContractLogs.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useCopyToClipboard.ts +19 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDeployedContractInfo.ts +86 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDisplayUsdMode.ts +21 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useFetchBlocks.ts +133 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useInitializeNativeCurrencyPrice.ts +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNativeCurrencyPrice.ts +34 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNetworkColor.ts +22 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useOutsideClick.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldContract.ts +65 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts +213 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts +80 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWatchContractEvent.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts +191 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useSelectedNetwork.ts +18 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTargetNetwork.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTransactor.tsx +114 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useWatchBalance.ts +21 -0
- package/templates/base/packages/nextjs/icons/CompassIcon.tsx +39 -0
- package/templates/base/packages/nextjs/icons/DarkBugAntIcon.tsx +30 -0
- package/templates/base/packages/nextjs/icons/LightBugAntIcon.tsx +52 -0
- package/templates/base/packages/nextjs/next-env.d.ts +5 -0
- package/templates/base/packages/nextjs/next.config.js +19 -0
- package/templates/base/packages/nextjs/package.json +58 -0
- package/templates/base/packages/nextjs/postcss.config.js +6 -0
- package/templates/base/packages/nextjs/public/debug-image.png +0 -0
- package/templates/base/packages/nextjs/public/favicon.png +0 -0
- package/templates/base/packages/nextjs/public/logo.svg +8 -0
- package/templates/base/packages/nextjs/public/manifest.json +5 -0
- package/templates/base/packages/nextjs/public/thumbnail.jpg +0 -0
- package/templates/base/packages/nextjs/react-copy-to-clipboard.d.ts +44 -0
- package/templates/base/packages/nextjs/scaffold.config.ts +56 -0
- package/templates/base/packages/nextjs/services/store/store.ts +39 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConfig.tsx +44 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConnectors.tsx +51 -0
- package/templates/base/packages/nextjs/styles/globals.css +80 -0
- package/templates/base/packages/nextjs/tailwind.config.js +97 -0
- package/templates/base/packages/nextjs/tsconfig.json +28 -0
- package/templates/base/packages/nextjs/types/abitype/abi.d.ts +16 -0
- package/templates/base/packages/nextjs/types/utils.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/block.ts +17 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/common.ts +8 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contract.ts +352 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contractsData.ts +11 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/decodeTxData.ts +65 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/fetchPriceFromUniswap.ts +72 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getMetadata.ts +50 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getParsedError.ts +35 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/index.ts +6 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/notification.tsx +90 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/burner.ts +59 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/chain.ts +42 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/index.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/networks.ts +94 -0
- package/templates/base/packages/nextjs/vercel.json +3 -0
- package/templates/base/packages/stylus/.env.example +13 -0
- package/templates/base/packages/stylus/.eslintrc.js +23 -0
- package/templates/base/packages/stylus/.gitignore.template.mjs +7 -0
- package/templates/base/packages/stylus/README.md +263 -0
- package/templates/base/packages/stylus/header.png +0 -0
- package/templates/base/packages/stylus/jest.config.js +15 -0
- package/templates/base/packages/stylus/package.json +49 -0
- package/templates/base/packages/stylus/scripts/deploy.ts +29 -0
- package/templates/base/packages/stylus/scripts/deploy_all_contracts.ts +59 -0
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +93 -0
- package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +79 -0
- package/templates/base/packages/stylus/scripts/export_abi.ts +87 -0
- package/templates/base/packages/stylus/scripts/index.ts +0 -0
- package/templates/base/packages/stylus/scripts/new_module.sh +35 -0
- package/templates/base/packages/stylus/scripts/test_network.ts +31 -0
- package/templates/base/packages/stylus/scripts/utils/command.ts +165 -0
- package/templates/base/packages/stylus/scripts/utils/contract.ts +219 -0
- package/templates/base/packages/stylus/scripts/utils/deployment.ts +136 -0
- package/templates/base/packages/stylus/scripts/utils/index.ts +6 -0
- package/templates/base/packages/stylus/scripts/utils/network.ts +112 -0
- package/templates/base/packages/stylus/scripts/utils/type.ts +48 -0
- package/templates/base/packages/stylus/scripts/utils.ts +3 -0
- package/templates/base/packages/stylus/tsconfig.json +41 -0
- package/templates/base/packages/stylus/your-contract/.cargo/config.toml +18 -0
- package/templates/base/packages/stylus/your-contract/Cargo.lock +5744 -0
- package/templates/base/packages/stylus/your-contract/Cargo.toml +46 -0
- package/templates/base/packages/stylus/your-contract/examples/counter.rs +78 -0
- package/templates/base/packages/stylus/your-contract/header.png +0 -0
- package/templates/base/packages/stylus/your-contract/licenses/Apache-2.0 +201 -0
- package/templates/base/packages/stylus/your-contract/licenses/COPYRIGHT.md +5 -0
- package/templates/base/packages/stylus/your-contract/licenses/DCO.txt +34 -0
- package/templates/base/packages/stylus/your-contract/licenses/MIT +21 -0
- package/templates/base/packages/stylus/your-contract/rust-toolchain.toml +2 -0
- package/templates/base/packages/stylus/your-contract/src/lib.rs +211 -0
- package/templates/base/packages/stylus/your-contract/src/main.rs +10 -0
- package/templates/base/readme.md +187 -0
- package/templates/base/yarn.lock +17860 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { Address } from "viem";
|
|
4
|
+
import { AddressComponent } from "~~/app/blockexplorer/_components/AddressComponent";
|
|
5
|
+
import deployedContracts from "~~/contracts/deployedContracts";
|
|
6
|
+
import { isZeroAddress } from "~~/utils/scaffold-eth/common";
|
|
7
|
+
import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";
|
|
8
|
+
import { arbitrumNitro } from "~~/utils/scaffold-stylus/chain";
|
|
9
|
+
|
|
10
|
+
type PageProps = {
|
|
11
|
+
params: Promise<{ address: Address }>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
async function fetchByteCodeAndAssembly(buildInfoDirectory: string, contractPath: string) {
|
|
15
|
+
const buildInfoFiles = fs.readdirSync(buildInfoDirectory);
|
|
16
|
+
let bytecode = "";
|
|
17
|
+
let assembly = "";
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < buildInfoFiles.length; i++) {
|
|
20
|
+
const filePath = path.join(buildInfoDirectory, buildInfoFiles[i]);
|
|
21
|
+
|
|
22
|
+
const buildInfo = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
23
|
+
|
|
24
|
+
if (buildInfo.output.contracts[contractPath]) {
|
|
25
|
+
for (const contract in buildInfo.output.contracts[contractPath]) {
|
|
26
|
+
bytecode = buildInfo.output.contracts[contractPath][contract].evm.bytecode.object;
|
|
27
|
+
assembly = buildInfo.output.contracts[contractPath][contract].evm.bytecode.opcodes;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (bytecode && assembly) {
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { bytecode, assembly };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const getContractData = async (address: Address) => {
|
|
41
|
+
const contracts = deployedContracts as GenericContractsDeclaration | null;
|
|
42
|
+
const chainId = arbitrumNitro.id;
|
|
43
|
+
|
|
44
|
+
if (!contracts || !contracts[chainId] || Object.keys(contracts[chainId]).length === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let contractPath = "";
|
|
49
|
+
|
|
50
|
+
const buildInfoDirectory = path.join(
|
|
51
|
+
__dirname,
|
|
52
|
+
"..",
|
|
53
|
+
"..",
|
|
54
|
+
"..",
|
|
55
|
+
"..",
|
|
56
|
+
"..",
|
|
57
|
+
"..",
|
|
58
|
+
"..",
|
|
59
|
+
"stylus",
|
|
60
|
+
"artifacts",
|
|
61
|
+
"build-info",
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (!fs.existsSync(buildInfoDirectory)) {
|
|
65
|
+
throw new Error(`Directory ${buildInfoDirectory} not found.`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const deployedContractsOnChain = contracts[chainId];
|
|
69
|
+
for (const [contractName, contractInfo] of Object.entries(deployedContractsOnChain)) {
|
|
70
|
+
if (contractInfo.address.toLowerCase() === address.toLowerCase()) {
|
|
71
|
+
contractPath = `contracts/${contractName}.sol`;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!contractPath) {
|
|
77
|
+
// No contract found at this address
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { bytecode, assembly } = await fetchByteCodeAndAssembly(buildInfoDirectory, contractPath);
|
|
82
|
+
|
|
83
|
+
return { bytecode, assembly };
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export function generateStaticParams() {
|
|
87
|
+
// An workaround to enable static exports in Next.js, generating single dummy page.
|
|
88
|
+
return [{ address: "0x0000000000000000000000000000000000000000" }];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const AddressPage = async (props: PageProps) => {
|
|
92
|
+
const params = await props.params;
|
|
93
|
+
const address = params?.address as Address;
|
|
94
|
+
|
|
95
|
+
if (isZeroAddress(address)) return null;
|
|
96
|
+
|
|
97
|
+
const contractData: { bytecode: string; assembly: string } | null = await getContractData(address);
|
|
98
|
+
return <AddressComponent address={address} contractData={contractData} />;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export default AddressPage;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getMetadata } from "~~/utils/scaffold-eth/getMetadata";
|
|
2
|
+
|
|
3
|
+
export const metadata = getMetadata({
|
|
4
|
+
title: "Block Explorer",
|
|
5
|
+
description: "Block Explorer created with 🏗 Scaffold-Stylus",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const BlockExplorerLayout = ({ children }: { children: React.ReactNode }) => {
|
|
9
|
+
return <>{children}</>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default BlockExplorerLayout;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { PaginationButton, SearchBar, TransactionsTable } from "./_components";
|
|
5
|
+
import type { NextPage } from "next";
|
|
6
|
+
import { useFetchBlocks } from "~~/hooks/scaffold-eth";
|
|
7
|
+
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
|
|
8
|
+
import { notification } from "~~/utils/scaffold-eth";
|
|
9
|
+
import { arbitrumNitro } from "~~/utils/scaffold-stylus/chain";
|
|
10
|
+
|
|
11
|
+
const BlockExplorer: NextPage = () => {
|
|
12
|
+
const { blocks, transactionReceipts, currentPage, totalBlocks, setCurrentPage, error } = useFetchBlocks();
|
|
13
|
+
const { targetNetwork } = useTargetNetwork();
|
|
14
|
+
const [isLocalNetwork, setIsLocalNetwork] = useState(true);
|
|
15
|
+
const [hasError, setHasError] = useState(false);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (targetNetwork.id !== arbitrumNitro.id) {
|
|
19
|
+
setIsLocalNetwork(false);
|
|
20
|
+
}
|
|
21
|
+
}, [targetNetwork.id]);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (targetNetwork.id === arbitrumNitro.id && error) {
|
|
25
|
+
setHasError(true);
|
|
26
|
+
}
|
|
27
|
+
}, [targetNetwork.id, error]);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!isLocalNetwork) {
|
|
31
|
+
notification.error(
|
|
32
|
+
<>
|
|
33
|
+
<p className="font-bold mt-0 mb-1">
|
|
34
|
+
<code className="italic bg-base-300 text-base font-bold"> targetNetwork </code> is not localhost
|
|
35
|
+
</p>
|
|
36
|
+
<p className="m-0">
|
|
37
|
+
- You are on <code className="italic bg-base-300 text-base font-bold">{targetNetwork.name}</code> .This
|
|
38
|
+
block explorer is only for <code className="italic bg-base-300 text-base font-bold">localhost</code>.
|
|
39
|
+
</p>
|
|
40
|
+
<p className="mt-1 break-normal">
|
|
41
|
+
- You can use{" "}
|
|
42
|
+
<a className="text-accent" href={targetNetwork.blockExplorers?.default.url}>
|
|
43
|
+
{targetNetwork.blockExplorers?.default.name}
|
|
44
|
+
</a>{" "}
|
|
45
|
+
instead
|
|
46
|
+
</p>
|
|
47
|
+
</>,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}, [
|
|
51
|
+
isLocalNetwork,
|
|
52
|
+
targetNetwork.blockExplorers?.default.name,
|
|
53
|
+
targetNetwork.blockExplorers?.default.url,
|
|
54
|
+
targetNetwork.name,
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (hasError) {
|
|
59
|
+
notification.error(
|
|
60
|
+
<>
|
|
61
|
+
<p className="font-bold mt-0 mb-1">Cannot connect to local provider</p>
|
|
62
|
+
<p className="m-0">
|
|
63
|
+
- Did you forget to run <code className="italic bg-base-300 text-base font-bold">yarn chain</code> ?
|
|
64
|
+
</p>
|
|
65
|
+
<p className="mt-1 break-normal">
|
|
66
|
+
- Or you can change <code className="italic bg-base-300 text-base font-bold">targetNetwork</code> in{" "}
|
|
67
|
+
<code className="italic bg-base-300 text-base font-bold">scaffold.config.ts</code>
|
|
68
|
+
</p>
|
|
69
|
+
</>,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}, [hasError]);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div className="container mx-auto my-10">
|
|
76
|
+
<SearchBar />
|
|
77
|
+
<TransactionsTable blocks={blocks} transactionReceipts={transactionReceipts} />
|
|
78
|
+
<PaginationButton currentPage={currentPage} totalItems={Number(totalBlocks)} setCurrentPage={setCurrentPage} />
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default BlockExplorer;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import TransactionComp from "../_components/TransactionComp";
|
|
2
|
+
import type { NextPage } from "next";
|
|
3
|
+
import { Hash } from "viem";
|
|
4
|
+
import { isZeroAddress } from "~~/utils/scaffold-eth/common";
|
|
5
|
+
|
|
6
|
+
type PageProps = {
|
|
7
|
+
params: Promise<{ txHash?: Hash }>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function generateStaticParams() {
|
|
11
|
+
// An workaround to enable static exports in Next.js, generating single dummy page.
|
|
12
|
+
return [{ txHash: "0x0000000000000000000000000000000000000000" }];
|
|
13
|
+
}
|
|
14
|
+
const TransactionPage: NextPage<PageProps> = async (props: PageProps) => {
|
|
15
|
+
const params = await props.params;
|
|
16
|
+
const txHash = params?.txHash as Hash;
|
|
17
|
+
|
|
18
|
+
if (isZeroAddress(txHash)) return null;
|
|
19
|
+
|
|
20
|
+
return <TransactionComp txHash={txHash} />;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default TransactionPage;
|
package/templates/base/packages/nextjs/app/blockexplorer/transaction/_components/TransactionComp.tsx
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { useRouter } from "next/navigation";
|
|
5
|
+
import { Hash, Transaction, TransactionReceipt, formatEther, formatUnits } from "viem";
|
|
6
|
+
import { usePublicClient } from "wagmi";
|
|
7
|
+
import { Address } from "~~/components/scaffold-eth";
|
|
8
|
+
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
|
|
9
|
+
import { decodeTransactionData, getFunctionDetails } from "~~/utils/scaffold-eth";
|
|
10
|
+
import { replacer } from "~~/utils/scaffold-eth/common";
|
|
11
|
+
import { arbitrumNitro } from "~~/utils/scaffold-stylus/chain";
|
|
12
|
+
|
|
13
|
+
const TransactionComp = ({ txHash }: { txHash: Hash }) => {
|
|
14
|
+
const client = usePublicClient({ chainId: arbitrumNitro.id });
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const [transaction, setTransaction] = useState<Transaction>();
|
|
17
|
+
const [receipt, setReceipt] = useState<TransactionReceipt>();
|
|
18
|
+
const [functionCalled, setFunctionCalled] = useState<string>();
|
|
19
|
+
|
|
20
|
+
const { targetNetwork } = useTargetNetwork();
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (txHash && client) {
|
|
24
|
+
const fetchTransaction = async () => {
|
|
25
|
+
const tx = await client.getTransaction({ hash: txHash });
|
|
26
|
+
const receipt = await client.getTransactionReceipt({ hash: txHash });
|
|
27
|
+
|
|
28
|
+
const transactionWithDecodedData = decodeTransactionData(tx);
|
|
29
|
+
setTransaction(transactionWithDecodedData);
|
|
30
|
+
setReceipt(receipt);
|
|
31
|
+
|
|
32
|
+
const functionCalled = transactionWithDecodedData.input.substring(0, 10);
|
|
33
|
+
setFunctionCalled(functionCalled);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
fetchTransaction();
|
|
37
|
+
}
|
|
38
|
+
}, [client, txHash]);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className="container mx-auto mt-10 mb-20 px-10 md:px-0">
|
|
42
|
+
<button className="btn btn-sm btn-primary" onClick={() => router.back()}>
|
|
43
|
+
Back
|
|
44
|
+
</button>
|
|
45
|
+
{transaction ? (
|
|
46
|
+
<div className="overflow-x-auto">
|
|
47
|
+
<h2 className="text-3xl font-bold mb-4 text-center text-primary-content">Transaction Details</h2>{" "}
|
|
48
|
+
<table className="table rounded-lg bg-base-100 w-full shadow-lg md:table-lg table-md">
|
|
49
|
+
<tbody>
|
|
50
|
+
<tr>
|
|
51
|
+
<td>
|
|
52
|
+
<strong>Transaction Hash:</strong>
|
|
53
|
+
</td>
|
|
54
|
+
<td>{transaction.hash}</td>
|
|
55
|
+
</tr>
|
|
56
|
+
<tr>
|
|
57
|
+
<td>
|
|
58
|
+
<strong>Block Number:</strong>
|
|
59
|
+
</td>
|
|
60
|
+
<td>{Number(transaction.blockNumber)}</td>
|
|
61
|
+
</tr>
|
|
62
|
+
<tr>
|
|
63
|
+
<td>
|
|
64
|
+
<strong>From:</strong>
|
|
65
|
+
</td>
|
|
66
|
+
<td>
|
|
67
|
+
<Address address={transaction.from} format="long" onlyEnsOrAddress />
|
|
68
|
+
</td>
|
|
69
|
+
</tr>
|
|
70
|
+
<tr>
|
|
71
|
+
<td>
|
|
72
|
+
<strong>To:</strong>
|
|
73
|
+
</td>
|
|
74
|
+
<td>
|
|
75
|
+
{!receipt?.contractAddress ? (
|
|
76
|
+
transaction.to && <Address address={transaction.to} format="long" onlyEnsOrAddress />
|
|
77
|
+
) : (
|
|
78
|
+
<span>
|
|
79
|
+
Contract Creation:
|
|
80
|
+
<Address address={receipt.contractAddress} format="long" onlyEnsOrAddress />
|
|
81
|
+
</span>
|
|
82
|
+
)}
|
|
83
|
+
</td>
|
|
84
|
+
</tr>
|
|
85
|
+
<tr>
|
|
86
|
+
<td>
|
|
87
|
+
<strong>Value:</strong>
|
|
88
|
+
</td>
|
|
89
|
+
<td>
|
|
90
|
+
{formatEther(transaction.value)} {targetNetwork.nativeCurrency.symbol}
|
|
91
|
+
</td>
|
|
92
|
+
</tr>
|
|
93
|
+
<tr>
|
|
94
|
+
<td>
|
|
95
|
+
<strong>Function called:</strong>
|
|
96
|
+
</td>
|
|
97
|
+
<td>
|
|
98
|
+
<div className="w-full md:max-w-[600px] lg:max-w-[800px] overflow-x-auto whitespace-nowrap">
|
|
99
|
+
{functionCalled === "0x" ? (
|
|
100
|
+
"This transaction did not call any function."
|
|
101
|
+
) : (
|
|
102
|
+
<>
|
|
103
|
+
<span className="mr-2">{getFunctionDetails(transaction)}</span>
|
|
104
|
+
<span className="badge badge-primary font-bold">{functionCalled}</span>
|
|
105
|
+
</>
|
|
106
|
+
)}
|
|
107
|
+
</div>
|
|
108
|
+
</td>
|
|
109
|
+
</tr>
|
|
110
|
+
<tr>
|
|
111
|
+
<td>
|
|
112
|
+
<strong>Gas Price:</strong>
|
|
113
|
+
</td>
|
|
114
|
+
<td>{formatUnits(transaction.gasPrice || 0n, 9)} Gwei</td>
|
|
115
|
+
</tr>
|
|
116
|
+
<tr>
|
|
117
|
+
<td>
|
|
118
|
+
<strong>Data:</strong>
|
|
119
|
+
</td>
|
|
120
|
+
<td className="form-control">
|
|
121
|
+
<textarea
|
|
122
|
+
readOnly
|
|
123
|
+
value={transaction.input}
|
|
124
|
+
className="p-0 w-full textarea-primary bg-inherit h-[150px]"
|
|
125
|
+
/>
|
|
126
|
+
</td>
|
|
127
|
+
</tr>
|
|
128
|
+
<tr>
|
|
129
|
+
<td>
|
|
130
|
+
<strong>Logs:</strong>
|
|
131
|
+
</td>
|
|
132
|
+
<td>
|
|
133
|
+
<ul>
|
|
134
|
+
{receipt?.logs?.map((log, i) => (
|
|
135
|
+
<li key={i}>
|
|
136
|
+
<strong>Log {i} topics:</strong> {JSON.stringify(log.topics, replacer, 2)}
|
|
137
|
+
</li>
|
|
138
|
+
))}
|
|
139
|
+
</ul>
|
|
140
|
+
</td>
|
|
141
|
+
</tr>
|
|
142
|
+
</tbody>
|
|
143
|
+
</table>
|
|
144
|
+
</div>
|
|
145
|
+
) : (
|
|
146
|
+
<p className="text-2xl text-base-content">Loading...</p>
|
|
147
|
+
)}
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default TransactionComp;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useMemo } from "react";
|
|
4
|
+
import { useSessionStorage } from "usehooks-ts";
|
|
5
|
+
import { BarsArrowUpIcon } from "@heroicons/react/20/solid";
|
|
6
|
+
import { ContractUI } from "~~/app/debug/_components/contract";
|
|
7
|
+
import { ContractName, GenericContract } from "~~/utils/scaffold-eth/contract";
|
|
8
|
+
import { useAllContracts } from "~~/utils/scaffold-eth/contractsData";
|
|
9
|
+
|
|
10
|
+
const selectedContractStorageKey = "scaffoldEth2.selectedContract";
|
|
11
|
+
|
|
12
|
+
export function DebugContracts() {
|
|
13
|
+
const contractsData = useAllContracts();
|
|
14
|
+
const contractNames = useMemo(
|
|
15
|
+
() =>
|
|
16
|
+
Object.keys(contractsData).sort((a, b) => {
|
|
17
|
+
return a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" });
|
|
18
|
+
}) as ContractName[],
|
|
19
|
+
[contractsData],
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const [selectedContract, setSelectedContract] = useSessionStorage<ContractName>(
|
|
23
|
+
selectedContractStorageKey,
|
|
24
|
+
contractNames[0],
|
|
25
|
+
{ initializeWithValue: false },
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!contractNames.includes(selectedContract)) {
|
|
30
|
+
setSelectedContract(contractNames[0]);
|
|
31
|
+
}
|
|
32
|
+
}, [contractNames, selectedContract, setSelectedContract]);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex flex-col gap-y-6 lg:gap-y-8 py-8 lg:py-12 justify-center items-center">
|
|
36
|
+
{contractNames.length === 0 ? (
|
|
37
|
+
<p className="text-3xl mt-14">No contracts found!</p>
|
|
38
|
+
) : (
|
|
39
|
+
<>
|
|
40
|
+
{contractNames.length > 1 && (
|
|
41
|
+
<div className="flex flex-row gap-2 w-full max-w-7xl pb-1 px-6 lg:px-10 flex-wrap">
|
|
42
|
+
{contractNames.map(contractName => (
|
|
43
|
+
<button
|
|
44
|
+
className={`btn btn-secondary btn-sm font-light hover:border-transparent ${
|
|
45
|
+
contractName === selectedContract
|
|
46
|
+
? "bg-base-300 hover:bg-base-300 no-animation"
|
|
47
|
+
: "bg-base-100 hover:bg-secondary"
|
|
48
|
+
}`}
|
|
49
|
+
key={contractName}
|
|
50
|
+
onClick={() => setSelectedContract(contractName)}
|
|
51
|
+
>
|
|
52
|
+
{contractName}
|
|
53
|
+
{(contractsData[contractName] as GenericContract)?.external && (
|
|
54
|
+
<span className="tooltip tooltip-top tooltip-accent" data-tip="External contract">
|
|
55
|
+
<BarsArrowUpIcon className="h-4 w-4 cursor-pointer" />
|
|
56
|
+
</span>
|
|
57
|
+
)}
|
|
58
|
+
</button>
|
|
59
|
+
))}
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
{contractNames.map(contractName => (
|
|
63
|
+
<ContractUI
|
|
64
|
+
key={contractName}
|
|
65
|
+
contractName={contractName}
|
|
66
|
+
className={contractName === selectedContract ? "" : "hidden"}
|
|
67
|
+
/>
|
|
68
|
+
))}
|
|
69
|
+
</>
|
|
70
|
+
)}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Dispatch, SetStateAction } from "react";
|
|
4
|
+
import { Tuple } from "./Tuple";
|
|
5
|
+
import { TupleArray } from "./TupleArray";
|
|
6
|
+
import { AbiParameter } from "abitype";
|
|
7
|
+
import {
|
|
8
|
+
AddressInput,
|
|
9
|
+
Bytes32Input,
|
|
10
|
+
BytesInput,
|
|
11
|
+
InputBase,
|
|
12
|
+
IntegerInput,
|
|
13
|
+
IntegerVariant,
|
|
14
|
+
} from "~~/components/scaffold-eth";
|
|
15
|
+
import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";
|
|
16
|
+
|
|
17
|
+
type ContractInputProps = {
|
|
18
|
+
setForm: Dispatch<SetStateAction<Record<string, any>>>;
|
|
19
|
+
form: Record<string, any> | undefined;
|
|
20
|
+
stateObjectKey: string;
|
|
21
|
+
paramType: AbiParameter;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Generic Input component to handle input's based on their function param type
|
|
26
|
+
*/
|
|
27
|
+
export const ContractInput = ({ setForm, form, stateObjectKey, paramType }: ContractInputProps) => {
|
|
28
|
+
const inputProps = {
|
|
29
|
+
name: stateObjectKey,
|
|
30
|
+
value: form?.[stateObjectKey],
|
|
31
|
+
placeholder: paramType.name ? `${paramType.type} ${paramType.name}` : paramType.type,
|
|
32
|
+
onChange: (value: any) => {
|
|
33
|
+
setForm(form => ({ ...form, [stateObjectKey]: value }));
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const renderInput = () => {
|
|
38
|
+
switch (paramType.type) {
|
|
39
|
+
case "address":
|
|
40
|
+
return <AddressInput {...inputProps} />;
|
|
41
|
+
case "bytes32":
|
|
42
|
+
return <Bytes32Input {...inputProps} />;
|
|
43
|
+
case "bytes":
|
|
44
|
+
return <BytesInput {...inputProps} />;
|
|
45
|
+
case "string":
|
|
46
|
+
return <InputBase {...inputProps} />;
|
|
47
|
+
case "tuple":
|
|
48
|
+
return (
|
|
49
|
+
<Tuple
|
|
50
|
+
setParentForm={setForm}
|
|
51
|
+
parentForm={form}
|
|
52
|
+
abiTupleParameter={paramType as AbiParameterTuple}
|
|
53
|
+
parentStateObjectKey={stateObjectKey}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
default:
|
|
57
|
+
// Handling 'int' types and 'tuple[]' types
|
|
58
|
+
if (paramType.type.includes("int") && !paramType.type.includes("[")) {
|
|
59
|
+
return <IntegerInput {...inputProps} variant={paramType.type as IntegerVariant} />;
|
|
60
|
+
} else if (paramType.type.startsWith("tuple[")) {
|
|
61
|
+
return (
|
|
62
|
+
<TupleArray
|
|
63
|
+
setParentForm={setForm}
|
|
64
|
+
parentForm={form}
|
|
65
|
+
abiTupleParameter={paramType as AbiParameterTuple}
|
|
66
|
+
parentStateObjectKey={stateObjectKey}
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
} else {
|
|
70
|
+
return <InputBase {...inputProps} />;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className="flex flex-col gap-1.5 w-full">
|
|
77
|
+
<div className="flex items-center ml-2">
|
|
78
|
+
{paramType.name && <span className="text-xs font-medium mr-2 leading-none">{paramType.name}</span>}
|
|
79
|
+
<span className="block text-xs font-extralight leading-none">{paramType.type}</span>
|
|
80
|
+
</div>
|
|
81
|
+
{renderInput()}
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Abi, AbiFunction } from "abitype";
|
|
2
|
+
import { ReadOnlyFunctionForm } from "~~/app/debug/_components/contract";
|
|
3
|
+
import { Contract, ContractName, GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract";
|
|
4
|
+
|
|
5
|
+
export const ContractReadMethods = ({ deployedContractData }: { deployedContractData: Contract<ContractName> }) => {
|
|
6
|
+
if (!deployedContractData) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const functionsToDisplay = (
|
|
11
|
+
((deployedContractData.abi || []) as Abi).filter(part => part.type === "function") as AbiFunction[]
|
|
12
|
+
)
|
|
13
|
+
.filter(fn => {
|
|
14
|
+
const isQueryableWithParams =
|
|
15
|
+
(fn.stateMutability === "view" || fn.stateMutability === "pure") && fn.inputs.length > 0;
|
|
16
|
+
return isQueryableWithParams;
|
|
17
|
+
})
|
|
18
|
+
.map(fn => {
|
|
19
|
+
return {
|
|
20
|
+
fn,
|
|
21
|
+
inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name],
|
|
22
|
+
};
|
|
23
|
+
})
|
|
24
|
+
.sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1));
|
|
25
|
+
|
|
26
|
+
if (!functionsToDisplay.length) {
|
|
27
|
+
return <div className="py-[2px]">No read methods</div>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
{functionsToDisplay.map(({ fn, inheritedFrom }) => (
|
|
33
|
+
<ReadOnlyFunctionForm
|
|
34
|
+
abi={deployedContractData.abi as Abi}
|
|
35
|
+
contractAddress={deployedContractData.address}
|
|
36
|
+
abiFunction={fn}
|
|
37
|
+
key={fn.name}
|
|
38
|
+
inheritedFrom={inheritedFrom}
|
|
39
|
+
/>
|
|
40
|
+
))}
|
|
41
|
+
</>
|
|
42
|
+
);
|
|
43
|
+
};
|