天天看点

React+Typescript调用Terra Station Wallet, 以及React+Typescript集成Rust wasm1、环境介绍:2、创建react项目3、创建rust项目4、安装react依赖5、报错更改6、钱包连接 (至此可以参照terra官方文档调用钱包)7、wasm调用

1、环境介绍:

rust 1.61.0

cargo 1.61.0

wasm-pack 0.10.3

node 18.10.0

yarn 1.22.10
           

2、创建react项目

//本项目名为wasmapp-react
//1、创建react项目
npx create-react-app wasmapp-react --template typescript
           

3、创建rust项目

//2、创建rust项目 rust项目名为wasm-hello
cd wasmapp-react
cargo new --lib wasm-hello
           

当前项目目录结构如下:

(base) ➜  wasmapp-react (master) ✗ tree
.
├── README.md
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   └── setupTests.ts
├── tsconfig.json
└── wasm-hello
    ├── Cargo.toml
    └── src
        └── lib.rs
           

4、安装react依赖

//以下按顺序执行
yarn

yarn add @terra-money/terra.js
yarn add @terra-money/wallet-provider
           

将terra依赖引入index.tsx,并修改index.tsx内容:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'semantic-ui-css'
import {getChainOptions ,WalletProvider} from '@terra-money/wallet-provider'

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
getChainOptions().then(chainOptions => {
  root.render(
    <WalletProvider {...chainOptions}>
      <App />
    </WalletProvider>
  );
})

reportWebVitals();
           

启动项目:

yarn start
           

上述步骤执行完,浏览器应该会报如下错误:

1、Uncaught ReferenceError: Buffer is not defined

    at ./node_modules/@terra-money/terra.js/dist/core/PublicKey.js (bundle.js:28070:34)

2、Uncaught ReferenceError: stream is not defined

发生报错后,页面是无法正常显示,我们需要做如下工作:

5、报错更改

出现上述错误是因为浏览器加载不到Buffer,我们是否可以通过yarn add buffer解决呢,并不行。

为解决上述错误,我们需要对webpack配置进行改造:

首先我们需要新增一些react依赖包:

yarn add --dev react-app-rewired process crypto-browserify stream-browserify assert stream-http https-browserify os-browserify url buffer next-tick
           

安装完依赖之后我们需要修改两个文件:

(1)package.json

in package.json
//before edit

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },


// after edit

 "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "build:wasm": "cd wasm-hello && wasm-pack build --target web --out-dir pkg",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  },
           

(2)tsconfig.json

{
  "compilerOptions": {
    "paths" : {
      "crypto": ["./node_modules/crypto-browserify"],
      "stream": ["./node_modules/stream-browserify"],
      "assert": ["./node_modules/assert"],
      "http": ["./node_modules/stream-http"],
      "https": ["./node_modules/https-browserify"],
      "os": ["./node_modules/os-browserify"]
    },
    "target": "ES2018",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "watch": true,
  },
  "include": [
    "src"
  ]
}
           

做完上述修改工作我们还需新建两个文件

(1)项目根目录创建config-overrides.js

此文件为了替换webpack的部分配置

const webpack = require('webpack');

module.exports = function override(config) {
    const fallback = config.resolve.fallback || {};
    Object.assign(fallback, {
        "crypto": require.resolve("crypto-browserify"),
        "stream": require.resolve("stream-browserify"),
        "assert": require.resolve("assert"),
        "http": require.resolve("stream-http"),
        "https": require.resolve("https-browserify"),
        "os": require.resolve("os-browserify"),
        "url": require.resolve("url")
    })
    config.resolve.fallback = fallback;
    config.plugins = (config.plugins || []).concat([
        new webpack.ProvidePlugin({
            process: 'process/browser',
            Buffer: ['buffer', 'Buffer']
        })
    ])
    config.ignoreWarnings = [/Failed to parse source map/];
    return config;
}
           

(2) 在src目录下新建polyfills.ts

import { Buffer } from 'buffer';
(window as any).global = window;
global.Buffer = Buffer;
global.process = {
    env: { DEBUG: undefined },
    version: '',
    nextTick: require('next-tick')
} as any;
           

(3)在index.tsx引入polyfills.ts:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import './polyfills';
import reportWebVitals from './reportWebVitals';
import {getChainOptions ,WalletProvider} from '@terra-money/wallet-provider'

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
getChainOptions().then(chainOptions => {
  root.render(
    <WalletProvider {...chainOptions}>
      <App />
    </WalletProvider>
  );
})

reportWebVitals();
           

6、钱包连接 (至此可以参照terra官方文档调用钱包)

7、wasm调用

rust编写的函数要让react访问到需要使用rust的wasm-bindgen依赖

只需执行cargo install wasm-pack即可,wasm-pack在运行时会自动下载wasm-bindgen

我们需要修改Cargo.toml文件如下:

[package]
name = "wasm-hello"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
wasm-bindgen = "0.2.63"
           

在lib.rs文件中定义我们的函数:

use wasm_bindgen::prelude::*;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[wasm_bindgen]
extern {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(hel:&str) {
    let init = "Hello, wasm-vue".to_string();
    let res =init +  &hel;
    alert(&res);
}
           

至此我们需将rust编译为wasm形式:

在步骤5中,我们已经在package.json中配置了build:wasm命令,以编译rust
所以,我们只需执行:

yarn build:wasm
           

执行完之后, wasm-hello文件夹中会新增pkg文件夹

React+Typescript调用Terra Station Wallet, 以及React+Typescript集成Rust wasm1、环境介绍:2、创建react项目3、创建rust项目4、安装react依赖5、报错更改6、钱包连接 (至此可以参照terra官方文档调用钱包)7、wasm调用

 最后,我们需要将rust编译后的内容install到node_modules中:

// 项目根目录执行
yarn add ./wasm-hello/pkg
           
React+Typescript调用Terra Station Wallet, 以及React+Typescript集成Rust wasm1、环境介绍:2、创建react项目3、创建rust项目4、安装react依赖5、报错更改6、钱包连接 (至此可以参照terra官方文档调用钱包)7、wasm调用

至此,我们的钱包调用和wasm集成都完成了,重新启动项目即可

项目代码见github:

GitHub - shaozhupeng/wasmapp-react: react+typescript+rust + wasm, terra wallet provider, terra.js