有沒有辦法從 ABI 中提取函式並將其顯示在前端?
我正在創建一個 DAPP,如果我通過契約的 ABI,功能將在前端顯示。
如果我通過 ABI,有沒有辦法提取合約的功能?
例如,
[ { inputs: [], name: 'count', outputs: [ [Object] ], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'increaseCount', outputs: [], stateMutability: 'nonpayable', type: 'function' } ]
如果那是 JSON 格式的範例契約的 ABI,我需要提取count和increaseCount函式並將其顯示在前面。
謝謝!
我用純 JS 和 HTML 創建了一個簡單而快速的實現,所以你可以看到類似的事情是如何完成的。
檢查(替換
<yourInfuraRinkebyKey>
為您自己的 infura api 密鑰):<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.7.5/web3.min.js" integrity="sha512-/T7YwzOsNeoNkuTfYKXn3CrJCGc5cnC8T4QW46Hy+3Xjdjrxzokmbx8M8Xavjq1K7dN4958kIRGy4J03VRIlSg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> </head> <body> <div id="container"> </div> <script> const web3 = new Web3("https://rinkeby.infura.io/v3/<yourInfuraRinkebyKey>"); const abi = [ { "inputs": [ { "internalType": "uint256", "name": "_element", "type": "uint256" } ], "name": "addElement", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "count", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "element", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "increaseCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ]; const counter = new web3.eth.Contract( abi, "0x0ea68C4FcF2B49280DC599e5F5D907844135f107", { from: "0x64eF77725E9E408FD6ea587ECAeAcA2476234Ba9", } ); async function handleClick() { const button = event.target; console.log(button) const children = [...button.parentNode.children]; const inputs = children.filter(element => element.nodeName === 'INPUT'); const args = inputs.map(input => input.value); const functionName = button.innerText; console.log("functionName: ", functionName); // Dynamically calling the function with it's args. More logic should be added, like making sure required args are provided and the correct type. const result = await counter.methods[functionName](...args).call(); // Show this result somewhere console.log("result: ", result) const displaySpan = children[children.length - 1]; displaySpan.innerText = result; } const groups = abi.filter(element => element.type === 'function') .map(element => { const button = document.createElement('button'); button.textContent = element.name; button.onclick = handleClick; const group = document.createElement('div'); group.setAttribute("class", "group"); group.appendChild(button); for(let i = 0; i < element.inputs.length; i++) { const input = element.inputs[i]; const inputText = document.createElement('input'); inputText.setAttribute("type", "text"); inputText.setAttribute("placeholder", `${input.type} ${input.name}`); group.appendChild(inputText); } const display = document.createElement('span'); group.appendChild(display); return group; }); const container = document.getElementById("container"); for(let i = 0; i < groups.length; i++) { container.appendChild(groups[i]); } </script> </body> </html>
它看起來像這樣:
醜陋,但這只是一個關於如何在前端動態創建按鈕/欄位以與智能合約互動的想法。
請注意,在我的範例中,應該使狀態靜音的函式不會改變狀態,因為它沒有連接到 Metamask 之類的錢包或類似的東西,因此它無法簽署交易。但是這些
view
函式將起作用並返回契約中的目前值。在呼叫函式時,檢查瀏覽器中的網路選項卡並分析正在發送的有效負載和響應。
請記住
<yourInfuraRinkebyKey>
用您自己的 infura api 密鑰替換,以便您可以測試此程式碼。合約部署在 Rinkeby 上,地址為:0x0ea68C4FcF2B49280DC599e5F5D907844135f107
它已經過驗證,因此您可以使用 rinkeby etherscan 中的函式:
https://rinkeby.etherscan.io/address/0x0ea68C4FcF2B49280DC599e5F5D907844135f107#readContract
https://rinkeby.etherscan.io/address/0x0ea68C4FcF2B49280DC599e5F5D907844135f107#writeContract
也許你想創建一個類似於 etherescan 的功能,它允許你與智能合約進行互動,向你顯示函式名稱和參數以及結果。
我為您提供了一個起點,讓您有一個想法。
也許在 React 中實現它會更好。
讓我知道它是否有幫助。