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,42 @@
1
+ import { TransactionReceipt } from "viem";
2
+ import { CheckCircleIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline";
3
+ import { ObjectFieldDisplay } from "~~/app/debug/_components/contract";
4
+ import { useCopyToClipboard } from "~~/hooks/scaffold-eth/useCopyToClipboard";
5
+ import { replacer } from "~~/utils/scaffold-eth/common";
6
+
7
+ export const TxReceipt = ({ txResult }: { txResult: TransactionReceipt }) => {
8
+ const { copyToClipboard: copyTxResultToClipboard, isCopiedToClipboard: isTxResultCopiedToClipboard } =
9
+ useCopyToClipboard();
10
+
11
+ return (
12
+ <div className="flex text-sm rounded-3xl peer-checked:rounded-b-none min-h-0 bg-secondary py-0">
13
+ <div className="mt-1 pl-2">
14
+ {isTxResultCopiedToClipboard ? (
15
+ <CheckCircleIcon
16
+ className="ml-1.5 text-xl font-normal text-base-content h-5 w-5 cursor-pointer"
17
+ aria-hidden="true"
18
+ />
19
+ ) : (
20
+ <DocumentDuplicateIcon
21
+ className="ml-1.5 text-xl font-normal h-5 w-5 cursor-pointer"
22
+ aria-hidden="true"
23
+ onClick={() => copyTxResultToClipboard(JSON.stringify(txResult, replacer, 2))}
24
+ />
25
+ )}
26
+ </div>
27
+ <div tabIndex={0} className="flex-wrap collapse collapse-arrow">
28
+ <input type="checkbox" className="min-h-0! peer" />
29
+ <div className="collapse-title text-sm min-h-0! py-1.5 pl-1 after:top-4!">
30
+ <strong>Transaction Receipt</strong>
31
+ </div>
32
+ <div className="collapse-content overflow-auto bg-secondary rounded-t-none rounded-3xl pl-0!">
33
+ <pre className="text-xs">
34
+ {Object.entries(txResult).map(([k, v]) => (
35
+ <ObjectFieldDisplay name={k} value={v} size="xs" leftPad={false} key={k} />
36
+ ))}
37
+ </pre>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ );
42
+ };
@@ -0,0 +1,144 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import { InheritanceTooltip } from "./InheritanceTooltip";
5
+ import { Abi, AbiFunction } from "abitype";
6
+ import { Address, TransactionReceipt } from "viem";
7
+ import { useAccount, useConfig, useWaitForTransactionReceipt, useWriteContract } from "wagmi";
8
+ import {
9
+ ContractInput,
10
+ TxReceipt,
11
+ getFunctionInputKey,
12
+ getInitialFormState,
13
+ getParsedContractFunctionArgs,
14
+ transformAbiFunction,
15
+ } from "~~/app/debug/_components/contract";
16
+ import { IntegerInput } from "~~/components/scaffold-eth";
17
+ import { useTransactor } from "~~/hooks/scaffold-eth";
18
+ import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
19
+ import { simulateContractWriteAndNotifyError } from "~~/utils/scaffold-eth/contract";
20
+
21
+ type WriteOnlyFunctionFormProps = {
22
+ abi: Abi;
23
+ abiFunction: AbiFunction;
24
+ onChange: () => void;
25
+ contractAddress: Address;
26
+ inheritedFrom?: string;
27
+ };
28
+
29
+ export const WriteOnlyFunctionForm = ({
30
+ abi,
31
+ abiFunction,
32
+ onChange,
33
+ contractAddress,
34
+ inheritedFrom,
35
+ }: WriteOnlyFunctionFormProps) => {
36
+ const [form, setForm] = useState<Record<string, any>>(() => getInitialFormState(abiFunction));
37
+ const [txValue, setTxValue] = useState<string>("");
38
+ const { chain } = useAccount();
39
+ const writeTxn = useTransactor();
40
+ const { targetNetwork } = useTargetNetwork();
41
+ const writeDisabled = !chain || chain?.id !== targetNetwork.id;
42
+
43
+ const { data: result, isPending, writeContractAsync } = useWriteContract();
44
+
45
+ const wagmiConfig = useConfig();
46
+
47
+ const handleWrite = async () => {
48
+ if (writeContractAsync) {
49
+ try {
50
+ const writeContractObj = {
51
+ address: contractAddress,
52
+ functionName: abiFunction.name,
53
+ abi: abi,
54
+ args: getParsedContractFunctionArgs(form),
55
+ value: BigInt(txValue),
56
+ };
57
+ await simulateContractWriteAndNotifyError({ wagmiConfig, writeContractParams: writeContractObj });
58
+
59
+ const makeWriteWithParams = () => writeContractAsync(writeContractObj);
60
+ await writeTxn(makeWriteWithParams);
61
+ onChange();
62
+ } catch (e: any) {
63
+ console.error("⚡️ ~ file: WriteOnlyFunctionForm.tsx:handleWrite ~ error", e);
64
+ }
65
+ }
66
+ };
67
+
68
+ const [displayedTxResult, setDisplayedTxResult] = useState<TransactionReceipt>();
69
+ const { data: txResult } = useWaitForTransactionReceipt({
70
+ hash: result,
71
+ });
72
+ useEffect(() => {
73
+ setDisplayedTxResult(txResult);
74
+ }, [txResult]);
75
+
76
+ // TODO use `useMemo` to optimize also update in ReadOnlyFunctionForm
77
+ const transformedFunction = transformAbiFunction(abiFunction);
78
+ const inputs = transformedFunction.inputs.map((input, inputIndex) => {
79
+ const key = getFunctionInputKey(abiFunction.name, input, inputIndex);
80
+ return (
81
+ <ContractInput
82
+ key={key}
83
+ setForm={updatedFormValue => {
84
+ setDisplayedTxResult(undefined);
85
+ setForm(updatedFormValue);
86
+ }}
87
+ form={form}
88
+ stateObjectKey={key}
89
+ paramType={input}
90
+ />
91
+ );
92
+ });
93
+ const zeroInputs = inputs.length === 0 && abiFunction.stateMutability !== "payable";
94
+
95
+ return (
96
+ <div className="py-5 space-y-3 first:pt-0 last:pb-1">
97
+ <div className={`flex gap-3 ${zeroInputs ? "flex-row justify-between items-center" : "flex-col"}`}>
98
+ <p className="font-medium my-0 break-words">
99
+ {abiFunction.name}
100
+ <InheritanceTooltip inheritedFrom={inheritedFrom} />
101
+ </p>
102
+ {inputs}
103
+ {abiFunction.stateMutability === "payable" ? (
104
+ <div className="flex flex-col gap-1.5 w-full">
105
+ <div className="flex items-center ml-2">
106
+ <span className="text-xs font-medium mr-2 leading-none">payable value</span>
107
+ <span className="block text-xs font-extralight leading-none">wei</span>
108
+ </div>
109
+ <IntegerInput
110
+ value={txValue}
111
+ onChange={updatedTxValue => {
112
+ setDisplayedTxResult(undefined);
113
+ setTxValue(updatedTxValue);
114
+ }}
115
+ placeholder="value (wei)"
116
+ />
117
+ </div>
118
+ ) : null}
119
+ <div className="flex justify-between gap-2">
120
+ {!zeroInputs && (
121
+ <div className="grow basis-0">{displayedTxResult ? <TxReceipt txResult={displayedTxResult} /> : null}</div>
122
+ )}
123
+ <div
124
+ className={`flex ${
125
+ writeDisabled &&
126
+ "tooltip tooltip-bottom tooltip-secondary before:content-[attr(data-tip)] before:-translate-x-1/3 before:left-auto before:transform-none"
127
+ }`}
128
+ data-tip={`${writeDisabled && "Wallet not connected or in the wrong network"}`}
129
+ >
130
+ <button className="btn btn-secondary btn-sm" disabled={writeDisabled || isPending} onClick={handleWrite}>
131
+ {isPending && <span className="loading loading-spinner loading-xs"></span>}
132
+ Send 💸
133
+ </button>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ {zeroInputs && txResult ? (
138
+ <div className="grow basis-0">
139
+ <TxReceipt txResult={txResult} />
140
+ </div>
141
+ ) : null}
142
+ </div>
143
+ );
144
+ };
@@ -0,0 +1,8 @@
1
+ export * from "./ContractInput";
2
+ export * from "./ContractUI";
3
+ export * from "./DisplayVariable";
4
+ export * from "./ReadOnlyFunctionForm";
5
+ export * from "./TxReceipt";
6
+ export * from "./utilsContract";
7
+ export * from "./utilsDisplay";
8
+ export * from "./WriteOnlyFunctionForm";
@@ -0,0 +1,166 @@
1
+ import { AbiFunction, AbiParameter } from "abitype";
2
+ import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";
3
+
4
+ /**
5
+ * Generates a key based on function metadata
6
+ */
7
+ const getFunctionInputKey = (functionName: string, input: AbiParameter, inputIndex: number): string => {
8
+ const name = input?.name || `input_${inputIndex}_`;
9
+ return functionName + "_" + name + "_" + input.internalType + "_" + input.type;
10
+ };
11
+
12
+ const isJsonString = (str: string) => {
13
+ try {
14
+ JSON.parse(str);
15
+ return true;
16
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
+ } catch (e) {
18
+ return false;
19
+ }
20
+ };
21
+
22
+ const isBigInt = (str: string) => {
23
+ if (str.trim().length === 0 || str.startsWith("0")) return false;
24
+ try {
25
+ BigInt(str);
26
+ return true;
27
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
28
+ } catch (e) {
29
+ return false;
30
+ }
31
+ };
32
+
33
+ // Recursive function to deeply parse JSON strings, correctly handling nested arrays and encoded JSON strings
34
+ const deepParseValues = (value: any): any => {
35
+ if (typeof value === "string") {
36
+ // first try with bigInt because we losse precision with JSON.parse
37
+ if (isBigInt(value)) {
38
+ return BigInt(value);
39
+ }
40
+
41
+ if (isJsonString(value)) {
42
+ const parsed = JSON.parse(value);
43
+ return deepParseValues(parsed);
44
+ }
45
+
46
+ // It's a string but not a JSON string, return as is
47
+ return value;
48
+ } else if (Array.isArray(value)) {
49
+ // If it's an array, recursively parse each element
50
+ return value.map(element => deepParseValues(element));
51
+ } else if (typeof value === "object" && value !== null) {
52
+ // If it's an object, recursively parse each value
53
+ return Object.entries(value).reduce((acc: any, [key, val]) => {
54
+ acc[key] = deepParseValues(val);
55
+ return acc;
56
+ }, {});
57
+ }
58
+
59
+ // Handle boolean values represented as strings
60
+ if (value === "true" || value === "1" || value === "0x1" || value === "0x01" || value === "0x0001") {
61
+ return true;
62
+ } else if (value === "false" || value === "0" || value === "0x0" || value === "0x00" || value === "0x0000") {
63
+ return false;
64
+ }
65
+
66
+ return value;
67
+ };
68
+
69
+ /**
70
+ * parses form input with array support
71
+ */
72
+ const getParsedContractFunctionArgs = (form: Record<string, any>) => {
73
+ return Object.keys(form).map(key => {
74
+ const valueOfArg = form[key];
75
+
76
+ // Attempt to deeply parse JSON strings
77
+ return deepParseValues(valueOfArg);
78
+ });
79
+ };
80
+
81
+ const getInitialFormState = (abiFunction: AbiFunction) => {
82
+ const initialForm: Record<string, any> = {};
83
+ if (!abiFunction.inputs) return initialForm;
84
+ abiFunction.inputs.forEach((input, inputIndex) => {
85
+ const key = getFunctionInputKey(abiFunction.name, input, inputIndex);
86
+ initialForm[key] = "";
87
+ });
88
+ return initialForm;
89
+ };
90
+
91
+ const getInitialTupleFormState = (abiTupleParameter: AbiParameterTuple) => {
92
+ const initialForm: Record<string, any> = {};
93
+ if (abiTupleParameter.components.length === 0) return initialForm;
94
+
95
+ abiTupleParameter.components.forEach((component, componentIndex) => {
96
+ const key = getFunctionInputKey(abiTupleParameter.name || "tuple", component, componentIndex);
97
+ initialForm[key] = "";
98
+ });
99
+ return initialForm;
100
+ };
101
+
102
+ const getInitialTupleArrayFormState = (abiTupleParameter: AbiParameterTuple) => {
103
+ const initialForm: Record<string, any> = {};
104
+ if (abiTupleParameter.components.length === 0) return initialForm;
105
+ abiTupleParameter.components.forEach((component, componentIndex) => {
106
+ const key = getFunctionInputKey("0_" + abiTupleParameter.name || "tuple", component, componentIndex);
107
+ initialForm[key] = "";
108
+ });
109
+ return initialForm;
110
+ };
111
+
112
+ const adjustInput = (input: AbiParameterTuple): AbiParameter => {
113
+ if (input.type.startsWith("tuple[")) {
114
+ const depth = (input.type.match(/\[\]/g) || []).length;
115
+ return {
116
+ ...input,
117
+ components: transformComponents(input.components, depth, {
118
+ internalType: input.internalType || "struct",
119
+ name: input.name,
120
+ }),
121
+ };
122
+ } else if (input.components) {
123
+ return {
124
+ ...input,
125
+ components: input.components.map(value => adjustInput(value as AbiParameterTuple)),
126
+ };
127
+ }
128
+ return input;
129
+ };
130
+
131
+ const transformComponents = (
132
+ components: readonly AbiParameter[],
133
+ depth: number,
134
+ parentComponentData: { internalType?: string; name?: string },
135
+ ): AbiParameter[] => {
136
+ // Base case: if depth is 1 or no components, return the original components
137
+ if (depth === 1 || !components) {
138
+ return [...components];
139
+ }
140
+
141
+ // Recursive case: wrap components in an additional tuple layer
142
+ const wrappedComponents: AbiParameter = {
143
+ internalType: `${parentComponentData.internalType || "struct"}`.replace(/\[\]/g, "") + "[]".repeat(depth - 1),
144
+ name: `${parentComponentData.name || "tuple"}`,
145
+ type: `tuple${"[]".repeat(depth - 1)}`,
146
+ components: transformComponents(components, depth - 1, parentComponentData),
147
+ };
148
+
149
+ return [wrappedComponents];
150
+ };
151
+
152
+ const transformAbiFunction = (abiFunction: AbiFunction): AbiFunction => {
153
+ return {
154
+ ...abiFunction,
155
+ inputs: abiFunction.inputs.map(value => adjustInput(value as AbiParameterTuple)),
156
+ };
157
+ };
158
+
159
+ export {
160
+ getFunctionInputKey,
161
+ getInitialFormState,
162
+ getParsedContractFunctionArgs,
163
+ getInitialTupleFormState,
164
+ getInitialTupleArrayFormState,
165
+ transformAbiFunction,
166
+ };
@@ -0,0 +1,114 @@
1
+ import { ReactElement, useState } from "react";
2
+ import { TransactionBase, TransactionReceipt, formatEther, isAddress, isHex } from "viem";
3
+ import { ArrowsRightLeftIcon } from "@heroicons/react/24/solid";
4
+ import { Address } from "~~/components/scaffold-eth";
5
+ import { replacer } from "~~/utils/scaffold-eth/common";
6
+
7
+ type DisplayContent =
8
+ | string
9
+ | number
10
+ | bigint
11
+ | Record<string, any>
12
+ | TransactionBase
13
+ | TransactionReceipt
14
+ | undefined
15
+ | unknown;
16
+
17
+ type ResultFontSize = "sm" | "base" | "xs" | "lg" | "xl" | "2xl" | "3xl";
18
+
19
+ export const displayTxResult = (
20
+ displayContent: DisplayContent | DisplayContent[],
21
+ fontSize: ResultFontSize = "base",
22
+ ): string | ReactElement | number => {
23
+ if (displayContent == null) {
24
+ return "";
25
+ }
26
+
27
+ if (typeof displayContent === "bigint") {
28
+ return <NumberDisplay value={displayContent} />;
29
+ }
30
+
31
+ if (typeof displayContent === "string") {
32
+ if (isAddress(displayContent)) {
33
+ return <Address address={displayContent} size={fontSize} onlyEnsOrAddress />;
34
+ }
35
+
36
+ if (isHex(displayContent)) {
37
+ return displayContent; // don't add quotes
38
+ }
39
+ }
40
+
41
+ if (Array.isArray(displayContent)) {
42
+ return <ArrayDisplay values={displayContent} size={fontSize} />;
43
+ }
44
+
45
+ if (typeof displayContent === "object") {
46
+ return <StructDisplay struct={displayContent} size={fontSize} />;
47
+ }
48
+
49
+ return JSON.stringify(displayContent, replacer, 2);
50
+ };
51
+
52
+ const NumberDisplay = ({ value }: { value: bigint }) => {
53
+ const [isEther, setIsEther] = useState(false);
54
+
55
+ const asNumber = Number(value);
56
+ if (asNumber <= Number.MAX_SAFE_INTEGER && asNumber >= Number.MIN_SAFE_INTEGER) {
57
+ return String(value);
58
+ }
59
+
60
+ return (
61
+ <div className="flex items-baseline">
62
+ {isEther ? "Ξ" + formatEther(value) : String(value)}
63
+ <span
64
+ className="tooltip tooltip-secondary font-sans ml-2"
65
+ data-tip={isEther ? "Multiply by 1e18" : "Divide by 1e18"}
66
+ >
67
+ <button className="btn btn-ghost btn-circle btn-xs" onClick={() => setIsEther(!isEther)}>
68
+ <ArrowsRightLeftIcon className="h-3 w-3 opacity-65" />
69
+ </button>
70
+ </span>
71
+ </div>
72
+ );
73
+ };
74
+
75
+ export const ObjectFieldDisplay = ({
76
+ name,
77
+ value,
78
+ size,
79
+ leftPad = true,
80
+ }: {
81
+ name: string;
82
+ value: DisplayContent;
83
+ size: ResultFontSize;
84
+ leftPad?: boolean;
85
+ }) => {
86
+ return (
87
+ <div className={`flex flex-row items-baseline ${leftPad ? "ml-4" : ""}`}>
88
+ <span className="text-base-content/60 mr-2">{name}:</span>
89
+ <span className="text-base-content">{displayTxResult(value, size)}</span>
90
+ </div>
91
+ );
92
+ };
93
+
94
+ const ArrayDisplay = ({ values, size }: { values: DisplayContent[]; size: ResultFontSize }) => {
95
+ return (
96
+ <div className="flex flex-col gap-y-1">
97
+ {values.length ? "array" : "[]"}
98
+ {values.map((v, i) => (
99
+ <ObjectFieldDisplay key={i} name={`[${i}]`} value={v} size={size} />
100
+ ))}
101
+ </div>
102
+ );
103
+ };
104
+
105
+ const StructDisplay = ({ struct, size }: { struct: Record<string, any>; size: ResultFontSize }) => {
106
+ return (
107
+ <div className="flex flex-col gap-y-1">
108
+ struct
109
+ {Object.entries(struct).map(([k, v]) => (
110
+ <ObjectFieldDisplay key={k} name={k} value={v} size={size} />
111
+ ))}
112
+ </div>
113
+ );
114
+ };
@@ -0,0 +1,14 @@
1
+ import { DebugContracts } from "./_components/DebugContracts";
2
+ import type { NextPage } from "next";
3
+ import { getMetadata } from "~~/utils/scaffold-eth/getMetadata";
4
+
5
+ export const metadata = getMetadata({
6
+ title: "Debug Contracts",
7
+ description: "Debug your deployed 🏗 Scaffold-Stylus contracts in an easy way",
8
+ });
9
+
10
+ const Debug: NextPage = () => {
11
+ return <DebugContracts />;
12
+ };
13
+
14
+ export default Debug;
@@ -0,0 +1,67 @@
1
+ import { DM_Sans } from "next/font/google";
2
+ import "@rainbow-me/rainbowkit/styles.css";
3
+ import { Metadata } from "next";
4
+ import { ScaffoldEthAppWithProviders } from "~~/components/ScaffoldEthAppWithProviders";
5
+ import { ThemeProvider } from "~~/components/ThemeProvider";
6
+ import "~~/styles/globals.css";
7
+
8
+ const dmSans = DM_Sans({
9
+ subsets: ["latin"],
10
+ variable: "--font-dm-sans",
11
+ });
12
+
13
+ const baseUrl = process.env.VERCEL_URL
14
+ ? `https://${process.env.VERCEL_URL}`
15
+ : `http://localhost:${process.env.PORT || 3000}`;
16
+ const imageUrl = `${baseUrl}/thumbnail.jpg`;
17
+
18
+ const title = "Create Stylus Dapp";
19
+ const titleTemplate = "%s | Create Stylus Dapp";
20
+ const description = "Built with 🏗 Scaffold-Stylus";
21
+
22
+ export const metadata: Metadata = {
23
+ metadataBase: new URL(baseUrl),
24
+ title: {
25
+ default: title,
26
+ template: titleTemplate,
27
+ },
28
+ description,
29
+ openGraph: {
30
+ title: {
31
+ default: title,
32
+ template: titleTemplate,
33
+ },
34
+ description,
35
+ images: [
36
+ {
37
+ url: imageUrl,
38
+ },
39
+ ],
40
+ },
41
+ twitter: {
42
+ card: "summary_large_image",
43
+ images: [imageUrl],
44
+ title: {
45
+ default: title,
46
+ template: titleTemplate,
47
+ },
48
+ description,
49
+ },
50
+ icons: {
51
+ icon: [{ url: "/favicon.png", sizes: "32x32", type: "image/png" }],
52
+ },
53
+ };
54
+
55
+ const ScaffoldEthApp = ({ children }: { children: React.ReactNode }) => {
56
+ return (
57
+ <html suppressHydrationWarning>
58
+ <body className={`${dmSans.variable} font-sans`} suppressHydrationWarning>
59
+ <ThemeProvider>
60
+ <ScaffoldEthAppWithProviders>{children}</ScaffoldEthAppWithProviders>
61
+ </ThemeProvider>
62
+ </body>
63
+ </html>
64
+ );
65
+ };
66
+
67
+ export default ScaffoldEthApp;
@@ -0,0 +1,16 @@
1
+ import Link from "next/link";
2
+
3
+ export default function NotFound() {
4
+ return (
5
+ <div className="flex items-center h-full flex-1 justify-center bg-base-200">
6
+ <div className="text-center">
7
+ <h1 className="text-6xl font-bold m-0 mb-1">404</h1>
8
+ <h2 className="text-2xl font-semibold m-0">Page Not Found</h2>
9
+ <p className="text-base-content/70 m-0 mb-4">The page you&apos;re looking for doesn&apos;t exist.</p>
10
+ <Link href="/" className="btn btn-primary">
11
+ Go Home
12
+ </Link>
13
+ </div>
14
+ </div>
15
+ );
16
+ }
@@ -0,0 +1,94 @@
1
+ "use client";
2
+
3
+ import type { NextPage } from "next";
4
+ import { useTheme } from "next-themes";
5
+ import { useAccount } from "wagmi";
6
+ import { Card } from "~~/components/Card";
7
+ import { Address } from "~~/components/scaffold-eth";
8
+ import CompassIcon from "~~/icons/CompassIcon";
9
+ import DarkBugAntIcon from "~~/icons/DarkBugAntIcon";
10
+ import LightBugAntIcon from "~~/icons/LightBugAntIcon";
11
+
12
+ const Home: NextPage = () => {
13
+ const { address: connectedAddress } = useAccount();
14
+ const { resolvedTheme } = useTheme();
15
+ const isDarkMode = resolvedTheme === "dark";
16
+
17
+ return (
18
+ <>
19
+ <div className="flex items-center flex-col justify-between flex-grow pt-10">
20
+ <div className="flex flex-col justify-center flex-grow">
21
+ <div className="px-5">
22
+ <h1 className="text-center">
23
+ <span className="block text-2xl mb-2">Welcome to</span>
24
+ <span className="block text-4xl font-bold">Scaffold-Stylus</span>
25
+ </h1>
26
+ <div className="flex justify-center items-center space-x-2 my-4">
27
+ <p className={`my-2 font-medium ${!isDarkMode ? "text-[#E3066E]" : ""}`}>Connected Address:</p>
28
+ <Address address={connectedAddress} />
29
+ </div>
30
+ <p className="text-center text-lg">
31
+ Get started by editing{" "}
32
+ <code
33
+ className="italic bg-base-300 text-black text-base font-bold max-w-full break-words break-all inline-block"
34
+ style={{
35
+ backgroundColor: isDarkMode ? "white" : "#F0F0F0",
36
+ }}
37
+ >
38
+ packages/nextjs/app/page.tsx
39
+ </code>
40
+ </p>
41
+ <p className="text-center text-lg">
42
+ Edit your smart contract{" "}
43
+ <code
44
+ className="italic bg-base-300 text-black text-base font-bold max-w-full break-words break-all inline-block"
45
+ style={{
46
+ backgroundColor: isDarkMode ? "white" : "#F0F0F0",
47
+ }}
48
+ >
49
+ lib.rs
50
+ </code>{" "}
51
+ in{" "}
52
+ <code
53
+ className="italic bg-base-300 text-black text-base font-bold max-w-full break-words break-all inline-block"
54
+ style={{
55
+ backgroundColor: isDarkMode ? "white" : "#F0F0F0",
56
+ }}
57
+ >
58
+ packages/stylus/your-contract/src
59
+ </code>
60
+ </p>
61
+ </div>
62
+ </div>
63
+
64
+ <div
65
+ className="h-auto sm:h-[306px] mb-3 w-full py-11"
66
+ style={{
67
+ backgroundColor: isDarkMode ? "#050505" : "white",
68
+ }}
69
+ >
70
+ <div className="flex justify-center items-center h-full gap-12 flex-col sm:flex-row">
71
+ {/* Debug Contracts Card */}
72
+ <Card
73
+ icon={isDarkMode ? <DarkBugAntIcon /> : <LightBugAntIcon />}
74
+ description={<>Tinker with your smart contract using the</>}
75
+ linkHref="/debug"
76
+ linkText="Debug Contracts"
77
+ isDarkMode={isDarkMode}
78
+ />
79
+ {/* Block Explorer Card */}
80
+ <Card
81
+ icon={<CompassIcon />}
82
+ description={<>Explore your local transactions with the</>}
83
+ linkHref="/blockexplorer"
84
+ linkText="Block Explorer"
85
+ isDarkMode={isDarkMode}
86
+ />
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </>
91
+ );
92
+ };
93
+
94
+ export default Home;