Dapp Не пойман (в обещании) Ошибка типа: Не удается прочитать свойство «setGreeting» неопределенного

#javascript #solidity

Вопрос:

Я пытался создать базовое приложение «Приветствие», но я не понимаю, почему оно выдает такую ошибку: Не поймано (в обещании) Ошибка типа: Не удается прочитать свойство «setGreeting» неопределенного. Я понимаю, что что-то не так с функциями setGreeting, но я понятия не имею. Я думал, что проблема в abi или имени функции, но нет. Также я проверил, развернуты ли они в одной сети, да, они это делают. И самое интересное, что функция вызова работает нормально, но отправка выдает ошибку. Это html/js код.

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    <button class="enableEthereumButton">Enable Ethereum</button>
    <div class = 'intro' id='intro'>
        <h2>Account <span class="showAccount"></span></h2>
        <h2>Balance: <span class="showBalance"></span> </h2>
        <h2>Greeting<span class="greet"></span></h2>
    </div>
    <input id="elem1" type="text" name="quantity" placeholder="Количество">
    <input id="butt" type="button" value="Кнопка"/><br><br>
    <div id="str"></div>
<script src="js/web3.min.js"></script>
    <script>
       if (typeof window.ethereum !== 'undefined') {
            console.log('MetaMask is installed!');
            var Web3 = require('web3');
            var web3 = new Web3(new Web3.providers.HttpProvider('https://data-seed-prebsc-1-s1.binance.org:8545/'));  
        } else{
            console.log('install metamask')
        }

        
        const contractAbi = [
    {
        "constant": true,
        "inputs": [],
        "name": "getGreeting",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "internalType": "string",
                "name": "_greeting",
                "type": "string"
            }
        ],
        "name": "setGreeting",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }
]

      // Set Contract Address
        const contractAddress = '0x6952803ea6E5048b85ab99f94A23caf4610ebD45'; // Add Your Contract address here!!!

      // Set the Contract
        const contract = web3.eth.contract(contractAbi).at(contractAddress);


        const ethereumButton = document.querySelector('.enableEthereumButton');
        const showAccount = document.querySelector('.showAccount');
        const showBalance = document.querySelector('.showBalance');
        const Greeting = document.querySelector('.greet');
            
        ethereumButton.addEventListener('click', () => {
            getAccount();
        });
        
        
        async function getAccount(){
            const accounts = await ethereum.request({method: 'eth_requestAccounts'});
            const account = accounts[0];
            showAccount.innerHTML= account;
        const balance = await ethereum.request({
            method: 'eth_getBalance',
            params: [account, "latest",]
        });
        
        const read = parseInt(balance)/10**18;

        console.log(read.toFixed(5));
        showBalance.innerHTML = read.toFixed(5);
        
        contract.getGreeting(function(err, candidateName){
            Greeting.innerHTML= candidateName;
});


        butt.onclick = async function() {
            var val = document.getElementById('elem1').value;
            document.getElementById('str').innerHTML="Вы ввели: " val;
            await contract.functions.setGreeting(val).send({from: account})
};

}

</script>
</body>
</html>
 

И код солидности

 pragma solidity ^0.5.16;
contract greeter{
    string greeting='Hello';
    
    function setGreeting(string memory _greeting) public returns(bool){
        greeting=_greeting;
        return true;
    }
    function getGreeting() public view returns(string memory) {
        return greeting;
    }
}

 

Ответ №1:

Web3 использует contract.методы, а не contract.functions .

Если бы у вашего приложения был закрытый ключ для account (или поставщика с разблокированным account ), вы могли бы просто использовать

 await contract.methods.setGreeting(val).send({from: account});
 

Однако, поскольку ваш код находится на интерфейсе и использует API поставщика Ethereum (вероятно, реализованный MetaMask) для доступа к учетной записи, у него, скорее всего, нет закрытого ключа (или разблокированной учетной записи) для отправки транзакции.

Вам нужно будет создать поле транзакции data с помощью функции web3 encodeABI (), а затем вызвать метод запроса API поставщика Ethereum (), чтобы пользователь мог вручную подтвердить транзакцию в своей метамаске (или в любом кошельке, который он использует).

 butt.onclick = async function() {
    var val = document.getElementById('elem1').value;
    document.getElementById('str').innerHTML="Вы ввели: " val;
    var dataFieldValue = await contract.methods.setGreeting(val).encodeABI();
    ethereum.request({
        method: 'eth_sendTransaction',
        [{
            from: account,
            to: contractAddress,
            data: dataFieldValue,
        }],
    });
};