Skip to Content
Pulsar EVM Standalone

Using EVM Trackers Standalone

While the Pulsar suite provides a comprehensive solution with a UI (@tuwaio/nova-transactions) and a Zustand-based state store (@tuwaio/pulsar-core), its architecture is modular. This means you can use the low-level trackers (evmTracker, gelatoTracker, safeTracker) from @tuwaio/pulsar-evm directly, without installing or configuring the core state management store.

This is incredibly useful if:

  • You already have your own state management solution (Redux, MobX, Valtio, etc.) and want to integrate only the tracking logic.
  • You need tracking logic on the server-side, where a client-side store is unnecessary.
  • You want maximum control over every stage of the transaction lifecycle.

Why Use evmTracker?

One might ask, “Why do I need evmTracker if I can just use waitForTransactionReceipt from viem?”

While waitForTransactionReceipt is an excellent function, it only solves part of the problem. evmTracker provides a more robust and complete solution out of the box.

FeaturewaitForTransactionReceipt (viem)evmTracker (Pulsar)
Handles RPC Lags❌ No. If called immediately after submission, the RPC node might not see the transaction yet, causing a “transaction not found” error.Yes. Includes a built-in retry mechanism to wait for the transaction to appear in the mempool.
Full Lifecycle🤷‍♂️ Limited. Mainly reacts to transaction completion or replacement.Yes. Provides callbacks for every stage: onInitialize (start), onTxDetailsGot (details received), onFinished (success), onReplaced (replacement), onFailed (error).
Fetches Tx Details❌ No. Does not return full transaction details like nonce, value, etc.Yes. Internally calls getTransaction and passes the full transaction data to the callbacks.
Abstraction LevelLow. Requires the developer to orchestrate the tracking logic themselves.High. Encapsulates the entire tracking process into one convenient async function.

Simply put, evmTracker is a reliable wrapper around viem’s functions that solves common edge cases and significantly simplifies your code.


Trackers Overview

1. EVM Tracker

This is the primary tracker for monitoring standard on-chain transactions in EVM networks. It operates using a transaction hash.

How It Works

evmTracker first tries to fetch transaction details using getTransaction. If the RPC node hasn’t indexed the transaction yet, it will retry several times. Once the details are fetched, it begins waiting for the receipt using waitForTransactionReceipt.

Example Usage

import { evmTracker } from '@tuwaio/pulsar-evm'; import { http, createPublicClient } from 'viem'; import { mainnet } from 'viem/chains'; // You need a viem public client const client = createPublicClient({ chain: mainnet, transport: http(), }); async function trackMyTransaction(txHash) { console.log(`Starting to track transaction: ${txHash}`); await evmTracker({ client, tx: { txKey: txHash, // The transaction hash chainId: 1, // The network ID }, // Callback when transaction details are successfully fetched onTxDetailsGot: (txDetails) => { console.log('Transaction details received:', txDetails); // Here you can update your state to show nonce, gas, etc. }, // Callback when the transaction is successfully mined onFinished: (txDetails, receipt) => { console.log('Transaction finished successfully!', receipt); // Update your state to 'Success' }, // Callback if the transaction was replaced (sped up/cancelled) onReplaced: (replacement) => { console.log('Transaction was replaced:', replacement); // Update your state to 'Replaced' }, // Callback on any error onFailed: (error) => { console.error('Tracking failed:', error); // Update your state to 'Failed' }, // Optional parameters retryCount: 5, // Retry fetching the tx 5 times retryTimeout: 2000, // with a 2-second interval }); }

2. Gelato Tracker

This tracker is designed for monitoring meta-transactions relayed via the Gelato Network. It works with a Gelato taskId.

How It Works

gelatoTracker uses a polling mechanism: it periodically queries the Gelato API (https://api.gelato.digital/tasks/status/...) to get the task status. When the task reaches a terminal state (e.g., ExecSuccess, ExecReverted), the tracker finishes its job.

Example Usage

import { gelatoTracker, GelatoTaskState } from '@tuwaio/pulsar-evm'; async function trackGelatoTask(taskId) { console.log(`Starting to track Gelato task: ${taskId}`); await gelatoTracker({ tx: { txKey: taskId }, // Callback on every response from the Gelato API onIntervalTick: (gelatoStatus) => { console.log('Current task status:', gelatoStatus.task.taskState); // Update your UI to show the current progress }, // Callback on successful execution onSucceed: (gelatoStatus) => { console.log('Gelato task executed successfully:', gelatoStatus); // Update your state to 'Success' }, // Callback on failure onFailed: (gelatoStatus) => { console.error('Gelato task failed:', gelatoStatus); // Update your state to 'Failed' }, pollingInterval: 5000, // Poll the API every 5 seconds }); }

3. Safe Tracker

Used for tracking transactions in Safe (formerly Gnosis Safe) multisig wallets. It operates using a safeTxHash.

How It Works

Similar to gelatoTracker, it uses polling, but this time against the Safe Transaction Service API. This tracker is also smart enough to detect if the current transaction was replaced by another one with the same nonce.

Example Usage

import { safeTracker } from '@tuwaio/pulsar-evm'; async function trackSafeTransaction(safeTxHash, chainId, safeAddress) { console.log(`Tracking Safe transaction: ${safeTxHash}`); await safeTracker({ tx: { txKey: safeTxHash, chainId: chainId, from: safeAddress, }, onIntervalTick: (safeStatus) => { console.log('Transaction is awaiting signatures...', safeStatus); }, onSucceed: (safeStatus) => { console.log('Safe transaction executed successfully!', safeStatus); }, onFailed: (safeStatus) => { console.error('Safe transaction failed.', safeStatus); }, onReplaced: (response) => { console.warn(`Transaction was replaced by: ${response.replacedHash}`); }, }); }

Helper Functions

The @tuwaio/pulsar-evm package also exports several utilities that simplify working with the trackers. Several of them:

checkTransactionsTracker

This is a key routing function. After you submit a transaction, you get back a key (ActionTxKey). This function helps you determine which tracker to use for that key based on its structure or the wallet type.

import { checkTransactionsTracker, TransactionTracker, isGelatoTxKey } from '@tuwaio/pulsar-evm'; function determineTracker(actionTxKey, walletType) { const { tracker, txKey } = checkTransactionsTracker(actionTxKey, walletType); switch (tracker) { case TransactionTracker.EVM: console.log(`Using EVM tracker for key: ${txKey}`); // trackMyTransaction(txKey); break; case TransactionTracker.GELATO: console.log(`Using Gelato tracker for key: ${txKey}`); // trackGelatoTask(txKey); break; case TransactionTracker.SAFE: console.log(`Using Safe tracker for key: ${txKey}`); // trackSafeTransaction(txKey, ...); break; } } // Example 1: Regular hash determineTracker('0x...', 'metaMask'); // Output: Using EVM tracker for key: 0x... // Example 2: Key from Gelato determineTracker({ taskId: '0x123...' }, 'metaMask'); // Output: Using Gelato tracker for key: 0x123... // Example 3: Hash from Safe determineTracker('0xabc...', 'safe'); // Output: Using Safe tracker for key: 0xabc...

checkChainForTx

A simple but important utility that checks if the user is on the correct network and, if not, prompts them to switch using your wagmi configuration.

import { checkChainForTx } from '@tuwaio/pulsar-evm'; import { config } from './config'; // Your wagmi config async function safeSendTransaction() { const targetChainId = 1; // Mainnet try { // This function will throw an error if the chain is wrong, // prompting the user to switch. await checkChainForTx(targetChainId, config); console.log('Network is correct, sending transaction...'); // ...transaction sending logic } catch (error) { console.error(error.message); // "User rejected chain switch..." } }

Safe Constants

You don’t need to manually find and paste URLs for the Safe API. The library exports them for you:

  • SafeTransactionServiceUrls: A map of chain IDs to their transaction service API URLs.
  • gnosisSafeLinksHelper: A map of chain IDs to the Safe web app base URL for building links.
Last updated on