create-stylus 1.1.0 → 1.1.2
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/package.json +1 -1
- package/templates/base/.gitignore.template.mjs +2 -2
- package/templates/base/dist/cli.js +683 -0
- package/templates/base/dist/cli.js.map +1 -0
- package/templates/base/package.json +2 -1
- package/templates/base/packages/nextjs/.gitignore.template.mjs +3 -3
- package/templates/base/packages/nextjs/scaffold.config.ts +2 -2
- package/templates/base/packages/stylus/.env.example +5 -2
- package/templates/base/packages/stylus/.gitignore.template.mjs +3 -3
- package/templates/base/packages/stylus/package.json +0 -1
- package/templates/base/packages/stylus/scripts/deploy.ts +29 -12
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +34 -43
- package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +4 -44
- package/templates/base/packages/stylus/scripts/export_abi.ts +13 -13
- package/templates/base/packages/stylus/scripts/utils/command.ts +18 -31
- package/templates/base/packages/stylus/scripts/utils/contract.ts +23 -14
- package/templates/base/packages/stylus/scripts/utils/deployment.ts +169 -45
- package/templates/base/packages/stylus/scripts/utils/network.ts +27 -7
- package/templates/base/packages/stylus/scripts/utils/type.ts +13 -10
- package/templates/base/packages/stylus/your-contract/Cargo.lock +35 -18
- package/templates/base/packages/stylus/your-contract/Cargo.toml +3 -1
- package/templates/base/packages/stylus/your-contract/src/lib.rs +51 -21
- package/templates/base/readme.md +207 -42
- package/templates/base/yarn.lock +1 -2
- package/templates/base/packages/stylus/README.md +0 -263
- package/templates/base/packages/stylus/header.png +0 -0
- package/templates/base/packages/stylus/scripts/deploy_all_contracts.ts +0 -59
|
@@ -3,8 +3,9 @@ import * as fs from "fs";
|
|
|
3
3
|
import { ethers } from "ethers";
|
|
4
4
|
import toml from "toml";
|
|
5
5
|
import prettier from "prettier";
|
|
6
|
-
import { ExportConfig } from "./type";
|
|
6
|
+
import { DeploymentData, ExportConfig } from "./type";
|
|
7
7
|
import { getContractDataFromDeployments } from "./deployment";
|
|
8
|
+
import { Address } from "viem";
|
|
8
9
|
|
|
9
10
|
export const generatedContractComment = `
|
|
10
11
|
/**
|
|
@@ -42,6 +43,7 @@ export function getContractNameFromCargoToml(contractFolder: string): string {
|
|
|
42
43
|
export function getExportConfig(
|
|
43
44
|
contractFolder?: string,
|
|
44
45
|
contractName?: string,
|
|
46
|
+
chainId?: string,
|
|
45
47
|
): ExportConfig {
|
|
46
48
|
if (!contractFolder) {
|
|
47
49
|
throw new Error("Contract folder is required");
|
|
@@ -53,10 +55,11 @@ export function getExportConfig(
|
|
|
53
55
|
const deploymentData = getContractDataFromDeployments(
|
|
54
56
|
deploymentDir,
|
|
55
57
|
contractName,
|
|
58
|
+
chainId,
|
|
56
59
|
);
|
|
57
60
|
if (!deploymentData) {
|
|
58
61
|
throw new Error(
|
|
59
|
-
`❌ Contract address for '${contractName}' not found in ${deploymentDir}
|
|
62
|
+
`❌ Contract address for '${contractName}' not found in any chain-specific deployment files in ${deploymentDir}. Please deploy the contract first.`,
|
|
60
63
|
);
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -64,7 +67,8 @@ export function getExportConfig(
|
|
|
64
67
|
contractFolder,
|
|
65
68
|
contractName,
|
|
66
69
|
deploymentDir,
|
|
67
|
-
contractAddress: deploymentData.address,
|
|
70
|
+
contractAddress: deploymentData.address as Address,
|
|
71
|
+
txHash: deploymentData.txHash,
|
|
68
72
|
chainId: deploymentData.chainId,
|
|
69
73
|
};
|
|
70
74
|
}
|
|
@@ -86,19 +90,28 @@ export function generateContractAddress(): string {
|
|
|
86
90
|
return wallet.address;
|
|
87
91
|
}
|
|
88
92
|
|
|
89
|
-
export function
|
|
90
|
-
|
|
93
|
+
export function extractDeploymentInfo(output: string): DeploymentData | null {
|
|
94
|
+
let result: DeploymentData | null = null;
|
|
91
95
|
const lines = output.split("\n");
|
|
92
96
|
for (const line of lines) {
|
|
93
97
|
if (line.includes("deployed code at address:")) {
|
|
94
|
-
//
|
|
98
|
+
// Extract the hex address directly
|
|
95
99
|
const hexMatch = line.match(/(0x[a-fA-F0-9]{40})/);
|
|
96
100
|
if (hexMatch && hexMatch[1]) {
|
|
97
|
-
|
|
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
|
+
};
|
|
98
111
|
}
|
|
99
112
|
}
|
|
100
113
|
}
|
|
101
|
-
return
|
|
114
|
+
return result;
|
|
102
115
|
}
|
|
103
116
|
|
|
104
117
|
export function extractGasPriceFromOutput(output: string): string | null {
|
|
@@ -109,7 +122,6 @@ export function extractGasPriceFromOutput(output: string): string | null {
|
|
|
109
122
|
// eslint-disable-next-line no-control-regex
|
|
110
123
|
const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, "");
|
|
111
124
|
|
|
112
|
-
// Extract the value inside quotes after 'gas price:'
|
|
113
125
|
const match = cleanLine.match(/gas price:\s*"([^"]+)"/);
|
|
114
126
|
if (match && match[1]) {
|
|
115
127
|
return match[1];
|
|
@@ -123,6 +135,7 @@ export async function generateTsAbi(
|
|
|
123
135
|
abiFilePath: string,
|
|
124
136
|
contractName: string,
|
|
125
137
|
contractAddress: string,
|
|
138
|
+
txHash: string,
|
|
126
139
|
chainId: string,
|
|
127
140
|
) {
|
|
128
141
|
const TARGET_DIR = "../nextjs/contracts/";
|
|
@@ -134,9 +147,9 @@ export async function generateTsAbi(
|
|
|
134
147
|
const extractedAbi = lines.slice(3).join("\n");
|
|
135
148
|
const abiJson = JSON.parse(extractedAbi);
|
|
136
149
|
|
|
137
|
-
// Helper to generate the contract entry
|
|
138
150
|
const newContractEntry = {
|
|
139
151
|
address: contractAddress,
|
|
152
|
+
txHash: txHash,
|
|
140
153
|
abi: abiJson,
|
|
141
154
|
};
|
|
142
155
|
|
|
@@ -146,7 +159,6 @@ export async function generateTsAbi(
|
|
|
146
159
|
'import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";\n\n';
|
|
147
160
|
|
|
148
161
|
if (fs.existsSync(TARGET_FILE)) {
|
|
149
|
-
// Read and parse the existing file
|
|
150
162
|
const fileContent = fs.readFileSync(TARGET_FILE, "utf8");
|
|
151
163
|
// Extract the deployedContracts object using regex
|
|
152
164
|
const match = fileContent.match(
|
|
@@ -158,14 +170,11 @@ export async function generateTsAbi(
|
|
|
158
170
|
}
|
|
159
171
|
}
|
|
160
172
|
|
|
161
|
-
// Ensure the chainId exists
|
|
162
173
|
if (!deployedContractsObj[chainId]) {
|
|
163
174
|
deployedContractsObj[chainId] = {};
|
|
164
175
|
}
|
|
165
|
-
// Update or insert the contract entry
|
|
166
176
|
deployedContractsObj[chainId][contractName] = newContractEntry;
|
|
167
177
|
|
|
168
|
-
// Stringify the object for TypeScript output
|
|
169
178
|
const contractsString = JSON.stringify(deployedContractsObj, null, 2);
|
|
170
179
|
|
|
171
180
|
const output = `${fileHeader}const deployedContracts = ${contractsString} as const;\n\nexport default deployedContracts satisfies GenericContractsDeclaration;\n`;
|
|
@@ -2,8 +2,8 @@ import { config as dotenvConfig } from "dotenv";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import * as fs from "fs";
|
|
4
4
|
import { arbitrumNitro } from "../../../nextjs/utils/scaffold-stylus/chain";
|
|
5
|
-
import { DeploymentConfig, DeployOptions } from "./type";
|
|
6
|
-
import { getChain, getPrivateKey } from "./network";
|
|
5
|
+
import { DeploymentConfig, DeployOptions, DeploymentData } from "./type";
|
|
6
|
+
import { getAccountAddress, getChain, getPrivateKey } from "./network";
|
|
7
7
|
import { getContractNameFromCargoToml } from "./contract";
|
|
8
8
|
|
|
9
9
|
// Load environment variables from .env file
|
|
@@ -42,6 +42,7 @@ export function getDeploymentConfig(
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
return {
|
|
45
|
+
deployerAddress: getAccountAddress(deployOptions.network),
|
|
45
46
|
privateKey: getPrivateKey(deployOptions.network),
|
|
46
47
|
contractFolder: deployOptions.contract!,
|
|
47
48
|
contractName,
|
|
@@ -58,79 +59,202 @@ export function ensureDeploymentDirectory(deploymentDir: string): void {
|
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
|
-
* Save the deployed contract address to
|
|
62
|
+
* Save the deployed contract address to <chain.id>_latest.json in the deployment directory.
|
|
63
|
+
* If a latest file already exists, it gets renamed to include a timestamp.
|
|
62
64
|
* Updates or creates the file, using contractName as the key.
|
|
63
65
|
*/
|
|
64
|
-
export function
|
|
66
|
+
export function saveDeployment(
|
|
67
|
+
config: DeploymentConfig,
|
|
68
|
+
deploymentInfo: DeploymentData,
|
|
69
|
+
) {
|
|
65
70
|
try {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
const chainId = config.chain?.id || arbitrumNitro.id;
|
|
72
|
+
const networkPath = path.resolve(
|
|
73
|
+
config.deploymentDir,
|
|
74
|
+
`${chainId}_latest.json`,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Check if the latest file exists and contains the same contract name
|
|
78
|
+
let shouldCreateNewFile = false;
|
|
79
|
+
if (fs.existsSync(networkPath)) {
|
|
80
|
+
try {
|
|
81
|
+
const existingDeployments = JSON.parse(
|
|
82
|
+
fs.readFileSync(networkPath, "utf8"),
|
|
83
|
+
);
|
|
84
|
+
if (existingDeployments[config.contractName]) {
|
|
85
|
+
// Contract with same name already exists, create new file
|
|
86
|
+
shouldCreateNewFile = true;
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.warn(
|
|
90
|
+
`⚠️ Could not parse existing ${chainId}_latest.json, will overwrite. Error: ${e}`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// If we need to create a new file (contract name already exists), backup the current latest file
|
|
96
|
+
if (shouldCreateNewFile) {
|
|
97
|
+
const currentTimestamp = new Date().getTime();
|
|
98
|
+
const backupPath = networkPath.replace(
|
|
99
|
+
"_latest.json",
|
|
100
|
+
`_${currentTimestamp}.json`,
|
|
101
|
+
);
|
|
102
|
+
fs.renameSync(networkPath, backupPath);
|
|
103
|
+
console.log(`📦 Backed up previous deployment to ${backupPath}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Read existing deployments or start fresh
|
|
107
|
+
let deployments: Record<string, any> = {};
|
|
108
|
+
if (fs.existsSync(networkPath)) {
|
|
109
|
+
const content = fs.readFileSync(networkPath, "utf8");
|
|
70
110
|
try {
|
|
71
|
-
|
|
111
|
+
deployments = JSON.parse(content);
|
|
72
112
|
} catch (e) {
|
|
73
113
|
console.warn(
|
|
74
|
-
`⚠️ Could not parse existing
|
|
114
|
+
`⚠️ Could not parse existing ${chainId}_latest.json, will overwrite. Error: ${e}`,
|
|
75
115
|
);
|
|
76
116
|
}
|
|
77
117
|
}
|
|
78
118
|
|
|
79
|
-
// Save
|
|
80
|
-
|
|
81
|
-
address:
|
|
82
|
-
|
|
119
|
+
// Save with the new format
|
|
120
|
+
deployments[config.contractName] = {
|
|
121
|
+
address: deploymentInfo.address,
|
|
122
|
+
txHash: deploymentInfo.txHash,
|
|
123
|
+
contract: config.contractFolder,
|
|
83
124
|
};
|
|
84
125
|
|
|
85
|
-
fs.writeFileSync(
|
|
86
|
-
console.log(`💾 Saved deployed
|
|
126
|
+
fs.writeFileSync(networkPath, JSON.stringify(deployments, null, 2));
|
|
127
|
+
console.log(`💾 Saved deployed contract to ${networkPath}`);
|
|
87
128
|
} catch (e) {
|
|
88
|
-
console.error(`❌ Failed to save deployed
|
|
129
|
+
console.error(`❌ Failed to save deployed contract: ${e}`);
|
|
89
130
|
}
|
|
90
131
|
}
|
|
91
132
|
|
|
92
|
-
export function printDeployedAddresses(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
133
|
+
export function printDeployedAddresses(
|
|
134
|
+
deploymentDir: string,
|
|
135
|
+
chainId?: string,
|
|
136
|
+
): void {
|
|
137
|
+
// If chainId is provided, only look for that specific chain's deployment file
|
|
138
|
+
if (chainId) {
|
|
139
|
+
const networkPath = path.resolve(deploymentDir, `${chainId}_latest.json`);
|
|
140
|
+
if (!fs.existsSync(networkPath)) {
|
|
141
|
+
console.log(
|
|
142
|
+
`📦 No deployment file found for chain ${chainId} in ${deploymentDir}`,
|
|
143
|
+
);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const deployments = JSON.parse(fs.readFileSync(networkPath, "utf8"));
|
|
149
|
+
console.log(
|
|
150
|
+
`📦 Deployed contracts for chain ${chainId} (${networkPath}):`,
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
// Format the output to show contract name, address, and contract folder clearly
|
|
154
|
+
Object.entries(deployments).forEach(([contractName, contractData]) => {
|
|
155
|
+
const data = contractData as {
|
|
156
|
+
address: string;
|
|
157
|
+
txHash: string;
|
|
158
|
+
contract: string;
|
|
159
|
+
};
|
|
160
|
+
console.log(` ${contractName}:`);
|
|
161
|
+
console.log(` Address: ${data.address}`);
|
|
162
|
+
console.log(` Tx Hash: ${data.txHash}`);
|
|
163
|
+
console.log(` Contract: ${data.contract}`);
|
|
164
|
+
});
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.warn(`⚠️ Could not parse deployment file ${networkPath}: ${e}`);
|
|
167
|
+
}
|
|
168
|
+
return;
|
|
108
169
|
}
|
|
170
|
+
|
|
171
|
+
// If no chainId provided, look for all chain-specific deployment files
|
|
172
|
+
const files = fs.readdirSync(deploymentDir);
|
|
173
|
+
const deploymentFiles = files.filter((file) => file.endsWith("_latest.json"));
|
|
174
|
+
|
|
175
|
+
if (deploymentFiles.length === 0) {
|
|
176
|
+
console.log(`📦 No deployment files found in ${deploymentDir}`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
deploymentFiles.forEach((file) => {
|
|
181
|
+
const filePath = path.resolve(deploymentDir, file);
|
|
182
|
+
const currentChainId = file.replace("_latest.json", "");
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
const deployments = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
186
|
+
console.log(
|
|
187
|
+
`📦 Deployed contracts for chain ${currentChainId} (${filePath}):`,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// Format the output to show contract name, address, and contract folder clearly
|
|
191
|
+
Object.entries(deployments).forEach(([contractName, contractData]) => {
|
|
192
|
+
const data = contractData as {
|
|
193
|
+
address: string;
|
|
194
|
+
txHash: string;
|
|
195
|
+
contract: string;
|
|
196
|
+
};
|
|
197
|
+
console.log(` ${contractName}:`);
|
|
198
|
+
console.log(` Address: ${data.address}`);
|
|
199
|
+
console.log(` Contract: ${data.contract}`);
|
|
200
|
+
});
|
|
201
|
+
} catch (e) {
|
|
202
|
+
console.warn(`⚠️ Could not parse deployment file ${filePath}: ${e}`);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
109
205
|
}
|
|
110
206
|
|
|
111
207
|
/**
|
|
112
|
-
* Reads the deployed contract data from
|
|
208
|
+
* Reads the deployed contract data from chain-specific deployment files in the deployment directory.
|
|
113
209
|
* Returns an object with address and chainId for the given contractName, or undefined if not found.
|
|
114
210
|
*/
|
|
115
211
|
export function getContractDataFromDeployments(
|
|
116
212
|
deploymentDir: string,
|
|
117
213
|
contractName: string,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
214
|
+
chainId?: string,
|
|
215
|
+
): { address: string; txHash: string; chainId: string } | undefined {
|
|
216
|
+
// If chainId is provided, look for that specific chain's deployment file
|
|
217
|
+
if (chainId) {
|
|
218
|
+
const networkPath = path.resolve(deploymentDir, `${chainId}_latest.json`);
|
|
219
|
+
if (fs.existsSync(networkPath)) {
|
|
220
|
+
try {
|
|
221
|
+
const deployments = JSON.parse(fs.readFileSync(networkPath, "utf8"));
|
|
222
|
+
if (deployments[contractName]?.address) {
|
|
223
|
+
return {
|
|
224
|
+
address: deployments[contractName].address,
|
|
225
|
+
txHash: deployments[contractName].txHash,
|
|
226
|
+
chainId: chainId,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
} catch (e) {
|
|
230
|
+
console.warn(
|
|
231
|
+
`⚠️ Could not parse deployment file at ${networkPath}: ${e}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// If no chainId provided, search all deployment files
|
|
239
|
+
const files = fs.readdirSync(deploymentDir);
|
|
240
|
+
const deploymentFiles = files.filter((file) => file.endsWith("_latest.json"));
|
|
241
|
+
|
|
242
|
+
for (const file of deploymentFiles) {
|
|
243
|
+
const filePath = path.resolve(deploymentDir, file);
|
|
244
|
+
const currentChainId = file.replace("_latest.json", "");
|
|
121
245
|
try {
|
|
122
|
-
const
|
|
123
|
-
if (
|
|
124
|
-
return
|
|
125
|
-
address:
|
|
126
|
-
|
|
246
|
+
const deployments = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
247
|
+
if (deployments[contractName]?.address) {
|
|
248
|
+
return {
|
|
249
|
+
address: deployments[contractName].address,
|
|
250
|
+
txHash: deployments[contractName].txHash,
|
|
251
|
+
chainId: currentChainId,
|
|
127
252
|
};
|
|
128
253
|
}
|
|
129
254
|
} catch (e) {
|
|
130
|
-
console.warn(
|
|
131
|
-
`⚠️ Could not parse addresses.json at ${addressesPath}: ${e}`,
|
|
132
|
-
);
|
|
255
|
+
console.warn(`⚠️ Could not parse deployment file at ${filePath}: ${e}`);
|
|
133
256
|
}
|
|
134
257
|
}
|
|
258
|
+
|
|
135
259
|
return undefined;
|
|
136
260
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { arbitrum, arbitrumSepolia } from "viem/chains";
|
|
2
|
-
import { Chain } from "viem";
|
|
2
|
+
import { Address, Chain } from "viem";
|
|
3
3
|
import { arbitrumNitro } from "../../../nextjs/utils/scaffold-stylus/chain";
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import * as fs from "fs";
|
|
@@ -25,10 +25,8 @@ export const ALIASES: Record<string, string> = {
|
|
|
25
25
|
|
|
26
26
|
export function getChain(networkName: string): SupportedNetworkMinimal | null {
|
|
27
27
|
try {
|
|
28
|
-
// Normalize network name to lowercase for case-insensitive lookup
|
|
29
28
|
const actualNetworkName = ALIASES[networkName.toLowerCase()] || networkName;
|
|
30
29
|
|
|
31
|
-
// Find the chain in SUPPORTED_NETWORKS (case-insensitive)
|
|
32
30
|
const chainEntry = Object.entries(SUPPORTED_NETWORKS).find(
|
|
33
31
|
([key]) => key.toLowerCase() === actualNetworkName.toLowerCase(),
|
|
34
32
|
);
|
|
@@ -42,7 +40,6 @@ export function getChain(networkName: string): SupportedNetworkMinimal | null {
|
|
|
42
40
|
};
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
// If not found, show warning with all supported networks
|
|
46
43
|
const supportedNetworks = Object.keys(SUPPORTED_NETWORKS);
|
|
47
44
|
console.warn(
|
|
48
45
|
`⚠️ Network '${networkName}' is not supported. Supported networks: ${supportedNetworks.join(", ")}`,
|
|
@@ -59,9 +56,17 @@ export function getPrivateKey(networkName: string): string {
|
|
|
59
56
|
|
|
60
57
|
switch (actualNetworkName.toLowerCase()) {
|
|
61
58
|
case "arbitrum":
|
|
62
|
-
|
|
59
|
+
if (process.env["PRIVATE_KEY_MAINNET"]) {
|
|
60
|
+
return process.env["PRIVATE_KEY_MAINNET"];
|
|
61
|
+
} else {
|
|
62
|
+
throw new Error("PRIVATE_KEY_MAINNET is not set");
|
|
63
|
+
}
|
|
63
64
|
case "arbitrumsepolia":
|
|
64
|
-
|
|
65
|
+
if (process.env["PRIVATE_KEY_SEPOLIA"]) {
|
|
66
|
+
return process.env["PRIVATE_KEY_SEPOLIA"];
|
|
67
|
+
} else {
|
|
68
|
+
throw new Error("PRIVATE_KEY_SEPOLIA is not set");
|
|
69
|
+
}
|
|
65
70
|
default:
|
|
66
71
|
return (
|
|
67
72
|
process.env["PRIVATE_KEY"] ||
|
|
@@ -70,6 +75,21 @@ export function getPrivateKey(networkName: string): string {
|
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
|
|
78
|
+
export const getAccountAddress = (networkName: string): Address | undefined => {
|
|
79
|
+
const actualNetworkName = ALIASES[networkName.toLowerCase()] || networkName;
|
|
80
|
+
switch (actualNetworkName.toLowerCase()) {
|
|
81
|
+
case "arbitrum":
|
|
82
|
+
return process.env["ACCOUNT_ADDRESS_MAINNET"] as Address;
|
|
83
|
+
case "arbitrumsepolia":
|
|
84
|
+
return process.env["ACCOUNT_ADDRESS_SEPOLIA"] as Address;
|
|
85
|
+
default:
|
|
86
|
+
return (
|
|
87
|
+
(process.env["ACCOUNT_ADDRESS"] as Address) ||
|
|
88
|
+
"0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E"
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
73
93
|
function getRpcUrlFromChain(chain: Chain): string {
|
|
74
94
|
//Prefer user rpc url from env
|
|
75
95
|
switch (chain.id) {
|
|
@@ -109,4 +129,4 @@ function getAliasFromNetworkName(networkName: string): string {
|
|
|
109
129
|
Object.entries(ALIASES).find(([, alias]) => alias === networkName)?.[0] ||
|
|
110
130
|
networkName
|
|
111
131
|
);
|
|
112
|
-
}
|
|
132
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Address } from "viem";
|
|
2
|
+
|
|
1
3
|
interface BaseCommandOptions {
|
|
2
4
|
_: (string | number)[];
|
|
3
5
|
$0: string;
|
|
@@ -6,29 +8,29 @@ interface BaseCommandOptions {
|
|
|
6
8
|
|
|
7
9
|
export interface DeployCommandOptions
|
|
8
10
|
extends BaseCommandOptions,
|
|
9
|
-
DeployOptions {
|
|
10
|
-
all?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface AdditionalOptions {
|
|
14
|
-
isSingleCommand?: boolean;
|
|
15
|
-
shouldClearDeploymentDir?: boolean;
|
|
16
|
-
}
|
|
11
|
+
DeployOptions {}
|
|
17
12
|
|
|
18
13
|
export interface DeployOptions {
|
|
19
14
|
contract?: string;
|
|
20
15
|
name?: string;
|
|
16
|
+
constructorArgs?: string[];
|
|
21
17
|
network?: string;
|
|
22
18
|
estimateGas?: boolean;
|
|
23
19
|
maxFee?: string;
|
|
20
|
+
verify?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface DeploymentData {
|
|
24
|
+
address: Address;
|
|
25
|
+
txHash: string;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export interface DeploymentConfig {
|
|
29
|
+
deployerAddress: Address | undefined;
|
|
27
30
|
privateKey: string;
|
|
28
31
|
contractFolder: string;
|
|
29
32
|
contractName: string;
|
|
30
33
|
deploymentDir: string;
|
|
31
|
-
contractAddress?: string;
|
|
32
34
|
chain?: SupportedNetworkMinimal;
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -36,7 +38,8 @@ export interface ExportConfig {
|
|
|
36
38
|
contractFolder: string;
|
|
37
39
|
contractName: string;
|
|
38
40
|
deploymentDir: string;
|
|
39
|
-
contractAddress:
|
|
41
|
+
contractAddress: Address;
|
|
42
|
+
txHash: string;
|
|
40
43
|
chainId: string;
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -382,9 +382,9 @@ dependencies = [
|
|
|
382
382
|
|
|
383
383
|
[[package]]
|
|
384
384
|
name = "alloy-sol-macro"
|
|
385
|
-
version = "0.8.
|
|
385
|
+
version = "0.8.20"
|
|
386
386
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
387
|
-
checksum = "
|
|
387
|
+
checksum = "13f28f2131dc3a7b8e2cda882758ad4d5231ca26281b9861d4b18c700713e2da"
|
|
388
388
|
dependencies = [
|
|
389
389
|
"alloy-sol-macro-expander",
|
|
390
390
|
"alloy-sol-macro-input",
|
|
@@ -396,9 +396,9 @@ dependencies = [
|
|
|
396
396
|
|
|
397
397
|
[[package]]
|
|
398
398
|
name = "alloy-sol-macro-expander"
|
|
399
|
-
version = "0.8.
|
|
399
|
+
version = "0.8.20"
|
|
400
400
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
401
|
-
checksum = "
|
|
401
|
+
checksum = "1ee2da033256a3b27131c030933eab0460a709fbcc4d4bd57bf9a5650b2441c5"
|
|
402
402
|
dependencies = [
|
|
403
403
|
"alloy-sol-macro-input",
|
|
404
404
|
"const-hex",
|
|
@@ -414,14 +414,13 @@ dependencies = [
|
|
|
414
414
|
|
|
415
415
|
[[package]]
|
|
416
416
|
name = "alloy-sol-macro-input"
|
|
417
|
-
version = "0.8.
|
|
417
|
+
version = "0.8.20"
|
|
418
418
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
419
|
-
checksum = "
|
|
419
|
+
checksum = "4e9d9918b0abb632818bf27e2dfb86b209be8433baacf22100b190bbc0904bd4"
|
|
420
420
|
dependencies = [
|
|
421
421
|
"const-hex",
|
|
422
422
|
"dunce",
|
|
423
423
|
"heck",
|
|
424
|
-
"macro-string",
|
|
425
424
|
"proc-macro2",
|
|
426
425
|
"quote",
|
|
427
426
|
"syn 2.0.101",
|
|
@@ -2824,17 +2823,6 @@ dependencies = [
|
|
|
2824
2823
|
"hashbrown 0.15.3",
|
|
2825
2824
|
]
|
|
2826
2825
|
|
|
2827
|
-
[[package]]
|
|
2828
|
-
name = "macro-string"
|
|
2829
|
-
version = "0.1.4"
|
|
2830
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2831
|
-
checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3"
|
|
2832
|
-
dependencies = [
|
|
2833
|
-
"proc-macro2",
|
|
2834
|
-
"quote",
|
|
2835
|
-
"syn 2.0.101",
|
|
2836
|
-
]
|
|
2837
|
-
|
|
2838
2826
|
[[package]]
|
|
2839
2827
|
name = "md-5"
|
|
2840
2828
|
version = "0.10.6"
|
|
@@ -3076,6 +3064,34 @@ dependencies = [
|
|
|
3076
3064
|
"vcpkg",
|
|
3077
3065
|
]
|
|
3078
3066
|
|
|
3067
|
+
[[package]]
|
|
3068
|
+
name = "openzeppelin-stylus"
|
|
3069
|
+
version = "0.2.0"
|
|
3070
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3071
|
+
checksum = "4a5bdc0165c9dd0628a88cbeb8c059b59fdb301156364c6759d838cbd4a581a2"
|
|
3072
|
+
dependencies = [
|
|
3073
|
+
"alloy-primitives",
|
|
3074
|
+
"alloy-sol-macro",
|
|
3075
|
+
"alloy-sol-macro-expander",
|
|
3076
|
+
"alloy-sol-macro-input",
|
|
3077
|
+
"alloy-sol-types",
|
|
3078
|
+
"keccak-const",
|
|
3079
|
+
"openzeppelin-stylus-proc",
|
|
3080
|
+
"stylus-sdk",
|
|
3081
|
+
]
|
|
3082
|
+
|
|
3083
|
+
[[package]]
|
|
3084
|
+
name = "openzeppelin-stylus-proc"
|
|
3085
|
+
version = "0.2.2"
|
|
3086
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3087
|
+
checksum = "f592a114a2f3bbfb29303435064b4444ea3d9c4283b667f551a8543e8da8896f"
|
|
3088
|
+
dependencies = [
|
|
3089
|
+
"convert_case",
|
|
3090
|
+
"proc-macro2",
|
|
3091
|
+
"quote",
|
|
3092
|
+
"syn 2.0.101",
|
|
3093
|
+
]
|
|
3094
|
+
|
|
3079
3095
|
[[package]]
|
|
3080
3096
|
name = "option-ext"
|
|
3081
3097
|
version = "0.2.0"
|
|
@@ -5596,6 +5612,7 @@ dependencies = [
|
|
|
5596
5612
|
"ethers",
|
|
5597
5613
|
"eyre",
|
|
5598
5614
|
"hex",
|
|
5615
|
+
"openzeppelin-stylus",
|
|
5599
5616
|
"stylus-sdk",
|
|
5600
5617
|
"tokio",
|
|
5601
5618
|
]
|
|
@@ -13,6 +13,7 @@ alloy-primitives = "=0.8.20"
|
|
|
13
13
|
alloy-sol-types = "=0.8.20"
|
|
14
14
|
stylus-sdk = "0.9.0"
|
|
15
15
|
hex = { version = "0.4", default-features = false }
|
|
16
|
+
openzeppelin-stylus = "0.2.0"
|
|
16
17
|
|
|
17
18
|
[dev-dependencies]
|
|
18
19
|
alloy-primitives = { version = "=0.8.20", features = ["sha3-keccak"] }
|
|
@@ -24,7 +25,8 @@ dotenv = "0.15.0"
|
|
|
24
25
|
|
|
25
26
|
[features]
|
|
26
27
|
default = ["mini-alloc"]
|
|
27
|
-
|
|
28
|
+
# stylus-sdk/export-abi will be enabled automatically.
|
|
29
|
+
export-abi = ["openzeppelin-stylus/export-abi"]
|
|
28
30
|
debug = ["stylus-sdk/debug"]
|
|
29
31
|
mini-alloc = ["stylus-sdk/mini-alloc"]
|
|
30
32
|
|