Skip to content

RPC Queries

Karl Oczadly edited this page Apr 1, 2021 · 14 revisions

Introduction to RPC requests

A query request is simply a command which can be sent to the official Nano node through RPC commands. Requests can be used for changing the state of a node or it's configured wallets, or for obtaining information from it about its current status or retrieving the block details from the ledger.

Requests are first serialized into the relevant JSON syntax and then sent over the HTTP protocol to the specified node address and port. From here the node will execute the command and feedback any necessary information as a response, which is then deserialized into the appropriate class.

Note: If you're using an external or public RPC service, consider reading the section on third-party services.

Node configuration

View the official Nano documentation for further detailed information on node configuration.

In order to make RPC requests, the external node needs to be correctly configured to accept and listen for them. To do this, you will need to open the following configuration files in the node's local working directory:

  • config-node.toml:
    • rpc.enable must be set to true in order for the node to accept RPC commands
  • config-rpc.toml:
    • address should be set to the network the RPC sever should bind to — for local connections, use ::1
    • port is the port which the RPC server binds to — default is 7076
    • enable_control needs to be set to true if you wish to use the control commands

How to use the library

Use the RpcQueryNode class to specify a remote node which accepts RPC requests and handles all requests. Each instance represents a different node endpoint (ip/port), allowing your program to operate with multiple nodes if necessary. If an IP address and port are not specified, then the library will default to using localhost on port 7076.

To specify a request and parameters, use one of the available pre-defined classes listed in the lookup table at the bottom of this page, or create your own for unsupported operations or custom nodes.

Examples

Synchronous queries (blocking)

Interacting with the node, the ledger and its wallets is a relatively simple process. The following sample sends a request to the node to create a new account from a given seed and index.

try {
    // Configure a connection to localhost:7076
    RpcQueryNode rpc = new RpcQueryNode();
    
    // Construct the request and arguments
    RequestBlockInfo req = new RequestBlockInfo(
            "B3B23FD0AB8B6E440953D443402EEE14BC7A3A1E3F71D60C43D001587EAD80F7");
    
    // Process the query
    ResponseBlockInfo info = rpc.processRequest(req);
        
    // Handle/print retrieved information
    System.out.println("Amount: " + info.getAmount());
    System.out.println("Type: " + info.getContents().getType());
    System.out.println("Height: " + info.getHeight());
} catch (RpcException | IOException e) {
    e.printStackTrace();
}

This outputs the following text to the console:

Amount: 15.628446… Nano
Type: state
Height: 525576

Asynchronous queries (non-blocking callbacks)

You can also make asynchronous requests to the node, which will prevent the called thread from locking up by utilizing a thread pool and callbacks. The following example code queries the balance of the specified account, and prints it to the console:

// Configure a connection to localhost:7076
RpcQueryNode rpc = new RpcQueryNode();

// Construct the request and arguments
RequestAccountBalance req = new RequestAccountBalance(
        "nano_3x4ui45q1cw8hydmfdn4ec5ijsdqi4ryp14g4ayh71jcdkwmddrq7ca9xzn9");

// Process the request and define callback as anonymous class
rpc.processRequestAsync(req, new QueryCallback<>() {
    @Override
    public void onResponse(ResponseBalance response, RequestAccountBalance request) {
        // Print the balance
        System.out.println("Account balance: " + response.getTotal());
    }
    
    @Override
    public void onFailure(RpcException ex, RequestAccountBalance request) {
        ex.printStackTrace();
    }
    
    @Override
    public void onFailure(IOException ex, RequestAccountBalance request) {
        ex.printStackTrace();
    }
});

This gives the following response output in the console:

Account balance: 12,888,717.767914… Nano

You can also retrieve a Future object from the call, like so:

Future<ResponseVersion> versionRes = node.processRequestAsync(new RequestVersion());

// ... elsewhere in your program ...
if (versionRes.isDone()) {
    ResponseVersion ver = versionRes.get();
    System.out.println("Node version: " + ver.getNodeVendor());
}

Third-party RPC providers

A range of pre-defined public RPC providers are available in the RpcServiceProviders class through static methods. These offer additional parsing of their own special exception messages and allow you to easily provide any API keys.

If you want to perform wallet-related actions when using an untrusted or unsafe RPC service, you should consider using the LocalRpcWalletAccount class. This allows you to send and receive funds without exposing the private key to the node, as all blocks are created and signed locally. Consider the example code below:

RpcQueryNode rpcClient = RpcServiceProviders.nanex(); // Use nanex.cc public RPC API

// Construct a block producer object with your configuration
BlockProducer blockProducer = new StateBlockProducer(
        BlockProducerSpecification.builder()
                .defaultRepresentative("nano_3caprkc56ebsaakn4j4n7g9p8h358mycfjcyzkrfw1nai6prbyk8ihc5yjjk")
                .workGenerator(new NodeWorkGenerator(rpcClient)) // Generate work on the node
                .build()
);

// Create account from private key
LocalRpcWalletAccount account = new LocalRpcWalletAccount(
        new HexData("183A1DEDCA9CD37029456C8A2ED31460A0E9A8D18032676010AC11B02A442417"), // Private key
        rpcClient, blockProducer); // Using the RPC client and BlockProducer defined above

// Print account info
System.out.printf("Using account address %s%n", account.getAccount());
System.out.printf("Initial balance: %s%n", account.getBalance());

// Receive all pending funds
System.out.printf("Received %,d blocks%n", account.receiveAll().size());
System.out.printf("Balance: %s%n", account.getBalance());

// Send funds to another account
System.out.printf("Send block hash: %s%n", account.send(
        NanoAccount.parseAddress("nano_34qjpc8t1u6wnb584pc4iwsukwa8jhrobpx4oea5gbaitnqafm6qsgoacpiz"),
        NanoAmount.valueOfNano("0.01"))
        .getHash());

Exceptions table

The below table contains a list of supported RPC exceptions that are automatically parsed and thrown. While these can be helpful, the actual exception class thrown should not be relied upon for any critical components of your program due to inconsistencies in the error response from the node. In cases where the appropriate exception category cannot be parsed, an RpcUnrecognizedException will be thrown.

Exception class Description
RpcException
Base exception class
The default superclass RPC exception, thrown if there is an error with the query or node.
RpcExternalException Base exception for errors returned by the node.
RpcInvalidArgumentException Thrown if one of the given request arguments are not valid.
RpcEntityNotFoundException Thrown if one of the referenced entities (eg. account, wallet, block hash) do not exist.
RpcWalletLockedException Thrown when a query needs access to a wallet which is currently locked.
RpcConfigForbiddenException Thrown if a requested command is disallowed due to a configuration option on the node.
You will need to change the relevant settings in the node's configuration.
RpcFeatureDisabledException
Extends RpcConfigForbiddenException
Thrown if a requested command requires a feature which is disabled on the node.
You will need to change the relevant settings in the node's configuration.
RpcControlDisabledException
Extends RpcFeatureDisabledException
Thrown when a request needs control access (which isn't enabled on the node).
Refer to configuration section above to change this.
RpcCommandNotAllowedException
Extends RpcFeatureDisabledException
Thrown when a request command is blocked.
These could be unsafe commands available only on the beta network, or blocked commands from a third-party node gateway.
RpcRequestCancelledException Thrown if a request was cancelled before it could be completed (eg. work generation request through work_cancel).
RpcInvalidRequestJsonException Thrown if the node was unable to parse the sent request.
Ensure you are using the right version of jNano for the node version you are using.
RpcUnknownCommandException Thrown if the node does not understand the request command.
Ensure you are using the right version of jNano for the node version you are using.
RpcInternalException Thrown if the node encounters an internal error.
RpcUnrecognizedException Thrown if the underlying exception type, category or details could not be determined.
RpcInvalidResponseException Thrown if the node returns an invalid JSON response.
Ensure you are using the right version of jNano for the node version you are using.

Command lookup table

Below is a list of request and response commands currently supported by jNano. Request classes are located in the uk.oczadly.karl.jnano.rpc.request.{category} packages, and response classes are in the uk.oczadly.karl.jnano.rpc.response package.

For more information on commands, view the official Nano RPC documentation.

RPC command Request class Response class
account_balance RequestAccountBalance ResponseBalance
account_block_count RequestAccountBlockCount ResponseAccountBlockCount
account_get RequestAccountFromKey ResponseAccount
account_history RequestAccountHistory ResponseAccountHistory
account_info RequestAccountInfo ResponseAccountInfo
account_key RequestAccountPublicKey ResponseKey
account_representative RequestAccountRepresentative ResponseAccount
account_weight RequestAccountWeight ResponseAmount
accounts_balances RequestMultiAccountBalances ResponseMultiAccountBalances
accounts_frontiers RequestMultiAccountFrontiers ResponseMultiAccountFrontiers
accounts_pending RequestMultiAccountsPending ResponseMultiAccountsPending
active_difficulty RequestActiveDifficulty ResponseActiveDifficulty
available_supply RequestAvailableSupply ResponseAmount
block_account RequestBlockAccount ResponseAccount
block_confirm RequestBlockConfirm ResponseSuccessful
block_count RequestBlockCount ResponseBlockCount
block_count_type RequestBlockCountByType ResponseBlockCountByType
block_create RequestBlockCreate ResponseBlockCreate
block_hash RequestBlockHash ResponseBlockHash
block_info RequestBlockInfo ResponseBlockInfo
blocks RequestMultiBlocks ResponseBlocksMap
blocks_info RequestMultiBlocksInfo ResponseMultiBlockInfo
bootstrap RequestBootstrap ResponseSuccessful
bootstrap_lazy RequestBootstrapLazy ResponseSuccessful
bootstrap_any RequestBootstrapAny ResponseSuccessful
chain RequestChain ResponseBlockHashes
confirmation_active RequestConfirmationActive ResponseBlockConfirmations
confirmation_info RequestConfirmationInfo ResponseConfirmationInfo
confirmation_quorum RequestConfirmationQuorum ResponseConfirmationQuorum
delegators RequestDelegators ResponseDelegators
delegators_count RequestDelegatorsCount ResponseCount
deterministic_key RequestDeterministicKey ResponseKeyPair
frontier_count RequestFrontierCount ResponseCount
frontiers RequestFrontiers ResponseMultiAccountFrontiers
keepalive RequestKeepAlive ResponseSuccessful
key_create RequestKeyCreate ResponseKeyPair
key_expand RequestKeyExpand ResponseKeyPair
ledger RequestLedger ResponseLedger
peers RequestPeers ResponsePeers
pending RequestPending ResponsePending
pending_exists RequestPendingExists ResponseExists
process RequestProcess ResponseBlockHash
representatives RequestRepresentatives ResponseRepresentatives
representatives_online RequestRepresentativesOnline ResponseOnlineRepresentatives
republish RequestRepublish ResponseBlockHashes
sign RequestSign ResponseSignature
stop RequestStop ResponseSuccessful
successors RequestSuccessors ResponseBlockHashes
telemetry RequestTelemetry ResponseTelemetry
validate_account_number RequestValidateAccount ResponseValidation
version RequestVersion ResponseVersion
unchecked RequestUnchecked ResponseBlocksMap
unchecked_clear RequestUncheckedClear ResponseSuccessful
unchecked_get RequestUncheckedGet ResponseBlock
unchecked_keys RequestUncheckedKeys ResponseUncheckedKeys
unopened RequestUnopened ResponseUnopened
uptime RequestUptime ResponseUptime
work_cancel RequestWorkCancel ResponseSuccessful
work_generate RequestWorkGenerate ResponseWork
work_peer_add RequestWorkPeerAdd ResponseSuccessful
work_peers RequestWorkPeers ResponseWorkPeers
work_peers_clear RequestWorkPeersClear ResponseSuccessful
work_validate RequestWorkValidate ResponseWorkValidation
account_create RequestAccountCreate ResponseAccount
account_list RequestAccountList ResponseAccounts
account_move RequestAccountsMove ResponseAccountsMoved
account_remove RequestAccountRemove ResponseSuccessful
account_representative_set RequestAccountRepresentativeSet ResponseBlockHash
accounts_create RequestAccountsCreate ResponseAccounts
password_change RequestPasswordChange ResponseSuccessful
password_enter RequestPasswordEnter ResponseValidation
password_valid RequestPasswordValid ResponseValidation
receive RequestReceive ResponseBlockHash
receive_minimum RequestReceiveMinimum ResponseAmount
receive_minimum_set RequestReceiveMinimumSet ResponseSuccessful
search_pending RequestSearchPending ResponseSuccessful
search_pending_all RequestSearchPendingAll ResponseSuccessful
send RequestSend ResponseBlockHash
wallet_add RequestWalletAdd ResponseAccount
wallet_add_watch RequestWalletAddWatch ResponseSuccessful
wallet_balances RequestWalletBalances ResponseMultiAccountBalances
wallet_change_seed RequestWalletChangeSeed ResponseWalletChangeSeed
wallet_contains RequestWalletContains ResponseExists
wallet_create RequestWalletCreate ResponseWalletId
wallet_destroy RequestWalletDestroy ResponseSuccessful
wallet_export RequestWalletExport ResponseWalletExport
wallet_frontiers RequestWalletFrontiers ResponseMultiAccountFrontiers
wallet_history RequestWalletHistory ResponseWalletHistory
wallet_info RequestWalletInfo ResponseWalletInfo
wallet_ledger RequestWalletLedger ResponseLedger
wallet_lock RequestWalletLock ResponseWalletLocked
wallet_locked RequestWalletLocked ResponseWalletLocked
wallet_pending RequestWalletPending ResponseWalletPending
wallet_representative RequestWalletRepresentative ResponseAccount
wallet_representative_set RequestWalletRepresentativeSet ResponseSuccessful
wallet_republish RequestWalletRepublish ResponseBlockHashes
wallet_work_get RequestWalletWorkGet ResponseWalletWork
work_get RequestWorkGet ResponseWork
work_set RequestWorkSet ResponseSuccessful
krai_from_raw
krai_to_raw
mrai_from_raw
mrai_to_raw
rai_from_raw
rai_to_raw
RequestConvertUnits ResponseAmountInt
node_id RequestNodeId ResponseNodeId
node_id_delete RequestNodeIdDelete ResponseSuccessful
confirmation_height_currently_processing RequestConfirmationHeightProcessing ResponseBlockHash
confirmation_history RequestConfirmationHistory ResponseConfirmationHistory
bootstrap_status RequestBootstrapStatus ResponseBootstrapStatus