Skip to content
DocsIndexing and receipts

DocsHow it works

Indexing and receipts

History is found through Envio HyperSync and proven from receipts over RPC. Coverage is always stated.

Nuntio keeps two jobs apart: finding what happened, and proving it.

#Finding: Envio HyperSync

The app asks Envio HyperSync for every Paid event from every deployment of the accounts it indexes: Nuntio's main account across its whole history of deployments, on testnet the Sandbox, and every team account. A redeploy appends a deployment to the list, so older payments never disappear.

Teams are not on a list. The same scan reads the team factory's own TeamCreated events in block order and keeps a Paid only from a listed account or a team the factory announced, so a team is covered from the block it was made in. A receipt from a team the scan has not reached yet is read after the factory confirms the account is one of its teams.

The scan is paginated towards the chain's finalized head, checkpointed, and bounded per request and per minute. Later page views only ask for blocks after the checkpoint. The index knows which events exist. It never supplies an amount to a screen.

#Proving: Monad RPC

Every payment shown is read again from its own transaction receipt over RPC, and decoded from the account's own Paid event. That is where the amount, the payee and the service come from. A payment the index found but the receipt does not confirm is shown as verifying, without an amount, and is never dropped.

#The amount is measured

Paid.amount is what the account measured leaving it: its AUSD balance before the transfer minus its balance after. It is never a figure a caller supplied. In the receipts Nuntio has checked, it equals the AUSD token's own Transfer value in the same transaction.

#Coverage is part of every answer

Each history response carries a coverage state:

CoverageMeaning
syncedThe scan reached the head. An empty list means nothing happened
partialThe scan has not finished, or the account is not one the index scans. The page says how far it got
unconfiguredNo index is configured on this deployment
unavailableThe index could not be asked

Only synced with an empty list is shown as "nothing has happened". Anything else is shown as "we do not know yet", never as an empty history.

#Pairing a settlement with its request

On VERSION 2 contracts, a payment made through paySettled emits the account's Paid and the queue's RequestSettled in the same transaction. A reader pairs them on (RequestSettled.spender, intentKey) == (Paid.spender, Paid.idempotencyKey) in that transaction, from the account and its bound queue. The spender is part of the match because paySettled can be called by anyone, so one transaction can carry two payments under the same key value.

RequestSettled.amount is the approved amount. Only Paid.amount is measured, so a receipt always takes the amount from Paid.

#What is not indexed yet

  • A HyperIndex projection is planned and not built. Today all history reads go through HyperSync and RPC.

#/stats

The public stats pages, nuntio.finance/stats and testnet.nuntio.finance/stats, count from the chain through their own event index: teams created through the factory, spending policies, payments settled, payments made by agents on their own, and payments held for an owner. They are rendered on request, never frozen at build time, and the reads are cached for about a minute.

On testnet, activity from our own load test on Monad testnet, run by the Nuntio team, is counted apart from real use in its own panel, "Load test, run by the Nuntio team", and listed transaction by transaction at testnet.nuntio.finance/stats/load-test. Teams from that load test are known by their factory numbers, so nothing they did can reach the real-use figures. Mainnet has no load-test panel.

#A provisional receipt is provisional

Monad's latest block is speculative. Before treating a payment as irreversible, check that its block is at or below the finalized block. The agent worker counts a payment as final only once its block is final.