Files
instantadpay/accounts.js
T
martbost f053c1befa InstantAdPay site skeleton: SIWE auth, live chain ledger, join links, buy flow
Zero-dependency Node server on the RM Circle pattern. Chain config lives in
the volume so the same code runs the Amoy dress rehearsal and mainnet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-04 12:25:34 -05:00

50 lines
1.9 KiB
JavaScript

// Site-side member records for InstantAdPay.
// The chain is the source of truth for money, credits, and qualification;
// this module holds only what the chain doesn't: free members who haven't
// touched the chain yet, sponsor attribution before first purchase (spec §4),
// display handles, and join stats. Wiping this file = the clean reset between
// the Amoy dress rehearsal and mainnet launch.
const fs = require('fs');
const path = require('path');
let DATA_DIR = null;
const FILE = () => path.join(DATA_DIR, 'accounts.json');
let db = { v: 1, byAddress: {}, joins: 0 };
function load() {
try { db = JSON.parse(fs.readFileSync(FILE(), 'utf8')); } catch (e) {}
if (!db || db.v !== 1) db = { v: 1, byAddress: {}, joins: 0 };
}
function save() {
try {
const tmp = FILE() + '.tmp';
fs.writeFileSync(tmp, JSON.stringify(db));
fs.renameSync(tmp, FILE());
} catch (e) { console.error('accounts save failed', e.message); }
}
function init(opts) { DATA_DIR = opts.dataDir; load(); }
function get(address) { return db.byAddress[(address || '').toLowerCase()] || null; }
function upsert(address, fields) {
const a = (address || '').toLowerCase();
if (!/^0x[0-9a-f]{40}$/.test(a)) return null;
const cur = db.byAddress[a] || { created: Date.now() };
db.byAddress[a] = Object.assign(cur, fields || {});
save();
return db.byAddress[a];
}
// Sponsor attribution: first touch wins, written on-chain at the member's
// first purchase/activation and permanent from then on.
function attributeSponsor(address, sponsorId) {
const a = (address || '').toLowerCase();
const cur = get(a);
if (cur && cur.sponsorId) return cur.sponsorId; // first touch already set
const id = Number(sponsorId) || 0;
upsert(a, { sponsorId: id });
db.joins += 1; save();
return id;
}
function count() { return Object.keys(db.byAddress).length; }
module.exports = { init, get, upsert, attributeSponsor, count };