泸州公司做网站,国内网页设计师个人网站,做自己的首席安全官的网站,校企合作网站建设审核看清楚了 #xff01; 这是以太坊测试网络#xff01;用于学习的测试网络#xff01;#xff01;#xff01; 有关web3 和区块链的内容为什么要给我审核不通过#xff1f; 别人凭什么可以发#xff01;
目标成果#xff1a; 实现功能分析#xff1a;
显示账户信…审核看清楚了 这是以太坊测试网络用于学习的测试网络 有关web3 和区块链的内容为什么要给我审核不通过 别人凭什么可以发
目标成果 实现功能分析
显示账户信息地址、chainID、网络ID、余额实现转账功能
需要准备的事情
一个有sepolia ETH余额的web3账户没有可以找水龙头领取或者某鱼购买浏览器插件安装了 MetaMask钱包插件小狐狸钱包准备一个web容器我这边使用的是nginx
操作环节
先写出网页大概的内容布局 !DOCTYPE html
htmlheadmeta charsetutf-8titlejs连接web3钱包/title/headbodydivdivh3详情信息/h3/divdivdivlabel账户地址span/span/label/divdivlabelChainIDspan/span/label/divdivlabel网络IDspan/span/label/divdivlabel余额span/span/label/div/divdivbutton转账/button/div/divdivlabel对手地址input typetext/labelbrlabelETH数量input typetext/labelbrbutton确定/buttonbutton取消/button/div/body
/html接下来是写js部分
把大概的框架都写出来:
//判断浏览器是否具备MetaMask环境const initialize async (){if(!isMetaMaskInstalled()){//如果没安装弹出窗口alert(请先安装 MetaMask);}else{await getNetwork(); //获取网络await getChainId(); //获取链await getAccount(); //获取账户地址await getBalance(); //获取余额}}在上面这个initialize()方法中,里面我们调用了5个方法,每个方法都有其各自的作用.
方法作用isMetaMaskInstalled()用来判断浏览器是否安装了MetaMask钱包getNetwork()获取网络号getChainId()获取链IDgetAccount()获取账户地址getBalance()获取账户余额
现在开始着手写这几个方法
判断是否安装 const isMetaMaskInstalled () {const { ethereum } window;return Boolean(ethereum ethereum.isMetaMask);}获取网络号然然后渲染到html页面上
html部分要要加上 对应的id进行innerHTML
divlabel账户地址span idaccountSpan/span/label/divdivlabelChainIDspan idChainIdSpan/span/label/divdivlabel网络IDspan idNetworkSpan/span/label/divdivlabel余额span idBalanceSpan/span/label/divjs部分 const getNetwork async () {try {const networkId await ethereum.request({ method: net_version });NetworkSpan.innerHTML networkId;} catch (error) {console.error(error);}}const getChainId async () {try {const chainId await ethereum.request({ method: eth_chainId });ChainIdSpan.innerHTML chainId;} catch (error) {console.error(error);}}const getAccount async () {try {const accounts await ethereum.request({ method: eth_requestAccounts });//调用这个方法会弹出MetaMask的一个授权窗口accountSpan.innerHTML accounts[0]; // 显示连接第一个账户} catch (error) {console.error(error);}}const getBalance async () {const accounts await ethereum.request({ method: eth_requestAccounts });const balance await ethereum.request({method: eth_getBalance,params: [accounts[0], latest]});userBalance parseInt(balance, 16);const ethBalance Web3.utils.fromWei(balance, ether);//这里要引入一个web3.js文件BalanceSpan.innerHTML ${ethBalance} ETH;}window.addEventListener(DOMContentLoaded, initialize);//进入网页后自动调用initialize方法,不调用就无法查询和渲染页面还要引入一个web3.js用于单位转换(其实我们也可以自己计算) script srchttps://cdn.jsdelivr.net/npm/web31.6.0/dist/web3.min.js/script现在已经完成显示账户信息的功能了! 接下来我们要实现我们的转账功能.代码如下还没有美化的版本 !DOCTYPE html
htmlheadmeta charsetutf-8titlejs连接web3钱包/titlestyle#transferModal {display: none;position: fixed;left: 50%;top: 50%;transform: translate(-50%, -50%);background-color: white;padding: 20px;box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);}/style/headbodydivdivh3详情信息/h3/divdivdivlabel账户地址span idaccountSpan/span/label/divdivlabelChainIDspan idChainIdSpan/span/label/divdivlabel网络IDspan idNetworkSpan/span/label/divdivlabel余额span idBalanceSpan/span/label/div/divdivbutton idsendButton转账/button/div/divdiv idtransferModallabel对手地址input typetext idrecipientAddress/labelbrlabelETH数量input typetext idethAmount required min0 step0.0001/labelbrbutton idconfirmTransferButton typesubmit确定/buttonbutton idcancelTransferButton取消/button/divscript srchttps://cdn.jsdelivr.net/npm/web31.6.0/dist/web3.min.js/scriptscript//判断浏览器是否具备MetaMask环境const initialize async () {if (!isMetaMaskInstalled()) {//如果没安装弹出窗口alert(请先安装 MetaMask);} else {await getNetwork(); //获取网络await getChainId(); //获取链await getAccount(); //获取账户地址await getBalance(); //获取余额}}//判断是否安装const isMetaMaskInstalled () {const { ethereum } window;return Boolean(ethereum ethereum.isMetaMask);}const getNetwork async () {try {const networkId await ethereum.request({ method: net_version });NetworkSpan.innerHTML networkId;} catch (error) {console.error(error);}}const getChainId async () {try {const chainId await ethereum.request({ method: eth_chainId });ChainIdSpan.innerHTML chainId;} catch (error) {console.error(error);}}const getAccount async () {try {const accounts await ethereum.request({ method: eth_requestAccounts });//调用这个方法会弹出MetaMask的一个授权窗口accountSpan.innerHTML accounts[0]; // 显示连接第一个账户} catch (error) {console.error(error);}}const getBalance async () {const accounts await ethereum.request({ method: eth_requestAccounts });const balance await ethereum.request({method: eth_getBalance,params: [accounts[0], latest]});userBalance parseInt(balance, 16);const ethBalance Web3.utils.fromWei(balance, ether);//这里要引入一个web3.js文件BalanceSpan.innerHTML ${ethBalance} ETH;}//获取最新的gas pricesconst getGasPrice async () {const web3 new Web3(Web3.givenProvider);const gasPrice await web3.eth.getGasPrice();console.log(Current gas prices gasPrice);return gasPrice;}// 显示和隐藏转账模态窗口const sendButton document.getElementById(sendButton);const transferModal document.getElementById(transferModal);const confirmTransferButton document.getElementById(confirmTransferButton);const cancelTransferButton document.getElementById(cancelTransferButton);sendButton.addEventListener(click, () {transferModal.style.display block;});cancelTransferButton.addEventListener(click, () {transferModal.style.display none;});// 处理转账逻辑confirmTransferButton.addEventListener(click, async () {const recipientAddress document.getElementById(recipientAddress).value;const ethAmount document.getElementById(ethAmount).value;if (!recipientAddress || !ethAmount) {alert(请填写所有字段);return;}try {const web3 new Web3(Web3.givenProvider);const accounts await ethereum.request({ method: eth_requestAccounts });const senderAddress accounts[0];const transactionParameters {to: recipientAddress,from: senderAddress,value: web3.utils.toHex(web3.utils.toWei(ethAmount, ether)),gasPrice: await getGasPrice(),gas: 21000, // 默认的gas limit};await ethereum.request({method: eth_sendTransaction,params: [transactionParameters],});alert(转账成功);transferModal.style.display none;await getBalance(); // 更新余额} catch (error) {console.error(error);alert(转账失败);}});// 切换账户的时候触发ethereum.on(accountsChanged, function (accounts) {console.log(账户已切换);window.location.reload();});// 切换网络的时候触发ethereum.on(chainChanged, function (accounts) {console.log(网络已切换);window.location.reload();});window.addEventListener(DOMContentLoaded, initialize);/script/body
/html
结果: 这样就可以完成转账功能了!
美化 二选一 bootstrap or layui.
使用bootstrap 美化一下 code:
!DOCTYPE html
htmlheadmeta charsetutf-8titleWeb3 钱包/title link relicon hrefhttp://u5a.cn/uftiP typeimage/x-icon/linklink hrefhttps://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css relstylesheetlink hrefhttps://cdn.bootcdn.net/ajax/libs/font-awesome/6.6.0/css/brands.min.css relstylesheetstylebody {background-color: #f8f9fa;}.wallet-info {margin-top: 20px;}.wallet-info label {font-weight: bold;}.wallet-info span {font-style: italic;}.navbar-brand {font-weight: bold;}.copy-icon {cursor: pointer;margin-left: 10px;color: #007bff;}.copy-icon:hover {color: #0056b3;}/style/headbodynav classnavbar navbar-expand-sm navbar-light bg-lightdiv classcontainer-fluidspan classnavbar-brand币圈老韭菜/span/div/navdiv classcontainer wallet-infodivh3详情信息/h3/divdivdiv classrowdiv classcol-md-6 mb-3label账户地址/labelspan idaccountSpan/spani classfas fa-copy copy-icon onclickcopyAddress()/i/divdiv classcol-md-6 mb-3labelChain/labelspan idNetworkSpan/span/div/divdiv classrowdiv classcol-md-6 mb-3label链ID/labelspan idChainIdSpan/span/divdiv classcol-md-6 mb-3label余额/labelspan idBalanceSpan/span/div/div/divdivbutton classbtn btn-primary idsendButton转账/button/div/div!-- 转账表单模态框 --div classmodal fade idtransferModal tabindex-1 aria-labelledbytransferModalLabel aria-hiddentruediv classmodal-dialogdiv classmodal-contentdiv classmodal-headerh5 classmodal-title idtransferModalLabel转账/h5button typebutton classbtn-close data-bs-dismissmodal aria-labelClose/button/divdiv classmodal-bodyform idtransferFormdiv classmb-3label forrecipientAddress classform-label转账地址/labelinput typetext classform-control idrecipientAddress required/divdiv classmb-3label forethAmount classform-labelETH 数量/labelinput typenumber classform-control idethAmount required min0 step0.0001/divbutton typesubmit classbtn btn-primary确定转账/button/form/div/div/div/divscript srchttps://cdn.jsdelivr.net/npm/web31.6.0/dist/web3.min.js/scriptscriptlet userBalance 0;// 初始化const initialize () {checkMetaMaskClient();}// 如果安装了小狐狸才可以获取信息const checkMetaMaskClient async () {if (!isMetaMaskInstalled()) {alert(请安装 MetaMask);} else {await getNetworkAndChainId(); // 获取网络IDawait getAccount(); // 使用 eth_requestAccounts 获取账户await getBalance(); // 使用 eth_getBalance 获取余额}}// 验证是不是安装了const isMetaMaskInstalled () {const { ethereum } window;return Boolean(ethereum ethereum.isMetaMask);}const getAccount async () {try {const accounts await ethereum.request({ method: eth_requestAccounts });accountSpan.innerHTML accounts[0]; // 显示第一个账户} catch (error) {console.error(error);}}const getNetworkAndChainId async () {try {const chainId await ethereum.request({ method: eth_chainId });ChainIdSpan.innerHTML chainId;const networkId await ethereum.request({ method: net_version });NetworkSpan.innerHTML networkId;} catch (error) {console.error(error);}}const getBalance async () {const accounts await ethereum.request({ method: eth_requestAccounts });const balance await ethereum.request({method: eth_getBalance,params: [accounts[0], latest]});userBalance parseInt(balance, 16);const ethBalance Web3.utils.fromWei(balance, ether);BalanceSpan.innerHTML ${ethBalance} ETH;}const getGasPrice async () {const web3 new Web3(Web3.givenProvider);const gasPrice await web3.eth.getGasPrice();console.log(Current gas prices gasPrice);return gasPrice;}// 事件触发// 点击转账按钮的时候触发document.getElementById(sendButton).onclick () {// 打开模态框new bootstrap.Modal(document.getElementById(transferModal)).show();}// 提交转账表单document.getElementById(transferForm).onsubmit async (e) {e.preventDefault();const recipientAddress document.getElementById(recipientAddress).value;const ethAmount parseFloat(document.getElementById(ethAmount).value);const weiAmount Web3.utils.toWei(ethAmount.toString(), ether);if (weiAmount 0) {alert(ETH 数量必须大于 0);return;}if (weiAmount userBalance) {alert(余额不足);return;}const gasPrice await getGasPrice();const accounts await ethereum.request({ method: eth_requestAccounts });const params [{from: accounts[0],to: recipientAddress,value: Web3.utils.toHex(weiAmount),gas: 0x5208, // 21000 gas 的十六进制gasPrice: Web3.utils.toHex(gasPrice), // 当前网络 gas price}];try {await ethereum.request({method: eth_sendTransaction,params: params,});alert(转账成功);} catch (error) {console.error(error);alert(转账失败);}}// 一键复制地址功能const copyAddress () {const address document.getElementById(accountSpan).textContent;navigator.clipboard.writeText(address).then(() {alert(地址已复制);}).catch(err {console.error(无法复制地址, err);});}// 切换账户的时候触发ethereum.on(accountsChanged, function (accounts) {console.log(账户已切换);window.location.reload();});// 切换网络的时候触发ethereum.on(chainChanged, function (accounts) {console.log(网络已切换);window.location.reload();});window.addEventListener(DOMContentLoaded, initialize);/scriptscript srchttps://cdn.staticfile.net/popper.js/2.11.8/umd/popper.min.js/script script srchttps://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js/scriptscript srchttps://cdn.staticfile.net/font-awesome/6.5.1/js/all.min.js/script/body
/html使用layui美化的效果 (感觉做的还是太丑了) code:
!DOCTYPE html
htmlheadmeta charsetutf-8titlejs连接web3钱包/titlelink relstylesheet hrefhttps://cdn.staticfile.net/layui/2.9.4/css/layui.min.css relstylesheetstylebody {font-size: 16px;}.layui-container {margin-top: 20px;}.layui-col-md4 {padding: 10px 0;}#transferModal {display: none;position: fixed;left: 50%;top: 50%;transform: translate(-50%, -50%);background-color: white;padding: 20px;box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);font-size: 16px;}.layui-form-label {width: 100px;}/style/headbodydiv classlayui-containerdivh3详情信息/h3/divdiv classlayui-row layui-col-space10div classlayui-col-md6label账户地址span idaccountSpan classlayui-badge/span/label/divdiv classlayui-col-md6labelChainIDspan idChainIdSpan classlayui-badge layui-bg-blue/span/label/divdiv classlayui-col-md6label网络IDspan idNetworkSpan classlayui-badge layui-bg-green/span/label/divdiv classlayui-col-md6label余额span idBalanceSpan classlayui-badge layui-bg-orange/span/label/div/divdivbutton idsendButton classlayui-btn layui-btn-normal转账/button/div/divdiv idtransferModal classlayui-carddiv classlayui-card-header转账/divdiv classlayui-card-bodydiv classlayui-form-itemlabel classlayui-form-label对手地址/labeldiv classlayui-input-blockinput typetext idrecipientAddress classlayui-input required/div/divdiv classlayui-form-itemlabel classlayui-form-labelETH数量/labeldiv classlayui-input-blockinput typetext idethAmount classlayui-input required min0 step0.0001/div/divdiv classlayui-form-itemdiv classlayui-input-blockbutton idconfirmTransferButton classlayui-btn typesubmit确定/buttonbutton idcancelTransferButton classlayui-btn layui-btn-primary取消/button/div/div/div/divscript srchttps://cdn.staticfile.net/layui/2.9.4/layui.min.js/scriptscript srchttps://cdn.jsdelivr.net/npm/web31.6.0/dist/web3.min.js/scriptscriptlayui.use([layer, form], function(){const layer layui.layer;const form layui.form;//判断浏览器是否具备MetaMask环境const initialize async () {if (!isMetaMaskInstalled()) {//如果没安装弹出窗口layer.alert(请先安装 MetaMask);} else {await getNetwork(); //获取网络await getChainId(); //获取链await getAccount(); //获取账户地址await getBalance(); //获取余额}}//判断是否安装const isMetaMaskInstalled () {const { ethereum } window;return Boolean(ethereum ethereum.isMetaMask);}const getNetwork async () {try {const networkId await ethereum.request({ method: net_version });NetworkSpan.innerHTML networkId;} catch (error) {console.error(error);}}const getChainId async () {try {const chainId await ethereum.request({ method: eth_chainId });ChainIdSpan.innerHTML chainId;} catch (error) {console.error(error);}}const getAccount async () {try {const accounts await ethereum.request({ method: eth_requestAccounts });//调用这个方法会弹出MetaMask的一个授权窗口accountSpan.innerHTML accounts[0]; // 显示连接第一个账户} catch (error) {console.error(error);}}const getBalance async () {const accounts await ethereum.request({ method: eth_requestAccounts });const balance await ethereum.request({method: eth_getBalance,params: [accounts[0], latest]});userBalance parseInt(balance, 16);const ethBalance Web3.utils.fromWei(balance, ether);//这里要引入一个web3.js文件BalanceSpan.innerHTML ${ethBalance} ETH;}//获取最新的gas pricesconst getGasPrice async () {const web3 new Web3(Web3.givenProvider);const gasPrice await web3.eth.getGasPrice();console.log(Current gas prices gasPrice);return gasPrice;}// 显示和隐藏转账模态窗口const sendButton document.getElementById(sendButton);const transferModal document.getElementById(transferModal);const confirmTransferButton document.getElementById(confirmTransferButton);const cancelTransferButton document.getElementById(cancelTransferButton);sendButton.addEventListener(click, () {transferModal.style.display block;});cancelTransferButton.addEventListener(click, () {transferModal.style.display none;});// 处理转账逻辑confirmTransferButton.addEventListener(click, async () {const recipientAddress document.getElementById(recipientAddress).value;const ethAmount document.getElementById(ethAmount).value;if (!recipientAddress || !ethAmount) {layer.alert(请填写所有字段);return;}try {const web3 new Web3(Web3.givenProvider);const accounts await ethereum.request({ method: eth_requestAccounts });const senderAddress accounts[0];const transactionParameters {to: recipientAddress,from: senderAddress,value: web3.utils.toHex(web3.utils.toWei(ethAmount, ether)),gasPrice: await getGasPrice(),gas: 21000, // 默认的gas limit};await ethereum.request({method: eth_sendTransaction,params: [transactionParameters],});layer.alert(转账成功);transferModal.style.display none;await getBalance(); // 更新余额} catch (error) {console.error(error);layer.alert(转账失败);}});// 切换账户的时候触发ethereum.on(accountsChanged, function (accounts) {console.log(账户已切换);window.location.reload();});// 切换网络的时候触发ethereum.on(chainChanged, function (accounts) {console.log(网络已切换);window.location.reload();});window.addEventListener(DOMContentLoaded, initialize);});/script/body
/html
展望:
后续还会添加切换账户\网络\加入代币\选择转账的币种\转账的历史记录
小结:
关于gas
Gas PriceGas 价格 表示为 gwei1 gwei 10^-9 ETH,wei是以太坊的最小单位。用户可以设定他们愿意支付的 gas 价格。Gas 价格越高交易被矿工处理的速度可能越快因为矿工更倾向于处理 gas 价格较高的交易以获得更多的报酬。 Gas LimitGas 限额 用户愿意为一个特定交易支付的最大 gas 数量。防止意外消耗过多的 gas 资源。 Transaction Fee交易费用 计算方式Gas Price * Gas Used。例如如果 gas 价格是 20 gwei并且交易消耗了 21,000 gas那么交易费用将是 20 gwei * 21,000 420,000 gwei大约等于 0.00042 ETH。
Gas 的作用
防止滥用 每个操作都需要支付 gas防止用户随意发起大量计算资源消耗的操作确保网络的安全性和稳定性。 奖励矿工 矿工通过处理交易获得 gas 费用作为奖励激励他们维护网络。 确保执行 确保用户为执行智能合约或其他操作付费智能合约的复杂度越高所需的 gas 就越多。
功能描述
1. MetaMask 环境检测
功能检查浏览器是否安装了 MetaMask 插件。实现通过 isMetaMaskInstalled 函数检测 ethereum 对象及其 isMetaMask 属性。
2. 获取网络信息
功能获取并显示当前网络的 Network ID 和 Chain ID。实现通过调用 MetaMask 提供的 ethereum.request({ method: net_version }) 和 ethereum.request({ method: eth_chainId }) 获取 Network ID 和 Chain ID。
3. 获取账户信息
功能获取并显示连接的以太坊账户地址。实现通过调用 MetaMask 提供的 ethereum.request({ method: eth_requestAccounts }) 获取账户地址并显示在页面上。
4. 获取账户余额
功能获取并显示当前账户的 ETH 余额。实现通过调用 MetaMask 提供的 ethereum.request({ method: eth_getBalance, params: [accounts[0], latest] }) 获取余额并转换为 ETH 后显示在页面上。
5. 转账功能
功能用户可以通过输入对手地址和 ETH 数量来进行转账操作。实现 提供一个按钮用于显示转账模态窗口。模态窗口中有输入框用于输入对手地址和转账数量。点击确定按钮后调用 MetaMask 提供的 ethereum.request({ method: eth_sendTransaction, params: [transactionParameters] }) 完成转账。
6. 实时更新
功能当账户或网络发生变化时页面会自动刷新。实现通过 ethereum.on(accountsChanged) 和 ethereum.on(chainChanged) 事件监听账户和网络变化并刷新页面以更新显示的信息。