npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@evmlord/multicall-sdk

v2.0.1

Published

A lightweight library to batch multiple calls via a single eth_call using Multicall3 on 285+ chains.

Readme

@evmlord/multicall-sdk – Batch smart-contract calls on Ethereum & EVM networks

A lightweight TypeScript/JavaScript library built on ethers v6 for DeFi dashboards, on-chain analytics and gas-optimised dApps.

npm @evmlord/multicall-sdk latest version CI Build Status MIT license for @evmlord/multicall-sdk Weekly npm downloads for @evmlord/multicall-sdk TypeScript types included Minified bundle size


🚀 Why @evmlord/multicall-sdk?

  • Gas & RPC Optimized
    Combine dozens of eth_call into one multicall, slashing HTTP/WebSocket overhead and minimizing latency.

  • Fully Typed
    Written in TypeScript with built-in declarations—autocomplete your batch calls, interfaces, and return values.

  • Failure-Tolerant
    Gracefully handle individual call failures (allowFailure) without aborting the entire batch.

  • Rich Decoding
    Automatically unpack tuples, structs, arrays and custom errors into plain JS objects & arrays—no manual unpacking.

  • EVM & DeFi Focused
    Supports Multicall3, Multicall2 and on-chain block helpers (getBlockNumber, getEthBalance, etc.) across 280+ networks.


🔧 Installation (Node .js / TypeScript)

# via yarn
yarn add @evmlord/multicall-sdk

# or npm
npm install @evmlord/multicall-sdk

📖 Quick-Start Example with ethers v6

287 EVM-compatible networks are supported by default, and custom networks can be supported by providing a deployed Multicall contract address.

👉 See the complete list in SUPPORTED_NETWORKS.md.

1. Create your Multicall client

import { JsonRpcProvider, WebSocketProvider } from "ethers";
import { Multicall } from "@evmlord/multicall-sdk";

// 1) HTTP RPC URL
const mc1 = new Multicall({
  provider: "https://mainnet.infura.io/v3/…",
  chainId: 1,
});

// 2) Browser/EIP-1193 (e.g. MetaMask)
const mc2 = new Multicall({
  provider: window.ethereum, // auto-wrapped
  multicallAddress: "0x…", // override default if deployed elsewhere
});

// 3) Already-constructed ethers Provider
const ws = new WebSocketProvider("wss://…");
const mc3 = new Multicall({ provider: ws, chainId: 5 });

// 4) Custom signer for writing txs
const signer = wallet.connect(provider);
const mc4 = new Multicall({
  provider: provider,
  signer: signer,
  chainId: 56,
});

2. Batch simple eth_calls

import erc20Abi from "./abi/ERC20.json";
import { Call } from "@evmlord/multicall-abi";

const token = new ethers.Contract("0x…ERC20", erc20Abi, provider);

// Prepare calls
const calls: Call[] = [
  { contract: token, functionFragment: "balanceOf", args: ["0xYourAddress1"] },
  { contract: token, functionFragment: "balanceOf", args: ["0xYourAddress2"] },
  { contract: token, functionFragment: "balanceOf", args: ["0xYourAddress3"] },
  { contract: token, functionFragment: "totalSupply", args: [] },
];

// Execute a single eth_call via Multicall
const { blockNumber, returnData } = await mc1.aggregate(calls);

// Decode your results
const [balance1] = token.interface.decodeFunctionResult(
  "balanceOf",
  returnData[0]
);
const [balance2] = token.interface.decodeFunctionResult(
  "balanceOf",
  returnData[1]
);
const [balance3] = token.interface.decodeFunctionResult(
  "balanceOf",
  returnData[2]
);
const [supply] = token.interface.decodeFunctionResult(
  "totalSupply",
  returnData[3]
);

console.log({
  blockNumber,
  balance1,
  balance2,
  balance3,
  supply,
});

/* 
 console:
{
  blockNumber: 55038412n,
  balance1: 76950775000000000000000n,
  balance2: 0n,
  balance3: 1583902570428472973924450219389n,
  supply: 10000000000000000000000000000000000000000000n
} 
*/

⚙️ API Reference

Batch Methods

| Method | Description | | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | aggregate(calls: Call[]) | Reverts on any failing call. Returns { blockNumber, returnData: string[] }. | | tryAggregate(requireSuccess, calls: Call[]) | Optionally continue on failed calls. Returns Array<{ success: boolean, returnData: string }> | | blockAndAggregate(calls: Call[]) | Alias for tryBlockAndAggregate(true, calls). Returns { blockNumber, blockHash, returnData }. | | tryBlockAndAggregate(requireSuccess, calls: Call[]) | Same as tryAggregate but also provides full block info plus per-call success flags. | | aggregate3(calls: Call3[]) | Multicall 3 style: each call has an allowFailure flag, and return values are auto-decoded to JS tuples/structs. | | aggregate3Value(calls: Call3Value[]) | Like aggregate3, but supports per-call native ETH value and automatically sums msg.value. | | sendAggregate3Value(calls: Call3Value[], overrides: Overrides) | Like aggregate3Value, but for real on-chain writes, accepts optional Ethers overrides (gasLimit, gasPrice, etc) and returns TransactionResponse, which you can .wait() on. |


// ── aggregate3 example ─────────────────────────────────────────
// call two view methods in one batch, but let one of them fail
const calls3: Call3[] = [
    {
      contract: token,
      functionFragment: "nonExistedProperty", // this will throw
      args: [],
      allowFailure: true,
    },
    {
      contract: token,
      functionFragment: "balanceOf",
      args: ["0x5500..."], // wallet address here
      allowFailure: true,
    },
  ];

  const results3 = await mc1.aggregate3(calls3);

  console.log({ results3 });

  /*
console:
{
  results3: [
    [ false, 'Revert: (unrecognized revert: 0x…)' ],
    [ true, 76950775000000000000000n ]
  ]
}
 */

// ── aggregate3Value example ────────────────────────────────────
// imagine a payable helper that charges a small fee per call
const helper = new ethers.Contract(
  "0x…EHelperContract",   // your helper address
  HelperABI,                 //  your ABI
  provider
)

// send 0.001 ETH with each call to fetch some on-chain data
const fee  = 0.001n * 10n**18n  // 0.001 ETH in wei as bigint
const calls3Value: Call3Value[] = [
  {
    contract:        helper,
    functionFragment:'getSomeData',
    args:            [ user ],
    allowFailure:    false,
    value:           fee
  },
  {
    contract:        helper,
    functionFragment:'getOtherData',
    args:            [ user, 42 ],
    allowFailure:    true,
    value:           fee
  }
]

const results3Value = await mc1.aggregate3Value(calls3Value)
// returns Array<[success: boolean, data]>
{
  const [ok, getSomeData] = results3Value[0];
  if (ok) {
  console.log('getSomeData →', getSomeData)
  }

}
 {
    const [ok, getOtherData] = results3Value[1];
    if (ok) {
      console.log('getOtherData →', getOtherData)
    }
  }

What’s happening here?

  • aggregate3 You pass allowFailure: true on any call that might revert—failed calls return [false, rawHex] while successes decode normally.

  • aggregate3Value Each call can carry its own ETH payment (value), and the SDK automatically sums them into one msg.value for the batch. Any call marked allowFailure: true won’t abort the entire batch if it reverts.

Sending State-Changing Multicall Transactions

Up until now we’ve only covered the “view” methods (aggregate, tryAggregate, aggregate3, etc). If you need to batch together state-changing calls (optionally with ETH attached) into a single on-chain tx, you can use sendAggregate3Value:

import { Multicall, Call3Value, ChainId } from "@evmlord/multicall-sdk";
import { ethers } from "ethers";

// 1) Create a signer-backed Multicall instance
const provider = new ethers.JsonRpcProvider("https://rpc.ankr.com/eth");
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

const multicall = new Multicall({
  provider,
  chainId: ChainId.MAINNET,
  signer: wallet, // <- needed for txs
});

// 2) Prepare your payable calls
//    each call3Value: { contract, functionFragment, args, allowFailure, value }
const fee = ethers.parseUnits("0.001", "ether"); // per-call ETH fee
const myHelper = new ethers.Contract("0xHelper…", HelperABI, provider);

const calls: Call3Value[] = [
  {
    contract: myHelper,
    functionFragment: "depositAndFetch",
    args: ["0xYourAddress"],
    allowFailure: false,
    value: fee,
  },
  {
    contract: myHelper,
    functionFragment: "updateRecord",
    args: [42, "hello"],
    allowFailure: true,
    value: fee,
  },
  // …etc
];

// 3) Send them all in one tx
const tx = await mc4.sendAggregate3Value(calls, {
  gasLimit: 1_200_000,
});
console.log("Multicall tx hash:", tx.hash);

// 4) Wait for it to be mined
const receipt = await tx.wait();
console.log("→ mined in block", receipt.blockNumber);
API
/**
 * Batch-execute multiple non-view calls (each may carry its own ETH value)
 * in a single on-chain TX via Multicall3.aggregate3Value.
 *
 * @param calls     – Array of { contract, functionFragment, args, allowFailure, value }
 * @param overrides – Ethers transaction overrides (gasLimit, maxPriorityFeePerGas, etc)
 * @returns          Promise<TransactionResponse>
 * @throws if no Signer was provided in the constructor.
 */
sendAggregate3Value(
  calls: Call3Value[],
  overrides?: Overrides
): Promise<TransactionResponse>;
  • allowFailure: true on any Call3Value lets that individual call revert without failing the entire batch.

  • The SDK automatically sums up all value fields into one msg.value on the multicall.

Helper Functions

All return either Promise<bigint> or Promise<string>:

  • getEthBalance Gets the ETH balance of an address

    const ethBalance = await mc1.getEthBalance("address");
  • getBlockHash Gets the block hash

    Only works for 256 most recent, excluding current according to Solidity docs

    const blockHash = await mc1.getBlockHash(blockNumber);
  • getLastBlockHash Gets the last blocks hash

    const lastBlockHash = await mc1.getLastBlockHash();
  • getCurrentBlockTimestamp Gets the current block timestamp

    const currentBlockTimestamp = await mc1.getCurrentBlockTimestamp();
  • getCurrentBlockDifficulty Gets the current block difficulty

    const currentBlockDifficulty = await mc1.getCurrentBlockDifficulty();
  • getCurrentBlockGasLimit Gets the current block gas limit

    const currentBlockGasLimit = await mc1.getCurrentBlockGasLimit();
  • getCurrentBlockCoinbase Gets the current block coinbase

    const currentBlockCoinbase = await mc1.getCurrentBlockCoinbase();

🧪 Testing

This SDK ships with a comprehensive Mocha + Chai + Sinon test suite.

# Run unit tests (Mocha + Chai + Sinon)
yarn test

🤝 Contributing

  1. Fork & clone
  2. yarn install
  3. Develop in src/, add tests in test/
  4. Run yarn test & Submit a PR

📜 LICENSE

Released under the MIT License.

© 2025 EVMlord