Below the surface of dApps, dexes, and DAO governance there’s a layer of molten data flowing. This walkthrough will show you how to use RPCs in Cosmos to excavate the on-chain data you’re digging for beneath the web3 landscape. Cosmos is a modular and communicative blockchain ecosystem with an SDK that allows developers to navigate, discover, and build highly composable apps. Maybe you’re traveling from Ethereum, or you’re a dev who’s new to web3; in either case, this guide will show you how to explore Cosmos using RPCs. Let the data flow! 🌋
Remote procedure calls (RPCs) are how users interface with computer networks, including blockchains. RPCs are the means by which information is requested and relayed from network servers to users.
Cosmos is an interoperable ecosystem of blockchain apps. Underneath Cosmos, there is an underlying layer called Tendermint. Tendermint is a network + consensus mechanism that enables blockchains to be built on top of it.
The ethos of Tendermint and Cosmos is interoperability.
Tendermint: interoperable blockchains substantiated by the Byzantine Fault Tolerant consensus algorithm.
Cosmos: interoperable blockchain applications built on top of the Tendermint core.
The Cosmos SDK enables the development of what Cosmos refers to as “the internet of blockchains.”
You need access to a node in order to read and write on a blockchain. There are three types of endpoints exposed on a Cosmos node:
the gRPC server,
the REST server,
and the Tendermint RPC endpoint.
Each end point is a different way of accessing an exposed node.
When application end-users request information through an interface (command-line) that interacts with a full-node, they are making a query. You can interact with a node using the CLI, gRPC, or REST endpoints.
Make sure you set up the keyring, which contains a private/public key pair used to interact with a node. Create a new key in the keyring by running the add subcommand with a <key_name> argument. Here’s a test example:
$ simd keys add my_validator --keyring-backend test
MY_VALIDATOR_ADDRESS=$(simd keys show my_validator -a --keyring-backend test)
The easiest way to generate transactions is using the CLI. Users run the CLI from their machines, which interacts directly with the full-node. You can create a MyQuery from the terminal by typing in the following command:
simd query staking delegations <delegatorAddress>
The format is as follows:
simd query [moduleName] [command] <arguments> --flag <flagArg>
For example, if you run the following code in the command line:
simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain --keyring-backend test
your machine will:
generate a transaction with one
Msg(x/bank'sMsgSend), and print the generated transaction to the console.ask the user for confirmation to relay the transaction from the
$MY_VALIDATOR_ADDRESSaccount.fetch
$MY_VALIDATOR_ADDRESSfrom the keyring.sign the generated transaction with the keyring's account.
broadcast the signed transaction to the network, which is possible because the CLI connects to the node's Tendermint RPC endpoint.
Protobufs is the main encoding library in the Cosmos SDK. Therefore, there are many Protobuf-based tools that are compatible with the Cosmos SDK. One such tool is gRPC, an RPC framework that supports multiple languages and allows for easy gRPC client-building. Each module exposes a Protobuf Query service that relays state queries. For example, the following function inside the application is used to hook up the Query services and a transaction service with the gRPC server, which is used to broadcast transactions:
server/types/app.go
which will output:
RegisterGRPCServer(grpc.Server)
Although the most popular transport is gRPC, there are alternatives that can cater to different tech stacks. For example, grpcurl, a module for generic debugging and testing, can be used as a gRPC request for MyQuery:
grpcurl \ -plaintext -import-path ./proto \ -proto ./proto/cosmos/staking/v1beta1/query.proto \ -d '{"address":"$MY_DELEGATOR"}' \ localhost:9090 \ cosmos.staking.v1beta1.Query/Delegations
Users can also make requests programmatically via Go, or make use of the CosmJS package which is geared towards JavaScript/TypeScript developers. CosmJS is included with the Cosmos SDK and contains npm packages which enable developers to integrate frontend user interfaces and backend servers with Cosmos blockchains that use distributed applications (DApps).
Users can also make queries through HTTP Requests to a REST server. If you cannot use gRPC, the Cosmos SDK offers REST routes via gRPC-gateway. Protobuf services auto-generate the REST server using gRPC-gateway. The following example shows you what an HTTP request for MyQuery looks like:
GET http://localhost:1317/cosmos/staking/v1beta1/delegators/{delegatorAddr}/delegations
gRPC-gateway is a tool to expose gRPC endpoints as REST endpoints. There is a REST equivalent for each gRPC endpoint.
For instance, querying a balance could be done via the /cosmos.bank.v1beta1.QueryAllBalances gRPC endpoint, or alternatively via the gRPC-gateway "/cosmos/bank/v1beta1/balances/{address}" REST endpoint. Both will return the same result.
For each RPC method defined in a Protobuf Query service, the corresponding REST endpoint is defined as an option:
// AllBalances queries the balance of all coins for a single account. rpc AllBalances(QueryAllBalancesRequest) returns (QueryAllBalancesResponse) { option (google.api.http).get = "/cosmos/bank/v1beta1/balances/{address}";
For application developers, gRPC-gateway REST routes needs to be wired up to the REST server, this is done by calling the RegisterGRPCGatewayRoutes function on the ModuleManager.
Behind a Cosmos SDK-based blockchain application is the Full-Node client. The full-node runs the state-machine which stores the status of all the users in the network. It processes transactions, block proposals, and signatures. The full-node is made up of an application and consensus engine which are connected through the Application Blockchain Interface (ABCI). ABCI is Cosmos’ native interface for request and response queries, which you can read more about here.
How does the client prepare the query and how does the node process it?
client.Context
All the data needed to process a request on the user side is stored in an object called client.Context. In particular, a client.Context stores the following:
Codec: The encoder/decoder used by the application, used to marshal the parameters and query before making the Tendermint RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf.
Account Decoder: The account decoder from the auth module, which translates []bytes into accounts.
RPC Client: The Tendermint RPC Client, or node, to which the request will be relayed to.
Keyring: A Key Manager used to sign transactions and handle other operations with keys. Output Writer: A Writer used to output the response.
Configurations: The flags configured by the user for this command, including --height, specifying the height of the blockchain to query and --indent, which indicates to add an indent to the JSON response.
The client.Context also contains various functions such as Query() which is received by a full-node and relayed back to the application through the ABCI. To understand the lifecycle of a query, click here.
The majority of remote procedure calls are queried through public nodes. These public nodes are maintained by trusted, centralized providers. Centralized data services are susceptible to manipulation, hacks, and censorship, and also come with scalability issues. Node operation must be sufficiently decentralized and diversified in order to secure data integrity, privacy, and accessibility. Lava is a Cosmos-native solution that incentivizes users to participate in a network that realizes web3’s vision of enabling people to read, write, and own their data.
