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.
- package/.github/issue_template.md +7 -0
- package/.github/pull_request_template.md +11 -0
- package/.github/workflows/release-alpha.yml +32 -0
- package/.github/workflows/release-manual.yml +26 -0
- package/.yarnrc.yml +1 -0
- package/CONTRIBUTING.md +42 -0
- package/README.md +66 -0
- package/bin/create-dapp-ss.js +4 -0
- package/package.json +46 -0
- package/rollup.config.js +22 -0
- package/src/cli.ts +14 -0
- package/src/extensions.json +14 -0
- package/src/main.ts +72 -0
- package/src/tasks/copy-extension-file.ts +227 -0
- package/src/tasks/copy-template-files.ts +252 -0
- package/src/tasks/create-first-git-commit.ts +35 -0
- package/src/tasks/create-project-directory.ts +34 -0
- package/src/tasks/index.ts +5 -0
- package/src/tasks/install-packages.ts +15 -0
- package/src/tasks/prettier-format.ts +17 -0
- package/src/types.ts +31 -0
- package/src/utils/consts.ts +1 -0
- package/src/utils/find-files-recursively.ts +19 -0
- package/src/utils/link.ts +44 -0
- package/src/utils/load-extensions.ts +10 -0
- package/src/utils/merge-package-json.ts +33 -0
- package/src/utils/parse-arguments-into-options.ts +38 -0
- package/src/utils/prompt-for-missing-options.ts +53 -0
- package/src/utils/render-intro-message.ts +11 -0
- package/src/utils/render-outro-message.ts +34 -0
- package/templates/base/.github/ISSUE_TEMPLATE/bug_report.yml +58 -0
- package/templates/base/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/templates/base/.github/pull_request_template.md +16 -0
- package/templates/base/.github/workflows/lint.yaml +300 -0
- package/templates/base/.gitignore.template.mjs +19 -0
- package/templates/base/.gitmodules +0 -0
- package/templates/base/.husky/pre-commit +4 -0
- package/templates/base/.lintstagedrc.js +21 -0
- package/templates/base/.vscode/settings.json +7 -0
- package/templates/base/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
- package/templates/base/.yarn/releases/yarn-3.2.3.cjs +783 -0
- package/templates/base/.yarnrc.yml +11 -0
- package/templates/base/CONTRIBUTING.md +86 -0
- package/templates/base/LICENCE +21 -0
- package/templates/base/dist/cli.js +683 -0
- package/templates/base/dist/cli.js.map +1 -0
- package/templates/base/nitro-devnode/LICENSE +201 -0
- package/templates/base/nitro-devnode/README.md +70 -0
- package/templates/base/nitro-devnode/run-dev-node.sh +132 -0
- package/templates/base/nitro-devnode/start-chain-with-cors.sh +150 -0
- package/templates/base/nitro-devnode/stylus-deployer-bytecode.txt +1 -0
- package/templates/base/nitro-devnode/stylus-dev/Dockerfile +10 -0
- package/templates/base/package.json +44 -0
- package/templates/base/packages/nextjs/.env.example +13 -0
- package/templates/base/packages/nextjs/.eslintignore +11 -0
- package/templates/base/packages/nextjs/.eslintrc.json +15 -0
- package/templates/base/packages/nextjs/.gitignore.template.mjs +42 -0
- package/templates/base/packages/nextjs/.prettierrc.js +9 -0
- package/templates/base/packages/nextjs/.prettierrc.json +8 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressCodeTab.tsx +27 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressComponent.tsx +36 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressLogsTab.tsx +21 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressStorageTab.tsx +61 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/BackButton.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/ContractTabs.tsx +102 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/PaginationButton.tsx +39 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/SearchBar.tsx +49 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionHash.tsx +28 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionsTable.tsx +71 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/index.tsx +7 -0
- package/templates/base/packages/nextjs/app/blockexplorer/address/[address]/page.tsx +101 -0
- package/templates/base/packages/nextjs/app/blockexplorer/layout.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/page.tsx +83 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/[txHash]/page.tsx +23 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/_components/TransactionComp.tsx +152 -0
- package/templates/base/packages/nextjs/app/debug/_components/DebugContracts.tsx +73 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractInput.tsx +84 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractReadMethods.tsx +43 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +164 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractVariables.tsx +50 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractWriteMethods.tsx +49 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +85 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/InheritanceTooltip.tsx +14 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +102 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/Tuple.tsx +44 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TupleArray.tsx +142 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +42 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/WriteOnlyFunctionForm.tsx +144 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/index.tsx +8 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsContract.tsx +166 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +114 -0
- package/templates/base/packages/nextjs/app/debug/page.tsx +14 -0
- package/templates/base/packages/nextjs/app/layout.tsx +67 -0
- package/templates/base/packages/nextjs/app/not-found.tsx +16 -0
- package/templates/base/packages/nextjs/app/page.tsx +94 -0
- package/templates/base/packages/nextjs/components/Background.tsx +37 -0
- package/templates/base/packages/nextjs/components/Card.tsx +40 -0
- package/templates/base/packages/nextjs/components/Footer.tsx +93 -0
- package/templates/base/packages/nextjs/components/Header.tsx +114 -0
- package/templates/base/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx +77 -0
- package/templates/base/packages/nextjs/components/SwitchTheme.tsx +41 -0
- package/templates/base/packages/nextjs/components/ThemeProvider.tsx +13 -0
- package/templates/base/packages/nextjs/components/assets/BuidlGuidlLogo.tsx +18 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/Address.tsx +187 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressCopyIcon.tsx +23 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressLinkWrapper.tsx +29 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Balance.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/BlockieAvatar.tsx +17 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Faucet.tsx +131 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/FaucetButton.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx +120 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/Bytes32Input.tsx +31 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/BytesInput.tsx +28 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/EtherInput.tsx +128 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx +66 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/index.ts +9 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/utils.ts +109 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressInfoDropdown.tsx +121 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressQRCodeModal.tsx +33 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/BurnerWalletModal.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/NetworkOptions.tsx +48 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/WrongNetworkDropdown.tsx +32 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/index.tsx +89 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/index.tsx +7 -0
- package/templates/base/packages/nextjs/contracts/deployedContracts.ts +9 -0
- package/templates/base/packages/nextjs/contracts/externalContracts.ts +16 -0
- package/templates/base/packages/nextjs/eslint.config.mjs +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/index.ts +17 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useAnimationConfig.ts +20 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useContractLogs.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useCopyToClipboard.ts +19 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDeployedContractInfo.ts +86 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDisplayUsdMode.ts +21 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useFetchBlocks.ts +133 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useInitializeNativeCurrencyPrice.ts +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNativeCurrencyPrice.ts +34 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNetworkColor.ts +22 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useOutsideClick.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldContract.ts +65 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts +213 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts +80 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWatchContractEvent.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts +191 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useSelectedNetwork.ts +18 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTargetNetwork.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTransactor.tsx +114 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useWatchBalance.ts +21 -0
- package/templates/base/packages/nextjs/icons/CompassIcon.tsx +39 -0
- package/templates/base/packages/nextjs/icons/DarkBugAntIcon.tsx +30 -0
- package/templates/base/packages/nextjs/icons/LightBugAntIcon.tsx +52 -0
- package/templates/base/packages/nextjs/next-env.d.ts +5 -0
- package/templates/base/packages/nextjs/next.config.js +19 -0
- package/templates/base/packages/nextjs/package.json +58 -0
- package/templates/base/packages/nextjs/postcss.config.js +6 -0
- package/templates/base/packages/nextjs/public/debug-image.png +0 -0
- package/templates/base/packages/nextjs/public/favicon.png +0 -0
- package/templates/base/packages/nextjs/public/logo.svg +8 -0
- package/templates/base/packages/nextjs/public/manifest.json +5 -0
- package/templates/base/packages/nextjs/public/thumbnail.jpg +0 -0
- package/templates/base/packages/nextjs/react-copy-to-clipboard.d.ts +44 -0
- package/templates/base/packages/nextjs/scaffold.config.ts +56 -0
- package/templates/base/packages/nextjs/services/store/store.ts +39 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConfig.tsx +44 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConnectors.tsx +51 -0
- package/templates/base/packages/nextjs/styles/globals.css +80 -0
- package/templates/base/packages/nextjs/tailwind.config.js +97 -0
- package/templates/base/packages/nextjs/tsconfig.json +28 -0
- package/templates/base/packages/nextjs/types/abitype/abi.d.ts +16 -0
- package/templates/base/packages/nextjs/types/utils.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/block.ts +17 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/common.ts +8 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contract.ts +352 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contractsData.ts +11 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/decodeTxData.ts +65 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/fetchPriceFromUniswap.ts +72 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getMetadata.ts +50 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getParsedError.ts +35 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/index.ts +6 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/notification.tsx +90 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/burner.ts +59 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/chain.ts +42 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/index.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/networks.ts +94 -0
- package/templates/base/packages/nextjs/vercel.json +3 -0
- package/templates/base/packages/stylus/.env.example +16 -0
- package/templates/base/packages/stylus/.eslintrc.js +23 -0
- package/templates/base/packages/stylus/.gitignore.template.mjs +7 -0
- package/templates/base/packages/stylus/jest.config.js +15 -0
- package/templates/base/packages/stylus/package.json +48 -0
- package/templates/base/packages/stylus/scripts/deploy.ts +46 -0
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +84 -0
- package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +39 -0
- package/templates/base/packages/stylus/scripts/export_abi.ts +87 -0
- package/templates/base/packages/stylus/scripts/index.ts +0 -0
- package/templates/base/packages/stylus/scripts/new_module.sh +35 -0
- package/templates/base/packages/stylus/scripts/test_network.ts +31 -0
- package/templates/base/packages/stylus/scripts/utils/command.ts +152 -0
- package/templates/base/packages/stylus/scripts/utils/contract.ts +228 -0
- package/templates/base/packages/stylus/scripts/utils/deployment.ts +260 -0
- package/templates/base/packages/stylus/scripts/utils/index.ts +6 -0
- package/templates/base/packages/stylus/scripts/utils/network.ts +132 -0
- package/templates/base/packages/stylus/scripts/utils/type.ts +51 -0
- package/templates/base/packages/stylus/scripts/utils.ts +3 -0
- package/templates/base/packages/stylus/tsconfig.json +41 -0
- package/templates/base/packages/stylus/your-contract/.cargo/config.toml +18 -0
- package/templates/base/packages/stylus/your-contract/Cargo.lock +5761 -0
- package/templates/base/packages/stylus/your-contract/Cargo.toml +48 -0
- package/templates/base/packages/stylus/your-contract/examples/counter.rs +78 -0
- package/templates/base/packages/stylus/your-contract/header.png +0 -0
- package/templates/base/packages/stylus/your-contract/licenses/Apache-2.0 +201 -0
- package/templates/base/packages/stylus/your-contract/licenses/COPYRIGHT.md +5 -0
- package/templates/base/packages/stylus/your-contract/licenses/DCO.txt +34 -0
- package/templates/base/packages/stylus/your-contract/licenses/MIT +21 -0
- package/templates/base/packages/stylus/your-contract/rust-toolchain.toml +2 -0
- package/templates/base/packages/stylus/your-contract/src/lib.rs +241 -0
- package/templates/base/packages/stylus/your-contract/src/main.rs +10 -0
- package/templates/base/readme.md +352 -0
- package/templates/base/yarn.lock +17859 -0
- 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
|
+
}
|
|
File without changes
|
|
@@ -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
|
+
}
|