thirdweb-dev / js

Best in class web3 SDKs for Browser, Node and Mobile apps
https://thirdweb.com
Apache License 2.0
420 stars 314 forks source link

How to use Multicall to read contracts at once? #4463

Open iamcryptofennec opened 1 week ago

iamcryptofennec commented 1 week ago

I don't see any example. Have seen only Multicall to do transactions at once.

jnsdls commented 1 week ago

what's the use-case for reading via multicall?

The SDK batches calls into one HTTP call already (if they are called in the same event loop) so I'm unsure what benefit multicall would give here?

for example:

import { tokenURI } from "thirdweb/extensions/erc721";

const [token1, token2] = await Promise.all([tokenURI({ contract , tokenId: 0n }), tokenURI({ contract, tokenId: 1n })]);

would make 1 RPC call (1 roundtrip), since both network calls are kicked off at the same time and awaited together


there definitely could be something we're missing that's a good use-case for multicall reads, and if there is we can probably figure out a way to add it in a nice way, but would love to collect some examples of its useful-ness first :)

iamcryptofennec commented 1 week ago

This is what I'm doing it right now. It will call 1 rpc call each. I'm not sure this case should uses Multicall thing. or can do with in a loop like you did to have only 1 RPC call?

// total staked //
const totalStaked = await readContract<any, any, any>({
    contract: contract,
    method: 'totalStaked',
    params: [],
})
setTotalStaked(Number(toEther(totalStaked)));

// End time //
const endTime = await readContract<any, any, any>({
    contract: contract,
    method: 'endTime',
    params: [],
})

if (Number(endTime) > (Date.now() / 1000)) {
    const dayleft = Math.ceil((Number(endTime) - (Date.now() / 1000)) / 86400);
    setTotalDayLeft(dayleft);
}
else {
    setTotalDayLeft(0);
}

// level up time //
const levelUpTime = await readContract<any, any, any>({
    contract: contract,
    method: 'levelUpTime',
    params: [],
})
setLevelUpTime(Number(levelUpTime));

// min level up amount //
const minLevelUpAmount = await readContract<any, any, any>({
    contract: contract,
    method: 'minLevelUpAmount',
    params: [],
})

setMinLevelUpAmount(Number(toEther(minLevelUpAmount)));`
iamcryptofennec commented 1 week ago

Omg! I haven't known that before after use Promise.All(). it will call only 1 RPC call. Ok thanks ;) I think don't need to use Multicall right now. even it's readContract()

image

iamcryptofennec commented 1 week ago

Ummm my senior dev said. It's multi eth_call. But multicall is single eth_eth call. I think there should have a feature to readContracts with a single eth_call via Multicall

jnsdls commented 1 week ago

Ummm my senior dev said. It's multi eth_call. But multicall is single eth_eth call. I think there should have a feature to readContracts with a single eth_call via Multicall

Something we can definitely look into, what's the concern with doing a multi eth_call?

iamcryptofennec commented 6 days ago

https://docs.chainstack.com/docs/http-batch-request-vs-multicall-contract

It has pros and cons between batch requests and Multicall read. I just think able to use multicall to read contract is a good choice too.

kien-ngo commented 6 days ago

Hi @iamcryptofennec, you could also use the Multicall3 contract if you have to do all the reads in one single rpc call. We do support its extensions: https://portal.thirdweb.com/typescript/v5/multicall3/aggregate3

(this ofc would require you to know how M3 works)

iamcryptofennec commented 6 days ago

Hi @iamcryptofennec, you could also use the Multicall3 contract if you have to do all the reads in one single rpc call. We do support its extensions: https://portal.thirdweb.com/typescript/v5/multicall3/aggregate3

(this ofc would require you to know how M3 works)

Maybe, I don't understand well about this feature. The example doesn't provides about how to read via Multicall

how to read the contract? because, readContract() needs to have "method". Please give me some example ;)