Skip to content

Transaction Broadcast API

Base URL: https://broadcast.cauldron.quest

Broadcast transactions via our broadcasting network. We ask that apps and bots that create transactions using Cauldron, Moria Protocol or other Riften Labs contracts use this API to broadcast their transcations. This is to mitigate fragmented mempool with double-spend conflicts on the network.

Available Endpoints

/broadcast

Endpoint: POST /broadcast

Status: Stable

Description: Broadcast a transaction to the network. The transaction should be encoded as hexadecimal and sent in the request body. The endpoint will broadcast the transaction to all connected nodes including our own infrastructure.

Request: - Method: POST - Content-Type: application/json - Body: JSON request with transaction and optional fields.

Request Example:

{
  "tx": "0100000001..."
}

Request Fields: - tx (required): Transaction encoded as hexadecimal string

Response (Success):

{
  "txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa"
}

Response (Error):

{
  "error": {
    "code": "REJECTED",
    "message": "Input already spent"
  }
}

Error Codes: - REJECTED: Transaction was rejected by node. - BROADCAST_FAILED: Failed to broadcast to network nodes (internal error).

Python example

import json
import sys
import urllib.request
import urllib.error

# Transaction hex string (first command-line argument)
tx_hex = sys.argv[1]

url = "http://broadcast.cauldron.quest/broadcast"
payload = {"tx": tx_hex}
data = json.dumps(payload).encode("utf-8")

req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"})
try:
    response = urllib.request.urlopen(req)
    body = response.read().decode("utf-8")
except urllib.error.HTTPError as e:
    body = e.read().decode("utf-8")

print(body)

Future Roadmap

The following features are planned for future releases:

Protection

The endpoint will support optional protection rules that can be specified in the request to reject transactions that meet certain criteria before broadcasting.

Request with Protection:

{
  "tx": "0100000001...",
  "protection": {
    "max_fee_per_byte": 100,
    "reject_token_burn": true,
    "reject_nft_burn": true
  }
}

Protection Options: - max_fee_per_byte: Maximum fee per byte in satoshis. If transaction exceeds this, it will be rejected. - reject_token_burn: If true, reject transactions that burn tokens - reject_nft_burn: If true, reject transactions that burn NFTs

Response (Protection Rejected):

{
  "error": {
    "code": "PROTECTION_REJECTED",
    "message": "Transaction rejected: fee per byte exceeds maximum",
    "details": {
      "reason": "FEE_TOO_HIGH",
      "fee_per_byte": 150,
      "max_fee_per_byte": 100
    }
  }
}

Diagnosis

When diagnosis: true is set in the request, error responses will include a diagnosis field with detailed analysis of why the transaction failed. Note: The response will be delayed while diagnosis is performed.

Request with Diagnosis:

{
  "tx": "0100000001...",
  "diagnosis": true
}

Response (Error with Diagnosis):

{
  "error": {
    "code": "BROADCAST_FAILED",
    "message": "Transaction was rejected by network nodes",
    "diagnosis": {
      "placeholder": "Detailed diagnosis information will be available in future versions"
    }
  }
}

Diagnosis Information: The diagnosis field will include detailed information such as: - Rejected inputs and their reasons - Double-spend detection with conflicting transaction IDs - Network consensus on rejection reasons - Specific rejection reasons per input

Status Check

Endpoint: GET /broadcast/status/<txid>

Check the broadcast status of a transaction. This endpoint should be called a few seconds after the initial broadcast to get detailed information about how the transaction propagated through the network.

  • txid: Transaction ID (64 character hex string)

Response Example:

{
  "txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa",
  "status": "accepted",
  "nodes_reached": 15,
  "nodes_total": 20,
  "estimated_network_reach": 0.75,
  "rejections": [
    {
      "node": "node-1",
      "reason": "insufficient_fee",
      "message": "Transaction fee too low"
    }
  ],
  "timestamp": 1709468902
}

Status Values: - broadcasting: Transaction is still being broadcast - accepted: Transaction accepted by majority of nodes - rejected: Transaction rejected by majority of nodes - pending: Transaction status is still being determined

Response (Not Found):

{
  "error": {
    "code": "TRANSACTION_NOT_FOUND",
    "message": "Transaction not found in broadcast system"
  }
}

Broadcast Simulation

The endpoint will support a dry-run mode to test transactions without actually broadcasting them to the network. This allows users to validate transactions and check for potential issues before committing to a broadcast.

Request with Dry Run:

{
  "tx": "0100000001...",
  "dry_run": true
}

Request Fields: - dry_run: If true, the transaction will be validated but not broadcast to the network

Response (Dry Run Success):

{
  "txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa",
  "dry_run": true,
  "validation": {
    "status": "valid",
    "message": "Transaction would be accepted"
  }
}

Response (Dry Run Rejected):

{
  "txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa",
  "dry_run": true,
  "validation": {
    "status": "rejected",
    "message": "Transaction would be rejected",
    "reason": "Input already spent"
  }
}

Note: When dry_run: true is set, the transaction is not broadcast to the network. The response indicates whether the transaction would be accepted or rejected if it were to be broadcast.