Complete HBAR transfer 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 with output specifications
- Structured Output: All command handlers return
CommandResultwith standardized output - SDK Isolation: All Hedera SDK code in Core API
- Type Safety: Full TypeScript support
src/plugins/hbar/
├── manifest.ts # Plugin manifest with command definitions
├── schema.ts # Transfer input schema with Zod validation
├── commands/
│ └── transfer/
│ ├── handler.ts # HBAR transfer handler
│ ├── output.ts # Output schema and template
│ └── index.ts # Command exports
├── __tests__/unit/
│ └── transfer.test.ts # 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.
Transfer HBAR between accounts with support for names, account IDs, and account-id:private-key pairs.
# Using account names
hcli hbar transfer \
--amount 1 \
--from alice \
--to bob \
--memo "Payment"
# Using account-id:private-key pair for sender
hcli hbar transfer \
--amount 100t \
--from 0.0.123456:302e020100300506032b657004220420... \
--to 0.0.789012
# Using operator from the cli state as sender (when --from is omitted)
hcli hbar transfer \
--amount 0.5 \
--to myaccountOptions:
-a, --amount <string>- Amount in HBAR (display units by default, add "t" for tinybar). Example: "1" = 1 HBAR, "100t" = 100 tinybar (required)-t, --to <string>- Recipient account ID or name (required)-f, --from <string>- Sender account: either an account-id:private-key pair or account name (optional, defaults to operator)-m, --memo <string>- Transfer memo (optional)
Examples:
# Transfer using names
hcli hbar transfer -a 1000000 -f alice -t bob
# Transfer using account IDs
hcli hbar transfer -a 5000000 -f 0.0.123456 -t 0.0.789012
# Transfer from operator account
hcli hbar transfer -a 100000 -t myaccountThe plugin uses the Core API services:
api.hbar- HBAR transfer operationsapi.txExecution- Transaction signing and executionapi.kms- Secure key managementapi.alias- Name resolutionapi.state- Account lookup in stateapi.network- Network informationapi.logger- Logging
The plugin intelligently determines which key to use for signing:
- Account-id:private-key pair - Imports the key and uses it for signing
- Name with keyRefId - Uses registered key for the name via alias service
- Account in state - Looks up account by ID or name, uses its keyRefId
- Default operator - Falls back to operator credentials from network configuration
This ensures transfers are signed with the correct key for the sender account.
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.
Unit tests located in __tests__/unit/transfer.test.ts:
npm test -- src/plugins/hbar/__tests__/unitTest coverage (71%):
- HBAR transfer success (all params provided)
- Balance validation (NaN, negative, zero)
- Missing from/to accounts
- Transfer to same account
- Transfer failures
- Default credentials fallback
- Multi-format support: Accepts names, account IDs, or account-id:private-key pairs
- Smart key resolution: Automatically finds correct signing key
- Default operator fallback: Uses network operator credentials when sender not specified
- Name integration: Works seamlessly with alias service
- Secure signing: Leverages
keyRefIdsystem for key management - Flexible amount input: Supports display units (HBAR) or base units (tinybar with "t" suffix)
When resolving --from or --to:
- Account-id:private-key pair - Parse and import the key
- Try name lookup via
api.alias.resolve() - Try account name in
account-accountsstate - Try account ID in
account-accountsstate - Use as raw account ID (operator will sign if
--fromnot provided)
The handler determines the signing key based on the --from parameter:
- If
--fromis an account-id:private-key pair, the key is imported and used - If
--fromis a name, the key is resolved via alias service or state lookup - If
--fromis omitted, the operator key from network configuration is used