#!/usr/bin/env bare
/**
* Hyper-Wallet - Unified Entry Point
*
* Supports both CLI and Web Server modes:
* - Web mode: bare hyper-wallet.cjs web [port]
* - CLI mode: bare hyper-wallet.cjs <command> [args]
*
* Pear compatible:
* - pear run pear://hash web 3003
* - pear run pear://hash init
*/
require('bare-node-runtime/global')
// WORKAROUND: Pear doesn't support import attributes with ESM yet
// Manually load imports.json into bundle for Bare 1.24/1.26 compatibility
require('bare-node-runtime/imports')
const fs = require('bare-fs')
const path = require('bare-path')
const { spawn } = require('bare-subprocess')
// Support both Pear runtime and bare/node
const isPear = typeof globalThis.Pear !== 'undefined'
const args = isPear ? (Pear.config.args || []) : (typeof Bare !== 'undefined' ? Bare.argv.slice(2) : process.argv.slice(2))
const mode = args[0]
// Show usage if no arguments
if (!mode) {
showUsage()
process.exit(0)
}
// Background OTA via pgh — content-addressed store, NO Hyperdrive/blobs.
// `pgh app update <name>` resolves the latest release from package.json's
// pgh.upgrade and ATOMICALLY materializes the new tree (safe while running;
// next launch uses it). Replaces the former pear-runtime Hyperdrive updater,
// which kept an unbounded append-only blob corestore under
// ~/.config/hyper-wallet/pear-runtime that grew on every release.
const _argv = typeof Bare !== 'undefined' ? Bare.argv : process.argv
if (!isPear && !_argv.includes('--no-updates')) {
try {
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf-8'))
const upgrade = pkg.pgh && pkg.pgh.upgrade
if (upgrade) {
const os = require('bare-os')
const appName = (pkg.pgh && pkg.pgh.bin) || pkg.name || 'hyper-wallet'
// Resolve the pgh CLI: prefer ~/.local/bin/pgh, else the store-installed
// bare runtime + entry. Bail if pgh isn't on this machine.
let argv = null
const launcher = path.join(os.homedir(), '.local', 'bin', 'pgh')
if (fs.existsSync(launcher)) argv = [launcher]
else {
const storeRoot = process.env.PGH_STORE_ROOT || path.join(os.homedir(), '.local', 'share', 'store')
const bareBin = path.join(storeRoot, 'apps', 'pgh', 'runtime', 'bare')
const entry = path.join(storeRoot, 'apps', 'pgh', 'bin', 'pgh.bare.js')
if (fs.existsSync(bareBin) && fs.existsSync(entry)) argv = [bareBin, entry]
}
if (argv) {
// Detached + best-effort: never blocks the wallet command.
const proc = spawn(argv[0], [...argv.slice(1), 'app', 'update', appName], {
stdio: 'ignore',
detached: true
})
proc.on('error', () => {})
if (proc.unref) proc.unref()
}
}
} catch {}
}
// Dispatch based on mode
if (mode === 'web') {
// Web server mode
// Check for --network flag (allow network access)
const networkFlag = args.includes('--network')
const port = args.find(arg => arg.match(/^\d+$/)) || process.env.PORT || '4004'
startWebServer(port, networkFlag)
} else {
// CLI mode - delegate to hyper-wallet-cli.cjs
runCliCommand(args)
}
function showUsage() {
console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
hyper-wallet - Self-custodial P2P Cryptocurrency Wallet
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
USAGE:
bare hyper-wallet.cjs <mode> [options]
pear run pear://hash <mode> [options]
MODES:
web [port] [--network]
Start web server (default: 4004)
Default: localhost only (secure)
--network: Allow network access (0.0.0.0)
Examples:
bare hyper-wallet.cjs web 3003
bare hyper-wallet.cjs web 3003 --network
pear run pear://hash web 3003
CLI COMMANDS:
init Generate new wallet
init --import Import wallet from mnemonic
whoami Show identity and addresses
balance [chain] Check balances (all, btc, or eth)
receive <chain> Generate receiving address (btc or eth)
send <chain> <address> <amount> Send transaction
history [chain] View transaction history
help Show this help
EXAMPLES:
# Start web server (localhost only - secure)
bare hyper-wallet.cjs web
bare hyper-wallet.cjs web 3003
# Start web server with network access (for testing)
bare hyper-wallet.cjs web 3003 --network
pear run pear://hash web 4004 --network
# CLI commands
bare hyper-wallet.cjs init
bare hyper-wallet.cjs whoami
bare hyper-wallet.cjs balance btc
bare hyper-wallet.cjs send btc tb1q... 0.001
# With Pear
pear run pear://hash web 3003
pear run pear://hash init
pear run pear://hash whoami
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`)
}
async function startWebServer(port, allowNetwork = false) {
console.log(`🚀 Starting hyper-wallet web server on port ${port}...`)
if (allowNetwork) {
console.log('⚠️ Network access enabled (--network flag)')
}
console.log('')
// Load and start wallet-server.cjs
// Set PORT and HOST env vars for wallet-server to use
process.env.PORT = port
if (allowNetwork) {
process.env.WALLET_HOST = '0.0.0.0'
}
// Require the wallet server module and call its startServer function
const { startServer } = require('./wallet-server.cjs')
await startServer()
}
function runCliCommand(args) {
// Delegate to hyper-wallet-advanced-cli.cjs CLI handler
// Provides full feature set: device management, daemon mode, UTXO management, etc.
require('./hyper-wallet-advanced-cli.cjs')
}