import { describe, expect, test } from 'vitest' import * as Campaigns from './Campaigns.js' import * as Events from './Events.js' const account = '0x0000000000000000000000000000000000000001' const other = '0x0000000000000000000000000000000000000002' const share = '0x0000000000000000000000000000000000000003' const vault = '0x0000000000000000000000000000000000000004' test('boundary excludes blocks exactly on the next interval boundary', () => { expect(Events.boundaryQuery(1_788_005_100)).toMatchInlineSnapshot(` " SELECT num, timestamp, (SELECT max(timestamp) FROM blocks) AS indexed_through FROM blocks WHERE timestamp < '2026-08-29 12:05:00.000' ORDER BY timestamp DESC, num DESC LIMIT 1 " `) }) describe('accountEventsQuery', () => { test('bounds history to nonzero external transfers involving tracked accounts', () => { const query = Events.accountEventsQuery({ accounts: [account, other, account], after: { blockNumber: 10, logIndex: 2, transactionIndex: 1 }, earnShare: share, earnVault: vault, throughBlock: 20, }) expect(query).toContain(`lower(receiver) IN ('${account}', '${other}')`) expect(query).toContain( `(lower("from") IN ('${account}', '${other}') OR lower("to") IN ('${account}', '${other}'))`, ) expect(query).toContain('AND lower("from") != lower("to")') expect(query).toContain('AND toUInt256(amount) > 0') expect(query).toContain( 'AND (block_num > 10 OR (block_num = 10 AND (tx_idx > 1 OR (tx_idx = 1 AND log_idx > 2))))', ) expect(query).toContain('LIMIT 10000') }) }) describe('accountDepositsQuery', () => { test('reads distinct positive deposits received by one tracked account', () => { const query = Events.accountDepositsQuery({ account, after: { blockNumber: 10, logIndex: 2, transactionIndex: 1 }, earnVault: vault, throughBlock: 20, }) expect(query).toContain("SELECT DISTINCT 'deposit' AS kind") expect(query).toContain(`AND lower(receiver) = '${account}'`) expect(query).toContain('AND toUInt256(assets) > 0') expect(query).toContain('AND toUInt256("earnShares") > 0') expect(query).not.toContain('token_transfers') expect(query).toContain( 'AND (block_num > 10 OR (block_num = 10 AND (tx_idx > 1 OR (tx_idx = 1 AND log_idx > 2))))', ) }) }) describe('capitalChangesQuery', () => { test('bounds target principal history to distinct nonzero supply-change blocks', () => { const query = Events.capitalChangesQuery({ afterBlock: 10, earnShare: share, throughBlock: 20, }) expect(query).toContain( `AND (lower("from") = '0x0000000000000000000000000000000000000000' OR lower("to") = '0x0000000000000000000000000000000000000000')`, ) expect(query).toContain('AND toUInt256(amount) > 0') expect(query).toContain('AND block_num > 10') expect(query).toContain('AND block_num <= 20') expect(query).toContain('GROUP BY block_num') expect(query).toContain('LIMIT 10000') }) test('retains same-second principal changes on their own bases', () => { const states = [ { assets: 100_000_000n, blockNumber: 10, price: 1_000_000_000n, supply: 100_000_000n, timestamp: 300, }, { assets: 500_000_000n, blockNumber: 11, price: 500_000_000n, supply: 1_000_000_000n, timestamp: 301, }, { assets: 1_100_000_000n, blockNumber: 12, price: 1_000_000_000n, supply: 1_100_000_000n, timestamp: 301, }, { assets: 1_100_000_000n, blockNumber: 13, price: 1_000_000_000n, supply: 1_100_000_000n, timestamp: 600, }, ] const boundaries = [ { blockNumber: 11, timestamp: 301 }, { blockNumber: 12, timestamp: 301 }, ] const checkpoints = [ states[0]!, ...boundaries.map( ({ blockNumber }) => states.find((state) => state.blockNumber === blockNumber)!, ), states[3]!, ] const periods = checkpoints.slice(0, -1).map((opening, index) => { const closing = checkpoints[index + 1]! return { closingValuePerEarnShare: closing.price, contributions: [], elapsedSeconds: closing.timestamp - opening.timestamp, openingAssets: opening.assets, openingEarnShareSupply: opening.supply, openingValuePerEarnShare: opening.price, } }) // The loss and recovery occur on different principal bases, leaving organic growth below the target. expect( Campaigns.targetFunding({ annualRateBps: 1_000, funding: [{ remainder: true, wallet: share }], periods, remainders: [], }).assets, ).toMatchInlineSnapshot(` [ 0n, ] `) expect(periods.map((period) => period.elapsedSeconds)).toStrictEqual([1, 0, 299]) }) })