diff --git a/packages/cli/src/write-script/render-ethers.ts b/packages/cli/src/write-script/render-ethers.ts index 532bc25d7..aeadb9644 100644 --- a/packages/cli/src/write-script/render-ethers.ts +++ b/packages/cli/src/write-script/render-ethers.ts @@ -1,6 +1,12 @@ import { EOL } from 'node:os'; import { Transform } from 'node:stream'; +/** + * This script is used to deploy contracts using Ethers.js. + * It outputs a JS script that can be used to deploy contracts and execute transactions. + * Note: Make sure you add `.js` extension to the output file. + */ + import type { DumpLine, DumpRenderer } from './types'; const header = `/* eslint-disable */ diff --git a/packages/cli/src/write-script/render-foundry.ts b/packages/cli/src/write-script/render-foundry.ts new file mode 100644 index 000000000..cd750560d --- /dev/null +++ b/packages/cli/src/write-script/render-foundry.ts @@ -0,0 +1,75 @@ +import { EOL } from 'node:os'; +import { Transform } from 'node:stream'; + +/** + * This script is used to deploy contracts using Foundry Cast. + * It outputs a bash script that can be used to deploy contracts and execute transactions. + * Note: Make sure you add `.sh` extension to the output file. + */ + +const header = `#!/bin/bash + +# Set your environment variables +# Set your environment variables +# export PRIVATE_KEY= +# export RPC_URL= + +# Start processing transactions +`; + +const footer = ` +echo "Transactions complete." +`; + +export const createRenderer = () => + new Transform({ + objectMode: true, + construct(cb) { + this.push(header); // Bash script header + return cb(); + }, + transform(line, _, cb) { + const title = `[${line.type}.${line.label}]`; + + if (!line.result) { + // Logging non-transaction steps + this.push(`# ${' '.repeat(line.depth)}${title}${EOL}`); + } + + for (const { to, input, value } of line.txns) { + // Start building the `cast send` command + let command = 'cast send'; + + // Add `--to` if present (for non-deployment transactions) + if (to) { + command += `--to ${to}`; + } + + // Add `--value` if a value is specified + if (value) { + command += ` --value ${value}`; + } + + // Add private key and RPC URL from environment variables + command += ' --private-key $PRIVATE_KEY --rpc-url $RPC_URL'; + + if (!to) { + command += ' --create'; + } + + // Add calldata + command += ` ${input}`; + + // Log the title and command + const indent = ' '.repeat(line.depth); + this.push(`${indent}echo "Executing: ${title}"${EOL}`); + this.push(`${indent}${command}${EOL}${EOL}`); + } + + return cb(); + }, + flush(cb) { + this.push(footer); // Bash script footer + return cb(); + }, + }); diff --git a/packages/cli/src/write-script/write.ts b/packages/cli/src/write-script/write.ts index 88605f72e..4ba1c34da 100644 --- a/packages/cli/src/write-script/write.ts +++ b/packages/cli/src/write-script/write.ts @@ -6,7 +6,7 @@ import * as viem from 'viem'; import { createStepsStream } from './stream-steps'; import { DumpRenderer } from './types'; -export const WRITE_SCRIPT_FORMATS = ['json', 'ethers'] as const; +export const WRITE_SCRIPT_FORMATS = ['json', 'ethers', 'foundry'] as const; export type WriteScriptFormat = (typeof WRITE_SCRIPT_FORMATS)[number];