# Sixty Nuts - A NIP-60 Cashu Wallet in Python
A lightweight, stateless Cashu wallet implementation following [NIP-60](https://github.com/nostr-protocol/nips/blob/master/60.md) specification for Nostr-based wallet state management.
## Features
- **NIP-60 Compliant**: Full implementation of the NIP-60 specification for Cashu wallet state management
- **NIP-44 Encryption**: Secure encryption using the NIP-44 v2 standard for all sensitive data
- **Stateless Design**: Wallet state stored on Nostr relays with automatic synchronization
- **Multi-Mint Support**: Seamlessly work with multiple Cashu mints with automatic token swapping
- **Modern Python**: Async/await implementation with full type hints (Python 3.11+)
- **LNURL Support**: Send to Lightning Addresses and other LNURL formats
- **CLI Interface**: Full-featured command-line interface for all wallet operations
- **Temporary Wallets**: Ephemeral wallets for one-time operations without key storage
- **Auto-Discovery**: Automatic relay and mint discovery with intelligent caching
- **QR Code Support**: Built-in QR code generation for invoices and tokens
## Installation
```bash
pip install sixty-nuts
```
For QR code support in the CLI:
```bash
pip install sixty-nuts[qr]
# or
pip install qrcode
```
## Quick Start
### CLI Usage (Recommended)
The easiest way to get started is with the CLI:
```bash
# Check status and initialize if needed
nuts status
# Check balance
nuts balance
# Create Lightning invoice to add funds
nuts mint 1000
# Send tokens
nuts send 100
# Redeem received token
nuts redeem cashuA...
# Send to Lightning Address
nuts send 500 --to-lnurl user@getalby.com
# Pay Lightning invoice
nuts pay lnbc...
```
### Python API Usage
```python
import asyncio
from sixty_nuts import Wallet
async def main():
# Create wallet with automatic relay/mint discovery
async with Wallet(nsec="your_nsec_private_key") as wallet:
# Check balance
balance = await wallet.get_balance()
print(f"Balance: {balance} sats")
# Create invoice and wait for payment
invoice, task = await wallet.mint_async(1000)
print(f"Pay: {invoice}")
paid = await task
if paid:
# Send tokens
token = await wallet.send(100)
print(f"Token: {token}")
asyncio.run(main())
```
## Command Line Interface
The `nuts` CLI provides a complete interface for wallet operations:
### Basic Commands
#### `nuts status`
Check wallet initialization status and configuration:
```bash
# Check if wallet is initialized
nuts status
# Initialize wallet if needed
nuts status --init
# Force re-initialization
nuts status --force
```
#### `nuts balance`
Check your wallet balance:
```bash
# Quick balance check
nuts balance
# Detailed breakdown by mint
nuts balance --details
# Skip proof validation for speed
nuts balance --no-validate
```
#### `nuts mint <amount>`
Create Lightning invoice to add funds:
```bash
# Mint 1000 sats
nuts mint 1000
# With custom timeout
nuts mint 1000 --timeout 600
# Without QR code display
nuts mint 1000 --no-qr
```
#### `nuts send <amount>`
Send sats as Cashu token or to Lightning Address:
```bash
# Create Cashu token
nuts send 100
# Send directly to Lightning Address
nuts send 500 --to-lnurl user@getalby.com
# Send without QR code
nuts send 100 --no-qr
```
#### `nuts redeem <token>`
Redeem received Cashu tokens:
```bash
# Redeem token to wallet
nuts redeem cashuA...
# Redeem and forward to Lightning Address
nuts redeem cashuA... --to-lnurl user@getalby.com
# Disable auto-swap from untrusted mints
nuts redeem cashuA... --no-auto-swap
```
#### `nuts pay <invoice>`
Pay Lightning invoices:
```bash
# Pay BOLT11 invoice
nuts pay lnbc...
```
### Management Commands
#### `nuts info`
Show detailed wallet information:
```bash
nuts info
```
#### `nuts history`
View transaction history:
```bash
# Show recent transactions
nuts history
# Limit number of entries
nuts history --limit 10
```
#### `nuts relays`
Manage Nostr relay configuration:
```bash
# List configured relays
nuts relays --list
# Test relay connectivity
nuts relays --test
# Discover relays from profile
nuts relays --discover
# Interactive configuration
nuts relays --configure
# Clear relay cache
nuts relays --clear-cache
```
#### `nuts cleanup`
Clean up wallet state:
```bash
# Show what would be cleaned up
nuts cleanup --dry-run
# Clean up old/corrupted events
nuts cleanup
# Skip confirmation
nuts cleanup --yes
```
#### `nuts erase`
Delete wallet data (⚠️ DANGEROUS):
```bash
# Delete wallet configuration
nuts erase --wallet
# Delete transaction history
nuts erase --history
# Delete token storage (affects balance!)
nuts erase --tokens
# Clear locally stored NSEC
nuts erase --nsec
# Nuclear option - delete everything
nuts erase --all
# Skip confirmation
nuts erase --all --yes
```
#### `nuts debug`
Debug wallet issues:
```bash
# Debug Nostr connectivity
nuts debug --nostr
# Debug balance/proof issues
nuts debug --balance
# Debug proof state
nuts debug --proofs
# Debug wallet configuration
nuts debug --wallet
# Debug history decryption
nuts debug --history
```
### Global Options
Most commands support these options:
- `--mint, -m`: Specify mint URLs
- `--help`: Show command help
- `--yes, -y`: Skip confirmations (where applicable)
### Environment Configuration
The CLI automatically manages configuration through environment variables and `.env` files:
#### Required Configuration
- `NSEC`: Your Nostr private key (nsec1... or hex format)
#### Optional Configuration
- `CASHU_MINTS`: Comma-separated list of mint URLs
- `NOSTR_RELAYS`: Comma-separated list of relay URLs
#### Example `.env` file
```bash
NSEC="nsec1your_private_key_here"
CASHU_MINTS="https://mint.minibits.cash/Bitcoin,https://mint.cubabitcoin.org"
NOSTR_RELAYS="wss://relay.damus.io,wss://nostr.wine"
```
The CLI will prompt for missing configuration and automatically cache your choices.
## Python API
### Basic Wallet Setup
```python
import asyncio
from sixty_nuts import Wallet
async def main():
# Create wallet with explicit configuration
wallet = await Wallet.create(
nsec="your_nsec_private_key", # hex or nsec1... format
mint_urls=["https://mint.minibits.cash/Bitcoin"],
relays=["wss://relay.damus.io", "wss://nostr.wine"]
)
# Or use context manager for automatic cleanup
async with Wallet(nsec="your_nsec_private_key") as wallet:
# Wallet operations here
pass
asyncio.run(main())
```
### Temporary Wallets
For one-time operations without storing keys:
```python
import asyncio
from sixty_nuts import TempWallet
async def main():
# Create temporary wallet with auto-generated keys
async with TempWallet() as wallet:
# Use wallet normally - keys are never stored
balance = await wallet.get_balance()
print(f"Balance: {balance} sats")
# Perfect for redeeming tokens to Lightning Address
token = "cashuA..."
amount, unit = await wallet.redeem(token)
await wallet.send_to_lnurl("user@getalby.com", amount)
asyncio.run(main())
```
**TempWallet Use Cases:**
- One-time token redemption
- Privacy-focused operations
- Testing and development
- Receiving tokens without account setup
### Core Operations
#### Minting (Receiving via Lightning)
```python
async def mint_tokens(wallet: Wallet):
# Create Lightning invoice
invoice, payment_task = await wallet.mint_async(1000)
print(f"Pay: {invoice}")
# Wait for payment (5 minute timeout)
paid = await payment_task
if paid:
balance = await wallet.get_balance()
print(f"New balance: {balance} sats")
```
#### Sending Tokens
```python
async def send_tokens(wallet: Wallet):
# Check balance
balance = await wallet.get_balance()
if balance >= 100:
# Create Cashu token (V4 format by default)
token = await wallet.send(100)
print(f"Token: {token}")
# Or use V3 format for compatibility
token_v3 = await wallet.send(100, token_version=3)
```
#### Redeeming Tokens
```python
async def redeem_tokens(wallet: Wallet):
token = "cashuA..." # Token from someone else
try:
amount, unit = await wallet.redeem(token)
print(f"Redeemed: {amount} {unit}")
balance = await wallet.get_balance()
print(f"New balance: {balance}")
except WalletError as e:
print(f"Failed: {e}")
```
#### Lightning Payments
```python
async def pay_invoice(wallet: Wallet):
invoice = "lnbc..."
try:
await wallet.melt(invoice)
print("Payment successful!")
except WalletError as e:
print(f"Payment failed: {e}")
```
#### LNURL/Lightning Address Support
```python
async def send_to_lightning_address(wallet: Wallet):
# Send to Lightning Address
amount_sent = await wallet.send_to_lnurl("user@getalby.com", 1000)
print(f"Sent: {amount_sent} sats")
# Works with various LNURL formats:
# - user@domain.com (Lightning Address)
# - LNURL1... (bech32 encoded)
# - lightning:user@domain.com (with prefix)
# - https://... (direct URL)
```
### Wallet State Management
```python
async def check_wallet_state(wallet: Wallet):
# Fetch complete wallet state
state = await wallet.fetch_wallet_state()
print(f"Balance: {state.balance} sats")
print(f"Proofs: {len(state.proofs)}")
print(f"Mints: {list(state.mint_keysets.keys())}")
# Show denomination breakdown
denominations = {}
for proof in state.proofs:
amount = proof["amount"]
denominations[amount] = denominations.get(amount, 0) + 1
for amount, count in sorted(denominations.items()):
print(f" {amount} sat: {count} proof(s)")
```
### Complete Example
```python
import asyncio
from sixty_nuts import Wallet
async def complete_example():
async with Wallet(nsec="your_nsec") as wallet:
# Initialize wallet events if needed
await wallet.initialize_wallet()
# Check initial state
balance = await wallet.get_balance()
print(f"Starting balance: {balance} sats")
# Mint tokens if balance is low
if balance < 1000:
invoice, task = await wallet.mint_async(1000)
print(f"Pay: {invoice}")
if await task:
print("Payment received!")
# Send some tokens
token = await wallet.send(100)
print(f"Created token: {token}")
# Send to Lightning Address
await wallet.send_to_lnurl("user@getalby.com", 200)
print("Sent to Lightning Address!")
# Final balance
final_balance = await wallet.get_balance()
print(f"Final balance: {final_balance} sats")
if __name__ == "__main__":
asyncio.run(complete_example())
```
## Architecture
### NIP-60 Implementation
Sixty Nuts implements the complete NIP-60 specification:
- **Wallet Events** (kind 17375): Encrypted wallet metadata and configuration
- **Token Events** (kind 7375): Encrypted Cashu proof storage with rollover support
- **History Events** (kind 7376): Optional encrypted transaction history
- **Delete Events** (kind 5): Proper event deletion with relay compatibility
### Multi-Mint Strategy
- **Primary Mint**: Default mint for operations
- **Auto-Swapping**: Automatic token swapping from untrusted mints
- **Fee Optimization**: Intelligent proof selection to minimize transaction fees
- **Denomination Management**: Automatic proof splitting for optimal denominations
### Proof Management
- **State Validation**: Real-time proof validation with mint connectivity
- **Caching System**: Smart caching to avoid re-validating spent proofs
- **Backup & Recovery**: Automatic proof backup to Nostr relays with local fallback
- **Consolidation**: Automatic cleanup of fragmented wallet state
### Security Features
- **NIP-44 Encryption**: All sensitive data encrypted using NIP-44 v2
- **Key Separation**: Separate keys for Nostr identity and P2PK ecash operations
- **Local Backup**: Automatic local proof backup before Nostr operations
- **State Validation**: Cryptographic proof validation before operations
## Development
### Project Structure
```
sixty_nuts/
├── __init__.py # Package exports
├── wallet.py # Main Wallet class implementation
├── temp.py # TempWallet for ephemeral operations
├── mint.py # Cashu mint API client
├── relay.py # Nostr relay WebSocket client
├── events.py # NIP-60 event management
├── crypto.py # Cryptographic primitives (BDHKE, NIP-44)
├── lnurl.py # LNURL protocol support
├── types.py # Type definitions and errors
└── cli.py # Command-line interface
tests/
├── unit/ # Unit tests (fast, no external deps)
├── integration/ # Integration tests (require Docker)
└── run_integration.py # Integration test orchestration
examples/
├── basic_operations.py # Basic wallet operations
├── multi_mint.py # Multi-mint examples
├── lnurl_operations.py # LNURL examples
└── one_off_redeem.py # TempWallet examples
```
### Running Tests
#### Unit Tests
```bash
# Run all unit tests
pytest tests/unit/ -v
# Run with coverage
pytest tests/unit/ --cov=sixty_nuts --cov-report=html
```
#### Integration Tests
```bash
# Automated with Docker
python tests/run_integration.py
# Manual control
docker-compose up -d
RUN_INTEGRATION_TESTS=1 pytest tests/integration/ -v
docker-compose down -v
```
### Code Quality
```bash
# Type checking
mypy sixty_nuts/
# Linting
ruff check sixty_nuts/
# Formatting
ruff format sixty_nuts/
```
## Contributing
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request
Please follow the existing code style and add comprehensive tests for new features.
## Implementation Status
### ✅ Completed Features
- [x] NIP-60 wallet state management
- [x] NIP-44 v2 encryption for all sensitive data
- [x] Multi-mint support with automatic swapping
- [x] Lightning invoice creation and payment
- [x] Cashu token sending and receiving (V3/V4 formats)
- [x] LNURL/Lightning Address support
- [x] Proof validation and state management
- [x] Automatic relay discovery and caching
- [x] Complete CLI interface
- [x] TempWallet for ephemeral operations
- [x] Automatic proof consolidation
- [x] Transaction history tracking
- [x] QR code generation
- [x] Comprehensive error handling
### 🚧 Work in Progress
- [ ] **P2PK Ecash Support** (NIP-61): Partially implemented
- [ ] **Quote Tracking**: Implement full NIP-60 quote tracking (kind 7374)
- [ ] **Multi-Mint Transactions**: Atomic operations across multiple mints
- [ ] **Advanced Coin Selection**: Privacy-optimized proof selection algorithms
- [ ] **Offline Operations**: Enhanced offline capability with delayed sync
## Troubleshooting
### Common Issues
#### "No mint URLs configured"
```bash
# Set mint URLs via environment
export CASHU_MINTS="https://mint.minibits.cash/Bitcoin"
# Or use CLI to select
nuts status --init
```
#### "Could not connect to relays"
```bash
# Test relay connectivity
nuts debug --nostr
# Configure relays manually
nuts relays --configure
```
#### "Insufficient balance"
```bash
# Check actual balance with validation
nuts balance --validate
# Clean up corrupted state
nuts cleanup
```
#### QR codes not displaying
```bash
# Install QR code support
pip install qrcode
# Disable QR codes
nuts mint 1000 --no-qr
```
### Debug Commands
The CLI provides extensive debugging capabilities:
```bash
# Comprehensive wallet debugging
nuts debug --wallet --nostr --balance --proofs
# Debug specific issues
nuts debug --history # Transaction history issues
nuts debug --balance # Balance calculation issues
nuts debug --proofs # Proof validation issues
```
## Related Projects
- [Cashu Protocol](https://cashu.space) - Chaumian ecash protocol specification
- [NIP-60](https://github.com/nostr-protocol/nips/blob/master/60.md) - Cashu Wallet specification
- [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md) - Encryption specification
- [Nostr Protocol](https://nostr.com) - Decentralized communication protocol
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Support
- **Issues**: [GitHub Issues](https://github.com/your-org/sixty-nuts/issues)
- **Discussions**: [GitHub Discussions](https://github.com/your-org/sixty-nuts/discussions)
- **Nostr**: Follow development updates via Nostr
---
**⚡ Start using Cashu with Nostr today!**
```bash
pip install sixty-nuts
nuts status --init
nuts mint 1000
```
Raw data
{
"_id": null,
"home_page": null,
"name": "sixty-nuts",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "bitcoin, cashu, ecash, lightning, nip-60, nostr, wallet",
"author": null,
"author_email": "shroominic <contact@shroominic.com>",
"download_url": "https://files.pythonhosted.org/packages/4b/24/ecab6ba4cf78ee4e32ddc1e820fdd72234850d80ccb365227ee46b5ddfe1/sixty_nuts-0.1.4.tar.gz",
"platform": null,
"description": "# Sixty Nuts - A NIP-60 Cashu Wallet in Python\n\nA lightweight, stateless Cashu wallet implementation following [NIP-60](https://github.com/nostr-protocol/nips/blob/master/60.md) specification for Nostr-based wallet state management.\n\n## Features\n\n- **NIP-60 Compliant**: Full implementation of the NIP-60 specification for Cashu wallet state management\n- **NIP-44 Encryption**: Secure encryption using the NIP-44 v2 standard for all sensitive data\n- **Stateless Design**: Wallet state stored on Nostr relays with automatic synchronization\n- **Multi-Mint Support**: Seamlessly work with multiple Cashu mints with automatic token swapping\n- **Modern Python**: Async/await implementation with full type hints (Python 3.11+)\n- **LNURL Support**: Send to Lightning Addresses and other LNURL formats\n- **CLI Interface**: Full-featured command-line interface for all wallet operations\n- **Temporary Wallets**: Ephemeral wallets for one-time operations without key storage\n- **Auto-Discovery**: Automatic relay and mint discovery with intelligent caching\n- **QR Code Support**: Built-in QR code generation for invoices and tokens\n\n## Installation\n\n```bash\npip install sixty-nuts\n```\n\nFor QR code support in the CLI:\n\n```bash\npip install sixty-nuts[qr]\n# or\npip install qrcode\n```\n\n## Quick Start\n\n### CLI Usage (Recommended)\n\nThe easiest way to get started is with the CLI:\n\n```bash\n# Check status and initialize if needed\nnuts status\n\n# Check balance\nnuts balance\n\n# Create Lightning invoice to add funds\nnuts mint 1000\n\n# Send tokens\nnuts send 100\n\n# Redeem received token\nnuts redeem cashuA...\n\n# Send to Lightning Address\nnuts send 500 --to-lnurl user@getalby.com\n\n# Pay Lightning invoice\nnuts pay lnbc...\n```\n\n### Python API Usage\n\n```python\nimport asyncio\nfrom sixty_nuts import Wallet\n\nasync def main():\n # Create wallet with automatic relay/mint discovery\n async with Wallet(nsec=\"your_nsec_private_key\") as wallet:\n # Check balance\n balance = await wallet.get_balance()\n print(f\"Balance: {balance} sats\")\n \n # Create invoice and wait for payment\n invoice, task = await wallet.mint_async(1000)\n print(f\"Pay: {invoice}\")\n paid = await task\n \n if paid:\n # Send tokens\n token = await wallet.send(100)\n print(f\"Token: {token}\")\n\nasyncio.run(main())\n```\n\n## Command Line Interface\n\nThe `nuts` CLI provides a complete interface for wallet operations:\n\n### Basic Commands\n\n#### `nuts status`\n\nCheck wallet initialization status and configuration:\n\n```bash\n# Check if wallet is initialized\nnuts status\n\n# Initialize wallet if needed\nnuts status --init\n\n# Force re-initialization\nnuts status --force\n```\n\n#### `nuts balance`\n\nCheck your wallet balance:\n\n```bash\n# Quick balance check\nnuts balance\n\n# Detailed breakdown by mint\nnuts balance --details\n\n# Skip proof validation for speed\nnuts balance --no-validate\n```\n\n#### `nuts mint <amount>`\n\nCreate Lightning invoice to add funds:\n\n```bash\n# Mint 1000 sats\nnuts mint 1000\n\n# With custom timeout\nnuts mint 1000 --timeout 600\n\n# Without QR code display\nnuts mint 1000 --no-qr\n```\n\n#### `nuts send <amount>`\n\nSend sats as Cashu token or to Lightning Address:\n\n```bash\n# Create Cashu token\nnuts send 100\n\n# Send directly to Lightning Address\nnuts send 500 --to-lnurl user@getalby.com\n\n# Send without QR code\nnuts send 100 --no-qr\n```\n\n#### `nuts redeem <token>`\n\nRedeem received Cashu tokens:\n\n```bash\n# Redeem token to wallet\nnuts redeem cashuA...\n\n# Redeem and forward to Lightning Address\nnuts redeem cashuA... --to-lnurl user@getalby.com\n\n# Disable auto-swap from untrusted mints\nnuts redeem cashuA... --no-auto-swap\n```\n\n#### `nuts pay <invoice>`\n\nPay Lightning invoices:\n\n```bash\n# Pay BOLT11 invoice\nnuts pay lnbc...\n```\n\n### Management Commands\n\n#### `nuts info`\n\nShow detailed wallet information:\n\n```bash\nnuts info\n```\n\n#### `nuts history`\n\nView transaction history:\n\n```bash\n# Show recent transactions\nnuts history\n\n# Limit number of entries\nnuts history --limit 10\n```\n\n#### `nuts relays`\n\nManage Nostr relay configuration:\n\n```bash\n# List configured relays\nnuts relays --list\n\n# Test relay connectivity\nnuts relays --test\n\n# Discover relays from profile\nnuts relays --discover\n\n# Interactive configuration\nnuts relays --configure\n\n# Clear relay cache\nnuts relays --clear-cache\n```\n\n#### `nuts cleanup`\n\nClean up wallet state:\n\n```bash\n# Show what would be cleaned up\nnuts cleanup --dry-run\n\n# Clean up old/corrupted events\nnuts cleanup\n\n# Skip confirmation\nnuts cleanup --yes\n```\n\n#### `nuts erase`\n\nDelete wallet data (\u26a0\ufe0f DANGEROUS):\n\n```bash\n# Delete wallet configuration\nnuts erase --wallet\n\n# Delete transaction history\nnuts erase --history\n\n# Delete token storage (affects balance!)\nnuts erase --tokens\n\n# Clear locally stored NSEC\nnuts erase --nsec\n\n# Nuclear option - delete everything\nnuts erase --all\n\n# Skip confirmation\nnuts erase --all --yes\n```\n\n#### `nuts debug`\n\nDebug wallet issues:\n\n```bash\n# Debug Nostr connectivity\nnuts debug --nostr\n\n# Debug balance/proof issues\nnuts debug --balance\n\n# Debug proof state\nnuts debug --proofs\n\n# Debug wallet configuration\nnuts debug --wallet\n\n# Debug history decryption\nnuts debug --history\n```\n\n### Global Options\n\nMost commands support these options:\n\n- `--mint, -m`: Specify mint URLs\n- `--help`: Show command help\n- `--yes, -y`: Skip confirmations (where applicable)\n\n### Environment Configuration\n\nThe CLI automatically manages configuration through environment variables and `.env` files:\n\n#### Required Configuration\n\n- `NSEC`: Your Nostr private key (nsec1... or hex format)\n\n#### Optional Configuration\n\n- `CASHU_MINTS`: Comma-separated list of mint URLs\n- `NOSTR_RELAYS`: Comma-separated list of relay URLs\n\n#### Example `.env` file\n\n```bash\nNSEC=\"nsec1your_private_key_here\"\nCASHU_MINTS=\"https://mint.minibits.cash/Bitcoin,https://mint.cubabitcoin.org\"\nNOSTR_RELAYS=\"wss://relay.damus.io,wss://nostr.wine\"\n```\n\nThe CLI will prompt for missing configuration and automatically cache your choices.\n\n## Python API\n\n### Basic Wallet Setup\n\n```python\nimport asyncio\nfrom sixty_nuts import Wallet\n\nasync def main():\n # Create wallet with explicit configuration\n wallet = await Wallet.create(\n nsec=\"your_nsec_private_key\", # hex or nsec1... format\n mint_urls=[\"https://mint.minibits.cash/Bitcoin\"],\n relays=[\"wss://relay.damus.io\", \"wss://nostr.wine\"]\n )\n \n # Or use context manager for automatic cleanup\n async with Wallet(nsec=\"your_nsec_private_key\") as wallet:\n # Wallet operations here\n pass\n\nasyncio.run(main())\n```\n\n### Temporary Wallets\n\nFor one-time operations without storing keys:\n\n```python\nimport asyncio\nfrom sixty_nuts import TempWallet\n\nasync def main():\n # Create temporary wallet with auto-generated keys\n async with TempWallet() as wallet:\n # Use wallet normally - keys are never stored\n balance = await wallet.get_balance()\n print(f\"Balance: {balance} sats\")\n \n # Perfect for redeeming tokens to Lightning Address\n token = \"cashuA...\"\n amount, unit = await wallet.redeem(token)\n await wallet.send_to_lnurl(\"user@getalby.com\", amount)\n\nasyncio.run(main())\n```\n\n**TempWallet Use Cases:**\n\n- One-time token redemption\n- Privacy-focused operations\n- Testing and development\n- Receiving tokens without account setup\n\n### Core Operations\n\n#### Minting (Receiving via Lightning)\n\n```python\nasync def mint_tokens(wallet: Wallet):\n # Create Lightning invoice\n invoice, payment_task = await wallet.mint_async(1000)\n \n print(f\"Pay: {invoice}\")\n \n # Wait for payment (5 minute timeout)\n paid = await payment_task\n \n if paid:\n balance = await wallet.get_balance()\n print(f\"New balance: {balance} sats\")\n```\n\n#### Sending Tokens\n\n```python\nasync def send_tokens(wallet: Wallet):\n # Check balance\n balance = await wallet.get_balance()\n \n if balance >= 100:\n # Create Cashu token (V4 format by default)\n token = await wallet.send(100)\n print(f\"Token: {token}\")\n \n # Or use V3 format for compatibility\n token_v3 = await wallet.send(100, token_version=3)\n```\n\n#### Redeeming Tokens\n\n```python\nasync def redeem_tokens(wallet: Wallet):\n token = \"cashuA...\" # Token from someone else\n \n try:\n amount, unit = await wallet.redeem(token)\n print(f\"Redeemed: {amount} {unit}\")\n \n balance = await wallet.get_balance()\n print(f\"New balance: {balance}\")\n except WalletError as e:\n print(f\"Failed: {e}\")\n```\n\n#### Lightning Payments\n\n```python\nasync def pay_invoice(wallet: Wallet):\n invoice = \"lnbc...\"\n \n try:\n await wallet.melt(invoice)\n print(\"Payment successful!\")\n except WalletError as e:\n print(f\"Payment failed: {e}\")\n```\n\n#### LNURL/Lightning Address Support\n\n```python\nasync def send_to_lightning_address(wallet: Wallet):\n # Send to Lightning Address\n amount_sent = await wallet.send_to_lnurl(\"user@getalby.com\", 1000)\n print(f\"Sent: {amount_sent} sats\")\n \n # Works with various LNURL formats:\n # - user@domain.com (Lightning Address)\n # - LNURL1... (bech32 encoded)\n # - lightning:user@domain.com (with prefix)\n # - https://... (direct URL)\n```\n\n### Wallet State Management\n\n```python\nasync def check_wallet_state(wallet: Wallet):\n # Fetch complete wallet state\n state = await wallet.fetch_wallet_state()\n \n print(f\"Balance: {state.balance} sats\")\n print(f\"Proofs: {len(state.proofs)}\")\n print(f\"Mints: {list(state.mint_keysets.keys())}\")\n \n # Show denomination breakdown\n denominations = {}\n for proof in state.proofs:\n amount = proof[\"amount\"]\n denominations[amount] = denominations.get(amount, 0) + 1\n \n for amount, count in sorted(denominations.items()):\n print(f\" {amount} sat: {count} proof(s)\")\n```\n\n### Complete Example\n\n```python\nimport asyncio\nfrom sixty_nuts import Wallet\n\nasync def complete_example():\n async with Wallet(nsec=\"your_nsec\") as wallet:\n # Initialize wallet events if needed\n await wallet.initialize_wallet()\n \n # Check initial state\n balance = await wallet.get_balance()\n print(f\"Starting balance: {balance} sats\")\n \n # Mint tokens if balance is low\n if balance < 1000:\n invoice, task = await wallet.mint_async(1000)\n print(f\"Pay: {invoice}\")\n \n if await task:\n print(\"Payment received!\")\n \n # Send some tokens\n token = await wallet.send(100)\n print(f\"Created token: {token}\")\n \n # Send to Lightning Address\n await wallet.send_to_lnurl(\"user@getalby.com\", 200)\n print(\"Sent to Lightning Address!\")\n \n # Final balance\n final_balance = await wallet.get_balance()\n print(f\"Final balance: {final_balance} sats\")\n\nif __name__ == \"__main__\":\n asyncio.run(complete_example())\n```\n\n## Architecture\n\n### NIP-60 Implementation\n\nSixty Nuts implements the complete NIP-60 specification:\n\n- **Wallet Events** (kind 17375): Encrypted wallet metadata and configuration\n- **Token Events** (kind 7375): Encrypted Cashu proof storage with rollover support\n- **History Events** (kind 7376): Optional encrypted transaction history\n- **Delete Events** (kind 5): Proper event deletion with relay compatibility\n\n### Multi-Mint Strategy\n\n- **Primary Mint**: Default mint for operations\n- **Auto-Swapping**: Automatic token swapping from untrusted mints\n- **Fee Optimization**: Intelligent proof selection to minimize transaction fees\n- **Denomination Management**: Automatic proof splitting for optimal denominations\n\n### Proof Management\n\n- **State Validation**: Real-time proof validation with mint connectivity\n- **Caching System**: Smart caching to avoid re-validating spent proofs\n- **Backup & Recovery**: Automatic proof backup to Nostr relays with local fallback\n- **Consolidation**: Automatic cleanup of fragmented wallet state\n\n### Security Features\n\n- **NIP-44 Encryption**: All sensitive data encrypted using NIP-44 v2\n- **Key Separation**: Separate keys for Nostr identity and P2PK ecash operations \n- **Local Backup**: Automatic local proof backup before Nostr operations\n- **State Validation**: Cryptographic proof validation before operations\n\n## Development\n\n### Project Structure\n\n```\nsixty_nuts/\n\u251c\u2500\u2500 __init__.py # Package exports\n\u251c\u2500\u2500 wallet.py # Main Wallet class implementation\n\u251c\u2500\u2500 temp.py # TempWallet for ephemeral operations\n\u251c\u2500\u2500 mint.py # Cashu mint API client\n\u251c\u2500\u2500 relay.py # Nostr relay WebSocket client\n\u251c\u2500\u2500 events.py # NIP-60 event management\n\u251c\u2500\u2500 crypto.py # Cryptographic primitives (BDHKE, NIP-44)\n\u251c\u2500\u2500 lnurl.py # LNURL protocol support\n\u251c\u2500\u2500 types.py # Type definitions and errors\n\u2514\u2500\u2500 cli.py # Command-line interface\n\ntests/\n\u251c\u2500\u2500 unit/ # Unit tests (fast, no external deps)\n\u251c\u2500\u2500 integration/ # Integration tests (require Docker)\n\u2514\u2500\u2500 run_integration.py # Integration test orchestration\n\nexamples/\n\u251c\u2500\u2500 basic_operations.py # Basic wallet operations\n\u251c\u2500\u2500 multi_mint.py # Multi-mint examples\n\u251c\u2500\u2500 lnurl_operations.py # LNURL examples\n\u2514\u2500\u2500 one_off_redeem.py # TempWallet examples\n```\n\n### Running Tests\n\n#### Unit Tests\n\n```bash\n# Run all unit tests\npytest tests/unit/ -v\n\n# Run with coverage\npytest tests/unit/ --cov=sixty_nuts --cov-report=html\n```\n\n#### Integration Tests\n\n```bash\n# Automated with Docker\npython tests/run_integration.py\n\n# Manual control\ndocker-compose up -d\nRUN_INTEGRATION_TESTS=1 pytest tests/integration/ -v\ndocker-compose down -v\n```\n\n### Code Quality\n\n```bash\n# Type checking\nmypy sixty_nuts/\n\n# Linting \nruff check sixty_nuts/\n\n# Formatting\nruff format sixty_nuts/\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new functionality\n4. Ensure all tests pass\n5. Submit a pull request\n\nPlease follow the existing code style and add comprehensive tests for new features.\n\n## Implementation Status\n\n### \u2705 Completed Features\n\n- [x] NIP-60 wallet state management\n- [x] NIP-44 v2 encryption for all sensitive data\n- [x] Multi-mint support with automatic swapping\n- [x] Lightning invoice creation and payment\n- [x] Cashu token sending and receiving (V3/V4 formats)\n- [x] LNURL/Lightning Address support\n- [x] Proof validation and state management\n- [x] Automatic relay discovery and caching\n- [x] Complete CLI interface\n- [x] TempWallet for ephemeral operations\n- [x] Automatic proof consolidation\n- [x] Transaction history tracking\n- [x] QR code generation\n- [x] Comprehensive error handling\n\n### \ud83d\udea7 Work in Progress\n\n- [ ] **P2PK Ecash Support** (NIP-61): Partially implemented\n- [ ] **Quote Tracking**: Implement full NIP-60 quote tracking (kind 7374)\n- [ ] **Multi-Mint Transactions**: Atomic operations across multiple mints\n- [ ] **Advanced Coin Selection**: Privacy-optimized proof selection algorithms\n- [ ] **Offline Operations**: Enhanced offline capability with delayed sync\n\n## Troubleshooting\n\n### Common Issues\n\n#### \"No mint URLs configured\"\n\n```bash\n# Set mint URLs via environment\nexport CASHU_MINTS=\"https://mint.minibits.cash/Bitcoin\"\n\n# Or use CLI to select\nnuts status --init\n```\n\n#### \"Could not connect to relays\"\n\n```bash\n# Test relay connectivity\nnuts debug --nostr\n\n# Configure relays manually\nnuts relays --configure\n```\n\n#### \"Insufficient balance\"\n\n```bash\n# Check actual balance with validation\nnuts balance --validate\n\n# Clean up corrupted state\nnuts cleanup\n```\n\n#### QR codes not displaying\n\n```bash\n# Install QR code support\npip install qrcode\n\n# Disable QR codes\nnuts mint 1000 --no-qr\n```\n\n### Debug Commands\n\nThe CLI provides extensive debugging capabilities:\n\n```bash\n# Comprehensive wallet debugging\nnuts debug --wallet --nostr --balance --proofs\n\n# Debug specific issues\nnuts debug --history # Transaction history issues\nnuts debug --balance # Balance calculation issues\nnuts debug --proofs # Proof validation issues\n```\n\n## Related Projects\n\n- [Cashu Protocol](https://cashu.space) - Chaumian ecash protocol specification\n- [NIP-60](https://github.com/nostr-protocol/nips/blob/master/60.md) - Cashu Wallet specification\n- [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md) - Encryption specification\n- [Nostr Protocol](https://nostr.com) - Decentralized communication protocol\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/your-org/sixty-nuts/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/your-org/sixty-nuts/discussions)\n- **Nostr**: Follow development updates via Nostr\n\n---\n\n**\u26a1 Start using Cashu with Nostr today!**\n\n```bash\npip install sixty-nuts\nnuts status --init\nnuts mint 1000\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Sixty Nuts - NIP-60 Cashu Wallet Implementation",
"version": "0.1.4",
"project_urls": {
"Repository": "https://github.com/shroominic/sixty-nuts"
},
"split_keywords": [
"bitcoin",
" cashu",
" ecash",
" lightning",
" nip-60",
" nostr",
" wallet"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "add666da093747f36728ebd5b7f1917241d3337cbd888c614454e61e134dcbbe",
"md5": "bcf63da9b669f859b2423ea2101fe873",
"sha256": "94ffd7fd28967413e141d7deb5b132d7e4ea6e952e35b9f3ce77d95812481145"
},
"downloads": -1,
"filename": "sixty_nuts-0.1.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "bcf63da9b669f859b2423ea2101fe873",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 98617,
"upload_time": "2025-07-19T17:30:33",
"upload_time_iso_8601": "2025-07-19T17:30:33.253956Z",
"url": "https://files.pythonhosted.org/packages/ad/d6/66da093747f36728ebd5b7f1917241d3337cbd888c614454e61e134dcbbe/sixty_nuts-0.1.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4b24ecab6ba4cf78ee4e32ddc1e820fdd72234850d80ccb365227ee46b5ddfe1",
"md5": "5c52e50fb353d7e07c172fb271db0cc7",
"sha256": "6b934fecee6bc8c2017313cfd2bc80e94bb9baa4ea1d176657c80b34030a52b9"
},
"downloads": -1,
"filename": "sixty_nuts-0.1.4.tar.gz",
"has_sig": false,
"md5_digest": "5c52e50fb353d7e07c172fb271db0cc7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 167747,
"upload_time": "2025-07-19T17:30:34",
"upload_time_iso_8601": "2025-07-19T17:30:34.668532Z",
"url": "https://files.pythonhosted.org/packages/4b/24/ecab6ba4cf78ee4e32ddc1e820fdd72234850d80ccb365227ee46b5ddfe1/sixty_nuts-0.1.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-19 17:30:34",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "shroominic",
"github_project": "sixty-nuts",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "sixty-nuts"
}