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,87 @@
1
+ import * as path from "path";
2
+ import * as fs from "fs";
3
+ import {
4
+ getExportConfig,
5
+ ensureDeploymentDirectory,
6
+ executeCommand,
7
+ generateTsAbi,
8
+ handleSolcError,
9
+ } from "./utils/";
10
+
11
+ export async function exportStylusAbi(
12
+ contractFolder: string,
13
+ contractName: string,
14
+ isScript: boolean = true,
15
+ chainId?: string,
16
+ ) {
17
+ console.log("šŸ“„ Starting Stylus ABI export...");
18
+
19
+ const config = getExportConfig(contractFolder, contractName, chainId);
20
+
21
+ if (!config.contractAddress) {
22
+ console.error(
23
+ `āŒ Contract address not found. Please deploy the contract first or ensure it is saved in a chain-specific deployment file in ${config.deploymentDir}`,
24
+ );
25
+ process.exit(1);
26
+ }
27
+
28
+ if (isScript) {
29
+ console.log(`šŸ“„ Contract name: ${config.contractName}`);
30
+ console.log(`šŸ“ Deployment directory: ${config.deploymentDir}`);
31
+ console.log(`šŸ“ Contract address: ${config.contractAddress}`);
32
+ console.log(`šŸ”— Chain ID: ${config.chainId}`);
33
+ }
34
+
35
+ try {
36
+ ensureDeploymentDirectory(config.deploymentDir);
37
+
38
+ // Export ABI
39
+ const exportCommand = `cargo stylus export-abi --output='../${config.deploymentDir}/${config.contractFolder}' --json`;
40
+ await executeCommand(exportCommand, contractFolder, "Exporting ABI");
41
+
42
+ console.log(
43
+ `šŸ“„ ABI file location: ${config.deploymentDir}/${config.contractFolder}`,
44
+ );
45
+
46
+ const abiFilePath = path.resolve(
47
+ config.deploymentDir,
48
+ `${config.contractFolder}`,
49
+ );
50
+ if (fs.existsSync(abiFilePath)) {
51
+ console.log(`āœ… ABI file verified at: ${abiFilePath}`);
52
+ } else {
53
+ console.warn(
54
+ `āš ļø ABI file not found at expected location: ${abiFilePath}`,
55
+ );
56
+ }
57
+
58
+ // do not Generate TypeScript ABI when called from yarn script
59
+ if (!isScript) {
60
+ await generateTsAbi(
61
+ abiFilePath,
62
+ config.contractName,
63
+ config.contractAddress,
64
+ config.txHash,
65
+ config.chainId,
66
+ );
67
+ }
68
+ } catch (error) {
69
+ handleSolcError(error as Error);
70
+ process.exit(1);
71
+ }
72
+ }
73
+
74
+ if (require.main === module) {
75
+ // Get contract folder from command line args, default to 'your-contract'
76
+ const contractFolder = process.argv[2] || "your-contract";
77
+ if (!fs.existsSync(contractFolder)) {
78
+ console.error(`āŒ Contract folder does not exist: ${contractFolder}`);
79
+ process.exit(1);
80
+ }
81
+ exportStylusAbi(contractFolder, contractFolder).catch(
82
+ (error) => {
83
+ console.error("Fatal error:", error);
84
+ process.exit(1);
85
+ },
86
+ );
87
+ }
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+
3
+ # Check if module name is provided
4
+ if [ -z "$1" ]; then
5
+ echo "Error: Module name is required"
6
+ echo "Usage: $0 <module_name>"
7
+ exit 1
8
+ fi
9
+
10
+ MODULE_NAME="$1"
11
+
12
+ CARGO_CMD="cargo stylus new \"$MODULE_NAME\""
13
+
14
+ echo "Creating new module: $MODULE_NAME"
15
+
16
+ if output=$(eval $CARGO_CMD 2>&1); then
17
+ cd "$MODULE_NAME"
18
+ # Remove unnecessary files
19
+ rm -rf .git .github ci .gitignore examples licenses .env.example header.png README.md
20
+ # Update Cargo.toml name field to $MODULE_NAME
21
+ if [ -f Cargo.toml ]; then
22
+ sed -i "s/^name = \".*\"/name = \"$MODULE_NAME\"/" Cargo.toml
23
+ fi
24
+ # Update main.rs module name in print_from_args call
25
+ if [ -f src/main.rs ]; then
26
+ MODULE_NAME_UNDERSCORE=$(echo "$MODULE_NAME" | tr '-' '_')
27
+ sed -i "s/^[[:space:]]*stylus_hello_world::print_from_args();/\t$MODULE_NAME_UNDERSCORE::print_from_args();/" src/main.rs
28
+ fi
29
+ cargo generate-lockfile
30
+ echo "New module created successfully"
31
+ else
32
+ echo "Error: Failed to create new module with '$CARGO_CMD'"
33
+ echo "$output"
34
+ exit 1
35
+ fi
@@ -0,0 +1,31 @@
1
+ import { getChain } from "./utils/";
2
+ import { SUPPORTED_NETWORKS } from "./utils/";
3
+
4
+ function testNetworkFunctionality() {
5
+ console.log("🧪 Testing network functionality...\n");
6
+
7
+ const testNetworks = [
8
+ ...Object.keys(SUPPORTED_NETWORKS),
9
+ "invalid-network",
10
+ ];
11
+
12
+ testNetworks.forEach(network => {
13
+ const chain = getChain(network);
14
+ if (chain) {
15
+ console.log(`āœ… ${network}: ${chain.rpcUrl}`);
16
+ } else {
17
+ console.log(`āŒ ${network}: Not found in viem chains`);
18
+ }
19
+ });
20
+
21
+ console.log("\nšŸ“ Usage examples:");
22
+ Object.keys(SUPPORTED_NETWORKS).forEach(network => {
23
+ const chain = getChain(network);
24
+ console.log(` yarn deploy --network ${chain?.name}\t# Deploy to ${chain?.name}`);
25
+ console.log(` yarn deploy --network ${chain?.alias}\t\t# Deploy to ${chain?.name} (alias)`);
26
+ });
27
+ }
28
+
29
+ if (require.main === module) {
30
+ testNetworkFunctionality();
31
+ }
@@ -0,0 +1,152 @@
1
+ import { spawn } from "child_process";
2
+ import { DeploymentConfig, DeployOptions } from "./type";
3
+ import { extractGasPriceFromOutput } from "./contract";
4
+
5
+ export async function buildDeployCommand(
6
+ config: DeploymentConfig,
7
+ deployOptions: DeployOptions,
8
+ ) {
9
+ let baseCommand = `cargo stylus deploy --endpoint='${config.chain?.rpcUrl}' --private-key='${config.privateKey}'`;
10
+
11
+ if (
12
+ deployOptions.constructorArgs &&
13
+ deployOptions.constructorArgs.length > 0
14
+ ) {
15
+ baseCommand += ` --constructor-args='${deployOptions.constructorArgs.join(" ")}'`;
16
+ }
17
+
18
+ if (deployOptions.estimateGas) {
19
+ return `${baseCommand} --estimate-gas`;
20
+ }
21
+
22
+ if (!deployOptions.verify) {
23
+ baseCommand += ` --no-verify`;
24
+ }
25
+
26
+ if (deployOptions.maxFee) {
27
+ baseCommand += ` --max-fee-per-gas-gwei=${deployOptions.maxFee}`;
28
+ }
29
+
30
+ return baseCommand;
31
+ }
32
+
33
+ export async function estimateGasPrice(
34
+ config: DeploymentConfig,
35
+ deployOptions: DeployOptions,
36
+ ): Promise<string> {
37
+ let deployCommand = `cargo stylus deploy --endpoint='${config.chain?.rpcUrl}' --private-key='${config.privateKey}' --no-verify --estimate-gas `;
38
+ if (deployOptions.constructorArgs) {
39
+ deployCommand += ` --constructor-args='${deployOptions.constructorArgs.join(" ")}'`;
40
+ }
41
+ const deployOutput = await executeCommand(
42
+ deployCommand,
43
+ config.contractName,
44
+ "Estimating gas price with cargo stylus",
45
+ );
46
+ const gasPrice = extractGasPriceFromOutput(deployOutput);
47
+ if (gasPrice) {
48
+ return gasPrice;
49
+ }
50
+ return "0";
51
+ }
52
+
53
+ export function executeCommand(
54
+ command: string,
55
+ cwd: string,
56
+ description: string,
57
+ ): Promise<string> {
58
+ console.log(`\nšŸ”„ ${description}...`);
59
+ // Sanitize command to hide private key (create a copy to avoid modifying original)
60
+ const sanitizedCommand = command.slice();
61
+ console.log(
62
+ `Executing: ${sanitizedCommand.replace(/--private-key=[^\s]+/g, "--private-key=***")}`,
63
+ );
64
+
65
+ return new Promise((resolve, reject) => {
66
+ const childProcess = spawn(command, [], {
67
+ cwd,
68
+ shell: true,
69
+ stdio: ["inherit", "pipe", "pipe"],
70
+ });
71
+
72
+ let output = "";
73
+ let errorOutput = "";
74
+ const outputLines: string[] = [];
75
+ let errorLines: string[] = [];
76
+
77
+ // Handle stdout
78
+ if (childProcess.stdout) {
79
+ childProcess.stdout.on("data", (data: Buffer) => {
80
+ const chunk = data.toString();
81
+ output += chunk;
82
+ const newLines = chunk.split("\n");
83
+ outputLines.push(...newLines);
84
+ });
85
+ }
86
+
87
+ // Handle stderr
88
+ if (childProcess.stderr) {
89
+ childProcess.stderr.on("data", (data: Buffer) => {
90
+ const chunk = data.toString();
91
+ errorOutput += chunk;
92
+ const newLines = chunk.split("\n");
93
+ errorLines.push(...newLines);
94
+ // Keep only the last 5 lines
95
+ if (errorLines.length > 5) {
96
+ errorLines = errorLines.slice(-5);
97
+ }
98
+ });
99
+ }
100
+
101
+ // Handle process completion
102
+ childProcess.on("close", (code: number | null) => {
103
+ if (code === 0) {
104
+ console.log(`\nāœ… ${description} completed successfully!`);
105
+ resolve(output);
106
+ } else {
107
+ console.error(`\nāŒ ${description} failed with exit code ${code}`);
108
+ // Print error output starting from "project metadata hash computed on deployment" or error patterns, or all logs if not found
109
+ if (errorLines.length > 0) {
110
+ const metadataIndex = errorLines.findIndex((line) =>
111
+ line.includes("project metadata hash computed on deployment"),
112
+ );
113
+ const errorIndex = errorLines.findIndex((line) =>
114
+ line.includes("error["),
115
+ );
116
+
117
+ let startIndex = -1;
118
+ if (metadataIndex >= 0) {
119
+ startIndex = metadataIndex;
120
+ } else if (errorIndex >= 0) {
121
+ startIndex = errorIndex;
122
+ }
123
+
124
+ if (startIndex >= 0) {
125
+ const linesToPrint = errorLines.slice(startIndex);
126
+ linesToPrint.forEach((line) => {
127
+ if (line.trim()) console.error(line);
128
+ });
129
+ } else {
130
+ errorLines.forEach((line) => {
131
+ if (line.trim()) console.error(line);
132
+ });
133
+ }
134
+ }
135
+ if (errorOutput) {
136
+ console.error(errorOutput);
137
+ }
138
+ reject(
139
+ new Error(
140
+ `Command failed with exit code ${code}. Error output: ${errorOutput}`,
141
+ ),
142
+ );
143
+ }
144
+ });
145
+
146
+ // Handle process errors
147
+ childProcess.on("error", (error: Error) => {
148
+ console.error(`\nāŒ ${description} failed:`, error);
149
+ reject(error);
150
+ });
151
+ });
152
+ }
@@ -0,0 +1,228 @@
1
+ import * as path from "path";
2
+ import * as fs from "fs";
3
+ import { ethers } from "ethers";
4
+ import toml from "toml";
5
+ import prettier from "prettier";
6
+ import { DeploymentData, ExportConfig } from "./type";
7
+ import { getContractDataFromDeployments } from "./deployment";
8
+ import { Address } from "viem";
9
+
10
+ export const generatedContractComment = `
11
+ /**
12
+ * This file is autogenerated by scaffold-stylus.
13
+ * You should not edit it manually or your changes might be overwritten.
14
+ */
15
+ `;
16
+
17
+ /**
18
+ * Reads the contract name from Cargo.toml in the given contract folder.
19
+ * Throws if the file or name field is missing.
20
+ */
21
+ export function getContractNameFromCargoToml(contractFolder: string): string {
22
+ const cargoTomlPath = path.join(contractFolder, "Cargo.toml");
23
+ if (!fs.existsSync(cargoTomlPath)) {
24
+ throw new Error(
25
+ `Cargo.toml not found in contract folder: ${cargoTomlPath}`,
26
+ );
27
+ }
28
+ const tomlContent = fs.readFileSync(cargoTomlPath, "utf8");
29
+ let parsed: any;
30
+ try {
31
+ parsed = toml.parse(tomlContent);
32
+ } catch (e) {
33
+ throw new Error(`Failed to parse Cargo.toml: ${e}`);
34
+ }
35
+ if (!parsed.package || !parsed.package.name) {
36
+ throw new Error(
37
+ `Missing [package] or name field in Cargo.toml at ${cargoTomlPath}`,
38
+ );
39
+ }
40
+ return parsed.package.name;
41
+ }
42
+
43
+ export function getExportConfig(
44
+ contractFolder?: string,
45
+ contractName?: string,
46
+ chainId?: string,
47
+ ): ExportConfig {
48
+ if (!contractFolder) {
49
+ throw new Error("Contract folder is required");
50
+ }
51
+
52
+ contractName = contractName || getContractNameFromCargoToml(contractFolder);
53
+ const deploymentDir = process.env["DEPLOYMENT_DIR"] || "deployments";
54
+
55
+ const deploymentData = getContractDataFromDeployments(
56
+ deploymentDir,
57
+ contractName,
58
+ chainId,
59
+ );
60
+ if (!deploymentData) {
61
+ throw new Error(
62
+ `āŒ Contract address for '${contractName}' not found in any chain-specific deployment files in ${deploymentDir}. Please deploy the contract first.`,
63
+ );
64
+ }
65
+
66
+ return {
67
+ contractFolder,
68
+ contractName,
69
+ deploymentDir,
70
+ contractAddress: deploymentData.address as Address,
71
+ txHash: deploymentData.txHash,
72
+ chainId: deploymentData.chainId,
73
+ };
74
+ }
75
+
76
+ export function isContractFolder(contractFolder: string): boolean {
77
+ const cargoTomlPath = path.join(contractFolder, "Cargo.toml");
78
+ const libRsPath = path.join(contractFolder, "src", "lib.rs");
79
+ const mainRsPath = path.join(contractFolder, "src", "main.rs");
80
+ return (
81
+ fs.existsSync(cargoTomlPath) &&
82
+ fs.existsSync(libRsPath) &&
83
+ fs.existsSync(mainRsPath)
84
+ );
85
+ }
86
+
87
+ export function generateContractAddress(): string {
88
+ // Generate a random private key and derive the address
89
+ const wallet = ethers.Wallet.createRandom();
90
+ return wallet.address;
91
+ }
92
+
93
+ export function extractDeploymentInfo(output: string): DeploymentData | null {
94
+ let result: DeploymentData | null = null;
95
+ const lines = output.split("\n");
96
+ for (const line of lines) {
97
+ if (line.includes("deployed code at address:")) {
98
+ // Extract the hex address directly
99
+ const hexMatch = line.match(/(0x[a-fA-F0-9]{40})/);
100
+ if (hexMatch && hexMatch[1]) {
101
+ result = { address: hexMatch[1] as Address, txHash: "" };
102
+ }
103
+ }
104
+ if (line.includes("deployment tx hash:")) {
105
+ const txHashMatch = line.match(/(0x[a-fA-F0-9]{64})/);
106
+ if (txHashMatch && txHashMatch[1]) {
107
+ result = {
108
+ address: result?.address as Address,
109
+ txHash: txHashMatch[1],
110
+ };
111
+ }
112
+ }
113
+ }
114
+ return result;
115
+ }
116
+
117
+ export function extractGasPriceFromOutput(output: string): string | null {
118
+ const lines = output.split("\n");
119
+ for (const line of lines) {
120
+ if (line.includes("gas price:")) {
121
+ // Remove ANSI color codes first
122
+ // eslint-disable-next-line no-control-regex
123
+ const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, "");
124
+
125
+ const match = cleanLine.match(/gas price:\s*"([^"]+)"/);
126
+ if (match && match[1]) {
127
+ return match[1];
128
+ }
129
+ }
130
+ }
131
+ return null;
132
+ }
133
+
134
+ export async function generateTsAbi(
135
+ abiFilePath: string,
136
+ contractName: string,
137
+ contractAddress: string,
138
+ txHash: string,
139
+ chainId: string,
140
+ ) {
141
+ const TARGET_DIR = "../nextjs/contracts/";
142
+ const TARGET_FILE = `${TARGET_DIR}deployedContracts.ts`;
143
+ const abiTxt = fs.readFileSync(abiFilePath, "utf8");
144
+
145
+ // Extract from 4th row to the end
146
+ const lines = abiTxt.split("\n");
147
+ const extractedAbi = lines.slice(3).join("\n");
148
+ const abiJson = JSON.parse(extractedAbi);
149
+
150
+ const newContractEntry = {
151
+ address: contractAddress,
152
+ txHash: txHash,
153
+ abi: abiJson,
154
+ };
155
+
156
+ let deployedContractsObj: any = {};
157
+ const fileHeader =
158
+ generatedContractComment +
159
+ 'import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";\n\n';
160
+
161
+ if (fs.existsSync(TARGET_FILE)) {
162
+ const fileContent = fs.readFileSync(TARGET_FILE, "utf8");
163
+ // Extract the deployedContracts object using regex
164
+ const match = fileContent.match(
165
+ /const deployedContracts = ([\s\S]*?) as const;/,
166
+ );
167
+ if (match) {
168
+ // eslint-disable-next-line no-eval
169
+ deployedContractsObj = eval("(" + match[1] + ")");
170
+ }
171
+ }
172
+
173
+ if (!deployedContractsObj[chainId]) {
174
+ deployedContractsObj[chainId] = {};
175
+ }
176
+ deployedContractsObj[chainId][contractName] = newContractEntry;
177
+
178
+ const contractsString = JSON.stringify(deployedContractsObj, null, 2);
179
+
180
+ const output = `${fileHeader}const deployedContracts = ${contractsString} as const;\n\nexport default deployedContracts satisfies GenericContractsDeclaration;\n`;
181
+
182
+ if (!fs.existsSync(TARGET_DIR)) {
183
+ fs.mkdirSync(TARGET_DIR);
184
+ }
185
+
186
+ fs.writeFileSync(
187
+ TARGET_FILE,
188
+ await prettier.format(output, { parser: "typescript" }),
189
+ );
190
+
191
+ console.log(
192
+ `šŸ“ Updated TypeScript contract definition file on ${TARGET_FILE}`,
193
+ );
194
+ }
195
+
196
+ export function handleSolcError(
197
+ error: Error,
198
+ context: string = "ABI export",
199
+ ): void {
200
+ console.error(`\nāŒ ${context} failed!`);
201
+ console.error("\nšŸ” Error details:", error.message);
202
+
203
+ // Check if the error is related to solc not being found
204
+ if (
205
+ error.message.includes("solc") ||
206
+ error.message.includes("solidity") ||
207
+ error.message.includes("command not found")
208
+ ) {
209
+ console.error(
210
+ "\nšŸ’” It appears that the Solidity compiler (solc) is not installed on your system.",
211
+ );
212
+ console.error("\nšŸ“š To install Solidity, please visit:");
213
+ console.error(
214
+ " https://docs.soliditylang.org/en/latest/installing-solidity.html",
215
+ );
216
+ console.error(
217
+ "\nšŸš€ After installing solc, you can run this command again:",
218
+ );
219
+ console.error(" yarn export-abi");
220
+ console.error("\nšŸ“‹ Quick installation options:");
221
+ console.error(" • npm: npm install --global solc");
222
+ console.error(" • Docker: docker run ethereum/solc:stable --help");
223
+ console.error(" • Homebrew (macOS): brew install solidity");
224
+ console.error(" • Linux: sudo apt-get install solc");
225
+ } else {
226
+ console.error("\nšŸ’” Please check the error details above and try again.");
227
+ }
228
+ }