Snowblossom Docs
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_* / flakes are integers (1 SNOW = 1,000,000 flakes); fields named snow / *_snow are 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, merkleRootHashHex for hashes and specHashAddress, recipientSpecHashAddress (snow:…) for addresses.
  • The wallet tops up its key pool at start; the balance/get_status/get_unspent calls 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

MethodParamsResult
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, …}}
getfreshmark_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_unspentaddress (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_walletwallet (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_addressxpub, index, chain (0){address} - derive an address from any xpub without importing it.

Sending

MethodParamsResult
send / create_transaction (aliases)see below{tx_hash, tx_data (hex), fee (flakes), signatures_added, all_signed}
sign_transactiontx_data hexAdds every signature this wallet can; same result shape. Call repeatedly on different wallets for multisig.
broadcasttx_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) or fee_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)

MethodParamsResult
get_address_balanceaddress{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_historyaddress{tx_list:[{tx_hash, block_height}, …, {tx_hash, mempool:true}]} (node addr_index required; max 10,000 entries).
get_transactiontx_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_blockheight 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_listaddressOutputs held “for benefit of” the address.
get_id_listname, type = username | channelnameOutputs claiming that name, oldest first.
get_address_hash / get_hash_addressaddress / spechashConvert between snow:… and the 20-byte hex hash.
parse_transactiontx_data hex{tx, inner} decoded as JSON - inspect before signing.
echoanyConnectivity 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.
  • send on the CLI truncates amount × 106; the RPC snow field rounds. Use flakes for 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.