Interact with solidity contract using JavaScript - javascript

I started working on a simple project and I don't have much experience in blockchain. I want to connect to a Solidity contract using JavaScript. Connecting with the contract and getting the address works, but when i'm calling getInfo I'm getting this error:
Uncaught (in promise) 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.
Below is the code.
The contract:
pragma solidity ^0.8.0;
contract NFT {
uint256 id;
string name;
string description;
address owner;
constructor(uint256 _id, string memory _name, string memory _description) public {
id = _id;
name = _name;
description = _description;
owner = msg.sender;
}
function transfer(address newOwner) public {
require(msg.sender == owner, "Only the owner can transfer the NFT");
owner = newOwner;
}
function getInfo() public view returns (uint256, string memory, string memory, address) {
return (id, name, description, owner);
}
function getAddress() external view returns(address) {
return address(this);
}
}
And the JavaScript code:
const connectContract = async () => {
const contractAbi = [
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transfer",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_id",
"type": "uint256"
},
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_description",
"type": "string"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "getAddress",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getInfo",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "string",
"name": "",
"type": "string"
},
{
"internalType": "string",
"name": "",
"type": "string"
},
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]; // the ABI of the NFT contract
const contractAddress =[contract address]; // the address of the deployed NFT contract
window.web3 = await new Web3(window.ethereum);
window.contract = await new window.web3.eth.Contract(contractAbi, contractAddress);
document.getElementById("contractArea").innerHTML = "Connected to Contract";
web3.eth.getAccounts(console.log);
}
const getInfo = async () => {
const info = await contract.methods.getInfo().call().then(console.log);
}
async function main() {
const contract = new web3.eth.Contract(contractAbi, contractAddress);
// Transfer the NFT to a new owner
const newOwner = [owner];
const receipt = await contract.methods.transfer(newOwner).send({ from: web3.eth.defaultAccount });
console.log(receipt);
}
Is this the correct way to connect with a smart contract? What am I missing?

Related

Get ERC20 Token balance returns Cannot read properties of undefined (reading 'balanceOf')

I am trying to get the balance of tokens on a specified wallet address but i keep getting the error Cannot read properties of undefined (reading 'balanceOf') I have done several searches and cant seem to find what's wrong with my code as seen below
async function getBalanceofToken() {
const tokenAbi = [
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
];
const web3 = new Web3('https://mainnet.infura.io/v3/XXXXXXXXXX');
const tokenAddress = '0x467bccd9d29f223bce8043b84e8c8b282827790f';
const WalletAddress = '0x3be417a3cf3381e979093c79f2ed4aec3545fa55';
const contract = web3.eth.contract(tokenAbi, tokenAddress);
try {
const WalletTokenBalance = await contract.methods.balanceOf(WalletAddress).call(function(err, res) {
if (err) {
console.log("An error occured", err);
return
}
console.log("The balance is: ",res)
})
var decimals = await contract.methods.decimals().call();
var adjustedBalance = WalletTokenBalance * 10 ** -decimals;
console.log(adjustedBalance);
}
catch (err) {
document.getElementById("outputerr").innerHTML = err;
}
}
I am currently using this version of web3.js https://unpkg.com/#metamask/legacy-web3#latest/dist/metamask.web3.min.js
Please what am i doing wrong and how do i fix this?
Regards.

Error: invalid string value (arg="_name", coderType="string", value=null)

I am trying to parse a persons information from a UI to a smart contract, the problem I seem to be having is the example I followed parses int's and I'm not sure what to change in order to parse strings across? This code is just trying to get the player name and birthday.
Here is my smart contract code:
pragma solidity 0.6.6;
contract Athlete_contract4{
string public playerName;
string public playerBirthday;
string public playerAddress;
string public playerNationality;
function setData(string memory _name, string memory _birthday) public{
playerName = _name;
playerBirthday = _birthday;
// playerAddress = _address;
// playerNationality = _nationality;
}
}
And my code for my UI:
<html>
<body>
<div>
<h4>Athlete Details</h4>
<input type="text" id="name" placeholder="Name">
<br><br>
<input type="date" id="birthday">
<br><br>
<input type="text" id="address" placeholder="Address">
<br><br>
<input type="text" id="nationality" placeholder="Nationality">
<br><br>
<button id='submit'>Submit</button>
</div>
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js#1.0.0-beta.36/dist/web3.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" crossorigin="anonymous"></script>
<script>
var contract;
$(document).ready(function () {
web3 = new Web3(window.web3.currentProvider);
var address = "0xD9190906543d08725f5d523A1CEd83Fcde4f1F28";
var abi = [
{
"inputs": [],
"name": "playerAddress",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "playerBirthday",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "playerName",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "playerNationality",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_birthday",
"type": "string"
}
],
"name": "setData",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
];
contract = new web3.eth.Contract(abi, address);
})
$('#submit').click(function()
{
var name = 0;
name = parseInt($('#name').val());
var birthday = 0;
birthday = parseInt($('#birthday').val());
web3.eth.getAccounts().then(function(accounts){
var acc = accounts[0];
return contract.methods.setData(name, birthday).send({from: acc});
}).then(function(tx)
{
console.log(tx);
}).catch(function(tx)
{
console.log(tx);
})
});
</script>
</body>
</html>
When I deploy this to a local host using http-server in visual studio code I get this error:
Is there a parse string code that has to be used? Or have I just missed a line of code somewhere?
In your submit function - you are casting your "name" and "birthday" fields to an integer (where solidity is expecting a string).
Try removing the parseInt function.
name = parseInt($('#name').val());
to
name = $('#name').val();

Parse ABI file to get the method signature

I have a simple Ethereum contract
pragma solidity ^0.4.0;
contract SampleContract {
uint storageData;
function set(uint x) {
storageData = x;
}
function get() constant returns (uint) {
return storageData;
}
}
I have complied it and here's the ABI JSON:
[
{
"constant": false,
"inputs": [
{
"name": "x",
"type": "uint256"
}
],
"name": "set",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "get",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
I want to parse this JSON file in such a way using node JS that it returns me the method signatures i.e. method names, their inputs/outputs with the type.
I thought to parse this JSON using JSON.parse.
While I am able to get the method names in an array using .map method , i am not able to get the input values and types as these are returned as [Object].

json-schema-faker including extra url in results

I'm setting up json-schema-faker to create some mock data for a project.
When I generate the data it includes an extra bit with the following as the last item in the generated data.
"id": "http://json-schema.org/schema#"
Here is my schema (from a file named 'mockDataSchema.js'):
exports.schema = {
"type": "object",
"properties": {
"users": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {
"type": "object",
"properties": {
"id": {
"type": "number",
"unique": true,
"minimum": 1
},
"firstName": {
"type": "string",
"faker": "name.firstName"
},
"lastName": {
"type": "string",
"faker": "name.lastName"
},
"email": {
"type": "string",
"faker": "internet.email"
}
},
"required": ["id", "firstName", "lastName", "email"]
}
}
},
"required": ["users"]
}
The code to generate the data ('generate-mock-data.js'):
var jsf = require('json-schema-faker')
var schema = require('./mockDataSchema')
var fs = require('fs')
var chalk = require('chalk')
const json = JSON.stringify(jsf(schema))
console.log(json)
fs.writeFile('./src/api/db.json', json, function(err) {
if (err) {
return console.log(chalk.red(err))
} else {
console.log(chalk.green('Mock data generated.'))
}
})
Add the data that is returned:
{
"schema": {
"users": [
{ "id": 25582343, "firstName": "Brycen", "lastName": "Dickens", "email": "Angelica_Jakubowski#hotmail.com" },
{ "id": 39817508, "firstName": "Marisa", "lastName": "Terry", "email": "Arlo.Hermann0#yahoo.com" }
]
},
"id": "http://json-schema.org/schema#"
}
I've been unable to determine why it includes the "id": "http://json-schema.org/schema#"
I would like to get rid of that line. I'll be using this with 'json-server' to provide a mock api and it chokes on that line.
Figured this out.
exports.schema = {
was causing jscon-schema-faker to interpret '.schema' as part of the schema.
Changed to
module.exports = {
and the trailing schema link wnet away.

Unable to access my contract function with web3.eth.contract

//Contract build .json to js obj
import { abi } from './contract.js'
//Init web3
import { getWeb3 } from './getWeb3'
// Import are working fine.
export const getTokenContract = () => (
new Promise((resolve, reject) => {
getWeb3.then(web3 => { //Get web3
var contract = web3.eth.contract(abi) //Instance contract with json abi
var instance = contract.at("0x918daf9d0bd5c927ca8f1c5776e7c0c200be0fc23994dbe34dd9c9669c6a900d") //Get adress of the contract
console.log(contract)
resolve(instance)
})
})
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.1/react-dom.min.js"></script>
I try to access my smart contract functions inside the instance. While I console.log, the function present in the abi are correctly display.
No functions is avalaible from the adress.
For exemple:
instance.getFidelity...
getFidelity isn't defined so crash.
testrpc launched.
truffle compile
truffle migrate (success deployed at 0x918...)
Abi json:
// Token Interface
export const Token = [
{
"contractName": "MetaCoin",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getFidelity",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "receiver",
"type": "address"
},
{
"name": "amount",
"type": "uint256"
}
],
"name": "sendCoin",
"outputs": [
{
"name": "sufficient",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "redeemFidelity",
"outputs": [
{
"name": "sufficient",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "addr",
"type": "address"
}
],
"name": "getBalance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"inputs": [],
"payable": false,
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
}
],
"name": "Fidelity",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
}
]
}
];
ERC20 Smart Contract
pragma solidity ^0.4.4;
import "./Ownable.sol";
contract MetaCoin is Ownable {
mapping (address => uint) balances;
mapping (address => uint) fidelity;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Fidelity(address indexed _from);
function MetaCoin() {
balances[tx.origin] = 10000;
fidelity[tx.origin] = 100;
}
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
if (receiver == owner && amount > 10) {
fidelity[msg.sender] += 1;
}
Transfer(msg.sender, receiver, amount);
return true;
}
function redeemFidelity() returns (bool sufficient) {
if (fidelity[msg.sender] < 10) return false;
fidelity[msg.sender] -= 10;
Fidelity(msg.sender);
return true;
}
function getBalance(address addr) returns(uint) {
return balances[addr];
}
function getFidelity(address addr) returns(uint) {
return fidelity[addr];
}
}

Categories

Resources