create-stylus 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/issue_template.md +7 -0
- package/.github/pull_request_template.md +11 -0
- package/.github/workflows/release-alpha.yml +32 -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/dist/cli.js +656 -0
- package/dist/cli.js.map +1 -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 +70 -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/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 +43 -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 +13 -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/README.md +263 -0
- package/templates/base/packages/stylus/header.png +0 -0
- package/templates/base/packages/stylus/jest.config.js +15 -0
- package/templates/base/packages/stylus/package.json +49 -0
- package/templates/base/packages/stylus/scripts/deploy.ts +29 -0
- package/templates/base/packages/stylus/scripts/deploy_all_contracts.ts +59 -0
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +93 -0
- package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +79 -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 +165 -0
- package/templates/base/packages/stylus/scripts/utils/contract.ts +219 -0
- package/templates/base/packages/stylus/scripts/utils/deployment.ts +136 -0
- package/templates/base/packages/stylus/scripts/utils/index.ts +6 -0
- package/templates/base/packages/stylus/scripts/utils/network.ts +112 -0
- package/templates/base/packages/stylus/scripts/utils/type.ts +48 -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 +5744 -0
- package/templates/base/packages/stylus/your-contract/Cargo.toml +46 -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 +211 -0
- package/templates/base/packages/stylus/your-contract/src/main.rs +10 -0
- package/templates/base/readme.md +187 -0
- package/templates/base/yarn.lock +17860 -0
- package/tsconfig.json +13 -0
|
@@ -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,165 @@
|
|
|
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
|
+
const baseCommand = `cargo stylus deploy --endpoint='${config.chain?.rpcUrl}' --private-key='${config.privateKey}' --no-verify`;
|
|
10
|
+
|
|
11
|
+
if (deployOptions.estimateGas) {
|
|
12
|
+
return `${baseCommand} --estimate-gas`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (deployOptions.maxFee) {
|
|
16
|
+
return `${baseCommand} --max-fee-per-gas-gwei=${deployOptions.maxFee}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// const gasPrice = await estimateGasPrice(config);
|
|
20
|
+
return baseCommand;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function estimateGasPrice(
|
|
24
|
+
config: DeploymentConfig,
|
|
25
|
+
): Promise<string> {
|
|
26
|
+
const deployCommand = `cargo stylus deploy --endpoint='${config.chain?.rpcUrl}' --private-key='${config.privateKey}' --no-verify --estimate-gas`;
|
|
27
|
+
const deployOutput = await executeCommand(
|
|
28
|
+
deployCommand,
|
|
29
|
+
config.contractName,
|
|
30
|
+
"Estimating gas price with cargo stylus",
|
|
31
|
+
);
|
|
32
|
+
const gasPrice = extractGasPriceFromOutput(deployOutput);
|
|
33
|
+
if (gasPrice) {
|
|
34
|
+
return gasPrice;
|
|
35
|
+
}
|
|
36
|
+
return "0";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function executeCommand(
|
|
40
|
+
command: string,
|
|
41
|
+
cwd: string,
|
|
42
|
+
description: string,
|
|
43
|
+
): Promise<string> {
|
|
44
|
+
console.log(`\nš ${description}...`);
|
|
45
|
+
// Sanitize command to hide private key (create a copy to avoid modifying original)
|
|
46
|
+
const sanitizedCommand = command.slice();
|
|
47
|
+
console.log(
|
|
48
|
+
`Executing: ${sanitizedCommand.replace(/--private-key=[^\s]+/g, "--private-key=***")}`,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const childProcess = spawn(command, [], {
|
|
53
|
+
cwd,
|
|
54
|
+
shell: true,
|
|
55
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
let output = "";
|
|
59
|
+
let errorOutput = "";
|
|
60
|
+
const outputLines: string[] = [];
|
|
61
|
+
let errorLines: string[] = [];
|
|
62
|
+
|
|
63
|
+
// Handle stdout
|
|
64
|
+
if (childProcess.stdout) {
|
|
65
|
+
childProcess.stdout.on("data", (data: Buffer) => {
|
|
66
|
+
const chunk = data.toString();
|
|
67
|
+
output += chunk;
|
|
68
|
+
const newLines = chunk.split("\n");
|
|
69
|
+
outputLines.push(...newLines);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Handle stderr
|
|
74
|
+
if (childProcess.stderr) {
|
|
75
|
+
childProcess.stderr.on("data", (data: Buffer) => {
|
|
76
|
+
const chunk = data.toString();
|
|
77
|
+
errorOutput += chunk;
|
|
78
|
+
const newLines = chunk.split("\n");
|
|
79
|
+
errorLines.push(...newLines);
|
|
80
|
+
// Keep only the last 5 lines
|
|
81
|
+
if (errorLines.length > 5) {
|
|
82
|
+
errorLines = errorLines.slice(-5);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Handle process completion
|
|
88
|
+
childProcess.on("close", (code: number | null) => {
|
|
89
|
+
if (code === 0) {
|
|
90
|
+
console.log(`\nā
${description} completed successfully!`);
|
|
91
|
+
// Print output starting from "project metadata hash computed on deployment" or error patterns, or all logs if not found
|
|
92
|
+
// if (outputLines.length > 0) {
|
|
93
|
+
// const metadataIndex = outputLines.findIndex((line) =>
|
|
94
|
+
// line.includes("project metadata hash computed on deployment"),
|
|
95
|
+
// );
|
|
96
|
+
// const errorIndex = outputLines.findIndex((line) =>
|
|
97
|
+
// line.includes("error["),
|
|
98
|
+
// );
|
|
99
|
+
|
|
100
|
+
// let startIndex = -1;
|
|
101
|
+
// if (metadataIndex >= 0) {
|
|
102
|
+
// startIndex = metadataIndex;
|
|
103
|
+
// } else if (errorIndex >= 0) {
|
|
104
|
+
// startIndex = errorIndex;
|
|
105
|
+
// }
|
|
106
|
+
|
|
107
|
+
// if (startIndex >= 0) {
|
|
108
|
+
// const linesToPrint = outputLines.slice(startIndex);
|
|
109
|
+
// linesToPrint.forEach((line) => {
|
|
110
|
+
// if (line.trim()) console.log(line);
|
|
111
|
+
// });
|
|
112
|
+
// } else {
|
|
113
|
+
// outputLines.forEach((line) => {
|
|
114
|
+
// if (line.trim()) console.log(line);
|
|
115
|
+
// });
|
|
116
|
+
// }
|
|
117
|
+
// }
|
|
118
|
+
resolve(output);
|
|
119
|
+
} else {
|
|
120
|
+
console.error(`\nā ${description} failed with exit code ${code}`);
|
|
121
|
+
// Print error output starting from "project metadata hash computed on deployment" or error patterns, or all logs if not found
|
|
122
|
+
if (errorLines.length > 0) {
|
|
123
|
+
const metadataIndex = errorLines.findIndex((line) =>
|
|
124
|
+
line.includes("project metadata hash computed on deployment"),
|
|
125
|
+
);
|
|
126
|
+
const errorIndex = errorLines.findIndex((line) =>
|
|
127
|
+
line.includes("error["),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
let startIndex = -1;
|
|
131
|
+
if (metadataIndex >= 0) {
|
|
132
|
+
startIndex = metadataIndex;
|
|
133
|
+
} else if (errorIndex >= 0) {
|
|
134
|
+
startIndex = errorIndex;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (startIndex >= 0) {
|
|
138
|
+
const linesToPrint = errorLines.slice(startIndex);
|
|
139
|
+
linesToPrint.forEach((line) => {
|
|
140
|
+
if (line.trim()) console.error(line);
|
|
141
|
+
});
|
|
142
|
+
} else {
|
|
143
|
+
errorLines.forEach((line) => {
|
|
144
|
+
if (line.trim()) console.error(line);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (errorOutput) {
|
|
149
|
+
console.error(errorOutput);
|
|
150
|
+
}
|
|
151
|
+
reject(
|
|
152
|
+
new Error(
|
|
153
|
+
`Command failed with exit code ${code}. Error output: ${errorOutput}`,
|
|
154
|
+
),
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Handle process errors
|
|
160
|
+
childProcess.on("error", (error: Error) => {
|
|
161
|
+
console.error(`\nā ${description} failed:`, error);
|
|
162
|
+
reject(error);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
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 { ExportConfig } from "./type";
|
|
7
|
+
import { getContractDataFromDeployments } from "./deployment";
|
|
8
|
+
|
|
9
|
+
export const generatedContractComment = `
|
|
10
|
+
/**
|
|
11
|
+
* This file is autogenerated by scaffold-stylus.
|
|
12
|
+
* You should not edit it manually or your changes might be overwritten.
|
|
13
|
+
*/
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Reads the contract name from Cargo.toml in the given contract folder.
|
|
18
|
+
* Throws if the file or name field is missing.
|
|
19
|
+
*/
|
|
20
|
+
export function getContractNameFromCargoToml(contractFolder: string): string {
|
|
21
|
+
const cargoTomlPath = path.join(contractFolder, "Cargo.toml");
|
|
22
|
+
if (!fs.existsSync(cargoTomlPath)) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
`Cargo.toml not found in contract folder: ${cargoTomlPath}`,
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const tomlContent = fs.readFileSync(cargoTomlPath, "utf8");
|
|
28
|
+
let parsed: any;
|
|
29
|
+
try {
|
|
30
|
+
parsed = toml.parse(tomlContent);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
throw new Error(`Failed to parse Cargo.toml: ${e}`);
|
|
33
|
+
}
|
|
34
|
+
if (!parsed.package || !parsed.package.name) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`Missing [package] or name field in Cargo.toml at ${cargoTomlPath}`,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return parsed.package.name;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getExportConfig(
|
|
43
|
+
contractFolder?: string,
|
|
44
|
+
contractName?: string,
|
|
45
|
+
): ExportConfig {
|
|
46
|
+
if (!contractFolder) {
|
|
47
|
+
throw new Error("Contract folder is required");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
contractName = contractName || getContractNameFromCargoToml(contractFolder);
|
|
51
|
+
const deploymentDir = process.env["DEPLOYMENT_DIR"] || "deployments";
|
|
52
|
+
|
|
53
|
+
const deploymentData = getContractDataFromDeployments(
|
|
54
|
+
deploymentDir,
|
|
55
|
+
contractName,
|
|
56
|
+
);
|
|
57
|
+
if (!deploymentData) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`ā Contract address for '${contractName}' not found in ${deploymentDir}/addresses.json. Please deploy the contract first.`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
contractFolder,
|
|
65
|
+
contractName,
|
|
66
|
+
deploymentDir,
|
|
67
|
+
contractAddress: deploymentData.address,
|
|
68
|
+
chainId: deploymentData.chainId,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function isContractFolder(contractFolder: string): boolean {
|
|
73
|
+
const cargoTomlPath = path.join(contractFolder, "Cargo.toml");
|
|
74
|
+
const libRsPath = path.join(contractFolder, "src", "lib.rs");
|
|
75
|
+
const mainRsPath = path.join(contractFolder, "src", "main.rs");
|
|
76
|
+
return (
|
|
77
|
+
fs.existsSync(cargoTomlPath) &&
|
|
78
|
+
fs.existsSync(libRsPath) &&
|
|
79
|
+
fs.existsSync(mainRsPath)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function generateContractAddress(): string {
|
|
84
|
+
// Generate a random private key and derive the address
|
|
85
|
+
const wallet = ethers.Wallet.createRandom();
|
|
86
|
+
return wallet.address;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function extractDeployedAddress(output: string): string | null {
|
|
90
|
+
// Look for the line containing "deployed code at address:"
|
|
91
|
+
const lines = output.split("\n");
|
|
92
|
+
for (const line of lines) {
|
|
93
|
+
if (line.includes("deployed code at address:")) {
|
|
94
|
+
// Simple approach: just extract the hex address directly
|
|
95
|
+
const hexMatch = line.match(/(0x[a-fA-F0-9]{40})/);
|
|
96
|
+
if (hexMatch && hexMatch[1]) {
|
|
97
|
+
return hexMatch[1];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function extractGasPriceFromOutput(output: string): string | null {
|
|
105
|
+
const lines = output.split("\n");
|
|
106
|
+
for (const line of lines) {
|
|
107
|
+
if (line.includes("gas price:")) {
|
|
108
|
+
// Remove ANSI color codes first
|
|
109
|
+
// eslint-disable-next-line no-control-regex
|
|
110
|
+
const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, "");
|
|
111
|
+
|
|
112
|
+
// Extract the value inside quotes after 'gas price:'
|
|
113
|
+
const match = cleanLine.match(/gas price:\s*"([^"]+)"/);
|
|
114
|
+
if (match && match[1]) {
|
|
115
|
+
return match[1];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function generateTsAbi(
|
|
123
|
+
abiFilePath: string,
|
|
124
|
+
contractName: string,
|
|
125
|
+
contractAddress: string,
|
|
126
|
+
chainId: string,
|
|
127
|
+
) {
|
|
128
|
+
const TARGET_DIR = "../nextjs/contracts/";
|
|
129
|
+
const TARGET_FILE = `${TARGET_DIR}deployedContracts.ts`;
|
|
130
|
+
const abiTxt = fs.readFileSync(abiFilePath, "utf8");
|
|
131
|
+
|
|
132
|
+
// Extract from 4th row to the end
|
|
133
|
+
const lines = abiTxt.split("\n");
|
|
134
|
+
const extractedAbi = lines.slice(3).join("\n");
|
|
135
|
+
const abiJson = JSON.parse(extractedAbi);
|
|
136
|
+
|
|
137
|
+
// Helper to generate the contract entry
|
|
138
|
+
const newContractEntry = {
|
|
139
|
+
address: contractAddress,
|
|
140
|
+
abi: abiJson,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
let deployedContractsObj: any = {};
|
|
144
|
+
const fileHeader =
|
|
145
|
+
generatedContractComment +
|
|
146
|
+
'import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";\n\n';
|
|
147
|
+
|
|
148
|
+
if (fs.existsSync(TARGET_FILE)) {
|
|
149
|
+
// Read and parse the existing file
|
|
150
|
+
const fileContent = fs.readFileSync(TARGET_FILE, "utf8");
|
|
151
|
+
// Extract the deployedContracts object using regex
|
|
152
|
+
const match = fileContent.match(
|
|
153
|
+
/const deployedContracts = ([\s\S]*?) as const;/,
|
|
154
|
+
);
|
|
155
|
+
if (match) {
|
|
156
|
+
// eslint-disable-next-line no-eval
|
|
157
|
+
deployedContractsObj = eval("(" + match[1] + ")");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Ensure the chainId exists
|
|
162
|
+
if (!deployedContractsObj[chainId]) {
|
|
163
|
+
deployedContractsObj[chainId] = {};
|
|
164
|
+
}
|
|
165
|
+
// Update or insert the contract entry
|
|
166
|
+
deployedContractsObj[chainId][contractName] = newContractEntry;
|
|
167
|
+
|
|
168
|
+
// Stringify the object for TypeScript output
|
|
169
|
+
const contractsString = JSON.stringify(deployedContractsObj, null, 2);
|
|
170
|
+
|
|
171
|
+
const output = `${fileHeader}const deployedContracts = ${contractsString} as const;\n\nexport default deployedContracts satisfies GenericContractsDeclaration;\n`;
|
|
172
|
+
|
|
173
|
+
if (!fs.existsSync(TARGET_DIR)) {
|
|
174
|
+
fs.mkdirSync(TARGET_DIR);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
fs.writeFileSync(
|
|
178
|
+
TARGET_FILE,
|
|
179
|
+
await prettier.format(output, { parser: "typescript" }),
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
console.log(
|
|
183
|
+
`š Updated TypeScript contract definition file on ${TARGET_FILE}`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function handleSolcError(
|
|
188
|
+
error: Error,
|
|
189
|
+
context: string = "ABI export",
|
|
190
|
+
): void {
|
|
191
|
+
console.error(`\nā ${context} failed!`);
|
|
192
|
+
console.error("\nš Error details:", error.message);
|
|
193
|
+
|
|
194
|
+
// Check if the error is related to solc not being found
|
|
195
|
+
if (
|
|
196
|
+
error.message.includes("solc") ||
|
|
197
|
+
error.message.includes("solidity") ||
|
|
198
|
+
error.message.includes("command not found")
|
|
199
|
+
) {
|
|
200
|
+
console.error(
|
|
201
|
+
"\nš” It appears that the Solidity compiler (solc) is not installed on your system.",
|
|
202
|
+
);
|
|
203
|
+
console.error("\nš To install Solidity, please visit:");
|
|
204
|
+
console.error(
|
|
205
|
+
" https://docs.soliditylang.org/en/latest/installing-solidity.html",
|
|
206
|
+
);
|
|
207
|
+
console.error(
|
|
208
|
+
"\nš After installing solc, you can run this command again:",
|
|
209
|
+
);
|
|
210
|
+
console.error(" yarn export-abi");
|
|
211
|
+
console.error("\nš Quick installation options:");
|
|
212
|
+
console.error(" ⢠npm: npm install --global solc");
|
|
213
|
+
console.error(" ⢠Docker: docker run ethereum/solc:stable --help");
|
|
214
|
+
console.error(" ⢠Homebrew (macOS): brew install solidity");
|
|
215
|
+
console.error(" ⢠Linux: sudo apt-get install solc");
|
|
216
|
+
} else {
|
|
217
|
+
console.error("\nš” Please check the error details above and try again.");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { config as dotenvConfig } from "dotenv";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import { arbitrumNitro } from "../../../nextjs/utils/scaffold-stylus/chain";
|
|
5
|
+
import { DeploymentConfig, DeployOptions } from "./type";
|
|
6
|
+
import { getChain, getPrivateKey } from "./network";
|
|
7
|
+
import { getContractNameFromCargoToml } from "./contract";
|
|
8
|
+
|
|
9
|
+
// Load environment variables from .env file
|
|
10
|
+
const envPath = path.resolve(__dirname, "../../.env");
|
|
11
|
+
if (fs.existsSync(envPath)) {
|
|
12
|
+
dotenvConfig({ path: envPath });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function clearDeploymentDir(): void {
|
|
16
|
+
const deploymentDir = process.env["DEPLOYMENT_DIR"] || "deployments";
|
|
17
|
+
if (fs.existsSync(deploymentDir)) {
|
|
18
|
+
fs.rmSync(deploymentDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getDeploymentConfig(
|
|
23
|
+
deployOptions: DeployOptions,
|
|
24
|
+
): DeploymentConfig {
|
|
25
|
+
// If network is specified, try to get RPC URL from viem chains
|
|
26
|
+
if (!deployOptions.network) deployOptions.network = "devnet";
|
|
27
|
+
|
|
28
|
+
const chain = getChain(deployOptions.network);
|
|
29
|
+
if (!chain) throw new Error(`Network ${deployOptions.network} not found`);
|
|
30
|
+
|
|
31
|
+
let contractName: string;
|
|
32
|
+
if (deployOptions.contract) {
|
|
33
|
+
try {
|
|
34
|
+
contractName =
|
|
35
|
+
deployOptions.name ||
|
|
36
|
+
getContractNameFromCargoToml(deployOptions.contract);
|
|
37
|
+
} catch (e) {
|
|
38
|
+
throw new Error(`ā Could not read contract name from Cargo.toml: ${e}`);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
contractName = "your-contract";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
privateKey: getPrivateKey(deployOptions.network),
|
|
46
|
+
contractFolder: deployOptions.contract!,
|
|
47
|
+
contractName,
|
|
48
|
+
deploymentDir: process.env["DEPLOYMENT_DIR"] || "deployments",
|
|
49
|
+
chain,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function ensureDeploymentDirectory(deploymentDir: string): void {
|
|
54
|
+
if (!fs.existsSync(deploymentDir)) {
|
|
55
|
+
console.log(`š Creating deployment directory: ${deploymentDir}`);
|
|
56
|
+
fs.mkdirSync(deploymentDir, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Save the deployed contract address to addresses.json in the deployment directory.
|
|
62
|
+
* Updates or creates the file, using contractName as the key.
|
|
63
|
+
*/
|
|
64
|
+
export function saveDeployedAddress(config: DeploymentConfig) {
|
|
65
|
+
try {
|
|
66
|
+
const addressesPath = path.resolve(config.deploymentDir, "addresses.json");
|
|
67
|
+
let addresses: Record<string, any> = {};
|
|
68
|
+
if (fs.existsSync(addressesPath)) {
|
|
69
|
+
const content = fs.readFileSync(addressesPath, "utf8");
|
|
70
|
+
try {
|
|
71
|
+
addresses = JSON.parse(content);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.warn(
|
|
74
|
+
`ā ļø Could not parse existing addresses.json, will overwrite. Error: ${e}`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Save both address and chain ID
|
|
80
|
+
addresses[config.contractName] = {
|
|
81
|
+
address: config.contractAddress || "",
|
|
82
|
+
chainId: (config.chain?.id || arbitrumNitro.id).toString(),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
fs.writeFileSync(addressesPath, JSON.stringify(addresses, null, 2));
|
|
86
|
+
console.log(`š¾ Saved deployed address and chain ID to ${addressesPath}`);
|
|
87
|
+
} catch (e) {
|
|
88
|
+
console.error(`ā Failed to save deployed address: ${e}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function printDeployedAddresses(deploymentDir: string): void {
|
|
93
|
+
const addressesPath = path.resolve(deploymentDir, "addresses.json");
|
|
94
|
+
if (fs.existsSync(addressesPath)) {
|
|
95
|
+
const addresses = JSON.parse(fs.readFileSync(addressesPath, "utf8"));
|
|
96
|
+
console.log(`š¦ Deployed contract addresses (${addressesPath}):`);
|
|
97
|
+
|
|
98
|
+
// Format the output to show contract name, address, and chain ID clearly
|
|
99
|
+
Object.entries(addresses).forEach(([contractName, contractData]) => {
|
|
100
|
+
const data = contractData as {
|
|
101
|
+
address: string;
|
|
102
|
+
chainId: string;
|
|
103
|
+
};
|
|
104
|
+
console.log(` ${contractName}:`);
|
|
105
|
+
console.log(` Address: ${data.address}`);
|
|
106
|
+
console.log(` Chain ID: ${data.chainId}`);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Reads the deployed contract data from addresses.json in the deployment directory.
|
|
113
|
+
* Returns an object with address and chainId for the given contractName, or undefined if not found.
|
|
114
|
+
*/
|
|
115
|
+
export function getContractDataFromDeployments(
|
|
116
|
+
deploymentDir: string,
|
|
117
|
+
contractName: string,
|
|
118
|
+
): { address: string; chainId: string } | undefined {
|
|
119
|
+
const addressesPath = path.resolve(deploymentDir, "addresses.json");
|
|
120
|
+
if (fs.existsSync(addressesPath)) {
|
|
121
|
+
try {
|
|
122
|
+
const addresses = JSON.parse(fs.readFileSync(addressesPath, "utf8"));
|
|
123
|
+
if (addresses[contractName]?.address) {
|
|
124
|
+
return addresses[contractName] as {
|
|
125
|
+
address: string;
|
|
126
|
+
chainId: string;
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
console.warn(
|
|
131
|
+
`ā ļø Could not parse addresses.json at ${addressesPath}: ${e}`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|