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.
Files changed (222) 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/.yarnrc.yml +1 -0
  5. package/CONTRIBUTING.md +42 -0
  6. package/README.md +66 -0
  7. package/bin/create-dapp-ss.js +4 -0
  8. package/dist/cli.js +656 -0
  9. package/dist/cli.js.map +1 -0
  10. package/package.json +46 -0
  11. package/rollup.config.js +22 -0
  12. package/src/cli.ts +14 -0
  13. package/src/extensions.json +14 -0
  14. package/src/main.ts +70 -0
  15. package/src/tasks/copy-extension-file.ts +227 -0
  16. package/src/tasks/copy-template-files.ts +252 -0
  17. package/src/tasks/create-first-git-commit.ts +35 -0
  18. package/src/tasks/create-project-directory.ts +34 -0
  19. package/src/tasks/index.ts +5 -0
  20. package/src/tasks/install-packages.ts +15 -0
  21. package/src/tasks/prettier-format.ts +17 -0
  22. package/src/types.ts +31 -0
  23. package/src/utils/consts.ts +1 -0
  24. package/src/utils/find-files-recursively.ts +19 -0
  25. package/src/utils/link.ts +44 -0
  26. package/src/utils/load-extensions.ts +10 -0
  27. package/src/utils/merge-package-json.ts +33 -0
  28. package/src/utils/parse-arguments-into-options.ts +38 -0
  29. package/src/utils/prompt-for-missing-options.ts +53 -0
  30. package/src/utils/render-intro-message.ts +11 -0
  31. package/src/utils/render-outro-message.ts +34 -0
  32. package/templates/base/.github/ISSUE_TEMPLATE/bug_report.yml +58 -0
  33. package/templates/base/.github/ISSUE_TEMPLATE/config.yml +8 -0
  34. package/templates/base/.github/pull_request_template.md +16 -0
  35. package/templates/base/.github/workflows/lint.yaml +300 -0
  36. package/templates/base/.gitignore.template.mjs +19 -0
  37. package/templates/base/.gitmodules +0 -0
  38. package/templates/base/.husky/pre-commit +4 -0
  39. package/templates/base/.lintstagedrc.js +21 -0
  40. package/templates/base/.vscode/settings.json +7 -0
  41. package/templates/base/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
  42. package/templates/base/.yarn/releases/yarn-3.2.3.cjs +783 -0
  43. package/templates/base/.yarnrc.yml +11 -0
  44. package/templates/base/CONTRIBUTING.md +86 -0
  45. package/templates/base/LICENCE +21 -0
  46. package/templates/base/nitro-devnode/LICENSE +201 -0
  47. package/templates/base/nitro-devnode/README.md +70 -0
  48. package/templates/base/nitro-devnode/run-dev-node.sh +132 -0
  49. package/templates/base/nitro-devnode/start-chain-with-cors.sh +150 -0
  50. package/templates/base/nitro-devnode/stylus-deployer-bytecode.txt +1 -0
  51. package/templates/base/nitro-devnode/stylus-dev/Dockerfile +10 -0
  52. package/templates/base/package.json +43 -0
  53. package/templates/base/packages/nextjs/.env.example +13 -0
  54. package/templates/base/packages/nextjs/.eslintignore +11 -0
  55. package/templates/base/packages/nextjs/.eslintrc.json +15 -0
  56. package/templates/base/packages/nextjs/.gitignore.template.mjs +42 -0
  57. package/templates/base/packages/nextjs/.prettierrc.js +9 -0
  58. package/templates/base/packages/nextjs/.prettierrc.json +8 -0
  59. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressCodeTab.tsx +27 -0
  60. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressComponent.tsx +36 -0
  61. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressLogsTab.tsx +21 -0
  62. package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressStorageTab.tsx +61 -0
  63. package/templates/base/packages/nextjs/app/blockexplorer/_components/BackButton.tsx +12 -0
  64. package/templates/base/packages/nextjs/app/blockexplorer/_components/ContractTabs.tsx +102 -0
  65. package/templates/base/packages/nextjs/app/blockexplorer/_components/PaginationButton.tsx +39 -0
  66. package/templates/base/packages/nextjs/app/blockexplorer/_components/SearchBar.tsx +49 -0
  67. package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionHash.tsx +28 -0
  68. package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionsTable.tsx +71 -0
  69. package/templates/base/packages/nextjs/app/blockexplorer/_components/index.tsx +7 -0
  70. package/templates/base/packages/nextjs/app/blockexplorer/address/[address]/page.tsx +101 -0
  71. package/templates/base/packages/nextjs/app/blockexplorer/layout.tsx +12 -0
  72. package/templates/base/packages/nextjs/app/blockexplorer/page.tsx +83 -0
  73. package/templates/base/packages/nextjs/app/blockexplorer/transaction/[txHash]/page.tsx +23 -0
  74. package/templates/base/packages/nextjs/app/blockexplorer/transaction/_components/TransactionComp.tsx +152 -0
  75. package/templates/base/packages/nextjs/app/debug/_components/DebugContracts.tsx +73 -0
  76. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractInput.tsx +84 -0
  77. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractReadMethods.tsx +43 -0
  78. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +164 -0
  79. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractVariables.tsx +50 -0
  80. package/templates/base/packages/nextjs/app/debug/_components/contract/ContractWriteMethods.tsx +49 -0
  81. package/templates/base/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +85 -0
  82. package/templates/base/packages/nextjs/app/debug/_components/contract/InheritanceTooltip.tsx +14 -0
  83. package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +102 -0
  84. package/templates/base/packages/nextjs/app/debug/_components/contract/Tuple.tsx +44 -0
  85. package/templates/base/packages/nextjs/app/debug/_components/contract/TupleArray.tsx +142 -0
  86. package/templates/base/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +42 -0
  87. package/templates/base/packages/nextjs/app/debug/_components/contract/WriteOnlyFunctionForm.tsx +144 -0
  88. package/templates/base/packages/nextjs/app/debug/_components/contract/index.tsx +8 -0
  89. package/templates/base/packages/nextjs/app/debug/_components/contract/utilsContract.tsx +166 -0
  90. package/templates/base/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +114 -0
  91. package/templates/base/packages/nextjs/app/debug/page.tsx +14 -0
  92. package/templates/base/packages/nextjs/app/layout.tsx +67 -0
  93. package/templates/base/packages/nextjs/app/not-found.tsx +16 -0
  94. package/templates/base/packages/nextjs/app/page.tsx +94 -0
  95. package/templates/base/packages/nextjs/components/Background.tsx +37 -0
  96. package/templates/base/packages/nextjs/components/Card.tsx +40 -0
  97. package/templates/base/packages/nextjs/components/Footer.tsx +93 -0
  98. package/templates/base/packages/nextjs/components/Header.tsx +114 -0
  99. package/templates/base/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx +77 -0
  100. package/templates/base/packages/nextjs/components/SwitchTheme.tsx +41 -0
  101. package/templates/base/packages/nextjs/components/ThemeProvider.tsx +13 -0
  102. package/templates/base/packages/nextjs/components/assets/BuidlGuidlLogo.tsx +18 -0
  103. package/templates/base/packages/nextjs/components/scaffold-eth/Address/Address.tsx +187 -0
  104. package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressCopyIcon.tsx +23 -0
  105. package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressLinkWrapper.tsx +29 -0
  106. package/templates/base/packages/nextjs/components/scaffold-eth/Balance.tsx +75 -0
  107. package/templates/base/packages/nextjs/components/scaffold-eth/BlockieAvatar.tsx +17 -0
  108. package/templates/base/packages/nextjs/components/scaffold-eth/Faucet.tsx +131 -0
  109. package/templates/base/packages/nextjs/components/scaffold-eth/FaucetButton.tsx +75 -0
  110. package/templates/base/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx +120 -0
  111. package/templates/base/packages/nextjs/components/scaffold-eth/Input/Bytes32Input.tsx +31 -0
  112. package/templates/base/packages/nextjs/components/scaffold-eth/Input/BytesInput.tsx +28 -0
  113. package/templates/base/packages/nextjs/components/scaffold-eth/Input/EtherInput.tsx +128 -0
  114. package/templates/base/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx +66 -0
  115. package/templates/base/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +63 -0
  116. package/templates/base/packages/nextjs/components/scaffold-eth/Input/index.ts +9 -0
  117. package/templates/base/packages/nextjs/components/scaffold-eth/Input/utils.ts +109 -0
  118. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressInfoDropdown.tsx +121 -0
  119. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressQRCodeModal.tsx +33 -0
  120. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/BurnerWalletModal.tsx +63 -0
  121. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/NetworkOptions.tsx +48 -0
  122. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/WrongNetworkDropdown.tsx +32 -0
  123. package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/index.tsx +89 -0
  124. package/templates/base/packages/nextjs/components/scaffold-eth/index.tsx +7 -0
  125. package/templates/base/packages/nextjs/contracts/deployedContracts.ts +9 -0
  126. package/templates/base/packages/nextjs/contracts/externalContracts.ts +16 -0
  127. package/templates/base/packages/nextjs/eslint.config.mjs +32 -0
  128. package/templates/base/packages/nextjs/hooks/scaffold-eth/index.ts +17 -0
  129. package/templates/base/packages/nextjs/hooks/scaffold-eth/useAnimationConfig.ts +20 -0
  130. package/templates/base/packages/nextjs/hooks/scaffold-eth/useContractLogs.ts +40 -0
  131. package/templates/base/packages/nextjs/hooks/scaffold-eth/useCopyToClipboard.ts +19 -0
  132. package/templates/base/packages/nextjs/hooks/scaffold-eth/useDeployedContractInfo.ts +86 -0
  133. package/templates/base/packages/nextjs/hooks/scaffold-eth/useDisplayUsdMode.ts +21 -0
  134. package/templates/base/packages/nextjs/hooks/scaffold-eth/useFetchBlocks.ts +133 -0
  135. package/templates/base/packages/nextjs/hooks/scaffold-eth/useInitializeNativeCurrencyPrice.ts +32 -0
  136. package/templates/base/packages/nextjs/hooks/scaffold-eth/useNativeCurrencyPrice.ts +34 -0
  137. package/templates/base/packages/nextjs/hooks/scaffold-eth/useNetworkColor.ts +22 -0
  138. package/templates/base/packages/nextjs/hooks/scaffold-eth/useOutsideClick.ts +23 -0
  139. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldContract.ts +65 -0
  140. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts +213 -0
  141. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts +80 -0
  142. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWatchContractEvent.ts +40 -0
  143. package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts +191 -0
  144. package/templates/base/packages/nextjs/hooks/scaffold-eth/useSelectedNetwork.ts +18 -0
  145. package/templates/base/packages/nextjs/hooks/scaffold-eth/useTargetNetwork.ts +23 -0
  146. package/templates/base/packages/nextjs/hooks/scaffold-eth/useTransactor.tsx +114 -0
  147. package/templates/base/packages/nextjs/hooks/scaffold-eth/useWatchBalance.ts +21 -0
  148. package/templates/base/packages/nextjs/icons/CompassIcon.tsx +39 -0
  149. package/templates/base/packages/nextjs/icons/DarkBugAntIcon.tsx +30 -0
  150. package/templates/base/packages/nextjs/icons/LightBugAntIcon.tsx +52 -0
  151. package/templates/base/packages/nextjs/next-env.d.ts +5 -0
  152. package/templates/base/packages/nextjs/next.config.js +19 -0
  153. package/templates/base/packages/nextjs/package.json +58 -0
  154. package/templates/base/packages/nextjs/postcss.config.js +6 -0
  155. package/templates/base/packages/nextjs/public/debug-image.png +0 -0
  156. package/templates/base/packages/nextjs/public/favicon.png +0 -0
  157. package/templates/base/packages/nextjs/public/logo.svg +8 -0
  158. package/templates/base/packages/nextjs/public/manifest.json +5 -0
  159. package/templates/base/packages/nextjs/public/thumbnail.jpg +0 -0
  160. package/templates/base/packages/nextjs/react-copy-to-clipboard.d.ts +44 -0
  161. package/templates/base/packages/nextjs/scaffold.config.ts +56 -0
  162. package/templates/base/packages/nextjs/services/store/store.ts +39 -0
  163. package/templates/base/packages/nextjs/services/web3/wagmiConfig.tsx +44 -0
  164. package/templates/base/packages/nextjs/services/web3/wagmiConnectors.tsx +51 -0
  165. package/templates/base/packages/nextjs/styles/globals.css +80 -0
  166. package/templates/base/packages/nextjs/tailwind.config.js +97 -0
  167. package/templates/base/packages/nextjs/tsconfig.json +28 -0
  168. package/templates/base/packages/nextjs/types/abitype/abi.d.ts +16 -0
  169. package/templates/base/packages/nextjs/types/utils.ts +3 -0
  170. package/templates/base/packages/nextjs/utils/scaffold-eth/block.ts +17 -0
  171. package/templates/base/packages/nextjs/utils/scaffold-eth/common.ts +8 -0
  172. package/templates/base/packages/nextjs/utils/scaffold-eth/contract.ts +352 -0
  173. package/templates/base/packages/nextjs/utils/scaffold-eth/contractsData.ts +11 -0
  174. package/templates/base/packages/nextjs/utils/scaffold-eth/decodeTxData.ts +65 -0
  175. package/templates/base/packages/nextjs/utils/scaffold-eth/fetchPriceFromUniswap.ts +72 -0
  176. package/templates/base/packages/nextjs/utils/scaffold-eth/getMetadata.ts +50 -0
  177. package/templates/base/packages/nextjs/utils/scaffold-eth/getParsedError.ts +35 -0
  178. package/templates/base/packages/nextjs/utils/scaffold-eth/index.ts +6 -0
  179. package/templates/base/packages/nextjs/utils/scaffold-eth/notification.tsx +90 -0
  180. package/templates/base/packages/nextjs/utils/scaffold-stylus/burner.ts +59 -0
  181. package/templates/base/packages/nextjs/utils/scaffold-stylus/chain.ts +42 -0
  182. package/templates/base/packages/nextjs/utils/scaffold-stylus/index.ts +3 -0
  183. package/templates/base/packages/nextjs/utils/scaffold-stylus/networks.ts +94 -0
  184. package/templates/base/packages/nextjs/vercel.json +3 -0
  185. package/templates/base/packages/stylus/.env.example +13 -0
  186. package/templates/base/packages/stylus/.eslintrc.js +23 -0
  187. package/templates/base/packages/stylus/.gitignore.template.mjs +7 -0
  188. package/templates/base/packages/stylus/README.md +263 -0
  189. package/templates/base/packages/stylus/header.png +0 -0
  190. package/templates/base/packages/stylus/jest.config.js +15 -0
  191. package/templates/base/packages/stylus/package.json +49 -0
  192. package/templates/base/packages/stylus/scripts/deploy.ts +29 -0
  193. package/templates/base/packages/stylus/scripts/deploy_all_contracts.ts +59 -0
  194. package/templates/base/packages/stylus/scripts/deploy_contract.ts +93 -0
  195. package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +79 -0
  196. package/templates/base/packages/stylus/scripts/export_abi.ts +87 -0
  197. package/templates/base/packages/stylus/scripts/index.ts +0 -0
  198. package/templates/base/packages/stylus/scripts/new_module.sh +35 -0
  199. package/templates/base/packages/stylus/scripts/test_network.ts +31 -0
  200. package/templates/base/packages/stylus/scripts/utils/command.ts +165 -0
  201. package/templates/base/packages/stylus/scripts/utils/contract.ts +219 -0
  202. package/templates/base/packages/stylus/scripts/utils/deployment.ts +136 -0
  203. package/templates/base/packages/stylus/scripts/utils/index.ts +6 -0
  204. package/templates/base/packages/stylus/scripts/utils/network.ts +112 -0
  205. package/templates/base/packages/stylus/scripts/utils/type.ts +48 -0
  206. package/templates/base/packages/stylus/scripts/utils.ts +3 -0
  207. package/templates/base/packages/stylus/tsconfig.json +41 -0
  208. package/templates/base/packages/stylus/your-contract/.cargo/config.toml +18 -0
  209. package/templates/base/packages/stylus/your-contract/Cargo.lock +5744 -0
  210. package/templates/base/packages/stylus/your-contract/Cargo.toml +46 -0
  211. package/templates/base/packages/stylus/your-contract/examples/counter.rs +78 -0
  212. package/templates/base/packages/stylus/your-contract/header.png +0 -0
  213. package/templates/base/packages/stylus/your-contract/licenses/Apache-2.0 +201 -0
  214. package/templates/base/packages/stylus/your-contract/licenses/COPYRIGHT.md +5 -0
  215. package/templates/base/packages/stylus/your-contract/licenses/DCO.txt +34 -0
  216. package/templates/base/packages/stylus/your-contract/licenses/MIT +21 -0
  217. package/templates/base/packages/stylus/your-contract/rust-toolchain.toml +2 -0
  218. package/templates/base/packages/stylus/your-contract/src/lib.rs +211 -0
  219. package/templates/base/packages/stylus/your-contract/src/main.rs +10 -0
  220. package/templates/base/readme.md +187 -0
  221. package/templates/base/yarn.lock +17860 -0
  222. package/tsconfig.json +13 -0
@@ -0,0 +1,164 @@
1
+ "use client";
2
+
3
+ // @refresh reset
4
+ import { useReducer } from "react";
5
+ import { ContractReadMethods } from "./ContractReadMethods";
6
+ import { ContractVariables } from "./ContractVariables";
7
+ import { ContractWriteMethods } from "./ContractWriteMethods";
8
+ import { Address, Balance } from "~~/components/scaffold-eth";
9
+ import { useDeployedContractInfo, useNetworkColor } from "~~/hooks/scaffold-eth";
10
+ import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
11
+ import { ContractName } from "~~/utils/scaffold-eth/contract";
12
+
13
+ type ContractUIProps = {
14
+ contractName: ContractName;
15
+ className?: string;
16
+ };
17
+
18
+ /**
19
+ * UI component to interface with deployed contracts.
20
+ **/
21
+ export const ContractUI = ({ contractName, className = "" }: ContractUIProps) => {
22
+ const [refreshDisplayVariables, triggerRefreshDisplayVariables] = useReducer(value => !value, false);
23
+ const { targetNetwork } = useTargetNetwork();
24
+ const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo({ contractName });
25
+ const networkColor = useNetworkColor();
26
+
27
+ if (deployedContractLoading) {
28
+ return (
29
+ <div className="mt-14">
30
+ <span className="loading loading-spinner loading-lg"></span>
31
+ </div>
32
+ );
33
+ }
34
+
35
+ if (!deployedContractData) {
36
+ return (
37
+ <p className="text-3xl mt-14">
38
+ {`No contract found by the name of "${contractName}" on chain "${targetNetwork.name}"!`}
39
+ </p>
40
+ );
41
+ }
42
+
43
+ return (
44
+ <div className={`grid grid-cols-1 lg:grid-cols-6 px-6 lg:px-10 lg:gap-12 w-full max-w-7xl my-0 ${className}`}>
45
+ <div className="col-span-5 grid grid-cols-1 lg:grid-cols-3 gap-8 lg:gap-10">
46
+ <div className="col-span-1 flex flex-col">
47
+ <div className="gradient-border shadow-md shadow-secondary rounded-xl px-6 lg:px-8 mb-6 space-y-1 py-4">
48
+ <div className="flex">
49
+ <div className="flex flex-col gap-1">
50
+ <span className="font-bold">{contractName}</span>
51
+ <Address address={deployedContractData.address} onlyEnsOrAddress />
52
+ <div className="flex gap-1 items-center">
53
+ <span className="font-bold text-sm">Balance:</span>
54
+ <Balance address={deployedContractData.address} className="px-0 h-1.5 min-h-[0.375rem]" />
55
+ </div>
56
+ </div>
57
+ </div>
58
+ {targetNetwork && (
59
+ <p className="my-0 text-sm">
60
+ <span className="font-bold">Network</span>:{" "}
61
+ <span style={{ color: networkColor }}>{targetNetwork.name}</span>
62
+ </p>
63
+ )}
64
+ </div>
65
+ <div className="gradient-border rounded-xl px-6 lg:px-8 py-4 shadow-lg shadow-base-300">
66
+ <ContractVariables
67
+ refreshDisplayVariables={refreshDisplayVariables}
68
+ deployedContractData={deployedContractData}
69
+ />
70
+ </div>
71
+ </div>
72
+ <div className="col-span-1 lg:col-span-2 flex flex-col gap-6">
73
+ <div className="z-10">
74
+ <div
75
+ className="flex flex-col gap-4"
76
+ //className="relative mt-10"
77
+ >
78
+ {/* Read Tab */}
79
+ {/*<div className="absolute -top-8 left-0 flex items-center z-20">*/}
80
+ <div className="relative inline-block w-[23%]">
81
+ {/* Botón con clip-path */}
82
+ <div
83
+ className="text-white px-8 py-2 text-xl font-medium border-2 relative z-10"
84
+ style={{
85
+ backgroundColor: "#630c3a",
86
+ borderColor: "#E3066E",
87
+ clipPath: "polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%)",
88
+ }}
89
+ >
90
+ Read
91
+ </div>
92
+
93
+ {/* Línea diagonal del corte */}
94
+ <div
95
+ className="absolute z-20"
96
+ style={{
97
+ top: "20px", // deja espacio para el border superior
98
+ right: "-1px", // deja espacio para el border derecho
99
+ width: "28.28px", // 20 * sqrt(2)
100
+ height: "2px", // igual al grosor del borde
101
+ backgroundColor: "#E3066E",
102
+ transform: "rotate(45deg)",
103
+ transformOrigin: "top right",
104
+ }}
105
+ />
106
+ </div>
107
+
108
+ {/*</div> */}
109
+ {/* Gradient Container */}
110
+ <div className="rounded-lg gradient-border min-h-[80px] flex items-center px-4 py-8 shadow-xl">
111
+ <ContractReadMethods deployedContractData={deployedContractData} />
112
+ </div>
113
+ </div>
114
+ </div>
115
+ <div className="z-10">
116
+ <div
117
+ className="flex flex-col gap-4"
118
+ //className="relative mt-10"
119
+ >
120
+ {/* Read Tab */}
121
+ {/*<div className="absolute -top-8 left-0 flex items-center z-20">*/}
122
+ <div className="relative inline-block w-[23%]">
123
+ {/* Botón con clip-path */}
124
+ <div
125
+ className="text-white px-8 py-2 text-xl font-medium border-2 relative z-10"
126
+ style={{
127
+ backgroundColor: "#630c3a",
128
+ borderColor: "#E3066E",
129
+ clipPath: "polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%)",
130
+ }}
131
+ >
132
+ Write
133
+ </div>
134
+
135
+ {/* Línea diagonal del corte */}
136
+ <div
137
+ className="absolute z-20"
138
+ style={{
139
+ top: "20px", // deja espacio para el border superior
140
+ right: "-1px", // deja espacio para el border derecho
141
+ width: "28.28px", // 20 * sqrt(2)
142
+ height: "2px", // igual al grosor del borde
143
+ backgroundColor: "#E3066E",
144
+ transform: "rotate(45deg)",
145
+ transformOrigin: "top right",
146
+ }}
147
+ />
148
+ </div>
149
+
150
+ {/*</div> */}
151
+ {/* Gradient Container */}
152
+ <div className="gradient-border rounded-lg min-h-[80px] flex flex-col px-6 py-6 shadow-xl">
153
+ <ContractWriteMethods
154
+ deployedContractData={deployedContractData}
155
+ onChange={triggerRefreshDisplayVariables}
156
+ />
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ );
164
+ };
@@ -0,0 +1,50 @@
1
+ import { DisplayVariable } from "./DisplayVariable";
2
+ import { Abi, AbiFunction } from "abitype";
3
+ import { Contract, ContractName, GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract";
4
+
5
+ export const ContractVariables = ({
6
+ refreshDisplayVariables,
7
+ deployedContractData,
8
+ }: {
9
+ refreshDisplayVariables: boolean;
10
+ deployedContractData: Contract<ContractName>;
11
+ }) => {
12
+ if (!deployedContractData) {
13
+ return null;
14
+ }
15
+
16
+ const functionsToDisplay = (
17
+ (deployedContractData.abi as Abi).filter(part => part.type === "function") as AbiFunction[]
18
+ )
19
+ .filter(fn => {
20
+ const isQueryableWithNoParams =
21
+ (fn.stateMutability === "view" || fn.stateMutability === "pure") && fn.inputs.length === 0;
22
+ return isQueryableWithNoParams;
23
+ })
24
+ .map(fn => {
25
+ return {
26
+ fn,
27
+ inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name],
28
+ };
29
+ })
30
+ .sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1));
31
+
32
+ if (!functionsToDisplay.length) {
33
+ return <>No contract variables</>;
34
+ }
35
+
36
+ return (
37
+ <>
38
+ {functionsToDisplay.map(({ fn, inheritedFrom }) => (
39
+ <DisplayVariable
40
+ abi={deployedContractData.abi as Abi}
41
+ abiFunction={fn}
42
+ contractAddress={deployedContractData.address}
43
+ key={fn.name}
44
+ refreshDisplayVariables={refreshDisplayVariables}
45
+ inheritedFrom={inheritedFrom}
46
+ />
47
+ ))}
48
+ </>
49
+ );
50
+ };
@@ -0,0 +1,49 @@
1
+ import { Abi, AbiFunction } from "abitype";
2
+ import { WriteOnlyFunctionForm } from "~~/app/debug/_components/contract";
3
+ import { Contract, ContractName, GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract";
4
+
5
+ export const ContractWriteMethods = ({
6
+ onChange,
7
+ deployedContractData,
8
+ }: {
9
+ onChange: () => void;
10
+ deployedContractData: Contract<ContractName>;
11
+ }) => {
12
+ if (!deployedContractData) {
13
+ return null;
14
+ }
15
+
16
+ const functionsToDisplay = (
17
+ (deployedContractData.abi as Abi).filter(part => part.type === "function") as AbiFunction[]
18
+ )
19
+ .filter(fn => {
20
+ const isWriteableFunction = fn.stateMutability !== "view" && fn.stateMutability !== "pure";
21
+ return isWriteableFunction;
22
+ })
23
+ .map(fn => {
24
+ return {
25
+ fn,
26
+ inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name],
27
+ };
28
+ })
29
+ .sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1));
30
+
31
+ if (!functionsToDisplay.length) {
32
+ return <>No write methods</>;
33
+ }
34
+
35
+ return (
36
+ <>
37
+ {functionsToDisplay.map(({ fn, inheritedFrom }, idx) => (
38
+ <WriteOnlyFunctionForm
39
+ abi={deployedContractData.abi as Abi}
40
+ key={`${fn.name}-${idx}}`}
41
+ abiFunction={fn}
42
+ onChange={onChange}
43
+ contractAddress={deployedContractData.address}
44
+ inheritedFrom={inheritedFrom}
45
+ />
46
+ ))}
47
+ </>
48
+ );
49
+ };
@@ -0,0 +1,85 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import { InheritanceTooltip } from "./InheritanceTooltip";
5
+ import { displayTxResult } from "./utilsDisplay";
6
+ import { Abi, AbiFunction } from "abitype";
7
+ import { Address } from "viem";
8
+ import { useReadContract } from "wagmi";
9
+ import { ArrowPathIcon } from "@heroicons/react/24/outline";
10
+ import { useAnimationConfig } from "~~/hooks/scaffold-eth";
11
+ import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
12
+ import { getParsedError, notification } from "~~/utils/scaffold-eth";
13
+
14
+ type DisplayVariableProps = {
15
+ contractAddress: Address;
16
+ abiFunction: AbiFunction;
17
+ refreshDisplayVariables: boolean;
18
+ inheritedFrom?: string;
19
+ abi: Abi;
20
+ };
21
+
22
+ export const DisplayVariable = ({
23
+ contractAddress,
24
+ abiFunction,
25
+ refreshDisplayVariables,
26
+ abi,
27
+ inheritedFrom,
28
+ }: DisplayVariableProps) => {
29
+ const { targetNetwork } = useTargetNetwork();
30
+
31
+ const {
32
+ data: result,
33
+ isFetching,
34
+ refetch,
35
+ error,
36
+ } = useReadContract({
37
+ address: contractAddress,
38
+ functionName: abiFunction.name,
39
+ abi: abi,
40
+ chainId: targetNetwork.id,
41
+ query: {
42
+ retry: false,
43
+ },
44
+ });
45
+
46
+ const { showAnimation } = useAnimationConfig(result);
47
+
48
+ useEffect(() => {
49
+ refetch();
50
+ }, [refetch, refreshDisplayVariables]);
51
+
52
+ useEffect(() => {
53
+ if (error) {
54
+ const parsedError = getParsedError(error);
55
+ notification.error(parsedError);
56
+ }
57
+ }, [error]);
58
+
59
+ return (
60
+ <div className="space-y-1 pb-2">
61
+ <div className="flex items-center">
62
+ <h3 className="font-medium text-lg mb-0 break-all">{abiFunction.name}</h3>
63
+ <button className="btn btn-ghost btn-xs" onClick={async () => await refetch()}>
64
+ {isFetching ? (
65
+ <span className="loading loading-spinner loading-xs"></span>
66
+ ) : (
67
+ <ArrowPathIcon className="h-3 w-3 cursor-pointer" aria-hidden="true" />
68
+ )}
69
+ </button>
70
+ <InheritanceTooltip inheritedFrom={inheritedFrom} />
71
+ </div>
72
+ <div className="font-medium flex flex-col items-start">
73
+ <div>
74
+ <div
75
+ className={`break-all block transition bg-transparent ${
76
+ showAnimation ? "bg-warning rounded-sm animate-pulse-fast" : ""
77
+ }`}
78
+ >
79
+ {displayTxResult(result)}
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ );
85
+ };
@@ -0,0 +1,14 @@
1
+ import { InformationCircleIcon } from "@heroicons/react/20/solid";
2
+
3
+ export const InheritanceTooltip = ({ inheritedFrom }: { inheritedFrom?: string }) => (
4
+ <>
5
+ {inheritedFrom && (
6
+ <span
7
+ className="tooltip tooltip-top tooltip-accent px-2 md:break-normal"
8
+ data-tip={`Inherited from: ${inheritedFrom}`}
9
+ >
10
+ <InformationCircleIcon className="h-4 w-4" aria-hidden="true" />
11
+ </span>
12
+ )}
13
+ </>
14
+ );
@@ -0,0 +1,102 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import { InheritanceTooltip } from "./InheritanceTooltip";
5
+ import { Abi, AbiFunction } from "abitype";
6
+ import { Address } from "viem";
7
+ import { useReadContract } from "wagmi";
8
+ import {
9
+ ContractInput,
10
+ displayTxResult,
11
+ getFunctionInputKey,
12
+ getInitialFormState,
13
+ getParsedContractFunctionArgs,
14
+ transformAbiFunction,
15
+ } from "~~/app/debug/_components/contract";
16
+ import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
17
+ import { getParsedError, notification } from "~~/utils/scaffold-eth";
18
+
19
+ type ReadOnlyFunctionFormProps = {
20
+ contractAddress: Address;
21
+ abiFunction: AbiFunction;
22
+ inheritedFrom?: string;
23
+ abi: Abi;
24
+ };
25
+
26
+ export const ReadOnlyFunctionForm = ({
27
+ contractAddress,
28
+ abiFunction,
29
+ inheritedFrom,
30
+ abi,
31
+ }: ReadOnlyFunctionFormProps) => {
32
+ const [form, setForm] = useState<Record<string, any>>(() => getInitialFormState(abiFunction));
33
+ const [result, setResult] = useState<unknown>();
34
+ const { targetNetwork } = useTargetNetwork();
35
+
36
+ const { isFetching, refetch, error } = useReadContract({
37
+ address: contractAddress,
38
+ functionName: abiFunction.name,
39
+ abi: abi,
40
+ args: getParsedContractFunctionArgs(form),
41
+ chainId: targetNetwork.id,
42
+ query: {
43
+ enabled: false,
44
+ retry: false,
45
+ },
46
+ });
47
+
48
+ useEffect(() => {
49
+ if (error) {
50
+ const parsedError = getParsedError(error);
51
+ notification.error(parsedError);
52
+ }
53
+ }, [error]);
54
+
55
+ const transformedFunction = transformAbiFunction(abiFunction);
56
+ const inputElements = transformedFunction.inputs.map((input, inputIndex) => {
57
+ const key = getFunctionInputKey(abiFunction.name, input, inputIndex);
58
+ return (
59
+ <ContractInput
60
+ key={key}
61
+ setForm={updatedFormValue => {
62
+ setResult(undefined);
63
+ setForm(updatedFormValue);
64
+ }}
65
+ form={form}
66
+ stateObjectKey={key}
67
+ paramType={input}
68
+ />
69
+ );
70
+ });
71
+
72
+ return (
73
+ <div className="flex flex-col gap-3 py-5 first:pt-0 last:pb-1">
74
+ <p className="font-medium my-0 break-words">
75
+ {abiFunction.name}
76
+ <InheritanceTooltip inheritedFrom={inheritedFrom} />
77
+ </p>
78
+ {inputElements}
79
+ <div className="flex flex-col md:flex-row justify-between gap-2 flex-wrap">
80
+ <div className="grow w-full md:max-w-[80%]">
81
+ {result !== null && result !== undefined && (
82
+ <div className="bg-secondary rounded-3xl text-sm px-4 py-1.5 break-words overflow-auto">
83
+ <p className="font-bold m-0 mb-1">Result:</p>
84
+ <pre className="whitespace-pre-wrap break-words">{displayTxResult(result, "sm")}</pre>
85
+ </div>
86
+ )}
87
+ </div>
88
+ <button
89
+ className="btn btn-secondary btn-sm self-end md:self-start"
90
+ onClick={async () => {
91
+ const { data } = await refetch();
92
+ setResult(data);
93
+ }}
94
+ disabled={isFetching}
95
+ >
96
+ {isFetching && <span className="loading loading-spinner loading-xs"></span>}
97
+ Read 📡
98
+ </button>
99
+ </div>
100
+ </div>
101
+ );
102
+ };
@@ -0,0 +1,44 @@
1
+ import { Dispatch, SetStateAction, useEffect, useState } from "react";
2
+ import { ContractInput } from "./ContractInput";
3
+ import { getFunctionInputKey, getInitialTupleFormState } from "./utilsContract";
4
+ import { replacer } from "~~/utils/scaffold-eth/common";
5
+ import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";
6
+
7
+ type TupleProps = {
8
+ abiTupleParameter: AbiParameterTuple;
9
+ setParentForm: Dispatch<SetStateAction<Record<string, any>>>;
10
+ parentStateObjectKey: string;
11
+ parentForm: Record<string, any> | undefined;
12
+ };
13
+
14
+ export const Tuple = ({ abiTupleParameter, setParentForm, parentStateObjectKey }: TupleProps) => {
15
+ const [form, setForm] = useState<Record<string, any>>(() => getInitialTupleFormState(abiTupleParameter));
16
+
17
+ useEffect(() => {
18
+ const values = Object.values(form);
19
+ const argsStruct: Record<string, any> = {};
20
+ abiTupleParameter.components.forEach((component, componentIndex) => {
21
+ argsStruct[component.name || `input_${componentIndex}_`] = values[componentIndex];
22
+ });
23
+
24
+ setParentForm(parentForm => ({ ...parentForm, [parentStateObjectKey]: JSON.stringify(argsStruct, replacer) }));
25
+ // eslint-disable-next-line react-hooks/exhaustive-deps
26
+ }, [JSON.stringify(form, replacer)]);
27
+
28
+ return (
29
+ <div>
30
+ <div tabIndex={0} className="collapse collapse-arrow bg-base-200 pl-4 py-1.5 border-2 border-secondary">
31
+ <input type="checkbox" className="min-h-fit! peer" />
32
+ <div className="collapse-title after:top-3.5! p-0 min-h-fit! peer-checked:mb-2 text-primary-content/50">
33
+ <p className="m-0 p-0 text-[1rem]">{abiTupleParameter.internalType}</p>
34
+ </div>
35
+ <div className="ml-3 flex-col space-y-4 border-secondary/80 border-l-2 pl-4 collapse-content">
36
+ {abiTupleParameter?.components?.map((param, index) => {
37
+ const key = getFunctionInputKey(abiTupleParameter.name || "tuple", param, index);
38
+ return <ContractInput setForm={setForm} form={form} key={key} stateObjectKey={key} paramType={param} />;
39
+ })}
40
+ </div>
41
+ </div>
42
+ </div>
43
+ );
44
+ };
@@ -0,0 +1,142 @@
1
+ import { Dispatch, SetStateAction, useEffect, useState } from "react";
2
+ import { ContractInput } from "./ContractInput";
3
+ import { getFunctionInputKey, getInitialTupleArrayFormState } from "./utilsContract";
4
+ import { replacer } from "~~/utils/scaffold-eth/common";
5
+ import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";
6
+
7
+ type TupleArrayProps = {
8
+ abiTupleParameter: AbiParameterTuple & { isVirtual?: true };
9
+ setParentForm: Dispatch<SetStateAction<Record<string, any>>>;
10
+ parentStateObjectKey: string;
11
+ parentForm: Record<string, any> | undefined;
12
+ };
13
+
14
+ export const TupleArray = ({ abiTupleParameter, setParentForm, parentStateObjectKey }: TupleArrayProps) => {
15
+ const [form, setForm] = useState<Record<string, any>>(() => getInitialTupleArrayFormState(abiTupleParameter));
16
+ const [additionalInputs, setAdditionalInputs] = useState<Array<typeof abiTupleParameter.components>>([
17
+ abiTupleParameter.components,
18
+ ]);
19
+
20
+ const depth = (abiTupleParameter.type.match(/\[\]/g) || []).length;
21
+
22
+ useEffect(() => {
23
+ // Extract and group fields based on index prefix
24
+ const groupedFields = Object.keys(form).reduce(
25
+ (acc, key) => {
26
+ const [indexPrefix, ...restArray] = key.split("_");
27
+ const componentName = restArray.join("_");
28
+ if (!acc[indexPrefix]) {
29
+ acc[indexPrefix] = {};
30
+ }
31
+ acc[indexPrefix][componentName] = form[key];
32
+ return acc;
33
+ },
34
+ {} as Record<string, Record<string, any>>,
35
+ );
36
+
37
+ let argsArray: Array<Record<string, any>> = [];
38
+
39
+ Object.keys(groupedFields).forEach(key => {
40
+ const currentKeyValues = Object.values(groupedFields[key]);
41
+
42
+ const argsStruct: Record<string, any> = {};
43
+ abiTupleParameter.components.forEach((component, componentIndex) => {
44
+ argsStruct[component.name || `input_${componentIndex}_`] = currentKeyValues[componentIndex];
45
+ });
46
+
47
+ argsArray.push(argsStruct);
48
+ });
49
+
50
+ if (depth > 1) {
51
+ argsArray = argsArray.map(args => {
52
+ return args[abiTupleParameter.components[0].name || "tuple"];
53
+ });
54
+ }
55
+
56
+ setParentForm(parentForm => {
57
+ return { ...parentForm, [parentStateObjectKey]: JSON.stringify(argsArray, replacer) };
58
+ });
59
+ // eslint-disable-next-line react-hooks/exhaustive-deps
60
+ }, [JSON.stringify(form, replacer)]);
61
+
62
+ const addInput = () => {
63
+ setAdditionalInputs(previousValue => {
64
+ const newAdditionalInputs = [...previousValue, abiTupleParameter.components];
65
+
66
+ // Add the new inputs to the form
67
+ setForm(form => {
68
+ const newForm = { ...form };
69
+ abiTupleParameter.components.forEach((component, componentIndex) => {
70
+ const key = getFunctionInputKey(
71
+ `${newAdditionalInputs.length - 1}_${abiTupleParameter.name || "tuple"}`,
72
+ component,
73
+ componentIndex,
74
+ );
75
+ newForm[key] = "";
76
+ });
77
+ return newForm;
78
+ });
79
+
80
+ return newAdditionalInputs;
81
+ });
82
+ };
83
+
84
+ const removeInput = () => {
85
+ // Remove the last inputs from the form
86
+ setForm(form => {
87
+ const newForm = { ...form };
88
+ abiTupleParameter.components.forEach((component, componentIndex) => {
89
+ const key = getFunctionInputKey(
90
+ `${additionalInputs.length - 1}_${abiTupleParameter.name || "tuple"}`,
91
+ component,
92
+ componentIndex,
93
+ );
94
+ delete newForm[key];
95
+ });
96
+ return newForm;
97
+ });
98
+ setAdditionalInputs(inputs => inputs.slice(0, -1));
99
+ };
100
+
101
+ return (
102
+ <div>
103
+ <div className="collapse collapse-arrow bg-base-200 pl-4 py-1.5 border-2 border-secondary">
104
+ <input type="checkbox" className="min-h-fit! peer" />
105
+ <div className="collapse-title after:top-3.5! p-0 min-h-fit! peer-checked:mb-1 text-primary-content/50">
106
+ <p className="m-0 text-[1rem]">{abiTupleParameter.internalType}</p>
107
+ </div>
108
+ <div className="ml-3 flex-col space-y-2 border-secondary/70 border-l-2 pl-4 collapse-content">
109
+ {additionalInputs.map((additionalInput, additionalIndex) => (
110
+ <div key={additionalIndex} className="space-y-1">
111
+ <span className="badge bg-base-300 badge-sm">
112
+ {depth > 1 ? `${additionalIndex}` : `tuple[${additionalIndex}]`}
113
+ </span>
114
+ <div className="space-y-4">
115
+ {additionalInput.map((param, index) => {
116
+ const key = getFunctionInputKey(
117
+ `${additionalIndex}_${abiTupleParameter.name || "tuple"}`,
118
+ param,
119
+ index,
120
+ );
121
+ return (
122
+ <ContractInput setForm={setForm} form={form} key={key} stateObjectKey={key} paramType={param} />
123
+ );
124
+ })}
125
+ </div>
126
+ </div>
127
+ ))}
128
+ <div className="flex space-x-2">
129
+ <button className="btn btn-sm btn-secondary" onClick={addInput}>
130
+ +
131
+ </button>
132
+ {additionalInputs.length > 0 && (
133
+ <button className="btn btn-sm btn-secondary" onClick={removeInput}>
134
+ -
135
+ </button>
136
+ )}
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ );
142
+ };