walletconnect 供应商 用法

walletconnect 供应商 使用

walletconnect官网有两种用法

1、Web3Modal

2、providers

本文介绍ethereum providers的使用

1、下载依赖

// npm
$ npm install @walletconnect/ethereum-provider @walletconnect/modal
// pnpm
$ pnpm add @walletconnect/ethereum-provider @walletconnect/modal

2、walletconnect使用

1、申请projectID

​ 官网申请:walletconnect.com

2、引入所需要的依赖

import { ethers } from 'ethers';
import EthereumProvider from '@walletconnect/ethereum-provider';
import {
  REQUIRED_METHODS,
  REQUIRED_EVENTS,
} from '@walletconnect/ethereum-provider';

3、walletconnect

1、准备配置walletconnect的参数
// 初始化walletconnect需要的参数
const singClientOption = {
  logger: 'warn',
  relayUrl: 'wss://relay.walletconnect.com',
  projectId: PROJECT_ID, // 输入自己的projectID,
  showQrModal: true, // 是否显示二维码页面
  methods: [...REQUIRED_METHODS, 'eth_signTypedData_v4'],
    events: [...REQUIRED_EVENTS],
    chains: [56],
    optionalChains: [56, 10, 137, 43114, 1],
    metadata: {
      name: '项目名称',
      description: '项目简介',
      url: window.location.host, // 项目地址
      icons: [`${window.location.origin}/favicon.svg`], // 项目icon
    },
};
2、创建walletconnect类
// 没有Provider输出错误
class ProviderNotFoundError extends Error {
  constructor() {
    super('Not found provider');
  }
}

// 是否需要自动连接
interface IConnectorOpt {
  autoConnect?: boolean;
}

// class
export class WalletConnectConnector {
  #wcProvider?: EthereumProvider;
  connectOpt?: IConnectorOpt;
  #onDisconnectHandler?: (error: unknown) => void;
  #onAccountsChangedHandler?: (accounts: string[]) => void;
  #onChainChangedHandler?: (chainId: string) => void;

  get provider(): ethers.providers.Web3Provider {
    if (!this.#wcProvider) throw new ProviderNotFoundError();
    // 构造ethers的providers,方便使用
    const provider = new ethers.providers.Web3Provider(this.#wcProvider);
    return provider;
  }
  constructor(opt?: IConnectorOpt) {
    this.connectOpt = opt;
    this.init(true);
  }

  // 初始化Provider
  async init(reset?: boolean) {
    if (reset) {
      this.#wcProvider = undefined;
    }
    if (!this.#wcProvider) {
      const provider = await await EthereumProvider.init({
        projectId: singClientOption.projectId,
        showQrModal: singClientOption.showQrModal,
        methods: singClientOption.methods,
        events: singClientOption.events,
        chains: singClientOption.chains,
        optionalChains: singClientOption.optionalChains,
        metadata: singClientOption.metadata,
      }).then(async (e) => {
        this.#wcProvider = e;
        return e;
      });
      return provider;
    } else {
      return this.#wcProvider;
    }
  }

  // 连接
  async connect(reset?: boolean) {
    if (!this.connectOpt?.autoConnect) {
      reset = true;
    }
    const provider = await this.init(reset);
    const session = await this.isConnected(); // 是否已连接

    if (session) {
      if (reset) {
        try {
          await provider.disconnect();
          await this.disconnect();
        } catch (error) {
          console.log(error);
        }
      }

      const [accounts, network] = await Promise.all([
        provider.enable(),
        Promise.race<ethers.providers.Networkish>([
          this.provider.send('eth_chainId', []).then((e) => {
            return Number(e);
          }),
          this.provider.getNetwork().then((e) => e.chainId),
        ]).then((e) => {
          return Number(e);
        }),
      ]);
      if (accounts[0]) {
        return {
          accounts,
          provider: new ethers.providers.Web3Provider(provider),
          network,
        };
      }
    }

    // 默认连接
    const isConnected = await Promise.race([
      provider
        .connect({
          chains: [56],
          optionalChains: [56, 10, 137, 43114, 1], // 待选链
          rpcMap: { // rpc连接
            56: 'https://rpc',
            10: 'https://rpc',
            137: 'https://rpc',
            43114: 'https://rpc',
            1: 'https://rpc',
          },
          pairingTopic: reset ? undefined : provider.session?.pairingTopic,
        })
        .then((e) => {
          console.log(e);
          return true;
        })
        .catch((e) => {
          console.log(e);
          return false;
        }),
      new Promise((resolve) => {
        provider.once(WalletConnectEvents.CONNECT, () => {
          resolve(true);
        });
        provider.modal?.subscribeModal((e: { open: any }) => {
          if (!e?.open) resolve(false);
        });
      }),
    ]);
    if (!isConnected) {
      throw Error('Modal Closed, Please try again');
    } else {
      console.log(isConnected);

      const [accounts, network] = await Promise.all([
        provider.enable(),
        Promise.race<ethers.providers.Networkish>([
          this.provider.send('eth_chainId', []).then((e) => {
            return Number(e);
          }),
          this.provider.getNetwork().then((e) => e.chainId),
        ]).then((e) => {
          return Number(e);
        }),
      ]);

      if (!accounts[0]) {
        throw Error('no account connected');
      }
      return {
        accounts,
        provider: new ethers.providers.Web3Provider(provider),
        network,
      };
    }
  }

  // 断开
  async disconnect() {
    return await this.#wcProvider?.disconnect();
  }

  // 是否已连接
  async isConnected(): Promise<boolean> {
    if (!this.connectOpt?.autoConnect) return false;
    if (!this.#wcProvider) {
      await this.init();
    }
    return !!this.#wcProvider?.connected;
  }

  // 切换链
  async switchChain(chainId: ChainIds) {
    if (!this.provider) throw new ProviderNotFoundError();
    const evmParameter = getEvmChainParameter(chainId);

    try {
      await this.provider.send('wallet_switchEthereumChain', [{ chainId: evmParameter.chainId }]);
    } catch (err: any) {
      if (err.code === 4902) {
        try {
          const evmParameter = getEvmChainParameter(chainId);

          await this.addChain(evmParameter);
        } catch (err: unknown) {
          console.error(err);
        }
      }
    }
  }

  // 添加chain
  async addChain(networkDetails: EvmChainParameter) {
    if (!this.provider) throw new ProviderNotFoundError();
    try {
      this.provider.send('wallet_addEthereumChain', [networkDetails]);
    } catch (err: unknown) {
      throw Error('wallet_addEthereumChain \n');
    }
  }

  // 监听方法:断开连接时
  onDisconnect(handler: (error?: unknown) => void) {
    if (!this.#wcProvider) throw new ProviderNotFoundError();
    if (this.#onDisconnectHandler) {
      this.#wcProvider.removeListener('disconnect', this.#onDisconnectHandler);
      this.#wcProvider.removeListener('session_delete', this.#onDisconnectHandler);
    }
    this.#onDisconnectHandler = handler;
    this.#wcProvider.on('disconnect', () => {
      handler();
    });
    this.#wcProvider.on('session_delete', () => {
      handler();
    });
  }

  // 监听方法:切换用户时
  onAccountsChanged(handler: (accounts: string[]) => void) {
    if (!this.#wcProvider) throw new ProviderNotFoundError();
    if (this.#onDisconnectHandler) {
      this.#wcProvider.removeListener('accountsChanged', this.#onDisconnectHandler);
    }
    this.#onAccountsChangedHandler = handler;
    this.#wcProvider.on('accountsChanged', (accounts: string[]) => {
      handler(accounts);
    });
  }

  // 监听方法:切换链时
  onChainChanged(handler: (chainId: string) => void) {
    if (!this.#wcProvider) throw new ProviderNotFoundError();
    if (this.#onChainChangedHandler) {
      this.#wcProvider.removeListener('chainChanged', this.#onChainChangedHandler);
    }
    this.#onChainChangedHandler = handler;
    this.#wcProvider!.on('chainChanged', (chainId: string) => {
      handler(chainId);
    });
  }
}
3、使用
// 初始化 WalletConnectConnector
const walletconnect = new WalletConnectConnector();

// 判断是否已经连接
walletconnect?.isConnected()

// 没连接的话,连接
walletconnect?.connect(false).then((e) => {
  // ----开始监听
  // 切换用户
  walletconnect?.onAccountsChanged async (accounts) => {
    accounts[0] // 最新连接的用户
  });
  // 切换链
  walletconnect?.onChainChanged(async (chainId) => {
    chainId // 切换的链
  });
  // 断开链接
  connector?.onDisconnect(() => {});
  return;
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值