我这个人很懒,发了一篇文章之后就好久没动了,我其实有考虑过要不要再发一篇关于tradingview的文章,毕竟我当年也是踩了很多坑的,搜了一下有前辈说的比较详细,也就懒得发了,看了一下之前的文章说的还是有点草率,这次讲详细点。理解失误,莫怪,我是个小白。
Web3Modal 的样式基本是不可更改,样式比较试用于pc端,那要自定义样式,然后自己判断怎么做呢?类似于:
这个需求过来的时候,我也是一头懵,要先判断有没有安装钱包,再连接钱包,然后猛翻文档,然后看到了这段话
这就可以自己判断了
看看代码
在此额外说明一下,Binance Wallet和MetaMask的连接方式一样,注入对象不一样,要额外写方法。两个钱包同时存在的时候,会默认打开Binance Wallet。所以同时存在的时候要判断一下。 walletConnect的链接方法也不一样,也得额外写调用方法。
const isNetwork = 97. //BSC测试链ID
//小狐狸调用
async initWeb3() {
const web3 = new Web3(window.ethereum); //注入对象window.ethereum
if (window.ethereum) {
window.ethereum.enable(); //默认连接
ethereum.on('accountsChanged', this.accountsChanged); //监听账户变化
ethereum.on('networkChanged', this.networkChanged);//监听网络变化
ethereum.on('close', this.disconnect); //断开连接
} else {
alert('no wallet');
return;
}
const Contract = new web3.eth.Contract(abi, address);
this.allMethods = Contract.methods;
//轮询去获取地址
const timer = setInterval(async () => {
const address = await this.getAddress(web3);
if (address) {
//地址
this.address = address;
//网络
this.network = ethereum.networkVersion;
sessionStorage.setItem('address', this.address);
//限制网络,当不在限制的网络时,强行切换(比如限制只能在BSC主链),不需要可以注释
if (this.network != isNetwork) {
this.switchNetwork();
this.address = '';
}
clearInterval(timer);
}
}, 1000);
}
//获取地址
async getAddress(web3) {
const account = await web3.eth.getCoinbase();
if (account) {
return account;
}
return false;
}
//切换网络方法,
switchNetwork() {
//调用小狐狸api方法,传入你要切换的网络id
try {
window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: Web3.utils.toHex(isNetwork) }],
});
} catch (switchError) {
if (switchError.code === 4902) {
alert('add this chain id');
}
}
}
const isBscNet = 'bsc-testnet';
//Binance Wallet调用
async initBSCWeb3() {
const web3 = new Web3(window.BinanceChain);//注入对象window.ethereum
if (window.BinanceChain) {
window.BinanceChain.enable();
BinanceChain.on('accountsChanged', this.accountsChanged);//监听账户变化
BinanceChain.on('chainChanged', this.BSCNetChanged);//监听网络变化
BinanceChain.on('disconnect', this.disconnect);//断开连接
// BinanceChain.on('close', this.disconnect);
} else {
alert('no wallet');
return;
}
const Contract = new web3.eth.Contract(abi, address);
this.allMethods = Contract.methods;
this.network = window.BinanceChain.chainId;
//网络不对时切换网络,不需要可以注释
if (this.network != isBscNet && this.network !== '0x61') {
this.switchBSCNet();
this.address = '';
}
//获取地址,异步
const account = await web3.eth.getAccounts();
if (account) {
this.address = account[0];
sessionStorage.setItem('address', this.address);
}
}
//Binance Wallet 切换网络
async switchBSCNet() {
try {
await window.BinanceChain.switchNetwork(isBscNet);
} catch (switchError) {
if (switchError.code === 4902) {
alert('add this chain id');
}
}
}
//walletConnect 链接方法, 有些坑,看上篇文章
async walletConnect() {
const provider = new WalletConnectProvider({
infuraId: infuraId, //需要自己去申请,上篇文章有讲
qrcode: true,
});
if (!provider.on) {
return;
}
// Subscribe to accounts change
provider.on('accountsChanged', this.accountsChanged);
provider.on('disconnect', (code, reason) => {
this.disconnect();
});
provider.on('close', () => {
localStorage.removeItem('walletconnect');
});
await provider.enable();
const web3 = new Web3(provider);
const accounts = await web3.eth.getAccounts();
this.address = accounts[0];
const Contract = new web3.eth.Contract(abi, address);
this.allMethods = Contract.methods;
this.network = await web3.eth.net.getId();
}
备注:abi就是你合约的abi,address就是你要调用的合约地址。
可以在bsc区块链浏览器上去查找所有的代币,搜索名字找你需要的代币,token contract就是代币的合约地址。如上,我查找的是币安链上的USDT, 0x55d398326f99059ff775485246999027b3197955就是USDT的合约地址,在搜索里面输入地址,就能得到地址的详细信息。
点击Contract就是代币的合约代码。往下翻就能看到它的Contract ABI。如果自己开发代币,后台也会给你ABI和地址。
必要参数都齐了,调用方法就能连接你的小狐狸或钱包。Contract.methods就是代币的所有方法(比如获取余额,转账)
这是代币的方法,比如USDT,我可以调用方法获取usdt的余额,那bsc呢,bsc不是代币是主币种,web3.eth就是主币种的方法,里面同样有获取余额转账的方法。
//代币获取余额
const getBal = async() = > {
const balance = await this.allMethods.balanceOf(user_address).call()
}
//代币转账,传入数量要转精度
const transfer = async (number) => {
const decimals = await this.allMethods.decimals().call();
const count = number * decimals //要专门方法处理,直接乘除会有精度丢失。
try{
const res = await this.allMethods
.transfer(toAddress, count)
.send({ from: user_address });
}catch(error){
console.log(error)
}
}
差不多了,其实我之前研究过别人的开源项目,如果你是用react,你可以看看@web3-react,这个可能能更好的解决这个问题,but,i'm vuer.