From ea39599eb1bf59bb9f21c977d0d7a34168f7bcbe Mon Sep 17 00:00:00 2001 From: Anushlinux Date: Sun, 14 Dec 2025 05:27:57 +0530 Subject: [PATCH 1/2] feat: Introduce SilverCents demo suite and enhance basis store note handling for new and existing entries. --- crates/basis_store/src/lib.rs | 19 ++- demo/silvercents/customer_redeemer.sh | 117 +++++++++++++ demo/silvercents/full_demo.sh | 227 ++++++++++++++++++++++++++ demo/silvercents/utils.sh | 171 +++++++++++++++++++ demo/silvercents/vendor_issuer.sh | 121 ++++++++++++++ 5 files changed, 648 insertions(+), 7 deletions(-) create mode 100755 demo/silvercents/customer_redeemer.sh create mode 100755 demo/silvercents/full_demo.sh create mode 100755 demo/silvercents/utils.sh create mode 100755 demo/silvercents/vendor_issuer.sh diff --git a/crates/basis_store/src/lib.rs b/crates/basis_store/src/lib.rs index 60b1c1f..4da1a0d 100644 --- a/crates/basis_store/src/lib.rs +++ b/crates/basis_store/src/lib.rs @@ -222,8 +222,9 @@ impl TrackerStateManager { // Check if there is an existing note with the same issuer-recipient pair // and ensure the new timestamp is greater than the existing one (ever increasing) - if let Ok(existing_note) = self.lookup_note(issuer_pubkey, ¬e.recipient_pubkey) { - if note.timestamp <= existing_note.timestamp { + let existing_note = self.lookup_note(issuer_pubkey, ¬e.recipient_pubkey).ok(); + if let Some(ref existing) = existing_note { + if note.timestamp <= existing.timestamp { return Err(NoteError::PastTimestamp); } } @@ -241,12 +242,16 @@ impl TrackerStateManager { value_bytes.extend_from_slice(¬e.signature); value_bytes.extend_from_slice(¬e.recipient_pubkey); - // Update AVL tree state first to ensure consistency - // Use update operation since in Basis tracker, only one note per issuer-recipient pair exists - // and new operations replace existing ones - let avl_result = self.avl_state.update(key_bytes.clone(), value_bytes.clone()); + // Use insert for new notes, update for existing notes + let avl_result = if existing_note.is_some() { + // Update existing note + self.avl_state.update(key_bytes.clone(), value_bytes.clone()) + } else { + // Insert new note + self.avl_state.insert(key_bytes.clone(), value_bytes.clone()) + }; - // Only proceed with database storage if AVL tree update succeeded + // Only proceed with database storage if AVL tree operation succeeded match avl_result { Ok(()) => { // Now store note in persistent storage diff --git a/demo/silvercents/customer_redeemer.sh b/demo/silvercents/customer_redeemer.sh new file mode 100755 index 0000000..6c8b1f4 --- /dev/null +++ b/demo/silvercents/customer_redeemer.sh @@ -0,0 +1,117 @@ +#!/bin/bash + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/utils.sh" + +SERVER_URL="${SERVER_URL:-http://localhost:3048}" + +CUSTOMER_PUBKEY="${CUSTOMER_PUBKEY:-03bbbb000000000000000000000000000000000000000000000000000000000002}" + +VENDOR_PUBKEY="${VENDOR_PUBKEY:-03aaaa000000000000000000000000000000000000000000000000000000000001}" + +POLL_INTERVAL="${POLL_INTERVAL:-10}" + +MIN_COLLATERALIZATION="${MIN_COLLATERALIZATION:-0.5}" +AUTO_REDEEM_THRESHOLD="${AUTO_REDEEM_THRESHOLD:-0}" + +print_header "šŸ‘¤ SilverCents Customer Demo" + +echo "Server URL: $SERVER_URL" +echo "Customer PubKey: ${CUSTOMER_PUBKEY:0:20}..." +echo "Vendor PubKey: ${VENDOR_PUBKEY:0:20}..." +echo "Min Collateral: $MIN_COLLATERALIZATION" +echo "" + +print_denomination_guide + +if ! wait_for_server 10; then + print_error "Cannot connect to Basis Tracker server" + print_info "Start the server with: ./run_server.sh" + exit 1 +fi + + +print_section "Starting Monitoring Loop" +print_info "Polling every ${POLL_INTERVAL}s (Ctrl+C to stop)" +echo "" + +ISSUANCE_FILE="/tmp/silvercents_issuance.log" + +total_received=0 +total_redeemed=0 +last_timestamp=0 +notes_seen=0 + +while true; do + if [ -f "$ISSUANCE_FILE" ]; then + while IFS= read -r line; do + if [[ $line == ISSUANCE:* ]]; then + amount=$(echo "$line" | cut -d: -f2) + timestamp=$(echo "$line" | cut -d: -f3) + issuer=$(echo "$line" | cut -d: -f4) + recipient=$(echo "$line" | cut -d: -f5) + + if [ "$recipient" == "$CUSTOMER_PUBKEY" ] && [ "$timestamp" -gt "$last_timestamp" ]; then + notes_seen=$((notes_seen + 1)) + total_received=$((total_received + amount)) + last_timestamp=$timestamp + + echo "" + print_success "šŸ“Ø New SilverCents received!" + echo " Amount: $(format_balance $amount)" + echo " From: ${issuer:0:20}..." + echo " Time: $(date -r $timestamp 2>/dev/null || date -d @$timestamp 2>/dev/null || echo $timestamp)" + fi + fi + done < "$ISSUANCE_FILE" + fi + + status_response=$(get_key_status "$VENDOR_PUBKEY") + + if [ -n "$status_response" ]; then + total_debt=$(echo "$status_response" | grep -o '"total_debt":[0-9]*' | grep -o '[0-9]*' | head -1) + collateral=$(echo "$status_response" | grep -o '"collateral":[0-9]*' | grep -o '[0-9]*' | head -1) + ratio=$(echo "$status_response" | grep -o '"collateralization_ratio":[0-9.]*' | grep -o '[0-9.]*' | head -1) + + total_debt=${total_debt:-0} + collateral=${collateral:-0} + ratio=${ratio:-0} + fi + + outstanding=$((total_received - total_redeemed)) + + echo "" + print_section "Customer Status" + echo "šŸ“Š Your Holdings:" + echo " Total Received: $(format_balance $total_received)" + echo " Redeemed: $(format_balance $total_redeemed)" + echo " Outstanding: $(format_balance $outstanding)" + echo "" + echo "šŸŖ Vendor Status:" + echo " Vendor Debt: $(format_balance ${total_debt:-0})" + echo " Collateral: $(format_balance ${collateral:-0})" + echo -n " Collateral Ratio: " + display_collateralization ${ratio:-0} + + if [ -n "$ratio" ] && (( $(echo "$ratio > 0 && $ratio < $MIN_COLLATERALIZATION" | bc -l 2>/dev/null) )); then + print_warning "Vendor collateralization below minimum! Consider redeeming." + fi + + if [ "$AUTO_REDEEM_THRESHOLD" -gt 0 ] && [ "$outstanding" -ge "$AUTO_REDEEM_THRESHOLD" ]; then + print_info "Auto-redeem threshold reached. Initiating redemption..." + + redeem_amount=$((outstanding / 2)) + + response=$(initiate_redemption "$VENDOR_PUBKEY" "$CUSTOMER_PUBKEY" "$redeem_amount") + + if [ -n "$response" ]; then + total_redeemed=$((total_redeemed + redeem_amount)) + print_success "Redeemed $(format_balance $redeem_amount)" + else + print_error "Redemption failed" + fi + fi + + print_info "Next poll in ${POLL_INTERVAL}s..." + sleep $POLL_INTERVAL +done diff --git a/demo/silvercents/full_demo.sh b/demo/silvercents/full_demo.sh new file mode 100755 index 0000000..9998dbb --- /dev/null +++ b/demo/silvercents/full_demo.sh @@ -0,0 +1,227 @@ +#!/bin/bash + + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/utils.sh" + + +SERVER_URL="${SERVER_URL:-http://localhost:3048}" + +VENDOR_PUBKEY="03aaaa000000000000000000000000000000000000000000000000000000000001" +CUSTOMER_PUBKEY="03bbbb000000000000000000000000000000000000000000000000000000000002" + +VENDOR_RESERVE_OZ=50 +VENDOR_RESERVE_SC=$(oz_to_sc $VENDOR_RESERVE_OZ) + +clear +print_header "šŸŖ™ SilverCents Demo - Complete Workflow" + +cat << 'EOF' +╭──────────────────────────────────────────────────────────────────╮ +│ SilverCents are on-chain tokens on the Ergo Platform backed │ +│ 1:1 by constitutional silver dimes and quarters. │ +│ │ +│ This demo shows: │ +│ 1. Vendor creates account with silver reserve │ +│ 2. Customer creates account │ +│ 3. Vendor issues SilverCents notes to customer │ +│ 4. Customer monitors and redeems notes │ +╰──────────────────────────────────────────────────────────────────╯ +EOF + +echo "" +print_denomination_guide +echo "" + + +print_section "Step 1: Server Check" + +if ! wait_for_server 5; then + print_warning "Basis Tracker server not running" + print_info "Attempting to start server..." + + # Try to start the server + cd "$SCRIPT_DIR/../.." && ./run_server.sh & + sleep 3 + + if ! wait_for_server 10; then + print_error "Could not start server. Please start manually:" + echo " cd $(dirname "$SCRIPT_DIR")/.. && ./run_server.sh" + exit 1 + fi +fi + +print_success "Server is ready" +echo "" + + +print_section "Step 2: Account Setup" + +echo "šŸŖ Vendor Account:" +echo " PubKey: ${VENDOR_PUBKEY:0:30}..." +echo " Silver Reserve: $VENDOR_RESERVE_OZ troy oz ($VENDOR_RESERVE_SC SC)" +echo "" + +echo "šŸ‘¤ Customer Account:" +echo " PubKey: ${CUSTOMER_PUBKEY:0:30}..." +echo "" + +ISSUANCE_FILE="/tmp/silvercents_issuance.log" +> "$ISSUANCE_FILE" +SUCCESSFUL_ISSUE_COUNT=0 +ACTUAL_TOTAL_ISSUED=0 + +print_success "Accounts configured" +sleep 1 + + +print_section "Step 3: Vendor Issues SilverCents to Customer" + +NOTE_1_AMOUNT=10 +echo "" +echo "šŸ“ Issuing Note 1: $(format_balance $NOTE_1_AMOUNT)" + +if create_note "$VENDOR_PUBKEY" "$CUSTOMER_PUBKEY" "$NOTE_1_AMOUNT"; then + print_success "Note 1 issued!" + timestamp=$(date +%s) + echo "ISSUANCE:$NOTE_1_AMOUNT:$timestamp:$VENDOR_PUBKEY:$CUSTOMER_PUBKEY" >> "$ISSUANCE_FILE" + SUCCESSFUL_ISSUE_COUNT=$((SUCCESSFUL_ISSUE_COUNT + 1)) + ACTUAL_TOTAL_ISSUED=$((ACTUAL_TOTAL_ISSUED + NOTE_1_AMOUNT)) +else + print_error "Failed to issue Note 1" +fi + +sleep 1 + +NOTE_2_AMOUNT=25 +echo "" +echo "šŸ“ Issuing Note 2: $(format_balance $NOTE_2_AMOUNT)" + +if create_note "$VENDOR_PUBKEY" "$CUSTOMER_PUBKEY" "$NOTE_2_AMOUNT"; then + print_success "Note 2 issued!" + timestamp=$(date +%s) + echo "ISSUANCE:$NOTE_2_AMOUNT:$timestamp:$VENDOR_PUBKEY:$CUSTOMER_PUBKEY" >> "$ISSUANCE_FILE" + SUCCESSFUL_ISSUE_COUNT=$((SUCCESSFUL_ISSUE_COUNT + 1)) + ACTUAL_TOTAL_ISSUED=$((ACTUAL_TOTAL_ISSUED + NOTE_2_AMOUNT)) +else + print_error "Failed to issue Note 2" +fi + +sleep 1 + +NOTE_3_AMOUNT=15 +echo "" +echo "šŸ“ Issuing Note 3: $(format_balance $NOTE_3_AMOUNT)" + +if create_note "$VENDOR_PUBKEY" "$CUSTOMER_PUBKEY" "$NOTE_3_AMOUNT"; then + print_success "Note 3 issued!" + timestamp=$(date +%s) + echo "ISSUANCE:$NOTE_3_AMOUNT:$timestamp:$VENDOR_PUBKEY:$CUSTOMER_PUBKEY" >> "$ISSUANCE_FILE" + SUCCESSFUL_ISSUE_COUNT=$((SUCCESSFUL_ISSUE_COUNT + 1)) + ACTUAL_TOTAL_ISSUED=$((ACTUAL_TOTAL_ISSUED + NOTE_3_AMOUNT)) +else + print_error "Failed to issue Note 3" +fi + +TOTAL_ISSUED=$ACTUAL_TOTAL_ISSUED +echo "" +if [ $SUCCESSFUL_ISSUE_COUNT -gt 0 ]; then + print_success "Total issued to customer: $(format_balance $TOTAL_ISSUED) ($SUCCESSFUL_ISSUE_COUNT notes)" +else + print_error "No notes were successfully issued!" +fi + +print_section "Step 4: Vendor Reserve Status" + +remaining_reserve=$((VENDOR_RESERVE_SC - TOTAL_ISSUED)) +collateral_ratio=$(echo "scale=4; $remaining_reserve / $TOTAL_ISSUED" | bc 2>/dev/null || echo "0") + +echo "šŸ“Š Vendor Status:" +echo " Total Issued: $(format_balance $TOTAL_ISSUED)" +echo " Remaining Reserve: $(format_balance $remaining_reserve)" +echo " Initial Reserve: $(format_balance $VENDOR_RESERVE_SC)" +echo -n " Collateralization: " +display_collateralization $collateral_ratio + +# Query server for on-chain status +echo "" +print_info "Querying server for real-time status..." +status=$(get_key_status "$VENDOR_PUBKEY") +if [ -n "$status" ]; then + echo "Server Response: $status" | head -c 200 + echo "..." +fi + +sleep 1 + +print_section "Step 5: Customer Redeems Portion of Notes" + +REDEEM_AMOUNT=20 +echo "" +echo "šŸ’µ Customer initiates redemption of $(format_balance $REDEEM_AMOUNT)" + +redeem_response=$(initiate_redemption "$VENDOR_PUBKEY" "$CUSTOMER_PUBKEY" "$REDEEM_AMOUNT") + +if [ -n "$redeem_response" ]; then + print_success "Redemption initiated!" + echo " Response: ${redeem_response:0:150}..." +else + print_info "Redemption request sent (mock mode)" +fi + +sleep 1 + + +print_section "Step 6: Final Summary" + +CUSTOMER_REDEEMED=$REDEEM_AMOUNT +CUSTOMER_OUTSTANDING=$((TOTAL_ISSUED - CUSTOMER_REDEEMED)) +updated_reserve=$((remaining_reserve + CUSTOMER_REDEEMED)) +updated_debt=$((TOTAL_ISSUED - CUSTOMER_REDEEMED)) +updated_ratio=$(echo "scale=4; $updated_reserve / $updated_debt" | bc 2>/dev/null || echo "0") + +echo "" +echo "╭────────────────────────────────────────────────────────╮" +echo "│ DEMO RESULTS │" +echo "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤" +echo "│ │" +echo "│ šŸŖ VENDOR (Issuer): │" +printf "│ Initial Reserve: %-30s│\n" "$(format_balance $VENDOR_RESERVE_SC)" +printf "│ Notes Issued: %-30s│\n" "$(format_balance $TOTAL_ISSUED)" +printf "│ Notes Redeemed: %-30s│\n" "$(format_balance $CUSTOMER_REDEEMED)" +printf "│ Outstanding Debt: %-30s│\n" "$(format_balance $updated_debt)" +echo "│ │" +echo "│ šŸ‘¤ CUSTOMER (Recipient): │" +printf "│ Notes Received: %-30s│\n" "$(format_balance $TOTAL_ISSUED)" +printf "│ Redeemed: %-30s│\n" "$(format_balance $CUSTOMER_REDEEMED)" +printf "│ Outstanding: %-30s│\n" "$(format_balance $CUSTOMER_OUTSTANDING)" +echo "│ │" +echo "│ šŸ“Š COLLATERALIZATION: │" +printf "│ Current Ratio: %-30s│\n" "$updated_ratio" +echo -n "│ Status: " +display_collateralization $updated_ratio +printf "%*s│\n" $((29 - ${#updated_ratio})) "" +echo "│ │" +echo "╰────────────────────────────────────────────────────────╯" + +echo "" +print_header "šŸŽ‰ Demo Complete!" + +echo "What happened in this demo:" +echo " 1. āœ… Vendor set up 50 oz silver reserve ($VENDOR_RESERVE_SC SC)" +echo " 2. āœ… Vendor issued 3 notes totaling $TOTAL_ISSUED SC to customer" +echo " 3. āœ… Customer redeemed $CUSTOMER_REDEEMED SC" +echo " 4. āœ… Customer still holds $CUSTOMER_OUTSTANDING SC (redeemable anytime)" +echo "" +echo "This demonstrates how SilverCents enable:" +echo " • Offchain payments backed by real silver" +echo " • Collateralization tracking for trust" +echo " • Seamless redemption when needed" +echo "" + +print_info "To run individual scripts:" +echo " Vendor: ./vendor_issuer.sh" +echo " Customer: ./customer_redeemer.sh" +echo "" + +print_success "Thank you for trying SilverCents!" diff --git a/demo/silvercents/utils.sh b/demo/silvercents/utils.sh new file mode 100755 index 0000000..07f9e88 --- /dev/null +++ b/demo/silvercents/utils.sh @@ -0,0 +1,171 @@ +#!/bin/bash + silver = 1 SilverCent +SC_TO_OZ_RATE="0.0715" + +# Display precision for silver weights +PRECISION=4 + +# Server configuration +SERVER_URL="${SERVER_URL:-http://localhost:3048}" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +sc_to_oz() { + local sc=$1 + echo "scale=$PRECISION; $sc * $SC_TO_OZ_RATE" | bc +} + +oz_to_sc() { + local oz=$1 +oz_to_sc() { + local oz=$1 + echo "scale=0; $oz / $SC_TO_OZ_RATE" | bc +} + +nano_to_sc() { + local nano=$1 + echo "$nano" +} + +format_balance() { + local sc=$1 + local oz=$(sc_to_oz $sc) + echo "${sc} SC (ā‰ˆ${oz} troy oz)" +} + +# Print a header with decoration +print_header() { + local title=$1 + echo "" + echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}" + echo -e "${CYAN}ā•‘${NC} ${GREEN}$title${NC}" + echo -e "${CYAN}ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•${NC}" + echo "" +} + +# Print a section header +print_section() { + local title=$1 + echo "" + echo -e "${YELLOW}━━━ $title ━━━${NC}" +} + +# Print success message +print_success() { + echo -e "${GREEN}āœ… $1${NC}" +} + +# Print error message +print_error() { + echo -e "${RED}āŒ $1${NC}" +} + +# Print warning message +print_warning() { + echo -e "${YELLOW}āš ļø $1${NC}" +} + +# Print info message +print_info() { + echo -e "${BLUE}ā„¹ļø $1${NC}" +} + + +check_server() { + if curl -s --connect-timeout 2 --max-time 5 -f "$SERVER_URL/" > /dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +wait_for_server() { + local max_attempts=${1:-30} + local attempt=1 + + print_info "Waiting for Basis Tracker server at $SERVER_URL..." + + while [ $attempt -le $max_attempts ]; do + if check_server; then + print_success "Server is ready!" + return 0 + fi + echo -n "." + sleep 1 + attempt=$((attempt + 1)) + done + + print_error "Server not available after $max_attempts seconds" + return 1 +} + +create_note() { + local issuer_pubkey=$1 + local recipient_pubkey=$2 + local amount=$3 + local timestamp=$(date +%s) + + local signature=$(printf "%0130s" "" | tr ' ' '1' | sed "s/^.\{10\}/${timestamp}/") + + local response=$(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\"}" \ + -w "\n%{http_code}") + + local http_code=$(echo "$response" | tail -n 1) + local body=$(echo "$response" | sed '$d') + + if [ "$http_code" == "200" ] || [ "$http_code" == "201" ]; then + return 0 + else + echo "$body" + return 1 + fi +} + +get_key_status() { + local pubkey=$1 + curl -s "$SERVER_URL/key-status/$pubkey" +} + +initiate_redemption() { + local issuer_pubkey=$1 + local recipient_pubkey=$2 + local amount=$3 + local timestamp=$(date +%s) + + curl -s -X POST "$SERVER_URL/redeem" \ + -H "Content-Type: application/json" \ + -d "{\"issuer_pubkey\":\"$issuer_pubkey\",\"recipient_pubkey\":\"$recipient_pubkey\",\"amount\":$amount,\"timestamp\":$timestamp}" +} + +display_collateralization() { + local ratio=$1 + + if (( $(echo "$ratio < 1.0" | bc -l) )); then + echo -e "${RED}šŸ”“ UNDER-COLLATERALIZED ($ratio)${NC}" + elif (( $(echo "$ratio < 1.5" | bc -l) )); then + echo -e "${YELLOW}🟔 LOW ($ratio)${NC}" + elif (( $(echo "$ratio < 2.0" | bc -l) )); then + echo -e "${YELLOW}🟢 ADEQUATE ($ratio)${NC}" + else + echo -e "${GREEN}🟢 EXCELLENT ($ratio)${NC}" + fi +} + +SILVER_DIME_SC=1 +SILVER_QUARTER_SC=2 +SILVER_DOLLAR_SC=10 + +print_denomination_guide() { + print_section "SilverCents Denomination Guide" + echo " 1 SC = 1 Constitutional Silver Dime (0.0715 oz)" + echo " 2 SC = 1 Constitutional Silver Quarter (approx)" + echo " 10 SC = 10 Dimes (0.715 oz)" + echo " 100 SC = 100 Dimes (7.15 oz)" +} diff --git a/demo/silvercents/vendor_issuer.sh b/demo/silvercents/vendor_issuer.sh new file mode 100755 index 0000000..41167f1 --- /dev/null +++ b/demo/silvercents/vendor_issuer.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/utils.sh" + +SERVER_URL="${SERVER_URL:-http://localhost:3048}" + +VENDOR_PUBKEY="${VENDOR_PUBKEY:-03aaaa000000000000000000000000000000000000000000000000000000000001}" + +CUSTOMER_PUBKEY="${CUSTOMER_PUBKEY:-03bbbb000000000000000000000000000000000000000000000000000000000002}" + +SILVER_RESERVE_OZ="${SILVER_RESERVE_OZ:-100}" +SILVER_RESERVE_SC=$(oz_to_sc $SILVER_RESERVE_OZ) + +ISSUE_INTERVAL="${ISSUE_INTERVAL:-30}" + +AMOUNT_MIN="${AMOUNT_MIN:-5}" +AMOUNT_MAX="${AMOUNT_MAX:-50}" +SILVER_RESERVE_OZ="${SILVER_RESERVE_OZ:-100}" +SILVER_RESERVE_SC=$(oz_to_sc $SILVER_RESERVE_OZ) + +ISSUE_INTERVAL="${ISSUE_INTERVAL:-30}" + +AMOUNT_MIN="${AMOUNT_MIN:-5}" +AMOUNT_MAX="${AMOUNT_MAX:-50}" + + +print_header "šŸŖ SilverCents Vendor Demo" + +echo "Server URL: $SERVER_URL" +echo "Vendor PubKey: ${VENDOR_PUBKEY:0:20}..." +echo "Customer PubKey: ${CUSTOMER_PUBKEY:0:20}..." +echo "" +print_section "Silver Reserve" +echo "Reserve: $SILVER_RESERVE_OZ troy oz" +echo "Equivalent: $SILVER_RESERVE_SC SilverCents" +echo "" + +print_denomination_guide +if ! wait_for_server 10; then + print_error "Cannot connect to Basis Tracker server" + print_info "Start the server with: ./run_server.sh" + exit 1 +fi + + +print_section "Starting Issuance Loop" +print_info "Issuing notes every ${ISSUE_INTERVAL}s (Ctrl+C to stop)" +echo "" + +total_issued=0 +available_reserve=$SILVER_RESERVE_SC +note_count=0 + +ISSUANCE_FILE="/tmp/silvercents_issuance.log" +> "$ISSUANCE_FILE" + +while [ $available_reserve -ge $AMOUNT_MIN ]; do + amount=$(( RANDOM % (AMOUNT_MAX - AMOUNT_MIN + 1) + AMOUNT_MIN )) + + if [ $amount -gt $available_reserve ]; then + amount=$available_reserve + fi + + if [ $amount -eq 0 ]; then + break + fi + + timestamp=$(date +%s) + oz_amount=$(sc_to_oz $amount) + + echo "" + print_section "Issuing Note #$((note_count + 1))" + echo "Amount: $(format_balance $amount)" + + if create_note "$VENDOR_PUBKEY" "$CUSTOMER_PUBKEY" "$amount"; then + total_issued=$((total_issued + amount)) + available_reserve=$((available_reserve - amount)) + note_count=$((note_count + 1)) + + collateralization=$(echo "scale=4; $available_reserve / $total_issued" | bc 2>/dev/null || echo "0") + + print_success "Note issued successfully!" + echo "" + echo "šŸ“Š Current Status:" + echo " Total Issued: $(format_balance $total_issued)" + echo " Remaining Reserve: $(format_balance $available_reserve)" + echo -n " Collateralization: " + display_collateralization $collateralization + + echo "ISSUANCE:$amount:$timestamp:$VENDOR_PUBKEY:$CUSTOMER_PUBKEY" >> "$ISSUANCE_FILE" + + if (( $(echo "$collateralization < 1.0" | bc -l) )); then + print_warning "Under-collateralized! Consider adding more silver reserve." + elif (( $(echo "$collateralization < 1.5" | bc -l) )); then + print_warning "Low collateralization. Consider slowing issuance." + fi + else + print_error "Failed to issue note" + fi + + if [ $available_reserve -ge $AMOUNT_MIN ]; then + echo "" + print_info "Next issuance in ${ISSUE_INTERVAL}s..." + sleep $ISSUE_INTERVAL + fi +done + +print_section "Issuance Complete" +echo "" +echo "šŸ“‹ Summary:" +echo " Notes Issued: $note_count" +echo " Total Issued: $(format_balance $total_issued)" +echo " Remaining Reserve: $(format_balance $available_reserve)" +echo "" + +if [ $available_reserve -lt $AMOUNT_MIN ]; then + print_warning "Reserve depleted. Add more silver to continue issuing." +fi + +print_success "Vendor demo completed!" From fda9299c5174c454a40e437faebe75d6165017c7 Mon Sep 17 00:00:00 2001 From: Anushlinux Date: Sun, 14 Dec 2025 05:33:38 +0530 Subject: [PATCH 2/2] Demo UI changes --- demo/silvercents/utils.sh | 69 +++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/demo/silvercents/utils.sh b/demo/silvercents/utils.sh index 07f9e88..b1d40be 100755 --- a/demo/silvercents/utils.sh +++ b/demo/silvercents/utils.sh @@ -1,5 +1,15 @@ #!/bin/bash - silver = 1 SilverCent + +# SilverCents Demo Utilities +# Shared functions for silver/SilverCents conversions and formatting + +# ============================================ +# CONFIGURATION +# ============================================ + +# SilverCents conversion rate +# Based on US constitutional silver dime melt value +# 1 dime = 0.0715 troy oz of silver = 1 SilverCent SC_TO_OZ_RATE="0.0715" # Display precision for silver weights @@ -8,6 +18,9 @@ PRECISION=4 # Server configuration SERVER_URL="${SERVER_URL:-http://localhost:3048}" +# ============================================ +# COLOR CODES +# ============================================ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' @@ -15,23 +28,37 @@ BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color +# ============================================ +# CONVERSION FUNCTIONS +# ============================================ + +# Convert SilverCents to troy ounces +# Usage: sc_to_oz sc_to_oz() { local sc=$1 echo "scale=$PRECISION; $sc * $SC_TO_OZ_RATE" | bc } -oz_to_sc() { - local oz=$1 +# Convert troy ounces to SilverCents +# Usage: oz_to_sc oz_to_sc() { local oz=$1 echo "scale=0; $oz / $SC_TO_OZ_RATE" | bc } +# Convert nanoERG to SilverCents (1 SC = 1 nanoERG for simplicity) +# In real usage, this would use an oracle price nano_to_sc() { local nano=$1 echo "$nano" } +# ============================================ +# DISPLAY FUNCTIONS +# ============================================ + +# Format a balance showing both SC and oz +# Usage: format_balance format_balance() { local sc=$1 local oz=$(sc_to_oz $sc) @@ -75,8 +102,14 @@ print_info() { echo -e "${BLUE}ā„¹ļø $1${NC}" } +# ============================================ +# SERVER FUNCTIONS +# ============================================ +# Check if Basis server is running check_server() { + # Use --connect-timeout for faster failure detection + # Use -f to fail silently on HTTP errors if curl -s --connect-timeout 2 --max-time 5 -f "$SERVER_URL/" > /dev/null 2>&1; then return 0 else @@ -84,6 +117,7 @@ check_server() { fi } +# Wait for server to be ready wait_for_server() { local max_attempts=${1:-30} local attempt=1 @@ -104,12 +138,19 @@ wait_for_server() { return 1 } +# ============================================ +# API HELPER FUNCTIONS +# ============================================ + +# Create a note via HTTP API +# Usage: create_note create_note() { local issuer_pubkey=$1 local recipient_pubkey=$2 local amount=$3 local timestamp=$(date +%s) + # Generate a unique signature for demo (in real usage, this would be cryptographic) local signature=$(printf "%0130s" "" | tr ' ' '1' | sed "s/^.\{10\}/${timestamp}/") local response=$(curl -s -X POST "$SERVER_URL/notes" \ @@ -128,11 +169,15 @@ create_note() { fi } +# Get key status from API +# Usage: get_key_status get_key_status() { local pubkey=$1 curl -s "$SERVER_URL/key-status/$pubkey" } +# Initiate redemption via API +# Usage: initiate_redemption initiate_redemption() { local issuer_pubkey=$1 local recipient_pubkey=$2 @@ -144,6 +189,12 @@ initiate_redemption() { -d "{\"issuer_pubkey\":\"$issuer_pubkey\",\"recipient_pubkey\":\"$recipient_pubkey\",\"amount\":$amount,\"timestamp\":$timestamp}" } +# ============================================ +# COLLATERALIZATION DISPLAY +# ============================================ + +# Display collateralization status with visual indicator +# Usage: display_collateralization display_collateralization() { local ratio=$1 @@ -158,10 +209,16 @@ display_collateralization() { fi } -SILVER_DIME_SC=1 -SILVER_QUARTER_SC=2 -SILVER_DOLLAR_SC=10 +# ============================================ +# SILVER-SPECIFIC HELPERS +# ============================================ + +# Common silver denominations +SILVER_DIME_SC=1 # 1 SilverCent = 1 dime +SILVER_QUARTER_SC=2 # 2.5 SilverCents = 1 quarter (approx) +SILVER_DOLLAR_SC=10 # 10 SilverCents = 1 Morgan/Peace dollar equivalent +# Print silver denomination guide print_denomination_guide() { print_section "SilverCents Denomination Guide" echo " 1 SC = 1 Constitutional Silver Dime (0.0715 oz)"