/** @module-tag localnet */ import { sendTransactionSync } from 'viem/actions' import { Actions } from 'viem/tempo' import * as Runtime from '../../../test/runtime.js' import * as TestTempo from '../../../test/Tempo.js' import * as Events from './Events.js' import * as Tidx from '../Tidx.js' import * as Value from '../Value.js' describe.runIf(Runtime.get().mode === 'localnet')('boundary', () => { test('waits until the indexer has crossed the requested boundary', async () => { const runtime = Runtime.get() const tidx = Tidx.getClient({ chainId: runtime.chainId, tidx: { baseUrl: runtime.tidxUrl }, }) const head = await tidx.fetch({ query: 'SELECT max(timestamp) AS timestamp FROM blocks' }) const indexedAt = Value.toIsoDateTime(head.rows[0]?.['timestamp']) if (!indexedAt) throw new Error('Local TIDX did not return its indexed head.') const timestamp = Math.floor(Date.parse(indexedAt) / 1_000) await new Promise((resolve) => setTimeout(resolve, Math.max(timestamp * 1_000 + 1_000 - Date.now(), 0)), ) await Actions.faucet.fundSync(TestTempo.client, { account: TestTempo.accounts[4], timeout: 60_000, }) await expect .poll( () => Events.boundary(tidx, timestamp + 1) .then((boundary) => boundary.timestamp) .catch(() => timestamp + 1), { timeout: 30_000 }, ) .toBeLessThan(timestamp + 1) const chainHead = await TestTempo.client.getBlock() const unavailableTimestamp = Number(chainHead.timestamp) + 1 await expect(Events.boundary(tidx, unavailableTimestamp)).rejects.toThrow( `TIDX has not indexed reward boundary ${unavailableTimestamp}.`, ) }) }) describe.runIf(Runtime.get().mode === 'localnet')('accountEventPages', () => { test('reads relevant account pages and distinct capital changes from TIDX', async () => { const runtime = Runtime.get() const tidx = Tidx.getClient({ chainId: runtime.chainId, tidx: { baseUrl: runtime.tidxUrl }, }) const account = TestTempo.accounts[0] const client = TestTempo.getClient({ account }) const { token } = await Actions.token.createSync(client, { currency: 'USD', name: 'Reward Principal', symbol: 'PRINCIPAL', }) const opening = await sendTransactionSync(client, { calls: [ Actions.token.grantRoles.call(client, { role: 'issuer', to: account.address, token }), Actions.token.mint.call(client, { amount: 1_000n, to: account.address, token }), ], }) const minted = await Actions.token.mintSync(client, { amount: 100n, to: account.address, token, }) const burned = await Actions.token.burnSync(client, { amount: 100n, token }) const throughBlock = Number(burned.receipt.blockNumber) await expect .poll( async () => { const changes = await Events.capitalChanges(tidx, { afterBlock: Number(opening.blockNumber), earnShare: token, throughBlock, }) return changes.map((entry) => entry.blockNumber) }, { timeout: 30_000 }, ) .toStrictEqual([Number(minted.receipt.blockNumber), throughBlock]) const pages = Events.accountEventPages(tidx, { after: { blockNumber: Number(opening.blockNumber), logIndex: Number.MAX_SAFE_INTEGER, transactionIndex: Number.MAX_SAFE_INTEGER, }, accounts: [account.address], earnShare: token, earnVault: token, throughBlock, }) const events = (await Array.fromAsync(pages)).flat() expect( events.map((event) => ({ blockNumber: event.cursor.blockNumber, kind: event.kind, })), ).toStrictEqual([ { blockNumber: Number(minted.receipt.blockNumber), kind: 'transfer' }, { blockNumber: throughBlock, kind: 'transfer' }, ]) }) })