0.1.3 • Published 2 years ago

@bobliao/web3-express-react v0.1.3

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

npm.io


English

Web3 express react - Reference API

Introduction:

1.Make you create React + web3js projects fastly & simply。 2.Systematically helps you manage contracts or networks under developement or production environment of your project。 3.With a configing tool (Contract-config-setter) ,contracts and configurations in your project can be automatically and quickly replaced,it will make more easer and faster of maintaining your projects. 4.GUI-Built in,could use the GUI of this package built in,fast and easely make friendly web3 experience。

Package features:

1.Out-of-the-box,can simply make wallet connect or install thow just a Function(). 2.Can directly obtain whether the current wallet is logged in and whether the network link is wrong through the exported status from this package.。 3.Intelligent network management. When Web3 express is running in the state of unlinked but wallet installed, Web3 express will work under the mode of HTTP-Node. When it's running in the working state of wallet linked, it will interact with the blockchain through the wallet. All these are automatic, without manual judgment and switching.。 4.walletConnect package built in

Install package

npm install @bobliao/web3-express-react

yarn add @bobliao/web3-express-react

pnpm install @bobliao/web3-express-react

Global Configuration In Your Project

Once the @bobliao/web3-express-react has been installed in your project,first thing is to set up the common parts of @bobliao/web3-express-react in your project of top component javascript file.

for excample app.js:

import Web3Express from "@bobliao/web3-express-react";

//Take out the hooks,and global contexts
const { useCommon, useWallet, commonContext, walletContext } = Web3Express;

//Use 'useCommon' hook to get common object
const commonObject = useCommon("development");
//Use `useWallet` hook to get walletHalper object
const walletHalper = useWallet(false, "development");

//Put `commonObject`,`walletHalper` inside `commonContext`,`walletContext` top of all your usiness code
return (
	<commonContext.Provider value={commonObject}>
		<walletContext.Provider value={walletHalper}>
			<ExcOne></ExcOne>
		</walletContext.Provider>
	</commonContext.Provider>
);

Fully excample:

import "./App.css";
import ExcOne from "./views/excamples/excOne";
import Web3Express from "@bobliao/web3-express-react";

function App() {
	//Take out the hooks,and global contexts
	const { useCommon, useWallet, commonContext, walletContext } = Web3Express;

	//Use 'useCommon' hook to get common object
	const commonObject = useCommon("development");
	//Use `useWallet` hook to get walletHalper object
	const walletHalper = useWallet(false, "development");

	return (
		<commonContext.Provider value={commonObject}>
			<walletContext.Provider value={walletHalper}>
				{/*
						Need to put all of those two contexts upon top all of your code,then your code can be use the @bobliao/web3-express-react.
					*/}
				<ExcOne></ExcOne>
			</walletContext.Provider>
		</commonContext.Provider>
	);
}

export default App;

Attention!

const commonObject = useCommon("development");
const walletHalper = useWallet(false, "development");

This part need to set with an environment variable,When usinguseCommon("development");anduseWallet(false, "development"), the "development"parameter need to replace with a environment variable of your project ,like NODE_ENV,you need to set like this in actual use:

const commonObject = useCommon(NODE_ENV);
const walletHalper = useWallet(false, NODE_ENV);

May need to set webpack.DefinePlugin in webpack to import the webpack environment variable in your project running code:

new webpack.DefinePlugin({
	NODE_ENV: JSON.stringify(process.env.NODE_ENV),
});

Reference: https://stackoverflow.com/questions/41705888/passing-the-node-env-value-using-webpack-via-defineplugin


中文 - Chinese

npm.io

Web3 express react - Reference API 参考文档

组件亮点:

1.通过简单地安装以及引用就可以快速配置一个 React + web3js 项目,从而避免在一开始配置环境时消耗大量的时间。 2.可根据不同的运行环境(developement/production)配置不同的网络依赖,以及不同的合约。 3.搭配专属工具可自动化快速更换项目中的合约以及配置,方便项目的开发和维护。 4.自带 Gui,可根据需要直接使用本组件的 Gui 快速完成 web3 交互。 5.支持 SSR,不需要担心 Razzle 和 Nuxt 的兼容性问题。

功能特性:

1.开箱即用,只需一个函数即可完成钱包的安装和链接 2.钱包状态管理功能齐全,可以通过导出的状态直接获得当前钱包是否登录,网络链接是否错误等。 3.智能地网络管理,当 Web3 express 运行在未链接/安装钱包的的状态下时,Web3 express 将会直接使用 http 节点的方式工作,当运行在有钱包链接的工作状态下时,会通过钱包对区块链进行交互,所有这一切都是自动的,无需手动判断和切换。 4.支持 walletConnect Deeplink 5.多种简化封装方便您快速上手工作,并可避免人为失误。

安装组件

npm install @bobliao/web3-express-react

yarn add @bobliao/web3-express-react

pnpm install @bobliao/web3-express-react

======= 进行全局配置 =======

进行全局配置将有效地使您的业务代码访问到 Web3 express 以下配置请配置到您项目中的顶级模块中去,例如App.js

import Web3Express from "@bobliao/web3-express-react";

//拿出钩子函数,以及需要全局使用的Context
const { useCommon, useWallet, commonContext, walletContext } = Web3Express;

//初始化commonHook
const commonObject = useCommon("development");
//初始化钱包操作器
const walletHalper = useWallet(false, "development");

//将Context置于项目最顶端,放入初始化好的commonObject(公共函数类)以及walletHalper(钱包操作器)
return (
	<commonContext.Provider value={commonObject}>
		<walletContext.Provider value={walletHalper}>
			<ExcOne></ExcOne>
		</walletContext.Provider>
	</commonContext.Provider>
);

完整示例:

import "./App.css";
import ExcOne from "./views/excamples/excOne";
import Web3Express from "@bobliao/web3-express-react";

function App() {
	const { useCommon, useWallet, commonContext, walletContext } = Web3Express;

	//初始化commonHook
	const commonObject = useCommon("development");
	//初始化钱包操作器
	const walletHalper = useWallet(false, "development");

	return (
		<commonContext.Provider value={commonObject}>
			<walletContext.Provider value={walletHalper}>
				{/*
						请一定要将以上两个对象置于您的业务逻辑代码的范围之上
						这样您在业务逻辑代码内就可以使用他们。
					*/}
				<ExcOne></ExcOne>
			</walletContext.Provider>
		</commonContext.Provider>
	);
}

export default App;

这里千万要注意

//初始化commonHook
const commonObject = useCommon("development");
//初始化钱包操作器
const walletHalper = useWallet(false, "development");

这个地方一定不能写死,在useCommon("development");useWallet(false, "development")的时候 "development"这个位置应该作为您项目的环境变量传入,例如 NODE_ENV,在实际使用 的时候,应该写成这样:

//初始化commonHook
const commonObject = useCommon(NODE_ENV);
//初始化钱包操作器
const walletHalper = useWallet(false, NODE_ENV);

可能需要使用 Webpack 的webpack.DefinePlugin功能将您 Webpack 的环境变量导入到您的项目代码的运行环境里去:

new webpack.DefinePlugin({
	/**
	 * 这里定义的环境变量可以直接在业务代码里拿到,
	 * 属于是webpack直接打印上去的,
	 * 并不是写在业务代码逻辑里的。
	 */
	NODE_ENV: JSON.stringify(process.env.NODE_ENV),
});

参考资料: https://stackoverflow.com/questions/41705888/passing-the-node-env-value-using-webpack-via-defineplugin

=======安装钱包,链接钱包,及钱包状态的管理=======

钱包的状态管理主要使用 WalletHelper 对象 使用 Web3Expres 导出useWalletContext钩子,并使用useWalletContext钩子导出 walletHelper 对象

示例:

import Web3Express from "@bobliao/web3-express-react";

//使用Web3Express导出useWalletContext
const { useWalletContext } = Web3Express;
//使用useWalletContext导出walletHelper
const walletHelper = useWalletContext();
//walletHelper包含两个对象
//一个是walletData 另一个是walletFuncs
const { walletData, walletFuncs } = walletHelper;
/**
 * 	walletData中的内容
 * 	当前链接的账号
 *	walletData.currentAccount
 *	当前使用的是哪个网络
 *	walletData.currentNetwork
 *	当前是否已经安装了钱包
 *	walletData.isWalletInstalled
 *	当前是否链接了钱包
 *	walletData.isConnectedWallet
 *	钱包对象
 *	walletData.ethereum
 *	状态更改指示
 *	一旦钱包登陆用户更改,或者网络更改
 *	都会触发这个状态的更改
 *	walletData.changeStemp
 *	是否为isTrustWallet
 *	walletData.isTrustWallet
 *	钱包状态更改次数
 *	walletData.changeTimes
 *	刚安装完钱包,如果不刷新页面钱包可能会未初始化
 *	walletData.isWalletUnInitlized
 *	用于显示的账号信息
 *	walletData.currentDisplayAccount
 *	工作模式  ethereum / walletConnect
 *  指示当前的钱包正使用什么模式工作
 *	walletData.workingMode
 */

/**
	 * walletFuncs中的内容
	 *
	 *	立刻链接登陆钱包(Metamask/本地钱包)
	 *	await walletFuncs.triggerConnect() => Promise<IstateResult>;
	 *	检测是否有链接钱包
	 *	walletFuncs.detactConnect() => {
			是否链接了钱包 true/false
			isConnectedWallet,
			当前链接到钱包的账号
			currentAccount,
		};
	 *	是否有安装钱包
	 *	walletFuncs.detactWallet() => null | ethereum
	 *	添加网络
	 *	await walletFuncs.addNetWork(InetWork) => Promise<IstateResult>,
	 *	切换网络
	 *	walletFuncs.switchNetWork(InetWork) => Promise<IstateResult>,
	 *	触发远程钱包链接
	 *	await walletFuncs.trigger_WalletConnect_connect() => Promise<void>,
	 *	断开链接
	 *	walletFuncs.disConnect() => void,
	 */

walletData 中的所有内容都可以被 useEffect 监听,例如:

useEffect(
	function () {
		console.log("钱包状态发生了更改,可能是 登录了/退出登录了/切换了网络状态");
		if (walletData.currentAccount === "") {
			console.log("钱包未登录");
		}

		if (walletData.currentAccount !== "") {
			console.log("钱包登录了,登录的钱包地址为:" + walletData.currentAccount);
		}
	},
	[walletData.changeStemp]
);

useEffect(
	function () {
		console.log("您的钱包地址为:" + walletData.currentAccount);
	},
	[walletData.currentAccount]
);

如果您希望触发本地钱包(Metamask)的登录、安装:

walletFuncs.triggerConnect()

<button
	onClick={function () {
		walletFuncs.triggerConnect();
	}}
>
	激活钱包
</button>

使用walletFuncs.triggerConnect()时,如果用户没有安装钱包,将会自动引导用户安装钱包

如果您希望使用 DeepLink 钱包:

walletFuncs.trigger_WalletConnect_connect()

<button
	onClick={function () {
		walletFuncs.trigger_WalletConnect_connect();
	}}
>
	激活Walletconnect
</button>

如果您希望断开钱包链接:

walletFuncs.disConnect()

<button
	onClick={function () {
		walletFuncs.disConnect();
	}}
>
	断开链接
</button>

使用 web3 express 内置的 GUI 完成钱包的链接交互

使用内置的 gui 将自动创建一个友好的下拉菜单,或者弹出窗口,友好地引导用户链接钱包

	import Web3Express from "@bobliao/web3-express-react";

	//导出ConnectSelect组件
	const { ConnectSelect } = Web3Express;


	<ConnectSelect mode="dropdown">
		<button>使用下拉菜单弹出链接选择菜单</button>
	</ConnectSelect>

	<ConnectSelect mode="window">
		<button>使用窗口弹出链接选择菜单</button>
	</ConnectSelect>

完整示例代码:

import React, { useEffect } from "react";
import { useState } from "react";
import Web3Express from "@bobliao/web3-express-react";

import "./index.css";

const ExcOne = () => {
	const [isMounted, setIsmounted] = useState(false);

	//使用Web3Express导出useWalletContext
	const { useWalletContext, ConnectSelect } = Web3Express;
	//使用useWalletContext导出walletHelper
	const walletHelper = useWalletContext();
	//walletHelper包含两个对象
	//一个是walletData 另一个是walletFuncs
	const { walletData, walletFuncs } = walletHelper;
	/**
	 * 	walletData中的内容
	 * 	当前链接的账号
	 *	walletData.currentAccount
	 *	当前使用的是哪个网络
	 *	walletData.currentNetwork
	 *	当前是否已经安装了钱包
	 *	walletData.isWalletInstalled
	 *	当前是否链接了钱包
	 *	walletData.isConnectedWallet
	 *	钱包对象
	 *	walletData.ethereum
	 *	状态更改指示
	 *	一旦钱包登陆用户更改,或者网络更改
	 *	都会触发这个状态的更改
	 *	walletData.changeStemp
	 *	是否为isTrustWallet
	 *	walletData.isTrustWallet
	 *	钱包状态更改次数
	 *	walletData.changeTimes
	 *	刚安装完钱包,如果不刷新页面钱包可能会未初始化
	 *	walletData.isWalletUnInitlized
	 *	用于显示的账号信息
	 *	walletData.currentDisplayAccount
	 *	工作模式  ethereum / walletConnect
	 *  指示当前的钱包正使用什么模式工作
	 *	walletData.workingMode
	 */

	/**
	 * walletFuncs中的内容
	 *
	 *	立刻链接登陆钱包(Metamask/本地钱包)
	 *	await walletFuncs.triggerConnect() => Promise<IstateResult>;
	 *	检测是否有链接钱包
	 *	walletFuncs.detactConnect() => {
			是否链接了钱包 true/false
			isConnectedWallet,
			当前链接到钱包的账号
			currentAccount,
		};
	 *	是否有安装钱包
	 *	walletFuncs.detactWallet() => null | ethereum
	 *	添加网络
	 *	await walletFuncs.addNetWork(InetWork) => Promise<IstateResult>,
	 *	切换网络
	 *	walletFuncs.switchNetWork(InetWork) => Promise<IstateResult>,
	 *	触发远程钱包链接
	 *	await walletFuncs.trigger_WalletConnect_connect() => Promise<void>,
	 *	断开链接
	 *	walletFuncs.disConnect() => void,
	 */

	useEffect(
		function () {
			console.log("钱包状态发生了更改,可能是 登录了/退出登录了/切换了网络状态");
			if (walletData.currentAccount === "") {
				console.log("钱包未登录");
			}

			if (walletData.currentAccount !== "") {
				console.log("钱包登录了,登录的钱包地址为:" + walletData.currentAccount);
			}
		},
		[walletData.changeStemp]
	);

	useEffect(
		function () {
			console.log("您的钱包地址为:" + walletData.currentAccount);
		},
		[walletData.currentAccount]
	);

	useEffect(
		function () {
			if (!isMounted) {
				setIsmounted(true);
			}

			return function () {
				if (isMounted) {
					setIsmounted(false);
				}
			};
		},
		[isMounted]
	);

	return (
		<div>
			<div>
				当前登陆的钱包账号:
				{walletData.currentAccount}
			</div>
			<div className="rrb-split">
				当前使用的网络:
				{walletData.currentNetwork}
			</div>
			<div className="rrb-split">
				当前是否已经安装了钱包:
				{walletData.isWalletInstalled.toString()}
			</div>
			<div className="rrb-split">
				当前是否链接了钱包:
				{walletData.isConnectedWallet.toString()}
			</div>
			<div className="rrb-split">
				钱包状态更改指示:
				{walletData.changeStemp}
			</div>
			<div className="rrb-split">
				钱包状态更改次数:
				{walletData.changeTimes}
			</div>
			<button
				onClick={function () {
					walletFuncs.triggerConnect();
				}}
			>
				激活钱包
			</button>
			<button
				onClick={function () {
					walletFuncs.trigger_WalletConnect_connect();
				}}
			>
				激活Walletconnect
			</button>
			<button
				onClick={function () {
					walletFuncs.disConnect();
				}}
			>
				断开链接
			</button>

			<ConnectSelect mode="dropdown">
				<button>使用下拉菜单弹出链接选择菜单</button>
			</ConnectSelect>

			<ConnectSelect mode="window">
				<button>使用窗口弹出链接选择菜单</button>
			</ConnectSelect>
		</div>
	);
};
export default ExcOne;

=======配置智能合约到您的项目里去=======

请严格按照本文推荐的文件名创建文件夹否则之后在使用专用工具管理您的配置的时候会出现问题

请在您的 src 目录下任意位置建立这样的文件夹结构:

	━ blockChanOperator
		┣ contractConfigs
		┗ abis

contractConfigs目录下创建一个您的合约配置,如果您没想好给它取什么名字,那就叫default.config.js

	━ blockChanOperator
		┣ contractConfigs
		┃	┗ default.config.js
		┗ abis

并在default.config.js中放入以下内容:

/**
 * 合约配置文件替换器自动生成
 * 用于使web3Operator/metaMaskOperator载入的合约配置文件
 */
const contractConfig = {
	//测试环境
	dev: {
		//环境信息
		info: {
			//依赖的网络id
			depChainId: 80001,
			//依赖的网络名称
			depChainName: "Polygon Testnet",
			//web3链接节点的地址
			provider: "https://matic-mumbai.chainstacklabs.com/",
			//web3链接节点的符号
			symbol: "MATIC",
			//查询浏览器的访问地址
			visitUrl: "https://mumbai.polygonscan.com/",
			//小数位数
			decimals: 18,
		},
		BuyStockNFT: {
			//合约id
			id: "0x9C84144c7035B77Ee4c5004844592747Ca97c3BD",
			//abi本地文件位置
			abiFileName: "../abis/buystocknft_abi_dev.json",
			//在线的abi文件地址,可以通过这个地址直接拿取线上的abi文件
			abiOnline: "https://api-testnet.polygonscan.com/api?module=contract&action=getabi&address=0x9C84144c7035B77Ee4c5004844592747Ca97c3BD&format=raw",
			//web3链接节点的地址
			provider: "https://matic-mumbai.chainstacklabs.com/",
			//异步获得本地版本的abi文件
			getAbiAsync: function (_callback) {
				require(["../abis/buystocknft_abi_dev.json"], function (_abi) {
					_callback(_abi);
				});
			},
			//依赖哪个网络
			depNetWork: "Polygon Testnet",
		},
		GodMusicStock: {
			//合约id
			id: "0xe3e8E26b801F4Fa19741b9562FB43aA75e6AA589",
			//abi本地文件位置
			abiFileName: "../abis/godmusicstock_abi_dev.json",
			//在线的abi文件地址,可以通过这个地址直接拿取线上的abi文件
			abiOnline: "https://api-testnet.polygonscan.com/api?module=contract&action=getabi&address=0xe3e8E26b801F4Fa19741b9562FB43aA75e6AA589&format=raw",
			//web3链接节点的地址
			provider: "https://matic-mumbai.chainstacklabs.com/",
			//异步获得本地版本的abi文件
			getAbiAsync: function (_callback) {
				require(["../abis/godmusicstock_abi_dev.json"], function (_abi) {
					_callback(_abi);
				});
			},
			//依赖哪个网络
			depNetWork: "Polygon Testnet",
		},
	},
	//正式环境
	pro: {
		//环境信息
		info: {
			//依赖的网络id
			depChainId: 137,
			//依赖的网络名称
			depChainName: "Polygon Mainnet",
			//web3链接节点的地址
			provider: "https://rpc-mainnet.matic.network",
			//web3链接节点的符号
			symbol: "MATIC",
			//查询浏览器的访问地址
			visitUrl: "https://polygonscan.com/",
			//小数位数
			decimals: 18,
		},
		BuyStockNFT: {
			//合约id
			id: "0x976FDba11c0B79eF9e31242a9Aad48A6680Bc6f9",
			//abi本地文件位置
			abiFileName: "../abis/buystocknft_abi_pro.json",
			//在线的abi文件地址,可以通过这个地址直接拿取线上的abi文件
			abiOnline: "https://api.polygonscan.com/api?module=contract&action=getabi&address=0x976FDba11c0B79eF9e31242a9Aad48A6680Bc6f9&format=raw",
			//web3链接节点的地址
			provider: "https://rpc-mainnet.matic.network",
			//异步获得本地版本的abi文件
			getAbiAsync: function (_callback) {
				require(["../abis/buystocknft_abi_pro.json"], function (_abi) {
					_callback(_abi);
				});
			},
			//依赖哪个网络
			depNetWork: "Polygon Mainnet",
		},
		GodMusicStock: {
			//合约id
			id: "0x6E1B735cd88E16F68a27b02ab32335e173A3C3dB",
			//abi本地文件位置
			abiFileName: "../abis/godmusicstock_abi_pro.json",
			//在线的abi文件地址,可以通过这个地址直接拿取线上的abi文件
			abiOnline: "https://api.polygonscan.com/api?module=contract&action=getabi&address=0x6E1B735cd88E16F68a27b02ab32335e173A3C3dB&format=raw",
			//web3链接节点的地址
			provider: "https://rpc-mainnet.matic.network",
			//异步获得本地版本的abi文件
			getAbiAsync: function (_callback) {
				require(["../abis/godmusicstock_abi_pro.json"], function (_abi) {
					_callback(_abi);
				});
			},
			//依赖哪个网络
			depNetWork: "Polygon Mainnet",
		},
	},
};
export { contractConfig };

我们可以看到,在配置中 ,有两个块,分别是 dev 和 pro 它们分别代表当前运行环境为development时和production时所使用的合约 与区块链的信息:

/**
 * 合约配置文件替换器自动生成
 * 用于使web3Operator/metaMaskOperator载入的合约配置文件
 */
const contractConfig = {
	//测试环境
	dev: {
		(...)
	},

	//正式环境
	pro: {
		(...)
	},
};
export { contractConfig };

正常情况下,这两个块中的 info 信息和配置的合约信息可能不一致,但是字段数量和合约数量 以及合约名称应该保持一致,否则可能在开发时没有问题,但是在发布以后出现合约读取不到等麻烦。 例如只在 dev 中配置了"BuyStockNFT"合约,但是在 pro 中"BuyStockNFT"并不存在,那就会出现问题。总之合约的地址,以及 abi 可能不一样,但是在 dev 中配置了的合约,一定要出现在 pro 里。

dev/pro -> info

您会注意到,在 dev 或 pro 中都会出现 info 这个配置块,这个配置块中配置的就是链的信息,您需要根据您的需求配置您在 pro/dev 下依赖的链,例如这个示例中,dev 依赖于 Polygon Testnet,那么在这里就要将 Polygon Testnet 的 id,链的名称,https 节点等都配置上去,这样的话就可以在之后的工作中,通过这套组件简单快捷地引导用户添加相应的网络,或切换到相应的网络。

	info: {
		//依赖的网络id
		depChainId: 80001,
		//依赖的网络名称
		depChainName: "Polygon Testnet",
		//web3链接节点的地址
		provider: "https://matic-mumbai.chainstacklabs.com/",
		//web3链接节点的符号
		symbol: "MATIC",
		//查询浏览器的访问地址
		visitUrl: "https://mumbai.polygonscan.com/",
		//小数位数
		decimals: 18,
	},

在这个示例中 dev 配置的是Polygon Testnet(测试链)那么相应的 pro 的配置是Polygon Mainnet(主链)

配置您的合约

在下面的内容中,就可以开始配置具体的合约:

		BuyStockNFT: {
            //合约id
            id: "0x9C84144c7035B77Ee4c5004844592747Ca97c3BD",
            //abi本地文件位置
            abiFileName: "../abis/buystocknft_abi_dev.json",
            //在线的abi文件地址,可以通过这个地址直接拿取线上的abi文件
            abiOnline: "https://api-testnet.polygonscan.com/api?module=contract&action=getabi&address=0x9C84144c7035B77Ee4c5004844592747Ca97c3BD&format=raw",
            //web3链接节点的地址
            provider: "https://matic-mumbai.chainstacklabs.com/",
            //异步获得本地版本的abi文件
            getAbiAsync: function (_callback) {
                require(["../abis/buystocknft_abi_dev.json"], function (_abi) {
                    _callback(_abi);
                });
            },
            //依赖哪个网络
            depNetWork: "Polygon Testnet",
        },

合约配置的编写格式如上所示,块名称就是合约名称:

		BuyStockNFT: {
         (...)
        },

如果您的合约叫 ILoveBlockChain,那就是这样的:

		ILoveBlockChain: {
         (...)
        },

这里的合约名称是您自己起的,与合约查询网络中的合约名称没有关系,但是还是建议您将此合约名称与查询网络中的合约名称保持一致:

https://mumbai.polygonscan.com/address/0x9C84144c7035B77Ee4c5004844592747Ca97c3BD#code

npm.io

例如在这个示例中,有 BuyStockNFT,GodMusicStock,这两个合约

那么就可以在测试环境配置测试的合约,正式环境配置正式的合约

手动配置合约的 abi 文件到本地

您也许注意到了合约配置块中,存在这样的配置字段:

			//abi本地文件位置
            abiFileName: "../abis/buystocknft_abi_dev.json",
            //在线的abi文件地址,可以通过这个地址直接拿取线上的abi文件
            abiOnline: "https://api-testnet.polygonscan.com/api?module=contract&action=getabi&address=0x9C84144c7035B77Ee4c5004844592747Ca97c3BD&format=raw",
			//异步获得本地版本的abi文件
            getAbiAsync: function (_callback) {
                require(["../abis/buystocknft_abi_dev.json"], function (_abi) {
                    _callback(_abi);
                });
            },

您需要先去合约查询网上,通过合约的 id 先找到它:

例如这里我们用的是Polygon Testnet,那么合约查询网址为https://mumbai.polygonscan.com/

打开它,然后在查询框里输入合约 id 例如0x9C84144c7035B77Ee4c5004844592747Ca97c3BD

npm.io

点击查询按钮,找到合约,然后找到页面上的ContractTab,切换过去,就可以看到Contract ABI栏目:

npm.io

点击RAW/Text Format按钮,得到 abi 文件内容和请求连接

npm.io

将请求连接复制到abiOnline配置字段上去

将内容复制下来,在以下目录创建一个 abi 文件buystocknft_abi_dev.json:

	━ blockChanOperator
		┣ contractConfigs
		┃	┗ default.config.js
		┗ abis
			┗ buystocknft_abi_dev.json

然后将您拷贝的内容放进去,并检查和保证getAbiAsync中的路径和abiFileName中的路径能访问到刚才保存的 abi 文件:buystocknft_abi_dev.json.

依次配置所有的测试、正式的合约的 abi 到 abis 目录中去.

手动配置完成!

通过“合约设置器”自动更新 abi 文件

您至少在contractConfigs目录中配置了一份合约配置文件

请前往以下地址获得合约设置器

https://github.com/AKAMKII6666/-bobliao-ContractConfigSetter

将代码克隆至本地,然后npm install或者pnpm install或者yarn安装依赖

完成依赖安装之后,使用npm start或者pnpm start或者yarn start运行“合约设置器”

npm.io

点击 选择文件按钮,定位到您在您项目里如上文指示的blockChanOperator目录.

npm.io

确认后,点击查找配置文件,将会找到您刚刚配置的default.config.js配置文件,您将会在下面的界面中看到您配置文件的所有图形化的选项:

npm.io

如果您配置的合约地址和 abi 源文件访问地址都准确,可以直接点击更改并保存配置按钮,“合约设置器”将自动去合约查询网站上拉取相应的 abi 并保存。

npm.io

npm.io

合约在您项目中的自动配置便已经完成!

=========调用智能合约============

使用 web3Express 中导出的useMmOperator钩子,并使用这个钩子载入我们配置好的default.config.js合约配置文件,然后导出contractOperator对象,用于操作合约:

import Web3Express from "@bobliao/web3-express-react";
//载入上文示例中配置好的合约配置文件
const defaultConfig = require("../../../blockChanOperator/contractConfigs/default.config").contractConfig;

const { useMmOperator } = Web3Express;
//创建合约操作器
const contractOperator = useMmOperator(defaultConfig);

useEffect(
	function () {
		if (contractOperator.data.isLoaded) {
			console.log("合约都已经载入完成,可以开始合约操作!");
		}
	},
	[contractOperator.data.changeTimes]
);

//用来监听合约的变化
contractOperator.data.changeTimes;

//配置中的合约载入完成后,此状态为true,否则为false
contractOperator.data.isLoaded;

contractOperator对象的内容:

		data: {
			//是否已经挂载
			isMounted,
			//当前合约操作器的工作模式
			//链接了钱包、网络选择准确 :"ETHEREUM"
			//没有链接钱包,网络链接不正确: "NODE"
			workingMode,
			//当前载入的合约对象
			contracts,
			//是否已经载入完成
			isLoaded,
			//操作器加载合约次数
			changeTimes,
			//是否为错误的网络
			isWrongNetWork,
			//当前使用的合约配置
			currentConfig,
		},
		funcs: {
			//获得当前能拿到的provider
			getProvider,
			//获得操作器
			makeOperator,
			//初始化合约
			initContract,
			//获得用户钱包余额
			getUserBalance,
			//批量操作合约
			mutilRequest,
			//获得正确的网络
			switchCurrentNetWork,
			//签名
			getSignForLogin,
			//发送交易
			send,
		},

向合约提供的函数查询数据:

查询合约内容,例如查询BuyStockNFTbuyCount 接口,核心代码:

let amount = await contractOperator.data.contracts.BuyStockNFT.methods.buyCount().call();
console.log(amount);

需要注意的是contractOperator.data.contracts.合约名称下面的所有的合约,就是您在default.config.js中配置好的

contractOperator.data.contracts.BuyStockNFT 这里您拿到的合约对象,实际上就是 web3js 的contract对象,参考文档:https://web3js.readthedocs.io/en/v1.7.5/web3-eth-contract.html#eth-contract

无论您要通过合约做何种操作,都需要等待合约载入完成:

useEffect(
	function () {
		if (contractOperator.data.isLoaded) {
			console.log("合约都已经载入完成,可以开始合约操作!");

			(async function () {
				let amount = await contractOperator.data.contracts.BuyStockNFT.methods
					.buyCount()
					.call();
				console.log(amount);
			})();
		}
	},
	[contractOperator.data.changeTimes]
);

完整代码:

import React, { useEffect } from "react";
import { useState } from "react";
import Web3Express from "@bobliao/web3-express-react";
import "./index.css";
const defaultConfig = require("../../../blockChanOperator/contractConfigs/default.config").contractConfig;

const ExcTwo = () => {
	const [isMounted, setIsmounted] = useState(false);

	//使用Web3Express导出useWalletContext
	const { useWalletContext, ConnectSelect, useMmOperator } = Web3Express;
	//使用useWalletContext导出walletHelper
	const walletHelper = useWalletContext();
	//walletHelper包含两个对象
	//一个是walletData 另一个是walletFuncs
	const { walletData } = walletHelper;

	//创建合约操作器
	const contractOperator = useMmOperator(defaultConfig);

	useEffect(
		function () {
			if (contractOperator.data.isLoaded) {
				console.log("合约都已经载入完成,可以开始合约操作!");

				(async function () {
					let amount = await contractOperator.data.contracts.BuyStockNFT.methods
						.buyCount()
						.call();
					console.log(amount);
				})();
			}
		},
		[contractOperator.data.changeTimes]
	);

	useEffect(
		function () {
			console.log("您的钱包地址为:" + walletData.currentAccount);
		},
		[walletData.currentAccount]
	);

	useEffect(
		function () {
			if (!isMounted) {
				setIsmounted(true);
			}

			return function () {
				if (isMounted) {
					setIsmounted(false);
				}
			};
		},
		[isMounted]
	);

	return (
		<div>
			<ConnectSelect mode="window">
				<button>使用窗口弹出链接选择菜单</button>
			</ConnectSelect>

			<div>
				当前登陆的钱包账号:
				{walletData.currentAccount}
			</div>
		</div>
	);
};
export default ExcTwo;

批量查询

//批量查询
var loadArray = [
	/**
	 * 查询当前售出多少
	 */
	contractOperator.data.contracts.BuyStockNFT.methods.salesVolume().call,
	/**
	 * 查询当前总共多少
	 */
	contractOperator.data.contracts.BuyStockNFT.methods.purchaseLimit().call,
	/**
	 * 查询一份多少钱
	 */
	contractOperator.data.contracts.BuyStockNFT.methods.buyCount().call,
];

//使用mutilRequest批量查询
var result = await contractOperator.funcs.mutilRequest(loadArray);

对合约提供的函数操作写入

可以使用 contractOperator.funcs.send 函数发起操作:

/**
 * 确保合约都载入完成
 */
if (contractOperator.data.isLoaded) {
	/**
	 * contractOperator.funcs.send函数,参数释意:
	 * 第一个参数为合约名称
	 * 第二个参数为方法名称
	 * 第三个参数为提供给方法的参数,没有就填写空数组
	 * 第四个参数为提交时必须要填写的参数集
	 */
	var result = await contractOperator.funcs.send("BuyStockNFT", "buyMidNFT", [], {
		//使用钱包的账号,如果未链接钱包即walletData.currentAccount = "",应该给出提示
		from: walletData.currentAccount,
		//这里是向这个“buyMidNFT”发起一个数额为0.001Matic的交易,由于Matic的缩进为18位,需要使用commonObj.shiftNumber来对数字进行缩进
		//直接向这里发起交易时输入浮点数将报错。
		value: commonObj.commonFuncs.shiftNumber(0.001, -18),
	});

	console.log(result);
}

或者使用更传统的方式:

/**
 * 确保合约都载入完成
 */
if (contractOperator.data.isLoaded) {
	let result = await contractOperator.data.contracts.BuyStockNFT.methods.buyMidNFT().send({
		//使用钱包的账号,如果未链接钱包即walletData.currentAccount = "",应该给出提示
		from: walletData.currentAccount,
		//这里是向这个“buyMidNFT”发起一个数额为0.001Matic的交易,由于Matic的缩进为18位,需要使用commonObj.shiftNumber来对数字进行缩进
		//直接向这里发起交易时输入浮点数将报错。
		value: commonObj.commonFuncs.shiftNumber(0.001, -18),
	});
	console.log(result);
}

完整示例

import React, { useEffect } from "react";
import { useState } from "react";
import Web3Express from "@bobliao/web3-express-react";
import "./index.css";
const defaultConfig = require("../../../blockChanOperator/contractConfigs/default.config").contractConfig;

const ExcTwo = () => {
	const [isMounted, setIsmounted] = useState(false);

	//使用Web3Express导出useWalletContext
	const { useWalletContext, ConnectSelect, useMmOperator, useCommon } = Web3Express;
	//使用useWalletContext导出walletHelper
	const walletHelper = useWalletContext();
	//walletHelper包含两个对象
	//一个是walletData 另一个是walletFuncs
	const { walletData } = walletHelper;

	//创建合约操作器
	const contractOperator = useMmOperator(defaultConfig);

	//导出公用函数集
	const commonObj = useCommon();

	useEffect(
		function () {
			if (contractOperator.data.isLoaded) {
				console.log("合约都已经载入完成,可以开始合约操作!");

				(async function () {
					let amount = await contractOperator.data.contracts.BuyStockNFT.methods
						.buyCount()
						.call();
					console.log(amount);
				})();
			}
		},
		[contractOperator.data.changeTimes]
	);

	useEffect(
		function () {
			console.log("您的钱包地址为:" + walletData.currentAccount);
		},
		[walletData.currentAccount]
	);

	useEffect(
		function () {
			if (!isMounted) {
				setIsmounted(true);
			}

			return function () {
				if (isMounted) {
					setIsmounted(false);
				}
			};
		},
		[isMounted]
	);

	return (
		<div>
			<ConnectSelect mode="window">
				<button>使用窗口弹出链接选择菜单</button>
			</ConnectSelect>

			<button
				onClick={function () {
					(async function () {
						/**
						 * 确保合约都载入完成
						 */
						if (contractOperator.data.isLoaded) {
							/**
							 * contractOperator.funcs.send函数,参数释意:
							 * 第一个参数为合约名称
							 * 第二个参数为方法名称
							 * 第三个参数为提供给方法的参数,没有就填写空数组
							 * 第四个参数为提交时必须要填写的参数集
							 */
							let result = await contractOperator.funcs.send(
								"BuyStockNFT",
								"buyMidNFT",
								[],
								{
									//使用钱包的账号,如果未链接钱包即walletData.currentAccount = "",应该给出提示
									from: walletData.currentAccount,
									//这里是向这个“buyMidNFT”发起一个数额为0.001Matic的交易,由于Matic的缩进为18位,需要使用commonObj.shiftNumber来对数字进行缩进
									//直接向这里发起交易时输入浮点数将报错。
									value: commonObj.commonFuncs.shiftNumber(
										0.001,
										-18
									),
								}
							);

							console.log(result);
						}
					})();
				}}
			>
				发起交易
			</button>

			<button
				onClick={function () {
					(async function () {
						/**
						 * 确保合约都载入完成
						 */
						if (contractOperator.data.isLoaded) {
							let result =
								await contractOperator.data.contracts.BuyStockNFT.methods
									.buyMidNFT()
									.send({
										//使用钱包的账号,如果未链接钱包即walletData.currentAccount = "",应该给出提示
										from: walletData.currentAccount,
										//这里是向这个“buyMidNFT”发起一个数额为0.001Matic的交易,由于Matic的缩进为18位,需要使用commonObj.shiftNumber来对数字进行缩进
										//直接向这里发起交易时输入浮点数将报错。
										value: commonObj.commonFuncs.shiftNumber(
											0.001,
											-18
										),
									});
							console.log(result);
						}
					})();
				}}
			>
				发起交易传统方式
			</button>

			<div>
				当前登陆的钱包账号:
				{walletData.currentAccount}
			</div>
		</div>
	);
};
export default ExcTwo;

使用 web3Express 内置的 GUI 完善您的应用体验

使用 web3Express.commonHook 中内置的 alt 函数和 ask 函数:

您可以使用 commonHook 中提供的一些便捷的函数制作完成类似 alert()或者 window.confirm 的体验,您的编码体验将会增强,用户的交互体验也会得到增强:

alt():弹出警告

	import Web3Express from "@bobliao/web3-express-react";

	//使用Web3Express导出useCommon,useWalletContext
	const { useCommon , useWalletContext} = Web3Express;

	//使用useWalletContext导出walletHelper
	const walletHelper = useWalletContext();

	//walletHelper包含两个对象
	//一个是walletData 另一个是walletFuncs
	const { walletData } = walletHelper;

	//导出公用函数集
	const { commonFuncs, alt, ask } = useCommon();

			<button
				onClick={function () {
					(async function () {
						/**
						 *检测用户钱包是否登录,未登录就警告用户登录
						 */
						if (walletData.currentAccount === "") {
							alt({
								message: "您没有登录钱包,请登录钱包再继续!",
							});

							return;
						}

						(...)

					})();
				}}
			>
				发起交易
			</button>

npm.io

alt():判断用户点击了确认键还是关闭了窗口

/**
 *检测用户钱包是否登录,未登录就警告用户登录
 */
if (walletData.currentAccount === "") {
	/**
	 * 打开窗口时接收一个返回的result对象
	 * resultObj 包含两个东西
	 * 一个是 promise 也就是处理窗口按钮点击返回的Promise
	 * 一个是 window 就是窗口的控制对象
	 */
	let resultObj = alt({
		message: "您没有登录钱包,请登录钱包再继续!",
	});
	/**
	 * 通过 await resultObj.promise 来得到窗口按钮点击的返回值
	 */
	var buttonResult = await resultObj.promise;
	/**
	 * 将返回一个对象:
	 *
		{
			"status":"NO/YES",
			"data":{}
		}
		*/
	if (buttonResult.status === "YES") {
		console.log("点击了确认键");
	}
	if (buttonResult.status === "NO") {
		console.log("点击了关闭");
	}
	debugger;
	return;
}

ask():弹出询问:

和 alt()的使用方法类似:

/**
 *检测用户钱包是否登录,未登录就警告用户登录
 */
if (walletData.currentAccount === "") {
	/**
	 * 打开窗口时接收一个返回的result对象
	 * resultObj 包含两个东西
	 * 一个是 promise 也就是处理窗口按钮点击返回的Promise
	 * 一个是 window 就是窗口的控制对象
	 */
	let resultObj = ask({
		message: "您没有登录钱包,您需要登录钱包吗?",
	});
	/**
	 * 通过 await resultObj.promise 来得到窗口按钮点击的返回值
	 */
	var buttonResult = await resultObj.promise;
	/**
	 * 将返回一个对象:
	 *
	{
		"status":"NO/YES",
		"data":{}
	}
	*/
	if (buttonResult.status === "YES") {
		walletFuncs.triggerConnect();
	}
	if (buttonResult.status === "NO") {
		console.log("点击了取消键");
	}
	debugger;
	return;
}

npm.io

利用 contractOperator.funcs.send 的返回值对交易状态进行处理:

let resultPromise = contractOperator.funcs.send("BuyStockNFT", "buyMidNFT", [], {
	//使用钱包的账号,如果未链接钱包即walletData.currentAccount = "",应该给出提示
	from: walletData.currentAccount,
	//这里是向这个“buyMidNFT”发起一个数额为0.001Matic的交易,由于Matic的缩进为18位,需要使用commonObj.shiftNumber来对数字进行缩进
	//直接向这里发起交易时输入浮点数将报错。
	value: commonFuncs.shiftNumber(0.001, -18),
});

/*
 *等待返回结果
 */
let result = await resultPromise;

/**
 * 交易成功
 */
if (result.status === "SUCCESSED") {
	alt({
		title: "交易訊息",
		message: "您已完成了交易",
	});
}

/**
 * 用户在metamask上点击了退出或者交易超时
 */
if (result.status === "USEREXIT") {
	alt({
		title: "交易訊息",
		message: "您已取消了交易",
	});
}

/**
 * 因为网络原因引起的交易错误
 */
if (result.status === "ERROR") {
	alt({
		title: "交易訊息",
		message: "交易失敗!請檢查您的網絡!",
	});
}

利用 switchCurrentNetWork 将用户选错的网络切换到准确的网络

通过 switchCurrentNetWork可以将错误的网络切换到往前运行环境下我们在合约配置里配置好的网络

//使用这个判断是否为正确的网络(可使用effect监听)
contractOperator.data.isWrongNetWork; //ture:错误的网络  ,false:网络正常

//使用这个唤出钱包自带的切换网络的界面,切换到项目需求的网络
contractOperator.funcs.switchCurrentNetWork();

//使用案例
if (contractOperator.data.isWrongNetWork) {
	contractOperator.funcs.switchCurrentNetWork();
}

commonHook 导出内容一览:

对象名称子对象参数返回说明
data.isMounted-booleancommon 对象是否已经挂载
data.envTag-string当前运行环境的字符 来自 RUNNING_ENV 自定义环境变量,内容有 "production","gray","devlopment"
data.isRunningInServer-booleantrue 表示当前代码在服务器上渲染中,false 表示当前代码在客户机上运行
commonFuncs.setDatadata = {key:value}void设置 data 里的内容
commonFuncs.findScrollNode_parent = jqueryObjectjqueryObject输入一个 jquery 对象,从这个对象开始往上查找第一个遇到的带有scroll:auto属性的节点并返回这个节点
commonFuncs.setCookiename: string, value: string, time: string or numbervoid设置 cookie
commonFuncs.delCookiename: stringvoid删除 cookie
commonFuncs.getCookiename: stringvoid or string获得 cookie
commonFuncs.getAnglept1: pointCoord, pt2: pointCoordnumber根据两个坐标点 获取角度
commonFuncs.changeTextArea_e: jQueryObjectvoid当 textArea 更改的时候改变高度react
commonFuncs.getLengthp1: pointCoord, p2: pointCoordnumber获得两点之间的距离
commonFuncs.getRandMax: number, Min: numbernumber获得一个随机数
commonFuncs.thousandsSplitnum: numberstring千分位分割
commonFuncs.getUnitNumber_num: number, _lan: string, _fix: numberstring通过语言信息获得单位换算
commonFuncs.getUrlParamsvoidobject提取 url 参数
commonFuncs.isNumber\_str: string | numberboolean判断是否为数字
commonFuncs.setUrlParam_key: string, _val: stringvoid设置 url 参数
commonFuncs.removeDuplicatearray: Array<any>, callBack: FunctionArray<any>去重算法
commonFuncs.newGuidvoidstring获得一个 gui ID
commonFuncs.formatDatedate: Date, format: stringstring格式化时间
commonFuncs.getDayOfWeek_date: Date or stringstring获得当前是周几
commonFuncs.getTimeOfDay_date: Dateor string获得一天每个时间段的文字描述
commonFuncs.getColorOfDay_value: stringstring获得一天中时间的的色彩
commonFuncs.dateAddDaysdateStr: string, dayCount: numberDate增加天数
commonFuncs.dateMDaysdateStr: string, dayCount: numberDate减去天数
commonFuncs.dateAddHoursdateStr: string, HCount: numberDate增加小时
commonFuncs.dateMHoursdateStr: string, HCount: numberDate减去小时
commonFuncs.isJsonObject_data: anyboolean判断是否为 json 对象
commonFuncs.shiftNumber_number: string or number, _shiftLength: numberstring换算区块链的数字单位
alt-{title:string,message:string}any弹出警告窗口
ask-{title:string,message:string}any弹出询问窗口
print-message:stringFunction用小气泡打印一行字
popUp-elements: ReactElement,time: numberPromise用小气泡打印 react 组件
printAlt-参考代码any用小气泡打印待确定按钮的警告窗口
printAsk-参考代码any用小气泡打印待确定/取消的询问窗口
printWarn-warnPropswarnReturn打印各类带图标的警告气泡
warn-warnPropswarnReturn弹出各类带图标的警告弹窗

感谢您的阅读 Thank you to check this out 英文文档和视频解说正在筹划中,敬请期待。 English version and viedo explanation is comming soon. 任何问题或交流请联系: Contact: liaoli66@gmail.com Telegram group: https://t.me/+h1HY2q-G5ApmYjU1

0.1.2

2 years ago

0.1.3

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

1.0.0

2 years ago