Integration guide
A practical recipe for accepting SNOW - in a shop, a service, or an exchange - using only the stock software: a node with indexes, a watch-only wallet for deposits, a separate hot wallet for withdrawals, and the wallet's JSON-RPC. Where the protocol has sharp edges, they are called out.
Architecture
1. Run a node with indexes
network=snowblossom
db_type=rocksdb
db_path=node_db/mainnet
addr_index=true
tx_index=true
service_port=2338
Both indexes must be on before the first sync (they are not retroactive). Without addr_index the wallet cannot see history, cannot detect used addresses beyond balance checks, and seed recovery is unreliable; without tx_index confirmed transactions cannot be looked up by id. Keep the node on its own host or container, reachable only from your wallets. See Node.
2. Deposit addresses from a watch-only wallet
- On an offline machine create the seed wallet (
key_mode=seed, the default) and record the 12 words;show_seedprints the account xpub. - Online, create a wallet config with
watch_only=trueand runimport_xpub <xpub>; startrpcserver. - Hand out deposit addresses with
getfresh {"mark_used":true}. Marking used guarantees an address is never issued twice and moves the derivation window forward; store the address → customer mapping in your database.
Alternatively derive addresses yourself with get_xpub_address {xpub, index} and track the index - then the wallet only learns that an address is used once the node's index or a balance shows it, so keep the node's addr_index on. The wallet derives 20 addresses past the highest used one (seed_gap); do not skip far ahead.
3. Detecting deposits
- Polling:
get_address_history {address}returns confirmed entries withblock_heightand mempool entries flaggedmempool:true. For each newtx_hashcallget_transaction {tx_hash, send_json:true}, sum the outputs whoserecipientSpecHashAddressis the deposit address, and readstatus.confirmations. - Push: over gRPC,
SubscribeAddressUpdatesfires once per address immediately and again whenever a block or mempool transaction touches it; then fetch as above. TheMonitorToolclass is a reference implementation (it replays full history, so de-duplicate by address + tx id). - Confirmations: blocks come every ~10 minutes; reorganisations are cheap for the protocol, so do not credit on 1 confirmation. There is no reorg notification - keep re-checking a transaction's status until it reaches your threshold, and treat a regression to
unknownas a reversal. Six confirmations (~1 hour) is a common choice; adjust to the value involved and the network hash rate. - Do not reuse one address for everything:
GetAddressHistoryreturns at most 10,000 entries per address.
4. Withdrawals
Fund a separate hot wallet (seed or standard keys) and run its rpcserver bound to localhost:
-d '{"jsonrpc":"2.0","id":1,"method":"send","params":{"outputs":[{"address":"snow:…","flakes":250000000}],"input_confirmed_only":true}}'
# → {"tx_hash":"…","fee":…,"all_signed":true}
Store the returned tx_hash and confirm it later with get_transaction. input_confirmed_only avoids building chains of unconfirmed transactions. For stricter control use the two-step flow: create_transaction {broadcast:false, sign:false} on the watch-only wallet, move the hex to the signing host, sign_transaction, then broadcast from anywhere - the transaction id is fixed before signing, so you can record it up front. parse_transaction shows exactly what will be signed; with SIP-4 the inputs can carry their values so an offline signer sees the full picture.
Since 2.2 the same flows work from the command line without the RPC server: send 250 snow:dest --confirmed-only --yes --json for scripted withdrawals (exit status 0/1, one JSON document on stdout), send … --out tx.hex on the watch-only wallet + signtx tx.hex --out signed.hex on the signing host + broadcast signed.hex for the offline flow, and decodetx to inspect any file before signing. outputs --json and consolidate help keep a busy hot wallet's UTXO set tidy. See wallet scripting and offline signing.
5. Amounts, fees and addresses
- Use integer flakes (106 per SNOW) everywhere; the
snowdecimal fields are for humans. - Fees are per byte (≈ 2.5 flakes/byte, i.e. well under 0.001 SNOW for an ordinary payment); the wallet estimates them from the node. Post-quantum wallets make transactions of several kilobytes - budget accordingly if you use them for the hot wallet.
- Validate addresses with
get_address_hash(checks the Duck32 checksum and network label). Accept bothsnow:xyz…and barexyz…; the label is recommended. - A send is funded from one shard only; on mainnet (single shard) this never matters, on a split network a very large withdrawal may have to be split into several sends.
6. Operations checklist
- Back up the hot wallet directory after it creates new addresses (each send creates a change address); back up the cold seed once. Wallet files are unencrypted - restrict permissions.
- The RPC server is plain HTTP with basic auth: bind to localhost, tunnel if needed, rotate the password.
- Monitor the node:
get_status→node_status.head_summary.header.block_heightshould track the explorer;connected_peers> 0. - Keep clocks in sync (NTP); nodes reject blocks 45 s in the future and warn at 5 s drift.
- Watch protocol upgrades: SIP activations require node updates by a block height (the last was SIP-6 at block 358,700). Follow the releases.
- Explorer cross-check:
https://snowblossom-explorer.org/api/tx/{hash}and/api/address/{address}give an independent view for support staff.
Alternatives
- Direct gRPC (reference): skip the wallet entirely, generate keys in your own code (secp256k1 compressed, 1-of-1 spec, Skein-256-160, Duck32) and build transactions yourself. The
TransactionFactory,AddressUtilandDuck32classes are small and readable references. - Embedding the Java library: the
//client:clientand//lib:libBazel targets can be used as a library from any JVM application.