Class: BSV::Network::WhatsOnChain

Inherits:
Object
  • Object
show all
Defined in:
lib/bsv/network/whats_on_chain.rb

Overview

WhatsOnChain chain data provider for reading transactions and UTXOs from the BSV network.

Any object responding to #fetch_utxos(address), #fetch_transaction(txid), #current_height, #get_block_header(height), and optionally #valid_root_for_height?(root_hex, height) can serve as a chain data source; this class implements that contract by delegating to Protocols::WoCREST.

The HTTP client is injectable for testability. It must respond to #request(uri, request) and return an object with #code and #body.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(network: :mainnet, http_client: nil, protocol: nil) ⇒ WhatsOnChain

Returns a new instance of WhatsOnChain.

Parameters:

  • network (Symbol) (defaults to: :mainnet)

    :main, :mainnet, :test, :testnet, :stn (legacy compat)

  • http_client (#request, nil) (defaults to: nil)

    injectable HTTP client

  • protocol (BSV::Network::Protocols::WoCREST, nil) (defaults to: nil)

    pre-configured protocol



32
33
34
35
36
37
38
39
# File 'lib/bsv/network/whats_on_chain.rb', line 32

def initialize(network: :mainnet, http_client: nil, protocol: nil)
  if protocol
    @protocol = protocol
  else
    provider = Providers::WhatsOnChain.default(network: network, http_client: http_client)
    @protocol = provider.protocol_for(:get_tx)
  end
end

Class Method Details

.default(testnet: false, **opts) ⇒ WhatsOnChain

Returns a WhatsOnChain instance using the provider default.

Parameters:

  • testnet (Boolean) (defaults to: false)

    when true, uses the testnet endpoint

  • opts (Hash)

    forwarded to the underlying protocol (e.g. api_key:, http_client:)

Returns:



24
25
26
27
# File 'lib/bsv/network/whats_on_chain.rb', line 24

def self.default(testnet: false, **opts)
  provider = Providers::WhatsOnChain.default(testnet: testnet, **opts)
  new(protocol: provider.protocol_for(:get_tx))
end

Instance Method Details

#current_heightInteger

Return the current blockchain height.

Returns:

  • (Integer)

Raises:



71
72
73
74
75
76
# File 'lib/bsv/network/whats_on_chain.rb', line 71

def current_height
  result = @protocol.call(:current_height)
  raise_on_error(result)

  result.data
end

#fetch_transaction(txid) ⇒ BSV::Transaction::Transaction

Fetch a raw transaction by its txid and parse it.

Parameters:

  • txid (String)

    transaction ID (hex)

Returns:



61
62
63
64
65
66
# File 'lib/bsv/network/whats_on_chain.rb', line 61

def fetch_transaction(txid)
  result = @protocol.call(:get_tx, txid)
  raise_on_error(result)

  BSV::Transaction::Transaction.from_hex(result.data)
end

#fetch_utxos(address) ⇒ Array<UTXO>

Fetch unspent transaction outputs for an address.

Parameters:

  • address (String)

    BSV address

Returns:



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/bsv/network/whats_on_chain.rb', line 44

def fetch_utxos(address)
  result = @protocol.call(:get_utxos_all, address)
  raise_on_error(result)

  result.data.map do |entry|
    UTXO.new(
      tx_hash: entry[:tx_hash],
      tx_pos: entry[:tx_pos],
      satoshis: entry[:satoshis],
      height: entry[:height]
    )
  end
end

#get_block_header(height) ⇒ Hash

Fetch the block header for a given height.

Parameters:

  • height (Integer)

    block height

Returns:

  • (Hash)

    parsed block header JSON

Raises:



82
83
84
85
86
87
# File 'lib/bsv/network/whats_on_chain.rb', line 82

def get_block_header(height)
  result = @protocol.call(:get_block_header, height)
  raise_on_error(result)

  result.data
end

#valid_root_for_height?(root, height) ⇒ Boolean

Verify that a merkle root is valid for the given block height. Returns false when the block is not found (404); raises on other errors.

Parameters:

  • root (String)

    expected merkle root as hex

  • height (Integer)

    block height

Returns:

  • (Boolean)

Raises:



95
96
97
98
99
100
101
102
# File 'lib/bsv/network/whats_on_chain.rb', line 95

def valid_root_for_height?(root, height)
  result = @protocol.call(:valid_root, root, height)
  return false if result.not_found?

  raise_on_error(result)

  result.data == true
end