【问题标题】:How can I define my Solidity contract as a javascript object?如何将我的 Solidity 合约定义为 javascript 对象?
【发布时间】:2021-08-14 23:16:05
【问题描述】:

我正在制作一个简单的应用程序来充当智能合约的前端。该合约具有公共字符串属性“消息”,我希望能够通过newContract.methods.message().call() 访问它。

我定义了一个对 showMessage() 函数的 onclick 调用,它应该将消息属性记录到控制台,但是当我单击带有 onclick 事件的按钮时,我会在这篇文章的底部收到错误消息。

新合约对象实例化下方的检查表明类型不是未定义的,但我仍然收到“未定义”错误。

编辑:
删除了无关的 ABI 部分并添加了智能合约源代码。

问题似乎与newContract 对象的范围有关。即使它是用var 声明的,它也不能通过showMessage() 函数内的全局窗口对象访问。正确的范围是多少?

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.3.5/web3.min.js" integrity="sha512-S/O+gH5szs/+/dUylm15Jp/JZJsIoWlpSVMwT6yAS4Rh7kazaRUxSzFBwnqE2/jBphcr7xovTQJaopiEZAzi+A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        
        <script type="text/javascript">
            
            let web3js;

            function startApp() {            
                var address = "...";
                const jsoninterface = [
                
                    {
                        "inputs": [
                            {
                                "internalType": "string",
                                "name": "_newMessage",
                                "type": "string"
                            }
                        ],
                        "name": "setMessage",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                   
                    {
                        "inputs": [],
                        "name": "message",
                        "outputs": [
                            {
                                "internalType": "string",
                                "name": "",
                                "type": "string"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    }
                ]
                var newContract = new web3js.eth.Contract(jsoninterface, address);
                if (typeof newContract === 'object' && typeof newContract !== 'undefined' && newContract !== null){
                    console.log("contract created")
                } else {
                    console.log("contract not created")
                }
            }
            window.addEventListener('load', function() {

                // Checking if Web3 has been injected by the browser (Mist/MetaMask)
                if (typeof web3 !== 'undefined') {
                // Use Mist/MetaMask's provider
                web3js = new Web3(web3.currentProvider);
                } else {
                    alert("Please install Metamask to continue");
                // Handle the case where the user doesn't have Metamask installed
                // Probably show them a message prompting them to install Metamask
                }

                // Now you can start your app & access web3 freely:
                startApp();
                console.log('startapp finished')
            })

            function showMessage(){
                var retval = window.newContract.methods.message().call();
                console.log(retval);
            }

        </script>
    </head>
    <body>
        <!-- the content goes here -->
        <button onclick="showMessage()">click here</button>
    </body>
</html>

这是控制台的输出。

contract created
startapp finished
Uncaught TypeError: Cannot read property 'message' of undefined
    at showMessage ((index):132)
    at HTMLButtonElement.onclick ((index):140)
showMessage @ (index):132
onclick @ (index):140

以下是智能合约代码

pragma solidity >=0.7.0 <0.9.0;


contract HelloWorld {
    string public message = "Hello World";
    uint public counter = 0;
    
    function setMessage(string calldata _newMessage) public {
        message = _newMessage;
    }
    
    function incrementCounter() public {
        counter++;
    }
}

【问题讨论】:

    标签: javascript ethereum solidity


    【解决方案1】:

    问题确实是合同变量的范围,使下面箭头所示的两个更改让我解决了我的问题。

    <!DOCTYPE html>
    <html>
        <head>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.3.5/web3.min.js" integrity="sha512-S/O+gH5szs/+/dUylm15Jp/JZJsIoWlpSVMwT6yAS4Rh7kazaRUxSzFBwnqE2/jBphcr7xovTQJaopiEZAzi+A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
            
            <script type="text/javascript">
                
                let web3js;
     ---------> var newContract;
                function startApp() {            
                    var address = "...";
                    const jsoninterface = [
                    
                        {
                            "inputs": [
                                {
                                    "internalType": "string",
                                    "name": "_newMessage",
                                    "type": "string"
                                }
                            ],
                            "name": "setMessage",
                            "outputs": [],
                            "stateMutability": "nonpayable",
                            "type": "function"
                        },
                       
                        {
                            "inputs": [],
                            "name": "message",
                            "outputs": [
                                {
                                    "internalType": "string",
                                    "name": "",
                                    "type": "string"
                                }
                            ],
                            "stateMutability": "view",
                            "type": "function"
                        }
                    ]
      ---------> window.newContract = new web3js.eth.Contract(jsoninterface, address);
                    if (typeof newContract === 'object' && typeof newContract !== 'undefined' && newContract !== null){
                        console.log("contract created")
                    } else {
                        console.log("contract not created")
                    }
                }
                window.addEventListener('load', function() {
    
                    // Checking if Web3 has been injected by the browser (Mist/MetaMask)
                    if (typeof web3 !== 'undefined') {
                    // Use Mist/MetaMask's provider
                    web3js = new Web3(web3.currentProvider);
                    } else {
                        alert("Please install Metamask to continue");
                    // Handle the case where the user doesn't have Metamask installed
                    // Probably show them a message prompting them to install Metamask
                    }
    
                    // Now you can start your app & access web3 freely:
                    startApp();
                    console.log('startapp finished')
                })
    
                function showMessage(){
                    var retval = window.newContract.methods.message().call();
                    console.log(retval);
                }
    
            </script>
        </head>
        <body>
            <!-- the content goes here -->
            <button onclick="showMessage()">click here</button>
        </body>
    </html>
    

    【讨论】:

      【解决方案2】:

      您的 ABI JSON 定义了 setMessage() 函数,但没有 message 属性(或函数)。如果您的合约中有 message 属性(或函数),则它必须是 externalpublic 才能从合约外部读取。

      在将属性或函数设为外部或公共后,您还需要重新生成 ABI JSON。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-12
        • 2018-05-31
        • 1970-01-01
        • 1970-01-01
        • 2022-12-03
        • 2017-08-19
        • 2011-05-09
        • 1970-01-01
        相关资源
        最近更新 更多