widgets icon indicating copy to clipboard operation
widgets copied to clipboard

SwapWidget not accepting ethers providers

Open rowanryan opened this issue 3 years ago • 10 comments

Bug Description Ethers.js FallbackProvider not working with SwapWidget. The FallbackProvider is what is returned by ethers.getDefaultPovider(). When using an editor like VSCode, the editor tells you that the passed in provider is missing properties of the jsonRpcProvider. This is weird, because the documentation says I can also pass in any ethers provider or any EIP-1193 provider.

Steps to Reproduce

  1. Import the SwapWidget on a page.
  2. Create a provider using ethers.getDefaultProvider()
  3. Pass the ethers provider into the provider props of the SwapWidget.
  4. You will get an error saying that the SwapWidget doesn't accept this provider.

Expected Behavior I expect the widget to accept any ethers provider, like the documentation says.

Additional Context I am using version 2.8.1 of the "@uniswap/widgets package". Version 5.7.0 of the "ethers" package.

Image of the error: image

rowanryan avatar Sep 21 '22 15:09 rowanryan

Yeah i have the same issue, using the most recent version of wagmi, I cant use the provider in the Uni wap widget. Seems like it must be an older version of the provider needed, not sure exactly which version tho,

0x2me avatar Oct 07 '22 12:10 0x2me

I think it's just a typescript error so if you cast your provider to a Web3Provider it will work. provider={provider as Web3Provider}

0x2me avatar Oct 07 '22 14:10 0x2me

I think it's just a typescript error so if you cast your provider to a Web3Provider it will work. provider={provider as Web3Provider}

I tried this now. It doesn't give the typescript error anymore, but it also doesn't work. I still have to manually connect my wallet through the widget. It doesn't detect the provider.

I also use wagmi, by the way.

rowanryan avatar Oct 07 '22 14:10 rowanryan

https://wagmi.sh/docs/hooks/useWebSocketProvider use the websocket provider. It worked for me. You actually don't need the cast then. You have to pass in the chain Id through

0x2me avatar Oct 07 '22 16:10 0x2me

https://wagmi.sh/docs/hooks/useWebSocketProvider use the websocket provider. It worked for me. You actually don't need the cast then. You have to pass in the chain Id through

So, I tested it, and it does work for fetching the price, but unfortunately it is still not picking up on the actual connected wallet. I connected my wallet through WalletConnect using wagmi, but the widget was still connected to my metamask wallet that is installed in my browser (google chrome). I think we'll just have to wait for Uniswap to update the widget.

Thank you for these tips, though.

rowanryan avatar Oct 09 '22 17:10 rowanryan

I figured out, that we should get provider from wallet connector. So I done something like:

  • useAccount to fetch connector
  • connector.getProvider() returns Promise, so either use react-query, either use effect and state hooks
  • then cast provider to any to skip ts errors
  • also we need react on isConnected, to remove provider from state. If user has disconnected their wallet

ilmpc avatar Nov 03 '22 00:11 ilmpc

@rowanryan did anything change regarding this after the latest updates to the widget?

zyrm avatar Jan 17 '23 16:01 zyrm

This is what I found working with the latest wagmi and @uniswap/widgets

import { Web3Provider } from '@ethersproject/providers'
import { useAccount } from 'wagmi'
import { SwapWidget } from '@uniswap/widgets'

// some code...

const [provider, setProvider] = useState<Web3Provider | undefined>()
const { connector } = useAccount()
useEffect(() => {
  if (!connector) {
    return () => setProvider(undefined)
  }

  connector.getProvider().then((provider) => {
    setProvider(new Web3Provider(provider))
  })
}, [connector])

// some code...

        <SwapWidget
          provider={provider} />

fdarian avatar Feb 27 '23 06:02 fdarian

@farreldarian Nice solution! I spent hours on this today and came up with a slightly different approach.

export function walletClientToProvider(walletClient: WalletClient) {
  const { chain, transport } = walletClient
  const network = {
    chainId: chain.id,
    name: chain.name,
    ensAddress: chain.contracts?.ensRegistry?.address,
  }
  const provider = new providers.Web3Provider(transport as any, network)
  return provider
}

/** Hook to convert a viem Wallet Client to an ethers.js Web3Provider. */
export function useEthersWeb3Provider({ chainId }: { chainId?: number } = {}) {
  const { data: walletClient } = useWalletClient({ chainId })
  return React.useMemo(
      () => (walletClient ? walletClientToProvider(walletClient) : undefined),
      [walletClient],
  )
}

Then just get the provider for the widget:

const { chain } = useNetwork()
const provider = useEthersWeb3Provider({chain?.id})

paintoshi avatar Sep 18 '23 17:09 paintoshi

@paintoshi the widget keep refreshing and loosing state using this method - any ideas ?

ZiggStardust avatar Nov 23 '23 16:11 ZiggStardust