Complete account management plugin for the Hiero CLI following the plugin architecture.
This plugin follows the plugin architecture principles:
- Stateless: Plugin is functionally stateless
- Dependency Injection: Services are injected into command handlers
- Manifest-Driven: Capabilities declared via manifest
- Namespace Isolation: Own state namespace (
account-accounts) - Type Safety: Full TypeScript support
src/plugins/account/
├── manifest.ts # Plugin manifest with command definitions
├── schema.ts # Account data schema with Zod validation
├── commands/
│ ├── create/
│ │ ├── handler.ts # Account creation handler
│ │ ├── input.ts # Input schema
│ │ ├── output.ts # Output schema and template
│ │ ├── types.ts # Command types
│ │ └── index.ts # Command exports
│ ├── import/
│ │ ├── handler.ts # Account import handler
│ │ ├── input.ts # Input schema
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ ├── balance/
│ │ ├── handler.ts # Balance retrieval handler
│ │ ├── input.ts # Input schema
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ ├── list/
│ │ ├── handler.ts # List accounts handler
│ │ ├── input.ts # Input schema
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ ├── view/
│ │ ├── handler.ts # View account details handler
│ │ ├── input.ts # Input schema
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ ├── delete/
│ │ ├── handler.ts # Delete account handler
│ │ ├── input.ts # Input schema
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ └── clear/
│ ├── handler.ts # Clear all accounts handler
│ ├── output.ts # Output schema and template
│ └── index.ts # Command exports
├── hooks/
│ ├── batch-create/
│ │ ├── handler.ts # AccountCreateBatchStateHook - persists account state after batch execution
│ │ ├── types.ts # AccountCreateNormalisedParamsSchema for batch item validation
│ │ └── index.ts # Hook exports
│ ├── batch-update/
│ │ ├── handler.ts # AccountUpdateBatchStateHook - updates account key state after batch execution
│ │ ├── types.ts # AccountUpdateNormalisedParamsSchema for batch item validation
│ │ └── index.ts # Hook exports
│ └── batch-delete/
│ ├── handler.ts # AccountDeleteBatchStateHook - removes account from state after batch execution
│ ├── types.ts # AccountDeleteNormalisedParamsSchema for batch item validation
│ └── index.ts # Hook exports
├── utils/
│ ├── account-address.ts # EVM address derivation helpers
│ ├── balance-helpers.ts # Balance retrieval utilities
│ └── account-validation.ts
├── zustand-state-helper.ts # State management helper
├── __tests__/unit/ # Unit tests
└── index.ts # Plugin exports
All commands return CommandResult with structured output data in the result field. Errors are thrown as typed CliError instances and handled uniformly by the core framework.
Each command defines a Zod schema for output validation and a Handlebars template for human-readable formatting.
Create a new Hedera account with specified balance and settings.
# Basic usage
hcli account create \
--balance 100000000 \
--auto-associations 10 \
--name myaccount \
--payer operator-name
# With specific key manager
hcli account create --balance 1.0 --name alice --key-manager local_encryptedBatch support: The account create command registers the batchify hook, so you can add account creation to a batch instead of executing immediately. Pass --batch <batch-name> to defer execution:
# Add account creation to a batch (transaction not executed until batch execute)
hcli account create --balance 1.0 --name alice --batch my-batchWhen the batch is executed via hcli batch execute --name my-batch, the AccountCreateBatchStateHook runs to persist each created account to state (including alias registration and EVM address derivation).
Update properties of an existing Hedera account on-chain.
# Update memo
hcli account update --account myaccount --memo "new memo"
# Clear memo
hcli account update --account myaccount --memo null
# Update key (key rotation — signs with both old and new key)
hcli account update --account myaccount --key <key-ref-or-private-key>
# Update staking
hcli account update --account myaccount --staked-node-id 3
hcli account update --account myaccount --staked-account-id 0.0.98
# Clear staking
hcli account update --account myaccount --staked-node-id null
# Update multiple fields
hcli account update --account myaccount \
--memo "updated" \
--max-auto-associations 10 \
--decline-staking-reward trueNullable fields — pass null (as a string) to reset a field to its Hedera default:
--memo null— clears the account memo--staked-account-id null— clears staked account--staked-node-id null— clears staked node
Batch support: The account update command registers the batchify hook:
hcli account update --account myaccount --memo "new memo" --batch my-batchWhen the batch is executed via hcli batch execute --name my-batch, the AccountUpdateBatchStateHook updates the account's key data in local state (runs only when a key rotation was part of the update).
hcli account import \
--id 0.0.123456 \
--key <private-key> \
--name imported-accounthcli account balance --account myaccount
hcli account balance --account 0.0.123456 --hbar-onlyhcli account list
hcli account list --private # Show key reference IDshcli account view --account myaccount
hcli account view --account 0.0.123456Deletes the account on Hedera (default) or only from local CLI state (--state-only). Network delete requires a beneficiary for remaining HBAR (--transfer-id).
hcli account delete --account myaccount --transfer-id 0.0.98
hcli account delete --account 0.0.123456 --transfer-id operator-alias
hcli account delete --account myaccount --state-onlyaccount delete also supports --batch / -B like account create; after batch execute, AccountDeleteBatchStateHook removes the account from local state.
hcli account clearThe account create, account update, and account delete commands support the --batch / -B flag via the batch plugin's batchify hook. When you pass --batch <batch-name>:
- No immediate execution – The transaction is not submitted to the network. Instead, it is serialized and added to the specified batch.
- Deferred execution – Run
hcli batch execute --name <batch-name>to submit all batched transactions atomically. - State persistence – After successful batch execution, domain-state hooks run:
AccountCreateBatchStateHook— fetches receipt, derives EVM address, saves account to state, registers aliasesAccountUpdateBatchStateHook— updates account key data in state (only when key rotation occurred)AccountDeleteBatchStateHook— removes account from local state
Example workflow:
# 1. Create a batch
hcli batch create --name my-batch --key operator-alias
# 2. Add operations to the batch
hcli account create --balance 1.0 --name alice --batch my-batch
hcli account update --account bob --memo "updated" --batch my-batch
hcli account delete --account old-account --transfer-id 0.0.98 --batch my-batch
# 3. Execute the batch (all operations atomically)
hcli batch execute --name my-batchThe --batch option is automatically injected by the batchify hook—no need to declare it in the account plugin. See the Batch Plugin README for full batch documentation.
The plugin uses the Core API services:
api.account- Account transaction creationapi.txExecution- Transaction signing and executionapi.state- Namespaced state managementapi.network- Network informationapi.kms- Secure key managementapi.alias- Name registration and resolutionapi.mirror- Mirror node queriesapi.receipt- Transaction receipt retrieval (used byAccountCreateBatchStateHook)api.logger- Logging
All commands return structured output through the CommandResult interface:
interface CommandResult {
result: object;
}Output Structure:
- Output Schemas: Each command defines a Zod schema in
output.tsfor type-safe output validation - Human Templates: Handlebars templates provide human-readable output formatting
- Error Handling: All errors are returned in the result structure, ensuring consistent error handling
The result field contains a structured object conforming to the Zod schema defined in each command's output.ts file, ensuring type safety and consistent output structure.
Example output schema:
export const AccountCreateOutputSchema = z.object({
accountId: EntityIdSchema,
name: z.string(),
type: KeyTypeSchema,
network: NetworkSchema,
transactionId: TransactionIdSchema,
evmAddress: EvmAddressSchema,
publicKey: PublicKeySchema,
});Account data is stored in the account-accounts namespace with the following structure:
interface AccountData {
keyRefId: string; // Reference to private key in secure storage
name: string; // Unique account name
accountId: string; // Hedera account ID (0.0.xxxxx)
type: KeyAlgorithm; // Key algorithm (ecdsa or ed25519)
publicKey: string; // Public key
evmAddress: string; // EVM address
network: 'mainnet' | 'testnet' | 'previewnet' | 'localnet';
}The schema is validated using Zod (AccountDataSchema) and stored as JSON Schema in the plugin manifest for runtime validation.
- Private keys stored securely via
KmsServiceusingkeyRefIdreferences - Two storage modes available:
local(plain text) andlocal_encrypted(AES-256-GCM) - Default storage mode configurable via
hcli config set -o default_key_manager -v local|local_encrypted - Per-operation override using
--key-managerflag - No raw private keys in plugin state JSON
- Secure key retrieval through Core API
- Keys isolated in credentials storage namespace
- Per-network names via
AliasService - Names resolve to account IDs and key references
- Example:
myaccount→0.0.123456on testnet - Registered during
createandimportwhen--nameprovided
Unit tests located in __tests__/unit/:
npm test -- src/plugins/account/__tests__/unitTest coverage:
- Account creation (happy path, failures)
- Account creation in batch (batch-create hook)
- Account update (all fields, null clearing, key rotation, batch-update hook)
- Account import with names
- Balance retrieval (HBAR only, with tokens, errors)
- Account listing
- Account view and deletion
- Clear all accounts