description |
---|
If you run an exchange, you will likely want to interact with your Obyte node via RPC interface. |
By default, RPC service is not enabled for security reasons. To enable it, you should start your headless node differently: instead of node start.js
, cd to tools
folder and start RPC-enabled node:
cd tools
node rpc_service.js
This headless node works as usual, plus it listens to port 6332 of loop-back interface (configured in conf.js or conf.json) for JSON-RPC commands. Here are some of the commands that are usually needed by custody wallet solutions, like exchanges (these are similar to older Bitcoin node RPC methods): getinfo
, getnewaddress
, validateaddress
, getbalance
, listtransactions
, sendtoaddress
.
There are more methods available, which documentation can be read from headless wallet documentation page, which is generated from JSDoc code comments.
These are all simple HTTP request, but you can build your own custom JSON-RPC API that can use WebSockets too and even make it to listen events.
The command returns information about the current state of the DAG.
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"getinfo", "params":{} }' http://127.0.0.1:6332 | json_pp
{
"jsonrpc": "2.0",
"result": {
"connections": 5,
"last_mci": 253151,
"last_stable_mci": 253120,
"count_unhandled": 0
},
"id": 1
}
The command has no parameters and returns an object with 4 fields:
connections
: number of incoming and outgoing connectionslast_mci
: the highest known main chain index (MCI)last_stable_mci
: last stable MCI (stability point)count_unhandled
: number of unhandled units in the queue. Large number indicates that sync is still in progress, 0 or small number means that the node is synced (it can occasionally go above 0 when new units are received out of order).
This command generates a new address in your wallet. You will likely want to use it to create a new deposit address and bind it to a user account.
Example usage:
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"getnewaddress", "params":{} }' http://127.0.0.1:6332 | json_pp
{
"jsonrpc": "2.0",
"result": "QZEM3UWTG5MPKYZYRMUZLNLX5AL437O3",
"id": 1
}
The command has no parameters and the response is a newly generated wallet address (32-character string).
This command validates a wallet address and returns true
or false
.
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"validateaddress", "params":["QZEM3UWTG5MPKYZYRMUZLNLX5AL437O3"] }' http://127.0.0.1:6332 | json_pp
{
"jsonrpc": "2.0",
"result": true,
"id": 1
}
You will likely want to use it before saving a withdrawal address for a customer. There is verifyaddress
alias for this method too.
Returns the balance of the specified address or the entire wallet.
Example usage for querying wallet balance:
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"getbalance", "params":{} }' http://127.0.0.1:6332 | json_pp
{
"jsonrpc": "2.0",
"result": {
"base": {
"stable": 8000,
"pending": 0
}
},
"id": 1
}
Querying balance of an individual address:
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"getbalance", "params":["QZEM3UWTG5MPKYZYRMUZLNLX5AL437O3"] }' http://127.0.0.1:6332 | json_pp
To query the balance of the entire wallet, parameters must be empty. To query the balance of an individual address, pass it as the only element of the params array.
The response is an object, keyed by asset ID ("base" for Bytes). For each asset, there is another nested object with keys stable
and pending
for stable and pending balances respectively. Balances are in the smallest units (bytes for the native currency), they are always integers.
If the queried address is invalid, you receive error "invalid address". If the address does not belong to your wallet, you receive error "address not found".
Use it to get the list of transactions on the wallet or on a specific address.
Example request for transactions on the entire wallet (all addresses):
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"listtransactions", "params":{"since_mci": 1234} }' http://127.0.0.1:6332 | json_pp
{
"jsonrpc": "2.0",
"result": [
{
"action": "received",
"amount": 3000,
"my_address": "YA3RYZ6FEUG3YEIDIJICGVPD6PPCTIZK",
"arrPayerAddresses": [
"EENED5HS2Y7IJ5HACSH4GHSCFRBLA6CN"
],
"confirmations": 0,
"unit": "sALugOU8fjVyUvtfKPP0pxlE74GlPqOJxMbwxA1B+eE=",
"fee": 588,
"time": "1490452729",
"level": 253518
},
{
"action": "received",
"amount": 5000,
"my_address": "QZEM3UWTG5MPKYZYRMUZLNLX5AL437O3",
"arrPayerAddresses": [
"UOOHQW4ZKPTII4ZEE4ENAM5PC6LWAQHQ"
],
"confirmations": 1,
"unit": "vlt1vzMtLCIpb8K+IrvqdpNLA9DkkNAGABJ420NvOBs=",
"fee": 541,
"time": "1490452322",
"level": 253483
}
],
"id": 1
}
On individual address:
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"listtransactions", "params":["QZEM3UWTG5MPKYZYRMUZLNLX5AL437O3"] }' http://127.0.0.1:6332 | json_pp
{
"jsonrpc": "2.0",
"result": [
{
"action": "received",
"amount": 5000,
"my_address": "QZEM3UWTG5MPKYZYRMUZLNLX5AL437O3",
"arrPayerAddresses": [
"UOOHQW4ZKPTII4ZEE4ENAM5PC6LWAQHQ"
],
"confirmations": 0,
"unit": "vlt1vzMtLCIpb8K+IrvqdpNLA9DkkNAGABJ420NvOBs=",
"fee": 541,
"time": "1490452322",
"level": 253483
}
],
"id": 1
}
To query the transactions on an individual address, pass it as the only element of the params
array. In this case, only transactions in bytes are returned. If the passed address is invalid, you receive error "invalid address".
Using params
as an object
gives more flexibility of parameter ordering, but if address
is set in a object or first element of array, all other parameters are ignored.
To get the list of transactions in a particular asset, set an asset
parameter in params
. If asset
is null
or omitted, transactions in bytes will be returned.
To query the list of transactions since a particular main chain index (MCI), specify since_mci
property in the params
object, e.g. "params": {"since_mci":254000}
or "params": {"since_mci":254000; "asset": "f2TMkqij/E3qx3ALfVBA8q5ve5xAwimUm92UrEribIE="}
. The full list of matching transactions will be returned, however large it is.
To query an individual transaction, specify its unit in the params
object: "params": {"unit":"vlt1vzMtLCIpb8K+IrvqdpNLA9DkkNAGABJ420NvOBs="}
.
The response is an array of transactions in reverse chronological order.
Each transaction is described by an object with the following fields:
action
: string, one ofinvalid
,received
,sent
,moved
.amount
: integer, amount of the transaction in the smallest unitsmy_address
: string, the address that belongs to your wallet and received funds (forreceived
andmoved
actions only)addressTo
: string, the address where the funds were moved (formoved
andsent
actions only)arrPayerAddresses
: array of payer addresses (forreceived
only)confirmations
: integer 0 (pending) or 1 (final), shows confirmation status of the transactionunit
: string, unit of the transaction (also known as transaction id)fee
: integer, fee in bytestime
: integer, seconds since the Epochlevel
: integer, level of the unit in the DAGmci
: integer, MCI of the unit. It can change while the unit is still pending and becomes immutable after the unit gets final
To operate an exchange, you'll want to wait for new deposits using the following scenario:
- call
getinfo
and rememberlast_stable_mci
, you'll use it in the following (not this one) iteration; - call
listtransactions
withsince_mci
set tolast_stable_mci
remembered from the previous (not this one!) iteration; - look for transactions with
action
sreceived
andmoved
(you needmoved
in case one user withdraws to a deposit address of another user) and identify the user bymy_address
; - wait;
- repeat the cycle.
In each cycle, save last_stable_mci
in persistent storage and start from it after the wallet is restarted.
If you support several Obyte-issued assets, you'll need to call listtransactions
with that asset parameter and store last_stable_mci
from getinfo
method for each asset individually.
Use this command to withdraw bytes or another asset. Example usage:
$ curl -s --data '{"jsonrpc":"2.0", "id":1, "method":"sendtoaddress", "params":["BVVJ2K7ENPZZ3VYZFWQWK7ISPCATFIW3", 1000] }' http://127.0.0.1:6332 | json_pp
{
"jsonrpc": "2.0",
"result": "vuudtbL5ASwr0LJZ9tuV4S0j/lIsotJCKifphvGATmU=",
"id": 1
}
There are 3 parameters to this command:
- destination address (32-character string);
- amount in bytes or smallest indivisible units (integer);
- (optional) asset (44-character string or
null
). If missing ornull
, the asset is assumed to be bytes.
On success, the response is the unit of the spending transaction (string). If the command failed, an error message is returned. It is possible that the command returns error due to lack of confirmed funds, in this case you should retry the command in a few minutes. If the request timed out without returning an error, do not retry automatically, the funds might be already sent!
If the destination address is invalid, the command returns error "invalid address". To avoid this, it is recommended to validate user-entered withdrawal address using validateaddress
above or C++ function or ocore library module in NodeJs:
var validationUtils = require("ocore/validation_utils.js");
if (!validationUtils.isValidAddress(address)){
// notify user that the entered wallet address is invalid
}
More detailed documentation of all RPC service methods can be found there https://byteball.github.io/headless-obyte/rpc_service.html