@openzeppelin/rwa-wizard-cli
v0.1.1
Published
CLI tool for generating RWA token projects. Interactive wizard and headless JSON config modes with file tree or ZIP output.
Readme
@openzeppelin/rwa-wizard-cli
CLI tool for generating RWA (Real World Asset) token projects based on the T-REX / ERC-3643 standard. Supports both an interactive step-by-step wizard and headless JSON config mode, with output as a file tree or ZIP archive.
Currently targets Stellar/Soroban. The architecture supports adding new chain generators (e.g. EVM/Solidity) without changing the CLI itself.
Installation
npm install -g @openzeppelin/rwa-wizard-cliOr run directly with npx:
npx @openzeppelin/rwa-wizard-cli generateRequires Node.js >= 20.0.0.
Quick Start
Interactive Wizard
Run without a config file to launch the step-by-step wizard:
rwa-wizard generateThe wizard walks through six steps matching the RWA Wizard web UI:
- Asset Configuration — token name, symbol, decimals, initial supply, Document Manager toggle
- Identity Configuration — claim topics and trusted issuers
- Compliance Modules — select and assign modules to compliance hooks
- Roles & Access Control — ownership model (single-owner / multi-sig / DAO) and operator roles
- Deployment Target — preset network (e.g. testnet) or custom RPC / explorer URLs
- Review & Generate — summary of all contracts to be generated, confirm, choose output format
After generation, you can optionally export the configuration as a JSON file for future headless runs.
Headless Mode
Pass a JSON config file to skip the wizard entirely:
# Generate as a file tree
rwa-wizard generate -c config.json -o ./my-rwa-project
# Generate as a ZIP archive
rwa-wizard generate -c config.json -o my-rwa-project.zip --zip
# Dev/testnet identity scaffolding (Stellar generator today; not for production)
rwa-wizard generate -c config.json -o ./my-rwa-project --include-identity-support --chain stellarCommands
generate
Generate an RWA token project.
rwa-wizard generate [options]| Option | Description | Default |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | --------- |
| -c, --config <path> | JSON config file (headless mode). Omit for interactive wizard. | — |
| -o, --output <path> | Output directory (file tree) or file path (ZIP). | . |
| --zip | Output as a ZIP archive instead of a file tree. | false |
| --allow-under-review-modules | Allow compliance modules marked under review upstream. Not for production. | false |
| --include-identity-support | Include optional dev/testnet identity-onboarding scaffolding when supported by the selected chain generator. Not for production. | false |
| --chain <name> | Target chain. | stellar |
validate
Validate a config file without generating any output.
rwa-wizard validate -c config.json| Option | Description | Default |
| ------------------------------ | ------------------------------------------------------------------------------ | --------- |
| -c, --config <path> | JSON config file to validate. (required) | — |
| --allow-under-review-modules | Allow compliance modules marked under review upstream. Not for production. | false |
| --chain <name> | Target chain. | stellar |
modules
List available compliance modules for a chain.
rwa-wizard modules
rwa-wizard modules --chain stellar| Option | Description | Default |
| ---------------- | ------------- | --------- |
| --chain <name> | Target chain. | stellar |
Configuration Schema
The config file follows the RWAConfig type from @openzeppelin/rwa-config. Here is a full example:
{
"token": {
"name": "My RWA Token",
"symbol": "MRWA",
"decimals": 8,
"initialSupply": "1000000000",
"administrativeControls": {
"burnable": true,
"mintable": true,
"pausable": true
},
"documentManager": { "enabled": true }
},
"identityVerification": {
"claimTopics": [{ "id": 1, "name": "KYC" }],
"trustedIssuers": [{ "address": "GCEXAMPLEISSUER1", "claimTopics": [1] }],
"controls": {
"addressFreezing": true,
"partialTokenFreezing": false,
"recovery": false,
"forcedTransfers": false
}
},
"compliance": {
"modules": []
},
"accessControl": {
"ownership": {
"type": "single-owner",
"ownerAddress": "GCEXAMPLEOWNER"
},
"roles": [{ "name": "Manager", "symbol": "manager", "addresses": ["GCMGR1"] }]
},
"deployment": {
"target": {
"kind": "preset",
"ecosystem": "stellar",
"networkId": "stellar-testnet"
}
}
}See examples/stellar-basic.json for a ready-to-use example.
Config Sections
| Section | Key Fields |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| token | name, symbol, decimals, initialSupply?, administrativeControls (burnable/mintable/pausable), documentManager.enabled |
| identityVerification | claimTopics[] (id + name), trustedIssuers[] (address + claimTopics), controls (addressFreezing/partialTokenFreezing/recovery/forcedTransfers) |
| compliance | modules[] — each with moduleId and optional module-specific config; hooks are auto-derived from the registry |
| accessControl | ownership (type + address), roles[] (name, symbol?, addresses) |
| deployment | target — either { kind: 'preset', ecosystem, networkId } or { kind: 'custom', ecosystem, rpcUrl, explorerUrl?, label? }, plus optional sourceAccount |
Ownership Models
| Type | Address Field |
| -------------- | -------------- |
| single-owner | ownerAddress |
| multi-sig | address |
| dao | address |
Generated Output
The generated project contains a complete, ready-to-build Stellar/Soroban RWA token system:
my-rwa-project/
├── contracts/
│ ├── rwa-token/ # RWA Token (FungibleToken + AccessControl + optional DocumentManager)
│ ├── compliance/ # Compliance (hook dispatch + token binding)
│ ├── identity-verifier/ # Identity Verifier (claim-based verification)
│ ├── claim-topics-issuers/ # Claim Topics & Issuers (trusted issuer registry)
│ ├── identity-registry-storage/ # Identity Registry Storage (identity data)
│ └── modules/ # Compliance modules (if any selected)
├── scripts/
│ ├── build.sh # Compile all contracts
│ └── deploy.sh # Deploy + configure (correct dependency order)
├── config.json # Serialized wizard config (consumed by scripts)
├── Cargo.toml # Workspace manifest
└── README.md # Setup instructions + architecture overviewAll 5 core contracts are always generated. Compliance module contracts are added based on your selection.
When the selected chain generator supports it, --include-identity-support adds development and testnet-only example onboarding scaffolding alongside the core project. It is meant for local demos, automated testnet flows, and e2e validation — not as a production KYC or holder-onboarding stack.
On Stellar today this emits upstream example claim-issuer and identity contracts plus a sign-claim helper tool. When token.initialSupply is set on a testnet target, the export also includes scripts/bootstrap-demo-mint.sh to onboard Admin and mint after ./scripts/deploy.sh (demo-only). Production deployments should use your own claim issuers and real holder identity onboarding instead.
Deploying with split admin/manager roles
Generated scripts/deploy.sh supports separate deploy signers when the configured admin and manager addresses differ. On Stellar, set distinct Stellar CLI identities:
export SOURCE_ACCOUNT=deployer
export ADMIN_SOURCE_ACCOUNT=admin-identity
export MANAGER_SOURCE_ACCOUNT=manager-identity
./scripts/deploy.shWhen admin and manager resolve to the same address, SOURCE_ACCOUNT is used for both.
Architecture
The CLI is built on a generator adapter pattern that decouples the interactive flow from chain-specific code generation:
┌─────────────────┐ ┌───────────────────┐ ┌─────────────────────────┐
│ CLI Commands │────▶│ Generator Adapter │────▶│ @openzeppelin/codegen-* │
│ (commander) │ │ (registry) │ │ (chain-specific) │
└─────────────────┘ └───────────────────┘ └─────────────────────────┘
│
▼
┌──────────────────┐
│ Interactive │
│ Wizard │
│ (@clack/prompts) │
└──────────────────┘GeneratorAdapter— interface that each chain generator implements (generate,validate,generateZip,getAvailableModules,hints)ChainHints— chain-specific metadata (address placeholders, validation limits, network options) that the wizard uses to stay chain-agnosticRWAConfig— shared configuration type from@openzeppelin/rwa-config, describing what the user wants without prescribing how
Adding a new chain requires implementing GeneratorAdapter and calling registerGenerator() — no wizard or command code changes needed.
Development
Setup
# From the monorepo root
pnpm install
pnpm --filter @openzeppelin/rwa-wizard-cli buildRun Locally
# Run the built binary
node packages/cli/dist/index.mjs generate
# Watch mode (rebuilds on save)
pnpm --filter @openzeppelin/rwa-wizard-cli dev
# Then in another terminal:
node packages/cli/dist/index.mjs generate -c packages/cli/examples/stellar-basic.json -o /tmp/testTests
# Run all tests (130+ tests across 16 files)
pnpm --filter @openzeppelin/rwa-wizard-cli test
# Watch mode
pnpm --filter @openzeppelin/rwa-wizard-cli test:watch
# With coverage
pnpm --filter @openzeppelin/rwa-wizard-cli test:coverageLint & Format
pnpm --filter @openzeppelin/rwa-wizard-cli lint
pnpm --filter @openzeppelin/rwa-wizard-cli format:checkDependencies
| Package | Purpose |
| ----------------------------------- | ------------------------------------------------------- |
| commander | Command parsing and option handling |
| @clack/prompts | Interactive step-by-step prompts |
| picocolors | Terminal color output |
| @openzeppelin/codegen-core | File tree assembly, ZIP packaging, validation framework |
| @openzeppelin/codegen-rwa-stellar | Stellar/Soroban RWA contract generator |
| @openzeppelin/rwa-config | Shared RWAConfig type and validation schema |
License
AGPL-3.0
