Api

Client API

Client-specific operations for addresses and transactions

The Client API provides client-specific operations including getting deposit addresses and sending transactions.

Endpoints


Get Deposit Address

Get a deposit address for receiving funds on a specific network.

Service: ClientServiceMethod: GetDepositAddress

Parameters:

NameTypeRequiredDescription
networkNetworkYESNetwork to get deposit address for

Network Object:

FieldTypeDescription
protocolint32Network protocol (0=Bitcoin, 1=EVM)
idstringChain identifier (magic bytes for Bitcoin, chain ID for EVM)

Response:

FieldTypeDescription
addressstringDeposit address for the network

Example Request:

TypeScript
import { hydraGrpcClient } from './services/grpcWebClient'
import { Protocol } from './proto/models'

// Get Bitcoin Signet deposit address
const address = await hydraGrpcClient.getDepositAddress({
  protocol: Protocol.BITCOIN,
  id: '0a03cf40' // Bitcoin Signet magic bytes
})

// Get Ethereum Sepolia deposit address
const ethAddress = await hydraGrpcClient.getDepositAddress({
  protocol: Protocol.EVM,
  id: '11155111' // Ethereum Sepolia chain ID
})
Go
import (
    pb "github.com/hydra/hydra-go/proto"
)

client := pb.NewClientServiceClient(conn)

req := &pb.GetDepositAddressRequest{
    Network: &pb.Network{
        Protocol: pb.Protocol_BITCOIN,
        Id:       "0a03cf40",
    },
}

resp, err := client.GetDepositAddress(context.Background(), req)
if err != nil {
    log.Fatal(err)
}

address := resp.Address
Rust
use hydra_api::client_service_client::ClientServiceClient;
use hydra_api::{GetDepositAddressRequest, Network, Protocol};

let mut client = ClientServiceClient::new(channel);

let request = tonic::Request::new(GetDepositAddressRequest {
    network: Some(Network {
        protocol: Protocol::Bitcoin as i32,
        id: "0a03cf40".to_string(),
    }),
});

let response = client.get_deposit_address(request).await?;
let address = response.into_inner().address;

Example Response:

{
  "address": "tb1q..."
}

Send Transaction

Send the native asset of a network to another address.

Service: ClientServiceMethod: SendTransaction

Parameters:

NameTypeRequiredDescription
networkNetworkYESNetwork to send transaction on
to_addressstringYESRecipient address
amountSendAmountYESAmount to send
fee_optionFeeOptionYESFee option for the transaction

SendAmount Object:

FieldTypeDescription
valueDecimalStringAmount as decimal string
asset_idstringAsset identifier

FeeOption Enum:

OptionDescription
LOWLow fee, slower confirmation
MEDIUMMedium fee, moderate confirmation time
HIGHHigh fee, faster confirmation
CUSTOMCustom fee rate (sats/vB for Bitcoin, gwei for EVM)

Response:

FieldTypeDescription
txidstringTransaction ID

Example Request:

TypeScript
import { FeeOption } from './proto/models'

const response = await hydraGrpcClient.sendTransaction({
  network: {
    protocol: Protocol.BITCOIN,
    id: '0a03cf40'
  },
  toAddress: 'tb1q...',
  amount: {
    value: '0.001',
    assetId: 'BTC'
  },
  feeOption: FeeOption.MEDIUM
})

console.log('Transaction ID:', response.txid)
Go
req := &pb.SendTransactionRequest{
    Network: &pb.Network{
        Protocol: pb.Protocol_BITCOIN,
        Id:       "0a03cf40",
    },
    ToAddress: "tb1q...",
    Amount: &pb.SendAmount{
        Value:   "0.001",
        AssetId: "BTC",
    },
    FeeOption: pb.FeeOption_MEDIUM,
}

resp, err := client.SendTransaction(context.Background(), req)
if err != nil {
    log.Fatal(err)
}

txid := resp.Txid
Rust
let request = tonic::Request::new(SendTransactionRequest {
    network: Some(Network {
        protocol: Protocol::Bitcoin as i32,
        id: "0a03cf40".to_string(),
    }),
    to_address: "tb1q...".to_string(),
    amount: Some(SendAmount {
        value: "0.001".to_string(),
        asset_id: "BTC".to_string(),
    }),
    fee_option: FeeOption::Medium as i32,
});

let response = client.send_transaction(request).await?;
let txid = response.into_inner().txid;

Example Response:

{
  "txid": "abc123..."
}

Send Token Transaction

Send a token (non-native asset) to another address on a network.

Service: ClientServiceMethod: SendTokenTransaction

Parameters:

NameTypeRequiredDescription
networkNetworkYESNetwork to send transaction on
to_addressstringYESRecipient address
token_idstringYESToken contract address or asset ID
amountSendAmountYESAmount to send
fee_optionFeeOptionYESFee option for the transaction

Response:

FieldTypeDescription
txidstringTransaction ID

Example Request:

TypeScript
// Send USDC on Ethereum Sepolia
const response = await hydraGrpcClient.sendTokenTransaction({
  network: {
    protocol: Protocol.EVM,
    id: '11155111'
  },
  toAddress: '0x...',
  tokenId: '0x...', // USDC contract address
  amount: {
    value: '100.0',
    assetId: 'USDC'
  },
  feeOption: FeeOption.MEDIUM
})
Go
req := &pb.SendTokenTransactionRequest{
    Network: &pb.Network{
        Protocol: pb.Protocol_EVM,
        Id:       "11155111",
    },
    ToAddress: "0x...",
    TokenId:   "0x...",
    Amount: &pb.SendAmount{
        Value:   "100.0",
        AssetId: "USDC",
    },
    FeeOption: pb.FeeOption_MEDIUM,
}

resp, err := client.SendTokenTransaction(context.Background(), req)
Rust
let request = tonic::Request::new(SendTokenTransactionRequest {
    network: Some(Network {
        protocol: Protocol::Evm as i32,
        id: "11155111".to_string(),
    }),
    to_address: "0x...".to_string(),
    token_id: "0x...".to_string(),
    amount: Some(SendAmount {
        value: "100.0".to_string(),
        asset_id: "USDC".to_string(),
    }),
    fee_option: FeeOption::Medium as i32,
});

let response = client.send_token_transaction(request).await?;

Example Response:

{
  "txid": "0x..."
}

Bump Transaction

Increase the fee of an existing unconfirmed transaction to speed up confirmation.

Service: ClientServiceMethod: BumpTransaction

Parameters:

NameTypeRequiredDescription
networkNetworkYESNetwork where transaction exists
txidstringYESTransaction ID to bump
fee_optionFeeOptionYESNew fee option (must be higher than original)

Response:

FieldTypeDescription
txidstringNew transaction ID (or same if RBF)

Example Request:

TypeScript
const response = await hydraGrpcClient.bumpTransaction({
  network: {
    protocol: Protocol.BITCOIN,
    id: '0a03cf40'
  },
  txid: 'abc123...',
  feeOption: FeeOption.HIGH
})
Go
req := &pb.BumpTransactionRequest{
    Network: &pb.Network{
        Protocol: pb.Protocol_BITCOIN,
        Id:       "0a03cf40",
    },
    Txid:      "abc123...",
    FeeOption: pb.FeeOption_HIGH,
}

resp, err := client.BumpTransaction(context.Background(), req)
Rust
let request = tonic::Request::new(BumpTransactionRequest {
    network: Some(Network {
        protocol: Protocol::Bitcoin as i32,
        id: "0a03cf40".to_string(),
    }),
    txid: "abc123...".to_string(),
    fee_option: FeeOption::High as i32,
});

let response = client.bump_transaction(request).await?;

Example Response:

{
  "txid": "def456..."
}

Set Token Allowance

Set the allowance for a spender to use a certain amount of a token on behalf of the owner (EVM only).

Service: ClientServiceMethod: SetTokenAllowance

Parameters:

NameTypeRequiredDescription
networkNetworkYESEVM network
spenderstringYESSpender address
allowanceSetAllowanceYESAllowance details
fee_optionFeeOptionYESFee option for the transaction

SetAllowance Object:

FieldTypeDescription
token_idstringToken contract address
amountDecimalStringAmount to allow

Response:

FieldTypeDescription
txidstringTransaction ID

Example Request:

TypeScript
const response = await hydraGrpcClient.setTokenAllowance({
  network: {
    protocol: Protocol.EVM,
    id: '11155111'
  },
  spender: '0x...', // Contract or address to approve
  allowance: {
    tokenId: '0x...', // Token contract
    amount: '1000.0'
  },
  feeOption: FeeOption.MEDIUM
})
Go
req := &pb.SetTokenAllowanceRequest{
    Network: &pb.Network{
        Protocol: pb.Protocol_EVM,
        Id:       "11155111",
    },
    Spender: "0x...",
    Allowance: &pb.SetAllowance{
        TokenId: "0x...",
        Amount:  "1000.0",
    },
    FeeOption: pb.FeeOption_MEDIUM,
}

resp, err := client.SetTokenAllowance(context.Background(), req)
Rust
let request = tonic::Request::new(SetTokenAllowanceRequest {
    network: Some(Network {
        protocol: Protocol::Evm as i32,
        id: "11155111".to_string(),
    }),
    spender: "0x...".to_string(),
    allowance: Some(SetAllowance {
        token_id: "0x...".to_string(),
        amount: "1000.0".to_string(),
    }),
    fee_option: FeeOption::Medium as i32,
});

let response = client.set_token_allowance(request).await?;

Example Response:

{
  "txid": "0x..."
}

Network ID Formats

Different networks use different ID formats:

Bitcoin Networks

  • Mainnet: f9beb4d9
  • Testnet3: 0b110907
  • Testnet4: 1c163f28
  • Signet: 0a03cf40
  • Regtest: fabfb5da

EVM Networks

  • Ethereum Mainnet: 1
  • Ethereum Sepolia: 11155111
  • Arbitrum One: 42161
  • Arbitrum Sepolia: 421614
  • Optimism: 10
  • Polygon: 137

Common Patterns

Get deposit address for all configured networks

TypeScript
async function getAllDepositAddresses() {
  const networks = await hydraGrpcClient.getNetworks()
  const addresses: Record<string, string> = {}

  for (const network of networks) {
    try {
      const address = await hydraGrpcClient.getDepositAddress(network)
      addresses[network.id] = address
    } catch (error) {
      console.error(`Failed to get address for ${network.id}:`, error)
    }
  }

  return addresses
}
Go
func getAllDepositAddresses(client pb.ClientServiceClient) (map[string]string, error) {
    networksResp, err := appClient.GetNetworks(context.Background(), &pb.GetNetworksRequest{})
    if err != nil {
        return nil, err
    }

    addresses := make(map[string]string)

    for _, network := range networksResp.Networks {
        resp, err := client.GetDepositAddress(context.Background(), &pb.GetDepositAddressRequest{
            Network: network,
        })
        if err != nil {
            log.Printf("Failed to get address for %s: %v", network.Id, err)
            continue
        }

        addresses[network.Id] = resp.Address
    }

    return addresses, nil
}
Rust
async fn get_all_deposit_addresses(
    client: &mut ClientServiceClient<Channel>,
    app_client: &mut AppServiceClient<Channel>,
) -> Result<HashMap<String, String>, Box<dyn std::error::Error>> {
    let networks = app_client
        .get_networks(GetNetworksRequest {})
        .await?
        .into_inner()
        .networks;

    let mut addresses = HashMap::new();

    for network in networks {
        match client
            .get_deposit_address(GetDepositAddressRequest {
                network: Some(network.clone()),
            })
            .await
        {
            Ok(resp) => {
                addresses.insert(network.id.clone(), resp.into_inner().address);
            }
            Err(e) => {
                eprintln!("Failed to get address for {}: {}", network.id, e);
            }
        }
    }

    Ok(addresses)
}

Error Handling

Error CodeDescriptionSolution
INVALID_ARGUMENTInvalid network, address, or amountVerify all parameters are correctly formatted
FAILED_PRECONDITIONInsufficient balance or wallet not initializedCheck balance and wallet status
NOT_FOUNDTransaction not found (for BumpTransaction)Verify transaction exists and is unconfirmed
UNAVAILABLEService temporarily unavailableRetry with exponential backoff

Best Practices

  1. Validate addresses - Always validate recipient addresses before sending
  2. Check balances - Verify sufficient balance before sending transactions
  3. Use appropriate fees - Choose fee option based on urgency (LOW for non-urgent, HIGH for urgent)
  4. Cache deposit addresses - Deposit addresses don't change frequently
  5. Monitor transactions - Use the Wallet API to monitor transaction confirmations
  6. Handle errors gracefully - Network issues can occur, implement retry logic

← Back to API Reference | Next: Asset API →


Copyright © 2025