Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/api/src/indexer/vault-contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,15 @@ export async function classifyVaults(env: Env): Promise<Record<string, unknown>>

// Outbound SWEEPS are ALSO a crack — a sweep moves EVERYTHING out of the address at once (no per-asset
// row), so any outbound sweep from a funded vault empties it. Merge with sends; earliest wins.
// Keep selected vaults outermost: scanning sweeps first makes SQLite probe every selected rowid
// for each sweep. A 1,000-vault production batch read 1.5M rows instead of 3k indexed probes.
const sweepRows =
(
await env.CORE_DB.prepare(
`WITH ${selected}
SELECT source.address,sweep.block_time,destination.address destination
FROM selected vault
JOIN sweeps sweep ON sweep.source_id=vault.btc_address_id
CROSS JOIN sweeps sweep INDEXED BY idx_sweeps_source ON sweep.source_id=vault.btc_address_id
JOIN address_dictionary source ON source.address_id=sweep.source_id
JOIN address_dictionary destination ON destination.address_id=sweep.destination_id
ORDER BY sweep.source_id,sweep.block_time`,
Expand Down
6 changes: 4 additions & 2 deletions apps/api/tests/vault-contents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ test("vault classification derives compact identities, contents, and crack recip
WHERE destination_address_id IS NOT NULL;
CREATE TABLE balances(address_id INTEGER,asset_id INTEGER,quantity TEXT,quantity_normalized TEXT);
CREATE TABLE sweeps(source_id INTEGER,destination_id INTEGER,block_time INTEGER);
CREATE INDEX idx_sweeps_source ON sweeps(source_id);
INSERT INTO address_dictionary VALUES
(10,'vault-single'),(11,'vault-multi'),(12,'vault-foreign'),(20,'funder'),(30,'cracker'),(40,'contract');
INSERT INTO asset_dictionary VALUES(1,'XCP'),(2,'CARD'),(3,'OTHER');
Expand All @@ -69,6 +70,7 @@ test("vault classification derives compact identities, contents, and crack recip
(4,20,11,NULL,NULL,3,'100000000','1',1,101),
(5,20,99,NULL,10,2,'100000000','1',1,110),
(6,99,99,10,30,2,'100000000','1',3,190);
INSERT INTO sweeps VALUES(11,30,150),(12,30,160),(20,30,170);
`);
const result = await classifyVaults({ CORE_DB: d1(sqlite) } as never);
assert.equal(result.classified, 3);
Expand Down Expand Up @@ -105,8 +107,8 @@ test("vault classification derives compact identities, contents, and crack recip
funded: 1,
contents_asset: null,
contents_qty: null,
cracked_at: null,
cracker: null,
cracked_at: 150,
cracker: "cracker",
},
{
token_id: "3",
Expand Down
Loading