Skip to content

feat(scripting): add CLI runner, script harness, and examples#691

Open
yahgwai wants to merge 83 commits intomainfrom
feat/zod-scripting
Open

feat(scripting): add CLI runner, script harness, and examples#691
yahgwai wants to merge 83 commits intomainfrom
feat/zod-scripting

Conversation

@yahgwai
Copy link
Copy Markdown
Contributor

@yahgwai yahgwai commented Apr 8, 2026

Summary

Extends the zod schema (#690) work with some scripting tools

  • Adds runScript boilerplate for quickly writing schema enhanced scripts that use the sdk
  • Add a CLI for all current SDK functions, so that any SDK function can be invoked from the command line. eg:
npx tsx src/scripting/cli.ts getDefaultSequencerInboxMaxTimeVariation '{"parentChainId": 1}'
  • Adds example scripts for some common workflows (createRollup, deployNewChain, transferOwnership, etc.). These are just example right now, but we'll soon extend the CLI with more general usage scripts, like deployNewChain

Not included for now

  • Additional parsing libs. Now that we have zod schemas which will parse json, we can use existing tooling to convert yaml, env vars or cli args to json and than parse with the same schema giving scripts more options of what they expose to users.
  • Describe() - we can add documentation to the schemas to give consumers and idea of what values to put into the params. Those descriptions can be accessed via a dry-run/help command or zod can be converted into json schemas to directly expose the documentation.
  • Documentation and readme. Three sets of documentation is required: one for sdk maintainers, one for script writers and one for users of the cli.
  • Extending the CLI with some standard useful scripts to be used by SRE/other consumers

yahgwai added 27 commits March 19, 2026 13:20
Prepare token bridge deployment transactions without requiring an orbit
chain RPC. enqueueTokenBridgeDeployment encodes the createTokenBridge
call with caller-provided gas params. enqueueSetWethGateway encodes the
setGateways call through UpgradeExecutor with explicit retryable costs.
- Rename maxFeePerGas to maxGasPrice in enqueueSetWethGateway for
  consistency with enqueueTokenBridgeDeployment and the constant name
- Nest rollup/rollupOwner in params object to match existing
  createTokenBridgePrepareTransactionRequest pattern
- Update idempotency comment to explain parent-chain-only check rationale
  and that failed retryables should be manually redeemed
- Restore gas override comments from reference implementation
- Replace duplicate deposit test with calldata verification test for
  enqueueSetWethGateway
…red ABI

- Rename enqueueTokenBridgeDeployment to
  enqueueTokenBridgePrepareTransactionRequest
- Rename enqueueSetWethGateway to
  enqueueSetWethGatewayPrepareTransactionRequest
- Extract parentChainGatewayRouterAbi to src/contracts/GatewayRouter.ts,
  replacing inline copies in both enqueue and existing set weth gateway files
…tion

- Split maxSubmissionFee into maxSubmissionCostForFactory and
  maxSubmissionCostForContracts to match existing retryable fee formula
- Update retryable fee calculation to sum both submission costs
- Rename enqueueSetWethGateway* to enqueueTokenBridgePrepareSetWethGateway*
  to match createTokenBridgePrepareSetWethGateway* naming convention
- Remove CR comments
Fixes vitest type checker failure caused by dynamic import syntax.
Extract getFactoryDeploymentDataSize and getContractsDeploymentData from
the existing estimation functions so that the enqueue variants can reuse
the same data-size logic for calculating retryable submission fees.
Replicates the SDK's estimateSubmissionFee logic: calls the Inbox's
calculateRetryableSubmissionFee on the parent chain with the current
base fee, then applies a 300% safety buffer matching the SDK default.
…tions

The enqueue functions now estimate maxSubmissionCost from parent chain
state using the shared data-size helpers and the Inbox's
calculateRetryableSubmissionFee, matching the approach used by the
create* variants via the SDK. Callers no longer need to provide
maxSubmissionCostForFactory, maxSubmissionCostForContracts, or
maxSubmissionCost.
The contracts deployment (7+ contracts + initialization) needs more gas
than the factory deployment (single contract creation).
Instead of using a hardcoded default, read gasLimitForL2FactoryDeployment
from the TokenBridgeCreator contract. The caller can still override via
the maxGasForFactory parameter.
Replace the separate enqueue* and create* prepare functions with a single
implementation that estimates retryable gas from parent chain state and
does not require an orbit chain connection.

The createTokenBridge orchestrator now calls registerNewNetwork explicitly
before waiting for retryables, since the prepare functions no longer do
this internally.
Add zod v4 validation schemas and transform functions for all SDK
operations. Includes shared primitives (address, hex, bigint schemas),
per-function schema/transform pairs, and viem client factory helpers.
Add runScript/runCli harness for executing validated SDK operations from
the command line. Includes CLI command registry wiring all schemas to
their SDK functions, and example scripts for common workflows.
@yahgwai yahgwai closed this Apr 8, 2026
yahgwai added 2 commits April 8, 2026 14:06
Abitype's peer dep on zod ^3 caused pnpm to keep zod@3.22.4 in the tree,
creating non-portable abitype resolution paths that TypeScript couldn't
name in .d.ts output.
yahgwai added 11 commits April 16, 2026 16:31
…forms

cli.ts now uses cmd(schema, fn) directly since schemas have transforms
baked in. schemaCoverage.ts mocks updated for all connection transforms.
…t type

Replace the inline `typeof import(...)` form with a regular named import.
Matches the style used by the sibling schemas in the same file and keeps
the import list in one place. No behavior change -- both forms produce a
type-only reference that TypeScript erases.
The schema coverage harness was sitting on this branch with no consumer
-- its only users (the schemaCoverage.unit.test.ts tests) live on
feat/schema-coverage. Remove it here so this branch doesn't carry dead
test infrastructure. The harness is being re-introduced on
feat/schema-coverage alongside the tests that use it.
…hema

The baked-in schema transforms from feat/zod-schema made
prepareChainConfigParamsSchema emit a Parameters<> tuple, which leaked
when composed via .extend() into the createRollup and deployNewChain
examples. Split it into prepareChainConfigParamsBaseSchema (plain
validation, composable) and prepareChainConfigParamsSchema (transformed,
CLI-ready). Examples now embed the Base variant and call
prepareChainConfig directly, matching the pre-transform shape.

Also repair the other two examples that still referenced the removed
getValidatorsTransform / setAnyTrustFastConfirmerTransform exports: the
schemas bake those transforms in now, so the examples just pass the
schemas straight to runScript.

Plus thread findChain(parentChainId) through toPublicClient /
toWalletClient calls in the two complex examples, so the resulting viem
clients carry an explicit chain.
…tion

Replace regex-based hex and address validators with viem's isHex and
isAddress. isAddress does EIP-55 checksum validation on mixed-case
addresses, catching a class of typo that the regex silently passed.
Same module viem is already a dependency of the SDK -- no new deps.
Removed vite, flatted, picomatch, brace-expansion, and yaml from
pnpm.overrides. Tested by removing them and running pnpm install +
pnpm audit-ci -- the natural version resolution satisfies the former
override floor in every case, and audit-ci still passes. Kept tmp
(active CVE) and zod (prevents a v3/v4 dual install via abitype).
…sage

process.exit is typed as never but tests mock it, so execution fell
through into JSON.parse/async IIFE, producing spurious stderr output.
Return after each exit/handleError call so control actually stops.
Also align runScript's missing-arg message with runCli's Usage format.
yahgwai added 17 commits April 22, 2026 15:17
The SDK function isTokenBridgeDeployed was removed as unused in the
merge from feat/enqueue-token-bridge-deployment. Clean up the scripting
references that depended on it:

- delete src/scripting/schemas/isTokenBridgeDeployed.ts
- drop the re-export from src/scripting/schemas/index.ts
- drop the type-level assertion in schemas.type.test.ts

Users wanting the same check can call
createTokenBridgeFetchTokenBridgeContracts and test the returned
router/gateway addresses for the zero address.
Follow-up to removing the isTokenBridgeDeployed SDK function. Drop the
schema import, SDK import, and cmd() wiring for the CLI command.
The coverage test framework derives test values from the schema's regex
patterns. Stripping the regex in favor of bare refine() left the generator
falling back to 'string_0', which fails address/hex validation. Layer the
viem checks on top of the regex so both the generator and runtime
validation work.
The regex layer was subsumed by viem's isHex/isAddress and was only
retained to feed the schema coverage test generator. Drop it here;
the coverage generator in feat/schema-coverage will need to learn
about the address/hex formats directly (follow-up on that branch).
Replace the regex with viem's isHex + size(v) === 32. Matches the
style of hexSchema / addressSchema (refine-backed, no regex).
Coverage generator follow-up lands on feat/schema-coverage.
Replace the regex with isHex + v.length === 66 (0x prefix plus 64 hex
chars). Matches the style of hexSchema / addressSchema. Coverage
generator follow-up lands on feat/schema-coverage.

Supersedes the earlier isHex + size attempt; viem's size() rounds
odd-length hex up via Math.ceil, so it couldn't strictly enforce
length. An explicit length check is accurate.
Base automatically changed from feat/zod-schema to main April 22, 2026 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants