Skip to content

kjartan221/testing-wallet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

BSV Wallet Transaction Playground

A Next.js playground for creating and monitoring BSV wallet transactions with live logs and real-time status updates.

Overview

This application creates ECDH-locked payments between a frontend wallet (browser extension) and a backend wallet, displaying live transaction logs and wallet action status as they happen.

Features

  • Transaction Testing: Create ECDH-locked payments with various amounts
  • Wallet State Monitoring: Real-time display of wallet action status transitions
  • Transaction Logging: Detailed logs with transaction hex and parameters
  • File Storage: All transactions saved to transaction-history.json with full ECDH parameters
  • Key Derivation Testing: Verify frontend/backend ECDH key synchronization
  • Single-Input Mode: Option to enforce single-input transactions by stripping wallet-added inputs
  • Frontend-Only Test: Create and spend a transaction entirely in the frontend wallet

Prerequisites

  • Node.js 18+ installed
  • A BSV wallet browser extension (e.g., Panda Wallet, MetaStrata)
  • A backend wallet private key for mainnet

Environment Setup

1. Create .env.local

Create a .env.local file in the project root:

# Backend wallet private key (WIF format)
BACKEND_WALLET_PRIVATE_KEY=your_private_key_here

You can also copy from the example:

cp .env.local.example .env.local

2. Backend Wallet Configuration

The backend wallet uses Babbage's storage URL by default on mainnet:

makeWallet('main', 'https://storage.babbage.systems', privateKey)
  • Network: Mainnet (main)
  • Storage URL: https://storage.babbage.systems
  • Private Key: Your wallet's private key in WIF format

Security Note: Never commit your .env.local file or expose your private key publicly.

Installation

# Install dependencies
npm install

# Run the development server
npm run dev

Open http://localhost:3000 (redirects to http://localhost:3000/playground)

How to Use

1. Connect Your Wallet

Click "Connect Wallet" to connect your browser wallet extension.

2. Test Key Derivation (Optional)

Click "πŸ” Test Key Derivation (Debug)" to verify that frontend and backend derive matching ECDH keys.

3. Create Transaction

Click "Create Transaction" to:

  • Frontend wallet creates a 100 sat ECDH-locked payment
  • Payment is locked to the backend using WalletP2PKH.lock()
  • Backend unlocks it using WalletP2PKH.unlock()
  • Transaction details are saved to transaction-history.json

4. Try Again Immediately

Click "Try Again Immediately" to create another transaction right away without waiting for the previous one to reach completed status.

5. Try Again After Proof

Click "Try Again After Proof" to:

  • Wait for the latest transaction to reach completed status
  • Poll wallet.listActions() until status changes
  • Create a new transaction once proven

6. Create 200 Sats (Single Input Enforced)

Click "Create 200 Sats (Single Input Enforced)" to create a 200 sat transaction where the backend strips any extra inputs the wallet might add, keeping only the input matching the derived payment key.

7. Frontend-Only Test

Click "πŸ”¬ Frontend-Only Test (No Backend)" to create a self-locked payment and immediately unlock it entirely within the frontend wallet β€” no backend involved.

ECDH Payment Architecture

Frontend                              Backend
─────────────────────────────────────────────────────
WalletP2PKH.lock()                 WalletP2PKH.unlock()
  protocolID: same                   protocolID: same
  keyID: same                        keyID: same
  counterparty: backendIdentity      counterparty: frontendIdentity
                                                   (swapped!)

Both sides derive the same key via ECDH with swapped counterparties.

Key Implementation Notes

acceptDelayedBroadcast: false

The createAction call uses acceptDelayedBroadcast: false in its options to ensure transactions are broadcast synchronously before the call returns. This was the fix for a previous issue where rapid sequential transactions could fail due to the wallet still processing the prior broadcast.

await wallet.createAction({
  description: '...',
  outputs: [...],
  options: {
    randomizeOutputs: false,
    acceptDelayedBroadcast: false,
  },
});

Wallet Action Status Lifecycle

unsigned β†’ nosend β†’ unproven β†’ completed

4-Step Backend Unlock Process

  1. Create unlocking script template and estimate length
  2. Create action with unlockingScriptLength (not actual script)
  3. Extract signableTransaction, add template + source, sign to get actual unlocking script
  4. Call signAction() with actual unlocking scripts

Transaction Storage

All transactions are automatically saved to transaction-history.json in the project root with:

{
  "timestamp": "2025-01-19T12:34:56.789Z",
  "frontendTxid": "abc123...",
  "frontendTxHex": "01000000...",
  "backendTxid": "def456...",
  "backendTxHex": "01000000...",
  "protocolID": [0, "wallet playground 1737291296789"],
  "keyID": "keyabc123",
  "counterparty": "03...",
  "paymentKey": "02...",
  "success": true,
  "error": null
}

Key Files

Frontend

  • src/app/playground/page.tsx - Main playground page (server component)
  • src/components/PlaygroundClient.tsx - Client component with state
  • src/components/TransactionTester.tsx - Transaction creation UI
  • src/components/WalletStateViewer.tsx - Real-time wallet action display
  • src/components/LogViewer.tsx - Transaction log display
  • src/utils/walletClient.ts - Frontend WalletClient (@bsv/sdk)

Backend

  • src/app/api/wallet/unlock-payment/route.ts - Standard unlock endpoint
  • src/app/api/wallet/unlock-payment-single-input/route.ts - Single-input enforcing unlock
  • src/app/api/wallet/derive-key/route.ts - Key derivation endpoint
  • src/app/api/wallet/identity/route.ts - Backend identity key endpoint
  • src/app/api/storage/save-transaction/route.ts - Transaction file storage
  • src/utils/backendWallet.ts - Backend wallet initialization

Development

# Install dependencies
npm install

# Run development server
npm run dev

# Build for production
npm run build

# Start production server
npm start

Troubleshooting

"Wallet not connected"

  • Ensure you have a BSV wallet extension installed (Panda, MetaStrata, etc.)
  • Refresh the page and try connecting again

"Backend identity key not available"

  • Check that BACKEND_WALLET_PRIVATE_KEY is set in .env.local
  • Verify the private key is in valid WIF format
  • Restart the dev server after changing .env.local

"No outputs match our derived payment key"

  • Ensure all wallet.getPublicKey() calls include forSelf: true
  • Use the "Test Key Derivation" button to verify keys match

License

MIT

About

Testing wallet and storage behaviour

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages