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

@1delta/providers

v0.0.54

Published

Resilient EVM provider infrastructure: chain mapping, RPC management, transport creation, and batched multicall with automatic retry/rotation.

Readme

@1delta/providers

Resilient EVM provider infrastructure: chain mapping, RPC management, transport creation, and batched multicall with automatic retry/rotation.

Module Reference

| Module | README | Purpose | |---|---|---| | chains/ | chains/README.md | Chain enum → viem Chain mapping, custom chain definitions | | client/ | client/README.md | PublicClient creation with RPC fallback/rotation | | rpc/ | rpc/README.md | Default RPC URL pools per chain (LIST_OVERRIDES) | | transport/ | transport/README.md | HTTP/WebSocket viem transport factory | | multicall/ | multicall/README.md | Batched multicall with retry, RPC rotation, revert isolation | | utils/ | utils/README.md | Shared constants and helpers |

Everything is re-exported from the package root via src/index.ts → src/evm.ts.


Building Efficient Batched Multicalls

The core pattern used across this repo is: build a flat call array from heterogeneous sources, fire one multicall, then walk the results array using tracked offsets. This minimizes RPC round-trips by packing as many reads as possible into a single multicall3 invocation.

1. Define the Call Shape

Each call is a plain object:

interface Call {
  address: string       // target contract
  name: string          // function name (must match ABI)
  params?: any[]        // function arguments (alias: args)
}

2. Build Calls — Track Lengths per Source

The key insight is to concatenate calls from different protocols into one flat array while recording how many calls each source contributed, so you can slice the results later.

From margin-fetcher/src/flash-liquidity/fetchLiquidity.ts:

let callLengths: { [protocol: string]: number } = {}
let aaveCalls: Call[] = []

// Aave forks: 2 calls per asset (balanceOf + getConfiguration) + 1 premium call
aaveProtocols.forEach((aaveFork) => {
  const underlyingsAndATokens = Object.entries(
    getAaveStyleProtocolTokenMap(chain, aaveFork),
  )
  const pool = getAaveTypePoolAddress(chain, aaveFork)

  const tokenCalls = underlyingsAndATokens.flatMap(
    ([underlying, tokens]: [string, any]) => [
      { name: 'balanceOf', address: underlying, params: [tokens.aToken] },
      { name: 'getConfiguration', address: pool, params: [underlying] },
    ],
  )

  // Track length so we know how many results belong to this fork
  callLengths[aaveFork] = tokenCalls.length + 1

  aaveCalls.push(...tokenCalls, {
    name: 'FLASHLOAN_PREMIUM_TOTAL',
    address: pool,
  })
})

For uniform sources (same call per asset), a helper keeps it concise:

const buildBalanceCalls = (
  forks: { pool: string; address: string }[],
): Call[] => {
  const result: Call[] = []
  for (const fork of forks) {
    callLengths[fork.pool] = unifiedAssets.length
    for (const address of unifiedAssets) {
      result.push(
        address === zeroAddress
          ? { name: 'getEthBalance', address: MULTICALL_ADDRESS[chain], params: [fork.address] }
          : { name: 'balanceOf', address, params: [fork.address] },
      )
    }
  }
  return result
}

3. Concatenate and Fire

Merge all sub-arrays into one flat call list and execute a single multicall:

const calls = [
  ...aaveCalls,
  ...balancerV2Calls,
  ...morphoCalls,
  ...balancerV3Calls,
  ...uniswapV4Calls,
]

const rawResults = await multicallRetryUniversal({
  chain,
  calls,
  abi: FlashAbi,          // single ABI covering all function signatures
  batchSize: 4096,
  allowFailure: true,     // failed calls return '0x' instead of throwing
})

ABI tip: When all calls use functions from the same ABI (or a merged superset ABI), pass a single ABI. When calls target different contracts with different ABIs, pass an array of ABIs (one per call) — see multicall/README.md.

4. Unwrap Results with Offset Walking

The results array is positionally aligned with the calls array. Use the tracked lengths to slice each source's chunk:

let currentOffset = 0

aaveProtocols.forEach((aave) => {
  const callLen = aaveAssets[aave].length * 2 + 1    // 2 calls per asset + 1 premium

  // Slice this fork's results
  const data = rawResults.slice(currentOffset, currentOffset + callLen)
  currentOffset += callLen                            // advance the cursor

  // Last result is the premium call
  const fee = data[callLen - 1]
  if (typeof fee !== 'bigint') return                 // skip fork if premium call failed

  // Walk interleaved results: [balance, config, balance, config, ...]
  aaveAssets[aave].forEach((asset, i) => {
    const rawAmount = data[2 * i]       // balanceOf result
    const config = data[2 * i + 1]      // getConfiguration result

    if (typeof rawAmount !== 'bigint' || typeof config !== 'bigint') return
    // ... process asset
  })
})

// Uniform sources are simpler — one result per asset
balancerV2s.forEach((balancer) => {
  const data = rawResults.slice(currentOffset, currentOffset + unifiedAssets.length)
  currentOffset += unifiedAssets.length

  unifiedAssets.forEach((asset, i) => {
    const rawAmount = data[i]
    if (typeof rawAmount === 'bigint' && rawAmount > 0n) {
      // ... process asset
    }
  })
})

5. Handling Failed Calls

With allowFailure: true, failed calls return '0x'. Guard with type checks:

// For bigint returns (balances, configs, etc.)
const isValidResult = (v: any): v is bigint => typeof v === 'bigint'

if (!isValidResult(rawAmount)) return  // skip this entry

Quick Reference

import { multicallRetryUniversal } from '@1delta/providers'

// Minimal call
const results = await multicallRetryUniversal({
  chain: '8453',
  calls: [
    { address: tokenAddr, name: 'balanceOf', params: [account] },
    { address: tokenAddr, name: 'decimals' },
  ],
  abi: ERC20_ABI,
})

const [balance, decimals] = results

For custom RPCs or factory usage, see multicall/README.md and client/README.md.