Docs › Running software › JSON-RPC (wallet)
JSON-RPC (wallet)
The wallet (SnowBlossomClient) can run an HTTP JSON-RPC 2.0 server: SnowBlossomClient client.conf rpcserver. It exposes the wallet's balance, address and transaction functions plus a few node lookups, and is the usual integration point for shops, exchanges and scripts. The node itself has no JSON API - it speaks gRPC.
Enabling the server
# client.conf
network=snowblossom
node_uri=grpc://localhost:2338
wallet_path=wallets/hot
rpc_port=8801
rpc_host=localhost # default localhost; do not expose - plain HTTP
rpc_username=user # HTTP basic auth, both required
rpc_password=change-me
java -jar SnowBlossomClient_deploy.jar client.conf rpcserver
# Docker: docker run -it --rm --network host -v snow.client:/data \
# -e snowblossom_rpc_port=8801 -e snowblossom_rpc_username=user -e snowblossom_rpc_password=pw \
# snowblossom/snowblossom client rpcserver
Conventions:
- JSON-RPC 2.0 with named parameters only. The request must be one line - the server reads a single line of the body.
- Missing/invalid auth → HTTP 401. A handler exception → JSON-RPC error
{"code":500,"message":"…"}. - Amounts: fields named
flake_*/flakesare integers (1 SNOW = 1,000,000 flakes); fields namedsnow/*_snoware decimals. Prefer flakes in integrations. - Protobuf objects are rendered as protobuf-JSON (camelCase, bytes in base64) with convenience fields added:
txHashHex,snowHashHex,prevBlockHashHex,srcTxIdHex,utxoRootHashHex,merkleRootHashHexfor hashes andspecHashAddress,recipientSpecHashAddress(snow:…) for addresses. - The wallet tops up its key pool at start; the
balance/get_status/get_unspentcalls trigger key maintenance lazily on first use.
curl -u user:change-me -H 'Content-Type: application/json' http://localhost:8801/ \
-d '{"jsonrpc":"2.0","id":1,"method":"balance"}'
Methods
Wallet
| Method | Params | Result |
|---|---|---|
balance | - | {flake_confirmed, flake_unconfirmed, flake_spendable, confirmed, unconfirmed, spendable} over all wallet addresses. |
get_status | - | {node_status: NodeStatus, balance: {flake_confirmed, flake_unconfirmed, flake_spendable, confirmed_snow, …}} |
getfresh | mark_used bool (false), generate_now bool (false) | {address, mark_used, generate_now}. Use mark_used:true for deposit addresses so they are never handed out twice nor used for change. |
get_unspent | address (optional; default: all wallet addresses) | {unspent:[{address, src_tx (hex), src_tx_out_idx, value (flakes), confirmed}]}; outputs spent in the mempool are excluded. |
import_wallet | wallet (WalletDatabase as protobuf-JSON) | Merges keys/addresses; {addresses:[…], keys:[…]}. Refuses keys into a watch-only wallet. Used to refresh watch-only wallets without restart. |
get_xpub_address | xpub, index, chain (0) | {address} - derive an address from any xpub without importing it. |
Sending
| Method | Params | Result |
|---|---|---|
send / create_transaction (aliases) | see below | {tx_hash, tx_data (hex), fee (flakes), signatures_added, all_signed} |
sign_transaction | tx_data hex | Adds every signature this wallet can; same result shape. Call repeatedly on different wallets for multisig. |
broadcast | tx_data hex | {broadcast:true, tx_hash, tx_data, fee}; error with the node's message if rejected. |
Parameters of send (unknown keys are rejected):
outputs- required array of
{address, flakes}or{address, snow}. broadcast- default true. Set false to get an unsigned/signed transaction back without sending.
sign- default true.
send_all- default false; sweep everything to exactly one output with value 0.
- change mode
- one of
change_fresh_address(default true),change_random_from_wallet,change_specific_addresses+change_addresses:[…]. - input mode
- one of
input_confirmed_then_pending(default),input_confirmed_only,input_specific_list+inputs:[{address, src_tx, src_tx_out_idx, value}]. - fee
fee_use_estimate(default: node estimate × estimated size) orfee_flat(SNOW, decimal).extra- hex bytes (≤ 100) stored in the transaction.
split_change_over- SNOW; change larger than this is split into chunks of that size.
# pay two recipients
-d '{"jsonrpc":"2.0","id":1,"method":"send","params":{"outputs":[{"address":"snow:…","flakes":1500000},{"address":"snow:…","snow":0.25}]}}'
# offline signing flow: build on the watch-only wallet, sign elsewhere, broadcast anywhere
-d '{"jsonrpc":"2.0","id":2,"method":"create_transaction","params":{"broadcast":false,"sign":false,"input_confirmed_only":true,"outputs":[{"address":"snow:…","flakes":1500000}]}}'
-d '{"jsonrpc":"2.0","id":3,"method":"sign_transaction","params":{"tx_data":"<hex>"}}'
-d '{"jsonrpc":"2.0","id":4,"method":"broadcast","params":{"tx_data":"<hex>"}}'
Lookups (via the connected node)
| Method | Params | Result |
|---|---|---|
get_address_balance | address | {balance:{flake_confirmed, flake_unconfirmed, flake_spendable, …}, history:{transaction_count, flake_total_received, total_received_snow}}; history needs a node with addr_index. |
get_address_history | address | {tx_list:[{tx_hash, block_height}, …, {tx_hash, mempool:true}]} (node addr_index required; max 10,000 entries). |
get_transaction | tx_hash hex, send_json bool | {tx_hash, tx_data, fee, status:{unknown|mempool|confirmed, heightConfirmed, confirmations}, tx_json, tx_inner_json} (node tx_index required for confirmed transactions). |
get_block | height or hash, send_json | {block_header, block_data} or with JSON the full block; empty object if unknown. Height lookups are shard 0. |
get_fbo_list | address | Outputs held “for benefit of” the address. |
get_id_list | name, type = username | channelname | Outputs claiming that name, oldest first. |
get_address_hash / get_hash_address | address / spechash | Convert between snow:… and the 20-byte hex hash. |
parse_transaction | tx_data hex | {tx, inner} decoded as JSON - inspect before signing. |
echo | any | Connectivity test. |
Operational notes
- Bind to localhost and tunnel (SSH, WireGuard) if another host needs access; there is no TLS on the RPC port.
- Watch-only + signing split: the RPC server on a watch-only wallet can do everything except
sign_transaction; a second instance with keys signs. See the integration guide. - Every new key the wallet creates is a new file in the wallet directory - back up that directory regularly for non-seed wallets.
sendon the CLI truncatesamount × 106; the RPCsnowfield rounds. Useflakesfor exact amounts.- A transaction must be funded from a single shard; on multi-shard networks a large send may fail with “Split spend required” even though the total balance suffices.