上一节我们讲了如何通过vue uniapp还有web3以及需要准备的相关组件,来搭建了DAPP开发的环境。
这一节,我们来说说如何用代码来实现DAPP相关接口。
1. ethers实现类
导入组件
import { ethers , providers , utils } from "ethers";
import tokenABI from '@/utils/tokenABI.json'
export class MetaEthers {}
初始化
static #provider = null ;
static #account = null ;
static #message = 'sign message'
static #max = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
constructor(){
check();
if(!MetaEthers.#provider)MetaEthers.#provider = new ethers.providers.Web3Provider(window.ethereum);
}
function check(target){
if(typeof window.ethereum == 'undefined')
throw uni.showToast({title: "MetaMask is unInstalled!", icon: "none"})
}
获取钱包地址
// 获取钱包地址
async setAccounts(){
let account = await MetaEthers.#provider.send("eth_requestAccounts", []);
MetaEthers.#account = account instanceof Array ? account[0] : account;
let info = JSON.parse(localStorage.getItem('userinfo'))
if( info && MetaEthers.#account.toLowerCase() !== info.chain_address){
this.destory()
throw t('dismacth');
} else{
return MetaEthers.#account;
}
}
签名获取
// 签名
async sign(){
if(!MetaEthers.#account) throw { reason: t('wallet_warning'), errType: -1 }
const signer = MetaEthers.#provider.getSigner();
let signature = await signer.signMessage(MetaEthers.#message)
console.log( utils.verifyMessage(MetaEthers.#message, signature).toLowerCase() )
return signature;
}
余额获取
// 钱包余额
async getWallet(){
if(!MetaEthers.#account) throw { reason: t('wallet_warning'), errType: -1 }
let Contract = new ethers.Contract(
tokenAddress,
tokenABI,
MetaEthers.#provider.getSigner()
);
let value = await Contract.balanceOf(MetaEthers.#account);
return ethers.utils.formatUnits(value, 18)
}
2. 实现签名登录
import {
MetaEthers
} from '@/utils/metamask.js'
let MetaWallet = {
destory: () => {}
};
// 通过实现类,获取地址及签名,后端进行验证
let chain_address = await MetaWallet.setAccounts();
let signature = await MetaWallet.sign();
const {
data,
code
} = await walletLogin({
method: "POST",
query: {
chain_address,
message: MetaEthers.getMessage(),
signature,
},
});
后端实现
/**
* <b>功能描述:</b>验签<br>
* <b>修订记录:</b><br>
*/
public static Boolean isSignatureValid(final String address, final String signature, final String message) {
log.info("isSignatureValid invoked for Address {} with Signature {} and Message {} ", address, signature, message);
final String personalMessagePrefix = "\u0019Ethereum Signed Message:\n";
boolean match = false;
final String prefix = personalMessagePrefix + message.length();
final byte[] msgHash = Hash.sha3((prefix + message).getBytes());
final byte[] signatureBytes = Numeric.hexStringToByteArray(signature);
byte v = signatureBytes[64];
if (v < 27) {
v += 27;
}
final Sign.SignatureData sd = new Sign.SignatureData(v,
Arrays.copyOfRange(signatureBytes, 0, 32),
Arrays.copyOfRange(signatureBytes, 32, 64));
String addressRecovered = null;
// Iterate for each possible key to recover
for (int i = 0; i < 4; i++) {
final BigInteger publicKey = Sign.recoverFromSignature((byte) i, new ECDSASignature(
new BigInteger(1, sd.getR()),
new BigInteger(1, sd.getS())), msgHash);
if (publicKey != null) {
addressRecovered = "0x" + Keys.getAddress(publicKey);
if (addressRecovered.equalsIgnoreCase(address)) {
match = true;
break;
}
}
}
return match;
}
当验签成功后,即实现登录,接下来基本都业务相关代码,自行开发吧!!!