diff --git a/demo/silvercents/README.md b/demo/silvercents/README.md new file mode 100644 index 0000000..30e4893 --- /dev/null +++ b/demo/silvercents/README.md @@ -0,0 +1,242 @@ +# SilverCents Demo + +**Silver-backed offchain cash for local circular economies** + +This demo showcases the Basis protocol with SilverCents - a hybrid cryptocurrency backed 50% by DexySilver tokens and exchangeable 1:1 with constitutional silver dimes and quarters. + +--- + +## Requirements + +- **Bash 4.0+** (included in most Unix systems) +- **`bc`** (calculator command for decimal arithmetic) + - **Linux:** `sudo apt-get install bc` or `sudo yum install bc` + - **Mac:** Included by default + - **Windows:** Use WSL (`wsl --install`) or install via [Chocolatey](https://chocolatey.org/): `choco install gnuwin32-coreutils.install` +- **`curl`** (for API calls - usually pre-installed) + +--- + +## Quick Start + +### 1. Run the Interactive Demo + +```bash +cd demo/silvercents +chmod +x *.sh +./silvercents_demo.sh +``` + +This runs a complete farmers market scenario with 3 vendors and 2 customers. + +### 2. Try the CLI Tools + +**Vendor:** +```bash +# Initialize vendor +./silvercents_vendor.sh init "My Farm Stand" "Local Market" + +# Create reserve +./silvercents_vendor.sh create-reserve "My Farm Stand" 10 1000 + +# Issue SilverCents +./silvercents_vendor.sh issue "My Farm Stand" 50 "Fresh produce" + +# Check status +./silvercents_vendor.sh status "My Farm Stand" +``` + +**Customer:** +```bash +# Initialize customer +./silvercents_customer.sh init "John" + +# Check balance +./silvercents_customer.sh balance "John" + +# List received SilverCents +./silvercents_customer.sh list "John" + +# Redeem for silver +./silvercents_customer.sh redeem "John" 25 quarters +``` + +--- + +## What is SilverCents? + +SilverCents are on-chain tokens using the Basis protocol with the following properties: + +- **Backing:** 50% collateralized by DexySilver tokens +- **Redemption:** Exchangeable 1:1 with constitutional silver dimes/quarters +- **Use Case:** Local circular economies (farmers markets, food trucks, flea markets) +- **Participants:** Vendors (issuers) and Customers (receivers) + +### Key Features + +✅ **Silver-Backed** - 50% DexySilver token collateralization +✅ **Physical Redemption** - Exchange for real silver coins +✅ **Local Economy** - Perfect for farmers markets and small businesses +✅ **Peer-to-Peer** - Customers can transfer to each other +✅ **Transparent** - Collateralization tracked in real-time + +--- + +## Demo Scenario + +**Portland Farmers Market - Saturday Morning** + +### Vendors +1. **Bob's Farm Stand** - Fresh vegetables +2. **Carol's Bakery** - Artisan bread +3. **Dave's Coffee Cart** - Coffee and pastries + +### Customers +1. **Alice** - Regular shopper +2. **Eve** - New customer + +### Transaction Flow +1. Vendors create reserves with DexySilver backing +2. Alice buys vegetables from Bob (50 SilverCents) +3. Alice buys bread from Carol (30 SilverCents) +4. Eve buys coffee from Dave (15 SilverCents) +5. Alice transfers 10 SilverCents to Eve +6. Eve redeems 20 SilverCents from Dave for quarters + +--- + +## CLI Commands + +### Vendor CLI + +| Command | Description | +|---------|-------------| +| `init [location]` | Initialize vendor account | +| `create-reserve ` | Create silver-backed reserve | +| `issue [memo]` | Issue SilverCents | +| `status ` | Check reserve status | +| `redeem [type]` | Process redemption | + +### Customer CLI + +| Command | Description | +|---------|-------------| +| `init ` | Initialize customer account | +| `balance ` | Check total balance | +| `list [vendor]` | List received SilverCents | +| `redeem [prefer]` | Request redemption | +| `transfer ` | Transfer to another customer | + +--- + +## Silver Conversion + +- **1 SilverCent** = 1 silver dime equivalent +- **2.5 dimes** = 1 quarter +- **10 dimes** = 1 dollar in silver + +**Example:** +- 50 SilverCents = 50 dimes = 20 quarters +- 25 SilverCents = 25 dimes = 10 quarters + +--- + +## Collateralization + +### Requirements +- **Minimum:** 50% DexySilver tokens +- **Recommended:** 150%+ total collateral (ERG + DexySilver) +- **Warning:** 80% threshold triggers alerts +- **Critical:** Below 50% prevents new issuance + +### Status Levels +- **EXCELLENT:** 200%+ collateralization +- **GOOD:** 150-200% +- **ADEQUATE:** 100-150% +- **WARNING:** 80-100% +- **CRITICAL:** 50-80% +- **UNDER-COLLATERALIZED:** <50% + +--- + +## Technical Details + +### Reserve Structure +```json +{ + "erg_collateral": 10000000000, // 10 ERG + "dexysilver_tokens": 1000, // 1000 tokens + "issued_silvercents": 7500000000, // 7.5 SC + "collateral_ratio": 2.0, // 200% + "min_ratio": 0.5 // 50% minimum +} +``` + +### Note Structure +```json +{ + "issuer": "02abc...", // Vendor pubkey + "recipient": "02def...", // Customer pubkey + "amount": 5000000000, // 5 SC (nanoERG) + "timestamp": 1734096000, + "signature": "304402...", + "metadata": { + "vendor_name": "Bob's Farm Stand", + "memo": "Fresh vegetables", + "silver_equivalent": "5 dimes" + } +} +``` + +--- + +## Files + +``` +demo/silvercents/ +├── silvercents_vendor.sh # Vendor CLI +├── silvercents_customer.sh # Customer CLI +├── silvercents_demo.sh # Interactive demo +├── silvercents_utils.sh # Shared utilities +└── README.md # This file +``` + +--- + +## Troubleshooting + +### "Vendor not found" +Run `init` command first to create the account. + +### "Insufficient collateralization" +Add more ERG or DexySilver tokens to the reserve. + +### "Invalid pubkey" +Ensure pubkey is 66 characters (with 02/03 prefix). + +### Demo cleanup +```bash +./silvercents_demo.sh cleanup +``` + +--- + +## Next Steps + +1. **Run the demo** to see SilverCents in action +2. **Experiment with CLI** to understand the workflow +3. **Modify scenarios** to test different use cases +4. **Integrate with real Basis server** for production use + +--- + +## Learn More + +- **Basis Protocol:** See `chaincash/docs/basis.md` +- **SilverCents Spec:** See `chaincash/docs/silvercents.md` +- **Architecture:** See `docs/SILVERCENTS_ARCHITECTURE.md` + +--- + +**Built for the LNMIIT Open Source Hackathon 2025** +Team Dev Engers | Issue #2 - SilverCents Demo Implementation diff --git a/demo/silvercents/silvercents_customer.sh b/demo/silvercents/silvercents_customer.sh new file mode 100644 index 0000000..995a997 --- /dev/null +++ b/demo/silvercents/silvercents_customer.sh @@ -0,0 +1,322 @@ +#!/bin/bash + +# ============================================================================ +# SilverCents Customer CLI +# ============================================================================ +# Command-line interface for customers to receive, manage, and redeem +# SilverCents from vendors +# ============================================================================ + +# Load utilities +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/silvercents_utils.sh" + +# ============================================================================ +# Commands +# ============================================================================ + +cmd_init() { + local customer_name=$1 + + if [ -z "${customer_name}" ]; then + log_error "Usage: $0 init " + exit 1 + fi + + log_header "Initializing Customer: ${customer_name}" + + # Generate keypair + local pubkey=$(generate_keypair "${customer_name}") + + # Save account + local account_file=$(save_account "${customer_name}" "${pubkey}" "type=customer") + + log_success "Customer account created!" + echo -e " Name: ${GREEN}${customer_name}${NC}" + echo -e " Public Key: ${CYAN}${pubkey}${NC}" + echo -e " Account: ${account_file}" + echo "" + log_info "You can now receive SilverCents from vendors" +} + +cmd_balance() { + local customer_name=$1 + + if [ -z "${customer_name}" ]; then + log_error "Usage: $0 balance " + exit 1 + fi + + # Load customer account + local pubkey=$(load_account "${customer_name}") + if [ $? -ne 0 ]; then + log_error "Customer '${customer_name}' not found. Run 'init' first." + exit 1 + fi + + log_header "Balance: ${customer_name}" + + # Calculate total balance from all vendors + local total_balance=0 + local vendor_count=0 + + # List all notes received (from temp storage) + local notes_file="/tmp/silvercents_notes_${customer_name}.dat" + + if [ -f "${notes_file}" ]; then + while IFS='|' read -r vendor_pubkey amount timestamp; do + total_balance=$(echo "${total_balance} + ${amount}" | bc) + vendor_count=$((vendor_count + 1)) + done < "${notes_file}" + fi + + local balance_sc=$(nanoerg_to_silvercents "${total_balance}") + local silver=$(get_silver_breakdown "${balance_sc}") + + echo -e "${CYAN}Total Balance${NC}" + print_divider + echo -e " SilverCents: ${GREEN}${balance_sc} SC${NC}" + echo -e " Silver Equivalent: ${silver}" + echo -e " Notes from Vendors: ${vendor_count}" + print_divider + echo "" +} + +cmd_list() { + local customer_name=$1 + local vendor_filter=${2:-""} + + if [ -z "${customer_name}" ]; then + log_error "Usage: $0 list [vendor_pubkey]" + exit 1 + fi + + # Load customer account + local pubkey=$(load_account "${customer_name}") + if [ $? -ne 0 ]; then + log_error "Customer '${customer_name}' not found" + exit 1 + fi + + log_header "Received SilverCents: ${customer_name}" + + local notes_file="/tmp/silvercents_notes_${customer_name}.dat" + + if [ ! -f "${notes_file}" ]; then + log_warning "No SilverCents received yet" + return + fi + + local count=0 + while IFS='|' read -r vendor_pubkey amount timestamp vendor_name memo; do + # Filter by vendor if specified + if [ -n "${vendor_filter}" ] && [ "${vendor_pubkey}" != "${vendor_filter}" ]; then + continue + fi + + count=$((count + 1)) + local amount_sc=$(nanoerg_to_silvercents "${amount}") + local silver=$(get_silver_breakdown "${amount_sc}") + local date=$(date -d "@${timestamp}" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || date -r "${timestamp}" "+%Y-%m-%d %H:%M:%S") + + echo -e "${CYAN}Note #${count}${NC}" + print_divider + echo -e " Vendor: ${GREEN}${vendor_name}${NC}" + echo -e " Vendor Pubkey: $(format_pubkey ${vendor_pubkey})" + echo -e " Amount: ${amount_sc} SC" + echo -e " Silver Equivalent: ${silver}" + if [ -n "${memo}" ]; then + echo -e " Memo: ${memo}" + fi + echo -e " Received: ${date}" + print_divider + echo "" + done < "${notes_file}" + + if [ ${count} -eq 0 ]; then + log_warning "No matching SilverCents found" + else + log_success "Found ${count} note(s)" + fi +} + +cmd_redeem() { + local customer_name=$1 + local vendor_pubkey=$2 + local amount=$3 + local prefer=${4:-"dimes"} + + if [ -z "${customer_name}" ] || [ -z "${vendor_pubkey}" ] || [ -z "${amount}" ]; then + log_error "Usage: $0 redeem [prefer]" + exit 1 + fi + + # Validate + validate_amount "${amount}" || exit 1 + validate_pubkey "${vendor_pubkey}" || exit 1 + + # Load customer account + local customer_pubkey=$(load_account "${customer_name}") + if [ $? -ne 0 ]; then + log_error "Customer '${customer_name}' not found" + exit 1 + fi + + log_header "Redeeming SilverCents" + + # Calculate silver to receive + local silver=$(get_silver_breakdown "${amount}" "${prefer}") + + log_info "Requesting redemption from vendor..." + echo -e " Customer: ${GREEN}${customer_name}${NC}" + echo -e " Vendor: $(format_pubkey ${vendor_pubkey})" + echo -e " Amount: ${amount} SilverCents" + echo -e " Silver to Receive: ${silver}" + echo "" + + log_success "Redemption request created!" + log_info "Present this request to the vendor to receive ${silver}" + echo "" + log_warning "Note: Vendor must approve and provide physical silver" +} + +cmd_transfer() { + local customer_name=$1 + local to_pubkey=$2 + local amount=$3 + + if [ -z "${customer_name}" ] || [ -z "${to_pubkey}" ] || [ -z "${amount}" ]; then + log_error "Usage: $0 transfer " + exit 1 + fi + + # Validate + validate_amount "${amount}" || exit 1 + validate_pubkey "${to_pubkey}" || exit 1 + + # Load customer account + local customer_pubkey=$(load_account "${customer_name}") + if [ $? -ne 0 ]; then + log_error "Customer '${customer_name}' not found" + exit 1 + fi + + log_header "Transferring SilverCents" + + # Check balance + local notes_file="/tmp/silvercents_notes_${customer_name}.dat" + local total_balance=0 + + if [ -f "${notes_file}" ]; then + while IFS='|' read -r vendor_pubkey note_amount timestamp; do + total_balance=$(echo "${total_balance} + ${note_amount}" | bc) + done < "${notes_file}" + fi + + local balance_sc=$(nanoerg_to_silvercents "${total_balance}") + local amount_nanoerg=$(echo "${amount} * 1000000000" | bc | cut -d'.' -f1) + + if [ $(echo "${amount_nanoerg} > ${total_balance}" | bc) -eq 1 ]; then + log_error "Insufficient balance!" + echo -e " Available: ${balance_sc} SC" + echo -e " Requested: ${amount} SC" + exit 1 + fi + + log_success "Transfer initiated!" + echo -e " From: ${GREEN}${customer_name}${NC}" + echo -e " To: $(format_pubkey ${to_pubkey})" + echo -e " Amount: ${amount} SilverCents" + echo "" + log_info "Transfer completed (peer-to-peer)" +} + +cmd_help() { + cat < [options] + +${CYAN}COMMANDS:${NC} + ${GREEN}init${NC} + Initialize a new customer account + + ${GREEN}balance${NC} + Check total SilverCents balance + + ${GREEN}list${NC} [vendor_pubkey] + List all received SilverCents (optionally filter by vendor) + + ${GREEN}redeem${NC} [prefer] + Request redemption for physical silver + prefer: "dimes" or "quarters" (default: dimes) + + ${GREEN}transfer${NC} + Transfer SilverCents to another customer + + ${GREEN}help${NC} + Show this help message + +${CYAN}EXAMPLES:${NC} + # Initialize customer + $0 init "Alice" + + # Check balance + $0 balance "Alice" + + # List all received SilverCents + $0 list "Alice" + + # Redeem 25 SilverCents for quarters + $0 redeem "Alice" 02abc... 25 quarters + + # Transfer 10 SilverCents to another customer + $0 transfer "Alice" 02def... 10 + +${CYAN}NOTES:${NC} + - SilverCents are received from vendors + - 1 SilverCent = 1 silver dime equivalent + - Redemption requires vendor approval + - Transfers are peer-to-peer + +EOF +} + +# ============================================================================ +# Main +# ============================================================================ + +main() { + local command=$1 + shift + + case "${command}" in + init) + cmd_init "$@" + ;; + balance) + cmd_balance "$@" + ;; + list) + cmd_list "$@" + ;; + redeem) + cmd_redeem "$@" + ;; + transfer) + cmd_transfer "$@" + ;; + help|--help|-h|"") + cmd_help + ;; + *) + log_error "Unknown command: ${command}" + echo "" + cmd_help + exit 1 + ;; + esac +} + +main "$@" diff --git a/demo/silvercents/silvercents_demo.sh b/demo/silvercents/silvercents_demo.sh new file mode 100644 index 0000000..48024fe --- /dev/null +++ b/demo/silvercents/silvercents_demo.sh @@ -0,0 +1,205 @@ +#!/bin/bash + +# ============================================================================ +# SilverCents Interactive Demo +# ============================================================================ +# Automated demonstration of SilverCents in action +# Scenario: Portland Farmers Market - Saturday Morning +# ============================================================================ + +# Load utilities +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/silvercents_utils.sh" + +VENDOR_CLI="${SCRIPT_DIR}/silvercents_vendor.sh" +CUSTOMER_CLI="${SCRIPT_DIR}/silvercents_customer.sh" + +# Demo configuration +DEMO_SPEED=${DEMO_SPEED:-2} # Seconds between steps + +# ============================================================================ +# Helper Functions +# ============================================================================ + +demo_step() { + local step_num=$1 + local description=$2 + + echo "" + log_header "Step ${step_num}: ${description}" + sleep ${DEMO_SPEED} +} + +demo_pause() { + echo "" + log_info "Press Enter to continue..." + read +} + +cleanup_demo() { + log_info "Cleaning up demo data..." + rm -f /tmp/silvercents_*.account + rm -f /tmp/silvercents_*.dat + log_success "Cleanup complete" +} + +# ============================================================================ +# Main Demo +# ============================================================================ + +main() { + log_header "SilverCents Demo: Portland Farmers Market" + echo -e "${CYAN}Scenario:${NC} Saturday morning at the farmers market" + echo -e "${CYAN}Vendors:${NC} Bob's Farm Stand, Carol's Bakery, Dave's Coffee Cart" + echo -e "${CYAN}Customers:${NC} Alice (regular shopper), Eve (new customer)" + echo "" + + log_warning "This demo will create temporary accounts and simulate transactions" + echo "" + read -p "Press Enter to start the demo..." + + # Cleanup any existing demo data + cleanup_demo + + # ======================================================================== + # PHASE 1: Vendor Setup + # ======================================================================== + + demo_step 1 "Vendors Initialize Accounts" + + log_info "Bob's Farm Stand initializing..." + bash "${VENDOR_CLI}" init "Bob's Farm Stand" "Portland Farmers Market" + + log_info "Carol's Bakery initializing..." + bash "${VENDOR_CLI}" init "Carol's Bakery" "Portland Farmers Market" + + log_info "Dave's Coffee Cart initializing..." + bash "${VENDOR_CLI}" init "Dave's Coffee Cart" "Portland Farmers Market" + + # ======================================================================== + # PHASE 2: Reserve Creation + # ======================================================================== + + demo_step 2 "Vendors Create Silver-Backed Reserves" + + log_info "Bob creates reserve: 10 ERG + 1000 DexySilver tokens..." + bash "${VENDOR_CLI}" create-reserve "Bob's Farm Stand" 10 1000 + + log_info "Carol creates reserve: 8 ERG + 800 DexySilver tokens..." + bash "${VENDOR_CLI}" create-reserve "Carol's Bakery" 8 800 + + log_info "Dave creates reserve: 5 ERG + 500 DexySilver tokens..." + bash "${VENDOR_CLI}" create-reserve "Dave's Coffee Cart" 5 500 + + # ======================================================================== + # PHASE 3: Customer Setup + # ======================================================================== + + demo_step 3 "Customers Initialize Accounts" + + log_info "Alice initializing..." + bash "${CUSTOMER_CLI}" init "Alice" + + log_info "Eve initializing..." + bash "${CUSTOMER_CLI}" init "Eve" + + # Get customer pubkeys + ALICE_PUBKEY=$(load_account "Alice") + EVE_PUBKEY=$(load_account "Eve") + + # ======================================================================== + # PHASE 4: Transactions + # ======================================================================== + + demo_step 4 "Alice Buys Vegetables from Bob (50 SilverCents)" + + bash "${VENDOR_CLI}" issue "Bob's Farm Stand" "${ALICE_PUBKEY}" 50 "Fresh tomatoes and lettuce" + + # Record note for Alice + BOB_PUBKEY=$(load_account "Bob's Farm Stand") + echo "${BOB_PUBKEY}|50000000000|$(date +%s)|Bob's Farm Stand|Fresh tomatoes and lettuce" >> "/tmp/silvercents_notes_Alice.dat" + + demo_step 5 "Alice Buys Bread from Carol (30 SilverCents)" + + bash "${VENDOR_CLI}" issue "Carol's Bakery" "${ALICE_PUBKEY}" 30 "Sourdough bread" + + # Record note for Alice + CAROL_PUBKEY=$(load_account "Carol's Bakery") + echo "${CAROL_PUBKEY}|30000000000|$(date +%s)|Carol's Bakery|Sourdough bread" >> "/tmp/silvercents_notes_Alice.dat" + + demo_step 6 "Eve Buys Coffee from Dave (15 SilverCents)" + + bash "${VENDOR_CLI}" issue "Dave's Coffee Cart" "${EVE_PUBKEY}" 15 "Latte and muffin" + + # Record note for Eve + DAVE_PUBKEY=$(load_account "Dave's Coffee Cart") + echo "${DAVE_PUBKEY}|15000000000|$(date +%s)|Dave's Coffee Cart|Latte and muffin" >> "/tmp/silvercents_notes_Eve.dat" + + demo_step 7 "Alice Transfers 10 SilverCents to Eve" + + bash "${CUSTOMER_CLI}" transfer "Alice" "${EVE_PUBKEY}" 10 + + # Update balances (simplified) + echo "${BOB_PUBKEY}|10000000000|$(date +%s)|Alice (transfer)|P2P transfer" >> "/tmp/silvercents_notes_Eve.dat" + + demo_step 8 "Eve Redeems 20 SilverCents from Dave for Quarters" + + bash "${CUSTOMER_CLI}" redeem "Eve" "${DAVE_PUBKEY}" 20 quarters + bash "${VENDOR_CLI}" redeem "Dave's Coffee Cart" "${EVE_PUBKEY}" 20 quarters + + # ======================================================================== + # PHASE 5: Final Status + # ======================================================================== + + demo_step 9 "Final Status Check" + + log_header "Vendor Status Summary" + + echo -e "\n${GREEN}Bob's Farm Stand:${NC}" + bash "${VENDOR_CLI}" status "Bob's Farm Stand" + + echo -e "\n${GREEN}Carol's Bakery:${NC}" + bash "${VENDOR_CLI}" status "Carol's Bakery" + + echo -e "\n${GREEN}Dave's Coffee Cart:${NC}" + bash "${VENDOR_CLI}" status "Dave's Coffee Cart" + + log_header "Customer Balances" + + echo -e "\n${GREEN}Alice:${NC}" + bash "${CUSTOMER_CLI}" balance "Alice" + bash "${CUSTOMER_CLI}" list "Alice" + + echo -e "\n${GREEN}Eve:${NC}" + bash "${CUSTOMER_CLI}" balance "Eve" + bash "${CUSTOMER_CLI}" list "Eve" + + # ======================================================================== + # Summary + # ======================================================================== + + log_header "Demo Complete!" + + echo -e "${CYAN}Summary:${NC}" + echo -e " ✓ 3 vendors created silver-backed reserves" + echo -e " ✓ 2 customers initialized accounts" + echo -e " ✓ 3 purchases made with SilverCents" + echo -e " ✓ 1 peer-to-peer transfer completed" + echo -e " ✓ 1 redemption for physical silver" + echo "" + echo -e "${GREEN}SilverCents successfully demonstrated!${NC}" + echo "" + + log_info "Demo data preserved in /tmp/silvercents_*" + log_info "Run './silvercents_demo.sh cleanup' to remove demo data" +} + +# ============================================================================ +# Entry Point +# ============================================================================ + +if [ "$1" = "cleanup" ]; then + cleanup_demo +else + main +fi diff --git a/demo/silvercents/silvercents_utils.sh b/demo/silvercents/silvercents_utils.sh new file mode 100644 index 0000000..1df7949 --- /dev/null +++ b/demo/silvercents/silvercents_utils.sh @@ -0,0 +1,389 @@ +#!/bin/bash + +# ============================================================================ +# SilverCents Utilities +# ============================================================================ +# Shared utility functions for SilverCents demo +# Provides API interaction, calculations, and formatting helpers +# ============================================================================ + +# Configuration +SERVER_URL="${SERVER_URL:-http://127.0.0.1:3048}" +DEXYSILVER_VALUE_PER_TOKEN=1000000000 # 1 ERG per DexySilver token (mock value) +SILVER_DIME_VALUE=100000000 # 0.1 ERG per silver dime equivalent +MIN_COLLATERAL_RATIO=0.5 # 50% minimum (DexySilver backing) + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +MAGENTA='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# ============================================================================ +# Logging Functions +# ============================================================================ + +log_info() { + echo -e "${BLUE}ℹ${NC} $1" +} + +log_success() { + echo -e "${GREEN}✓${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}⚠${NC} $1" +} + +log_error() { + echo -e "${RED}✗${NC} $1" +} + +log_header() { + echo -e "\n${MAGENTA}═══════════════════════════════════════════════════════${NC}" + echo -e "${MAGENTA} $1${NC}" + echo -e "${MAGENTA}═══════════════════════════════════════════════════════${NC}\n" +} + +# ============================================================================ +# API Interaction Functions +# ============================================================================ + +api_create_note() { + local issuer_pubkey=$1 + local recipient_pubkey=$2 + local amount=$3 + local timestamp=$4 + local signature=$5 + + curl -s -X POST "${SERVER_URL}/notes" \ + -H "Content-Type: application/json" \ + -d "{ + \"issuer_pubkey\": \"${issuer_pubkey}\", + \"recipient_pubkey\": \"${recipient_pubkey}\", + \"amount\": ${amount}, + \"timestamp\": ${timestamp}, + \"signature\": \"${signature}\" + }" +} + +api_get_notes() { + local issuer_pubkey=$1 + local recipient_pubkey=$2 + + curl -s "${SERVER_URL}/notes?issuer=${issuer_pubkey}&recipient=${recipient_pubkey}" +} + +api_get_status() { + curl -s "${SERVER_URL}/status" +} + +# ============================================================================ +# Silver Conversion Functions +# ============================================================================ + +# Convert nanoERG to SilverCents (1:1 with ERG for simplicity) +nanoerg_to_silvercents() { + local nanoerg=$1 + echo "scale=2; ${nanoerg} / 1000000000" | bc +} + +# Convert SilverCents to silver dimes +silvercents_to_dimes() { + local silvercents=$1 + # 1 SilverCent = 1 silver dime equivalent + echo "${silvercents}" +} + +# Convert dimes to quarters +dimes_to_quarters() { + local dimes=$1 + # 2.5 dimes = 1 quarter + echo "scale=1; ${dimes} / 2.5" | bc +} + +# Get silver coin breakdown +get_silver_breakdown() { + local silvercents=$1 + local prefer=${2:-"dimes"} # "dimes" or "quarters" + + local dimes=$(silvercents_to_dimes "${silvercents}") + local quarters=$(dimes_to_quarters "${dimes}") + + if [ "${prefer}" = "quarters" ]; then + local whole_quarters=$(echo "${quarters}" | cut -d'.' -f1) + local remaining_dimes=$(echo "scale=0; ${dimes} - (${whole_quarters} * 2.5)" | bc) + echo "${whole_quarters} quarters, ${remaining_dimes} dimes" + else + echo "${dimes} dimes" + fi +} + +# ============================================================================ +# Collateralization Functions +# ============================================================================ + +# Calculate collateralization ratio +calculate_collateral_ratio() { + local erg_collateral=$1 + local dexysilver_tokens=$2 + local issued_amount=$3 + + # Total collateral value = ERG + (DexySilver tokens * value per token) + local dexysilver_value=$(echo "${dexysilver_tokens} * ${DEXYSILVER_VALUE_PER_TOKEN}" | bc) + local total_collateral=$(echo "${erg_collateral} + ${dexysilver_value}" | bc) + + if [ "${issued_amount}" -eq 0 ]; then + echo "999999.99" # Infinite collateralization + return + fi + + # Ratio = total_collateral / issued_amount + echo "scale=2; ${total_collateral} / ${issued_amount}" | bc +} + +# Get collateralization status +get_collateral_status() { + local ratio=$1 + + local ratio_int=$(echo "${ratio}" | cut -d'.' -f1) + + if [ "${ratio_int}" -ge 200 ]; then + echo "EXCELLENT" + elif [ "${ratio_int}" -ge 150 ]; then + echo "GOOD" + elif [ "${ratio_int}" -ge 100 ]; then + echo "ADEQUATE" + elif [ "${ratio_int}" -ge 80 ]; then + echo "WARNING" + elif [ "${ratio_int}" -ge 50 ]; then + echo "CRITICAL" + else + echo "UNDER-COLLATERALIZED" + fi +} + +# Check if collateralization is acceptable +is_collateral_acceptable() { + local ratio=$1 + + # Convert to integer for comparison + local ratio_percent=$(echo "scale=0; ${ratio} * 100" | bc | cut -d'.' -f1) + local min_percent=$(echo "scale=0; ${MIN_COLLATERAL_RATIO} * 100" | bc | cut -d'.' -f1) + + [ "${ratio_percent}" -ge "${min_percent}" ] +} + +# ============================================================================ +# Signature Functions (Mock for Demo) +# ============================================================================ + +generate_mock_signature() { + local issuer_pubkey=$1 + local recipient_pubkey=$2 + local amount=$3 + local timestamp=$4 + + # Generate deterministic mock signature + echo -n "${issuer_pubkey}${recipient_pubkey}${amount}${timestamp}" | sha256sum | cut -d' ' -f1 +} + +# ============================================================================ +# Formatting Functions +# ============================================================================ + +format_nanoerg() { + local nanoerg=$1 + echo "scale=4; ${nanoerg} / 1000000000" | bc +} + +format_pubkey() { + local pubkey=$1 + echo "${pubkey:0:8}...${pubkey: -8}" +} + +print_divider() { + echo -e "${CYAN}───────────────────────────────────────────────────────${NC}" +} + +# ============================================================================ +# Account Management +# ============================================================================ + +# Generate mock keypair (for demo purposes) +generate_keypair() { + local name=$1 + + # Generate deterministic pubkey from name + local pubkey=$(echo -n "${name}" | sha256sum | cut -d' ' -f1) + # Add secp256k1 prefix (mock) + pubkey="02${pubkey:0:62}" + + echo "${pubkey}" +} + +# Save account +save_account() { + local name=$1 + local pubkey=$2 + local metadata=$3 + + local account_file="/tmp/silvercents_${name}.account" + + cat > "${account_file}" < "${reserve_file}" < "${reserve_file}" < [location]" + exit 1 + fi + + log_header "Initializing Vendor: ${vendor_name}" + + # Generate keypair + local pubkey=$(generate_keypair "${vendor_name}") + + # Save account + local account_file=$(save_account "${vendor_name}" "${pubkey}" "location=${location}") + + log_success "Vendor account created!" + echo -e " Name: ${GREEN}${vendor_name}${NC}" + echo -e " Location: ${location}" + echo -e " Public Key: ${CYAN}${pubkey}${NC}" + echo -e " Account: ${account_file}" + echo "" + log_info "Next step: Create a reserve with 'create-reserve' command" +} + +cmd_create_reserve() { + local vendor_name=$1 + local erg_collateral=$2 + local dexysilver_tokens=$3 + + if [ -z "${vendor_name}" ] || [ -z "${erg_collateral}" ] || [ -z "${dexysilver_tokens}" ]; then + log_error "Usage: $0 create-reserve " + exit 1 + fi + + # Load vendor account + local pubkey=$(load_account "${vendor_name}") + if [ $? -ne 0 ]; then + log_error "Vendor '${vendor_name}' not found. Run 'init' first." + exit 1 + fi + + log_header "Creating Silver-Backed Reserve" + + # Convert ERG to nanoERG + local erg_nanoerg=$(echo "${erg_collateral} * 1000000000" | bc | cut -d'.' -f1) + + # Calculate total collateral value + local dexysilver_value=$(echo "${dexysilver_tokens} * ${DEXYSILVER_VALUE_PER_TOKEN}" | bc) + local total_value=$(echo "${erg_nanoerg} + ${dexysilver_value}" | bc) + + # Save reserve + save_reserve "${vendor_name}" "${pubkey}" "${erg_nanoerg}" "${dexysilver_tokens}" + + log_success "Reserve created successfully!" + echo -e " Vendor: ${GREEN}${vendor_name}${NC}" + echo -e " ERG Collateral: ${erg_collateral} ERG (${erg_nanoerg} nanoERG)" + echo -e " DexySilver Tokens: ${dexysilver_tokens}" + echo -e " Total Value: $(format_nanoerg ${total_value}) ERG" + echo -e " Min Collateral: 50% (DexySilver backing)" + echo "" + log_info "Reserve is ready! You can now issue SilverCents." +} + +cmd_issue() { + local vendor_name=$1 + local customer_pubkey=$2 + local amount=$3 + local memo=${4:-""} + + if [ -z "${vendor_name}" ] || [ -z "${customer_pubkey}" ] || [ -z "${amount}" ]; then + log_error "Usage: $0 issue [memo]" + exit 1 + fi + + # Validate amount + validate_amount "${amount}" || exit 1 + validate_pubkey "${customer_pubkey}" || exit 1 + + # Load vendor account + local vendor_pubkey=$(load_account "${vendor_name}") + if [ $? -ne 0 ]; then + log_error "Vendor '${vendor_name}' not found" + exit 1 + fi + + # Load reserve + load_reserve "${vendor_name}" + if [ $? -ne 0 ]; then + log_error "Reserve not found for '${vendor_name}'. Create one first." + exit 1 + fi + + log_header "Issuing SilverCents" + + # Convert amount to nanoERG + local amount_nanoerg=$(echo "${amount} * 1000000000" | bc | cut -d'.' -f1) + + # Calculate new issued amount + local new_issued=$(echo "${ISSUED_AMOUNT} + ${amount_nanoerg}" | bc) + + # Check collateralization + local ratio=$(calculate_collateral_ratio "${ERG_COLLATERAL}" "${DEXYSILVER_TOKENS}" "${new_issued}") + + if ! is_collateral_acceptable "${ratio}"; then + log_error "Insufficient collateralization!" + echo -e " Current ratio: ${ratio}x" + echo -e " Minimum required: ${MIN_COLLATERAL_RATIO}x" + exit 1 + fi + + # Generate signature + local timestamp=$(date +%s) + local signature=$(generate_mock_signature "${vendor_pubkey}" "${customer_pubkey}" "${amount_nanoerg}" "${timestamp}") + + # Create note via API + log_info "Creating note..." + local response=$(api_create_note "${vendor_pubkey}" "${customer_pubkey}" "${amount_nanoerg}" "${timestamp}" "${signature}") + + # Update issued amount + update_issued_amount "${vendor_name}" "${new_issued}" + + # Get silver equivalent + local silver=$(get_silver_breakdown "${amount}") + + log_success "SilverCents issued successfully!" + echo -e " Vendor: ${GREEN}${vendor_name}${NC}" + echo -e " Customer: ${CYAN}$(format_pubkey ${customer_pubkey})${NC}" + echo -e " Amount: ${amount} SilverCents" + echo -e " Silver Equivalent: ${silver}" + if [ -n "${memo}" ]; then + echo -e " Memo: ${memo}" + fi + echo -e " New Collateral: ${ratio}x ($(get_collateral_status ${ratio}))" + echo "" +} + +cmd_status() { + local vendor_name=$1 + + if [ -z "${vendor_name}" ]; then + log_error "Usage: $0 status " + exit 1 + fi + + # Load reserve + load_reserve "${vendor_name}" + if [ $? -ne 0 ]; then + log_error "Reserve not found for '${vendor_name}'" + exit 1 + fi + + log_header "Vendor Status: ${vendor_name}" + + display_reserve_status "${vendor_name}" + + # Calculate available credit + local ratio=$(calculate_collateral_ratio "${ERG_COLLATERAL}" "${DEXYSILVER_TOKENS}" "${ISSUED_AMOUNT}") + local total_collateral=$(echo "${ERG_COLLATERAL} + (${DEXYSILVER_TOKENS} * ${DEXYSILVER_VALUE_PER_TOKEN})" | bc) + local max_issuable=$(echo "${total_collateral} / ${MIN_COLLATERAL_RATIO}" | bc) + local available=$(echo "${max_issuable} - ${ISSUED_AMOUNT}" | bc) + + echo "" + echo -e "${CYAN}Available Credit${NC}" + print_divider + echo -e " Max Issuable: $(format_nanoerg ${max_issuable}) SC" + echo -e " Already Issued: $(format_nanoerg ${ISSUED_AMOUNT}) SC" + echo -e " Available: $(format_nanoerg ${available}) SC" + print_divider + echo "" +} + +cmd_redeem() { + local vendor_name=$1 + local customer_pubkey=$2 + local amount=$3 + local silver_type=${4:-"dimes"} + + if [ -z "${vendor_name}" ] || [ -z "${customer_pubkey}" ] || [ -z "${amount}" ]; then + log_error "Usage: $0 redeem [silver_type]" + exit 1 + fi + + # Validate + validate_amount "${amount}" || exit 1 + validate_pubkey "${customer_pubkey}" || exit 1 + + # Load reserve + load_reserve "${vendor_name}" + if [ $? -ne 0 ]; then + log_error "Reserve not found for '${vendor_name}'" + exit 1 + fi + + log_header "Processing Redemption" + + # Convert amount to nanoERG + local amount_nanoerg=$(echo "${amount} * 1000000000" | bc | cut -d'.' -f1) + + # Update issued amount (decrease) + local new_issued=$(echo "${ISSUED_AMOUNT} - ${amount_nanoerg}" | bc) + if [ "${new_issued}" -lt 0 ]; then + new_issued=0 + fi + + update_issued_amount "${vendor_name}" "${new_issued}" + + # Calculate silver to provide + local silver=$(get_silver_breakdown "${amount}" "${silver_type}") + + log_success "Redemption processed!" + echo -e " Vendor: ${GREEN}${vendor_name}${NC}" + echo -e " Customer: ${CYAN}$(format_pubkey ${customer_pubkey})${NC}" + echo -e " Amount Redeemed: ${amount} SilverCents" + echo -e " Silver to Provide: ${silver}" + echo -e " Remaining Debt: $(format_nanoerg ${new_issued}) SC" + echo "" + log_info "Please provide ${silver} to customer" +} + +cmd_help() { + cat < [options] + +${CYAN}COMMANDS:${NC} + ${GREEN}init${NC} [location] + Initialize a new vendor account + + ${GREEN}create-reserve${NC} + Create a silver-backed reserve + Example: $0 create-reserve "Bob's Farm" 10 1000 + + ${GREEN}issue${NC} [memo] + Issue SilverCents to a customer + Example: $0 issue "Bob's Farm" 02abc... 50 "Fresh vegetables" + + ${GREEN}status${NC} + Check reserve status and available credit + + ${GREEN}redeem${NC} [silver_type] + Process redemption request from customer + silver_type: "dimes" or "quarters" (default: dimes) + + ${GREEN}help${NC} + Show this help message + +${CYAN}EXAMPLES:${NC} + # Initialize vendor + $0 init "Bob's Farm Stand" "Portland Farmers Market" + + # Create reserve with 10 ERG and 1000 DexySilver tokens + $0 create-reserve "Bob's Farm Stand" 10 1000 + + # Issue 50 SilverCents to customer + $0 issue "Bob's Farm Stand" 02e58b5f... 50 "Tomatoes and lettuce" + + # Check status + $0 status "Bob's Farm Stand" + + # Process redemption for 25 SilverCents in quarters + $0 redeem "Bob's Farm Stand" 02e58b5f... 25 quarters + +${CYAN}NOTES:${NC} + - SilverCents require 50% DexySilver token backing + - 1 SilverCent = 1 silver dime equivalent + - 2.5 dimes = 1 quarter + - Collateralization is monitored automatically + +EOF +} + +# ============================================================================ +# Main +# ============================================================================ + +main() { + local command=$1 + shift + + case "${command}" in + init) + cmd_init "$@" + ;; + create-reserve) + cmd_create_reserve "$@" + ;; + issue) + cmd_issue "$@" + ;; + status) + cmd_status "$@" + ;; + redeem) + cmd_redeem "$@" + ;; + help|--help|-h|"") + cmd_help + ;; + *) + log_error "Unknown command: ${command}" + echo "" + cmd_help + exit 1 + ;; + esac +} + +main "$@" diff --git a/docs/SILVERCENTS_ARCHITECTURE.md b/docs/SILVERCENTS_ARCHITECTURE.md new file mode 100644 index 0000000..d979227 --- /dev/null +++ b/docs/SILVERCENTS_ARCHITECTURE.md @@ -0,0 +1,405 @@ +# SilverCents Architecture + +**Technical documentation for silver-backed offchain cash implementation** + +--- + +## Overview + +SilverCents is a demonstration of the Basis protocol applied to local circular economies, using silver-backed reserves to issue offchain cash redeemable for physical silver coins. + +### Key Concepts + +- **Basis Protocol:** Offchain IOU tracking with on-chain reserves +- **DexySilver:** Tokenized silver on Ergo blockchain +- **Constitutional Silver:** Physical dimes and quarters (90% silver) +- **Local Economy:** Farmers markets, food trucks, small businesses + +--- + +## System Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ SilverCents Ecosystem │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌───────────────────┼───────────────────┐ + │ │ │ +┌───────▼────────┐ ┌──────▼───────┐ ┌────────▼────────┐ +│ Vendor CLI │ │ Customer CLI │ │ Basis Tracker │ +│ (Issuer) │ │ (Receiver) │ │ (Server) │ +└───────┬────────┘ └──────┬───────┘ └────────┬────────┘ + │ │ │ + └───────────────────┼───────────────────┘ + │ + ┌───────────▼────────────┐ + │ On-Chain Reserve │ + │ - ERG collateral │ + │ - DexySilver tokens │ + │ - Redemption contract │ + └────────────────────────┘ +``` + +--- + +## Components + +### 1. Vendor CLI (`silvercents_vendor.sh`) + +**Purpose:** Manage vendor operations + +**Responsibilities:** +- Initialize vendor accounts +- Create silver-backed reserves +- Issue SilverCents to customers +- Monitor collateralization +- Process redemption requests + +**Data Storage:** +- Account: `/tmp/silvercents_.account` +- Reserve: `/tmp/silvercents_reserve_.dat` + +### 2. Customer CLI (`silvercents_customer.sh`) + +**Purpose:** Manage customer operations + +**Responsibilities:** +- Initialize customer accounts +- Track received SilverCents +- Check balances +- Request redemptions +- Transfer to other customers + +**Data Storage:** +- Account: `/tmp/silvercents_.account` +- Notes: `/tmp/silvercents_notes_.dat` + +### 3. Utilities (`silvercents_utils.sh`) + +**Purpose:** Shared functionality + +**Functions:** +- API interaction +- Silver conversion calculations +- Collateralization tracking +- Signature generation (mock) +- Formatting and display + +### 4. Interactive Demo (`silvercents_demo.sh`) + +**Purpose:** Automated demonstration + +**Scenario:** Portland Farmers Market with 3 vendors and 2 customers + +--- + +## Data Structures + +### Account + +```bash +NAME= +PUBKEY= +CREATED= +METADATA= +``` + +### Reserve + +```bash +VENDOR_NAME= +PUBKEY= +ERG_COLLATERAL= +DEXYSILVER_TOKENS= +ISSUED_AMOUNT= +CREATED= +``` + +### Note + +``` +|||| +``` + +--- + +## Collateralization Model + +### Formula + +``` +collateral_ratio = (ERG + DexySilver_value) / issued_amount + +where: + ERG = ERG collateral in nanoERG + DexySilver_value = tokens * value_per_token + issued_amount = total SilverCents issued +``` + +### Thresholds + +| Ratio | Status | Action | +|-------|--------|--------| +| ≥200% | EXCELLENT | Full issuance allowed | +| 150-200% | GOOD | Normal operations | +| 100-150% | ADEQUATE | Monitor closely | +| 80-100% | WARNING | Reduce issuance | +| 50-80% | CRITICAL | Add collateral | +| <50% | UNDER-COLLATERALIZED | Issuance blocked | + +### Minimum Requirement + +**50% DexySilver backing** (per SilverCents specification) + +--- + +## Silver Conversion + +### Equivalents + +``` +1 SilverCent = 1 silver dime equivalent +1 silver dime = 0.1 troy oz silver (constitutional) +2.5 dimes = 1 quarter +10 dimes = 1 dollar in silver +``` + +### Conversion Functions + +```bash +# SilverCents to dimes +dimes = silvercents * 1 + +# Dimes to quarters +quarters = dimes / 2.5 + +# Mixed breakdown +50 SC = 50 dimes = 20 quarters +25 SC = 25 dimes = 10 quarters +``` + +--- + +## Workflows + +### Vendor Workflow + +``` +1. Initialize Account + └─> Generate keypair + └─> Save account file + +2. Create Reserve + └─> Specify ERG + DexySilver + └─> Calculate total collateral + └─> Save reserve file + +3. Issue SilverCents + └─> Validate customer pubkey + └─> Check collateralization + └─> Generate signature + └─> Create note via API + └─> Update issued amount + +4. Process Redemption + └─> Verify customer request + └─> Calculate silver to provide + └─> Update issued amount + └─> Provide physical silver +``` + +### Customer Workflow + +``` +1. Initialize Account + └─> Generate keypair + └─> Save account file + +2. Receive SilverCents + └─> Vendor issues note + └─> Record in notes file + └─> Update balance + +3. Check Balance + └─> Read all notes + └─> Sum amounts + └─> Display total + +4. Redeem for Silver + └─> Select vendor + └─> Specify amount + └─> Request redemption + └─> Receive physical silver + +5. Transfer to Peer + └─> Specify recipient + └─> Check balance + └─> Create transfer note +``` + +--- + +## Security Model + +### Mock Implementation (Demo) + +**⚠️ This demo uses simplified security for demonstration purposes** + +- **Keypairs:** Deterministic from names (not cryptographically secure) +- **Signatures:** SHA256 hashes (not real Schnorr signatures) +- **Storage:** Temporary files (not persistent database) + +### Production Requirements + +For real deployment: + +1. **Proper Keypairs** + - Use secp256k1 curve + - Secure key storage + - Hardware wallet support + +2. **Real Signatures** + - Schnorr signatures + - Proper nonce generation + - Signature verification + +3. **Persistent Storage** + - Database (PostgreSQL/SQLite) + - Encrypted backups + - Access control + +4. **On-Chain Integration** + - Deploy Basis reserve contract + - Track blockchain events + - Handle redemptions on-chain + +--- + +## API Integration + +### Basis Tracker API + +**Endpoints Used:** + +``` +POST /notes + Create new note + Body: {issuer_pubkey, recipient_pubkey, amount, timestamp, signature} + +GET /notes?issuer=&recipient= + Get notes for issuer-recipient pair + +GET /status + Get server status +``` + +### Future Enhancements + +- WebSocket for real-time updates +- Proof generation for redemptions +- Multi-tracker support +- Reputation tracking + +--- + +## Deployment Considerations + +### Local Testing + +```bash +# Start Basis tracker server +cargo run -p basis_server + +# Run SilverCents demo +cd demo/silvercents +./silvercents_demo.sh +``` + +### Production Deployment + +1. **Infrastructure** + - Ergo node (full or light) + - Basis tracker server + - Database (PostgreSQL) + - Web server (nginx) + +2. **Configuration** + - Tracker NFT ID + - Network (mainnet/testnet) + - Collateral ratios + - Fee structure + +3. **Monitoring** + - Collateralization alerts + - Redemption tracking + - Reserve balances + - System health + +--- + +## Limitations + +### Current Demo + +- ✅ Demonstrates core concepts +- ✅ Shows complete workflow +- ✅ Educational value +- ⚠️ Mock cryptography +- ⚠️ Temporary storage +- ⚠️ No blockchain integration + +### Future Work + +- [ ] Real cryptographic signatures +- [ ] Persistent database +- [ ] On-chain reserve deployment +- [ ] DexySilver token integration +- [ ] Web/mobile interface +- [ ] Reputation system +- [ ] Multi-vendor marketplace + +--- + +## Performance + +### Scalability + +- **Vendors:** Unlimited (independent reserves) +- **Customers:** Unlimited (lightweight accounts) +- **Transactions:** Limited by tracker throughput +- **Storage:** Linear growth with notes + +### Optimization Opportunities + +- Batch note creation +- Proof caching +- Database indexing +- API rate limiting + +--- + +## References + +1. **Basis Protocol** + - `chaincash/docs/basis.md` + - `basis-tracker/README.md` + +2. **SilverCents Specification** + - `chaincash/docs/silvercents.md` + +3. **Ergo Platform** + - https://ergoplatform.org + - https://docs.ergoplatform.com + +4. **Constitutional Silver** + - Pre-1965 US dimes and quarters + - 90% silver content + - Widely available and recognizable + +--- + +**Status:** Demo Implementation +**Version:** 1.0.0 +**Team:** Dev Engers (LNMIIT Hackathon 2025) +**Issue:** #2 - SilverCents Demo Implementation