fix: un dépôt est délivré une fois et retiré, comme en amont

This commit is contained in:
Sylvain Duchesne
2026-08-26 14:11:56 +02:00
parent abfb619c76
commit f6a48a4507
24 changed files with 1486 additions and 176 deletions
+23 -4
View File
@@ -249,12 +249,27 @@ export function makeWallet(quads: Quad[], options: WalletOptions = {}): FakeWall
const anchor = a[2] as string | undefined;
const del = query.match(/DELETE\s+WHERE\s*\{([\s\S]*)\}/i);
if (del) {
const pattern = del[1]!.match(/<([^>]+)>\s+<([^>]+)>\s+\?/);
if (pattern && anchor !== undefined) {
if (del && anchor !== undefined) {
// Two shapes, and the second one REMOVES A DEPOSIT — so the fake has to model it
// rather than answer "nothing matched" and let a consuming test pass on a queue that
// never shrank.
//
// `<s> <p> ?o` — one register slot, what the address/cap writers clear;
// `<s> ?p ?o` — every triple of one subject, which is how a deposit is retired
// (`emulated-verifier/inbox-consume.removeDeposit`): a deposit
// carries `a`/`payload`/`ts` and optionally `from`, so naming the
// predicates would leave some behind.
const boundPredicate = del[1]!.match(/<([^>]+)>\s+<([^>]+)>\s+\?/);
const wholeSubject = del[1]!.match(/<([^>]+)>\s+\?\w+\s+\?\w+/);
const matches = boundPredicate
? (q: Quad) => q.s === boundPredicate[1] && q.p === boundPredicate[2]
: wholeSubject
? (q: Quad) => q.s === wholeSubject[1]
: null;
if (matches) {
for (let i = quads.length - 1; i >= 0; i--) {
const q = quads[i]!;
if (q.g === anchor && q.s === pattern[1] && q.p === pattern[2]) quads.splice(i, 1);
if (q.g === anchor && matches(q)) quads.splice(i, 1);
}
commit(anchor);
}
@@ -333,6 +348,9 @@ export function makeWallet(quads: Quad[], options: WalletOptions = {}): FakeWall
const bySubject = new Map<string, Record<string, string>>();
for (const q of inGraph) {
const rec = bySubject.get(q.s) ?? {};
// `d` is the deposit's own subject, and it is bound because RETIRING a deposit
// names it. A fake that dropped it would hand back deposits nothing can consume.
rec.d = q.s;
if (q.p === `${INBOX}:payload`) rec.payload = q.o;
if (q.p === `${INBOX}:ts`) rec.ts = q.o;
if (q.p === `${INBOX}:from`) rec.from = q.o;
@@ -342,6 +360,7 @@ export function makeWallet(quads: Quad[], options: WalletOptions = {}): FakeWall
.filter((r) => r.payload !== undefined && r.ts !== undefined)
.map((r) => {
const row: Record<string, { value: string }> = {
d: { value: r.d! },
payload: { value: r.payload! },
ts: { value: r.ts! },
};