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].
Related
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?
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.
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();
Our school receives data from a source during a sync.
I'm familiar with JavaScript but would like to ask for a litle help before I make a change.
Here is the scenario: The source sending the information to us has the default value as "tobedeleted". We need this to be translated to "inactivate". and then put into our DB.
What's being sent I think is simply ignored because it doesn't match any of our enum values.
My idea is to get help writing: if the get value = "tobedeleted" then translate it to "inactivate" and then update our database.
{
"path": "/v1/courses/{course_id}/enrollments/{id}",
"description": "Conclude, deactivate, or delete an enrollment. If the +task+ argument isn't given, the enrollment\nwill be concluded.",
"operations": [
{
"method": "DELETE",
"summary": "Conclude, deactivate, or delete an enrollment",
"notes": "Conclude, deactivate, or delete an enrollment. If the +task+ argument isn't given, the enrollment\nwill be concluded.",
"nickname": "conclude_deactivate_or_delete_enrollment",
"parameters": [
{
"paramType": "path",
"name": "course_id",
"description": "ID",
"type": "string",
"format": null,
"required": true,
"deprecated": false
},
{
"paramType": "path",
"name": "id",
"description": "ID",
"type": "string",
"format": null,
"required": true,
"deprecated": false
},
{
"paramType": "query",
"name": "task",
"description": "The action to take on the enrollment.\nWhen inactive, a user will still appear in the course roster to admins, but be unable to participate.\n(\"inactivate\" and \"deactivate\" are equivalent tasks)",
"type": "string",
"format": null,
"required": false,
"deprecated": false,
"enum": [
"conclude",
"delete",
"inactivate",
"deactivate"
]
}
],
"response_fields": [
],
"deprecated": false,
"deprecation_description": "",
"type": "Enrollment"
}
]
},
Thank you in advance!
Lets assign the JSON to a variable named data. Then you can do
data.operations.map((operation) => {
if (operation.method === 'DELETE') {
operation.parameters.map((param, queryIndex) => {
if (param.paramType === 'query') {
param.enum.map((item, enumIndex) => {
if (item === 'tobedeleted') {
operation.parameters[queryIndex].enum[enumIndex] = 'inactivate';
//item = 'inactivate';
}
});
}
});
}
return operation;
});
Note: This may not be an optimized code but it does the work.
//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];
}
}