Supercharge Multicall.js with nitro features 💨

Overview

multicall-nitro

Tests npm version codecov

Supercharge Multicall.js with nitro features 💨

Highlights

  • TypeScript support
  • Ready-to-use calls ✍🏻
  • React hook ⚛️
  • One time call 🎯
  • Simplified API

Why

While Multicall.js provides a JavaScript interface to the amazing Multicall contract by MakerDAO, it still requires a bit of work to integrate it into a real world production application. This is where multicall-nitro comes in.

The goal is to provide a layer on top of Multicall.js that supercharges its features and eases its usage in different contexts. Thanks to fully typed and simplified APIs plus different utilities, your Multicall integration will be on nitro 💨

Getting started

  1. Install the package & its peer dependency
yarn install @enzoferey/multicall-nitro @makerdao/multicall
  1. Follow along the use cases below 👇🏻

💡 No matter the use case, you will need to provide a configuration object containing:

  • rpcUrl: the url of the RPC node you want to use to make the calls (it could be Infura, Alchemy, etc.)
  • multicallAddress: the address of the Multicall contract in your target blockchain. See here

Get batched values and subscribe to changes

The most common use case is to get batched values from the blockchain and subscribe to changes.

import {
  createWatcher,
  BigNumber,
  getErc20BalanceMulticall,
} from "@enzoferey/multicall-nitro";

type Value = { balanceToken1: BigNumber; balanceToken2: BigNumber };

const connectedAccountAddress = "0x...";

const tokenAddress1 = "0x...";
const tokenAddress2 = "0x...";

const calls = [
  getErc20BalanceMulticall(tokenAddress1, connectedAccountAddress, {
    label: "balanceToken1",
  }),
  getErc20BalanceMulticall(tokenAddress2, connectedAccountAddress, {
    label: "balanceToken2",
  }),
];

const watcher = createWatcher<Value>(calls, {
  rpcUrl: "INSERT HERE YOUR RPC NODE URL",
  multicallAddress: "INSERT HERE THE TARGET MULTICALL CONTRACT ADDRESS",
});

// Start watching for the values
await watcher.start();

// Subscribe to values changes
watcher.subscribe((update) => {
  // `update` contains the value for one of the calls
  //  -> `update.type` is the label of the call
  //  -> `update.value` is the value of the call
  //
  // For example, with the calls above, we could get `{ type: "balanceToken1", value: BigNumber(...) }`
  console.log(`Call with label ${update.type} returned value ${update.value}`);
});

// Later when finished
await watcher.stop();

Get batched values once

Sometimes you do not want to subscribe to values updates but just get them once. The returned promise will resolve when all values have been received.

import {
  getBatchedValuesOnce,
  BigNumber,
  getErc20BalanceMulticall,
} from "@enzoferey/multicall-nitro";

type Value = { balanceToken1: BigNumber; balanceToken2: BigNumber };

const connectedAccountAddress = "0x...";

const tokenAddress1 = "0x...";
const tokenAddress2 = "0x...";

const calls = [
  getErc20BalanceMulticall(tokenAddress1, connectedAccountAddress, {
    label: "balanceToken1",
  }),
  getErc20BalanceMulticall(tokenAddress2, connectedAccountAddress, {
    label: "balanceToken2",
  }),
];

const batchedValues = await getBatchedValuesOnce<Value>(calls, {
  rpcUrl: "INSERT HERE YOUR RPC NODE URL",
  multicallAddress: "INSERT HERE THE TARGET MULTICALL CONTRACT ADDRESS",
});

// At this point `batchedValues` contains the values of the specified calls
// -> `batchedValues.balanceToken1` is the value of the call with label "balanceToken1"
// -> `batchedValues.balanceToken2` is the value of the call with label "balanceToken2"

Get ERC20 token values

Writing calls is tedious and error-prone, use these utilities to get values of ERC20 tokens.

import {
  getErc20BalanceMulticall,
  getErc20DecimalsMulticall,
  getErc20AllowanceMulticall,
} from "@enzoferey/multicall-nitro";

const tokenAddress1 = "0x...";
const connectedAccountAddress = "0x...";
const someOtherAccountAddress = "0x...";

const calls = [
  // Get the ERC20 token balance of `connectedAccountAddress`
  getErc20BalanceMulticall(tokenAddress1, connectedAccountAddress, {
    label: "balanceToken1",
  }),
  // Get the ERC20 token decimals
  getErc20DecimalsMulticall(tokenAddress1, {
    label: "decimalsToken1",
  }),
  // Get the ERC20 token allowance provided by `connectedAccountAddress` to `someOtherAccountAddress`
  getErc20AllowanceMulticall(
    tokenAddress1,
    connectedAccountAddress,
    someOtherAccountAddress,
    {
      label: "allowanceToken1",
    }
  ),
];

// you can then pass these `calls` into `createWatcher`, `getBatchedValuesOnce` or any other entry point

Are you missing any utility for ERC20 tokens values ? Please open an issue or pull request 🙏🏻

Get blockchain values

Writing calls is tedious and error-prone, use these utilities to get values of the blockchain you connect to.

import { getBlockchainNativeTokenBalanceMulticall } from "@enzoferey/multicall-nitro";

const connectedAccountAddress = "0x...";

const calls = [
  // Get the native token (ETH, MATIC, BNB, etc.) balance of `connectedAccountAddress`
  getBlockchainNativeTokenBalanceMulticall(connectedAccountAddress, {
    label: "nativeTokenBalance",
  }),
];

// you can then pass these `calls` into `createWatcher`, `getBatchedValuesOnce` or any other entry point

Are you missing any utility for blockchain values ? Please open an issue or pull request 🙏🏻

Custom calls

On top of the built-in utilities that enable you to construct common calls, you can write your own custom calls.

import { Call } from "@enzoferey/multicall-nitro";

const calls = [
  // Call method "getResult" on contract address 0x2222222222222222222222222222222222222222
  // This method takes an `uint256` and a `string` as argument and returns a `string`
  {
    target: "0x2222222222222222222222222222222222222222",
    call: ["getResult(uint256,string)(string)", 10, "hello"],
    label: "someCustomCallLabel1",
  },
  // Call method "getBestNumber" on contract address 0x3333333333333333333333333333333333333333
  // This method takes three `uint16` and returns a `uint16`
  {
    target: "0x3333333333333333333333333333333333333333",
    call: ["getBestNumber(uint16,uint16,uint16)(uint16)", 10, 12, 14],
    label: "someCustomCallLabel2",
  },
  // any other call you want to make
];

// you can then pass these `calls` into `createWatcher`, `getBatchedValuesOnce` or any other entry point

Use batched values in React

Wraps createWatcher into a React hook.

💡 In order to use this hook, you need to have the react peer dependency installed.

yarn install react

Notice the trailing /react on the import statement, this is for reducing bundle size if you don't use the React specific code.

import { useBatchedValues } from "@enzoferey/multicall-nitro/react";
import { Call, BigNumber } from "@enzoferey/multicall-nitro";

// You can define your calls outside the render function if statis
const calls = [
  getErc20BalanceMulticall("0x...", connectedAddress, { label: "balance" }),
  getErc20DecimalsMulticall("0x...", {
    label: "decimals",
  }),
];

const MyComponent = (props) => {
  const { tokenAddress } = props;

  // You can define your calls inside the render function if dynamic
  const calls = React.useMemo<Call[]>(() => {
    return [
      getErc20BalanceMulticall(tokenAddress, connectedAddress, {
        label: "balance",
      }),
      getErc20DecimalsMulticall(tokenAddress, {
        label: "decimals",
      }),
    ];
  }, []);

  // In both cases, you can then use `useBatchedValues` to get the values of your calls
  const batchedValues = useBatchedValues<{
    balance: BigNumber;
    decimals: number;
  }>(calls);

  // First, `batchedValues` will be `null` until the first value arrives
  // Then, `batchedValues` will be the partial object defined by the type passed, in this case:
  // `{ balance?: BigNumber, decimals?: number }`
};

Use batched values once in React

Wraps getBatchedValuesOnce into a React hook. The returned value will be null until all values have been received.

💡 In order to use this hook, you need to have the react peer dependency installed.

yarn install react

Notice the trailing /react on the import statement, this is for reducing bundle size if you don't use the React specific code.

import { useBatchedValuesOnce } from "@enzoferey/multicall-nitro/react";
import { Call, BigNumber } from "@enzoferey/multicall-nitro";

// You can define your calls outside the render function if statis
const calls = [
  getErc20BalanceMulticall("0x...", connectedAddress, { label: "balance" }),
  getErc20DecimalsMulticall("0x...", {
    label: "decimals",
  }),
];

const MyComponent = (props) => {
  const { tokenAddress } = props;

  // You can define your calls inside the render function if dynamic
  const calls = React.useMemo<Call[]>(() => {
    return [
      getErc20BalanceMulticall(tokenAddress, connectedAddress, {
        label: "balance",
      }),
      getErc20DecimalsMulticall(tokenAddress, {
        label: "decimals",
      }),
    ];
  }, []);

  // In both cases, you can then use `useBatchedValuesOnce` to get the values of your calls
  const batchedValues = useBatchedValuesOnce<{
    balance: BigNumber;
    decimals: number;
  }>(calls);

  // First, `batchedValues` will be `null` until all values are received
  // Then, `batchedValues` will be the object defined by the type passed
};
You might also like...

VanillaSelectBox - A dropdown menu with lots of features that takes a select tag and transforms it into a single or multi-select menu with 1 or 2 levels

VanillaSelectBox - A dropdown menu with lots of features that takes a select tag and transforms it into a single or multi-select menu with 1 or 2 levels

vanillaSelectBox v1.0.0 vanillaSelectBox : v1.00 : Adding a package.json file New : Possibility to change the dropdown tree and change the remote sear

Dec 16, 2022

This Application provides basic authentication features like you can register and create account and then login and access your profile.

  This Application provides basic authentication features like you can register and create account and then login and access your profile.

Authentication API This Application provides basic authentication features like you can register and create account and then login and access your pro

Jan 17, 2022

JavaScript/TypeScript library to run repetitive tasks with throttle control and other cool features

JavaScript/TypeScript library to run repetitive tasks with throttle control and other cool features

Repeatify JavaScript/TypeScript library to run repetitive tasks with throttle control and other cool features Install npm install repeatify Usage impo

Jan 15, 2022

JavaScript project for the Leader-board list app, using webpack and ES6 features, notably modules

JavaScript project for the Leader-board list app, using webpack and ES6 features, notably modules

Leaderboard JavaScript project for the Leader-board list app, using webpack and ES6 features, Built With HTML CSS Javascript webpack Getting started t

Feb 17, 2022

A JavaScript project for the Leaderboard list app, using webpack and ES6 features, notably modules

A JavaScript project for the Leaderboard list app, using webpack and ES6 features, notably modules

LEADERBOARD In this activity I am setting up a JavaScript project for the Leaderboard list app, using webpack and ES6 features, notably modules. I wil

Mar 16, 2022

JavaScript project for the Leaderboard list app, built using webpack and ES6 features.

JavaScript project for the Leaderboard list app, built using webpack and ES6 features.

Leaderboard List App JavaScript project for the Leaderboard list app, built using webpack and ES6 features. The leaderboard website displays scores su

Aug 16, 2022

The Leaderboard list app using webpack and ES6 features

Leaderboard Game In this activity I set up a JavaScript project for the Leaderboard list app, using webpack and ES6 features, notably modules. I consu

Sep 16, 2022

A weather dashboard that features dynamically updated HTML and CSS using OpenWeather API data.

A weather dashboard that features dynamically updated HTML and CSS using OpenWeather API data.

Weather Dashboard A weather dashboard that features dynamically updated HTML and CSS using OpenWeather API data. User Story AS A traveler I WANT to se

Apr 19, 2022
Comments
  • Return type should be inferred from calls labels and functions return type

    Return type should be inferred from calls labels and functions return type

    As of right now the returned type needs to be typed manually like:

    createWatcher<Value>
    getBatchedValuesOnce<Value>
    useBatchedValues<Value>
    useBatchedValuesOnce<Value>
    

    This is error prone because the passed calls can change (the label or returned type does not match anymore), so the library should be able to infer the Value type from the calls labels and functions return type.

    Inferring the labels should be straightforward with some TypeScript magic. Inferring the labels' types also requires some TypeScript magic but should be doable.

    An alternative solution could be to wrap the calls generators in some glue that defines its types, so everything about a call would be defined where the call is defined and then the function using it would pick up those definitions.

    enhancement 
    opened by enzoferey 0
Releases(v0.1.1)
  • v0.1.1(Jul 25, 2022)

  • v0.1.0(Jul 24, 2022)

    Supercharge Multicall.js with nitro features 💨

    The goal is to provide a layer on top of Multicall.js that supercharges its features and eases its usage in different contexts. Thanks to fully typed and simplified APIs plus different utilities, your Multicall integration will be on nitro.

    Source code(tar.gz)
    Source code(zip)
Owner
Enzo Ferey
Learning to be the developer you want to work with | React.js lover | Maker | Crypto
Enzo Ferey
Supercharge Notion with custom commands to record, draw, and more ✍️

Slashy Supercharge Notion with custom commands to record, draw, and more ✨ Slashy is an open source extension that lets you create custom commands for

Alyssa X 425 Dec 28, 2022
Supercharge your All-in-One workspace with the Command Palette within Notion 🕹️

Notion Palette Supercharge your All-in-One workspace with the Command Palette within Notion ??️ Notion Palette is a free and open source extension, yo

Ruter 13 Nov 10, 2022
🔥 A Powerful JavaScript Module for Generating and Checking Discord Nitro 🌹

DANG: Dreamy's Awesome Nitro Generator Join Our Discord Getting Started Before, We start please follow these Steps: Required* ⭐ Give a Star to this dr

Dreamy Developer 73 Jan 5, 2023
A discord bot that generates Discord Nitro, Hulu accounts, Origin, spotify and VPNs!

Discord-Account-Generator-Bot A discord bot that generates Discord Nitro, Hulu accounts, Origin, spotify and VPNs! Tutorial Basically download the fil

#Fluroescent 20 Oct 4, 2022
⚗️Nitro provides a powerful toolchain and a runtime framework from the UnJS ecosystem to build and deploy any JavaScript server, anywhere

⚗️Nitro provides a powerful toolchain and a runtime framework from the UnJS ecosystem to build and deploy any JavaScript server, anywhere

unjs 1.3k Jan 5, 2023
Générateur de nitro Discord by RyzeTool

Vlaque Nitro Generator Le Vlaque Nitro Générator comme son nom l'indique génère des code nitro. Ryze Ryze Avant de d'installer le tool n'hésite pas a

Ryze 4 Dec 9, 2022
this is a discord nitro generator and checker⚙ EZPZ

Language | EN Hello my dear friends ???? In this new project, I wrote a program to extract nitro discord code, which after extracting the code, verifi

Sobhan.SRZA 6 Sep 17, 2022
A customizable lightweight Alert Library with Material UI and awesome features.

SoloAlert A customizable lightweight Alert Library with Material UI and awesome features. view soloalert on npm : https://www.npmjs.com/soloalert Inst

Arnav Kumar 21 Nov 30, 2022
Functions Recipes is a library of examples to help you getting started with Salesforce Functions and get used to their main features.

Functions Recipes Introduction Salesforce Functions lets you use the Salesforce Platform for building event-driven, elastically scalable apps and expe

Trailhead Apps 172 Dec 29, 2022
BIND-ing the good features together.

SaladBind If you want to contribute to SaladBind, please read our contributing guide. Table of Contents Features Installation Configuration Miner Setu

Vukky Limited 7 May 31, 2022