Paid-sale workflow
This commit is contained in:
@@ -4,6 +4,7 @@ import { ADDITIONAL_MARKET_FEE } from '../../shared/market.ts';
|
||||
import { parseAtomicXmr } from '../../shared/xmr-amount.ts';
|
||||
import { allocateXmrSale } from '../../shared/xmr-pricing.ts';
|
||||
import { validateXmrAddress } from './xmr.ts';
|
||||
import { replayReservedSale } from './sale-rehearsal.ts';
|
||||
|
||||
/** Codes only: never attach customer IDs, payloads, SQL errors or addresses to operational diagnostics. */
|
||||
export class CustodyIntegrityError extends Error {
|
||||
@@ -96,6 +97,30 @@ async function checkOrders(client: PoolClient, rows: OrderRow[]) {
|
||||
expectJournal(posting, `settle:${o.id}`, 'mock-sale-settlement', o.status === 'settled' ? [d(account, o.grossAtomicXmr),
|
||||
c(`customer:${o.seller}:available`, o.sellerAtomicXmr), c(`author:${o.authorAddress}`, o.authorAtomicXmr),
|
||||
c(o.hostFeeAddress ? `revenue:host:${o.hostFeeAddress}` : 'revenue:host', o.hostAtomicXmr)] : null);
|
||||
const evidenceRows = await client.query('SELECT key,value FROM wk_custody.custody_meta WHERE key=ANY($1::text[])',
|
||||
[[`sale-rehearsal-binding:${o.id}`, `sale-rehearsal-observation:${o.id}`, `sale-rehearsal-terminal:${o.id}`]]);
|
||||
if (evidenceRows.rowCount) {
|
||||
try {
|
||||
const records = new Map<string, string>(evidenceRows.rows.map(r => [r.key, r.value]));
|
||||
const binding = records.get(`sale-rehearsal-binding:${o.id}`);
|
||||
const identity = await client.query("SELECT value FROM wk_custody.custody_meta WHERE key='identity'");
|
||||
const verify = (key: string) => {
|
||||
const evidence = JSON.parse(records.get(key) ?? '');
|
||||
const replay = replayReservedSale({ ...o, status: 'awaiting-lock' }, JSON.parse(identity.rows[0].value).id, evidence.input, l.feeBps);
|
||||
if (evidence.version !== 1 || evidence.binding !== binding || replay.binding !== binding ||
|
||||
replay.stateRoot !== evidence.stateRoot) fail('sale-rehearsal-evidence-mismatch');
|
||||
return replay;
|
||||
};
|
||||
verify(`sale-rehearsal-observation:${o.id}`);
|
||||
if (o.status === 'awaiting-lock') {
|
||||
if (records.has(`sale-rehearsal-terminal:${o.id}`)) fail('sale-rehearsal-evidence-mismatch');
|
||||
} else {
|
||||
const replay = verify(`sale-rehearsal-terminal:${o.id}`);
|
||||
if (replay.decision.action !== (o.status === 'settled' ? 'settle' : 'refund') ||
|
||||
(o.status === 'settled' && row.box_data !== `fixture:${replay.stateRoot}`)) fail('sale-rehearsal-evidence-mismatch');
|
||||
}
|
||||
} catch { fail('sale-rehearsal-evidence-mismatch'); }
|
||||
}
|
||||
}
|
||||
await validateWallets(wallets);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user