create-stylus 0.0.5

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.
Files changed (220) hide show
  1. package/.github/issue_template.md +7 -0
  2. package/.github/pull_request_template.md +11 -0
  3. package/.github/workflows/release-alpha.yml +32 -0
  4. package/.github/workflows/release-manual.yml +26 -0
  5. package/.yarnrc.yml +1 -0
  6. package/CONTRIBUTING.md +42 -0
  7. package/README.md +66 -0
  8. package/bin/create-dapp-ss.js +4 -0
  9. package/package.json +46 -0
  10. package/rollup.config.js +22 -0
  11. package/src/cli.ts +14 -0
  12. package/src/extensions.json +14 -0
  13. package/src/main.ts +72 -0
  14. package/src/tasks/copy-extension-file.ts +227 -0
  15. package/src/tasks/copy-template-files.ts +252 -0
  16. package/src/tasks/create-first-git-commit.ts +35 -0
  17. package/src/tasks/create-project-directory.ts +34 -0
  18. package/src/tasks/index.ts +5 -0
  19. package/src/tasks/install-packages.ts +15 -0
  20. package/src/tasks/prettier-format.ts +17 -0
  21. package/src/types.ts +31 -0
  22. package/src/utils/consts.ts +1 -0
  23. package/src/utils/find-files-recursively.ts +19 -0
  24. package/src/utils/link.ts +44 -0
  25. package/src/utils/load-extensions.ts +10 -0
  26. package/src/utils/merge-package-json.ts +33 -0
  27. package/src/utils/parse-arguments-into-options.ts +38 -0
  28. package/src/utils/prompt-for-missing-options.ts +53 -0
  29. package/src/utils/render-intro-message.ts +11 -0
  30. package/src/utils/render-outro-message.ts +34 -0
  31. package/templates/base/.github/ISSUE_TEMPLATE/bug_report.yml +58 -0
  32. package/templates/base/.github/ISSUE_TEMPLATE/config.yml +8 -0
  33. package/templates/base/.github/pull_request_template.md +16 -0
  34. package/templates/base/.github/workflows/lint.yaml +300 -0
  35. package/templates/base/.gitignore.template.mjs +19 -0
  36. package/templates/base/.gitmodules +0 -0
  37. package/templates/base/.husky/pre-commit +4 -0
  38. package/templates/base/.lintstagedrc.js +21 -0
  39. package/templates/base/.vscode/settings.json +7 -0
  40. package/templates/base/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
  41. package/templates/base/.yarn/releases/yarn-3.2.3.cjs +783 -0
  42. package/templates/base/.yarnrc.yml +11 -0
  43. package/templates/base/CONTRIBUTING.md +86 -0
  44. package/templates/base/LICENCE +21 -0
  45. package/templates/base/dist/cli.js +683 -0
  46. package/templates/base/dist/cli.js.map +1 -0
  47. package/templates/base/nitro-devnode/LICENSE +201 -0
  48. package/templates/base/nitro-devnode/README.md +70 -0
  49. package/templates/base/nitro-devnode/run-dev-node.sh +132 -0
  50. package/templates/base/nitro-devnode/start-chain-with-cors.sh +150 -0
  51. package/templates/base/nitro-devnode/stylus-deployer-bytecode.txt +1 -0
  52. package/templates/base/nitro-devnode/stylus-dev/Dockerfile +10 -0
  53. package/templates/base/package.json +44 -0
  54. package/templates/base/packages/nextjs/.env.example +13 -0
  55. package/templates/base/packages/nextjs/.eslintignore +11 -0
  56. package/templates/base/packages/nextjs/.eslintrc.json +15 -0
  57. package/templates/base/packages/nextjs/.gitignore.template.mjs +42 -0
  58. package/templates/base/packages/nextjs/.prettierrc.js +9 -0
  59. package/templates/base/packages/nextjs/.prettierrc.json +8 -0
  60. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressCodeTab.tsx +27 -0
  61. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressComponent.tsx +36 -0
  62. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressLogsTab.tsx +21 -0
  63. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressStorageTab.tsx +61 -0
  64. package/templates/base/packages/nextjs/app/blockexplorer/_components/BackButton.tsx +12 -0
  65. package/templates/base/packages/nextjs/app/blockexplorer/_components/ContractTabs.tsx +102 -0
  66. package/templates/base/packages/nextjs/app/blockexplorer/_components/PaginationButton.tsx +39 -0
  67. package/templates/base/packages/nextjs/app/blockexplorer/_components/SearchBar.tsx +49 -0
  68. package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionHash.tsx +28 -0
  69. package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionsTable.tsx +71 -0
  70. package/templates/base/packages/nextjs/app/blockexplorer/_components/index.tsx +7 -0
  71. package/templates/base/packages/nextjs/app/blockexplorer/address/[address]/page.tsx +101 -0
  72. package/templates/base/packages/nextjs/app/blockexplorer/layout.tsx +12 -0
  73. package/templates/base/packages/nextjs/app/blockexplorer/page.tsx +83 -0
  74. package/templates/base/packages/nextjs/app/blockexplorer/transaction/[txHash]/page.tsx +23 -0
  75. package/templates/base/packages/nextjs/app/blockexplorer/transaction/_components/TransactionComp.tsx +152 -0
  76. package/templates/base/packages/nextjs/app/debug/_components/DebugContracts.tsx +73 -0
  77. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractInput.tsx +84 -0
  78. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractReadMethods.tsx +43 -0
  79. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +164 -0
  80. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractVariables.tsx +50 -0
  81. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractWriteMethods.tsx +49 -0
  82. package/templates/base/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +85 -0
  83. package/templates/base/packages/nextjs/app/debug/_components/contract/InheritanceTooltip.tsx +14 -0
  84. package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +102 -0
  85. package/templates/base/packages/nextjs/app/debug/_components/contract/Tuple.tsx +44 -0
  86. package/templates/base/packages/nextjs/app/debug/_components/contract/TupleArray.tsx +142 -0
  87. package/templates/base/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +42 -0
  88. package/templates/base/packages/nextjs/app/debug/_components/contract/WriteOnlyFunctionForm.tsx +144 -0
  89. package/templates/base/packages/nextjs/app/debug/_components/contract/index.tsx +8 -0
  90. package/templates/base/packages/nextjs/app/debug/_components/contract/utilsContract.tsx +166 -0
  91. package/templates/base/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +114 -0
  92. package/templates/base/packages/nextjs/app/debug/page.tsx +14 -0
  93. package/templates/base/packages/nextjs/app/layout.tsx +67 -0
  94. package/templates/base/packages/nextjs/app/not-found.tsx +16 -0
  95. package/templates/base/packages/nextjs/app/page.tsx +94 -0
  96. package/templates/base/packages/nextjs/components/Background.tsx +37 -0
  97. package/templates/base/packages/nextjs/components/Card.tsx +40 -0
  98. package/templates/base/packages/nextjs/components/Footer.tsx +93 -0
  99. package/templates/base/packages/nextjs/components/Header.tsx +114 -0
  100. package/templates/base/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx +77 -0
  101. package/templates/base/packages/nextjs/components/SwitchTheme.tsx +41 -0
  102. package/templates/base/packages/nextjs/components/ThemeProvider.tsx +13 -0
  103. package/templates/base/packages/nextjs/components/assets/BuidlGuidlLogo.tsx +18 -0
  104. package/templates/base/packages/nextjs/components/scaffold-eth/Address/Address.tsx +187 -0
  105. package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressCopyIcon.tsx +23 -0
  106. package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressLinkWrapper.tsx +29 -0
  107. package/templates/base/packages/nextjs/components/scaffold-eth/Balance.tsx +75 -0
  108. package/templates/base/packages/nextjs/components/scaffold-eth/BlockieAvatar.tsx +17 -0
  109. package/templates/base/packages/nextjs/components/scaffold-eth/Faucet.tsx +131 -0
  110. package/templates/base/packages/nextjs/components/scaffold-eth/FaucetButton.tsx +75 -0
  111. package/templates/base/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx +120 -0
  112. package/templates/base/packages/nextjs/components/scaffold-eth/Input/Bytes32Input.tsx +31 -0
  113. package/templates/base/packages/nextjs/components/scaffold-eth/Input/BytesInput.tsx +28 -0
  114. package/templates/base/packages/nextjs/components/scaffold-eth/Input/EtherInput.tsx +128 -0
  115. package/templates/base/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx +66 -0
  116. package/templates/base/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +63 -0
  117. package/templates/base/packages/nextjs/components/scaffold-eth/Input/index.ts +9 -0
  118. package/templates/base/packages/nextjs/components/scaffold-eth/Input/utils.ts +109 -0
  119. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressInfoDropdown.tsx +121 -0
  120. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressQRCodeModal.tsx +33 -0
  121. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/BurnerWalletModal.tsx +63 -0
  122. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/NetworkOptions.tsx +48 -0
  123. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/WrongNetworkDropdown.tsx +32 -0
  124. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/index.tsx +89 -0
  125. package/templates/base/packages/nextjs/components/scaffold-eth/index.tsx +7 -0
  126. package/templates/base/packages/nextjs/contracts/deployedContracts.ts +9 -0
  127. package/templates/base/packages/nextjs/contracts/externalContracts.ts +16 -0
  128. package/templates/base/packages/nextjs/eslint.config.mjs +32 -0
  129. package/templates/base/packages/nextjs/hooks/scaffold-eth/index.ts +17 -0
  130. package/templates/base/packages/nextjs/hooks/scaffold-eth/useAnimationConfig.ts +20 -0
  131. package/templates/base/packages/nextjs/hooks/scaffold-eth/useContractLogs.ts +40 -0
  132. package/templates/base/packages/nextjs/hooks/scaffold-eth/useCopyToClipboard.ts +19 -0
  133. package/templates/base/packages/nextjs/hooks/scaffold-eth/useDeployedContractInfo.ts +86 -0
  134. package/templates/base/packages/nextjs/hooks/scaffold-eth/useDisplayUsdMode.ts +21 -0
  135. package/templates/base/packages/nextjs/hooks/scaffold-eth/useFetchBlocks.ts +133 -0
  136. package/templates/base/packages/nextjs/hooks/scaffold-eth/useInitializeNativeCurrencyPrice.ts +32 -0
  137. package/templates/base/packages/nextjs/hooks/scaffold-eth/useNativeCurrencyPrice.ts +34 -0
  138. package/templates/base/packages/nextjs/hooks/scaffold-eth/useNetworkColor.ts +22 -0
  139. package/templates/base/packages/nextjs/hooks/scaffold-eth/useOutsideClick.ts +23 -0
  140. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldContract.ts +65 -0
  141. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts +213 -0
  142. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts +80 -0
  143. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWatchContractEvent.ts +40 -0
  144. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts +191 -0
  145. package/templates/base/packages/nextjs/hooks/scaffold-eth/useSelectedNetwork.ts +18 -0
  146. package/templates/base/packages/nextjs/hooks/scaffold-eth/useTargetNetwork.ts +23 -0
  147. package/templates/base/packages/nextjs/hooks/scaffold-eth/useTransactor.tsx +114 -0
  148. package/templates/base/packages/nextjs/hooks/scaffold-eth/useWatchBalance.ts +21 -0
  149. package/templates/base/packages/nextjs/icons/CompassIcon.tsx +39 -0
  150. package/templates/base/packages/nextjs/icons/DarkBugAntIcon.tsx +30 -0
  151. package/templates/base/packages/nextjs/icons/LightBugAntIcon.tsx +52 -0
  152. package/templates/base/packages/nextjs/next-env.d.ts +5 -0
  153. package/templates/base/packages/nextjs/next.config.js +19 -0
  154. package/templates/base/packages/nextjs/package.json +58 -0
  155. package/templates/base/packages/nextjs/postcss.config.js +6 -0
  156. package/templates/base/packages/nextjs/public/debug-image.png +0 -0
  157. package/templates/base/packages/nextjs/public/favicon.png +0 -0
  158. package/templates/base/packages/nextjs/public/logo.svg +8 -0
  159. package/templates/base/packages/nextjs/public/manifest.json +5 -0
  160. package/templates/base/packages/nextjs/public/thumbnail.jpg +0 -0
  161. package/templates/base/packages/nextjs/react-copy-to-clipboard.d.ts +44 -0
  162. package/templates/base/packages/nextjs/scaffold.config.ts +56 -0
  163. package/templates/base/packages/nextjs/services/store/store.ts +39 -0
  164. package/templates/base/packages/nextjs/services/web3/wagmiConfig.tsx +44 -0
  165. package/templates/base/packages/nextjs/services/web3/wagmiConnectors.tsx +51 -0
  166. package/templates/base/packages/nextjs/styles/globals.css +80 -0
  167. package/templates/base/packages/nextjs/tailwind.config.js +97 -0
  168. package/templates/base/packages/nextjs/tsconfig.json +28 -0
  169. package/templates/base/packages/nextjs/types/abitype/abi.d.ts +16 -0
  170. package/templates/base/packages/nextjs/types/utils.ts +3 -0
  171. package/templates/base/packages/nextjs/utils/scaffold-eth/block.ts +17 -0
  172. package/templates/base/packages/nextjs/utils/scaffold-eth/common.ts +8 -0
  173. package/templates/base/packages/nextjs/utils/scaffold-eth/contract.ts +352 -0
  174. package/templates/base/packages/nextjs/utils/scaffold-eth/contractsData.ts +11 -0
  175. package/templates/base/packages/nextjs/utils/scaffold-eth/decodeTxData.ts +65 -0
  176. package/templates/base/packages/nextjs/utils/scaffold-eth/fetchPriceFromUniswap.ts +72 -0
  177. package/templates/base/packages/nextjs/utils/scaffold-eth/getMetadata.ts +50 -0
  178. package/templates/base/packages/nextjs/utils/scaffold-eth/getParsedError.ts +35 -0
  179. package/templates/base/packages/nextjs/utils/scaffold-eth/index.ts +6 -0
  180. package/templates/base/packages/nextjs/utils/scaffold-eth/notification.tsx +90 -0
  181. package/templates/base/packages/nextjs/utils/scaffold-stylus/burner.ts +59 -0
  182. package/templates/base/packages/nextjs/utils/scaffold-stylus/chain.ts +42 -0
  183. package/templates/base/packages/nextjs/utils/scaffold-stylus/index.ts +3 -0
  184. package/templates/base/packages/nextjs/utils/scaffold-stylus/networks.ts +94 -0
  185. package/templates/base/packages/nextjs/vercel.json +3 -0
  186. package/templates/base/packages/stylus/.env.example +16 -0
  187. package/templates/base/packages/stylus/.eslintrc.js +23 -0
  188. package/templates/base/packages/stylus/.gitignore.template.mjs +7 -0
  189. package/templates/base/packages/stylus/jest.config.js +15 -0
  190. package/templates/base/packages/stylus/package.json +48 -0
  191. package/templates/base/packages/stylus/scripts/deploy.ts +46 -0
  192. package/templates/base/packages/stylus/scripts/deploy_contract.ts +84 -0
  193. package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +39 -0
  194. package/templates/base/packages/stylus/scripts/export_abi.ts +87 -0
  195. package/templates/base/packages/stylus/scripts/index.ts +0 -0
  196. package/templates/base/packages/stylus/scripts/new_module.sh +35 -0
  197. package/templates/base/packages/stylus/scripts/test_network.ts +31 -0
  198. package/templates/base/packages/stylus/scripts/utils/command.ts +152 -0
  199. package/templates/base/packages/stylus/scripts/utils/contract.ts +228 -0
  200. package/templates/base/packages/stylus/scripts/utils/deployment.ts +260 -0
  201. package/templates/base/packages/stylus/scripts/utils/index.ts +6 -0
  202. package/templates/base/packages/stylus/scripts/utils/network.ts +132 -0
  203. package/templates/base/packages/stylus/scripts/utils/type.ts +51 -0
  204. package/templates/base/packages/stylus/scripts/utils.ts +3 -0
  205. package/templates/base/packages/stylus/tsconfig.json +41 -0
  206. package/templates/base/packages/stylus/your-contract/.cargo/config.toml +18 -0
  207. package/templates/base/packages/stylus/your-contract/Cargo.lock +5761 -0
  208. package/templates/base/packages/stylus/your-contract/Cargo.toml +48 -0
  209. package/templates/base/packages/stylus/your-contract/examples/counter.rs +78 -0
  210. package/templates/base/packages/stylus/your-contract/header.png +0 -0
  211. package/templates/base/packages/stylus/your-contract/licenses/Apache-2.0 +201 -0
  212. package/templates/base/packages/stylus/your-contract/licenses/COPYRIGHT.md +5 -0
  213. package/templates/base/packages/stylus/your-contract/licenses/DCO.txt +34 -0
  214. package/templates/base/packages/stylus/your-contract/licenses/MIT +21 -0
  215. package/templates/base/packages/stylus/your-contract/rust-toolchain.toml +2 -0
  216. package/templates/base/packages/stylus/your-contract/src/lib.rs +241 -0
  217. package/templates/base/packages/stylus/your-contract/src/main.rs +10 -0
  218. package/templates/base/readme.md +352 -0
  219. package/templates/base/yarn.lock +17859 -0
  220. 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;
@@ -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
+ };