OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-wallet / deprecated / cli.cjs

219 lines · javascript ref:
#!/usr/bin/env bare

// cli.cjs - Hyper Wallet CLI Entry Point (Bare Runtime)
//
// Self-custodial P2P cryptocurrency wallet
// Built on Holepunchto + Tether WDK

// CRITICAL: Load bare-node-runtime first
require('bare-node-runtime/global')

const WalletContext = require('./lib/wallet-context.cjs')
const { loadMnemonic, storeMnemonic, isInitialized } = require('./lib/secure-storage.cjs')

// Hard-coded config for now (TODO: load from file)
const defaultConfig = {
  storagePath: '~/.hyper-wallet/storage',
  network: 'testnet',
  protocols: ['wdk'],
  wdk: {
    chains: ['ethereum', 'bitcoin'],
    networks: {
      ethereum: {
        name: 'sepolia',
        provider: 'https://ethereum-sepolia-rpc.publicnode.com',
        chainId: 11155111
      },
      bitcoin: {
        network: 'testnet',
        host: 'electrum.blockstream.info',
        port: 60001
      }
    }
  }
}

// Command handlers
const cmdInit = require('./cmd/init.cjs')
const cmdWhoami = require('./cmd/whoami.cjs')
const cmdBalance = require('./cmd/balance.cjs')
const cmdSend = require('./cmd/send.cjs')
const cmdReceive = require('./cmd/receive.cjs')
const cmdHistory = require('./cmd/history.cjs')
const { getEnabledProtocols } = require('./protocols/index.cjs')

async function main() {
  const args = process.argv.slice(2)
  const command = args[0]

  // Load config (merge default + user config if exists)
  const config = defaultConfig

  // Create wallet context
  const context = new WalletContext(config)

  try {
    switch (command) {
      case 'init': {
        const importMnemonic = args.includes('--import') ?
          args[args.indexOf('--import') + 1] : null

        const handler = cmdInit(context)[0]
        await handler({ import: importMnemonic })
        break
      }

      case 'whoami': {
        // Check if wallet is initialized
        if (!(await isInitialized())) {
          console.error('❌ Wallet not initialized. Run: bare cli.cjs init')
          process.exit(1)
        }

        // Load existing wallet
        await context.init(await loadMnemonic())

        const enabled = getEnabledProtocols(config)
        await context.loadProtocols(enabled)

        const handler = cmdWhoami(context)[0]
        await handler({})
        break
      }

      case 'balance': {
        // Check if wallet is initialized
        if (!(await isInitialized())) {
          console.error('❌ Wallet not initialized. Run: bare cli.cjs init')
          process.exit(1)
        }

        // Load existing wallet
        await context.init(await loadMnemonic())

        const enabled = getEnabledProtocols(config)
        await context.loadProtocols(enabled)

        const protocol = args[1]
        const handler = cmdBalance(context, enabled)[0]
        await handler({ protocol })
        break
      }

      case 'send': {
        // Check if wallet is initialized
        if (!(await isInitialized())) {
          console.error('❌ Wallet not initialized. Run: bare cli.cjs init')
          process.exit(1)
        }

        // Load existing wallet
        await context.init(await loadMnemonic())

        const enabled = getEnabledProtocols(config)
        await context.loadProtocols(enabled)

        const handler = cmdSend(context, enabled)[0]
        await handler(args.slice(1))
        break
      }

      case 'receive': {
        // Check if wallet is initialized
        if (!(await isInitialized())) {
          console.error('❌ Wallet not initialized. Run: bare cli.cjs init')
          process.exit(1)
        }

        // Load existing wallet
        await context.init(await loadMnemonic())

        const enabled = getEnabledProtocols(config)
        await context.loadProtocols(enabled)

        const handler = cmdReceive(context, enabled)[0]
        await handler(args.slice(1))
        break
      }

      case 'history': {
        // Check if wallet is initialized
        if (!(await isInitialized())) {
          console.error('❌ Wallet not initialized. Run: bare cli.cjs init')
          process.exit(1)
        }

        // Load existing wallet
        await context.init(await loadMnemonic())

        const enabled = getEnabledProtocols(config)
        await context.loadProtocols(enabled)

        const handler = cmdHistory(context, enabled)[0]
        await handler(args.slice(1))
        break
      }

      case 'help':
      case '--help':
      case '-h':
      default:
        showHelp()
        break
    }
  } catch (err) {
    console.error('❌ Error:', err.message)
    if (process.env.DEBUG) {
      console.error(err.stack)
    }
    process.exit(1)
  } finally {
    await context.close()
  }
}

/**
 * Show help message
 */
function showHelp() {
  console.log(`
hyper-wallet - Self-custodial P2P cryptocurrency wallet

USAGE:
  bare cli.cjs <command> [options]

COMMANDS:
  init              Initialize new wallet
  init --import     Import existing wallet from mnemonic
  whoami            Show wallet identity and addresses
  balance           Show balances across all protocols
  balance <proto>   Show balance for specific protocol
  send <to> <amt>   Send payment
  receive [chain]   Generate receiving address
  history [proto]   Show transaction history
  help              Show this help message

EXAMPLES:
  bare cli.cjs init
  bare cli.cjs whoami
  bare cli.cjs balance
  bare cli.cjs receive wdk ethereum
  bare cli.cjs send 0x123... 0.1
  bare cli.cjs history wdk

Supported protocols: wdk (Tether WDK - Bitcoin, Ethereum)

Powered by:
  ✅ Bare Runtime v1.26.0
  ✅ keet-identity-key (multi-device sync)
  ✅ Tether WDK (multi-chain wallets)
  ✅ Holepunchto P2P stack
`)
}

// Run CLI
main().catch(err => {
  console.error('Fatal error:', err)
  process.exit(1)
})