Complete token 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
- Namespace Isolation: Own state namespace (
token-tokens) - Type Safety: Full TypeScript support
- Structured Output: All command handlers return
CommandExecutionResultwith standardized output
src/plugins/token/
├── manifest.ts # Plugin manifest with command definitions and output specs
├── schema.ts # Token data schema with Zod validation
├── commands/
│ ├── create/
│ │ ├── handler.ts # Token creation handler
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ ├── transfer/
│ │ ├── handler.ts # Token transfer handler
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ ├── associate/
│ │ ├── handler.ts # Token association handler
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ ├── list/
│ │ ├── handler.ts # Token list handler
│ │ ├── output.ts # Output schema and template
│ │ └── index.ts # Command exports
│ └── createFromFile/
│ ├── handler.ts # Token from file handler
│ ├── output.ts # Output schema and template
│ └── index.ts # Command exports
├── zustand-state-helper.ts # State management helper
├── resolver-helper.ts # Token and account resolver utilities
├── __tests__/ # Comprehensive test suite
│ └── unit/
│ ├── adr003-compliance.test.ts # Output structure compliance tests
│ └── [other test files...]
└── index.ts # Plugin exports
All commands return CommandExecutionResult with structured output that includes:
status: Success or failure statuserrorMessage: Optional error message (present when status is not 'success')outputJson: JSON string conforming to the output schema defined inoutput.ts
Each command defines a Zod schema for output validation and a Handlebars template for human-readable formatting.
Create a new fungible token with specified properties.
# Using account alias
hcli token create \
--token-name "My Token" \
--symbol "MTK" \
--treasury alice \
--decimals 2 \
--initial-supply 1000 \
--supply-type FINITE \
--max-supply 10000 \
--admin-key admin-public-key \
--name mytoken-alias
# Using treasury-id:treasury-key pair
hcli token create \
--token-name "My Token" \
--symbol "MTK" \
--treasury 0.0.123456:302e020100300506032b657004220420... \
--decimals 2 \
--initial-supply 1000 \
--supply-type INFINITE \
--name mytoken-aliasAssociate a token with an account to enable transfers.
# Using account alias
hcli token associate \
--token mytoken-alias \
--account alice
# Using account-id:account-key pair
hcli token associate \
--token 0.0.123456 \
--account 0.0.789012:302e020100300506032b657004220420...Transfer a fungible token from one account to another.
# Using account name for source
hcli token transfer \
--token mytoken-alias \
--from alice \
--to bob \
--amount 100
# Using account-id:private-key pair for source
hcli token transfer \
--token 0.0.123456 \
--from 0.0.111111:302e020100300506032b657004220420... \
--to 0.0.222222 \
--amount 100tList all tokens stored in state for all networks.
hcli token list
hcli token list --keys # Show token key informationCreate a new token from a JSON file definition with advanced features.
# Basic usage
hcli token create-from-file --file token-definition.json
# With specific key manager
hcli token create-from-file --file token-definition.json --key-manager local_encryptedToken File Format:
The token file supports aliases and raw keys with optional key type prefixes:
{
"name": "my-token",
"symbol": "MTK",
"decimals": 8,
"supplyType": "finite",
"initialSupply": 1000000,
"maxSupply": 10000000,
"treasuryKey": "<alias or accountId:privateKey>",
"adminKey": "<alias or accountId:privateKey>",
"supplyKey": "<alias or accountId:privateKey>",
"wipeKey": "<alias or accountId:privateKey>",
"kycKey": "<alias or accountId:privateKey>",
"freezeKey": "<alias or accountId:privateKey>",
"pauseKey": "<alias or accountId:privateKey>",
"feeScheduleKey": "<alias or accountId:privateKey>",
"memo": "Optional token memo",
"associations": ["<alias or accountId:privateKey>", "..."],
"customFees": [
{
"type": "fixed",
"amount": 100,
"unitType": "HBAR",
"collectorId": "<accountId>",
"exempt": false
}
]
}Supported formats for treasury and keys:
- Alias:
"my-account"- resolved via alias service - Account with key:
"0.0.123456:privateKey"
Note: Token name is automatically registered as an alias after successful creation. Duplicate names are not allowed.
The plugin supports flexible parameter formats:
- Token: Token alias (name) or token ID (
0.0.123456) - Treasury: Account alias (name) or
treasury-id:treasury-keypair (e.g.,0.0.123456:302e0201...) - Account ID only:
0.0.123456(for destination accounts) - Account ID with key:
0.0.123456:private-key(for source accounts that need signing) - Account name:
alice(resolved via alias service) - Amount: Display units (default) or base units with
tsuffix (e.g.,100t)
Private keys can optionally be prefixed with their key type:
- With prefix:
ed25519:12345676543212345orecdsa:12345676543212345 - Without prefix:
12345676543212345(defaults toecdsa)
This applies to:
- Treasury keys in
create-from-filecommand - Association keys in
create-from-filecommand - Account keys in
treasury-id:keyformat
The plugin uses the Core API services:
api.token- Token transaction creation and managementapi.txExecution- Transaction signing and executionapi.kms- Account credentials and key managementapi.alias- Account and token name resolutionapi.state- Namespaced state managementapi.network- Network informationapi.logger- Logging
All commands return structured output through the CommandExecutionResult interface:
interface CommandExecutionResult {
status: 'success' | 'failure';
errorMessage?: string; // Present when status !== 'success'
outputJson?: string; // JSON string conforming to the output schema
}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 outputJson field contains a JSON string that conforms to the Zod schema defined in each command's output.ts file, ensuring type safety and consistent output structure.
Token data is stored in the token-tokens namespace with the following structure:
interface TokenData {
tokenId: string;
name: string;
symbol: string;
treasuryId: string;
decimals: number;
initialSupply: number;
supplyType: 'FINITE' | 'INFINITE';
maxSupply: number;
memo?: string;
keys: TokenKeys;
network: 'mainnet' | 'testnet' | 'previewnet' | 'localnet';
associations: TokenAssociation[];
customFees: CustomFee[];
}The schema is validated using Zod (TokenDataSchema) and stored as JSON Schema in the plugin manifest for runtime validation.
The plugin includes comprehensive tests for output structure:
import { Status } from '../../../core/shared/constants';
// Example test verifying CommandExecutionResult structure
describe('Token Plugin Output Structure', () => {
test('token create command returns CommandExecutionResult', async () => {
const result = await createTokenHandler(mockArgs);
// Assert structure
expect(result.status).toBe(Status.Success);
expect(result.outputJson).toBeDefined();
// Assert output format
const output = JSON.parse(result.outputJson) as CreateTokenOutput;
expect(output.tokenId).toBe('0.0.12345');
expect(output.name).toBe('TestToken');
});
});- Output Compliance:
adr003-compliance.test.ts- Tests all handlers return properCommandExecutionResult - Unit Tests: Individual command handler tests with mocks and fixtures
- Integration Tests: End-to-end token lifecycle tests
- Schema Tests: Validation of input/output schemas
All commands support multiple output formats:
✅ Token created successfully: 0.0.12345
Name: MyToken (MTK)
Treasury: 0.0.111
Decimals: 2
Initial Supply: 1000000
Supply Type: INFINITE
Network: testnet
Transaction ID: 0.0.123@1700000000.123456789
{
"tokenId": "0.0.12345",
"name": "MyToken",
"symbol": "MTK",
"treasuryId": "0.0.111",
"decimals": 2,
"initialSupply": "1000000",
"supplyType": "INFINITE",
"transactionId": "0.0.123@1700000000.123456789",
"network": "testnet"
}Output format is controlled by the CLI's --format option (default: human, or json for machine-readable output).