# 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

| Method | Description |
|--------|-------------|
| `.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

| Method | Description |
|--------|-------------|
| `.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

| Method | Description |
|--------|-------------|
| `.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

| Method | Description |
|--------|-------------|
| `.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

| Constant | Type | Description |
|----------|------|-------------|
| `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

| Contract | Address |
|----------|---------|
| USDA (Fee Token) | `0xa1700000000000000000000000000000000000001` |
| Fee Token Factory | `0xa170000000000000000000000000000000000000` |
| Fee Manager | `0xFE00000000000000000000000000000000000001` |

---

## License

MIT OR Apache-2.0
