cavanmflynn / ethers-multicall Goto Github PK
View Code? Open in Web Editor NEWMake multiple Ethereum network requests in a single HTTP query. ethcall for ethers v5.
License: MIT License
Make multiple Ethereum network requests in a single HTTP query. ethcall for ethers v5.
License: MIT License
When providing the full ABI to the multicall Contract, I get an error "TypeError: Cannot read properties of null (reading 'type')"
Here is where the code brings me to. If I remove all event types and only leave function types, it will work.
Contract.js line 12
for (var _i = 0, callFunctions_1 = callFunctions; _i < callFunctions_1.length; _i++) { var callFunction = callFunctions_1[_i]; var name = callFunction.name; var getCall = makeCallFunction(this, name); if (!this[name]) { defineReadOnly(this, name, getCall); } };
Hello, I am trying to run a multicall using your API (thank you by the way), however I am running in to the following issue.
Uncaught (in promise) Error: invalid address (argument="address", value=0, code=INVALID_ARGUMENT, version=address/5.7.0) (argument=null, value=0, code=INVALID_ARGUMENT, version=abi/5.7.0)
The following is my code for running the multiCall API.
`
async loadDataUsingMulticall() {
const { web3 } = this.state;
var multicall = null;
// Your multicall code here
console.log("test zero -");
multicall = new Multicall({
web3Instance: web3,
tryAggregate: true,
});
console.log("test zero");
const contractCallContext = [
{
reference: "mirrorBalance",
contractAddress: MIRROR_ADDRESS,
abi: MIRRORABI,
calls: [
{
methodName: "balanceOf",
methodParameters: [this.state.account[0]],
},
],
},
{
reference: "morWholeBurn",
contractAddress: MIRROR_ADDRESS,
abi: MIRRORABI,
calls: [
{
methodName: "balanceOf",
methodParameters: ["0x0000000000000000000000000000000000000000"],
},
],
},
{
reference: "morRFIBurn",
contractAddress: MIRROR_ADDRESS,
abi: MIRRORABI,
calls: [
{
methodName: "balanceOf",
methodParameters: ["0x000000000000000000000000000000000000dead"],
},
],
},
{
reference: "totalFees",
contractAddress: MIRROR_ADDRESS,
abi: MIRRORABI,
calls: [{ methodName: "totalFees", methodParameters: [] }],
},
{
reference: "numFarmers",
contractAddress: MIRROR_ADDRESS,
abi: MIRRORABI,
calls: [{ methodName: "numFarmers", methodParameters: [] }],
},
];
console.log("test before");
console.log(MIRROR_ADDRESS);
// Loop for dynamic method calls like 'farmers' and 'farmingLeaderboard'
for (let i = 0; i < 5; i++) {
contractCallContext.push({
reference: `farmer${i}`,
contractAddress: MIRROR_ADDRESS,
abi: MIRRORABI,
calls: [{ methodName: "farmers", methodParameters: [i] }],
});
contractCallContext.push({
reference: `farmer${i}amt`,
contractAddress: MIRROR_ADDRESS,
abi: MIRRORABI,
calls: [{ methodName: "farmingLeaderboard", methodParameters: [i] }],
});
}
////////////
const callResults = await multicall.call(contractCallContext);
console.log("test)");
console.log(callResults);
//THE ISSUE COULD BE HERE TO THE WAY: callResults.results.<nameofId>.callsReturnContext[0].returnValues
// Accessing individual results
const mirrorBalance = Web3.utils.fromWei(
callResults.results.mirrorBalance.callsReturnContext[0].returnValues[0],
"ether",
);
const morWholeBurn = Web3.utils.fromWei(
callResults.results.morWholeBurn.callsReturnContext[0].returnValues[0],
"ether",
);
const morRFIBurn = Web3.utils.fromWei(
callResults.results.morRFIBurn.callsReturnContext[0].returnValues[0],
"ether",
);
const totalFees = Web3.utils.fromWei(
callResults.results.totalFees.callsReturnContext[0].returnValues[0],
"ether",
);
const numFarmers = parseInt(
callResults.results.numFarmers.callsReturnContext[0].returnValues[0],
);
console.log("This is mirror Balance");
console.log(mirrorBalance);
console.log("This is morWhole Burn");
console.log(morWholeBurn);
console.log("This is total Farmers");
console.log(numFarmers);
// Loop to access farmers and farmingLeaderboard data
let farmerData = {};
for (let i = 0; i < 5; i++) {
farmerData[`farmer${i}`] =
callResults.results[`farmer${i}`].callsReturnContext[0].returnValues[0];
farmerData[`farmer${i}amt`] =
callResults.results[
`farmer${i}amt`
].callsReturnContext[0].returnValues[0];
}
// Update state with all the gathered data
this.setState({
mirrorBalance,
morWholeBurn,
morRFIBurn,
totalFees,
numFarmers,
...farmerData,
loadingLeaderBoard: false,
});
}`
Hi, I'm using ethers-multicall in my app but getting the following error on network change:
index.js?4a96:219 Uncaught (in promise) Error: underlying network changed (event="changed", network={"name":"matic","chainId":137,"ensAddress":null}, detectedNetwork={"name":"homestead","chainId":1,"ensAddress":"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"}, code=NETWORK_ERROR, version=providers/5.6.8)
I'm calling a getBalances() function in order to fetch the user's balances of multi tokens:
export const getMultipleTokenBalancesByMultiCall = async (
tokens: Token[],
userAddress: string,
chainId: number,
provider: ethers.providers.Provider
): Promise<TokenWithBalance[]> => {
const ethCallProvider = new Provider(provider, chainId);
const balanceCalls = tokens.map((token) => {
if (NATIVE[chainId].equals(token)) {
return ethCallProvider.getEthBalance(userAddress);
}
return getERC20Contract_MultiCall(token.address).balanceOf(userAddress);
});
const balances = await ethCallProvider?.all(balanceCalls);
return tokens.map(
(token, index) =>
({
...token,
balance: FixBigNumber.fromWei(
balances[index].toString(),
token.decimals
),
} as TokenWithBalance)
);
};
The function is called like below:
export const useGetUserAssetsBalances = (assets: any): TokenWithBalance[] => {
const { account, provider, chainId } = useWeb3React();
const [balances, setBalances] = useState<TokenWithBalance[]>([]);
const fetchBalances = useCallback(async () => {
const tokens: Token[] = Object.values(assets);
const data = (await getMultipleTokenBalancesByMultiCall(
tokens,
account!,
chainId!,
provider!,
)) as TokenWithBalance[];
setBalances(data);
}, [account, provider, assets, chainId]);
useEffect(() => {
if (account && assets && provider && chainId) {
fetchBalances();
}
}, [account, chainId, provider, assets, setBalances, fetchBalances]);
return balances;
};
I don't have any idea on what happens here. Do someone has an idea?
I am using a custom ABI,
I can use without problems balanceOf
and symbol
.
but if I try to use the getAmountOut
function
"function getAmountsOut (uint amountIn, address [] memory path) public view returns (uint [] memory amounts)"
I get the following error:
const error: any = new Error(message);
^
Error: types/values length mismatch (count={"types":2,"values":0}, value={"types":[{"name":"amountIn","type":"uint256","indexed":null,"components":null,"arrayLength":null,"arrayChildren":null,"baseType":"uint256","_isParamType":true},{"name":"path","type":"address[]","indexed":null,"components":null,"arrayLength":-1,"arrayChildren":{"name":null,"type":"address","indexed":null,"components":null,"arrayLength":null,"arrayChildren":null,"baseType":"address","_isParamType":true},"baseType":"array","_isParamType":true}],"values":[]}, code=INVALID_ARGUMENT, version=abi/5.7.0)
which is the correct way?
async function lpTokenUsd(currentBlock) { await multiCallProvider.init(); const oneLPAmount = BigNumber.from(10).pow(18); const calculateBlocks = 10; const priceCalls = []; for (let i = 1; i < calculateBlocks; i += 1) { const block = currentBlock - i; priceCalls.push( swapPool.calc_withdraw_one_coin(oneLPAmount, 0, { blockTag: block }) ); } const result = await multiCallProvider.all(priceCalls); console.log(
result : ${JSON.stringify(result)}); }
run above function will get error:
Error: types/values length mismatch (count={"types":2,"values":3}, value={"types":[{"name":"_token_amount","type":"uint256","indexed":null,"components":null,"arrayLength":null,"arrayChildren":null,"baseType":"uint256","_isParamType":true},{"name":"i","type":"int128","indexed":null,"components":null,"arrayLength":null,"arrayChildren":null,"baseType":"int128","_isParamType":true}],"values":[{"type":"BigNumber","hex":"0x0de0b6b3a7640000"},0,{"blockTag":11135382}]}, code=INVALID_ARGUMENT, version=abi/5.4.1)
Once I removed the blockTag, it will work and return result.
I got this error when I tried to add polygon using setMulticallAddress
25: '0x5e954f5972EC6BFc7dECd75779F10d848230345F'
Code:
import { Provider } from 'ethers-multicall';
import { ethers } from 'ethers';
(async function() {
const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545/');
const ethcallProvider = new Provider(provider);
await ethcallProvider.init();
const ganche_account_0 = '0x66aB6D9362d4F35596279692F0251Db635165871';
const ethBalance = await provider.getBalance(ganche_account_0);
const [ethBalanceMulticall] = await ethcallProvider.all([ethcallProvider.getEthBalance(ganche_account_0)]);
console.log('ETH Balance:', ethers.utils.formatUnits(ethBalance));
console.log('ETH Balance multicall:', ethers.utils.formatUnits(ethBalanceMulticall));
})()
Output:
ETH Balance: 100.0
ETH Balance multicall: 180143885.09481982
Add support for optimistic ethereum and optimistic kovan
heco multicall contract needed
We are trying to use ethers-multicall (https://www.npmjs.com/package/ethers-multicall) to group multiple calls to Fantom RPC, but it seems not working. Would you mind to take a look at and share any thoughts/guidance if possible?
let mushContract = new Contract("0x883fb00742161dce2235bbf4a67df84cd0e50c08", "contractABI");
let marketPriceCall = mushContract.getMarkPrice("0x321162Cd933E2Be498Cd2267a90534A804051b11");
let exposureBalanceCall = mushContract.exposureBalances("0x43229759E12eFbe3e2A0fB0510B15e516d046442", "0x321162Cd933E2Be498Cd2267a90534A804051b11");
let tokenBalanceCall = mushContract.tokenBalances("0x43229759E12eFbe3e2A0fB0510B15e516d046442", "0x321162Cd933E2Be498Cd2267a90534A804051b11");
let exposureLeverageBpsCall = mushContract.exposureLeverageBps("0x43229759E12eFbe3e2A0fB0510B15e516d046442","0x321162Cd933E2Be498Cd2267a90534A804051b11");
let [
marketPrice,
exposureBalance,
tokenBalance,
exposureLeverageBps,
] = await callProvider.all([
marketPriceCall,
exposureBalanceCall,
tokenBalanceCall,
exposureLeverageBpsCall,
]);
For some reasons, if the ABI contains a receive
payable function with no further arguments, instantiating a new Contract will throw an TypeError: Cannot read property 'type' of null
error.
The problem seems to be coming from the Fragment
from ethersprojects, but can also be fixed in the library.
Can be reproduced by using this ABI:
const abi = [
{
constant: true,
inputs: [],
name: 'totalSupply',
outputs: [
{
internalType: 'uint256',
name: '',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
stateMutability: 'payable',
type: 'receive'
}
]
in the tests.
Hello! Thanks for merging my PR. I also just made this: https://github.com/quorumcontrol/kasumah/tree/main/packages/kasumah-multicall and I'm wondering if it makes sense for me to merge that code into this repo too.
Basically that code allows you to create an app singleton that will handle using Multicall for you... you just wrap your contracts and that package takes care of batching up the requests and returning them to you using Multicall.
The current version supports multicall
contract instead of multicall2
, which allows one of many requests failed but still return the rest of results.
Here is multicall2:
https://github.com/makerdao/multicall
This repository seems to not be maintained anymore: last commit dates back to beginning of January 2022.
I encourage anyone willing to get support to start using ethers-multicall-provider, which is well tested and has a similar API. The move should not be cumbersome, as it boilds down to the following changes:
- import { Contract, Provider } from 'ethers-multicall';
+ import { MulticallProvider } from 'ethers-multicall-provider';
- const multicallProvider = new Provider(provider);
+ const multicallProvider = MulticallProvider.wrap(provider);
Our team has deployed Multicall contract on Aurora mainnet and testnet for our own use
Easy two line addition here -
ethers-multicall/src/provider.ts
Line 51 in fb84bcc
1313161554: '0xdc1522872E440cF9cD48E237EAFEfaa5F157Ca1d',
1313161555: '0x8f81207F59A4f86d68608fF90b259A0927242967'
Is there a way to currently (or in the future) make the contract aware of the functions it supports? Example:
Thanks to TypeChain
we have a generated contract type which would be as follows for the example above:
start_time(
overrides?: CallOverrides
): Promise<{
0: BigNumber;
}>;
I'm thinking there might be a way to pass it to the Contract
class if we make it generic โ taking contract type as a type argument.
deployed at address 0x77dca2c955b15e9de4dbbcf1246b4b85b651e50e, chainID 5. no reason not to add this in
const callProvider = new Provider(
new ethers.providers.JsonRpcProvider(
"https://api.avax.network/ext/bc/C/rpc"
)
);
callProvider.init();
const daiContract = new Contract(daiAddress, daiAbi);
const poolDaiBalanceCall = daiContract.balanceOf(poolAddress);
const myDaiBalanceCall = daiContract.balanceOf(account);
const [poolDaiBalance, myDaiBalance] = await callProvider.all([
poolDaiBalanceCall,
myDaiBalanceCall,
]);
in
const [poolDaiBalance, myDaiBalance] = await callProvider.all([
poolDaiBalanceCall,
myDaiBalanceCall,
]);
Error pop up, Error: invalid contract address or ENS name (argument="addressOrName", value=undefined, code=INVALID_ARGUMENT, version=contracts/5.5.0)
I am currently running into this error when await-ing the result of a multicall.all() call.
ethers-multicall: ^0.2.3
ethers: ^5.7.2
Below is the relevant code:
const multicallProvider = new Provider(provider, 1); //Provider is an AlchemyProvider
const call1 = new Contract(address, abi).liquidity; // ethers-multicall contract
const call2 = new Contract(address, abi).protocolFees; //ethers-multicall-contract
await multicallProvider.all([call1, call2]) //Fails and throws error
Thanks!
see #6
if the abi contains for example:
{ payable: true, stateMutability: 'payable', type: 'fallback' },
the contract instantiation will fail because x.type is undefined.
one can simply remove the abi entry but it would be nice if that would ignore it instead.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.