diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..85ebc1f --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,71 @@ +name: Publish to crates.io + +on: + release: + types: [published] + +env: + CARGO_TERM_COLOR: always + +jobs: + publish: + name: Publish bittensor-rs + runs-on: ubuntu-latest + # Only run if this is a bittensor-rs release + if: startsWith(github.event.release.tag_name, 'bittensor-rs-v') + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-action@stable + with: + components: rustfmt, clippy + + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install -y protobuf-compiler + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-publish-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-publish- + + - name: Verify package + working-directory: bittensor-rs + run: | + cargo publish --dry-run + + - name: Publish to crates.io + working-directory: bittensor-rs + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: | + cargo publish --no-verify + + # Notify on failure + notify-failure: + name: Notify on Failure + runs-on: ubuntu-latest + needs: publish + if: failure() + steps: + - name: Create issue on failure + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `Failed to publish ${context.payload.release.tag_name} to crates.io`, + body: `The publish workflow failed for release ${context.payload.release.tag_name}.\n\nPlease check the [workflow run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) for details.`, + labels: ['bug', 'ci'] + }) + diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..c6a0475 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,26 @@ +name: Release Please + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + bittensor-rs--release_created: ${{ steps.release.outputs['bittensor-rs--release_created'] }} + steps: + - uses: googleapis/release-please-action@v4 + id: release + with: + token: ${{ secrets.GITHUB_TOKEN }} + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..ba49d1f --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,4 @@ +{ + "bittensor-rs": "0.1.0" +} + diff --git a/LICENSE b/LICENSE index 5987d85..4f72d15 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 distributedstatemachine +Copyright (c) 2024 covenant.ai Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md new file mode 100644 index 0000000..bdf1ede --- /dev/null +++ b/README.md @@ -0,0 +1,117 @@ +# Bittensor Rust SDK + +[![CI](https://github.com/one-covenant/bittensor-rs/workflows/CI/badge.svg)](https://github.com/one-covenant/bittensor-rs/actions) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + +A collection of Rust crates for interacting with the [Bittensor](https://bittensor.com) blockchain network. + +## Workspace Structure + +This monorepo contains the following crates: + +| Crate | Description | Crates.io | +|-------|-------------|-----------| +| [`bittensor-rs`](./bittensor-rs) | Core SDK for Bittensor chain interactions | [![Crates.io](https://img.shields.io/crates/v/bittensor-rs.svg)](https://crates.io/crates/bittensor-rs) | +| [`bittensor-wallet`](./bittensor-wallet) | Wallet management with Python bindings | - | +| [`lightning-tensor`](./lightning-tensor) | Terminal UI for Bittensor | - | + +## Quick Start + +### Using bittensor-rs + +Add to your `Cargo.toml`: + +```toml +[dependencies] +bittensor-rs = "0.1" +``` + +```rust +use bittensor::{config::BittensorConfig, Service}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Connect to Finney mainnet + let config = BittensorConfig::finney("my_wallet", "my_hotkey", 1); + let service = Service::new(config).await?; + + // Query metagraph + let metagraph = service.get_metagraph(1).await?; + println!("Found {} neurons", metagraph.hotkeys.len()); + + Ok(()) +} +``` + +## Development + +### Prerequisites + +- Rust 1.70 or later +- Protocol Buffers compiler (`protoc`) + +### Building + +```bash +# Build all crates +cargo build --workspace + +# Build with all features +cargo build --workspace --all-features + +# Run tests +cargo test --workspace + +# Run specific crate tests +cargo test -p bittensor-rs +``` + +### Using Just (Recommended) + +This project includes a [justfile](./justfile) for common tasks: + +```bash +# Install just: https://github.com/casey/just +cargo install just + +# See available commands +just --list +``` + +## Documentation + +- [bittensor-rs API docs](https://docs.rs/bittensor-rs) - Full API documentation on docs.rs +- [bittensor-wallet README](./bittensor-wallet/README.md) - Wallet crate documentation + +## Contributing + +Contributions are welcome! Please follow these guidelines: + +1. **Conventional Commits**: Use [conventional commit](https://www.conventionalcommits.org/) format: + - `feat: add new feature` + - `fix: resolve bug` + - `docs: update documentation` + - `chore: maintenance task` + +2. **Pull Requests**: All changes should go through PR review + +3. **Testing**: Add tests for new functionality + +## Release Process + +This repository uses [release-please](https://github.com/googleapis/release-please) for automated releases: + +1. Merge PRs with conventional commits to `main` +2. Release-please automatically creates/updates a release PR with changelog +3. Merge the release PR to trigger a GitHub release +4. The publish workflow automatically publishes to crates.io + +## License + +MIT License - see [LICENSE](LICENSE) for details. + +## Related Projects + +- [Bittensor](https://github.com/opentensor/bittensor) - Python SDK and CLI +- [Subtensor](https://github.com/opentensor/subtensor) - Bittensor blockchain node + diff --git a/bittensor-rs/CHANGELOG.md b/bittensor-rs/CHANGELOG.md new file mode 100644 index 0000000..a04a054 --- /dev/null +++ b/bittensor-rs/CHANGELOG.md @@ -0,0 +1,61 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] - Initial Release + +### Features + +- **Connection Management** + - Connection pooling with configurable pool size + - Automatic health checks and connection monitoring + - Circuit breaker pattern for cascade failure prevention + - Exponential backoff retry logic with jitter + +- **Chain Queries** + - `get_metagraph` / `get_selective_metagraph` - Subnet metagraph data + - `get_neuron` / `get_neuron_lite` - Neuron information + - `get_balance` / `get_stake` - Account balances and stake + - `get_subnet_info` / `get_subnet_hyperparameters` - Subnet configuration + - `get_total_subnets` / `subnet_exists` - Subnet enumeration + +- **Extrinsics (Transactions)** + - Staking: `add_stake`, `remove_stake`, `delegate_stake`, `undelegate_stake` + - Weights: `set_weights`, `commit_weights`, `reveal_weights` + - Transfer: `transfer`, `transfer_keep_alive`, `transfer_all` + - Registration: `serve_axon`, `serve_prometheus`, `burned_register` + - Subnet: `register_network`, `set_subnet_identity` + - Children: `set_children`, `set_childkey_take`, `revoke_children` + - Root: `root_register`, `set_root_weights` + +- **Wallet Management** + - Load wallets from Bittensor CLI format (`~/.bittensor/wallets`) + - Create wallets from mnemonic or hex seed + - Sign and verify messages + - Subxt-compatible signer for transactions + +- **Error Handling** + - Comprehensive error types with categories + - Retry configuration per error category + - Detailed error messages with context + +- **Configuration** + - Network presets: Finney, Testnet, Local + - Custom endpoint configuration + - Connection pool settings + - Read-only mode support + +### Dependencies + +- `subxt` 0.44.0 for Substrate interactions +- `tokio` for async runtime +- `sp-core` / `sp-runtime` for cryptography + +[Unreleased]: https://github.com/one-covenant/bittensor-rs/compare/bittensor-rs-v0.1.0...HEAD +[0.1.0]: https://github.com/one-covenant/bittensor-rs/releases/tag/bittensor-rs-v0.1.0 + diff --git a/bittensor-rs/Cargo.toml b/bittensor-rs/Cargo.toml index 0970a72..3884e85 100644 --- a/bittensor-rs/Cargo.toml +++ b/bittensor-rs/Cargo.toml @@ -2,11 +2,21 @@ name = "bittensor-rs" version = "0.1.0" edition = "2021" +authors = ["covenant.ai"] description = "Standalone Rust SDK for Bittensor blockchain interactions" -rust-version = "1.70" +documentation = "https://docs.rs/bittensor-rs" +homepage = "https://github.com/one-covenant/bittensor-rs" +repository = "https://github.com/one-covenant/bittensor-rs" +readme = "README.md" license = "MIT" -repository = "https://github.com/opentensor/bittensor-rust-sdk" -keywords = ["bittensor", "blockchain", "substrate", "cryptocurrency", "decentralized"] +rust-version = "1.70" +keywords = [ + "bittensor", + "blockchain", + "substrate", + "cryptocurrency", + "decentralized", +] categories = ["cryptography::cryptocurrencies", "api-bindings"] [features] diff --git a/bittensor-rs/LICENSE b/bittensor-rs/LICENSE new file mode 100644 index 0000000..4f72d15 --- /dev/null +++ b/bittensor-rs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 covenant.ai + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/bittensor-rs/README.md b/bittensor-rs/README.md new file mode 100644 index 0000000..f13e7e6 --- /dev/null +++ b/bittensor-rs/README.md @@ -0,0 +1,237 @@ +# bittensor-rs + +[![Crates.io](https://img.shields.io/crates/v/bittensor-rs.svg)](https://crates.io/crates/bittensor-rs) +[![Documentation](https://docs.rs/bittensor-rs/badge.svg)](https://docs.rs/bittensor-rs) +[![CI](https://github.com/one-covenant/bittensor-rs/workflows/CI/badge.svg)](https://github.com/one-covenant/bittensor-rs/actions) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + +A standalone Rust SDK for interacting with the [Bittensor](https://bittensor.com) blockchain network. + +## Features + +- **Connection Pooling** - Automatic connection management with health checks, failover, and circuit breaker patterns +- **Wallet Management** - Load wallets, sign transactions, and manage keys compatible with the Bittensor CLI +- **Chain Queries** - Query metagraph data, neuron information, subnet details, balances, and stake +- **Extrinsics** - Submit transactions for staking, weight setting, registration, transfers, and more +- **Retry Logic** - Built-in exponential backoff with configurable retry strategies +- **Type-Safe API** - Strongly typed interfaces generated from Bittensor chain metadata + +## Installation + +Add to your `Cargo.toml`: + +```toml +[dependencies] +bittensor-rs = "0.1" +``` + +## Quick Start + +```rust +use bittensor::{config::BittensorConfig, Service}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Create configuration for Finney mainnet + let config = BittensorConfig::finney("my_wallet", "my_hotkey", 1); + + // Initialize the service (connects to the chain) + let service = Service::new(config).await?; + + // Query the metagraph + let metagraph = service.get_metagraph(1).await?; + println!("Found {} neurons on subnet 1", metagraph.hotkeys.len()); + + // Get current block + let block = service.get_block_number().await?; + println!("Current block: {}", block); + + Ok(()) +} +``` + +## Configuration + +The SDK supports multiple network configurations: + +```rust +use bittensor::config::BittensorConfig; + +// Finney mainnet +let config = BittensorConfig::finney("wallet", "hotkey", 1); + +// Test network +let config = BittensorConfig::testnet("wallet", "hotkey", 1); + +// Local development +let config = BittensorConfig::local("wallet", "hotkey", 1); + +// Custom endpoint with connection pool settings +let config = BittensorConfig::finney("wallet", "hotkey", 1) + .with_endpoint("wss://custom-endpoint.com:443") + .with_pool_size(5) + .with_read_only(true); +``` + +## Core Modules + +### Chain Queries + +```rust +use bittensor::{get_metagraph, get_balance, get_neuron, get_subnet_info}; + +// Get the full metagraph for a subnet +let metagraph = get_metagraph(&client, netuid).await?; + +// Query account balance +let balance = get_balance(&client, &account_id).await?; + +// Get neuron info by UID +let neuron = get_neuron(&client, netuid, uid).await?; + +// Get subnet hyperparameters +let info = get_subnet_info(&client, netuid).await?; +``` + +### Extrinsics (Transactions) + +```rust +use bittensor::extrinsics::{ + set_weights, add_stake, transfer, serve_axon, + WeightsParams, StakeParams, TransferParams, ServeAxonParams, +}; + +// Set weights on a subnet +let params = WeightsParams { + netuid: 1, + uids: vec![0, 1, 2], + weights: vec![100, 200, 300], + version_key: 0, +}; +set_weights(&client, &signer, params).await?; + +// Add stake to a hotkey +let params = StakeParams { + hotkey: hotkey_account, + amount_rao: 1_000_000_000, // 1 TAO +}; +add_stake(&client, &signer, params).await?; + +// Transfer TAO +let params = TransferParams { + dest: destination_account, + amount_rao: 500_000_000, +}; +transfer(&client, &signer, params).await?; +``` + +### Wallet Management + +```rust +use bittensor::wallet::Wallet; + +// Load an existing wallet from ~/.bittensor/wallets +let wallet = Wallet::load("my_wallet", "my_hotkey")?; + +// Get the hotkey address +println!("Hotkey: {}", wallet.hotkey()); + +// Sign arbitrary data +let signature = wallet.sign(b"message to sign"); + +// Create from mnemonic +let wallet = Wallet::from_mnemonic("wallet", "hotkey", "word1 word2 ...")?; +``` + +### Connection Management + +The SDK includes robust connection handling: + +```rust +use bittensor::{ConnectionPool, ConnectionPoolBuilder, HealthChecker}; + +// Build a connection pool with custom settings +let pool = ConnectionPoolBuilder::new(endpoints) + .max_connections(5) + .retry_config(RetryConfig::network()) + .build(); + +// Get connection metrics +let metrics = service.connection_metrics().await; +println!("Healthy connections: {}/{}", + metrics.healthy_connections, + metrics.total_connections); + +// Force reconnection if needed +service.force_reconnect().await?; +``` + +## Error Handling + +The SDK provides detailed error types with retry classification: + +```rust +use bittensor::{BittensorError, ErrorCategory}; + +match service.get_metagraph(1).await { + Ok(metagraph) => { /* success */ } + Err(e) => { + match e.category() { + ErrorCategory::Transient => { + // Retry with backoff + } + ErrorCategory::Network => { + // Network issues, try reconnecting + } + ErrorCategory::Permanent => { + // Don't retry + } + _ => {} + } + } +} +``` + +## Feature Flags + +| Feature | Description | Default | +|---------|-------------|---------| +| `wallet` | Enable wallet management functionality | ✓ | +| `generate-metadata` | Build-time metadata generation | | + +## Supported Operations + +### Queries +- `get_metagraph` / `get_selective_metagraph` - Subnet metagraph data +- `get_neuron` / `get_neuron_lite` - Neuron information +- `get_balance` / `get_stake` - Account balances +- `get_subnet_info` / `get_subnet_hyperparameters` - Subnet configuration +- `get_total_subnets` / `subnet_exists` - Subnet enumeration + +### Extrinsics +- **Staking**: `add_stake`, `remove_stake`, `delegate_stake`, `undelegate_stake` +- **Weights**: `set_weights`, `commit_weights`, `reveal_weights` +- **Transfer**: `transfer`, `transfer_keep_alive`, `transfer_all` +- **Registration**: `serve_axon`, `serve_prometheus`, `burned_register` +- **Subnet**: `register_network`, `set_subnet_identity` +- **Children**: `set_children`, `set_childkey_take`, `revoke_children` +- **Root**: `root_register`, `set_root_weights` + +## Requirements + +- Rust 1.70 or later +- Tokio runtime + +## License + +MIT License - see [LICENSE](LICENSE) for details. + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +## Related Projects + +- [Bittensor](https://github.com/opentensor/bittensor) - Python SDK +- [Subtensor](https://github.com/opentensor/subtensor) - Bittensor blockchain node + diff --git a/bittensor-rs/examples/test_axon_discovery.rs b/bittensor-rs/examples/test_axon_discovery.rs index 002cad6..fed0eb2 100644 --- a/bittensor-rs/examples/test_axon_discovery.rs +++ b/bittensor-rs/examples/test_axon_discovery.rs @@ -29,7 +29,7 @@ async fn test_metagraph_method( let runtime_api = client.runtime_api().at_latest().await?; // Import the generated API types - use bittensor::api::api; + use bittensor_rs::api::api; let metagraph = runtime_api .call( @@ -114,7 +114,7 @@ async fn test_direct_extrinsic( // First get a few hotkeys from the metagraph to query directly let runtime_api = client.runtime_api().at_latest().await?; - use bittensor::api::api; + use bittensor_rs::api::api; let metagraph = runtime_api .call( @@ -133,7 +133,7 @@ async fn test_direct_extrinsic( } // Build storage query for Axons(netuid, hotkey) - let storage_query = api::storage().subtensor_module().axons(NETUID, hotkey); + let storage_query = api::storage().subtensor_module().axons(NETUID, hotkey.clone()); // Query the storage match client diff --git a/bittensor-rs/src/config.rs b/bittensor-rs/src/config.rs index d881a21..2c9df26 100644 --- a/bittensor-rs/src/config.rs +++ b/bittensor-rs/src/config.rs @@ -11,7 +11,7 @@ use std::time::Duration; /// # Example /// /// ``` -/// use bittensor::config::BittensorConfig; +/// use bittensor_rs::config::BittensorConfig; /// /// let config = BittensorConfig::default(); /// assert_eq!(config.network, "finney"); @@ -87,7 +87,7 @@ impl BittensorConfig { /// # Example /// /// ``` - /// use bittensor::config::BittensorConfig; + /// use bittensor_rs::config::BittensorConfig; /// /// let config = BittensorConfig::finney("my_wallet", "my_hotkey", 1); /// assert_eq!(config.network, "finney"); @@ -107,7 +107,7 @@ impl BittensorConfig { /// # Example /// /// ``` - /// use bittensor::config::BittensorConfig; + /// use bittensor_rs::config::BittensorConfig; /// /// let config = BittensorConfig::testnet("my_wallet", "my_hotkey", 1); /// assert_eq!(config.network, "test"); @@ -127,7 +127,7 @@ impl BittensorConfig { /// # Example /// /// ``` - /// use bittensor::config::BittensorConfig; + /// use bittensor_rs::config::BittensorConfig; /// /// let config = BittensorConfig::local("my_wallet", "my_hotkey", 1); /// assert_eq!(config.network, "local"); @@ -151,7 +151,7 @@ impl BittensorConfig { /// # Example /// /// ``` - /// use bittensor::config::BittensorConfig; + /// use bittensor_rs::config::BittensorConfig; /// /// let config = BittensorConfig::default(); /// let endpoint = config.get_chain_endpoint(); @@ -179,7 +179,7 @@ impl BittensorConfig { /// # Example /// /// ``` - /// use bittensor::config::BittensorConfig; + /// use bittensor_rs::config::BittensorConfig; /// /// let config = BittensorConfig::default(); /// let endpoints = config.get_chain_endpoints(); @@ -221,7 +221,7 @@ impl BittensorConfig { /// # Example /// /// ``` - /// use bittensor::config::BittensorConfig; + /// use bittensor_rs::config::BittensorConfig; /// /// let config = BittensorConfig::default(); /// assert!(config.validate().is_ok()); diff --git a/bittensor-rs/src/connect/mod.rs b/bittensor-rs/src/connect/mod.rs index 3c6b6dc..e673c50 100644 --- a/bittensor-rs/src/connect/mod.rs +++ b/bittensor-rs/src/connect/mod.rs @@ -1,7 +1,56 @@ -//! Connection subsystem: pooling, health checks, connection state, retries, and monitors. +//! # Connection Management //! -//! This module groups all connection-related primitives behind a cohesive API while -//! re-exporting items to keep the public surface stable. +//! Connection pooling, health monitoring, and retry logic for Bittensor chain interactions. +//! +//! This module provides robust connection handling with: +//! +//! - **Connection Pool**: Manages multiple WebSocket connections with automatic failover +//! - **Health Checker**: Periodic health monitoring with configurable thresholds +//! - **Circuit Breaker**: Prevents cascade failures during extended outages +//! - **Retry Node**: Exponential backoff with jitter for transient errors +//! +//! # Architecture +//! +//! ```text +//! ┌─────────────────────────────────────────────────────────────┐ +//! │ ConnectionPool │ +//! │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ +//! │ │ Connection 1│ │ Connection 2│ │ Connection 3│ ... │ +//! │ │ (healthy) │ │ (healthy) │ │ (unhealthy) │ │ +//! │ └─────────────┘ └─────────────┘ └─────────────┘ │ +//! │ │ │ │ +//! │ └────────────────┼──────────────────────────────────│ +//! │ ▼ │ +//! │ HealthChecker │ +//! │ (periodic monitoring) │ +//! └─────────────────────────────────────────────────────────────┘ +//! ``` +//! +//! # Example +//! +//! ```rust,no_run +//! use bittensor_rs::connect::{ConnectionPoolBuilder, RetryConfig, HealthChecker}; +//! use std::sync::Arc; +//! +//! # async fn example() -> Result<(), Box> { +//! let endpoints = vec![ +//! "wss://entrypoint-finney.opentensor.ai:443".to_string(), +//! ]; +//! +//! let pool = Arc::new( +//! ConnectionPoolBuilder::new(endpoints) +//! .max_connections(3) +//! .retry_config(RetryConfig::network()) +//! .build() +//! ); +//! +//! pool.initialize().await?; +//! +//! // Get a healthy client +//! let client = pool.get_healthy_client().await?; +//! # Ok(()) +//! # } +//! ``` pub mod health; pub mod monitor; diff --git a/bittensor-rs/src/extrinsics/children.rs b/bittensor-rs/src/extrinsics/children.rs index 64ca4de..2332926 100644 --- a/bittensor-rs/src/extrinsics/children.rs +++ b/bittensor-rs/src/extrinsics/children.rs @@ -31,7 +31,7 @@ impl ChildKey { /// # Example /// /// ``` - /// use bittensor::extrinsics::ChildKey; + /// use bittensor_rs::extrinsics::ChildKey; /// use subxt::utils::AccountId32; /// /// let child = AccountId32::from([1u8; 32]); diff --git a/bittensor-rs/src/extrinsics/mod.rs b/bittensor-rs/src/extrinsics/mod.rs index 406fe3f..1b67298 100644 --- a/bittensor-rs/src/extrinsics/mod.rs +++ b/bittensor-rs/src/extrinsics/mod.rs @@ -1,13 +1,49 @@ -//! # Extrinsics Module -//! -//! Bittensor blockchain extrinsics (transactions) for: -//! - Staking: add_stake, remove_stake, delegate, undelegate -//! - Transfer: transfer, transfer_keep_alive -//! - Weights: set_weights, commit_weights, reveal_weights -//! - Registration: serve_axon, serve_prometheus, burned_register -//! - Subnet: register_network, set_subnet_identity -//! - Children: set_children, set_childkey_take, revoke_children -//! - Root: root_register, set_root_weights +//! # Extrinsics (Transactions) +//! +//! Submit signed transactions to the Bittensor blockchain. +//! +//! This module provides functions for all Bittensor chain operations: +//! +//! | Category | Functions | +//! |----------|-----------| +//! | **Staking** | [`add_stake`], [`remove_stake`], [`delegate_stake`], [`undelegate_stake`] | +//! | **Transfer** | [`transfer`], [`transfer_keep_alive`], [`transfer_all`] | +//! | **Weights** | [`set_weights`], [`commit_weights`], [`reveal_weights`] | +//! | **Registration** | [`serve_axon`], [`serve_prometheus`], [`burned_register`] | +//! | **Subnet** | [`register_network`], [`set_subnet_identity`] | +//! | **Children** | [`set_children`], [`set_childkey_take`], [`revoke_children`] | +//! | **Root** | [`root_register`], [`set_root_weights`] | +//! +//! # Example +//! +//! ```rust,ignore +//! use bittensor_rs::extrinsics::{set_weights, WeightsParams, add_stake, StakeParams}; +//! +//! async fn example( +//! client: &subxt::OnlineClient, +//! signer: &subxt_signer::sr25519::Keypair, +//! hotkey: subxt::config::polkadot::AccountId32, +//! ) -> Result<(), Box> { +//! // Set weights on subnet 1 +//! let params = WeightsParams { +//! netuid: 1, +//! uids: vec![0, 1, 2], +//! weights: vec![100, 200, 300], +//! version_key: 0, +//! }; +//! let response = set_weights(client, signer, params).await?; +//! +//! // Add stake to a hotkey (1 TAO = 1e9 rao) +//! let stake_params = StakeParams { +//! hotkey, +//! amount_rao: 1_000_000_000, +//! }; +//! add_stake(client, signer, stake_params).await?; +//! Ok(()) +//! } +//! ``` +//! +//! All extrinsic functions return [`ExtrinsicResponse`] with transaction status. mod children; mod registration; diff --git a/bittensor-rs/src/extrinsics/registration.rs b/bittensor-rs/src/extrinsics/registration.rs index 2ed56dd..8cbbb5e 100644 --- a/bittensor-rs/src/extrinsics/registration.rs +++ b/bittensor-rs/src/extrinsics/registration.rs @@ -38,7 +38,7 @@ impl ServeAxonParams { /// # Example /// /// ``` - /// use bittensor::extrinsics::ServeAxonParams; + /// use bittensor_rs::extrinsics::ServeAxonParams; /// /// let params = ServeAxonParams::ipv4(1, "192.168.1.1", 8080); /// assert!(params.is_ok()); diff --git a/bittensor-rs/src/extrinsics/response.rs b/bittensor-rs/src/extrinsics/response.rs index bcc5a26..29700c1 100644 --- a/bittensor-rs/src/extrinsics/response.rs +++ b/bittensor-rs/src/extrinsics/response.rs @@ -42,7 +42,7 @@ impl std::fmt::Display for ExtrinsicStatus { /// # Example /// /// ``` -/// use bittensor::extrinsics::{ExtrinsicResponse, ExtrinsicStatus}; +/// use bittensor_rs::extrinsics::{ExtrinsicResponse, ExtrinsicStatus}; /// /// // Create a successful response /// let response = ExtrinsicResponse::::success() @@ -81,7 +81,7 @@ impl ExtrinsicResponse { /// # Example /// /// ``` - /// use bittensor::extrinsics::ExtrinsicResponse; + /// use bittensor_rs::extrinsics::ExtrinsicResponse; /// /// let response: ExtrinsicResponse<()> = ExtrinsicResponse::success(); /// assert!(response.is_success()); @@ -104,7 +104,7 @@ impl ExtrinsicResponse { /// # Example /// /// ``` - /// use bittensor::extrinsics::ExtrinsicResponse; + /// use bittensor_rs::extrinsics::ExtrinsicResponse; /// /// let response: ExtrinsicResponse<()> = ExtrinsicResponse::failed("Something went wrong"); /// assert!(!response.is_success()); diff --git a/bittensor-rs/src/extrinsics/root.rs b/bittensor-rs/src/extrinsics/root.rs index cdf7ca0..63a1ae1 100644 --- a/bittensor-rs/src/extrinsics/root.rs +++ b/bittensor-rs/src/extrinsics/root.rs @@ -35,7 +35,7 @@ impl RootWeightsParams { /// # Example /// /// ``` - /// use bittensor::extrinsics::RootWeightsParams; + /// use bittensor_rs::extrinsics::RootWeightsParams; /// use subxt::utils::AccountId32; /// /// let hotkey = AccountId32::from([1u8; 32]); diff --git a/bittensor-rs/src/extrinsics/staking.rs b/bittensor-rs/src/extrinsics/staking.rs index 6e34279..64eb422 100644 --- a/bittensor-rs/src/extrinsics/staking.rs +++ b/bittensor-rs/src/extrinsics/staking.rs @@ -32,7 +32,7 @@ impl StakeParams { /// # Example /// /// ``` - /// use bittensor::extrinsics::StakeParams; + /// use bittensor_rs::extrinsics::StakeParams; /// /// let params = StakeParams::new_tao( /// "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", @@ -75,20 +75,18 @@ impl StakeParams { /// /// # Example /// -/// ```rust,no_run -/// use bittensor::extrinsics::{add_stake, StakeParams}; -/// -/// # async fn example() -> Result<(), Box> { -/// # let client: subxt::OnlineClient = todo!(); -/// # let signer: bittensor::WalletSigner = todo!(); -/// let params = StakeParams::new_tao( -/// "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", -/// 1, // netuid -/// 1.0 // TAO amount -/// ); -/// let result = add_stake(&client, &signer, params).await?; -/// # Ok(()) -/// # } +/// ```rust,ignore +/// use bittensor_rs::extrinsics::{add_stake, StakeParams}; +/// +/// async fn example(client: &subxt::OnlineClient, signer: &impl subxt::tx::Signer) -> Result<(), Box> { +/// let params = StakeParams::new_tao( +/// "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", +/// 1, // netuid +/// 1.0 // TAO amount +/// ); +/// let result = add_stake(client, signer, params).await?; +/// Ok(()) +/// } /// ``` pub async fn add_stake( client: &OnlineClient, diff --git a/bittensor-rs/src/extrinsics/subnet.rs b/bittensor-rs/src/extrinsics/subnet.rs index 3491fa3..7a9b692 100644 --- a/bittensor-rs/src/extrinsics/subnet.rs +++ b/bittensor-rs/src/extrinsics/subnet.rs @@ -39,7 +39,7 @@ impl SubnetIdentity { /// # Example /// /// ``` - /// use bittensor::extrinsics::SubnetIdentity; + /// use bittensor_rs::extrinsics::SubnetIdentity; /// /// let identity = SubnetIdentity::new("My Subnet"); /// assert_eq!(identity.name, "My Subnet"); diff --git a/bittensor-rs/src/extrinsics/transfer.rs b/bittensor-rs/src/extrinsics/transfer.rs index e3ae828..a18d62f 100644 --- a/bittensor-rs/src/extrinsics/transfer.rs +++ b/bittensor-rs/src/extrinsics/transfer.rs @@ -31,7 +31,7 @@ impl TransferParams { /// # Example /// /// ``` - /// use bittensor::extrinsics::TransferParams; + /// use bittensor_rs::extrinsics::TransferParams; /// /// let params = TransferParams::new_tao( /// "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", @@ -77,19 +77,17 @@ impl TransferParams { /// /// # Example /// -/// ```rust,no_run -/// use bittensor::extrinsics::{transfer, TransferParams}; +/// ```rust,ignore +/// use bittensor_rs::extrinsics::{transfer, TransferParams}; /// -/// # async fn example() -> Result<(), Box> { -/// # let client: subxt::OnlineClient = todo!(); -/// # let signer: bittensor::WalletSigner = todo!(); -/// let params = TransferParams::new_tao( -/// "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", -/// 1.0 -/// ); -/// let result = transfer(&client, &signer, params).await?; -/// # Ok(()) -/// # } +/// async fn example(client: &subxt::OnlineClient, signer: &impl subxt::tx::Signer) -> Result<(), Box> { +/// let params = TransferParams::new_tao( +/// "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", +/// 1.0 +/// ); +/// let result = transfer(client, signer, params).await?; +/// Ok(()) +/// } /// ``` pub async fn transfer( client: &OnlineClient, diff --git a/bittensor-rs/src/extrinsics/weights.rs b/bittensor-rs/src/extrinsics/weights.rs index 54687c3..0631f91 100644 --- a/bittensor-rs/src/extrinsics/weights.rs +++ b/bittensor-rs/src/extrinsics/weights.rs @@ -31,9 +31,9 @@ impl WeightsParams { /// # Example /// /// ``` - /// use bittensor::extrinsics::WeightsParams; + /// use bittensor_rs::extrinsics::WeightsParams; /// - /// let params = WeightsParams::new(1, vec![0, 1, 2], vec![100, 200, 300]); + /// let params = WeightsParams::new(1, vec![0, 1, 2], vec![100, 200, 300]).unwrap(); /// assert_eq!(params.netuid, 1); /// assert_eq!(params.uids.len(), 3); /// ``` @@ -157,16 +157,14 @@ fn compute_commit_hash(uids: &[u16], weights: &[u16], salt: &[u16], version_key: /// /// # Example /// -/// ```rust,no_run -/// use bittensor::extrinsics::{set_weights, WeightsParams}; +/// ```rust,ignore +/// use bittensor_rs::extrinsics::{set_weights, WeightsParams}; /// -/// # async fn example() -> Result<(), Box> { -/// # let client: subxt::OnlineClient = todo!(); -/// # let signer: bittensor::WalletSigner = todo!(); -/// let params = WeightsParams::new(1, vec![0, 1, 2], vec![100, 200, 300]); -/// let result = set_weights(&client, &signer, params).await?; -/// # Ok(()) -/// # } +/// async fn example(client: &subxt::OnlineClient, signer: &impl subxt::tx::Signer) -> Result<(), Box> { +/// let params = WeightsParams::new(1, vec![0, 1, 2], vec![100, 200, 300]).unwrap(); +/// let result = set_weights(client, signer, params).await?; +/// Ok(()) +/// } /// ``` pub async fn set_weights( client: &OnlineClient, @@ -275,7 +273,7 @@ mod tests { #[test] fn test_weights_params() { - let params = WeightsParams::new(1, vec![0, 1, 2], vec![100, 200, 300]); + let params = WeightsParams::new(1, vec![0, 1, 2], vec![100, 200, 300]).unwrap(); assert_eq!(params.netuid, 1); assert_eq!(params.uids.len(), 3); assert_eq!(params.weights.len(), 3); @@ -284,13 +282,15 @@ mod tests { #[test] fn test_weights_params_builder() { - let params = WeightsParams::new(1, vec![0], vec![100]).with_version_key(42); + let params = WeightsParams::new(1, vec![0], vec![100]) + .unwrap() + .with_version_key(42); assert_eq!(params.version_key, 42); } #[test] fn test_normalize_weights() { - let params = WeightsParams::new(1, vec![0, 1], vec![100, 100]); + let params = WeightsParams::new(1, vec![0, 1], vec![100, 100]).unwrap(); let normalized = params.to_normalized(); assert_eq!(normalized.len(), 2); diff --git a/bittensor-rs/src/lib.rs b/bittensor-rs/src/lib.rs index 408e18c..4507476 100644 --- a/bittensor-rs/src/lib.rs +++ b/bittensor-rs/src/lib.rs @@ -11,7 +11,7 @@ //! # Quick Start //! //! ```rust,no_run -//! use bittensor::{config::BittensorConfig, Service}; +//! use bittensor_rs::{config::BittensorConfig, Service}; //! //! #[tokio::main] //! async fn main() -> Result<(), Box> { diff --git a/bittensor-rs/src/queries/account.rs b/bittensor-rs/src/queries/account.rs index d8ca816..8a8d8e7 100644 --- a/bittensor-rs/src/queries/account.rs +++ b/bittensor-rs/src/queries/account.rs @@ -24,7 +24,7 @@ use subxt::PolkadotConfig; /// # Example /// /// ```rust,no_run -/// use bittensor::queries::get_balance; +/// use bittensor_rs::queries::get_balance; /// /// # async fn example() -> Result<(), Box> { /// # let client: subxt::OnlineClient = todo!(); diff --git a/bittensor-rs/src/queries/metagraph.rs b/bittensor-rs/src/queries/metagraph.rs index 580a18b..074ca73 100644 --- a/bittensor-rs/src/queries/metagraph.rs +++ b/bittensor-rs/src/queries/metagraph.rs @@ -36,7 +36,7 @@ pub type SelectiveMetagraph = /// # Example /// /// ```rust,no_run -/// use bittensor::queries::get_metagraph; +/// use bittensor_rs::queries::get_metagraph; /// /// # async fn example() -> Result<(), Box> { /// # let client: subxt::OnlineClient = todo!(); diff --git a/bittensor-rs/src/queries/mod.rs b/bittensor-rs/src/queries/mod.rs index 97eddf8..d9c6aba 100644 --- a/bittensor-rs/src/queries/mod.rs +++ b/bittensor-rs/src/queries/mod.rs @@ -1,10 +1,33 @@ -//! # Query Modules +//! # Chain Queries //! -//! Chain state queries for the Bittensor network: -//! - Account balance queries -//! - Metagraph queries -//! - Subnet information queries -//! - Neuron information queries +//! Read-only queries against Bittensor blockchain state. +//! +//! This module provides functions for querying: +//! +//! - **Account**: Balances, stake amounts, and stake info +//! - **Metagraph**: Full or selective metagraph data for subnets +//! - **Neurons**: Individual neuron info and UID lookups +//! - **Subnets**: Subnet existence, hyperparameters, and metadata +//! +//! # Example +//! +//! ```rust,ignore +//! use bittensor_rs::queries::{get_metagraph, get_balance, get_neuron}; +//! +//! async fn example(client: &subxt::OnlineClient, account_id: &subxt::config::polkadot::AccountId32) -> Result<(), Box> { +//! // Get metagraph for subnet 1 +//! let metagraph = get_metagraph(client, 1).await?; +//! +//! // Check account balance +//! let balance = get_balance(client, account_id).await?; +//! +//! // Get specific neuron by UID +//! let neuron = get_neuron(client, 1, 0).await?; +//! Ok(()) +//! } +//! ``` +//! +//! All query functions accept a subxt `OnlineClient` and return typed results. mod account; mod metagraph; diff --git a/bittensor-rs/src/service.rs b/bittensor-rs/src/service.rs index 421c5bf..57f7dbb 100644 --- a/bittensor-rs/src/service.rs +++ b/bittensor-rs/src/service.rs @@ -1,6 +1,54 @@ //! # Bittensor Service //! -//! Central service for all Bittensor chain interactions. +//! Central service for all Bittensor chain interactions with connection pooling, +//! automatic failover, and circuit breaker protection. +//! +//! The [`Service`] struct is the main entry point for interacting with the Bittensor +//! blockchain. It manages: +//! +//! - **Connection pooling**: Multiple connections with automatic health checks +//! - **Retry logic**: Exponential backoff for transient failures +//! - **Circuit breaker**: Prevents cascade failures during outages +//! - **Transaction signing**: Uses the configured wallet hotkey +//! +//! # Example +//! +//! ```rust,no_run +//! use bittensor_rs::{config::BittensorConfig, Service}; +//! +//! #[tokio::main] +//! async fn main() -> Result<(), Box> { +//! let config = BittensorConfig::finney("my_wallet", "my_hotkey", 1); +//! let service = Service::new(config).await?; +//! +//! // Query metagraph +//! let metagraph = service.get_metagraph(1).await?; +//! println!("Neurons: {}", metagraph.hotkeys.len()); +//! +//! // Set weights +//! service.set_weights(1, vec![(0, 100), (1, 200)]).await?; +//! +//! // Graceful shutdown +//! service.shutdown().await; +//! Ok(()) +//! } +//! ``` +//! +//! # Connection Monitoring +//! +//! Monitor connection health and metrics: +//! +//! ```rust,no_run +//! # use bittensor_rs::{config::BittensorConfig, Service}; +//! # async fn example(service: Service) -> Result<(), Box> { +//! let metrics = service.connection_metrics().await; +//! println!("Healthy: {}/{}", metrics.healthy_connections, metrics.total_connections); +//! +//! // Force reconnect if needed +//! service.force_reconnect().await?; +//! # Ok(()) +//! # } +//! ``` use crate::config::BittensorConfig; use crate::connect::{CircuitBreaker, HealthChecker, RetryConfig, RetryNode}; @@ -568,8 +616,8 @@ impl Service { /// # Example /// /// ```rust,no_run - /// # use bittensor::Service; - /// # use bittensor::config::BittensorConfig; + /// # use bittensor_rs::Service; + /// # use bittensor_rs::config::BittensorConfig; /// # #[tokio::main] /// # async fn main() -> Result<(), Box> { /// # let config = BittensorConfig::default(); @@ -637,8 +685,8 @@ impl Service { /// # Example /// /// ```rust,no_run - /// # use bittensor::Service; - /// # use bittensor::config::BittensorConfig; + /// # use bittensor_rs::Service; + /// # use bittensor_rs::config::BittensorConfig; /// # #[tokio::main] /// # async fn main() -> Result<(), Box> { /// # let config = BittensorConfig::default(); @@ -679,8 +727,8 @@ impl Service { /// # Example /// /// ```rust,no_run - /// # use bittensor::Service; - /// # use bittensor::config::BittensorConfig; + /// # use bittensor_rs::Service; + /// # use bittensor_rs::config::BittensorConfig; /// # #[tokio::main] /// # async fn main() -> Result<(), Box> { /// # let config = BittensorConfig::default(); @@ -734,8 +782,8 @@ impl Service { /// # Example /// /// ```rust,no_run - /// # use bittensor::Service; - /// # use bittensor::config::BittensorConfig; + /// # use bittensor_rs::Service; + /// # use bittensor_rs::config::BittensorConfig; /// # #[tokio::main] /// # async fn main() -> Result<(), Box> { /// # let config = BittensorConfig::default(); @@ -758,8 +806,8 @@ impl Service { /// # Example /// /// ```rust,no_run - /// # use bittensor::Service; - /// # use bittensor::config::BittensorConfig; + /// # use bittensor_rs::Service; + /// # use bittensor_rs::config::BittensorConfig; /// # #[tokio::main] /// # async fn main() -> Result<(), Box> { /// # let config = BittensorConfig::default(); @@ -789,8 +837,8 @@ impl Service { /// # Example /// /// ```rust,no_run - /// # use bittensor::Service; - /// # use bittensor::config::BittensorConfig; + /// # use bittensor_rs::Service; + /// # use bittensor_rs::config::BittensorConfig; /// # #[tokio::main] /// # async fn main() -> Result<(), Box> { /// # let config = BittensorConfig::default(); diff --git a/bittensor-rs/src/types/account.rs b/bittensor-rs/src/types/account.rs index 3004729..e10914b 100644 --- a/bittensor-rs/src/types/account.rs +++ b/bittensor-rs/src/types/account.rs @@ -12,7 +12,7 @@ use std::str::FromStr; /// # Example /// /// ``` -/// use bittensor::types::{Hotkey, hotkey_to_account_id}; +/// use bittensor_rs::types::{Hotkey, hotkey_to_account_id}; /// /// let hotkey = Hotkey::new("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".to_string()).unwrap(); /// let account_id = hotkey_to_account_id(&hotkey); @@ -29,7 +29,7 @@ pub fn hotkey_to_account_id(hotkey: &Hotkey) -> Result for u64 { /// # Example /// /// ``` -/// use bittensor::types::tao_to_rao; +/// use bittensor_rs::types::tao_to_rao; /// /// assert_eq!(tao_to_rao(1.0), 1_000_000_000); /// assert_eq!(tao_to_rao(0.5), 500_000_000); @@ -293,7 +293,7 @@ pub fn tao_to_rao(tao: f64) -> u64 { /// # Example /// /// ``` -/// use bittensor::types::rao_to_tao; +/// use bittensor_rs::types::rao_to_tao; /// /// assert_eq!(rao_to_tao(1_000_000_000), 1.0); /// assert_eq!(rao_to_tao(500_000_000), 0.5); diff --git a/bittensor-rs/src/types/hotkey.rs b/bittensor-rs/src/types/hotkey.rs index 61d5e6b..59b9c22 100644 --- a/bittensor-rs/src/types/hotkey.rs +++ b/bittensor-rs/src/types/hotkey.rs @@ -17,7 +17,7 @@ use crate::AccountId; /// # Example /// /// ``` -/// use bittensor::types::Hotkey; +/// use bittensor_rs::types::Hotkey; /// /// let hotkey = Hotkey::new("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".to_string()); /// assert!(hotkey.is_ok()); @@ -40,7 +40,7 @@ impl Hotkey { /// # Example /// /// ``` - /// use bittensor::types::Hotkey; + /// use bittensor_rs::types::Hotkey; /// /// // Valid SS58 address /// let valid = Hotkey::new("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".to_string()); @@ -93,7 +93,7 @@ impl Hotkey { /// # Example /// /// ``` - /// use bittensor::types::Hotkey; + /// use bittensor_rs::types::Hotkey; /// /// let hotkey = Hotkey::new("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".to_string()).unwrap(); /// assert_eq!(hotkey.as_str(), "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"); @@ -117,7 +117,7 @@ impl Hotkey { /// # Example /// /// ``` - /// use bittensor::types::Hotkey; + /// use bittensor_rs::types::Hotkey; /// /// let hotkey = Hotkey::new("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".to_string()).unwrap(); /// let account_id = hotkey.to_account_id(); @@ -133,7 +133,7 @@ impl Hotkey { /// # Example /// /// ``` - /// use bittensor::types::Hotkey; + /// use bittensor_rs::types::Hotkey; /// use std::str::FromStr; /// /// let hotkey = Hotkey::new("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".to_string()).unwrap(); diff --git a/bittensor-rs/src/utils.rs b/bittensor-rs/src/utils.rs index 8af6718..0122341 100644 --- a/bittensor-rs/src/utils.rs +++ b/bittensor-rs/src/utils.rs @@ -35,7 +35,7 @@ pub struct NormalizedWeight { /// # Example /// /// ``` -/// use bittensor::utils::{normalize_weights, NormalizedWeight}; +/// use bittensor_rs::utils::{normalize_weights, NormalizedWeight}; /// /// let weights = vec![(0, 100), (1, 100)]; /// let normalized = normalize_weights(&weights); @@ -112,8 +112,8 @@ pub fn set_weights_payload( /// # Example /// /// ```rust,no_run -/// use bittensor::types::Hotkey; -/// use bittensor::utils::verify_bittensor_signature; +/// use bittensor_rs::types::Hotkey; +/// use bittensor_rs::utils::verify_bittensor_signature; /// /// let hotkey = Hotkey::new("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".to_string()).unwrap(); /// let result = verify_bittensor_signature(&hotkey, "abcd...", b"message"); diff --git a/bittensor-rs/src/wallet/mod.rs b/bittensor-rs/src/wallet/mod.rs index ec68f6d..c649b3f 100644 --- a/bittensor-rs/src/wallet/mod.rs +++ b/bittensor-rs/src/wallet/mod.rs @@ -6,7 +6,7 @@ //! # Example //! //! ```rust,no_run -//! use bittensor::wallet::Wallet; +//! use bittensor_rs::wallet::Wallet; //! //! // Load an existing wallet //! let wallet = Wallet::load("my_wallet", "my_hotkey")?; @@ -28,8 +28,8 @@ pub use signer::WalletSigner; use crate::error::BittensorError; use crate::types::Hotkey; use crate::AccountId; -use std::path::{Path, PathBuf}; use sp_core::{sr25519, Pair}; +use std::path::{Path, PathBuf}; /// Bittensor wallet for managing keys and signing transactions /// @@ -40,12 +40,12 @@ use sp_core::{sr25519, Pair}; /// # Example /// /// ```rust,no_run -/// use bittensor::wallet::Wallet; +/// use bittensor_rs::wallet::Wallet; /// /// // Load from default ~/.bittensor/wallets path /// let wallet = Wallet::load("my_wallet", "my_hotkey")?; /// println!("Hotkey: {}", wallet.hotkey()); -/// # Ok::<(), bittensor::BittensorError>(()) +/// # Ok::<(), bittensor_rs::BittensorError>(()) /// ``` #[derive(Clone)] pub struct Wallet { @@ -91,10 +91,10 @@ impl Wallet { /// # Example /// /// ```rust,no_run - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// /// let wallet = Wallet::load("default", "default")?; - /// # Ok::<(), bittensor::BittensorError>(()) + /// # Ok::<(), bittensor_rs::BittensorError>(()) /// ``` pub fn load(wallet_name: &str, hotkey_name: &str) -> Result { let wallet_path = Self::default_wallet_path()?; @@ -112,12 +112,12 @@ impl Wallet { /// # Example /// /// ```rust,no_run - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// use std::path::PathBuf; /// /// let base_path = PathBuf::from("/custom/wallets"); /// let wallet = Wallet::load_from_path("my_wallet", "my_hotkey", &base_path)?; - /// # Ok::<(), bittensor::BittensorError>(()) + /// # Ok::<(), bittensor_rs::BittensorError>(()) /// ``` pub fn load_from_path( wallet_name: &str, @@ -161,9 +161,9 @@ impl Wallet { /// # Example /// /// ``` - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// - /// let wallet = Wallet::create_random("test_wallet", "test_hotkey"); + /// let wallet = Wallet::create_random("test_wallet", "test_hotkey").unwrap(); /// assert!(!wallet.hotkey().as_str().is_empty()); /// ``` pub fn create_random(wallet_name: &str, hotkey_name: &str) -> Result { @@ -190,11 +190,11 @@ impl Wallet { /// # Example /// /// ```rust,no_run - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// /// let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; /// let wallet = Wallet::from_mnemonic("test", "test", mnemonic)?; - /// # Ok::<(), bittensor::BittensorError>(()) + /// # Ok::<(), bittensor_rs::BittensorError>(()) /// ``` pub fn from_mnemonic( wallet_name: &str, @@ -230,7 +230,7 @@ impl Wallet { /// # Example /// /// ``` - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// /// let seed = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; /// let wallet = Wallet::from_seed_hex("test", "test", seed).unwrap(); @@ -272,9 +272,9 @@ impl Wallet { /// # Example /// /// ``` - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// - /// let wallet = Wallet::create_random("test", "test"); + /// let wallet = Wallet::create_random("test", "test").unwrap(); /// let hotkey = wallet.hotkey(); /// println!("Address: {}", hotkey); /// ``` @@ -302,9 +302,9 @@ impl Wallet { /// # Example /// /// ``` - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// - /// let wallet = Wallet::create_random("test", "test"); + /// let wallet = Wallet::create_random("test", "test").unwrap(); /// let signature = wallet.sign(b"hello world"); /// assert_eq!(signature.len(), 64); /// ``` @@ -318,9 +318,9 @@ impl Wallet { /// # Example /// /// ``` - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// - /// let wallet = Wallet::create_random("test", "test"); + /// let wallet = Wallet::create_random("test", "test").unwrap(); /// let sig_hex = wallet.sign_hex(b"hello"); /// assert_eq!(sig_hex.len(), 128); // 64 bytes = 128 hex chars /// ``` @@ -333,9 +333,9 @@ impl Wallet { /// # Example /// /// ``` - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// - /// let wallet = Wallet::create_random("test", "test"); + /// let wallet = Wallet::create_random("test", "test").unwrap(); /// let signer = wallet.signer(); /// ``` pub fn signer(&self) -> WalletSigner { @@ -361,9 +361,9 @@ impl Wallet { /// # Example /// /// ``` - /// use bittensor::wallet::Wallet; + /// use bittensor_rs::wallet::Wallet; /// - /// let wallet = Wallet::create_random("test", "test"); + /// let wallet = Wallet::create_random("test", "test").unwrap(); /// let message = b"hello world"; /// let signature = wallet.sign(message); /// assert!(wallet.verify(message, &signature)); @@ -439,7 +439,7 @@ mod tests { #[test] fn test_create_random_wallet() { - let wallet = Wallet::create_random("test_wallet", "test_hotkey"); + let wallet = Wallet::create_random("test_wallet", "test_hotkey").unwrap(); assert_eq!(wallet.name, "test_wallet"); assert_eq!(wallet.hotkey_name, "test_hotkey"); // Check that we have a valid hotkey @@ -449,7 +449,7 @@ mod tests { #[test] fn test_sign_and_verify() { - let wallet = Wallet::create_random("test", "test"); + let wallet = Wallet::create_random("test", "test").unwrap(); let message = b"test message"; let signature = wallet.sign(message); @@ -459,7 +459,7 @@ mod tests { #[test] fn test_sign_hex() { - let wallet = Wallet::create_random("test", "test"); + let wallet = Wallet::create_random("test", "test").unwrap(); let sig_hex = wallet.sign_hex(b"test"); assert_eq!(sig_hex.len(), 128); assert!(hex::decode(&sig_hex).is_ok()); @@ -488,21 +488,21 @@ mod tests { #[test] fn test_verify_wrong_signature() { - let wallet = Wallet::create_random("test", "test"); + let wallet = Wallet::create_random("test", "test").unwrap(); let wrong_sig = vec![0u8; 64]; assert!(!wallet.verify(b"test", &wrong_sig)); } #[test] fn test_verify_wrong_length() { - let wallet = Wallet::create_random("test", "test"); + let wallet = Wallet::create_random("test", "test").unwrap(); let short_sig = vec![0u8; 32]; assert!(!wallet.verify(b"test", &short_sig)); } #[test] fn test_account_id() { - let wallet = Wallet::create_random("test", "test"); + let wallet = Wallet::create_random("test", "test").unwrap(); let account_id = wallet.account_id(); let hotkey = wallet.hotkey(); @@ -512,7 +512,7 @@ mod tests { #[test] fn test_coldkey_not_unlocked() { - let wallet = Wallet::create_random("test", "test"); + let wallet = Wallet::create_random("test", "test").unwrap(); assert!(!wallet.is_coldkey_unlocked()); assert!(wallet.coldkey().is_none()); } diff --git a/bittensor-rs/src/wallet/signer.rs b/bittensor-rs/src/wallet/signer.rs index 9ed4986..137965e 100644 --- a/bittensor-rs/src/wallet/signer.rs +++ b/bittensor-rs/src/wallet/signer.rs @@ -18,7 +18,7 @@ impl WalletSigner { /// # Example /// /// ```ignore - /// use bittensor::wallet::WalletSigner; + /// use bittensor_rs::wallet::WalletSigner; /// use subxt_signer::sr25519::Keypair; /// /// let keypair = Keypair::from_uri(&"//Alice".parse().unwrap()).unwrap(); diff --git a/bittensor-rs/tests/connection_reliability_tests.rs b/bittensor-rs/tests/connection_reliability_tests.rs index c8c3ac6..956c045 100644 --- a/bittensor-rs/tests/connection_reliability_tests.rs +++ b/bittensor-rs/tests/connection_reliability_tests.rs @@ -1,6 +1,6 @@ //! Integration tests for connection reliability improvements -use bittensor::{ +use bittensor_rs::{ config::BittensorConfig, BittensorError, ConnectionManager, ConnectionPool, ConnectionPoolBuilder, ConnectionState, HealthChecker, RetryConfig, }; diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..20adf85 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "packages": { + "bittensor-rs": { + "release-type": "rust", + "component": "bittensor-rs", + "changelog-path": "CHANGELOG.md", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "draft": false, + "prerelease": false, + "extra-files": [] + } + }, + "changelog-sections": [ + {"type": "feat", "section": "Features"}, + {"type": "fix", "section": "Bug Fixes"}, + {"type": "perf", "section": "Performance Improvements"}, + {"type": "docs", "section": "Documentation"}, + {"type": "chore", "section": "Miscellaneous", "hidden": true}, + {"type": "refactor", "section": "Code Refactoring", "hidden": true}, + {"type": "test", "section": "Tests", "hidden": true}, + {"type": "ci", "section": "Continuous Integration", "hidden": true} + ] +} +