Skip to content

feat: implement event listeners#155

Open
FarajiOranj wants to merge 1 commit into
ryangoree:mainfrom
FarajiOranj:feat/event-listeners
Open

feat: implement event listeners#155
FarajiOranj wants to merge 1 commit into
ryangoree:mainfrom
FarajiOranj:feat/event-listeners

Conversation

@FarajiOranj

Copy link
Copy Markdown

Summary

Closes #121.

Adds event listeners: callbacks that fire as new contract events, blocks, or
signer changes are observed. Each listener polls the underlying adapter on an
interval (as suggested in the issue) and returns a function that stops it.

API

// Contract events (the main ask), e.g. to update a UI on each Transfer.
const unsubscribe = contract.onEvent("Transfer", (events) => {
  for (const event of events) console.log(event.args);
});
unsubscribe();

// Client-level equivalents:
drift.onEvent({ abi, address, event: "Transfer" }, (events) => {/* ... */});
drift.onBlock((blockNumber) => {/* ... */});          // block created
drift.onSignerChange((address) => {/* ... */});       // signer changed
  • Listeners are future-only by default; pass fromBlock to also receive
    historical events on the first poll. contract.onEvent applies the contract's
    epochBlock the same way getEvents does.
  • pollingInterval and onError are configurable per listener; the interval
    defaults to the adapter's pollingInterval, then 4000ms.
  • No changes to Client/createDrift wiring were needed.

Implementation notes

  • Listeners poll the adapter directly (not the client's cached getEvents),
    since the cache is keyed and would return stale data to a live listener.
  • Polling uses a recursive setTimeout (createPoller) so polls never overlap,
    and a guard prevents any callback from firing after unsubscribe(), even
    mid-poll.

Tests

New createPoller.test.ts and eventListeners.test.ts (block/event/signer
listeners, fromBlock history, in-flight-unsubscribe, throwing-onError
resilience) plus a Contract.onEvent + epochBlock test. Also updated the
README and added a changeset.

Known limitation / follow-ups

  • onEvent polls forward by block number and does not handle chain
    reorganizations, so events in blocks re-mined after a reorg may be missed (as
    scoped by the issue's "initial implementation"). This is documented on the
    methods. A reorg-aware mode (confirmations / re-scan window with dedup) would
    make a good follow-up, as would wallet-native signer changed events
    (e.g. accountsChanged) instead of polling.

Add polling-based event listeners that fire callbacks as new contract
events, blocks, or signer changes are observed:

- `client.onEvent` / `contract.onEvent` fire with new logs as matching
  contract events are emitted (future-only by default; pass `fromBlock`
  for history, and `contract.onEvent` applies `epochBlock`).
- `client.onBlock` fires with the latest block number as blocks are created.
- `client.onSignerChange` fires when the signer changes.

Each listener polls the adapter directly (bypassing the client cache) on a
configurable interval via a shared `createPoller` utility, and returns a
function that stops it. A guard prevents callbacks firing after unsubscribe.
@changeset-bot

changeset-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fbd5956

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@gud/drift Minor
@gud/drift-ethers-v5 Minor
@gud/drift-ethers Minor
@gud/drift-viem Minor
@gud/drift-web3 Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement event listeners

1 participant