const Database = require("better-sqlite3"); const config = require("./config"); const db = new Database(config.DB_PATH); // Enable WAL mode for better concurrent read performance db.pragma("journal_mode = WAL"); // Create tables if they don't exist db.exec(` CREATE TABLE IF NOT EXISTS wallets ( disk_id TEXT PRIMARY KEY, address TEXT NOT NULL, private_key TEXT NOT NULL, name TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS contract_state ( key TEXT PRIMARY KEY, value TEXT ); CREATE TABLE IF NOT EXISTS payments ( id TEXT PRIMARY KEY, disk_id TEXT NOT NULL, amount_afc INTEGER NOT NULL, amount_mxn REAL NOT NULL, status TEXT NOT NULL DEFAULT 'pending', mp_preference_id TEXT, mp_payment_id TEXT, tx_hash TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS redemptions ( id TEXT PRIMARY KEY, disk_id TEXT NOT NULL, amount_afc INTEGER NOT NULL, prize_type TEXT NOT NULL, prize_detail TEXT NOT NULL, delivery_info TEXT, status TEXT NOT NULL DEFAULT 'pending', burn_tx_hash TEXT, admin_notes TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP, updated_at TEXT DEFAULT CURRENT_TIMESTAMP ); `); function getWallet(diskId) { const stmt = db.prepare("SELECT * FROM wallets WHERE disk_id = ?"); return stmt.get(diskId) || null; } function createWallet(diskId, address, privateKey, name) { const stmt = db.prepare( "INSERT INTO wallets (disk_id, address, private_key, name) VALUES (?, ?, ?, ?)" ); return stmt.run(diskId, address, privateKey, name); } function getContractAddress() { const stmt = db.prepare( "SELECT value FROM contract_state WHERE key = 'contract_address'" ); const row = stmt.get(); return row ? row.value : null; } function setContractAddress(address) { const stmt = db.prepare( "INSERT OR REPLACE INTO contract_state (key, value) VALUES ('contract_address', ?)" ); return stmt.run(address); } function getAllWallets() { const stmt = db.prepare("SELECT * FROM wallets"); return stmt.all(); } // Payments function createPayment(id, diskId, amountAfc, amountMxn) { const stmt = db.prepare( "INSERT INTO payments (id, disk_id, amount_afc, amount_mxn) VALUES (?, ?, ?, ?)" ); return stmt.run(id, diskId, amountAfc, amountMxn); } function getPayment(id) { const stmt = db.prepare("SELECT * FROM payments WHERE id = ?"); return stmt.get(id) || null; } function updatePayment(id, fields) { const allowed = ["status", "mp_preference_id", "mp_payment_id", "tx_hash"]; const sets = []; const values = []; for (const key of allowed) { if (fields[key] !== undefined) { sets.push(`${key} = ?`); values.push(fields[key]); } } if (sets.length === 0) return null; sets.push("updated_at = CURRENT_TIMESTAMP"); values.push(id); const stmt = db.prepare(`UPDATE payments SET ${sets.join(", ")} WHERE id = ?`); return stmt.run(...values); } function getPaymentsByDiskId(diskId) { const stmt = db.prepare("SELECT * FROM payments WHERE disk_id = ? ORDER BY created_at DESC"); return stmt.all(diskId); } function getPaymentByMpPaymentId(mpPaymentId) { const stmt = db.prepare("SELECT * FROM payments WHERE mp_payment_id = ?"); return stmt.get(mpPaymentId) || null; } // Redemptions function createRedemption(id, diskId, amountAfc, prizeType, prizeDetail, deliveryInfo, burnTxHash) { const stmt = db.prepare( "INSERT INTO redemptions (id, disk_id, amount_afc, prize_type, prize_detail, delivery_info, burn_tx_hash) VALUES (?, ?, ?, ?, ?, ?, ?)" ); return stmt.run(id, diskId, amountAfc, prizeType, prizeDetail, deliveryInfo, burnTxHash); } function getRedemption(id) { const stmt = db.prepare("SELECT * FROM redemptions WHERE id = ?"); return stmt.get(id) || null; } function getRedemptionsByDiskId(diskId) { const stmt = db.prepare("SELECT * FROM redemptions WHERE disk_id = ? ORDER BY created_at DESC"); return stmt.all(diskId); } function getPendingRedemptions() { const stmt = db.prepare("SELECT * FROM redemptions WHERE status = 'pending' ORDER BY created_at ASC"); return stmt.all(); } function updateRedemption(id, fields) { const allowed = ["status", "admin_notes"]; const sets = []; const values = []; for (const key of allowed) { if (fields[key] !== undefined) { sets.push(`${key} = ?`); values.push(fields[key]); } } if (sets.length === 0) return null; sets.push("updated_at = CURRENT_TIMESTAMP"); values.push(id); const stmt = db.prepare(`UPDATE redemptions SET ${sets.join(", ")} WHERE id = ?`); return stmt.run(...values); } module.exports = { db, getWallet, createWallet, getContractAddress, setContractAddress, getAllWallets, createPayment, getPayment, updatePayment, getPaymentsByDiskId, getPaymentByMpPaymentId, createRedemption, getRedemption, getRedemptionsByDiskId, getPendingRedemptions, updateRedemption, };