Real-time Cauldron tracking API
cauldron.contract.subscribe
Method: cauldron.contract.subscribe
Description: Subscribe to real-time notifications for Cauldron contract changes for a specific token. This is an Electrum API method that provides both initial state and ongoing updates when contracts are created, modified, or withdrawn.
Parameters
contract_version(integer): The contract version to subscribe to. Currently only version2is supported.token_id(string): The 32-byte token ID (category) to monitor for contract changes.
Response
Initial Response
When first subscribing, the server returns the current state of all active contracts for the specified token:
{
"utxos": [
{
"pkh": "36c0020dd39e7cd66c21f237dc53d384661a557f",
"is_withdrawn": false,
"spent_utxo_hash": "0000000000000000000000000000000000000000000000000000000000000000",
"new_utxo_hash": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890",
"new_utxo_txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa",
"new_utxo_n": 0,
"token_id": "b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92",
"sats": 776661580,
"token_amount": 16
}
],
"type": "initial"
}
Update Notifications
After the initial response, the client will receive JSON-RPC notifications whenever contracts change:
{
"jsonrpc": "2.0",
"method": "cauldron.contract.subscribe",
"params": {
"utxos": [
{
"pkh": "36c0020dd39e7cd66c21f237dc53d384661a557f",
"is_withdrawn": false,
"spent_utxo_hash": "0000000000000000000000000000000000000000000000000000000000000000",
"new_utxo_hash": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890",
"new_utxo_txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa",
"new_utxo_n": 0,
"token_id": "b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92",
"sats": 776661580,
"token_amount": 16
}
],
"type": "update"
}
}
Field Descriptions
Contract Object Fields
pkh(string): The public key hash of the contract owner in hex formatis_withdrawn(boolean): Whether the contract has been withdrawnspent_utxo_hash(string): Hash of the UTXO that was spent to create this contract (all zeros for new contracts)new_utxo_hash(string): Hash of the UTXO containing this contractnew_utxo_txid(string): Transaction ID of the transaction containing this contractnew_utxo_n(integer): Output index of the contract in the transactiontoken_id(string): The 32-byte token ID this contract is forsats(integer): Amount of satoshis locked in the contracttoken_amount(integer): Amount of tokens locked in the contract
UTXO Hash Calculation
Both spent_utxo_hash and new_utxo_hash are computed using the same algorithm:
utxo_hash = sha256(txid + n)
Where:
- txid is the transaction ID (32 bytes, in internal byte order)
- n is the output index as a little-endian 32-bit unsigned integer (4 bytes)
- The result is a single SHA-256 hash (not double-SHA256)
Examples
Example 1: New Contract
For a newly created contract:
- spent_utxo_hash = "0000000000000000000000000000000000000000000000000000000000000000" (all zeros, indicating no previous UTXO)
- new_utxo_hash is calculated from the contract's UTXO:
- txid: 94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa
- output index (n): 0
- Calculate: sha256(txid_bytes + little_endian_u32(0))
Example 2: Modified Contract
When a contract is modified (e.g., liquidity added/removed):
- spent_utxo_hash = hash of the previous contract UTXO (the one being spent)
- new_utxo_hash = hash of the new contract UTXO (the one being created)
Code Example
Python:
import hashlib
import struct
def calculate_utxo_hash(txid_hex: str, output_index: int) -> str:
"""Calculate UTXO hash from txid and output index.
Args:
txid_hex: Transaction ID as hex string (64 chars)
output_index: Output index (0-based)
Returns:
UTXO hash as hex string (64 chars)
"""
# Convert txid from hex to bytes (internal byte order)
txid_bytes = bytes.fromhex(txid_hex)
# Convert output index to little-endian 32-bit unsigned int
index_bytes = struct.pack('<I', output_index)
# Concatenate and hash
combined = txid_bytes + index_bytes
utxo_hash = hashlib.sha256(combined).digest()
return utxo_hash.hex()
# Example usage:
txid = "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa"
output_index = 0
hash_result = calculate_utxo_hash(txid, output_index)
print(f"UTXO hash: {hash_result}")
Important Notes
- Byte Order: The txid must be in internal byte order (as stored in blocks/transactions), not display/RPC order. Most libraries handle this correctly when parsing hex txids.
- Index Encoding: The output index must be encoded as a little-endian 32-bit unsigned integer (4 bytes).
- Single SHA-256: Use SHA-256 once, not double-SHA256 (which is used elsewhere in Bitcoin Cash).
- All Zeros: A
spent_utxo_hashof all zeros (0000...0000) indicates a newly created contract with no previous UTXO.
Client-Side UTXO Tracking
Important: You must track UTXOs client-side and update your local state from the notifications. The server does not topologically sort changes, so you need to process updates in two steps:
- First, add all new UTXOs from the notification
- Then, remove all used UTXOs (those with
spent_utxo_hashnot all zeros)
This two-step process ensures that UTXOs that are created and used within the same update are properly created and removed from local state.
Unsubscribing
To stop receiving notifications, use the cauldron.contract.unsubscribe method:
{
"jsonrpc": "2.0",
"id": 2,
"method": "cauldron.contract.unsubscribe",
"params": [2, "b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92"]
}
Available Electrum Servers
You can connect to the following Electrum server that supports this API:
- wss://rostrum.riften.net:443
Notes
- This is an Electrum API method that uses WebSocket connections
- The server maintains subscription limits per connection to prevent abuse
- Notifications are sent in real-time as transactions are seen in the mempool.
- The
typefield distinguishes between initial state ("initial") and updates ("update") - Contract withdrawals will have
is_withdrawn: truein update notifications - Only contracts for the specified token ID will be included in notifications
- Important: Process UTXO updates in two steps: add new UTXOs first, then remove spent UTXOs
DApp Integration
If your dapp uses this API, please let us know. We need to know if the API should be maintained.
We're also interested to hear who would wants to host a Rostrum server with Cauldron subscription API. This feedback will be used as grounds open-sourcing such server software.
Error Handling
Common error responses:
Invalid contract version: Only version 2 is currently supportedInvalid token ID: The provided token ID is not a valid 32-byte hex stringSubscription limit exceeded: Too many active subscriptions for this connection