Skip to content

Latest commit

 

History

History
282 lines (213 loc) · 7.34 KB

File metadata and controls

282 lines (213 loc) · 7.34 KB

Wallet Queries

Documentation for querying wallet balances and account information from the Bittensor network.

Overview

Wallet queries provide access to account balances, transaction history, and staking information. These queries are essential for monitoring account state and managing funds.

Query Functions

Balance Queries

Get Account Balance

use bittensor_rs::queries::wallets;
use bittensor_rs::format_rao_as_tao;

// Get total balance
let balance = wallets::get_balance(&client, &account_id).await?;
println!("Balance: {} TAO", format_rao_as_tao(balance));

// Get detailed balance info
let account_info = wallets::get_account_info(&client, &account_id).await?;
if let Some(info) = account_info {
    println!("Free: {} TAO", format_rao_as_tao(info.data.free));
    println!("Reserved: {} TAO", format_rao_as_tao(info.data.reserved));
    println!("Frozen: {} TAO", format_rao_as_tao(info.data.frozen));
}

Get Multiple Balances

// Query multiple accounts
let addresses = vec![account1, account2, account3];
let balances = wallets::get_balances(&client, &addresses).await?;

for (account, balance) in addresses.iter().zip(balances.iter()) {
    println!("{}: {} TAO", 
        account.to_ss58check(), 
        balance.as_ref().map(|b| format_rao_as_tao(*b)).unwrap_or_else(|| "0.000000000".to_string())
    );
}

Address Conversion

SS58 to AccountId32

use sp_core::crypto::AccountId32;

// From SS58 string
let ss58 = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
let account_id = AccountId32::from_ss58check(ss58)?;

// With custom format
let account_id = AccountId32::from_ss58check_with_version(ss58)?;

AccountId32 to SS58

use sp_core::crypto::Ss58Codec;
use bittensor_rs::core::SS58_FORMAT;

// To Bittensor SS58 format
let ss58 = account_id.to_ss58check_with_version(
    sp_core::crypto::Ss58AddressFormat::custom(SS58_FORMAT)
);

// To default format
let ss58 = account_id.to_ss58check();

Staking Queries

Total Stake

use bittensor_rs::queries::stakes;

// Get total stake for a hotkey
let total_stake = stakes::get_total_stake(&client, &hotkey).await?;
println!("Total stake: {} TAO", format_rao_as_tao(total_stake));

// Get stake for specific subnet
let stake = stakes::get_stake(&client, netuid, &hotkey).await?;

Stake Distribution

// Get all stakes for a hotkey
let all_stakes = stakes::get_all_stakes_for_hotkey(&client, &hotkey).await?;

for (subnet, stake) in all_stakes {
    println!("Subnet {}: {} TAO", subnet, format_rao_as_tao(stake));
}

// Get delegators for a hotkey
let delegators = stakes::get_delegators(&client, &hotkey).await?;
for (delegator, amount) in delegators {
    println!("Delegator {}: {} TAO", 
        delegator.to_ss58check(), 
        format_rao_as_tao(amount)
    );
}

Usage Examples

Monitor Account Activity

async fn monitor_account(client: &BittensorClient, account: &AccountId32) -> Result<()> {
    let mut last_balance = 0u128;
    
    loop {
        let balance = wallets::get_balance(client, account).await?
            .unwrap_or(0);
        
        if balance != last_balance {
            let change = if balance > last_balance {
                format!("+{} TAO", format_rao_as_tao(balance - last_balance))
            } else {
                format!("-{} TAO", format_rao_as_tao(last_balance - balance))
            };
            
            println!("Balance changed: {} (new total: {} TAO)", 
                change, format_rao_as_tao(balance)
            );
            
            last_balance = balance;
        }
        
        tokio::time::sleep(Duration::from_secs(12)).await;
    }
}

Find Rich Accounts

async fn find_wealthy_accounts(
    client: &BittensorClient, 
    accounts: &[AccountId32], 
    min_balance: u128
) -> Result<Vec<(AccountId32, u128)>> {
    let mut wealthy = Vec::new();
    
    for account in accounts {
        if let Some(balance) = wallets::get_balance(client, account).await? {
            if balance >= min_balance {
                wealthy.push((account.clone(), balance));
            }
        }
    }
    
    wealthy.sort_by(|a, b| b.1.cmp(&a.1));
    Ok(wealthy)
}

Calculate Portfolio Value

async fn calculate_portfolio(
    client: &BittensorClient,
    accounts: &[(AccountId32, String)]  // (account, name)
) -> Result<()> {
    let mut total = 0u128;
    
    println!("Portfolio Summary");
    println!("{:-<50}", "");
    
    for (account, name) in accounts {
        let balance = wallets::get_balance(client, account).await?
            .unwrap_or(0);
        
        let stake = stakes::get_total_stake(client, account).await?
            .unwrap_or(0);
        
        let account_total = balance + stake;
        total += account_total;
        
        println!("{:<20} {:>15} TAO (Balance: {}, Stake: {})",
            name,
            format_rao_as_tao(account_total),
            format_rao_as_tao(balance),
            format_rao_as_tao(stake)
        );
    }
    
    println!("{:-<50}", "");
    println!("{:<20} {:>15} TAO", "Total", format_rao_as_tao(total));
    
    Ok(())
}

Export Account Data

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct AccountExport {
    address: String,
    balance: u128,
    stake: u128,
    delegations: Vec<(String, u128)>,
    timestamp: u64,
}

async fn export_account_data(
    client: &BittensorClient,
    account: &AccountId32
) -> Result<AccountExport> {
    let balance = wallets::get_balance(client, account).await?
        .unwrap_or(0);
    
    let stake = stakes::get_total_stake(client, account).await?
        .unwrap_or(0);
    
    let delegators = stakes::get_delegators(client, account).await?
        .unwrap_or_default();
    
    let delegations: Vec<_> = delegators
        .into_iter()
        .map(|(d, a)| (d.to_ss58check(), a))
        .collect();
    
    let block = client.get_block_number().await?;
    
    Ok(AccountExport {
        address: account.to_ss58check(),
        balance,
        stake,
        delegations,
        timestamp: block,
    })
}

Performance Considerations

  1. Batch balance queries when checking multiple accounts
  2. Cache balance information for frequently accessed accounts
  3. Use event subscriptions for real-time balance monitoring
  4. Consider rate limiting for continuous monitoring

Error Handling

use bittensor_rs::Error;

match wallets::get_balance(&client, &account).await {
    Ok(Some(balance)) => println!("Balance: {} TAO", format_rao_as_tao(balance)),
    Ok(None) => println!("Account not found or zero balance"),
    Err(Error::DecodingError(e)) => println!("Failed to decode balance: {}", e),
    Err(e) => println!("Query failed: {}", e),
}

Security Notes

  1. Never log or display private keys
  2. Use secure storage for sensitive account information
  3. Validate SS58 addresses before processing
  4. Consider using hardware wallets for high-value accounts

Related Documentation