VanillaJS library for Ethereum blockchain interactions with reactive primitives and utilities for building Ethereum applications
—
Real-time event watching for accounts, chains, blocks, and contract events. Reactive programming support.
Monitor account state changes in real-time.
/**
* Watches for account changes
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchAccount<config extends Config>(
config: config,
parameters: WatchAccountParameters<config>
): WatchAccountReturnType;
interface WatchAccountParameters<config extends Config> {
/** Callback when account changes */
onChange(account: GetAccountReturnType<config>): void;
}
type WatchAccountReturnType = () => void; // Unsubscribe functionUsage Example:
import { watchAccount } from '@wagmi/core'
const unsubscribe = watchAccount(config, {
onChange(account) {
console.log('Account changed:', {
address: account.address,
isConnected: account.isConnected,
status: account.status,
})
if (account.isConnected) {
// User connected - update UI
updateWalletUI(account.address)
} else {
// User disconnected - clear UI
clearWalletUI()
}
},
})
// Cleanup when component unmounts
// unsubscribe()Monitor chain ID changes in real-time.
/**
* Watches for chain ID changes
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchChainId<config extends Config>(
config: config,
parameters: WatchChainIdParameters<config>
): WatchChainIdReturnType;
interface WatchChainIdParameters<config extends Config> {
/** Callback when chain ID changes */
onChange(chainId: GetChainIdReturnType<config>): void;
}
type WatchChainIdReturnType = () => void;Usage Example:
import { watchChainId } from '@wagmi/core'
const unsubscribe = watchChainId(config, {
onChange(chainId) {
const chain = config.chains.find(c => c.id === chainId)
console.log('Switched to chain:', {
id: chainId,
name: chain?.name,
})
// Update app state for new chain
handleChainChange(chainId)
},
})Monitor new blocks in real-time.
/**
* Watches for new block numbers
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchBlockNumber<config extends Config>(
config: config,
parameters: WatchBlockNumberParameters<config>
): WatchBlockNumberReturnType;
interface WatchBlockNumberParameters<config extends Config> {
/** Callback when new block */
onBlockNumber(blockNumber: bigint): void;
/** Callback for errors */
onError?(error: Error): void;
/** Chain ID to watch */
chainId?: config['chains'][number]['id'];
/** Enable polling mode */
poll?: boolean;
/** Polling interval in ms */
pollingInterval?: number;
}
type WatchBlockNumberReturnType = () => void;Usage Example:
import { watchBlockNumber } from '@wagmi/core'
const unsubscribe = watchBlockNumber(config, {
onBlockNumber(blockNumber) {
console.log('New block:', blockNumber.toString())
// Update block-dependent data
refreshBlockData(blockNumber)
},
onError(error) {
console.error('Block watching error:', error)
},
pollingInterval: 12000, // 12 seconds
})Monitor complete block data.
/**
* Watches for new blocks
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchBlocks<config extends Config>(
config: config,
parameters: WatchBlocksParameters<config>
): WatchBlocksReturnType;
interface WatchBlocksParameters<config extends Config> {
/** Callback when new block */
onBlock(block: Block): void;
/** Callback for errors */
onError?(error: Error): void;
/** Chain ID to watch */
chainId?: config['chains'][number]['id'];
/** Include transactions */
includeTransactions?: boolean;
/** Block tag to watch */
blockTag?: 'latest' | 'pending' | 'safe' | 'finalized';
/** Enable polling mode */
poll?: boolean;
/** Polling interval */
pollingInterval?: number;
}
type WatchBlocksReturnType = () => void;
interface Block {
hash: Hash;
number: bigint;
timestamp: bigint;
parentHash: Hash;
gasLimit: bigint;
gasUsed: bigint;
miner: Address;
transactions: Hash[] | Transaction[];
baseFeePerGas?: bigint;
}Monitor smart contract events in real-time.
/**
* Watches for contract events
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchContractEvent<config extends Config>(
config: config,
parameters: WatchContractEventParameters<config>
): WatchContractEventReturnType;
interface WatchContractEventParameters<config extends Config> {
/** Contract address */
address: Address;
/** Contract ABI */
abi: Abi;
/** Event name to watch */
eventName?: string;
/** Event filter arguments */
args?: Record<string, any>;
/** Callback when event occurs */
onLogs(logs: Log[]): void;
/** Callback for errors */
onError?(error: Error): void;
/** Chain ID */
chainId?: config['chains'][number]['id'];
/** Start from block */
fromBlock?: bigint;
/** Enable polling */
poll?: boolean;
/** Polling interval */
pollingInterval?: number;
}
type WatchContractEventReturnType = () => void;
interface Log {
address: Address;
topics: readonly Hex[];
data: Hex;
blockNumber: bigint;
transactionHash: Hash;
transactionIndex: number;
blockHash: Hash;
logIndex: number;
removed: boolean;
}Usage Example:
import { watchContractEvent, decodeEventLog } from '@wagmi/core'
// Watch ERC-20 Transfer events
const unsubscribe = watchContractEvent(config, {
address: '0xA0b86a33E6411c0B7f8C4b5d3e1B9d3e8b4a4e6f',
abi: erc20Abi,
eventName: 'Transfer',
args: {
from: '0x742d35Cc6601C2F3Ac5e5c7A9d16e4e6Be4e6e9e', // Filter by sender
},
onLogs(logs) {
logs.forEach(log => {
try {
const decoded = decodeEventLog({
abi: erc20Abi,
data: log.data,
topics: log.topics,
})
console.log('Transfer event:', {
from: decoded.args.from,
to: decoded.args.to,
value: decoded.args.value.toString(),
blockNumber: log.blockNumber.toString(),
transactionHash: log.transactionHash,
})
} catch (error) {
console.error('Failed to decode log:', error)
}
})
},
onError(error) {
console.error('Event watching error:', error)
},
})
// Watch all events from a contract
const unsubscribeAll = watchContractEvent(config, {
address: '0xContractAddress',
abi: contractAbi,
// No eventName = watch all events
onLogs(logs) {
console.log('Contract events:', logs.length)
},
})Monitor pending transactions in the mempool.
/**
* Watches for pending transactions
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchPendingTransactions<config extends Config>(
config: config,
parameters: WatchPendingTransactionsParameters<config>
): WatchPendingTransactionsReturnType;
interface WatchPendingTransactionsParameters<config extends Config> {
/** Callback when new pending transactions */
onTransactions(hashes: Hash[]): void;
/** Callback for errors */
onError?(error: Error): void;
/** Chain ID to watch */
chainId?: config['chains'][number]['id'];
/** Enable polling */
poll?: boolean;
/** Polling interval */
pollingInterval?: number;
}
type WatchPendingTransactionsReturnType = () => void;Monitor changes to wallet connections.
/**
* Watches for changes to wallet connections
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchConnections<config extends Config>(
config: config,
parameters: WatchConnectionsParameters
): WatchConnectionsReturnType;
interface WatchConnectionsParameters {
/** Callback when connections change */
onChange(
connections: GetConnectionsReturnType,
prevConnections: GetConnectionsReturnType
): void;
}
type WatchConnectionsReturnType = () => void;Monitor changes to available wallet connectors.
/**
* Watches for changes to available connectors
* @param config - Wagmi configuration
* @param parameters - Watch parameters
* @returns Unsubscribe function
*/
function watchConnectors<config extends Config>(
config: config,
parameters: WatchConnectorsParameters<config>
): WatchConnectorsReturnType;
interface WatchConnectorsParameters<config extends Config> {
/** Callback when connectors change */
onChange(
connectors: GetConnectorsReturnType<config>,
prevConnectors: GetConnectorsReturnType<config>
): void;
}
type WatchConnectorsReturnType = () => void;Example of using multiple watchers together:
import {
watchAccount,
watchChainId,
watchBlockNumber,
watchContractEvent
} from '@wagmi/core'
class WalletManager {
private unsubscribers: (() => void)[] = []
start() {
// Watch account changes
this.unsubscribers.push(
watchAccount(config, {
onChange: (account) => {
this.handleAccountChange(account)
},
})
)
// Watch chain changes
this.unsubscribers.push(
watchChainId(config, {
onChange: (chainId) => {
this.handleChainChange(chainId)
},
})
)
// Watch new blocks
this.unsubscribers.push(
watchBlockNumber(config, {
onBlockNumber: (blockNumber) => {
this.handleNewBlock(blockNumber)
},
pollingInterval: 12000,
})
)
}
stop() {
// Cleanup all watchers
this.unsubscribers.forEach(unsubscribe => unsubscribe())
this.unsubscribers = []
}
private handleAccountChange(account: any) {
if (account.isConnected) {
console.log('User connected:', account.address)
this.startUserSpecificWatchers(account.address)
} else {
console.log('User disconnected')
this.stopUserSpecificWatchers()
}
}
private handleChainChange(chainId: number) {
console.log('Chain changed:', chainId)
// Restart chain-specific watchers
this.restartChainWatchers(chainId)
}
private handleNewBlock(blockNumber: bigint) {
console.log('New block:', blockNumber.toString())
// Update any block-dependent UI
}
private startUserSpecificWatchers(userAddress: Address) {
// Watch user's token transfers
this.unsubscribers.push(
watchContractEvent(config, {
address: '0xTokenAddress',
abi: erc20Abi,
eventName: 'Transfer',
args: {
to: userAddress, // Incoming transfers
},
onLogs: (logs) => {
console.log('Incoming token transfers:', logs.length)
},
})
)
}
private stopUserSpecificWatchers() {
// Implementation to stop user-specific watchers
}
private restartChainWatchers(chainId: number) {
// Implementation to restart chain-specific watchers
}
}
// Usage
const walletManager = new WalletManager()
walletManager.start()
// Later, cleanup
// walletManager.stop()If using with React, here's a common pattern:
import { useEffect, useState } from 'react'
import { watchAccount, watchChainId } from '@wagmi/core'
function useWagmiState() {
const [account, setAccount] = useState(null)
const [chainId, setChainId] = useState(null)
useEffect(() => {
const unsubscribeAccount = watchAccount(config, {
onChange: setAccount,
})
const unsubscribeChain = watchChainId(config, {
onChange: setChainId,
})
return () => {
unsubscribeAccount()
unsubscribeChain()
}
}, [])
return { account, chainId }
}
// Usage in component
function MyComponent() {
const { account, chainId } = useWagmiState()
return (
<div>
<div>Account: {account?.address}</div>
<div>Chain: {chainId}</div>
</div>
)
}All watch functions return unsubscribe functions that should be called to clean up listeners and prevent memory leaks.
Install with Tessl CLI
npx tessl i tessl/npm-wagmi--core