likes
comments
collection
share

RainbowKitV1.0.3新版本,变动很大,也很稳定

作者站长头像
站长
· 阅读数 44

一、前言

端午放假回来,忽然发现很多在用的网站或者工具都进行了大版本更新,其中包括github的新版本UI出现(非常不适应),figma大更新,可以切换为开发模式或者设计模式,而目前使用的dapp连接工具Rainbowkit也迎来了V1.0.3版本。

话不多说,进入正题,其实RainbowkitV1版本的更新已经有一段时间的了吧,但是在刚刚发布的V1版本中,YaSol测试发现还是不稳定的,有很多rainbowkitwagmi版本适配问题没有做好,所以就选择了继续使用0.11,但是这次更新到v1.0.3后决定再试一下,看看有没有好一些了,测试发现之前1.0版本的适配问题,在1.0.3版本中没有出现,所以这次决定将项目中的Rainbowkit更新为最新版本。

二、更新后的感受

将项目中的Rainbowkit更新为最新版后,最直观的感受就是切链的时候不会再断开了,在使用v0.11版本的时候,经常一切链,项目中的连接状态就断开了,但是更新了新版本之后发现在切链的时候任然可以保持连接状态。

项目中目前是使用useAccount里面的isDisconnecteds来判断的

其次就是好像与链上交互的稳定性有了提升。目前来说,感觉还是很支持升级的。

三、配置变动

新版rainbowkit的config是有变动的,所以在更新的时候,需要注意配置的更新

3.1、config变动

1、configureChains不再返回 provider,webSocketProvider

2、getDefaultWallets需要添加一个projectId,这个id可以直接在WalletConnect网站申请

3、v0.11版本是createClient,而在V1.0.3版本中是createConfig

//v0.11 configureChains
const {chains, provider, webSocketProvider} = configureChains(
    [mainnet, polygon, goerli,polygonMumbai],
    [publicProvider()],
);
//v1.0.3 configureChains
export const { chains, publicClient } = configureChains(
  [mainnet, polygon, goerli,polygonMumbai],
  [publicProvider()]
);


//v0.11 getDefaultWallets
const {connectors} = getDefaultWallets({
    appName: "YaSol",
    chains,
});
//v1.0.3 getDefaultWallets
const { connectors } = getDefaultWallets({
  appName: 'YaSol',
  projectId: '6175672e3657ffXXXXXa0ddd3573bc745', // 新增WalletConnect的projectId
  chains
});


//v0.11 createClient
export const wagmiClient = createClient({
    autoConnect: true,
    connectors,
    provider,
    webSocketProvider,
});
//v1.0.3 createConfig
export const wagmiConfig = createConfig({
  autoConnect: true,
  connectors,
  publicClient
})


3.2、全局包裹的Provider变动
//v0.11版本的provider
<WagmiConfig client={wagmiClient}>
    <RainbowKitProvider  chains={chains}>
        {children}
    </RainbowKitProvider>
</WagmiConfig>

// v1.03版本的provider
<WagmiConfig config={wagmiConfig}>
    <RainbowKitProvider  chains={chains}>
        {children}
    </RainbowKitProvider>
</WagmiConfig>

通过上述配置文件的更新之后,你的网站基础rainbowkit就更新完啦🎉

四、获取provider实例的变动

因为新版的Rainbowkit使用了最新版的Wagmi,而最新版的Wagmi剔除了对ethers.js的依赖,而转向了Viem。因此如果在项目中我们有使用到ethersprovider时,我们就需要注意本次的更新。

//旧版的获取
const {data: signer, isLoading: signerLoadig, isError: signerError} = useSigner();
const web3 = new Web3((signer?.provider as any).provider);

但是我们在Wagmi的更新日志中可以发现,新版的Wagmi已经移除了useSigner或者fetchSigner的用法,改成了useWalletClientgetWalletClient,但是在更新日志中说了这么一句话

The getSigner method has been renamed to getWalletClient, and also returns viem's WalletClient instead of an Ethers.js Signer

大概意思就是说,你通过getWalletClient或者useWalletClient返回的是 viem 的 Wallet Client 而不是 Ethers.js Signer,那我们项目中需要用到Ethers.js的provider咋办,别慌,我们认真看一下wagmi的官网wagmi.sh/react/ether…

RainbowKitV1.0.3新版本,变动很大,也很稳定

在官网侧边的最下方,有一个Ethers.js Adapters,这个就是Wagmi在切换到viem后,考虑到可能有些项目任然需要使用ethersprovider,所以特意添加了这个Ethers.js的适配器。在适配器里面有获取ethersprovidersigner的解决方案。

4.1如果你需要获取ethers.js V5jsonRpcProvider
import * as React from 'react'
import { type PublicClient, usePublicClient } from 'wagmi'
import { providers } from 'ethers'
import { type HttpTransport } from 'viem'

export function publicClientToProvider(publicClient: PublicClient) {
  const { chain, transport } = publicClient
  const network = {
    chainId: chain.id,
    name: chain.name,
    ensAddress: chain.contracts?.ensRegistry?.address,
  }
  if (transport.type === 'fallback')
    return new providers.FallbackProvider(
      (transport.transports as ReturnType<HttpTransport>[]).map(
        ({ value }) => new providers.JsonRpcProvider(value?.url, network),
      ),
    )
  return new providers.JsonRpcProvider(transport.url, network)
}

/** Hook to convert a viem Public Client to an ethers.js Provider. */
export function useEthersProvider({ chainId }: { chainId?: number } = {}) {
  const publicClient = usePublicClient({ chainId })
  return React.useMemo(() => publicClientToProvider(publicClient), [publicClient])
}

4.2如果你需要获取ethers.js V5signer
import * as React from 'react'
import { type WalletClient, useWalletClient } from 'wagmi'
import { providers } from 'ethers'

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

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

如果你需要获取ethers.js V5Web3Provider

yasol在项目中需要使用的Web3Provider所以在官网的例子中做了一个修改,我们认真看获取signer的例子,其实里面是用到了Web3Provider的,所以我们就直接return provider记得

import * as React from 'react'
import { type WalletClient, useWalletClient } from 'wagmi'
import { providers } from 'ethers'

export function walletClientToSigner(walletClient: WalletClient) {
  const { account, 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 Signer. */
export function useEthersProvider({ chainId }: { chainId?: number } = {}) {
  const { data: walletClient } = useWalletClient({ chainId })
  return React.useMemo(
    () => (walletClient ? walletClientToSigner(walletClient) : undefined),
    [walletClient],
  )
}

五、发送交易的方法变动

这里主要以函数形式的调用来讲,Hook原理相同

//旧版
const config = await prepareWriteContract({
      address:`contractAddress`,
      abi: `contract abi`,
      functionName: `functionName`,
      args: `args`,
});
const {hash, wait} = await writeContract(config);
await wait();
//新版
import { prepareWriteContract, writeContract, waitForTransaction } from '@wagmi/core'; 
const config = await prepareWriteContract({
    address:`contractAddress`,
      abi: `contract abi`,
      functionName: `functionName`,
      args: `args`,
});
const { hash } = await writeContract(config);
const receipt = await waitForTransaction({ hash });
console.log("receipt", receipt);
if (receipt?.status !== "success") {
  console.log(receipt);
  throw new Error(errorMessage);
}

六、错误信息变动

在旧版的时候,我们只需要trycatch以下,然后再catch里面捕获错误,最后用err.message就能拿到干净的错误信息。

比如:在与钱包交互的时候,用户拒绝了本次交互,那么我们使用err.message就能很完美的捕获到错误,但是新版中的err.message不仅有错误信息还有一些data数据以及viem版本信息

// 旧版v0.11
User rejected the request.
//新版本v1.0.3
User rejected the request.

Request Arguments:
  from:  0x7857AeB275cE51f7C3338D9f4D2676A329A021ec
  to:    0x61011FefaC5A24f30C5811801A691698A65c7A28
  data:  0x2846c41500000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000260000000000000007857aeb275ce51f7c3338d9f4d2676a329a021ec0000000012000000000000000000000000000000000000000000000000000000000000000b3132333132333132333132000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b3132333132333132333132000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005d68747470733a2f2f6170692e6c696b6e2e636f2f6e66742f6e66742f3735353430323137343639383137343130363939373037333031393539353436333134303136333637303432353032363632353432323735333831302f7b69647d000000000000000000000000000000000000000000000000000000000000000000005f68747470733a2f2f6170692e6c696b6e2e636f2f6e66742f636f6c6c656374696f6e2f37353534303231373436393831373431303639393730373330313935393534363331343031363336373034323530323636323534323237353338313000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000021b0b84ffab5a8c48291f5ec9d9fdb9aef574052

Details: MetaMask Tx Signature: User denied transaction signature.
Version: viem@1.1.7

解决办法:

在拿到err.message后用split(".")去截取到User rejected the request类似的错误信息

import {sendMessage} from "./message";

const errorMessage = (err: any) => {
    console.log(err.message);
    const metamaskError = err?.message?.split(".")[0] || "Unknown error";
    const message = err?.message ? metamaskError : err;
    sendMessage("error", message);
};
export default errorMessage;

总结

RainbowkitWagmi的本次更新相对来说是变动比较大的,在更新日志中有一大堆更新,但是以上内容只是针对项目目前需要而写的一部分,大家也可以前往Wagmi的更新日志中查看全部更新,做了很多优化,有机会的话,也去看看viem的用法。以上的解决方案仅为自己的想法和思路,如果有更好的方法,欢迎大家相互讨论学习。

Wagmi更新日志:wagmi.sh/core/migrat…

转载自:https://juejin.cn/post/7248890696819933245
评论
请登录