1.2.71 • Published 2 years ago

@dodoex/wallet v1.2.71

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

dodo-web 项目抽出来的钱包模块,意图独立钱包相关的逻辑,方便维护升级,也希望可以在将来的其他项目中直接引用,目前是 Init 版本,仅规范了一些用法和一部分监听逻辑

使用(可参照 example)

初始化

import { initWallet, WalletReducer } from 'dodo-wallet';
import { createStore, combineReducers, compose, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import mixpanel from 'mixpanel-browser';
import { enUS as walletEnUS, zhCN as walletZhCN } from 'dodo-wallet';

mixpanel.init('8b3e8750fd267914f7911af086a5e5d7');

// ... 处理多语言

const store = createStore(
  combineReducers(WalletReducer),
  undefined,
  compose(applyMiddleware(thunkMiddleware)),
);
initWallet({
  walletConfig: {
    ETH_NETWORK: 'mainnet',
    PORTIS_ID: 'portis',
  },
  customChainConfig: {},
  projectStore: store,
  projectMixpanel: mixpanel,
});

initWallet 初始化一些环境变量级别的配置和项目本身的 Store,参数说明:

walletConfig: {
  ETH_NETWORK, // 初始化web3Modal以及指定默认ChainId
  PORTIS_ID    // 初始化Portis
}
customChainConfig // 选填,自定义配置,目前支持multicallAddr字段,用于打包RPC查询请求
store // 项目的Store,WalletReducer在项目初始化store的时候要放到Reducers里,```state.dodoWallet```就是钱包的reducer

API

Hooks

useDODOWallet(); // 自动连接浏览器插件钱包,监听TokenList变化和ProxyAddress变化加载TokenList的Balance和Allowance
useBlockNumberTimer(); // 轮询区块高度,每13秒查询一次
useBalancesTimer(); // 轮询ETH余额,每13秒查询一次

Actions,举例两个特殊的 Action,setTokens setProxyAddress,他们除了更新 Reducer 数据外,还会触发一些其他的逻辑。使用useDODOWallet()时,初始 Store 里的 Tokens 和 ProxyAddress 是undefined,当 Tokens 和 ProxyAddress 发生改变时会去查询 Balance 和 Allowance,意味着只要有 TokenList,并且连接钱包成功获取到钱包地址,那么就会去加载一次全部 Token 的 Balance,同时如果存在 ProxyAddress,那么就会加载一次全部的 Allowance。这里没有轮询的逻辑,如果需要更新数据则需要手动执行loadTokenBalancesloadTokenAllowances

Selectors,如果是一次性的查询,可以直接用getCurrentAccount()方法获取到当前连接到的钱包地址,如果需要 Hooks 监听状态变化,则可以使用useSelector(getCurrentAccount)

web3,定义了一些 web3 方法,如connectToWallet连接钱包。也可以通过getWeb3()来直接获取一个 web3 实例。

开发流程

根目录执行yarn安装依赖和本地打包 package 文件

建立本地 package 软链接

yarn link

进入到example/路径或 dodo-web 项目下

alias 不能使用不同依赖的包

yarn link @dodoex-io/wallet 后,dodo-wallet 下的文件会使用最近一层的 node_modules,外部的文件使用自身项目的 node_modules 。导致两者不唯一。使用 alias ,确保使用的是同一个包.

// config-overrides.js (for create-react-app)
const path = require('path');
const {
  override,
  addWebpackAlias,
} = require('customize-cra');

const webpackAlias = {
  src: path.resolve(__dirname, 'src'),
};
if (process.env.NODE_ENV !== 'production') {
  // avoid Link leading to depends on errors
  const reactLinkPackages = [
    'react',
    'react-dom',
    'react-router-dom',
    'react-redux',
    'styled-components',
    'react-i18next',
    'redux',
  ];
  reactLinkPackages.forEach((pkg) => {
    webpackAlias[pkg] = path.resolve(__dirname, `node_modules/${pkg}`);
  });
}

const overrides = [
  addWebpackAlias(webpackAlias)
];

module.exports = override(...overrides);

执行

yarn
yarn link @dodoex-io/wallet
yarn run start

运行 example,默认写了 3000 端口,浏览器打开页面进行调试

Add new chain

  • chainConfig.ts
  • wallet.ts registerArbitrumNetworkWithMetamask()
  • src/components/images/networks-logo/CHAIN.svg
  • NetworkMismatchDialog.ts registerMap
  • WalletsPage.ts Network networkKeyMap networkMatchChainNameMap chainLogoMap list handleChange
  • utils/wallet.ts getChainIdWithNetworkName getNetworkNameWithChainId isETHOrBSCChain ChainType getChainType validNetworkList

新增配置

新增 chain

  1. 配置 chainConfigs.ts;
  2. 配置 injects/chain/types 下的 ChainType;
  3. 配置 injects/chain/constant.ts;
  4. 如果可代码切换 chain,在 NetworkMismatchDialogwallet.ts 下配置相关切换代码;

新增 wallet

  1. 配置 injects/wallet/types 下的 WalletType (如果是 inject ,则无需配置);
  2. 配置 injects/wallet/constant.ts;

单元测试

监听 __tests__ 文件下的 [jt]sx?,使用 js-dom 环境执行

测试步骤

yarn test:unit

setup

默认执行 testUtils/setup.ts 文件,初始化 wallet ,并简单 mock metamask 环境

hooks

使用 @testing-library/react-hooks 测试

import { renderHook } from '@testing-library/react-hooks/dom';

it('should use counter', () => {
  const { result } = renderHook(() => useCounter())

  expect(result.current.count).toBe(0)
  expect(typeof result.current.increment).toBe('function')
});

组件渲染

封装 @testing-library/react 渲染,注入项目需要的一些 配置

import { renderProvider, store } from '../../../testUtils/init';

// PC
renderProvider(
  <div>children render</div>
)

// mobile
renderProvider(
  <div>children render</div>
, true)

多语言

import i18n from '../../../testUtils/i18n';
import { screen } from '@testing-library/react';

// ...render

it(('title is exist') => {
  const title = i18n.t('wallet.dialog.network-mismatch.title1');
  expect(screen.queryByText(title)).toBeTruthy();
})

redux

import { renderProvider, store } from '../../../testUtils/init';

// ...render

it(('set redux') => {
  store.dispatch(setChainId(1));
  expect(store.getState().dodoWallet.get('chainId')).toBe(1);
})

e2e 测试

目录结构

├── e2e
│   ├── setup.ts // .env 赋值
│   ├── chrome-data // chrome 生成的用户数据
│   ├── commands // 测试站点的封装
│   │   ├── metamask.ts
│   │   └── wallet.ts
│   ├── extension
│   │   └── metamask-chrome-10.0.1
│   ├── integration // 测试
│   │   └── connectWallet.ts
│   └── support
│       ├── constants.ts // 常量的配置。包括测试地址,钱包助记词等(可直接在 .env 配置)
│       └── helpers.ts
├── src
│   └── dom.ts // test-id 配置,供定位 dom 使用
├── .env // 常量配置
├── jest.config.ts // 单元测试配置
├── jest-e2e.config.js // e2e 测试配置
├── jest-e2e.sequencer.js // test-sequencer 配置
└── jest-puppeteer.config.js // puppeteer 启动浏览器配置

测试步骤

  1. 配置 .env (可选)。对应 e2e/support/constants.ts 文件
TEST_URL=http://localhost:3000
WALLET_KEY=jelly interest enjoy grace energy battle brief private duck rent alarm call
WALLET_PWD=12345678
  1. 运行示例站点。这里以 example 为例
yarn link

cd example
yarn link @dodoex-io/wallet
yarn start # server localhost:3000
  1. 执行测试
# dodo-wallet 根目录
yarn test:e2e

相关文档

Tips

  1. peerDependencies 的包直接使用 yarn add -P @owen05/dodo-sdk-v2 安装后再调用 yarn 安装之后该包会被删掉,导致 build 报错。参考 How to handle peer dependencies when developing modules 使用 install-peers-cli 和 prepare 脚本来在 yarn 之后执行 peers 的安装,而 prepare 脚本在包被其他项目安装时不会被执行,避免了安装重复的包。

  2. 修改打包配置,默认包为 commonjs 模块的包可以在 nodejs 环境例如 nextjs 中使用,es 模块的包会被 webpack 自动识别在浏览器环境下使用。