Introduction
This comment led me to realize that we don't really have good documentation on how to use Steem API. So this post is going to fix that!
The Steem full node is called steemd
, it is responsible for maintaining the database of blockchain state, and producing blocks (if you are a witness / miner). The full node provides an RPC interface; the rpc-endpoint
option specifies the interace and port to serve the RPC.
The Steem wallet is called cli_wallet
, which is a completely separate binary which runs in a separate process (or even a separate machine). The cli_wallet
is responsible for maintaining the user's private keys and signing transactions. The cli_wallet
talks to steemd
to get information about the chain, for example to respond to user balance queries. When running cli_wallet
, you need to specify the host and port of the "upstream" steemd
process with the -s
option.
The cli_wallet
also supports downstream clients which connect to the cli_wallet
. To expose the cli_wallet
RPC to downstream clients, use the -r 127.0.0.1:port
option (for example 127.0.0.1:8093
). Specifying 127.0.0.1
before the colon secures the cli_wallet
RPC interface by limiting access to the local machine. Specifying 127.0.0.1
is extremely important since anyone who can connect to the RPC socket will be able to spend your funds [1]!
[1] Specifying something other than 127.0.0.1 (i.e. a different interface or a wildcard address) with the -r
parameter of the cli_wallet
is not recommended by the developers, and should only be attempted by experts who understand the risks, are running in a properly firewalled and isolated LAN, and trust every user and machine on that LAN with direct access to their funds.
Using cli_wallet commands
The format of cli_wallet
commands is JSON HTTP. For example with curl
:
curl http://127.0.0.1:8093 --data '{"jsonrpc": "2.0", "method": "list_my_accounts", "params": [], "id": 1}'
If your wallet is unlocked, you will see a JSON object summarizing the accounts in the wallet. You can even do things that require keys (provided the wallet is unlocked):
curl http://127.0.0.1:8093 --data '{"jsonrpc": "2.0", "method": "transfer", "params": ["ned", "theoretical", "1.000 STEEM", "Thanks for the article", true], "id": 2}'
If you replace the account name "ned" in the above command with your own account name, you will send me some STEEM.
As well as HTTP, the command supports websockets. For example, you can connect with the wscat
program (from NPM) and type the same JSON as in the HTTP case, then press Enter to get a reply.
Most bots can accomplish everything they need only by talking to the cli_wallet
, but if you're curious about talking directly to steemd
, read on...
steemd commands
The steemd
API is similar but not identical. First of all, the set of available commands is different. The commands steemd
are the functions listed in database_api.hpp
in the source code, as well as commands provided by any plugins you have configured in config.ini
(see here for more information about configuring plugins).
Second, how you access commands is different. The steemd
commands are organized into different API's, and you have to use a call
command at the "outer level". The parameters of call
consist of an API name, a method name, and a JSON list of parameters to the method. It sounds complicated, but it's actually really simple:
curl http://127.0.0.1:8090 --data '{"jsonrpc": "2.0", "method": "call", "params": ["database_api", "get_block", [2889019]], "id": 3}'
Just like with cli_wallet
, you can also opt to use websockets with steemd
.
Why websockets?
Websockets are provided by steemd
because they're what we use to implement steemit.com
. The steemit.com
website is essentially an in-browser JavaScript implementation of most of the cli_wallet
functionality (with lots of additional functionality and a pretty GUI as well, of course). Websockets are much saner to use for modern interactive web applications than HTTP connections. In BitShares, the previous Graphene-powered blockchain, websockets were also used for the server to send asynchronous notifications to the client, but Steem currently has little to no functionality that uses websockets in that way.
What is the id?
The ID is a meaningless number that is echoed back to the client on each request. The reason it exists is to simplify the implementation of clients which want to be able to route an incoming response to its initiating request. It also allows distinguishing of push notifications from responses.
Error handling
On success, the "result"
member of the returned JSON dictionary contains the result of the call. If something goes wrong and an exception is thrown in the C++ code, the returned JSON will have no "result"
member, but will have an "error"
member with some diagnostic text.