Skip to content

Commit

Permalink
feat: deploy local, cleanup, frontend envs
Browse files Browse the repository at this point in the history
  • Loading branch information
wsdt committed Aug 9, 2024
1 parent cc79727 commit bc1a70f
Show file tree
Hide file tree
Showing 16 changed files with 3,406 additions and 2,148 deletions.
9 changes: 5 additions & 4 deletions contracts/.env-example
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
HYBRID_ACCOUNT=
ENTRY_POINT=
ENTRY_POINT=0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789
TOKEN_PRICE_CONTRACT=
HC_HELPER_ADDR=
BACKEND_URL=
HC_HELPER_ADDR=0x587a06089ed54101dd6d9A8ecDe1d146f97Af6B8 # boba sepolia system wide helper address
BACKEND_URL=https://aa-hc-example.onrender.com
# 0x...
PRIVATE_KEY=
RPC_URL=
RPC_URL=https://sepolia.boba.network
CLIENT_ADDR=
BUNDLER_RPC=

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

49 changes: 1 addition & 48 deletions contracts/script/deploy-local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Readable } from "stream";
import * as dotenv from "dotenv";
import { ethers } from "ethers";
import { getLocalIpAddress } from "./utils";
import {execPromise} from './utils'

dotenv.config();

Expand Down Expand Up @@ -37,54 +38,6 @@ const ha1Owner = ethers.getAddress(
const ha1Privkey =
"0x7c0c629efc797f8c5f658919b7efbae01275470d59d03fdeb0fca1e6bd11d7fa";

const execPromise = (
command: string,
inputs: string[] = [],
cwd: ProcessEnvOptions["cwd"] = undefined,
env?: NodeJS.ProcessEnv
): Promise<string> => {
return new Promise((resolve, reject) => {
const [cmd, ...args] = command.split(" ");
const child = spawn(cmd, args, {
shell: true,
stdio: ["pipe", "pipe", "pipe"],
cwd,
env,
});

let stdout = "";
let stderr = "";

child.stdout.on("data", (data) => {
stdout += data.toString();
console.log(data.toString());
});

child.stderr.on("data", (data) => {
stderr += data.toString();
console.error(data.toString());
});

const stdinStream = new Readable({
read() {
inputs.forEach((input) => {
this.push(input + "\n");
});
this.push(null);
},
});

stdinStream.pipe(child.stdin);

child.on("close", (code) => {
if (code !== 0) {
reject(new Error(`Command failed with exit code ${code}`));
} else {
resolve(stdout);
}
});
});
};

const updateEnvVariable = (key: string, value: string, envPath: string) => {
let envFile = fs.readFileSync(envPath, "utf8");
Expand Down
93 changes: 33 additions & 60 deletions contracts/script/deploy-stack.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,10 @@
import { exec, spawn } from "child_process";
import * as fs from "fs";
import * as dotenv from "dotenv";
import * as path from "path";
import { Readable } from "stream";
import {execPromise, updateEnvVariable} from './utils'

dotenv.config();

const execPromise = (
command: string,
inputs: string[] = []
): Promise<string> => {
return new Promise((resolve, reject) => {
const [cmd, ...args] = command.split(" ");
const child = spawn(cmd, args, { stdio: ["pipe", "pipe", "pipe"] });

let stdout = "";
let stderr = "";

child.stdout.on("data", (data) => {
stdout += data.toString();
console.log(data.toString());
});

child.stderr.on("data", (data) => {
stderr += data.toString();
console.error(data.toString());
});

const stdinStream = new Readable({
read() {
inputs.forEach((input) => {
this.push(input + "\n");
});
this.push(null);
},
});

stdinStream.pipe(child.stdin);

child.on("close", (code) => {
if (code !== 0) {
reject(new Error(`Command failed with exit code ${code}`));
} else {
resolve(stdout);
}
});
});
};

const updateEnvVariable = (key: string, value: string) => {
const envPath = path.resolve(__dirname, "../.env");
let envFile = fs.readFileSync(envPath, "utf8");
const regex = new RegExp(`^${key}=.*`, "m");
if (regex.test(envFile)) {
envFile = envFile.replace(regex, `${key}=${value}`);
} else {
envFile += `\n${key}=${value}`;
}
fs.writeFileSync(envPath, envFile);
dotenv.config();
};

const readHybridAccountAddress = () => {
const jsonPath = path.resolve(
__dirname,
Expand Down Expand Up @@ -111,8 +55,13 @@ async function main() {
console.log("Deploying TokenPrice contract...");
deleteIgnitionDeployments();
const ignitionOutput = await execPromise(
"npx hardhat ignition deploy ./ignition/modules/TokenPrice.ts --network boba_sepolia",
["y"]
"npx hardhat ignition deploy ./ignition/modules/TokenPrice.ts --network boba_sepolia",
["y"],
path.resolve(__dirname, "../"),
{
...process.env,
HYBRID_ACCOUNT: hybridAccountAddress,
}
);

// Extract the TokenPrice contract address from output
Expand Down Expand Up @@ -140,11 +89,35 @@ async function main() {

// Step 5: Run production push script
console.log("Running production push script...");
const {HC_HELPER_ADDR, PRIVATE_KEY, RPC_URL, BACKEND_URL} = process.env
console.log('HCH = ', HC_HELPER_ADDR)
console.log('HA = ', hybridAccountAddress);
console.log('TTP = ', tokenPriceAddress);
console.log('BE = ', BACKEND_URL)
console.log('RPC_URL = ', RPC_URL)
console.log('-------------------')

if (!BACKEND_URL) {
console.warn('BACKEND_URL not defined. Using default public endpoint https://aa-hc-example.onrender.com')
}
if (!HC_HELPER_ADDR || !hybridAccountAddress || !tokenPriceAddress) {
throw Error("Configuration missing")
}

await execPromise(
`node script/pushProduction.js ${process.env.RPC_URL} ${process.env.PRIVATE_KEY} ${process.env.HC_HELPER_ADDR} ${hybridAccountAddress} ${tokenPriceAddress} ${process.env.BACKEND_URL}`
`node script/pushProduction.js ${RPC_URL} ${PRIVATE_KEY} ${HC_HELPER_ADDR} ${hybridAccountAddress} ${tokenPriceAddress} ${BACKEND_URL}`
);

console.log("Deployment process completed successfully!");


// save relevant envs to frontend
console.log('Saving relevant env variables to frontend. The Boba sepolia config will be used if some variables are missing.')
updateEnvVariable("VITE_ENTRY_POINT", process.env.ENTRYPOINT ?? '0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789', '../../frontend/.env');
updateEnvVariable("VITE_PRIVATE_KEY", PRIVATE_KEY!, '../../frontend/.env');
updateEnvVariable("VITE_SMART_CONTRACT", tokenPriceAddress, '../../frontend/.env');
updateEnvVariable("VITE_RPC_PROVIDER", RPC_URL ?? 'https://sepolia.boba.network', '../../frontend/.env');

} catch (error) {
console.error("An error occurred during the deployment process:", error);
}
Expand Down
3 changes: 2 additions & 1 deletion contracts/script/pushProduction.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ const PRIVATE_KEY = args[1];
const HC_HELPER_ADDR = args[2];
const HYBRID_ACCOUNT = args[3];
const TOKEN_PRICE_ACCOUNT_ADDR = args[4];
const BACKEND_URL = args[5];
const BACKEND_URL = args[5] ?? 'https://aa-hc-example.onrender.com'; // use public backend by default

console.log('HCH = ', HC_HELPER_ADDR)
console.log('HA = ', HYBRID_ACCOUNT);
console.log('TTP = ', TOKEN_PRICE_ACCOUNT_ADDR);
console.log('BE = ', BACKEND_URL)
console.log('RPC_URL = ', RPC_URL)

const signer = new ethers.Wallet(PRIVATE_KEY, new ethers.JsonRpcProvider(RPC_URL));

Expand Down
112 changes: 27 additions & 85 deletions contracts/script/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as os from "os";
import * as fs from "fs";
import * as path from "path";
import { ProcessEnvOptions, spawn } from "child_process";
import { Readable } from "stream";
import * as fs from "fs";
import * as dotenv from "dotenv";
import * as path from "path";

export const getLocalIpAddress = () => {
const networkInterfaces = os.networkInterfaces();
Expand All @@ -17,15 +18,34 @@ export const getLocalIpAddress = () => {
throw new Error("No Local IP-Address found");
};

const execPromise = (
command: string,
inputs: string[] = [],
cwd: ProcessEnvOptions["cwd"] = undefined,
env?: NodeJS.ProcessEnv

export const updateEnvVariable = (key: string, value: string, customEnvPath?: string) => {
const envPath = path.resolve(__dirname, customEnvPath ?? "../.env")
if (!fs.existsSync(envPath)) {
// create empty .env file if not yet created
fs.closeSync(fs.openSync(envPath, 'w'));
}
let envFile = fs.readFileSync(envPath, "utf8");
const regex = new RegExp(`^${key}=.*`, "m");
if (regex.test(envFile)) {
envFile = envFile.replace(regex, `${key}=${value}`);
} else {
envFile += `\n${key}=${value}`;
}
fs.writeFileSync(envPath, envFile);
dotenv.config();
};

export const execPromise = (
command: string,
inputs: string[] = [],
cwd: ProcessEnvOptions["cwd"] = undefined,
env?: NodeJS.ProcessEnv
): Promise<string> => {
return new Promise((resolve, reject) => {
const [cmd, ...args] = command.split(" ");
const child = spawn(cmd, args, {
shell: true,
stdio: ["pipe", "pipe", "pipe"],
cwd,
env,
Expand Down Expand Up @@ -64,81 +84,3 @@ const execPromise = (
});
});
};

const updateEnvVariable = (key: string, value: string) => {
const envPath = path.resolve(__dirname, "../.env");
let envFile = fs.readFileSync(envPath, "utf8");
const regex = new RegExp(`^${key}=.*`, "m");
if (regex.test(envFile)) {
envFile = envFile.replace(regex, `${key}=${value}`);
} else {
envFile += `\n${key}=${value}`;
}
fs.writeFileSync(envPath, envFile);
};

const parseLocalDeployAddresses = () => {
const jsonPath = path.resolve(
__dirname,
"../broadcast/LocalDeploy.s.sol/901/run-latest.json"
);

try {
const data = fs.readFileSync(jsonPath, "utf8");
const jsonData = JSON.parse(data);

const contracts: { contractName: string; address: string }[] =
jsonData.transactions.map((transaction: any) => ({
contractName: transaction.contractName ?? "",
address: transaction.contractAddress ?? "",
}));

const hybridAccount = jsonData.transactions
.map((transaction: any) => {
if (
transaction.contractName === "HybridAccountFactory" &&
transaction.function === "createAccount(address,uint256)"
) {
return {
contractName: "HybridAccount",
address: transaction.additionalContracts[0].address,
};
}
})
.filter((ha: any) => ha); // filter out undefined values

contracts.push(...hybridAccount);

console.log("Parsed JSON data:", contracts);
return contracts;
} catch (err) {
console.error("Error reading or parsing the file:", err);
}
};

const readHybridAccountAddress = () => {
const jsonPath = path.resolve(
__dirname,
"../broadcast/deploy-hybrid-account.s.sol/28882/run-latest.json"
);
const jsonContent = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
const transaction = jsonContent.transactions.find(
(tx: any) => tx.transactionType === "CREATE"
);
if (!transaction) {
throw new Error("CREATE transaction not found in the JSON file");
}
return transaction.contractAddress;
};

const deleteIgnitionDeployments = () => {
const deploymentsPath = path.resolve(__dirname, "../ignition/deployments");
if (fs.existsSync(deploymentsPath)) {
fs.rmSync(deploymentsPath, { recursive: true, force: true });
console.log("Ignition deployments folder deleted.");
} else {
console.log(
"Ignition deployments folder does not exist. Skipping deletion."
);
}
};
4 changes: 2 additions & 2 deletions frontend/.env-template
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VITE_ENTRY_POINT=
VITE_ENTRY_POINT=0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789
VITE_PRIVATE_KEY=
VITE_SMART_CONTRACT=
VITE_RPC_PROVIDER=
VITE_RPC_PROVIDER=https://sepolia.boba.network
Loading

0 comments on commit bc1a70f

Please sign in to comment.