# Altius Transaction SDK (Rust)
A Rust SDK for signing and encoding Altius USD multi-token transactions. Supports the USD Multi-Token fee model (0x7a transaction type).
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
altius-tx-sdk = "0.1"
```
## Usage
### Quick Start
```rust
use altius_tx_sdk::{TxClient, generate_private_key, USDA_ADDRESS};
let private_key = generate_private_key();
let client = TxClient::new(&private_key, "https://rpc.altius.xyz", USDA_ADDRESS)?;
let tx_hash = client.transfer_usda(recipient, 1_000_000).await?; // 1 USD
println!("Transaction hash: {}", tx_hash);
```
### Transaction Builder
```rust
use altius_tx_sdk::{TxBuilder, TxFields};
let tx = TxBuilder::new()
.chain_id(1)
.nonce(0)
.gas_limit(21000)
.to(Some(address))
.value(U256::ZERO)
.fee_token(USDA_ADDRESS)
.max_fee_per_gas_usd(50000000000)
.build();
```
---
## API Reference
### Wallet & Signing
#### `generate_private_key() -> String`
Generate a new random private key.
```rust
let private_key = generate_private_key();
```
#### `private_key_to_address(private_key: &str) -> Result<String>`
Derive address from private key.
```rust
let address = private_key_to_address("0x...")?;
```
#### `Wallet`
Wallet struct for transaction signing.
```rust
use altius_tx_sdk::Wallet;
// Generate new wallet
let wallet = Wallet::generate()?;
// Create from private key
let wallet = Wallet::from_private_key("0x...")?;
```
---
### Transaction Builder
#### `TxBuilder`
Builder for USD Multi-Token transactions.
```rust
use altius_tx_sdk::TxBuilder;
use alloy_primitives::{address, U256};
let tx = TxBuilder::new()
.chain_id(1)
.nonce(0)
.gas_limit(21000)
.to(Some(address!("0x...")))
.value(U256::ZERO)
.fee_token(USDA_ADDRESS)
.max_fee_per_gas_usd(50000000000)
.build();
```
#### `TxBuilder` Methods
| `.chain_id(id: u64)` | Set chain ID |
| `.nonce(nonce: u64)` | Set transaction nonce |
| `.gas_limit(limit: u64)` | Set gas limit |
| `.to(address: Option<Address>)` | Set recipient address |
| `.to_address(address: Address)` | Set recipient address |
| `.value(value: U256)` | Set transaction value |
| `.data(data: Bytes)` | Set input data |
| `.max_priority_fee_per_gas(gas: u128)` | Set max priority fee |
| `.max_fee_per_gas(gas: u128)` | Set max fee per gas |
| `.fee_token(address: Address)` | Set fee token address |
| `.fee_payer(address: Option<Address>)` | Set fee payer (optional) |
| `.max_fee_per_gas_usd(usd: u128)` | Set max fee in USD attodollars |
| `.fee_payer_signature(signature: Bytes)` | Set fee payer signature |
| `.erc20_transfer(token: Address, to: Address, amount: U256)` | Build ERC20 transfer |
| `.build() -> TxFields` | Build transaction |
| `.signature_hash() -> B256` | Compute signature hash |
| `.sign(signer: &impl Signer) -> Result<SignedTx>` | Sign transaction |
---
### RPC Client
#### `RpcClient`
JSON-RPC client for Altius node.
```rust
use altius_tx_sdk::RpcClient;
let rpc = RpcClient::new("https://rpc.altius.xyz");
```
#### `RpcClient` Methods
| `.new(url: &str) -> Self` | Create RPC client |
| `.get_chain_id() -> Result<u64>` | Get chain ID |
| `.get_block_number() -> Result<u64>` | Get latest block |
| `.get_balance(address: Address) -> Result<U256>` | Get native balance |
| `.get_nonce(address: Address) -> Result<u64>` | Get transaction count |
| `.get_code(address: Address) -> Result<Bytes>` | Get contract code |
| `.call(call: CallRequest) -> Result<Bytes>` | Execute contract call |
| `.send_raw_transaction(tx: Bytes) -> Result<B256>` | Send signed transaction |
| `.get_transaction_receipt(hash: B256) -> Result<Option<TransactionReceipt>>` | Get receipt |
| `.wait_for_receipt(hash: B256, timeout_ms: u64) -> Result<TransactionReceipt>` | Wait for receipt |
| `.get_erc20_balance(token: Address, owner: Address) -> Result<U256>` | Get ERC20 balance |
---
### Nonce Manager
#### `NonceManager`
Manages transaction nonces with caching.
```rust
use altius_tx_sdk::{NonceManager, RpcClient};
use std::sync::Arc;
let rpc = Arc::new(RpcClient::new("https://rpc.altius.xyz"));
let nm = NonceManager::new(rpc, address);
```
#### `NonceManager` Methods
| `.new(rpc: Arc<RpcClient>, address: Address) -> Self` | Create nonce manager |
| `.get_nonce() -> Result<u64>` | Get current nonce |
| `.get_and_increment_nonce() -> Result<u64>` | Get and increment nonce |
| `.reset_nonce()` | Reset nonce cache |
---
### High-Level Client
#### `TxClient`
High-level transaction client.
```rust
use altius_tx_sdk::TxClient;
let client = TxClient::new(private_key, "https://rpc.altius.xyz", USDA_ADDRESS)?;
```
#### `TxClientBuilder`
```rust
use altius_tx_sdk::TxClientBuilder;
let client = TxClientBuilder::new(private_key, "https://rpc.altius.xyz")
.fee_token(USDA_ADDRESS)
.base_fee(50000000000)
.gas_limit(100000)
.build()?;
```
#### `TxClient` Methods
| `.new(private_key: &str, rpc_url: &str, fee_token: &str) -> Result<Self>` | Create client |
| `.address() -> Address` | Get wallet address |
| `.chain_id() -> Result<u64>` | Get chain ID |
| `.get_nonce() -> Result<u64>` | Get current nonce |
| `.build_erc20_transfer(token: Address, recipient: Address, amount: U256) -> Result<TxBuilder>` | Build ERC20 transfer |
| `.sign(tx: TxBuilder) -> Result<SignedTransaction>` | Sign transaction |
| `.send(signed: SignedTransaction) -> Result<String>` | Send transaction |
| `.send_and_wait(signed: SignedTransaction, timeout_ms: u64) -> Result<TransactionReceipt>` | Send and wait |
| `.send_erc20_transfer(token: Address, recipient: Address, amount: U256) -> Result<String>` | Send ERC20 transfer |
| `.transfer_usda(recipient: Address, amount_micro: u64) -> Result<String>` | Transfer USDA |
| `.fee_token_balance(address: Address) -> Result<U256>` | Get fee token balance |
| `.native_balance(address: Address) -> Result<U256>` | Get native balance |
| `.reset_nonce()` | Reset nonce cache |
---
### Utilities
#### `compute_fee_token_address(creator: Address, salt: B256) -> (Address, u64)`
Compute deterministic fee token address.
```rust
use altius_tx_sdk::compute_fee_token_address;
let (address, index) = compute_fee_token_address(creator, salt);
```
#### `is_reserved_address(creator: Address, salt: B256) -> bool`
Check if address is reserved (index < 256).
```rust
use altius_tx_sdk::is_reserved_address;
let is_reserved = is_reserved_address(creator, salt);
```
#### `is_fee_token_prefix(addr: Address) -> bool`
Check if address has fee token prefix (0xa170...).
```rust
use altius_tx_sdk::is_fee_token_prefix;
let has_prefix = is_fee_token_prefix(address);
```
#### `is_valid_fee_token_address(addr: Address) -> bool`
Check if address is valid fee token (has prefix and not zero).
```rust
use altius_tx_sdk::is_valid_fee_token_address;
let is_valid = is_valid_fee_token_address(address);
```
#### `is_index_reserved(index: u64) -> bool`
Check if index is reserved (index < 256).
```rust
use altius_tx_sdk::is_index_reserved;
let is_reserved = is_index_reserved(100);
```
#### `pad_hex(hex: &str, bytes: usize) -> String`
Pad hex string to specified length.
```rust
use altius_tx_sdk::pad_hex;
let padded = pad_hex("0x1234", 32);
```
#### `num_to_hex(num: u64, bytes: usize) -> String`
Convert number to padded hex.
```rust
use altius_tx_sdk::num_to_hex;
let hex = num_to_hex(123, 32);
```
---
### Constants
| `USDA_ADDRESS` | `Address` | USDA Fee Token: `0xa1700000000000000000000000000000000000001` |
| `FEE_TOKEN_FACTORY_ADDRESS` | `Address` | Fee Token Factory: `0xa170000000000000000000000000000000000000` |
| `FEE_MANAGER_ADDRESS` | `Address` | Fee Manager: `0xFE00000000000000000000000000000000000001` |
| `ZERO_ADDRESS` | `Address` | Zero address: `0x0000000000000000000000000000000000000000` |
| `BASE_FEE_ATTO` | `u64` | Base fee: 50,000,000,000 |
| `DEFAULT_MAX_FEE_PER_GAS` | `u64` | Default max fee: 100,000,000,000 |
| `DEFAULT_GAS_LIMIT` | `u64` | Default gas limit: 100,000 |
| `FAUCET_AMOUNT_MICRO` | `u64` | Faucet amount: 100,000,000 |
| `FAUCET_AMOUNT_WEI` | `u128` | Faucet amount: 100,000,000,000,000,000,000 |
| `DEFAULT_FAUCET_AMOUNT` | `u128` | Default faucet amount: 100,000,000,000,000,000,000 |
| `DEFAULT_FAUCET_AMOUNT_MICRO` | `u64` | Default faucet: 100,000,000 |
| `TRANSFER_AMOUNT_MICRO` | `u64` | Transfer amount: 10,000,000 |
| `TRANSFER_AMOUNT_WEI` | `u128` | Transfer amount: 10,000,000,000,000,000,000 |
| `RESERVED_THRESHOLD` | `u64` | Reserved threshold: 256 |
| `FAUCET_FEE_TOKEN` | `Address` | Default faucet fee token |
---
## Security Note
**IMPORTANT**: Never transmit private keys over the network. Sign transactions locally and only send the signed raw transaction to the RPC node.
```rust
// WRONG - never send private key to server
// client.send_private_key_to_server(private_key).await;
// CORRECT - sign locally, send raw transaction
let signed = client.sign(tx).await?;
rpc.send_raw_transaction(signed.raw_transaction()).await?;
```
---
## Transaction Type
This SDK supports the USD Multi-Token fee model (0x7a transaction type):
- **fee_token**: ERC20 token address used for gas payment
- **fee_payer**: Account paying the fee (optional, defaults to sender)
- **max_fee_per_gas_usd_attodollars**: Max gas price in USD attodollars/gas
---
## Key Addresses
| USDA (Fee Token) | `0xa1700000000000000000000000000000000000001` |
| Fee Token Factory | `0xa170000000000000000000000000000000000000` |
| Fee Manager | `0xFE00000000000000000000000000000000000001` |
---
## License
MIT OR Apache-2.0