Solidity

有沒有辦法從 ABI 中提取函式並將其顯示在前端?

  • September 8, 2022

我正在創建一個 DAPP,如果我通過契約的 ABI,功能將在前端顯示。

如果我通過 ABI,有沒有辦法提取合約的功能?

例如,

[
 {
   inputs: [],
   name: 'count',
   outputs: [ [Object] ],
   stateMutability: 'view',
   type: 'function'
 },
 {
   inputs: [],
   name: 'increaseCount',
   outputs: [],
   stateMutability: 'nonpayable',
   type: 'function'
 }
]

如果那是 JSON 格式的範例契約的 ABI,我需要提取countincreaseCount函式並將其顯示在前面。

謝謝!

我用純 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 中實現它會更好。

讓我知道它是否有幫助。

引用自:https://ethereum.stackexchange.com/questions/135214