Bash Guide
0. A brief primer on CLI applications
This is as good a place as any to discuss what iroha_client_cli
is and what you should expect it to be able to do.
Most users think that everything that's run inside the terminal is a CLI program. This is not the case. A Command-line Interface is a glorified scripting language that you interact with using the shell.
CLI programs are run multiple times and given different arguments: --flag1
file2
--help
, etc., depending on what you want to do. A single session doesn't begin with you opening the program and end with you closing it. When you've stopped interacting, the iroha_client_cli
session is finished.
You also don't configure a CLI program in the usual sense of the word. Most people expect that it's possible to change some settings of a program from inside that same program, but most CLI programs are configured differently.
First of all, if you want to make a certain --flag
part of the way you invoke iroha_client_cli
, you should create a shell alias. Some programs, but not iroha_client_cli
, also use something called Environment variables.
Finally, most programs store persistent information that is too big for either a shell alias or an environment variable in a separate file. iroha_client_cli
does not yet follow the XDG_CONFIG_HOME specification. It only looks for a configuration file in one of two places:
If the
-c
or--config
command line flag is specified, the next argument interpreted as a path.For example:
-c ~/Git/iroha/configs/peer/config.json
. If that file doesn't exist, you will see an error, andiroha_client_cli
won't look for a configuration file anywhere else.If neither
-c
nor--config
were given, it will look in the current working directory.
These defaults are not very ergonomic. They are artifacts of the way in which Iroha is being deployed, and the fact that a CLI interface is used exclusively for testing purposes.
INFO
This might change in the future, but likely not by fixing iroha_client_cli
but rather by replacing it entirely with Iroha Python. The only thing stopping us from that today is that Iroha Python has not gotten the attention it deserves.
It is possible that a user might be expecting iroha_client_cli
to behave like a graphical program using terminal graphics: a Terminal User Interface. While we'd like to provide you with such a program, we don't think that it offers enough convenience over the amount of effort that we'd need to put in.
INFO
It is possible that in the future, once iroha_client_cli
is phased out and iroha_python
is the official scripting interface, we might use the excellent Python libraries for creating a useful TUI. For now, one must make do with what one has.
1. Iroha 2 Client Setup
Note, first, that we have already created the iroha_client_cli
binary executable, when we ran the build
command.
Create a fresh directory for the client:
$ mkdir -p test_docker
$ mkdir -p test_docker
Copy the configuration file to the client directory:
$ cp ./configs/client/config.json test_docker/
$ cp ./configs/client/config.json test_docker/
TIP
You could also use a file manager (e.g. finder) to do that. We prefer providing command-line instructions, because they are easier to follow step-by-step.
To test Iroha 2 metadata capabilities, let's also create a dummy metadata.json
file:
$ echo '{"comment":{"String": "Hello Meta!"}}' > test_docker/metadata.json
$ echo '{"comment":{"String": "Hello Meta!"}}' > test_docker/metadata.json
To get the CLI started, copy the iroha_client_cli
binary into the client directory:
$ cp ./target/debug/iroha_client_cli test_docker/
$ cp ./target/debug/iroha_client_cli test_docker/
Make sure you bring up the test network as well.
2. Configuring Iroha 2
Now let's look at how to properly configure Iroha 2, and especially its Command-Line Interface client.
Make sure that you have another terminal tab or window open with a running version, using the instructions above. You can use this screen to monitor the pipeline events as they are output.
On a new terminal tab run:
$ cd ~/Git/iroha/test_docker
$ cd ~/Git/iroha/test_docker
If you followed the steps correctly, this should contain the iroha_client_cli
and config.json
.
TIP
Use ls
to make sure both files are there, and if not, return to Step 1.
Run
$ ./iroha_client_cli
$ ./iroha_client_cli
Expand to see the expected output
iroha_client_cli 0.1.0
Soramitsu Iroha2 team (https, //github.com/orgs/soramitsu/teams/iroha2)
Iroha CLI Client provides an ability to interact with Iroha Peers Web API without direct network usage
USAGE:
iroha_client_cli [OPTIONS] <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-c, --config <config> Sets a config file path [default: config.json]
SUBCOMMANDS:
account The subcommand related to accounts
asset The subcommand related to assets
blocks The subcommand related to block streaming
domain The subcommand related to domains
events The subcommand related to event streaming
help Prints this message or the help of the given subcommand(s)
json The subcommand related to multi-instructions as Json
peer The subcommand related to p2p networking
wasm The subcommand related to Wasm
iroha_client_cli 0.1.0
Soramitsu Iroha2 team (https, //github.com/orgs/soramitsu/teams/iroha2)
Iroha CLI Client provides an ability to interact with Iroha Peers Web API without direct network usage
USAGE:
iroha_client_cli [OPTIONS] <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-c, --config <config> Sets a config file path [default: config.json]
SUBCOMMANDS:
account The subcommand related to accounts
asset The subcommand related to assets
blocks The subcommand related to block streaming
domain The subcommand related to domains
events The subcommand related to event streaming
help Prints this message or the help of the given subcommand(s)
json The subcommand related to multi-instructions as Json
peer The subcommand related to p2p networking
wasm The subcommand related to Wasm
To configure the Iroha client, run:
$ ./iroha_client_cli --config ./test_docker/config.json
$ ./iroha_client_cli --config ./test_docker/config.json
It should be noted that this is not persistent configuration: each time you run iroha_client_cli
, you must add the --config ./test_docker/config.json
command-line argument.
TIP
Because the client checks the working directory for a file called config.json
, it's always much easier to just copy (or link) the file into the working directory. Alternatively, you could also create a shell alias.
Feel free to edit the file and see what each option does. The only thing that you shouldn't edit at this point is the account. You see, alice
has to be pre-registered in the genesis block. Only she can interact with the blockchain, and if you change the value of the user account, you should also make sure that that user exists in the blockchain.
To make sure that your configuration options worked, try to run a query, e.g.:
$ ./iroha_client_cli domain list all
$ ./iroha_client_cli domain list all
If the output looks like some form of JSON (but not quite), then the configuration was successful!
3. Registering a Domain
To get started, you must register a domain:
$ ./iroha_client_cli domain register --id="looking_glass"
$ ./iroha_client_cli domain register --id="looking_glass"
You will receive a confirmation of the domain creation. However, this information will not be clearly visible within the message. To confirm that the new domain looking_glass has been created successfully, run:
$ ./iroha_client_cli domain list all
$ ./iroha_client_cli domain list all
The printout should contain the recently-created looking_glass domain
Domain {
name: "looking_glass",
accounts: {},
asset_definitions: {},
metadata: Metadata {
map: {},
},
},
Domain {
name: "looking_glass",
accounts: {},
asset_definitions: {},
metadata: Metadata {
map: {},
},
},
With a domain available, it is time to register an account.
4. Registering an Account
To register an account, you need a public key, think of it as the "password" used by mad_hatter@looking_glass
.
Keys always come in pairs. It is possible to generate a pair of public
and private
keys using one of our tools, kagami
. Once Iroha is released, you will be able to install it separately and call it like any other program on your system. For now you can either ask cargo
to run
it for you, or build the program and find it in one of the target directories (either target/debug
or target/release
)
Create a new key pair:
$ cargo run --bin kagami -- crypto
$ cargo run --bin kagami -- crypto
For the purpose of this tutorial, we are going to use the following keys for mad_hatter@looking_glass
:
Public key (multihash): ed01204595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5
Private key: 14d382c5bd8c0bfbaefdef1133196b78839ed3c136e296e0d969b7a3fca2fb424595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5
Digest function: ed25519
Public key (multihash): ed01204595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5
Private key: 14d382c5bd8c0bfbaefdef1133196b78839ed3c136e296e0d969b7a3fca2fb424595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5
Digest function: ed25519
To register a new account called mad_hatter within the looking_glass domain, run:
$ ./iroha_client_cli account register \
--id="mad_hatter@looking_glass" \
--key="ed01204595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5"
$ ./iroha_client_cli account register \
--id="mad_hatter@looking_glass" \
--key="ed01204595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5"
The --id
argument in the above code snippet specifies the account id, the unique name assigned to that account in the blockchain. This name includes the domain, which is a group of things like asset definitions, account ids, and other objects that we'll talk about later. The --key
argument specifies the public key, which is the one we generated above using kagami
.
If the account registration is successful, you will receive a confirmation message. Like before, it is necessary to query the accounts to verify that mad_hatter has been registered.
Now, let's switch to the newly created account, mad_hatter, and continue experimenting with it. For this, we need to modify the PUBLIC_KEY
, PRIVATE_KEY
, and ACCOUNT_ID
in the config.json
file with the ones we registered earlier, which is located in the same directory as iroha_client_cli
.
TIP
Your updated config.json should look like this
{
"PUBLIC_KEY": "ed01204595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5",
"PRIVATE_KEY": {
"digest_function": "ed25519",
"payload": "14d382c5bd8c0bfbaefdef1133196b78839ed3c136e296e0d969b7a3fca2fb424595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5"
},
"ACCOUNT_ID": "mad_hatter@looking_glass",
"BASIC_AUTH": {
"web_login": "mad_hatter",
"password": "ilovetea"
},
"TORII_API_URL": "http://127.0.0.1:8080",
"TORII_TELEMETRY_URL": "http://127.0.0.1:8180",
"TRANSACTION_TIME_TO_LIVE_MS": 100000,
"TRANSACTION_STATUS_TIMEOUT_MS": 15000,
"TRANSACTION_LIMITS": {
"max_instruction_number": 4096,
"max_wasm_size_bytes": 4194304
},
"ADD_TRANSACTION_NONCE": false
}
{
"PUBLIC_KEY": "ed01204595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5",
"PRIVATE_KEY": {
"digest_function": "ed25519",
"payload": "14d382c5bd8c0bfbaefdef1133196b78839ed3c136e296e0d969b7a3fca2fb424595da8957c5598d4de20fe5f3eb4c14820678e1a1957a535db1fd4b3d1607c5"
},
"ACCOUNT_ID": "mad_hatter@looking_glass",
"BASIC_AUTH": {
"web_login": "mad_hatter",
"password": "ilovetea"
},
"TORII_API_URL": "http://127.0.0.1:8080",
"TORII_TELEMETRY_URL": "http://127.0.0.1:8180",
"TRANSACTION_TIME_TO_LIVE_MS": 100000,
"TRANSACTION_STATUS_TIMEOUT_MS": 15000,
"TRANSACTION_LIMITS": {
"max_instruction_number": 4096,
"max_wasm_size_bytes": 4194304
},
"ADD_TRANSACTION_NONCE": false
}
To see all the accounts on the network as mad_hatter, run:
$ ./iroha_client_cli account list all
$ ./iroha_client_cli account list all
This will list the active accounts on the network, along with their assets. It will look like this:
Expand to see the expected output
Account {
id: Id {
name: "mad_hatter",
domain_name: Id {
name: "looking_glass",
},
},
assets: {},
signatories: {
{ digest: "ed25519", payload: "A753146E75B910AE5E2994DC8ADEA9E7D87E5D53024CFA310CE992F17106F92C",
},
},
permission_tokens: {},
signature_check_condition: SignatureCheckCondition(
EvaluatesTo {
expression: ContainsAny(
ContainsAny {
collection: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "transaction_signatories",
},
),
_value_type: PhantomData,
},
elements: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "account_signatories",
},
),
_value_type: PhantomData,
},
},
),
_value_type: PhantomData,
},
),
metadata: Metadata {
map: {},
},
roles: {},
}
Account {
id: Id {
name: "mad_hatter",
domain_name: Id {
name: "looking_glass",
},
},
assets: {},
signatories: {
{ digest: "ed25519", payload: "A753146E75B910AE5E2994DC8ADEA9E7D87E5D53024CFA310CE992F17106F92C",
},
},
permission_tokens: {},
signature_check_condition: SignatureCheckCondition(
EvaluatesTo {
expression: ContainsAny(
ContainsAny {
collection: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "transaction_signatories",
},
),
_value_type: PhantomData,
},
elements: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "account_signatories",
},
),
_value_type: PhantomData,
},
},
),
_value_type: PhantomData,
},
),
metadata: Metadata {
map: {},
},
roles: {},
}
Another way to create a user (and the user's keys) is as follows:
Open a new tab and navigate to the
/iroha
directory, then run:bash$ ./target/debug/iroha_crypto_cli
$ ./target/debug/iroha_crypto_cli
Copy the public key and repeat the instructions to register a new account. Every time you run this command, you will generate a new key-pair.
In this case, we will create an account for white_rabbit within the looking_glass domain, so we will run:
$ ./iroha_client_cli account register \
--id="white_rabbit@looking_glass" \
--key="ed0120a4c4dadd9f18b0f63d6a420151fe0748d785475dec63034a15fcf999ceda1e65"
$ ./iroha_client_cli account register \
--id="white_rabbit@looking_glass" \
--key="ed0120a4c4dadd9f18b0f63d6a420151fe0748d785475dec63034a15fcf999ceda1e65"
And like before, the new active user will be listed on the network:
Expand to see the expected output
Account {
id: Id {
name: "white_rabbit",
domain_name: Id {
name: "looking_glass",
},
},
assets: {},
signatories: {
{ digest: "ed25519", payload: "A4C4DADD9F18B0F63D6A420151FE0748D785475DEC63034A15FCF999CEDA1E65",
},
},
permission_tokens: {},
signature_check_condition: SignatureCheckCondition(
EvaluatesTo {
expression: ContainsAny(
ContainsAny {
collection: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "transaction_signatories",
},
),
_value_type: PhantomData,
},
elements: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "account_signatories",
},
),
_value_type: PhantomData,
},
},
),
_value_type: PhantomData,
},
),
metadata: Metadata {
map: {},
},
roles: {},
}
Account {
id: Id {
name: "white_rabbit",
domain_name: Id {
name: "looking_glass",
},
},
assets: {},
signatories: {
{ digest: "ed25519", payload: "A4C4DADD9F18B0F63D6A420151FE0748D785475DEC63034A15FCF999CEDA1E65",
},
},
permission_tokens: {},
signature_check_condition: SignatureCheckCondition(
EvaluatesTo {
expression: ContainsAny(
ContainsAny {
collection: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "transaction_signatories",
},
),
_value_type: PhantomData,
},
elements: EvaluatesTo {
expression: ContextValue(
ContextValue {
value_name: "account_signatories",
},
),
_value_type: PhantomData,
},
},
),
_value_type: PhantomData,
},
),
metadata: Metadata {
map: {},
},
roles: {},
}
Now that the network and users are registered, it is possible to mint assets.
5. Registering and minting assets
In order to mint assets, you need to register the asset first. We are going to register the tea token within the looking_glass network. To do that, run:
$ ./iroha_client_cli asset register \
--id="tea#looking_glass" \
--value-type=Quantity
$ ./iroha_client_cli asset register \
--id="tea#looking_glass" \
--value-type=Quantity
The tea asset is now registered within the looking_glass network. The output within the CLI is the same as with other commands, you will be able to see that there are new events in the pipeline.
With the asset created, you can now mint tokens. Run:
$ ./iroha_client_cli asset mint \
--account="mad_hatter@looking_glass" \
--asset="tea#looking_glass" \
--quantity="100"
$ ./iroha_client_cli asset mint \
--account="mad_hatter@looking_glass" \
--asset="tea#looking_glass" \
--quantity="100"
After minting one hundred tea, you will see more pipeline events in the logger, and you can also query the assets that you have just minted:
$ ./iroha_client_cli asset list all
$ ./iroha_client_cli asset list all
After running this command, you will be able to see the tokens currently available on the network:
[
Asset {
id: Id {
definition_id: DefinitionId {
name: "tea",
domain_name: "looking_glass",
},
account_id: Id {
name: "mad_hatter",
domain_name: "looking_glass",
},
},
value: Quantity(
100,
),
},
Asset {
id: Id {
definition_id: DefinitionId {
name: "rose",
domain_name: "wonderland",
},
account_id: Id {
name: "alice",
domain_name: "wonderland",
},
},
value: Quantity(
13,
),
},
]
[
Asset {
id: Id {
definition_id: DefinitionId {
name: "tea",
domain_name: "looking_glass",
},
account_id: Id {
name: "mad_hatter",
domain_name: "looking_glass",
},
},
value: Quantity(
100,
),
},
Asset {
id: Id {
definition_id: DefinitionId {
name: "rose",
domain_name: "wonderland",
},
account_id: Id {
name: "alice",
domain_name: "wonderland",
},
},
value: Quantity(
13,
),
},
]
INFO
Iroha 2 currently doesn't validate the account names, so you could (in theory) add invalid characters to the name, e.g. spaces. We recommend sticking to English alphanumeric characters and underscores.
6. Transferring assets
After minting the assets, you can transfer some of Mad Hatter's tea to White Rabbit:
$ ./iroha_client_cli asset transfer --from mad_hatter@looking_glass --to white_rabbit@looking_glass --asset-id tea#looking_glass --quantity 5
$ ./iroha_client_cli asset transfer --from mad_hatter@looking_glass --to white_rabbit@looking_glass --asset-id tea#looking_glass --quantity 5
7. Burning assets
Burning assets is quite similar to minting them:
$ ./iroha_client_cli asset burn \
--account="mad_hatter@looking_glass" \
--asset="tea#looking_glass" \
--quantity="10"
$ ./iroha_client_cli asset burn \
--account="mad_hatter@looking_glass" \
--asset="tea#looking_glass" \
--quantity="10"
8. Visualizing outputs
Although you will get a constant data feed of the network within the terminal running docker compose, you can also configure an output to listen to events on the network.
From a terminal tab/window run:
$ ./iroha_client_cli events pipeline
$ ./iroha_client_cli events pipeline
This view will output all the events related to Iroha 2, such as transactions, block validations, or data events (e.g. when the in-memory representation of the blockchain gets committed to the hard disk).
The output would look like this:
Iroha Client CLI: build v0.0.1 [release]
User: alice@wonderland
{"PUBLIC_KEY":"ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0","PRIVATE_KEY":{"digest_function":"ed25519","payload":"9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"},"ACCOUNT_ID":{"name":"alice","domain_name":"wonderland"},"TORII_API_URL":"http://127.0.0.1:8080","TORII_STATUS_URL":"127.0.0.1:8180","TRANSACTION_TIME_TO_LIVE_MS":100000,"TRANSACTION_STATUS_TIMEOUT_MS":10000,"MAX_INSTRUCTION_NUMBER":4096,"ADD_TRANSACTION_NONCE":false,"LOGGER_CONFIGURATION":{"MAX_LOG_LEVEL":"INFO","TELEMETRY_CAPACITY":1000,"COMPACT_MODE":false,"LOG_FILE_PATH":null}}
Listening to events with filter: Pipeline(EventFilter { entity: None, hash: None })
Pipeline(
Event {
entity_type: Transaction,
status: Validating,
hash: 10fadf7b7fb8036d00bbd8cadc5358193b04ad6573537463acef2091ba4d0e77,
},
)
Pipeline(
Event {
entity_type: Block,
status: Validating,
hash: 944269f27e1ed8882c6c8c74bd641bc3551ef5651320f4e1e1be11a470b4e3c3,
},
)
Pipeline(
Event {
entity_type: Transaction,
status: Committed,
hash: 10fadf7b7fb8036d00bbd8cadc5358193b04ad6573537463acef2091ba4d0e77,
},
)
Iroha Client CLI: build v0.0.1 [release]
User: alice@wonderland
{"PUBLIC_KEY":"ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0","PRIVATE_KEY":{"digest_function":"ed25519","payload":"9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"},"ACCOUNT_ID":{"name":"alice","domain_name":"wonderland"},"TORII_API_URL":"http://127.0.0.1:8080","TORII_STATUS_URL":"127.0.0.1:8180","TRANSACTION_TIME_TO_LIVE_MS":100000,"TRANSACTION_STATUS_TIMEOUT_MS":10000,"MAX_INSTRUCTION_NUMBER":4096,"ADD_TRANSACTION_NONCE":false,"LOGGER_CONFIGURATION":{"MAX_LOG_LEVEL":"INFO","TELEMETRY_CAPACITY":1000,"COMPACT_MODE":false,"LOG_FILE_PATH":null}}
Listening to events with filter: Pipeline(EventFilter { entity: None, hash: None })
Pipeline(
Event {
entity_type: Transaction,
status: Validating,
hash: 10fadf7b7fb8036d00bbd8cadc5358193b04ad6573537463acef2091ba4d0e77,
},
)
Pipeline(
Event {
entity_type: Block,
status: Validating,
hash: 944269f27e1ed8882c6c8c74bd641bc3551ef5651320f4e1e1be11a470b4e3c3,
},
)
Pipeline(
Event {
entity_type: Transaction,
status: Committed,
hash: 10fadf7b7fb8036d00bbd8cadc5358193b04ad6573537463acef2091ba4d0e77,
},
)