// lib/wallet-context.cjs - Storage layer with Corestore + Hyperbee
require('bare-node-runtime/global')
const path = require('bare-path')
const os = require('bare-os')
const Corestore = require('corestore')
const Hyperbee = require('hyperbee')
// Storage configuration
const STORAGE_DIR = path.join(os.homedir(), '.hyper-wallet', 'storage')
// Singleton instances
let store = null
let txHistoryDb = null
/**
* Initialize Corestore and Hyperbee
* Creates storage directory and sets up transaction history database
*/
async function initializeStorage() {
if (store && txHistoryDb) {
return { store, txHistoryDb }
}
// Initialize Corestore
store = new Corestore(STORAGE_DIR)
await store.ready()
// Create Hyperbee for transaction history
const txHistoryCore = store.get({ name: 'tx-history' })
await txHistoryCore.ready()
txHistoryDb = new Hyperbee(txHistoryCore, {
keyEncoding: 'utf-8',
valueEncoding: 'json'
})
await txHistoryDb.ready()
return { store, txHistoryDb }
}
/**
* Store a transaction in the history database
* @param {Object} tx - Transaction details
* @param {string} tx.hash - Transaction hash
* @param {string} tx.chain - Chain ('bitcoin' or 'ethereum')
* @param {string} tx.to - Recipient address
* @param {string} tx.amount - Amount (as string to preserve BigInt)
* @param {string} tx.fee - Fee (as string to preserve BigInt)
* @param {number} tx.timestamp - Unix timestamp
* @param {string} tx.status - Transaction status ('pending', 'confirmed', 'failed')
*/
async function storeTx(tx) {
const { txHistoryDb } = await initializeStorage()
// Key format: tx:<timestamp>:<hash> (sorted by time, unique by hash)
const key = `tx:${tx.timestamp}:${tx.hash}`
await txHistoryDb.put(key, {
hash: tx.hash,
chain: tx.chain,
to: tx.to,
amount: tx.amount,
fee: tx.fee,
timestamp: tx.timestamp,
status: tx.status || 'pending'
})
}
/**
* Get all transactions, optionally filtered by chain
* @param {string} chain - Optional chain filter ('bitcoin', 'ethereum', or null for all)
* @returns {Array} Array of transaction objects
*/
async function getTxHistory(chain = null) {
const { txHistoryDb } = await initializeStorage()
const transactions = []
// Read all transactions from Hyperbee
for await (const entry of txHistoryDb.createReadStream()) {
const tx = entry.value
// Filter by chain if specified
if (chain && tx.chain !== chain) {
continue
}
transactions.push(tx)
}
// Sort by timestamp (newest first)
transactions.sort((a, b) => b.timestamp - a.timestamp)
return transactions
}
/**
* Get a specific transaction by hash
* @param {string} hash - Transaction hash
* @returns {Object|null} Transaction object or null if not found
*/
async function getTx(hash) {
const { txHistoryDb } = await initializeStorage()
// Scan for transaction with matching hash
for await (const entry of txHistoryDb.createReadStream()) {
if (entry.value.hash === hash) {
return entry.value
}
}
return null
}
/**
* Update transaction status
* @param {string} hash - Transaction hash
* @param {string} status - New status
*/
async function updateTxStatus(hash, status) {
const { txHistoryDb } = await initializeStorage()
// Find and update the transaction
for await (const entry of txHistoryDb.createReadStream()) {
if (entry.value.hash === hash) {
const tx = entry.value
tx.status = status
await txHistoryDb.put(entry.key, tx)
return
}
}
}
/**
* Close storage (cleanup)
*/
async function closeStorage() {
if (txHistoryDb) {
await txHistoryDb.close()
txHistoryDb = null
}
if (store) {
await store.close()
store = null
}
}
module.exports = {
initializeStorage,
storeTx,
getTxHistory,
getTx,
updateTxStatus,
closeStorage
}