From dbe273f12e6fe3886bd2fc3beb5d49514ae38f56 Mon Sep 17 00:00:00 2001 From: Sorin Guga Date: Fri, 3 Jul 2026 12:15:03 +0300 Subject: [PATCH] Add Connection#get_block_height MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose the getBlockHeight RPC call so callers can compare the chain's current height against the lastValidBlockHeight returned by get_latest_blockhash — the standard blockhash-expiry check. Defaults to the connection's commitment so the comparison stays apples-to-apples. Covered by validator-backed tests and documented on the Connection & RPC page. Co-Authored-By: Claude Fable 5 --- gem/lib/solace/connection.rb | 11 +++++++++++ gem/test/solace/connection_test.rb | 26 ++++++++++++++++++++++++++ site/concepts/connection-and-rpc.md | 7 ++++++- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 gem/test/solace/connection_test.rb diff --git a/gem/lib/solace/connection.rb b/gem/lib/solace/connection.rb index 06c2ced..4968c81 100644 --- a/gem/lib/solace/connection.rb +++ b/gem/lib/solace/connection.rb @@ -157,6 +157,17 @@ def get_latest_blockhash [@last_fetched_blockhash, @last_fetched_block_height] end + # Get the current block height from the Solana node + # + # Defaults to the connection's commitment so comparisons against the + # +lastValidBlockHeight+ from {#get_latest_blockhash} stay consistent. + # + # @param commitment [String] The commitment level for the request + # @return [Integer] The current block height + def get_block_height(commitment: default_options[:commitment]) + @rpc_client.rpc_request('getBlockHeight', [{ commitment: commitment }])['result'] + end + # Get the minimum required lamports for rent exemption # # @param space [Integer] Number of bytes to allocate for the account diff --git a/gem/test/solace/connection_test.rb b/gem/test/solace/connection_test.rb new file mode 100644 index 0000000..17dc51a --- /dev/null +++ b/gem/test/solace/connection_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'test_helper' + +describe Solace::Connection do + let(:connection) { Solace::Connection.new(commitment: 'processed') } + + describe '#get_block_height' do + it 'returns the current block height' do + assert_kind_of Integer, connection.get_block_height + end + + it 'accepts a commitment override' do + finalized = connection.get_block_height(commitment: 'finalized') + processed = connection.get_block_height(commitment: 'processed') + + assert_operator finalized, :<=, processed + end + + it 'stays at or below the last valid block height' do + _blockhash, last_valid_block_height = connection.get_latest_blockhash + + assert_operator connection.get_block_height, :<=, last_valid_block_height + end + end +end diff --git a/site/concepts/connection-and-rpc.md b/site/concepts/connection-and-rpc.md index 1a668f7..390788c 100644 --- a/site/concepts/connection-and-rpc.md +++ b/site/concepts/connection-and-rpc.md @@ -35,6 +35,7 @@ test suite and most examples assume. | `get_mint_program_id(mint)` | `String \| nil` | Which token program owns a mint (SPL vs. Token-2022). | | `get_minimum_lamports_for_rent_exemption(space)` | `Integer` | Rent-exempt minimum for `space` bytes. | | `get_program_accounts(program_id, filters)` | `Array` | Accounts owned by a program. | +| `get_block_height(commitment:)` | `Integer` | Current block height (defaults to the connection's commitment). | | `get_version` / `get_health` / `get_genesis_hash` | varies | Node metadata. | ## Blockhash and rent @@ -44,10 +45,14 @@ array — the blockhash and the last valid block height: ```ruby blockhash, last_valid_height = connection.get_latest_blockhash + +# The blockhash stays usable until the chain passes last_valid_height: +connection.get_block_height <= last_valid_height # => true while the blockhash is usable ``` The composer layer fetches this for you; you only call it directly when assembling a -[`Message`](/concepts/transactions-and-messages) by hand. +[`Message`](/concepts/transactions-and-messages) by hand. `get_block_height` uses the +connection's commitment by default, so the expiry comparison is apples-to-apples. ## Sending and confirming