Add persistent cross-game player bank (Refs #146)

This commit is contained in:
2026-10-12 20:21:58 -04:00
parent bcd3b99ee4
commit e071e5b574
14 changed files with 866 additions and 1 deletions
+27
View File
@@ -0,0 +1,27 @@
import type Database from 'better-sqlite3';
/** No match/server foreign keys: money and idempotency outlive fleet/history cleanup. */
export function migrateBank(handle: Database.Database): void {
handle.exec(`
CREATE TABLE IF NOT EXISTS bank_accounts (
guid TEXT PRIMARY KEY,
balance INTEGER NOT NULL DEFAULT 0 CHECK (typeof(balance) = 'integer' AND balance BETWEEN 0 AND 1000000)
);
CREATE TABLE IF NOT EXISTS bank_requests (
server TEXT NOT NULL, request_id TEXT NOT NULL, guid TEXT NOT NULL,
fingerprint TEXT NOT NULL, operation TEXT NOT NULL CHECK (operation IN ('deposit','withdraw')),
match_id INTEGER, amount INTEGER NOT NULL DEFAULT 0,
state TEXT NOT NULL CHECK (state IN ('prepared','committed','cancelled','rejected')),
result TEXT NOT NULL, created_at TEXT NOT NULL, settled_at TEXT,
PRIMARY KEY(server, request_id)
);
CREATE UNIQUE INDEX IF NOT EXISTS bank_pending_guid ON bank_requests(guid) WHERE state = 'prepared';
CREATE TABLE IF NOT EXISTS bank_ledger (
id INTEGER PRIMARY KEY AUTOINCREMENT, guid TEXT NOT NULL,
server TEXT NOT NULL, request_id TEXT NOT NULL, match_id INTEGER,
amount INTEGER NOT NULL, balance INTEGER NOT NULL, created_at TEXT NOT NULL,
UNIQUE(server, request_id)
);
CREATE INDEX IF NOT EXISTS bank_ledger_guid ON bank_ledger(guid, id DESC);
`);
}
+3 -1
View File
@@ -18,6 +18,7 @@ import { migrateAuthSchema, migrateSuperViewerRole } from '../auth/schema.js';
import { migrateGameFileSchema } from '../game-files/schema.js';
import { migrateLeaderboardReports } from './leaderboard-reports.js';
import { migratePlayerScoreTotal } from './player-score-total.js';
import { migrateBank } from './bank.js';
import type { Migration } from './migration-runner.js';
// Append only: never renumber entries or change an applied migration to add an
@@ -109,7 +110,8 @@ export const migrations: readonly Migration[] = [
version: 19,
name: 'cumulative player score per match',
run: migratePlayerScoreTotal
}
},
{ version: 20, name: 'persistent player bank and transfer ledger', run: migrateBank }
];
export const databaseVersion = migrations.length;