Blockchain API
The Blockchain API exposes Hydra App's BlockchainService — read-only methods to query on-chain data and a single broadcast method for fully-signed raw transactions.
JSON-RPC namespace: blockchain
Endpoints
- Get Block Number
- Get Block Header
- Get Transaction By Id
- Get Fee Estimates
- Broadcast Raw Transaction
- Get Address Balance
- Get Token Balance
- Get Token Allowance
Get Block Number
Get the current block number for a network.
Service: BlockchainServiceMethod: GetBlockNumber
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network to query |
Response:
| Field | Type | Description |
|---|---|---|
block_number | uint64 | Current block number/height |
Example Request:
TypeScript
const blockNumber = await hydraGrpcClient.getBlockNumber({
protocol: Protocol.BITCOIN,
id: '0a03cf40' // Bitcoin Signet
})
Rust
let request = tonic::Request::new(GetBlockNumberRequest {
network: Some(Network {
protocol: Protocol::Bitcoin as i32,
id: "0a03cf40".to_string(),
}),
});
let response = client.get_block_number(request).await?;
let block_number = response.into_inner().block_number;
Get Block Header
Get block header information for a specific block.
Service: BlockchainServiceMethod: GetBlockHeader
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network to query |
block_number | uint64 | NO | Block number (omit for latest) |
Response:
| Field | Type | Description |
|---|---|---|
header | BlockHeader | Block header data |
BlockHeader Object:
| Field | Type | Description |
|---|---|---|
hash | string | Block hash |
number | uint64 | Block number |
timestamp | Timestamp | Block timestamp |
parent_hash | string | Previous block hash |
Example Request:
TypeScript
// Get latest block header
const header = await hydraGrpcClient.getBlockHeader({
protocol: Protocol.EVM,
id: '11155111'
})
// Get specific block
const header = await hydraGrpcClient.getBlockHeader({
protocol: Protocol.EVM,
id: '11155111'
}, 1000000)
Rust
// Latest block
let request = tonic::Request::new(GetBlockHeaderRequest {
network: Some(Network {
protocol: Protocol::Evm as i32,
id: "11155111".to_string(),
}),
block_number: None,
});
let response = client.get_block_header(request).await?;
let header = response.into_inner().header;
Get Transaction By Id
Returns the details of a specific on-chain transaction by its ID.
Method: GetTransactionById
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Target network |
txid | string | YES | Transaction ID to query |
Response:
| Field | Type | Description |
|---|---|---|
transaction | ChainTransaction | On-chain transaction details |
Example Request:
import { GetTransactionByIdRequest } from './proto/blockchain_pb'
const request = new GetTransactionByIdRequest()
request.setNetwork({ protocol: 1, id: '0a03cf40' })
request.setTxid('abc123def456...')
const response = await client.getTransactionById(request, {})
console.log('Transaction:', response.getTransaction()?.toObject())
Get Fee Estimates
Get current fee estimates for transactions on a network.
Service: BlockchainServiceMethod: GetFeeEstimates
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network to get fees for |
Response:
| Field | Type | Description |
|---|---|---|
low | DecimalString | Low priority fee (sats/vB or gwei) |
medium | DecimalString | Medium priority fee |
high | DecimalString | High priority fee |
Example Request:
TypeScript
const fees = await hydraGrpcClient.getFeeEstimates({
protocol: Protocol.BITCOIN,
id: '0a03cf40'
})
console.log(`Low: ${fees.low} sat/vB`)
console.log(`Medium: ${fees.medium} sat/vB`)
console.log(`High: ${fees.high} sat/vB`)
Rust
let request = tonic::Request::new(GetFeeEstimatesRequest {
network: Some(Network {
protocol: Protocol::Bitcoin as i32,
id: "0a03cf40".to_string(),
}),
});
let response = client.get_fee_estimates(request).await?;
let fees = response.into_inner();
println!("Low: {} sat/vB", fees.low);
println!("Medium: {} sat/vB", fees.medium);
println!("High: {} sat/vB", fees.high);
Broadcast Raw Transaction
Broadcasts a fully signed raw transaction to the specified network. Use this when you have a pre-signed transaction in serialized form (e.g. produced offline or by an external signer).
Method: BroadcastRawTransaction
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Target network |
raw_tx | bytes | YES | Fully signed raw transaction bytes |
Response:
| Field | Type | Description |
|---|---|---|
txid | string | Resulting transaction ID |
Example Request:
import { BroadcastRawTransactionRequest } from './proto/blockchain_pb'
const request = new BroadcastRawTransactionRequest()
request.setNetwork({ protocol: 1, id: '0a03cf40' })
request.setRawTx(Buffer.from('0200000001...', 'hex'))
const response = await client.broadcastRawTransaction(request, {})
console.log('Broadcast TXID:', response.getTxid())
Example Response:
{ "txid": "abc123def456..." }
Get Address Balance
Returns the native asset balance for an arbitrary address (not necessarily this wallet's).
Method: GetAddressBalance
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Target network |
address | string | YES | Address to query |
Response:
| Field | Type | Description |
|---|---|---|
balance | DecimalString | Native asset balance |
Example Request:
import { GetAddressBalanceRequest } from './proto/blockchain_pb'
const request = new GetAddressBalanceRequest()
request.setNetwork({ protocol: 2, id: '11155111' })
request.setAddress('0xabc...')
const response = await client.getAddressBalance(request, {})
console.log('Balance:', response.getBalance()?.getValue())
Example Response:
{ "balance": "1.234567" }
Get Token Balance
Returns the token balance for the given token contract and address (EVM only).
Method: GetTokenBalance
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | EVM network |
token_id | string | YES | Token contract address |
address | string | YES | Holder address |
Response:
| Field | Type | Description |
|---|---|---|
balance | DecimalString | Token balance |
Example Request:
import { GetTokenBalanceRequest } from './proto/blockchain_pb'
const request = new GetTokenBalanceRequest()
request.setNetwork({ protocol: 2, id: '11155111' })
request.setTokenId('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48') // USDC
request.setAddress('0xabc...')
const response = await client.getTokenBalance(request, {})
console.log('Token balance:', response.getBalance()?.getValue())
Example Response:
{ "balance": "1500.000000" }
Get Token Allowance
Returns the current token allowance granted by an owner to a spender on the specified network. EVM only.
Method: GetTokenAllowance
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | EVM network |
token_id | string | YES | Token contract address |
owner | string | YES | Token owner address |
spender | string | YES | Approved spender address |
Response:
| Field | Type | Description |
|---|---|---|
allowance | TokenAllowance | Allowance details (token type + amount + approval status) |
Example Request:
import { GetTokenAllowanceRequest } from './proto/blockchain_pb'
const request = new GetTokenAllowanceRequest()
request.setNetwork({ protocol: 2, id: '11155111' })
request.setTokenId('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48')
request.setOwner('0xowner...')
request.setSpender('0xspender...')
const response = await client.getTokenAllowance(request, {})
console.log('Allowance:', response.getAllowance()?.toObject())
Common Patterns
Monitor block confirmations
Rust
async fn wait_for_confirmations(
client: &mut BlockchainServiceClient<Channel>,
network: Network,
tx_block: u64,
required_confirmations: u64,
) -> Result<(), Box<dyn std::error::Error>> {
loop {
let current_block = client
.get_block_number(GetBlockNumberRequest {
network: Some(network.clone()),
})
.await?
.into_inner()
.block_number;
let confirmations = current_block.saturating_sub(tx_block);
if confirmations >= required_confirmations {
return Ok(());
}
tokio::time::sleep(tokio::time::Duration::from_secs(15)).await;
}
}
Get appropriate fee for urgency
Rust
async fn get_fee_for_urgency(
client: &mut BlockchainServiceClient<Channel>,
network: Network,
urgent: bool,
) -> Result<String, Box<dyn std::error::Error>> {
let fees = client
.get_fee_estimates(GetFeeEstimatesRequest {
network: Some(network),
})
.await?
.into_inner();
Ok(if urgent { fees.high } else { fees.medium })
}
Error Handling
| Error Code | Description | Solution |
|---|---|---|
INVALID_ARGUMENT | Invalid network or parameters | Verify all parameters |
NOT_FOUND | Block not found | Check block number exists |
UNAVAILABLE | Node temporarily unavailable | Retry with backoff |
Best Practices
- Cache fee estimates - Update every 30-60 seconds, not per transaction
- Monitor confirmations - Poll block number for transaction confirmations
- Use appropriate fees - Balance cost vs confirmation time
- Handle reorgs - Be aware of blockchain reorganizations on short confirmation counts