Bonança
Bonança (pronounced boh-nahn-sah) is an open-source library for creating crypto defi bots on various blockchains. It provides functionalities for creating HD wallets, private key encryption, executing trades, lending and borrow crypto, and more.
Bonança is fully free and completely open source. You can find the source code on GitHub. The crypto is yours, and you are in full control of your funds at all times.
Features
- Create and manage wallets using secure
KeyVaults. - Connect to multiple blockchains (e.g., Solana, EVM-compatible chains).
- Integrate with various exchanges and oracles for trading and price data.
- Python wrapper
Disclaimer
This documentation has been largely written by AI, so it is likely there are some inaccuracies in the code examples. I occasionally look over the docs to fix them, but some might still be out there.
Getting Started
To get started with Bonança, follow the instructions in the Installation guide. Once installed, you can create a wallet by following the steps in the Create Account section. After setting up your wallet, you can manage your index fund using the instructions provided in the Manage Index Fund documentation.
About The Name
Bonança is a Portuguese word used to describe a period of prosperity and tranquility, that typically comes after a period of instability or hardship. In the context of this project, Bonança represents a tool that aims to bring financial stability and growth to cryptocurrency investors.
A big insipration for the name comes from a verse in a famous Brazilian funk song "Rap da Felicidade" by Cidinho and Doca:
"Sofri na tempestade, agora eu quero a bonança"
Which translates to "I suffered in the storm, now I want prosperity". I hope this CLI can help users find their own "bonança" in the volatile world of cryptocurrency investing.
Installation
cargo add bonanca
Wallets
This section documents the wallet and key management utilities provided by Bonanca. It covers creating and managing EVM and Solana wallets, using the keyvault, signing transactions, and helper functions for balance and token operations.
HD Wallets
Bonança can create a master key for a Hierarchical Deterministic (HD)
wallet, which can generate multiple child keys for different blockchains.
This means you can manage multiple wallets for multiple blockchains (e.g.,
Solana, EVM-compatible chains) using a single KeyVault file. If you are
unfamiliar with HD wallets consider reading this post.
Creating a New HD Wallet
HD wallets are stored as KeyVault files in Bonança, which is explained
in more depth here. You can create a KeyVault using Rust
or Python.
Rust
use bonanca::keyvault::KeyVault;
use std::path::Path;
fn main() {
// Create new KeyVault with english mneomonic
let key_vault = KeyVault::new("English");
let filename = Path::new("./keyvault.json");
// Write json file
key_vault.write(filename)
}
Python
from bonanca import KeyVault
# Create new KeyVault with english mneomonic
key_vault = KeyVault.new("English")
# Write json file
key_vault.write("./keyvault.json")
The available languages for the mneomonic are:
- English
- Simplified Chinese
- Traditional Chinese,
- French
- Italian
- Japanese
- Korean
- Spanish
Create a KeyVault from a Mneomonic
You can also create a KeyVault from an existing mneomonic phrase. This is useful if you already have a wallet and want to manage it using Bonança.
Rust
use bonanca::keyvault::KeyVault;
fn main() {
// Your mneomonic (in any language listed above)
let mneomonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
let key_vault = KeyVault::from_mneomonic(mneomonic);
let filename = Path::new("./keyvault.json");
// Write json file
key_vault.write(filename)
}
Python
from bonanca import KeyVault
# Your mneomonic (in any language listed above)
mneomonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
key_vault = KeyVault.from_mneomonic(mneomonic)
# Write json file
key_vault.write("./keyvault.json")
View vs Load
Bonança offers you the ability to interact with wallets in two modes; view and
load. In view mode the wallet is only the public key, whereas, load has
both public and private keys. This is useful for when you want to check token
balances without having to expose your private key or type your password in.
Rust
In Rust view and load are both methods of the wallet struct.
use bonanca::wallets::{EvmWallet, SolWallet}
use std::path::Path;
fn main() {
let filename = Path::new("./keyvault.json");
let child = 0;
let evm_wallet_view = EvmWallet::view(filename, "rpc_url", child)
let sol_wallet_view = SolWallet::view(filename, "rpc_url", child)
let evm_wallet_load = EvmWallet::load(filename, "rpc_url", child)
let sol_wallet_load = SolWallet::load(filename, "rpc_url", child)
}
Python
In Python the dynamic style view and load isn't possible, so instead there
are two different classes for each method.
import bonanca
wallet_view = bonanca.wallets.EvmWalletView("keyvault.json", "rpc_url", 0)
wallet_load = bonanca.wallets.EvmWallet("keyvault.json", "rpc_url", 0)
EVM Wallet
To interact with an EVM-compatible wallet using bonanca you can use
the EvmWallet struct.
Parse and Format Decimals
You can use the parse_decimals and format_decimals methods to convert between
the raw integer representation of token amounts and the human-readable decimal format.
Rust
// Format a float into a big int
let big_amount = wallet.format_native(2.5); // Native (ETH, POL, ...) only
let big_amount_token = wallet.format_token(14.2, "TOKEN_ADDRESS"); // Any token
// Parse a big int number into a float
let x0 = wallet.parse_native(big_amount); // Native (ETH, POL, ...) only
let x1 = wallet.parse_token(big_amount_token, "TOKEN_ADDRESS"); // Any token
Python
# Format a float into a big int
big_amount = wallet.format_native(2.5)# Native (ETH, POL, ...) only
big_amount_token = wallet.format_token(14.2, "TOKEN_ADDRESS")# Any token
# Parse a big int number into a float
x0 = wallet.parse_native(big_amount)# Native (ETH, POL, ...) only
x1 = wallet.parse_token(big_amount_token, "TOKEN_ADDRESS")# Any token
Balances
Bonança provides methods to check native and token balances in your wallet. You can use the balance method to retrieve the native balance and the token_balance method for tokens.
Rust
// Get native balance (as float)
let nat_bal = wallet.balance().await?;
// Get token balance (as float)
let tkn_bal = wallet.token_balance("TOKEN_ADDRESS").await?;
Python
sol_bal = wallet.balance()
spl_bal = wallet.token_balance("TOKEN_ADDRESS")
Token Approvals
To approve an address for spending your tokens you can use the
approve_token_spending method.
Rust
// Approve 2.05 tokens to be spent by spender address
wallet.approve_token_spending("TOKEN_ADDRESS","SPENDER_ADDRESS", 2.05).await?;
Python
wallet.approve_token_spending("TOKEN_ADDRESS","SPENDER_ADDRESS", 2.05)
Transfers
For native transfers you can use the transfer method, and token_transfer for
tokens. For native transfers, specify the recipient's public key and the amount
as a decimal value. For token transfers, specify the recipient's token
account, the token address, and the amount in decimal value.
Rust
// Transfer 2.5 native
let receipt = wallet.transfer(2.5, "TO_ADDRESS").await?;
// Transfer 2.5 token
let receipt2 = wallet.token_transfer("TOKEN_ADDRESS", 2.5, "TO_ADDRESS").await?;
Python
# Transfer 2.5 native
receipt = wallet.transfer(2.5, "TO_ADDRESS")
# Transfer 2.5 token
receipt2 = wallet.token_transfer("TOKEN_ADDRESS", 2.5, "TO_ADDRESS")
Solana Wallet
To interact with a Solana wallet using Bonança you can use the SolWallet
struct. For all examples shown below its assumed a wallet has been initialized
as wallet. In the examples where signing is not required a view wallet is
sufficient.
Parse and Format Decimals
You can use the parse_decimals and format_decimals methods to convert between
the raw integer representation of token amounts and the human-readable decimal format.
Rust
// Format a float into a big int
let big_amount = wallet.format_native(2.5); // Sol only
let big_amount_token = wallet.format_token(14.2, "TOKEN_MINT"); // Any SPL token
// Parse a big int number into a float
let x0 = wallet.parse_native(big_amount); // Sol only
let x1 = wallet.parse_token(big_amount_token, "TOKEN_MINT"); // Any SPL token
# Format a float into a big int
big_amount = wallet.format_native(2.5) # Sol only
big_amount_token = wallet.format_token(14.2, "TOKEN_MINT") # Any SPL token
# Parse a big int number into a float
x0 = wallet.parse_native(big_amount)# Sol only
x1 = wallet.parse_token(big_amount_token, "TOKEN_MINT")# Any SPL token
Balances
Bonança provides methods to check the balance of SOL and SPL tokens in your wallet. You can use the balance method to retrieve the balance of SOL and the token_balance method for SPL tokens.
Rust
// Get Sol balance (as float)
let sol_bal = wallet.balance().await?;
// Get SPL token balance (as float)
let spl_bal = wallet.token_balance("TOKEN_MINT").await?;
Python
sol_bal = wallet.balance()
spl_bal = wallet.token_balance("TOKEN_MINT")
Create Token Account
Before you can hold or transfer SPL tokens, you need to create a token account for the specific token mint. You can use the create_token_account method to create a new token account.
Rust
let ata_pubkey = wallet.create_token_account("TOKEN_MINT").await?;
Python
ata_pubkey = wallet.create_token_account("TOKEN_MINT")
Burn Token
To burn SPL tokens, you can use the burn_token method. This will permanently remove the specified amount of tokens from circulation. Note that unlike EVM
chains in Solana you can't burn tokens by sending them to burn address.
Rust
let receipt = wallet.burn_token("TOKEN_MINT", 2.5).await?;
Python
receipt = wallet.burn_token("TOKEN_MINT", 2.5)
Close Token Account
To close a token account, you can use the close_token_account method. This
can only be done when the token balance is zero (you must send or burn all
tokens before calling this method). After closing the account the SOL deposit
for the account will be returned to your wallet.
Rust
wallet.close_token_account("TOKEN_MINT").await?;
Python
wallet.close_token_account("TOKEN_MINT")
Transfers
To transfer SOL you can use the transfer method, and token_transfer for SPL
tokens. For SOL transfers, specify the recipient's public key and the amount
as a decimal value. For SPL token transfers, specify the recipient's token
account, the token mint, and the amount in decimal value.
Rust
// Transfer 2.5 Sol
let receipt = wallet.transfer(2.5, "TO_ADDRESS").await?;
// Transfer 2.5 SPL token
let receipt2 = wallet.token_transfer("TOKEN_MINT", 2.5, "TO_ADDRESS").await?;
Python
# Transfer 2.5 Sol
receipt = wallet.transfer(2.5, "TO_ADDRESS")
# Transfer 2.5 SPL token
receipt2 = wallet.token_transfer("TOKEN_MINT", 2.5, "TO_ADDRESS")
DeFi
Overview of protocol integrations and adapters provided by Bonanca. This section links into EVM and Solana integrations (Aave, 0x, CoW, Morpho, Jupiter, Kamino, etc.) and shows how to query markets, perform swaps, and manage vaults from Rust and Python.
EVM DeFi Interfaces
Bonanca provides interfaces to interact with popular DeFi protocols on EVM-compatible blockchains. This section covers the main DeFi integrations available.
Aave V3 - Lending Protocol
Aave V3 is a decentralized lending protocol that allows users to supply assets as collateral, borrow tokens, and earn interest. The AaveV3 interface provides methods for managing lending positions.
Overview
- Supply: Deposit tokens to earn interest
- Borrow: Borrow tokens using your collateral
- Repay: Pay back borrowed tokens
- Withdraw: Withdraw supplied tokens
- Account Data: Query user's collateral, debt, and health factor
Supported Operations
Rust
use bonanca::defi::AaveV3;
use bonanca::wallets::evm::EvmWallet;
#[tokio::main]
async fn main() -> Result<()> {
// Initialize wallet
let wallet = EvmWallet::new(
"private_key",
"rpc_url",
137 // Chain ID for Polygon
)?;
// Initialize Aave V3 for Polygon (chain_id=137)
let aave = AaveV3::new(137);
// Example 1: Supply USDC
let usdc_address = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359";
let receipt = aave.supply(&wallet, usdc_address, 100.0).await?;
println!("Supply tx: {:?}", receipt.transaction_hash);
// Example 2: Check user account data
let user_data = aave.get_user_data(
&wallet.pubkey.to_string(),
&wallet.client
).await?;
println!("Health Factor: {}", user_data.health_factor);
println!("Total Collateral: {}", user_data.total_collateral);
println!("Total Debt: {}", user_data.total_debt);
println!("Available Borrows: {}", user_data.available_borrows);
// Example 3: Borrow WETH
let weth_address = "0x7ceB23fD6bC0adD59E27f9EA9d0231e0f01cc726";
let borrow_receipt = aave.borrow(&wallet, weth_address, 0.5).await?;
println!("Borrow tx: {:?}", borrow_receipt.transaction_hash);
// Example 4: Repay borrowed tokens
let repay_receipt = aave.repay(&wallet, weth_address, 0.3).await?;
println!("Repay tx: {:?}", repay_receipt.transaction_hash);
// Example 5: Withdraw collateral
let withdraw_receipt = aave.withdraw(&wallet, usdc_address, 50.0).await?;
println!("Withdraw tx: {:?}", withdraw_receipt.transaction_hash);
Ok(())
}
Python
import bonanca
# Initialize wallet
wallet = bonanca.wallets.EvmWallet(
"private_key",
"https://polygon-rpc.com",
137 # Chain ID for Polygon
)
# Initialize Aave V3
aave = bonanca.defi.AaveV3(137)
# Token addresses on Polygon
usdc = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
weth = "0x7ceB23fD6bC0adD59E27f9EA9d0231e0f01cc726"
# Supply tokens
supply_receipt = aave.supply(wallet, usdc, 100.0)
print(f"Supply tx: {supply_receipt['transaction_hash']}")
# Check account data
account_data = aave.get_user_data(wallet.pubkey, wallet)
print(f"Health Factor: {account_data['Health Factor']}")
print(f"Total Collateral: {account_data['Total Collateral']}")
print(f"Total Debt: {account_data['Total Debt']}")
# Borrow tokens
borrow_receipt = aave.borrow(wallet, weth, 0.5)
print(f"Borrow tx: {borrow_receipt['transaction_hash']}")
# Repay debt
repay_receipt = aave.repay(wallet, weth, 0.3)
print(f"Repay tx: {repay_receipt['transaction_hash']}")
# Withdraw collateral
withdraw_receipt = aave.withdraw(wallet, usdc, 50.0)
print(f"Withdraw tx: {withdraw_receipt['transaction_hash']}")
Chain IDs
Common Aave V3 deployments:
- Ethereum: 1
- Polygon: 137
- Arbitrum: 42161
- Optimism: 10
- Base: 8453
- Avalanche: 43114
Important Notes
- Ensure sufficient collateral before borrowing
- Monitor your health factor to avoid liquidation
- The health factor formula considers collateral and debt ratios
- Interest rates vary based on market utilization
- Requires token approval before first interaction with Aave
CoW (Coincidence of Wants) - DEX Aggregator
CoW is an order-based DEX aggregator that uses batch auctions to execute trades. It supports both market orders and limit orders.
Overview
- Market Orders: Execute immediately at best available price
- Limit Orders: Execute only when price reaches your target
- Order Queries: Check order status and history
- EIP-712 Signing: Secure order signing
Supported Operations
Rust
use bonanca::defi::CoW;
use bonanca::wallets::evm::EvmWallet;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<()> {
let wallet = EvmWallet::new(
"private_key",
"https://polygon-rpc.com",
137
)?;
// Initialize CoW for Polygon
let cow = CoW::new("polygon")?;
let weth = "0x7ceB23fD6bC0adD59E27f9EA9d0231e0f01cc726";
let usdc = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359";
// Example 1: Execute market order (WETH → USDC)
let market_quote = cow.get_market_quote(
&wallet,
weth,
usdc,
0.1 // 0.1 WETH
).await?;
let order_uid = cow.post_market_order(
&wallet,
market_quote
).await?;
println!("Market order placed: {}", order_uid);
// Example 2: Check order status
let order_info = cow.get_order_info(&order_uid).await?;
println!("Status: {}", order_info.status);
println!("Executed Buy Amount: {}", order_info.executed_buy_amount);
println!("Executed Sell Amount: {}", order_info.executed_sell_amount);
// Example 3: Get user order history
let user_orders = cow.get_user_orders(
&wallet.pubkey.to_string(),
Some(10) // Last 10 orders
).await?;
println!("Recent orders: {} found", user_orders.len());
// Example 4: Place limit order
// Valid for 1 hour (60 minutes + 0 seconds)
let limit_duration = Duration::new(3600, 0);
let limit_uid = cow.limit_order(
&wallet,
weth, // Selling WETH
usdc, // Buying USDC
0.1, // Sell amount
200.0, // Buy amount (minimum)
limit_duration
).await?;
println!("Limit order placed: {}", limit_uid);
// Example 5: Place limit order by price
let price_limit_uid = cow.limit_order_by_price(
&wallet,
weth,
usdc,
0.1, // Amount of WETH to sell
2000.0, // Minimum price (USDC per WETH)
limit_duration
).await?;
println!("Price limit order placed: {}", price_limit_uid);
Ok(())
}
Python
import bonanca
wallet = bonanca.wallets.EvmWallet(
"private_key",
"https://polygon-rpc.com",
137
)
# Initialize CoW for Polygon
cow = bonanca.defi.CoW("polygon")
weth = "0x7ceB23fD6bC0adD59E27f9EA9d0231e0f01cc726"
usdc = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
# Market order: Sell 0.1 WETH for USDC
order_uid = cow.market_order(wallet, weth, usdc, 0.1)
print(f"Order UID: {order_uid}")
# Get order details
order_info = cow.get_order_info(order_uid)
print(f"Status: {order_info['status']}")
print(f"Buy Amount: {order_info['executed_buy_amount']}")
print(f"Sell Amount: {order_info['executed_sell_amount']}")
# Get all orders for a user
user_orders = cow.get_user_orders(wallet.pubkey, 10)
print(f"Found {len(user_orders)} recent orders")
# Limit order: Sell 0.1 WETH for minimum 200 USDC, valid for 1 hour
limit_uid = cow.limit_order(
wallet,
weth, # Sell token
usdc, # Buy token
0.1, # Sell amount
200.0, # Minimum buy amount
(1, 0) # Duration: 1 hour, 0 minutes
)
print(f"Limit order: {limit_uid}")
# Limit order by price
price_uid = cow.limit_order_by_price(
wallet,
weth,
usdc,
0.1, # Amount to sell
2000.0, # Minimum price
(1, 0) # Duration
)
print(f"Price limit order: {price_uid}")
Supported Chains
- Ethereum (mainnet)
- Polygon
- Arbitrum
- Optimism
- Base
- Gnosis Chain (xDai)
- Linea
- Avalanche
- BNB Chain
Important Notes
- CoW Protocol uses batch auctions for better pricing
- Limit orders expire after specified duration
- Orders must be signed with EIP-712
- Focus on MEV protection compared to traditional DEXs
- No gas required for failed orders
Morpho - Lending Optimization
Morpho optimizes lending by matching users peer-to-peer while falling back to lending pools. The MorphoVaultV1 interface provides access to Morpho vaults.
Overview
- Supply: Deposit into optimized vaults
- Withdraw: Withdraw from vaults
- Vault Data: Query available vaults for specific tokens
- User Positions: Track user's vault positions
Supported Operations
Rust
use bonanca::defi::MorphoVaultV1;
use bonanca::wallets::evm::EvmWallet;
#[tokio::main]
async fn main() -> Result<()> {
let wallet = EvmWallet::new(
"private_key",
"https://polygon-rpc.com",
137
)?;
let morpho = MorphoVaultV1::new();
// Example 1: Get user's vault positions
let user_positions = morpho.get_user_data(
&wallet.pubkey.to_string(),
137 // Chain ID
).await?;
println!("User positions: {:?}", user_positions);
// Example 2: Find USDC vaults
let usdc_vaults = morpho.get_token_vaults(
"USDC",
137
).await?;
println!("Available USDC vaults: {}", usdc_vaults.len());
for vault in &usdc_vaults {
println!("Vault: {:?}", vault);
}
// Example 3: Supply to a vault
// First, get a vault address from get_token_vaults()
let vault_address = "0x..."; // Example vault address
let deposit_receipt = morpho.supply(
&wallet,
vault_address,
100.0 // Amount in decimal format
).await?;
println!("Deposit tx: {:?}", deposit_receipt.transaction_hash);
// Example 4: Withdraw from vault
let withdraw_receipt = morpho.withdraw(
&wallet,
vault_address,
50.0
).await?;
println!("Withdraw tx: {:?}", withdraw_receipt.transaction_hash);
Ok(())
}
Python
import bonanca
wallet = bonanca.wallets.EvmWallet(
"private_key",
"https://polygon-rpc.com",
137
)
morpho = bonanca.defi.MorphoVaultV1()
# Get user's vault positions
user_data = morpho.get_user_data(wallet.pubkey, 137, wallet)
print(f"User positions: {user_data}")
# Find USDC vaults
usdc_vaults = morpho.get_token_vaults("USDC", 137, wallet)
print(f"Available vaults: {usdc_vaults}")
# Supply to a vault (replace with actual vault address)
vault_address = "0x..."
deposit_receipt = morpho.supply(wallet, vault_address, 100.0)
print(f"Deposit tx: {deposit_receipt['transaction_hash']}")
# Withdraw from vault
withdraw_receipt = morpho.withdraw(wallet, vault_address, 50.0)
print(f"Withdraw tx: {withdraw_receipt['transaction_hash']}")
Morpho Vaults
Morpho offers specialized vaults for different strategies:
- USDC Vaults: Stable yield on USDC
- WETH Vaults: Ethereum staking
- Strategy Vaults: Custom yield strategies
- Metamorpho Vaults: User-created vault bundles
Important Notes
- Vault addresses vary by chain
- Deposits are immediately invested
- Withdrawals may take time depending on vault liquidity
- Each vault has different risk/reward profiles
- Query vault details for APY and TVL information
0x (ZeroX) - DEX Aggregator
0x is a decentralized exchange aggregator that sources liquidity from multiple DEXs to find the best prices for token swaps.
Overview
- Swap Quotes: Get best available swap prices
- Quick Swaps: Execute swaps in one transaction
- Issue Checking: Verify swap feasibility
- Multi-source Routing: Optimal liquidity from multiple DEXs
Supported Operations
Rust
use bonanca::defi::ZeroX;
use bonanca::wallets::evm::EvmWallet;
#[tokio::main]
async fn main() -> Result<()> {
let wallet = EvmWallet::new(
"private_key",
"https://polygon-rpc.com",
137
)?;
// Initialize 0x with API key (get from 0x.org)
let zerox = ZeroX::new("your_api_key".to_string(), 137);
let weth = "0x7ceB23fD6bC0adD59E27f9EA9d0231e0f01cc726";
let usdc = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359";
// Example 1: Check for swap issues
let issues = zerox.check_swap(
&wallet,
weth,
usdc,
0.1 // 0.1 WETH
).await?;
if issues.allowance.is_some() {
println!("Token approval required");
}
if issues.balance.is_some() {
println!("Insufficient balance");
}
// Example 2: Get swap quote
let quote = zerox.get_swap_quote(
&wallet,
weth,
usdc,
0.1
).await?;
println!("Buy Amount: {}", quote.buy_amount);
println!("Min Buy Amount: {}", quote.min_buy_amount);
println!("Liquidity Available: {}", quote.liquidity_available);
println!("Allowance Target: {}", quote.allowance_target);
// Example 3: Execute swap with quote
let swap_receipt = zerox.swap(
&wallet,
quote
).await?;
println!("Swap tx: {:?}", swap_receipt.transaction_hash);
// Example 4: Quick swap (get quote and swap in one call)
// This is more convenient for simpler scenarios
let receipt = zerox.quick_swap(
&wallet,
weth,
usdc,
0.1
).await?;
println!("Quick swap tx: {:?}", receipt.transaction_hash);
Ok(())
}
Python
import bonanca
wallet = bonanca.wallets.EvmWallet(
"private_key",
"https://polygon-rpc.com",
137
)
# Initialize 0x (replace with actual API key from 0x.org)
zerox = bonanca.defi.ZeroX("api_key", 137)
weth = "0x7ceB23fD6bC0adD59E27f9EA9d0231e0f01cc726"
usdc = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
# Check for swap issues (allowance, balance)
issues = zerox.check_swap(wallet, weth, usdc, 0.1)
print(f"Issues: {issues}")
# Get detailed quote
quote = zerox.get_swap_quote(wallet, weth, usdc, 0.1)
print(f"Buy Amount: {quote.buy_amount}")
print(f"Min Buy Amount: {quote.min_buy_amount}")
print(f"Liquidity Available: {quote.liquidity_available}")
# Execute swap with quote
swap_receipt = zerox.swap(wallet, quote)
print(f"Swap tx: {swap_receipt['transaction_hash']}")
# Quick swap (recommended for simple swaps)
quick_receipt = zerox.quick_swap(wallet, weth, usdc, 0.1)
print(f"Quick swap tx: {quick_receipt['transaction_hash']}")
Supported Chains
- Ethereum
- Polygon
- Arbitrum
- Optimism
- Base
- Avalanche
- BNB Chain
- Linea
- Scroll
Quote Information
The swap quote returns:
- buy_amount: Exact amount of output tokens
- min_buy_amount: Minimum considering slippage
- sell_amount: Amount of input tokens
- allowance_target: Address to approve for token spending
- liquidity_available: Whether sufficient liquidity exists
Important Notes
- Requires 0x API key (free tier available)
- Always check issues before executing trades
- Slippage is automatically handled
- Gas estimates included in quotes
- Quote validity is typically 1 minute
- Quick swaps are simpler but less flexible than manual swap flow
General Best Practices
Security
-
Private Key Management
- Never hardcode private keys
- Use environment variables or secure vaults
- Rotate keys regularly
-
Token Approval
- Check allowances before transactions
- Use minimal necessary amounts
- Revoke approvals when done
-
Position Management
- Monitor health factors in lending protocols
- Set alerts for liquidation risk
- Rebalance positions regularly
Gas Optimization
- Batch multiple operations when possible
- Use limit orders for time-insensitive trades
- Monitor gas prices before executing
- Consider network congestion
Testing
- Test on testnet before mainnet
- Start with small amounts
- Verify transactions before committing funds
- Use price impact slippage limits
Transaction Confirmation
All operations return transaction receipts containing:
- Transaction hash
- Block number
- Gas used
- Transaction status
Always verify successful execution before relying on results.
Solana DeFi Interfaces
Bonanca provides interfaces to interact with popular DeFi protocols on Solana. This section covers the main DeFi integrations available.
Jupiter - DEX Aggregator
Jupiter is the leading decentralized exchange aggregator on Solana, sourcing liquidity from multiple DEXs to find the best prices for token swaps. It also offers a lending protocol called Jupiter Earn.
Overview
- Token Swaps: Get best pricing across multiple Solana DEXs
- Limit Orders: Place orders that execute at specified prices
- Price Queries: Check token prices and value conversions
- Lending/Earn: Deposit tokens to earn yield
- Lendable Markets: Query available lending markets
Supported Operations
Rust
use bonanca::defi::Jupiter;
use bonanca::wallets::solana::SolWallet;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<()> {
// Initialize wallet
let wallet = SolWallet::new(
"base58_private_key",
"https://api.mainnet-beta.solana.com"
)?;
// Initialize Jupiter with API key
let jupiter = Jupiter::new("your_api_key".to_string());
// Token mint addresses
let sol = "So11111111111111111111111111111111111111112";
let usdc = "EPjFWdd5Au17FXxeB6VWyeXKSa3LvwV0LCH7f3uyxVEP";
let orca = "orcaEKTdK7LKz57chYcUBK6GDZT5bNvmnucEZDfmWQe";
// Example 1: Get token price in USD
let sol_price = jupiter.get_token_price(token_mint, 1.0).await?;
println!("1 SOL = ${}", sol_price);
// Example 2: Get swap quote
let quote = jupiter.get_swap_quote(
&wallet,
sol, // Sell token (SOL)
usdc, // Buy token (USDC)
1.0 // Amount in decimal format
).await?;
println!("Input Amount: {}", quote.in_amount);
println!("Output Amount: {}", quote.out_amount);
println!("Price Impact: {}%", quote.price_impact_pct);
println!("Slippage (bps): {}", quote.slippage_bps);
// Example 3: Execute swap with quote
let swap_receipt = jupiter.swap(&wallet, quote).await?;
println!("Swap signature: {}", swap_receipt.hash);
println!("Slot: {}", swap_receipt.slot);
// Example 4: Quick swap (get quote and swap in one call)
let receipt = jupiter.quick_swap(
&wallet,
sol,
usdc,
1.0
).await?;
println!("Quick swap signature: {}", receipt.hash);
// Example 5: Place limit order
// Order is valid for 24 hours (86400 seconds)
let limit_receipt = jupiter.limit_order(
&wallet,
sol, // Sell token
usdc, // Buy token
1.0, // Amount to sell
34.5, // Minimum to receive
Duration::from_secs(86400)
).await?;
println!("Limit order signature: {}", limit_receipt.hash);
// Example 6: Limit order by price
// Sell 1 SOL if price reaches 35 USDC per SOL
let price_limit_receipt = jupiter.limit_order_by_price(
&wallet,
sol,
usdc,
1.0, // Amount to sell
35.0, // Price threshold
Duration::from_secs(86400)
).await?;
println!("Price limit order: {}", price_limit_receipt.hash);
// Example 7: Get available lending markets
let markets = jupiter.get_lendable_tokens().await?;
for market in &markets {
println!("Market: {} ({})", market.name, market.symbol);
println!(" Supply Rate: {}", market.supply_rate);
println!(" Total Assets: {}", market.total_assets);
println!(" Total Supply: {}", market.total_supply);
}
// Example 8: Deposit into lending market
let deposit_receipt = jupiter.deposit(
&wallet,
usdc, // Token to deposit
100.0 // Amount in decimal format
).await?;
println!("Deposit signature: {}", deposit_receipt.hash);
// Example 9: Withdraw from lending market
let withdraw_receipt = jupiter.withdraw(
&wallet,
usdc,
50.0
).await?;
println!("Withdraw signature: {}", withdraw_receipt.hash);
Ok(())
}
Python
import bonanca
import time
# Initialize wallet
wallet = bonanca.wallets.SolWallet(
"base58_private_key",
"https://api.mainnet-beta.solana.com"
)
# Initialize Jupiter
jupiter = bonanca.defi.Jupiter("your_api_key")
# Token mint addresses
sol = "So11111111111111111111111111111111111111112"
usdc = "EPjFWdd5Au17FXxeB6VWyeXKSa3LvwV0LCH7f3uyxVEP"
orca = "orcaEKTdK7LKz57chYcUBK6GDZT5bNvmnucEZDfmWQe"
# Get token price
sol_price = jupiter.get_token_price(wallet, sol, 1.0)
print(f"1 SOL = ${sol_price}")
# Get swap quote
quote = jupiter.get_swap_quote(wallet, sol, usdc, 1.0)
print(f"Input: {quote.in_amount}")
print(f"Output: {quote.out_amount}")
print(f"Price Impact: {quote.price_impact_pct}%")
# Execute swap
swap_receipt = jupiter.swap(wallet, quote)
print(f"Swap tx: {swap_receipt.hash}")
# Quick swap (simpler one-liner)
receipt = jupiter.quick_swap(wallet, sol, usdc, 1.0)
print(f"Quick swap tx: {receipt.hash}")
# Limit order (valid for 1 day = 86400 seconds)
limit_receipt = jupiter.limit_order(
wallet,
sol, # Sell token
usdc, # Buy token
1.0, # Amount to sell
34.5, # Minimum to receive
86400 # Lifetime in seconds
)
print(f"Limit order: {limit_receipt.hash}")
# Price-based limit order
price_receipt = jupiter.limit_order_by_price(
wallet,
sol,
usdc,
1.0, # Amount to sell
35.0, # Price threshold
86400
)
print(f"Price limit: {price_receipt.hash}")
# Get available lending markets
markets = jupiter.get_lendable_tokens(wallet)
for market in markets:
print(f"Market: {market.name} ({market.symbol})")
print(f" APY: {market.supply_rate}")
print(f" TVL: {market.total_assets}")
# Deposit into lending protocol
deposit_receipt = jupiter.deposit(wallet, usdc, 100.0)
print(f"Deposit tx: {deposit_receipt.hash}")
# Withdraw from lending protocol
withdraw_receipt = jupiter.withdraw(wallet, usdc, 50.0)
print(f"Withdraw tx: {withdraw_receipt.hash}")
Quote Structure
The swap quote includes:
- in_amount: Exact input amount needed
- out_amount: Expected output amount
- other_amount_threshold: Minimum output considering slippage
- price_impact_pct: Price impact percentage
- slippage_bps: Slippage in basis points
- context_slot: Slot when quote was created
- swap_mode: Type of swap (ExactIn, ExactOut)
Lending Markets
Jupiter Earn provides lending markets with:
- supply_rate: Current APY for deposits
- total_assets: Total assets in the market
- total_supply: Total supply shares issued
- decimals: Token decimal places
- symbol: Token symbol
API Key
Get a free API key from Jupiter:
- Free tier available for development
- Rate limits apply
- Required for production swaps
Kamino - Yield Optimization Vaults
Kamino is a vault protocol on Solana that optimizes yield strategies by allocating assets across multiple lending markets. Kamino vaults provide automated yield farming and lending strategies.
Overview
- Vault Discovery: Find vaults by name, ID, or underlying token
- Vault Metrics: APY, TVL, performance tracking
- Position Management: Deposit and withdraw from vaults
- User Positions: Track vault holdings across all vaults
- Strategy Allocation: Vaults allocate across KLend reserves
Important Note
Kamino is currently available in Rust only. Python bindings are not yet available. The interface requires direct interaction with the Kamino smart contracts via Anchor.
Supported Operations (Rust Only)
use bonanca::defi::Kamino;
use bonanca::wallets::solana::SolWallet;
#[tokio::main]
async fn main() -> Result<()> {
let wallet = SolWallet::new(
"base58_private_key",
"https://api.mainnet-beta.solana.com"
)?;
let kamino = Kamino::new();
// Example 1: Get all available vaults
let all_vaults = kamino.get_vaults().await?;
println!("Total vaults: {}", all_vaults.len());
for vault in &all_vaults {
println!("Vault: {} ({})", vault.state.name, vault.address);
println!(" Token: {}", vault.state.token_mint);
println!(" APY: {}", vault.state.name);
}
// Example 2: Find vault by name
let usdc_vault = kamino.get_vault_data_by_name("Kamino USDC")
.await?;
println!("USDC Vault Address: {}", usdc_vault.address);
// Example 3: Find vault by ID
let vault_id = "7i..."; // Vault address
let vault_data = kamino.get_vault_data_by_id(vault_id).await?;
println!("Vault Name: {}", vault_data.state.name);
// Example 4: Get user's vault positions
let positions = kamino.get_user_data(&wallet.pubkey.to_string()).await?;
println!("User positions: {}", positions.len());
for position in &positions {
println!("Vault: {}", position.vault_address);
println!(" Staked Shares: {}", position.staked_shares);
println!(" Unstaked Shares: {}", position.unstaked_shares);
println!(" Total Shares: {}", position.total_shares);
}
// Example 5: Find all USDC vaults
let usdc_mint = "EPjFWdd5Au17FXxeB6VWyeXKSa3LvwV0LCH7f3uyxVEP";
let usdc_vaults = kamino.get_token_vaults(usdc_mint).await?;
println!("USDC vaults available: {}", usdc_vaults.len());
// Example 6: Deposit into a vault
let vault = kamino.get_vault_data_by_name("Kamino USDC").await?;
kamino.supply(&wallet, &vault, 1000.0).await?;
println!("Deposited 1000 USDC into vault");
// Example 7: Withdraw from a vault
kamino.withdraw(&wallet, &vault, 500.0).await?;
println!("Withdrew 500 USDC from vault");
// Example 8: Monitor vault performance
println!("\nVault Details:");
println!(" Name: {}", vault.state.name);
println!(" Token Mint: {}", vault.state.token_mint);
println!(" Shares Mint: {}", vault.state.shares_mint);
println!(" Total Shares Issued: {}", vault.state.shares_issued);
println!(" Performance Fee: {} bps", vault.state.performance_fee_bps);
println!(" Management Fee: {} bps", vault.state.management_fee_bps);
Ok(())
}
Vault Information
Each vault provides detailed information:
- name: Human-readable vault name
- token_mint: The token deposited in this vault
- shares_mint: The receipt token for vault shares
- address: Vault account address
- token_available: Amount available for withdrawal
- shares_issued: Total shares in circulation
- performance_fee_bps: Fee on profits (basis points)
- management_fee_bps: Annual management fee
- vault_allocation_strategy: How tokens are allocated across reserves
Vault Allocation
Kamino vaults automatically allocate deposits across multiple lending reserves:
- Optimizes yield across KLend markets
- Rebalances automatically
- Charges performance and management fees
- Reinvests earned interest
User Positions
Track positions across all vaults:
- staked_shares: Shares in staking/earning strategies
- unstaked_shares: Shares not yet fully invested
- total_shares: Total position size
- One entry per vault per user
Fee Structure
- Performance Fee: Percentage of earned yield (in basis points)
- Management Fee: Annual fee charged (in basis points)
- Example: 10% performance fee = 1000 bps, 1% management fee = 100 bps
Swap Best Practices
General Guidelines
-
Slippage Management
- Always check
other_amount_thresholdon quotes - Jupiter automatically handles slippage configuration
- Adjust slippage for volatile markets
- Always check
-
Quote Validity
- Quotes are typically valid for ~30 seconds
- Refresh quotes before executing large swaps
- Use quick_swap for time-sensitive trades
-
Price Impact
- Monitor
price_impact_pctin quotes - Larger swaps have higher price impact
- Consider breaking into smaller swaps if > 5% impact
- Monitor
Limit Order Strategy
-
Expiration: Set lifetime based on trading frequency
- Short-term: 1-24 hours
- Day trading: 1 hour
- Long-term: 7+ days
-
Order Amounts
- limit_order takes exact amounts
- limit_order_by_price calculates amounts from price
-
Order Book
- Limit orders wait for market to reach your price
- No execution guarantee
- Prices are checked continuously
Vault Management Best Practices
Deposit Strategy
-
Find Appropriate Vault
- Check vault APY and TVL
- Verify vault allocation strategy
- Review fee structure
-
Monitor Positions
- Track share value over time
- Monitor APY changes
- Watch fee deductions
-
Withdrawal Timing
- Withdraw when strategy is optimal
- Consider gas costs
- Account for any lock-up periods
Risk Management
- Concentration Risk: Diversify across multiple vaults/tokens
- Smart Contract Risk: Kamino/KLend are audited but not risk-free
- Market Risk: Underlying tokens can be volatile
- Strategy Risk: Allocations may not perform as expected
Common Patterns
Simple Swap
let receipt = jupiter.quick_swap(&wallet, sell_token, buy_token, 1.0).await?;
Quoted Swap
let quote = jupiter.get_swap_quote(&wallet, sell, buy, amount).await?;
// Check quote before proceeding
let receipt = jupiter.swap(&wallet, quote).await?;
Deposit to Earn
let markets = jupiter.get_lendable_tokens().await?;
// Find market with best APY
let receipt = jupiter.deposit(&wallet, chosen_market, amount).await?;
Vault Position Tracking
let kamino = Kamino::new();
let positions = kamino.get_user_data(&wallet_pubkey).await?;
for position in positions {
let vault = kamino.get_vault_data_by_id(&position.vault_address).await?;
println!("Position in {}: {}", vault.state.name, position.total_shares);
}
Token Addresses
Common Solana token addresses:
- SOL: So11111111111111111111111111111111111111112
- USDC: EPjFWdd5Au17FXxeB6VWyeXKSa3LvwV0LCH7f3uyxVEP
- USDT: Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenEst
- ORCA: orcaEKTdK7LKz57chYcUBK6GDZT5bNvmnucEZDfmWQe
- JUP: JUPyiwrYJFskidvHPcMj5kLSnsxPJ3Bad7Or7SvxJvP
- COPE: 8HGyAAB1yoM1ttS7pnK6DGPhcF1JSQhQTiNrgQpTsEq
- RAY: 4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX4r
Troubleshooting
Swap Failures
- Insufficient Balance: Ensure wallet has enough tokens
- Slippage Exceeded: Quote may have expired, refresh and try again
- Network Congestion: Retry after waiting or increase priority fee
- Liquidity Issues: Requested pair may not have sufficient liquidity
Limit Order Issues
- Order Not Filling: Price may not have reached your target
- Expired Order: Lifetime has passed, create new order
- Invalid Amounts: Ensure amounts are correctly formatted
Vault Operations
- Deposit Fails: Verify token balance and vault capacity
- Withdraw Fails: Ensure sufficient shares, check vault liquidity
- Account Creation: First interaction with vault may require account setup
Security Considerations
- Never share your private key
- Use environment variables for sensitive data
- Test on devnet before mainnet
- Monitor transaction fees and balances
- Verify token addresses before trading
- Start with small amounts while testing
Examples
A curated collection of example projects and scripts demonstrating common Bonanca workflows. Browse the examples to learn how to run bots, manage index funds, use the scalper, and interact with on-chain protocols in both Rust and Python.
Index Fund Example
The Index Fund is a Rust-based portfolio management tool that maintains a diversified cryptocurrency index. It allows you to manage a basket of tokens with automatic rebalancing to maintain target weights.
You can see the example code here.
Features
- Create and manage a diversified portfolio of cryptocurrencies
- Automatic rebalancing to target weights
- Multiple rebalancing strategies
Building the Project
cd examples/crates/index-fund
cargo build --release
Basic Usage
This example project build a CLI which includes help docs that cover basic usage.
index --help
Configuration
Create an index fund configuration file:
{
"name": "Basic Index Fund",
"chain": "EVM:Polygon",
"chain_id": 137,
"rpc_url": "https://1rpc.io/matic",
"keyvault": "./keyvault.json",
"child": 0,
"max_offset": 0.01,
"aggregator": {
"name": "0x",
"api_key": "API_KEY"
},
"oracle": {
"name": "DefiLlama",
"api_key": "API_KEY"
},
"auxiliary_assets": [
{
"name": "Dai Stablecoin",
"symbol": "DAI",
"address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063"
}
],
"sectors": [
{
"name": "Layer 1",
"weight": 0.4,
"assets": [
{
"name": "Bitcoin",
"symbol": "WBTC",
"address": "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6"
},
{
"name": "Ethereum",
"symbol": "WETH",
"address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"
}
]
},
{
"name": "DeFi",
"weight": 0.2,
"assets": [
{
"name": "Uniswap",
"symbol": "UNI",
"address": "0xb33EaAd8d922B1083446DC23f610c2567fB5180f"
},
{
"name": "Aave",
"symbol": "AAVE",
"address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B"
}
]
},
{
"name": "Infrastructure",
"weight": 0.2,
"assets": [
{
"name": "ChainLink",
"symbol": "LINK",
"address": "0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39"
},
{
"name": "Graph Token",
"symbol": "GRT",
"address": "0x5fe2B58c013d7601147DcdD68C143A77499f5531"
}
]
},
{
"name": "Stablecoins",
"weight": 0.2,
"assets": [
{
"name": "Circle USD",
"symbol": "USDC",
"address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
},
{
"name": "Stasis EUR",
"symbol": "EURS",
"address": "0xE111178A87A3BFf0c8d18DECBa5798827539Ae99"
}
]
}
]
}
Grid Bot Example
The Grid Bot is a Rust-based automated trading bot that implements a grid trading strategy on EVM-compatible blockchains. Grid trading works by placing buy and sell orders at regular price intervals (grid levels) to capture profits from price fluctuations.
You can see the example code here.
Features
- Automated grid trading on EVM chains
- Configurable grid parameters (size, max orders, price delta)
- Trading history and profit tracking
- Real-time order management
- Balance monitoring
Building the Project
cd examples/crates/grid-bot
cargo build --release
Basic Usage
This example project build a CLI which includes help docs that cover basic usage.
grid-bot --help
Configuration
Create a grid_bot.json configuration file with the following structure:
{
"chain": "base",
"rpc_url": "https://base.drpc.org",
"keyvault": "./keyvault.json",
"log_file": "./grid_bot_log.json",
"child": 0,
"trading_pair": {
"token_a": {
"name": "Circle USD",
"symbol": "USDC",
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"decimals": 6
},
"token_b": {
"name": "Ethereum",
"symbol": "WETH",
"address": "0x4200000000000000000000000000000000000006",
"decimals": 18
},
"num_grids": 5,
"upper_limit": 2300.0,
"lower_limit": 1700.0,
"buy_amount": 0.1,
"sell_amount": 0.1
}
}
Parameters
- num_grids: Number of grid levels to place
- upper_limit: The highest price at which to place sell orders
- lower_limit: The lowest price at which to place buy orders
- buy_amount: The amount of token_a to use for each buy level
- sell_amount: The amount of token_b to sell at each sell level
Scalper Bot Example
The Scalper Bot is a Python-based trading bot. Scalping involves making many small trades to capture tiny price differences (spreads). This uses the CoW protocol for limit orders.
You can check out the code here.
Features
- Automated scalping on EVM-compatible blockchains
- Configurable trade parameters and limits
- Detailed trade logging and performance tracking
- Order history tracking (buy/sell averages)
- Profit monitoring and reporting
- Support for any EVM token pair
Configuration
Create a scalper.toml configuration file:
chain = "Polygon"
rpc_url = "https://polygon-rpc.com"
keyvault = "./keyvault.json"
child = 0
log_file = "./grid_bot_log.json"
[base]
name = "Wrapped Ether"
symbol = "WETH"
address = "0x7ceB23fD6bC0adD59E27f9EA9d0231e0f01cc726"
decimals = 18
[target]
name = "USDC Coin"
symbol = "USDC"
address = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
decimals = 6
[trade_settings]
size = 0.1
max_orders = 5
delta = 0.2
profit = 1.5
expiry = "0-30-300"
Configuration Parameters
Trade Settings
- size: The size of each scalp trade (in base token units)
- max_orders: Maximum number of concurrent orders
- delta: Price difference between placed buy orders (percentage)
- profit: Minimum profit target for sell orders (percentage)
- expiry: Order expiration time format "DAYS-HOURS-MINUTES"
Output Files
- log_file: JSON file containing:
- Active orders
- Current profit
- Buy history (total bought, average buy price)
- Sell history (total sold, average sell price)
KeyVault
Bonança stores the seed to your HD wallet in what is called a KeyVault,
which can be serialized into a json file. This takes inspiration from
keystore files, if you are unfamiliar with them consider reading
this post.
When serialized, your HD wallet seed is encrypted using a password you
define. An example key vault json file structure is as follows:
{
"vault": {
"cipher": "aes256-gcm",
"cipher_params": { "nonce": "287189f34a1433d2de201d08" },
"cipher_text": "7a34170003c0a7b3ccb75bac28757801a7d9b5e1ff062afa4af5f3c03e7d8982eb1f36ccce87436e42b44ffea6bcf39eba8c15d4e79ee0bf012811fca81ae1e112c0f8ae5d8e43ac8cad1ae961b11207",
"kdf": "pbkdf2",
"kdf_params": {
"key_length": 32,
"n": 600000,
"salt": "M6lWvNAGuZBSp9fBGAUEqw"
},
"mac": "$argon2id$v=19$m=19456,t=2,p=1$M6lWvNAGuZBSp9fBGAUEqw$/U5VYPmg3+BQj0ttOyPnOUjH7bP23V9/tgvBpovna/8",
"salt": "M6lWvNAGuZBSp9fBGAUEqw"
},
"chain_keys": {
"Solana": ["AbwHhAquPXvDfxvWEh1b4mG969DQF9wJQSK5k8XKSKtG"],
"EVM": ["0x50940F0C5779BE15F7ACB12E9b75128e1415BFec"]
}
}
Breaking down the components:
cipheris the encryption algorithm used to encrypt your HD wallet seed- Within
cipher_paramsyou findnoncewhich is an initialization vector for the AES-256-GCM algorithm cipher_textis your encrypted seedkdfis the key derivation function used (PBKDF2)kdf_paramsare the parameters used in the key derivation functionkey_lengthis the length in bytes of the keynis the number of cycles in the algorithm, where 600,000 is used to make encrypting/decrypting time consuming to prevent brute force attackssaltis the password salt
macis your hashed and salted password using Argon2 (its parameters are included in the mac string)saltagain the password saltchain_keysthese are your public keys for various blockchains
Changes to any of these fields can result in failure to decrypt the seed, and possibly permanent loss of all funds.
The only point of weakness within the KeyVault encryption is your choice
of password. If a malicious actor were to get a hold of your json file,
they could try to decrypt it by either guessing the password or the seed.
Guessing the seed is extremely difficult and unlikely, whereas guessing
a password is more doable. This means picking a good password is crucial.
KeyVault includes your public keys within the chain_keys field, which
allows you to view your accounts without having to decrypt your KeyVault.
There are positives and negatives to this approach, with the main benefit
being that you can check wallet balances without supplying your password.
The main drawback is that if a malicious actor were to get this file, they
would know how valuable breaking the encryption is.
Contributing to Bonança
I welcome contributions from the community to help improve Bonança! Whether it's fixing bugs, adding new features, or improving documentation, your contributions are valuable to me. Here are some guidelines to help you get started:
Getting Started
- Fork the Repository: Start by forking the Bonança repository on GitHub to create your own copy of the project.
- Create a Branch: Create a new branch for your feature or bug fix. Use a descriptive name for your branch, such as
add-new-botorfix-index-calculation. - Make Changes: Make your changes in the new branch. Ensure that your code follows the existing coding style and conventions used in the project.
- Test Your Changes: Write tests for your changes to ensure they work as expected and do not introduce new issues. Run existing tests to verify that everything is still functioning correctly.
- Commit Your Changes: Commit your changes with clear and concise commit messages that describe the purpose of the changes.
- Push to Your Fork: Push your changes to your forked repository on GitHub.
- Create a Pull Request: Open a pull request from your branch to the main Bonança repository. Provide a detailed description of the changes you made and any relevant information for reviewers.
Reporting Issues
If you encounter any bugs or have suggestions for new features, please open an issue on the GitHub Issues page. Provide as much detail as possible to help us understand and address the issue.
Support Bonança
If you find Bonança useful and would like to support its development, there are several ways you can contribute:
- Star the Repository: Show your appreciation by starring the Bonança GitHub repository. This helps increase the visibility of the project and encourages others to check it out.
- Report Issues: If you encounter any bugs or have suggestions for new features, please open an issue on the GitHub Issues page. Providing detailed information helps me address problems more effectively.
- Contribute Code: If you're a developer, consider contributing code to the project. You can fork the repository, make improvements or add new features, and submit a pull request.
- Spread the Word: Share Bonança with your friends, colleagues, and on social media. The more people who know about it, the more support and contributions the project can receive.
Thank you for being a part of the Bonança community!
Reporting Security Issues
If you discover a security vulnerability in Bonança, please report it to me privately so that we can address the issue before it becomes public knowledge. This helps protect all users of Bonança and ensures that vulnerabilities are fixed promptly.