web3modal icon indicating copy to clipboard operation
web3modal copied to clipboard

[bug] <w3m-button> does not update balance after successful transaction

Open spider9375 opened this issue 2 years ago • 13 comments

Link to minimal reproducible example

Summary

I have a w3m-button that after a transaction does not update the balance. Correct one is 0.3539 which could get rounded to 0.354 but the w3m button shows 0.355

image

image

the getBalance wagmi action returns the correct amount. However the w3m button does not update

List of related npm package versions

"typescript": "5.0.2", "vite": "4.4.5", "@wagmi/core": "1.4.3", "@web3modal/wagmi": "3.1.0", "viem": "1.16.6"

spider9375 avatar Oct 19 '23 09:10 spider9375

Call wagmi's fetchBalance after your tx is successful. https://wagmi.sh/core/actions/fetchBalance

This will update wagmi's state and in turn what's displayed in modal components.

xzilja avatar Oct 19 '23 12:10 xzilja

@0xAsimetriq I have the same problem. Using react, calling fetchBalance after transaction completed.

import { fetchBalance } from 'wagmi/actions';
    useEffect(() => {
        const fetchData = async () => {
            var data = await fetchBalance({
                address: '0x7...E6d2d4C3B8',
            });
        }

        fetchData()
    }, [complete])

It's calling the code and I get the new balance, but the button does not reflect the change.

jvanderbiest avatar Nov 10 '23 13:11 jvanderbiest

@jvanderbiest it should be import { fetchBalance } from '@wagmi/core/actions but since you are using react (and probabli wagmi package and not their core one) you need to use https://wagmi.sh/react/hooks/useBalance

xzilja avatar Nov 10 '23 13:11 xzilja

Thanks for your quick reply and for the insights. I still couldn't get it working though.

Console logs the new balance, <w3m-button /> doesn't reflect the balance.

import { useBalance } from 'wagmi';

const { data, refetch } = useBalance({
        address: '0x7...E6d2d4C3B8',
      });

useEffect(() => {
    const fetchData = async () => {
        var fetchData = await refetch();
        console.log(`fetched balance: ${fetchData.data?.value}`);
        console.log(`usebalance: ${data?.value}`);
    }

    fetchData()
}, [complete]);

jvanderbiest avatar Nov 10 '23 13:11 jvanderbiest

@0xAsimetriq I can confirm this bug with the latest version as well. We are using core inside svelte. We are creating the transaction via getContract() [...] .write.someFunction() and call fetchBalance afterwards. It logs the new balance, so wagmi has it, but it does not update the w3m-button state.

import { fetchBalance } from '@wagmi/core'

export const refreshUserBalance = async () => {
  const account = getAccount();
  if (account?.address) {

    const newBalance = await fetchBalance({
      address: account.address,
    })
    console.log("new balance", newBalance);
  }
};

KorbinianK avatar Jan 04 '24 16:01 KorbinianK

I'm not sure if this is possible though, there's no global track in wagmi for balance or balance RPC calls AFAIK

glitch-txs avatar Jan 04 '24 17:01 glitch-txs

I'm not sure if this is possible though, there's no global track in wagmi for balance or balance RPC calls AFAIK

Then there should be a way to call something like modal.refresh() which calls the internal fetchBalance. I feel like this is a pretty common use-case, refreshing the balance.

KorbinianK avatar Jan 04 '24 17:01 KorbinianK

sounds like a good addition, refetchBalance could work I guess, we'll look into this 👍

glitch-txs avatar Jan 04 '24 23:01 glitch-txs

@glitch-txs Looked into it a bit now, for wagmi/ethers for plain js it seems to be really simple, as syncBalance is already there, just missing the public exposed wrapper.

Adding this to packages/wagmi/src/client.ts (similar for ethers) exposes the necessary functionality and can then be called via modal.refetchBalance():

public async refetchBalance() {
    const { address, isConnected } = getAccount()
    const { chain } = getNetwork()
    if (isConnected && address && chain) {
      await this.syncBalance(address, chain)
    }
  }

I would provide a PR, but I was not yet able to make it work for react & vue derived from the scaffold package. Not sure it makes sense to only expose it for plain javascript for now? (biased, as that's all I need :P)

KorbinianK avatar Jan 08 '24 11:01 KorbinianK

any update? I am having the same problem.

vietvh-3042 avatar Jul 31 '24 12:07 vietvh-3042

I am using

const modal = createWeb3Modal({...})

and then

modal.syncAccount()

Josepdal avatar Aug 01 '24 08:08 Josepdal

I am using

const modal = createWeb3Modal({...})

and then

modal.syncAccount()

Does syncAccount exist in the react lib? I don't have it on the createWeb3Modal return

chainxdev avatar Aug 27 '24 22:08 chainxdev

createWeb3Modal({
  //...
  tokens: {
    1: {
      address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
    },
    137: {
      address: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619'
    }
  }
})

I have the same issue, where the balance of custom tokens cannot be updated.

baijunjie avatar Sep 15 '24 06:09 baijunjie

Fixed in the next release.

rtomas avatar Dec 11 '24 14:12 rtomas

I was still having issues with the native balance on the React button (v1.6.5). There is no easy way of updating it. I tried calling Wagmi's getBalance, fetchBalance, even useBalance and nothing worked.

If you are still trying to update the balance, try this:

export const reownModal = createAppKit({
  ...
});

// @ts-expect-error this is a workaround
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
reownModal.updateNativeBalance();

This works because TypeScript's private modifier only restricts access at compile time. Ignoring TypeScript's errors and calling it anyway will update the button's balance.

Also, I'd suggest making this method public in the future.

PS: sorry for digging this issue, but it's the first one that appears when searching for "reown appkit refetch balance"

GiovaniGuizzo avatar Jan 24 '25 14:01 GiovaniGuizzo