Skip to Content
Pulsar EVM Standalone

Using EVM Trackers Standalone

While the Pulsar suite offers a full stack solution with a UI (@tuwaio/nova-transactions) and a Zustand-based state store (@tuwaio/pulsar-core), its architecture remains modular and flexible. This means you can utilize the low-level trackers (evmTracker, gelatoFetcher, safeFetcher) from @tuwaio/pulsar-evm directly, without installing or configuring the complete state management store.

This flexibility is ideal if:

  • You already have your own state management solution (Redux, MobX, Valtio, etc.) and want to integrate only the transaction tracking logic.
  • You require tracking on the server-side, where a client-centric store isn’t necessary.
  • You desire granular control over each stage of a transaction’s lifecycle for custom workflows.

Why Use evmTracker?

Some might ask, “Why should I use evmTracker when I can just call waitForTransactionReceipt from viem?” While waitForTransactionReceipt is effective, it only addresses part of the problem. evmTracker provides a more robust, comprehensive, and ready-to-use solution.

FeaturewaitForTransactionReceipt (viem)evmTracker (Pulsar)
Handles RPC Lags❌ No. If called immediately after submission, the RPC node might not have indexed the transaction yet, causing errors.Yes. Built-in retry mechanism to wait for the transaction to appear in the mempool, mitigating RPC delays.
Full Lifecycle Support🤷‍♂️ Limited. Mainly reacts once the transaction is confirmed or replaced.Yes. Provides callbacks for each stage: initialization, details fetched, mined, replaced, failed, etc.
Fetches Full Tx Details❌ No. Doesn’t return complete info such as nonce, value, etc.Yes. Calls getTransaction internally, passing all transaction details to callbacks.
Abstraction LevelLow. You must manage the tracking states manually.High. Encapsulates the entire process into a single, convenient async function, simplifying implementation.

In essence, evmTracker is a reliable wrapper around viem functions, addressing common edge cases and significantly reducing manual effort.


Trackers Overview

1. EVM Tracker

This is the primary tracker for monitoring standard transactions on EVM-compatible chains, identified via transaction hash.

How It Works

evmTracker initially fetches transaction details using getTransaction. If unavailable (due to RPC indexing delay), it retries several times. Once the details are available, it actively waits for the transaction receipt using waitForTransactionReceipt.

Example Usage

import { evmTracker } from '@tuwaio/pulsar-evm'; import { mainnet } from 'viem/chains'; async function trackMyTransaction(txHash) { console.log(`Starting to track transaction: ${txHash}`); await evmTracker({ chains: [mainnet], // Chains array for internal client creation tx: { txKey: txHash, // Transaction hash chainId: 1, // Chain ID (e.g., 1 for Ethereum Mainnet) }, onTxDetailsFetched: (txDetails) => { console.log('Transaction details received:', txDetails); // Update your UI/state with nonce, gas, etc. }, onSuccess: (txDetails, receipt) => { console.log('Transaction mined!', receipt); if (receipt.status === 'success') { // Update status as successful } else { // Update status as failed } }, onReplaced: (replacement) => { console.log('Transaction was replaced:', replacement); // Handle replacement logic }, onFailure: (error) => { console.error('Tracking failed:', error); // Handle errors }, }); }

2. Gelato & Safe Fetchers

For polling-based tracking, especially for Gelato and Safe multisig transactions, we expose fetcher functions. You can integrate these directly with Pulsar’s initializePollingTracker or your custom polling setup.

Example for Handling Gelato & Safe Transactions

import { initializePollingTracker } from '@tuwaio/pulsar-core'; import { gelatoFetcher, safeFetcher } from '@tuwaio/pulsar-evm'; // Tracking a Gelato relay task async function trackGelatoTask(taskId) { await initializePollingTracker({ tx: { txKey: taskId }, fetcher: gelatoFetcher, onSuccess: (status) => { console.log('Gelato task succeeded:', status); }, onFailure: (status) => { console.error('Gelato task failed:', status); }, }); } // Tracking a Safe multisig transaction async function trackSafeTx(safeTxHash, chainId, fromAddress) { await initializePollingTracker({ tx: { txKey: safeTxHash, chainId, from: fromAddress }, fetcher: safeFetcher, onSuccess: (status) => { console.log('Safe transaction succeeded:', status); }, onFailure: (status) => { console.error('Safe transaction failed:', status); }, onReplaced: (replacement) => { console.warn('Transaction was replaced:', replacement); }, }); }

Helper Functions

Additionally, the package provides several utilities for managing transaction states and chain interactions:

checkTransactionsTracker

Determines which tracker is suitable based on a transaction key.

import { checkTransactionsTracker } from '@tuwaio/pulsar-evm'; const { tracker, txKey } = checkTransactionsTracker('0xabc...', 'injected'); // tracker -> 'ethereum' or relevant tracker type // txKey -> same as input or derived key

checkChainForTx

Verifies if the user is connected to the correct network and prompts for a switch if necessary.

import { checkChainForTx } from '@tuwaio/pulsar-evm'; import { wagmiConfig } from './config'; async function ensureCorrectNetwork(chainId: number | string) { try { await checkChainForTx(chainId, wagmiConfig); console.log('Network is correct, proceeding...'); // Proceed with your transaction or other logic here } catch (error) { console.error(error.message); // Handle error, e.g., showing a message to the user about network mismatch } }

Feel free to ask for further customization examples or clarifications on implementing specific trackers or utilities!

Last updated on