The Contract is given above the html file code.
It's basically getting and setting numbers.
I have used promises in my code. Is that the problem?
The ABI is correct as well as the Contract Address.
I have used web3.currentProvider because i am using metamask.
I am a beginner in blockchain.
pragma solidity ^0.5.0;
contract sample {
uint number;
constructor () public {
number = 5;
}
function getNum () public view returns (uint) {
return number;
}
function setNum (uint n) public {
number = n;
}
}
At console, Error:
Uncaught TypeError: Cannot read property 'getNum' of undefined
at index.html:51
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Test for Web3</title>
<!--<script src="https://cdn.jsdelivr.net/npm/web3#1.2.1/src/index.min.js"></script>-->
</head>
<body>
<script>
var web3;
web3 = new Web3(web3.currentProvider);
var contract = web3.eth.contract(
[
{
"constant": false,
"inputs": [
{
"name": "n",
"type": "uint256"
}
],
"name": "setNum",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"constant": true,
"inputs": [],
"name": "getNum",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
],"0x0c094f6ffbf8dbfde107e819e5060c509eab8951");
contract.methods.getNum().call().then(function(result){
console.log("Number: " + JSON.stringify(result));
});
</script>
</body>
</html>
Looks like you are using 1.X web3.js version. Use var contract = new web3.eth.Contract in this case. See https://web3js.readthedocs.io/en/v1.2.0/web3-eth-contract.html for more info:
new web3.eth.Contract(jsonInterface[, address][, options])
Related
I'm calling the methods in the deployed smart contracts in Ganache. Other methods are working fine, but the view functions returns an error.
Here's the view function in Solidity:
mapping (address => Count) private counts;
function getCounts (address user)
public
view
returns(uint a, uint b, uint total){
return(counts[user].a, counts[user].b, counts[user].total);
}
Here's how I call the method:
web3.eth.getAccounts(function(error, accounts){
if(error){
console.log(error);
}
var account = accounts[0];
contracts.SampleContract.deployed().then(function(instance){
credsInstance = instance;
return credsInstance.getCounts.call(account, {from: account});
}).then(function(creds){
console.log(creds[0]);
}).catch(function(error){
console.log(error.message);
});
});
Here's the ABI of getCounts
{
"inputs": [
{
"internalType": "address",
"name": "user",
"type": "address"
}
],
"name": "getCounts",
"outputs": [
{
"internalType": "uint256",
"name": "academic",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "workExp",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "total",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
I'm getting this error:
Returned values aren't valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced.
I also have the latest web3. How can I fix this?
Edit:
to initialize the contract I used Truffle's official documentation. Here's the code:
var contract = require('#truffle/contract');
$.getJSON('../build/contracts/SampleContract.json', function(data) {
// Get the necessary contract artifact file and instantiate it with #truffle/contract
var CredsArtifact = data;
contracts.SampleContract = TruffleContract(CredsArtifact);
// Set the provider for our contract
contracts.SampleContract.setProvider(web3Provider);
});
I had the same problem, and I was using Hardhat .
after spending hours and not resolved, I switched Rinkeby test network, and everything goes well.
refer to: https://ethereum.stackexchange.com/a/129721/30431
I'm trying to connect this example to a frontend using web3. I have it copied exactly in my truffle project /contracts folder.
Compilation and migration are both successful. (I have truffle configured to deploy on my ganache test network, and when I run truffle migrate, I see that the first account is debited ether).
I've created a Vue app to interact with the contract via web3. Here's what my component looks like:
<template>
<div class="hello">
<button #click="inc">increment</button>
<button #click="dec">decrement</button>
<button #click="get">get</button>
</div>
</template>
<script>
const Web3 = require("web3");
const addr = '0xfbe7892aF06c7ecfbd83a0aD7F1D0a228d90Bf89'
const abi = [
{
"inputs": [],
"name": "count",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [],
"name": "get",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [],
"name": "inc",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "dec",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
export default {
name: 'HelloWorld',
data () {
return {
web3: null,
contract: null,
}
},
methods: {
get(){
self.contract.methods.get().call(function(err, result){
console.log(result)
})
},
inc(){
self.contract.methods.inc().call(function(err, result){
console.log(result)
})
},
dec(){
self.contract.methods.dec().call(function(err, result){
console.log(result)
})
},
},
created () {
self.web3 = new Web3('http://localhost:7545')
self.contract = new self.web3.eth.Contract(abi, addr)
}
}
</script>
When I run inc, no err is thrown. I expect to see that value increment when I run get, but it always outputs 0 - apparently inc doesn't update the state. Am I missing something?
There's a difference between a call (read-only, gas-free) and a transaction (read-write, costs gas fees).
Since you want the inc() function to update the state, you need to send() a transaction instead of a call.
Your local web3 instance (usually in production) or the remote node (usually in development, e.g. using Ganache) needs to hold the private key to the senderAddress to be able to send the transaction.
self.contract.methods.inc().send({from: senderAddress}, function(err, result){
console.log(result)
})
"pagemap": {
"cse_thumbnail": [
{
"src": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTviYVS-9NyQU80P95iiB8_h2MuM6FM4u7a56V5_KFbD-PNqhbPbZ9KRQDf",
"width": "263",
"height": "192"
}
],
"metatags": [
{
"msapplication-tilecolor": "#D70F64",
"msapplication-config": "none",
"msapplication-square70x70logo": "https://micro-assets.foodora.com/favicons/fp/square70x70logo.png",
"viewport": "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no",
"msapplication-square310x310logo": "https://micro-assets.foodora.com/favicons/fp/square310x310logo.png",
"msapplication-wide310x150logo": "https://micro-assets.foodora.com/favicons/fp/wide310x150logo.png",
"msapplication-square150x150logo": "https://micro-assets.foodora.com/favicons/fp/square150x150logo.png"
}
],
"cse_image": [
{
"src": "https://images.deliveryhero.io/image/fd-tw/LH/a3pj-hero.jpg"
}
]
}
How to get cse_thumbnail -> src
my code is
-- pagemap.cse_thumbnail[0].src--
Appscript is show me below
--TypeError: Cannot read property '0' of undefined --
I can't reproduce the error. It works just fine:
var jsn = {"pagemap": {
"cse_thumbnail": [
{
"src": "https://encrypted-tbn0.gstatic.com",
"width": "263",
"height": "192"
}
],
}
};
console.log(jsn.pagemap.cse_thumbnail[0].src);
Perhaps the error in the way you're tying to get the value. Show this part of your script.
I coded this really simple smart contract in Solidity which allows users to add todo tasks to their personal list, to fetch their list of todos, and so on.
pragma solidity ^0.8.0;
contract ToDo {
struct Task {
string content;
bool completed;
}
mapping(address => Task[]) private tasks;
function addTask(string memory content) public {
tasks[msg.sender].push(Task(content, false));
}
function changeTaskState(uint256 taskId) public {
tasks[msg.sender][taskId].completed = !tasks[msg.sender][taskId].completed;
}
function editTaskContent(uint256 taskId, string memory content) public {
tasks[msg.sender][taskId].content = content;
}
function getTasks() public view returns(Task[] memory) {
return tasks[msg.sender];
}
}
This works exactly as intended when deployed through Truffle and tested in the Truffle(develop) terminal:
truffle(develop)> const todo = await ToDo.deployed()
undefined
truffle(develop)> todo.getTasks()
[]
truffle(develop)> todo.addTask("Hello, world!")
{
tx: '0x7e607352c1ab8f6532c5b43e282eb20f29d5bfa451dfbb873bac3506df00cb1a',
receipt: {
transactionHash: '0x7e607352c1ab8f6532c5b43e282eb20f29d5bfa451dfbb873bac3506df00cb1a',
transactionIndex: 0,
blockHash: '0x98b361190eadf1905c3e15b5054aa4ace8eaa33a2b4d35898f78e2165ea996a2',
blockNumber: 5,
from: '0x3455100c0b0617afbf0f53db5e5c07366e20791b',
to: '0x645a78fe8eb3529291ba63a8e420d26c7baf61a0',
gasUsed: 66634,
cumulativeGasUsed: 66634,
contractAddress: null,
logs: [],
status: true,
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
rawLogs: []
},
logs: []
}
truffle(develop)> todo.changeTaskState(0)
{
tx: '0xddb313978411cd3f1429f1eb61b9bbde816e3a874d765aa5588a69508d226b44',
receipt: {
transactionHash: '0xddb313978411cd3f1429f1eb61b9bbde816e3a874d765aa5588a69508d226b44',
transactionIndex: 0,
blockHash: '0xbae43abf22ca06de65a41e3e54493ad944f4b997b12a3ed407bc5f778d00a3be',
blockNumber: 6,
from: '0x3455100c0b0617afbf0f53db5e5c07366e20791b',
to: '0x645a78fe8eb3529291ba63a8e420d26c7baf61a0',
gasUsed: 45320,
cumulativeGasUsed: 45320,
contractAddress: null,
logs: [],
status: true,
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
rawLogs: []
},
logs: []
}
truffle(develop)> todo.getTasks()
[
[ 'Hello, world!', true, content: 'Hello, world!', completed: true ]
]
However, when I try to call these contract's functions from a web-app, it seems like there are some kind of communication errors with the local blockchain provided by Truffle.
Of course I've installed Metamask in my browser and I've connected it to http://127.0.0.1:9545 (as Truffle tells me to do upon executing the truffle develop command). I've also imported the private phrase provided by Truffle, so that I could access the 10 test addresses on that local network.
I've also found the contract's address and ABI in the build/contracts directory and set up a simple front end in React.
import Web3 from 'web3';
import React, { useState, useEffect } from "react";
const TODO_ABI =
[
{
"inputs": [
{
"internalType": "string",
"name": "content",
"type": "string"
}
],
"name": "addTask",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "taskId",
"type": "uint256"
}
],
"name": "changeTaskState",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "taskId",
"type": "uint256"
},
{
"internalType": "string",
"name": "content",
"type": "string"
}
],
"name": "editTaskContent",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getTasks",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "content",
"type": "string"
},
{
"internalType": "bool",
"name": "completed",
"type": "bool"
}
],
"internalType": "struct ToDo.Task[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
}
];
const TODO_ADDRESS = "0x645a78fe8eb3529291ba63a8e420d26c7baf61a0";
function ChangeTaskStateButton(props) {
return (
<button onClick={ () => props.contract.methods.changeTaskState(props.id).call() }>{ props.state }</button>
);
}
function Task(props) {
return (
<li>
{ props.content } | <ChangeTaskStateButton contract={ props.contract } id={ props.id } state={ props.completed ? "Completed" : "Pending "}></ChangeTaskStateButton>
</li>
);
}
function TasksList(props) {
let tasks = [];
const tasksData = props.tasks;
for(let i = 0; i < tasksData.length; i++) {
tasks.push(<Task id={i} content={ tasksData[i].content } completed={ tasksData[i].completed } contract={ props.contract }></Task>);
}
return (
<div>
<ul>
{ tasks }
</ul>
</div>
);
}
function TaskForm(props) {
const [content, setContent] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
props.contract.methods.addTask(content).call()
.then(() => props.setTasks(props.tasks.concat({content: content, completed: false})));
};
const handleChange = (event) => {
setContent(event.target.value);
};
return(
<form onSubmit={ handleSubmit }>
<input type="text" onChange={ handleChange }></input>
<button type="submit">Submit</button>
</form>
);
}
function App() {
const [web3] = useState(new Web3(Web3.givenProvider || "http://localhost:9545"));
const [contract] = useState(new web3.eth.Contract(TODO_ABI, TODO_ADDRESS));
const [tasks, setTasks] = useState([]);
useEffect(() => {
contract.methods.getTasks().call()
.then(tasks => {
setTasks(tasks);
});
}, [contract.methods]);
return (
<div>
<TaskForm contract={contract} setTasks={setTasks} tasks={tasks}></TaskForm>
<TasksList tasks={tasks} contract={contract}></TasksList>
</div>
);
}
The call to getTasks() always returns an empty array, even if I add a task through the terminal with the same address that's currently in use on Metamask, while the call to addTask() doesn't store anything in the smart contracts's map. The call to these two functions don't cause any errors or warnings to appear in the browser's console. However, the call to changeTaskState() does cause two errors do be displayed:
inpage.js:1 MetaMask - RPC Error: Internal JSON-RPC error.
{code: -32603, message: "Internal JSON-RPC error.", data: {…}}
code: -32603
data: {message: "VM Exception while processing transaction: revert", code: -32000, data: {…}}
message: "Internal JSON-RPC error."
__proto__: Object
index.js:50 Uncaught (in promise) Error: Internal JSON-RPC error.
{
"message": "VM Exception while processing transaction: revert",
"code": -32000,
"data": {
"0x359c33ac64b2b3eb0096b40b2d225679d4212f40fc86ef938af49fcc47159f2c": {
"error": "revert",
"program_counter": 994,
"return": "0x4e487b710000000000000000000000000000000000000000000000000000000000000032"
},
"stack": "RuntimeError: VM Exception while processing transaction: revert\n at Function.RuntimeError.fromResults (C:\\Users\\gianm\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:1)\n at C:\\Users\\gianm\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\node_modules\\ganache-core\\lib\\blockchain_double.js:568:1",
"name": "RuntimeError"
}
}
at Object._fireError (index.js:50)
at sendTxCallback (index.js:540)
at cb (util.js:689)
at callbackifyOnRejected (util.js:666)
at Item.push../node_modules/process/browser.js.Item.run (browser.js:153)
at drainQueue (browser.js:123)
I've also tried to use Ganache, instead of Truffle's built-in local blockchain, and I even tried to change browser, but nothing seems to work. I've also checked whether Metamask was actually connected to the webapp and sure enough it was. What am I missing here?
There are two main ways to interact with a smart contract. A call (read-only, free) and a transaction (read-write, requires gas fees).
Your react code uses the .call() method for addTask() and changeTaskState(), which doesn't allow writing in the contract storage.
Since you're working with MetaMask, you should use the Ethereum Provider API and submit a request to MM that will ask the user to confirm the transaction.
So instead of the props.contract.methods.addTask(content).call() you can get the contents of the data field and then generate the transaction request.
const data = props.contract.methods.addTask(content).encodeABI();
ethereum.request({
method: 'eth_sendTransaction',
params: [{
from: senderAddress,
to: contractAddress,
data: data
}],
});
Note: You can set the senderAddress after connecting to MM.
Another way is to use the web3 .send() method, but this requires passing the private key of the sender to web3 (bad idea in a frontend JS app) or unlocked provider account (local providers usually have few unlocked accounts, but production ones don't).
Please help. I'm unable to match JSON parsed values to customer name using Data tables. I was able to populate table column with contact info, but parsed data is identical for both accounts in the table created by code shown. Is there a better way to loop through the data so it displays correctly.
I've seen a few examples of doing this with a simple table, but I would like to keep the sorting capability of Data Tables if possible. Any help will be greatly appreciated.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Table 01</title>
</head>
<body>
<link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<table id="tableId" class="table table-condensed responsive"></table>
</body>
<script>
var data01 = [
{
"name": "EXAMPLE Mickey",
"due": "2018-11-22T19:00:00.000Z",
"labels": [
{
"name": "Salesperson_1",
"color": "green"
}
],
"pluginData": [
{
"value": "{\"billContact\":\"Mickey Mouse\",\"billCompany\":\"MM Clubhouse\"}",
"access": "shared"
}
]
},
{
"name": "EXAMPLE Carl",
"due": "2018-11-25T19:00:00.000Z",
"labels": [
{
"name": "Salesperson_2",
"color": "yellow"
}
],
"pluginData": [
{
"value": "{\"billContact\":\"Carl Grimes\",\"billCompany\":\"Rick's Group\"}",
"access": "shared"
}
]
}
];
$('#tableId').DataTable({
data: data01,
"columns": [
{"data": "name"},
{"data": "due"},
{"data": "labels.0.name"},
{"data": "pluginData.0.value"},
{"data": function(){
for (var i=0; i < data01.length; i++){
var values = data01[i].pluginData[0].value;
var parsedVal = JSON.parse(values);
var contact = parsedVal.billContact;
return contact;
//console.log(contact);
}
}}
]
});
</script>
</html>
When you pass a function to a column, an argument is passed to that function which represents one entry of your data. So there is no need to iterate over your data by yourself, jQuery is doing that for you.
$('#tableId').DataTable({
data: data01,
"columns": [
{"data": "name"},
{"data": "due"},
{"data": "labels.0.name"},
{"data": "pluginData.0.value"},
{"data": function (row){
let values = row.pluginData[0].value;
let parsedVal = JSON.parse(values);
let contact = parsedVal.billContact;
return contact;
}}
]
});
If you do the iteration by yourself, the function will terminate at the return statement. So everytime the function is called it just see the first entry and return it and stop at that point.