本节作者:@LiKang 以太坊除了有主网和测试网以外还有丰富的 L2 生态,对于有的 DApp 来说可能需要连接不同的链。这一讲将会指引开发者如何在 DApp 中连接多条链。 多链 DApp 支持多链是指能够在多个区块链平台上运行或与之交互。这意味着 DApp 不仅限于单一的区块链生态系统,而是可以跨越不同的区块链,利用各个平台的特点和优势,以提供更广泛的功能、更好的用户体验或更高的效率。可以使用户利用在一个区块链上的资产,在另一个区块链上进行操作。例如,用户可以将某区块链上的代币通过跨链技术(如区块链桥)转移到另一个区块链上, DApp 可以在这两个链上识别并使用这些资产。不同的区块链平台具有不同的技术特性和优势,比如交易速度、费用等。
本节作者:@LiKang
以太坊除了有主网和测试网以外还有丰富的 L2 生态,对于有的 DApp 来说可能需要连接不同的链。这一讲将会指引开发者如何在 DApp 中连接多条链。
DApp 支持多链是指能够在多个区块链平台上运行或与之交互。这意味着 DApp 不仅限于单一的区块链生态系统,而是可以跨越不同的区块链,利用各个平台的特点和优势,以提供更广泛的功能、更好的用户体验或更高的效率。可以使用户利用在一个区块链上的资产,在另一个区块链上进行操作。例如,用户可以将某区块链上的代币通过跨链技术(如区块链桥)转移到另一个区块链上, DApp 可以在这两个链上识别并使用这些资产。不同的区块链平台具有不同的技术特性和优势,比如交易速度、费用等。每个链都有其自身的用户社区,支持多链也可以帮助 DApp 将这些不同社区的用户聚集起来。
实现 DApp 支持多链通常需要开发者使用一些特定的技术和工具,比如跨链桥、智能合约多版本管理、以及可能的链间通讯协议等。虽然这可能会增加开发和维护的复杂性,但鉴于其带来的多元化和扩展性优势,越来越多的 DApp 选择支持多个区块链。
我们以一个多链的 NFT 合约为例,为了使 NFT 支持多链,通常需要使用以下几种技术或方法:
在前边的 第四讲 和 第五讲 中我们已经学习过了合约的调用和事件监听,那我们就在这个基础上继续学习支持多链,改造代码如下:
import { createConfig, http, useReadContract, useWriteContract } from "wagmi"; - import { mainnet, sepolia } from "wagmi/chains"; + import { mainnet, sepolia, polygon } from "wagmi/chains"; import { WagmiWeb3ConfigProvider, MetaMask, Sepolia, + Polygon } from "@ant-design/web3-wagmi"; import { Address, NFTCard, Connector, ConnectButton, useAccount, + useProvider } from "@ant-design/web3"; import { injected } from "wagmi/connectors"; import { Button, message } from "antd"; import { parseEther } from "viem"; const config = createConfig({ - chains: [mainnet, sepolia], + chains: [mainnet, sepolia, polygon], transports: { [mainnet.id]: http(), [sepolia.id]: http(), + [polygon.id]: http(), }, connectors: [ injected({ target: "metaMask", }), ], }); + const contractInfo = [ + { + id:1, + name: "Ethereum", + contractAddress: "0xEcd0D12E21805803f70de03B72B1C162dB0898d9" + }, { + id:5, + name: "Sepolia", + contractAddress: "0x418325c3979b7f8a17678ec2463a74355bdbe72c" + }, { + id:137, + name: "Polygon", + contractAddress: "0x418325c3979b7f8a17678ec2463a74355bdbe72c" + } + ] const CallTest = () => { const { account } = useAccount(); + const { chain } = useProvider(); const result = useReadContract({ abi: [ { type: "function", name: "balanceOf", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ type: "uint256" }], }, ], - // Sepolia test contract 0x418325c3979b7f8a17678ec2463a74355bdbe72c - address: "0xEcd0D12E21805803f70de03B72B1C162dB0898d9", + address: contractInfo.find((item) => item.id === chain?.id)?.contractAddress as `0x${string}`, functionName: "balanceOf", args: [account?.address as `0x${string}`], }); const { writeContract } = useWriteContract(); return ( <div> {result.data?.toString()} <Button onClick={() => { writeContract( { abi: [ { type: "function", name: "mint", stateMutability: "payable", inputs: [ { internalType: "uint256", name: "quantity", type: "uint256", }, ], outputs: [], }, ], - address: "0xEcd0D12E21805803f70de03B72B1C162dB0898d9", + address: contractInfo.find((item) => item.id === chain?.id)?.contractAddress as `0x${string}`, functionName: "mint", args: [1], value: parseEther("0.01"), }, { onSuccess: () => { message.success("Mint Success"); }, onError: (err) => { message.error(err.message); }, } ); }} > mint </Button> </div> ); }; export default function Web3() { return ( <WagmiWeb3ConfigProvider config={config} - chains={[Sepolia]} + chains={[Sepolia, Polygon]} wallets={[MetaMask()]} > <Address format address="0xEcd0D12E21805803f70de03B72B1C162dB0898d9" /> <NFTCard address="0xEcd0D12E21805803f70de03B72B1C162dB0898d9" tokenId={641} /> <Connector> <ConnectButton /> </Connector> <CallTest /> </WagmiWeb3ConfigProvider> ); }
当我们点击链切换为 Polygon 时,就可以看到如下弹窗:

@ant-design/web3 提供的 useProvider,则可以拿到当前链的信息,我们通过切换的链 ID 去找到我们在 contractInfo 里存的不同链的合约地址,去获取余额和点击 mint 按钮发到不同的链和相应的合约地址。