#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,
}],
});
};