I am trying to connect web3js in the javascript section of my html to my ganache-cli nodejs server
ganache deployment script:
const ganache = require("ganache-cli");
const Web3 = require("web3");
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require("./compile");
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({
data: bytecode,
arguments: ["test"],
})
.send({ from: accounts[0], gas: "1000000" });
console.log(`Contract address: ${result.options.address}`);
};
var server = ganache.server();
server.listen(8545, function (err, blockchain) {
console.log(server);
console.log(" live at port 8545");
});
deploy();
my frontend html/js file
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
} else {
web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
web3.eth.defaultAccount = web3.eth.accounts[0];
var info = new web3.eth.Contract(
JSON.parse(interface), '0xeD9a9f326F38223a6599309F7201562DfB177997');
console.log(info.methods.GetInfo("test").call());
}
But I get the following error:
index.js:297 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.
solidty code:
pragma solidity ^0.4.17;
pragma experimental ABIEncoderV2;
contract DVA {
struct Info {
// uint Age;
// bool AgeRestriction;
string DO_Num;
string date;
string time;
string status;
string otherstatus;
string imagehash;
string imagename;
}
mapping (string => Info[]) AllInfo;
function SetInfo(string _DO, string _date, string _time, string _status, string _otherstatus, string _imagehash, string _imagename) public {
Info memory info = Info(_DO,_date,_time,_status,_otherstatus,_imagehash,_imagename);
AllInfo[_DO].push(info);
}
function GetInfo(string _DO) public view returns (string memory) {
// return (AllInfo[_DO].status,AllInfo[_DO].time);
return "hi";
}
}
The code above is the contract code.
The weird thing is, I can call SetInfo but not GetInfo. I have ensured the contract address is valid, and that the ABI is correct as well. In fact, the ABI is retrieved directly upon each compilation of the solidty code as well.
Related
Hi I'm new to blockchain, truffle and Solidity and I've been stuck on this problem for quite long. I want to get all token balances given a wallet address and the token contract addresses using a contract, but I keep encountering
Error: Returned error: VM Exception while processing transaction: revert
whenever I test my contract.
Here's the code of my contract in Solidity:
pragma solidity ^0.8.17;
import {IERC20} from './IERC20.sol';
contract UtilityContract {
function getBalances(address walletAddress, address[] memory tokenAddresses) public view returns (address[] memory, uint[] memory) {
uint len = tokenAddresses.length;
uint[] memory balances = new uint256[](len);
for (uint i=0; i<len; i++) {
balances[i] = IERC20(tokenAddresses[i]).balanceOf(walletAddress);
}
return (tokenAddresses, balances);
}
}
and here's my test code:
const ADDRESS = "0xF977814e90dA44bFA03b6295A0616a897441aceC"; // some wallet address with token balance
const TOKENS = [ // token contract addresses
"0x111111111117dC0aa78b770fA6A738034120C302",
"0xC943c5320B9c18C153d1e2d12cC3074bebfb31A2",
];
const UtilityContract = artifacts.require('UtilityContract.sol');
contract('UtilityContract', ()=> {
it('getBalances', async ()=> {
const utilityContract = await UtilityContract.new();
const output = await utilityContract.getBalances(ADDRESS, TOKENS);
console.log(output);
});
});
Here's a screenshot of the error:
I imported the IERC20 interface to use the balanceOf function but for some reason it does not work.
Please try this line into your code..
address() convert your wallet string to a valid wallet address format.
IERC20(tokenAddresses[i]).balanceOf(address(walletAddress));
I'm doing transactions with Contract on Avalanche test network. I am simply minting an NFT in my Contract. I'm implementing this in Node.js as an API. Normally my codes are working. However, sometimes I get an error like this and I couldn't figure out why. Can you help me?
message: {
code: -32000,
message: 'nonce too low: address 0x190cc0978615a474092676aB740F486b7f528A5F current nonce (491) > tx nonce (490) -- Reason given: Custom error (could not decode).',
reason: 'Custom error (could not decode)'
}
Here are the parts I made with Mint:
On Contracts...
function mint(address minter, string memory uri) public returns (uint256) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
idToOwner[newItemId] = minter;
_safeMint(minter, newItemId);
_setTokenURI(newItemId, uri);
emit Mint(minter, uri, newItemId);
return newItemId;
}
On Nodejs API...
const mintMetaData = async (_id, mintURL, res) => {
const _instance = await hyliContract.at(process.env.CONTRACT_NFT_ADDRESS);
try {
const result = await _instance.mint(provider.getAddress(), mintURL, { from: provider.getAddress() });
...
I'm trying to connect a NodeJs server to a solidity contract thats been migrated to a local blockchain and then call the methods on this class via javascript. However, the code returns an error stating that getGreeting() is not defined.
I'm very new Solidity and JavaScript (background in C and Java) so I feel like I'm overlooking something really simple?
My question is how to get it to work and find the method and return "Hello, World!" to the terminal?
My development environment is:
Truffle v5.1.10 (core: 5.1.10)
Solidity - 0.4.25 (solc-js)
Node v12.14.1
Web3.js v1.2.1
Below is the code I'm working on:
// import our compiled JSON
const contractJSON = require("./build/contracts/Hello.json");
const contract = require("#truffle/contract");
const Web3 = require('web3');
// create instance of ganache-cli provider
const web3 = new Web3("http://localhost:9545");
var Hello = contract(contractJSON);
Hello.setProvider(web3);
// if contract is deployed return instance of it and store in app variable
let app = Hello.deployed().then((instance) =>{
return instance;
}).catch(function(error) {
return error;
});
// call a method on our contract via javascript
app.getGreeting().then(() => {
console.log(app);
});
For context the Solidity contract is as follows:
pragma solidity >=0.4.0 <0.7.0;
contract Hello {
string greeting;
constructor() public {
greeting = "Hello, World!";
}
function getGreeting() public view returns (string memory) {
return greeting;
}
function setGreeting(string memory _greeting) public {
greeting = _greeting;
}
}
For those of you who view this in the future the issue was that I imported the provider incorrectly according to the #truffle/contract documentation here. Also, forgot to fulfill the second promise. Therefore the answer to this solution as of the time of writing is as follows:
const provider = new Web3.providers.HttpProvider("http://localhost:9545");
let Hello = contract(contractJSON);
Hello.setProvider(provider);
Hello.deployed().then((instance) => {
deployed = instance;
return instance.getGreeting();
}).then((result) => {
console.log(result);
}).catch((error) => {
console.log(error);
});
Many thanks to #blex for the assistance.
Your are calling the function "getGreeting()" on the Promise object and not on the contract instance.
// import our compiled JSON
const contractJSON = require("./build/contracts/Hello.json");
const contract = require("#truffle/contract");
const Web3 = require('web3');
// create instance of ganache-cli provider
const web3 = new Web3("http://localhost:9545");
var Hello = contract(contractJSON);
Hello.setProvider(web3);
(async () => {
// Get Contract Instance
let app = await Hello.deployed();
// Call Function
const response = await app.getGreeting();
console.log(response);
})()
I am trying to implement a very simple dialogflow agent integration with nodejs.
Here is what I did so far
I followed the code from Intent detection
I added the service account private key file .json to my server.
I added the environment variable GOOGLE_APPLICATION_CREDENTIALS with the path to my .json private key file.
Here is the code I am trying to run right now:
require('dotenv').config()
const projectId = 'gg-chatbot-216808';
const sessionId = 'quickstart-session-id';
const query = 'hello';
const languageCode = 'en-US';
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient();
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// This prints the private key path correctly.
console.log(process.env.GOOGLE_APPLICATION_CREDENTIALS);
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});
Then I get this error in the console when I run this file
Auth error:Error: invalid_user: Robot is disabled.
ERROR: { Error: 14 UNAVAILABLE: Getting metadata from plugin failed with error: invalid_user: Robot is disabled.
at Object.exports.createStatusError (/var/www/html/google_auth/node_modules/grpc/src/common.js:87:15)
at Object.onReceiveStatus (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:1188:28)
at InterceptingListener._callNext (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:564:42)
at InterceptingListener.onReceiveStatus (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:614:8)
at callback (/var/www/html/google_auth/node_modules/grpc/src/client_interceptors.js:841:24)
code: 14,
metadata: Metadata { _internal_repr: {} },
details: 'Getting metadata from plugin failed with error: invalid_user: Robot is disabled.' }
i also faced a similar issue for my angular bot.
What i did was, instead of using using the google_credentials from the json file, i created an object with private_key,client_email {these values can be taken from the service account private key file .json}, and passed the object while setting up the session client.
var config = {
credentials: {
private_key: "YOUR_PRIVATE_KEY",
client_email: "YOUR_CLIENT_EMAIL"
}
}
const sessionClient = new dialogflow.SessionsClient(config);
note: do copy the full private_key string from .json. It will start as "-----BEGIN PRIVATE KEY-----\n......" .
Also, in GCP go to the project->IAM then try setting role for the service as DIALOGLOW API ADMIN. Check if this works.
If this has not been resolved yet , the solution is to provide "fileKey" inside sessionClient.
const sessionClient = new dialogflow.SessionsClient({
fileKey:" path of your credentials.json file"
});
or
let filePath = process.env.GOOGLE_APPLICATION_CREDENTIALS ="Location of credentials file".
const sessionClient = new dialogflow.SessionsClient({
fileKey:filePath
});
this will even work if there is no system env variable is set as GOOGLE_APPLICATION_CREDENTIALS.
Hope this is helpful.
I am confused about how I should be executing a contract's method using the web3 1.0 library.
This code works (so long as I manually unlock the account first):
var contract = new web3.eth.Contract(contractJson, contractAddress);
contract.methods
.transfer("0x0e0479bC23a96F6d701D003c5F004Bb0f28e773C", 1000)
.send({
from: "0x2EBd0A4729129b45b23aAd4656b98026cf67650A"
})
.on('confirmation', (confirmationNumber, receipt) => {
io.emit('confirmation', confirmationNumber);
});
I get this error (if I don't unlock manually first):
Returned error: authentication needed: password or unlock
The above code is an API endpoint in node.js, so I want it to unlock or authenticate programmatically.
There is no method in web3.js 1.0 to unlock the account.
I also don't think this is necessary (at least that's what I am confused about). Since I am managing accounts, I know what the private key is.
I am thinking the transaction needs to be signed with the private key?? Is this correct? Is this effectively the same thing as "unlocking the account"?
I tried doing this:
var contract = new web3.eth.Contract(contractJson, contractAddress);
var tx = {
from: "...{fromAddress -- address that has the private key below}",
to: "...",
value: ...
};
var signed = web3.eth.accounts.signTransaction(tx,
"...{privateKey}");
console.log(signed);
var promise = web3.eth.sendSignedTransaction(signed);
I get this error:
Returned error: The method net_version does not exist/is not available
What is the easiest way to authenticate and submit a transaction?
Ideally, I want to use the first approach in my code sample, as it is the cleanest.
This code allows me to sign a transaction server-side (node.js) using the privateKey from the account I created (using web3.eth.accounts.create()), and send the signed transaction to the network without having to unlock the account.
I am using Geth 1.7.1
var contract = new web3.eth.Contract(contractJson, contractAddress);
var transfer = contract.methods.transfer("0x...", 490);
var encodedABI = transfer.encodeABI();
var tx = {
from: "0x...",
to: contractAddress,
gas: 2000000,
data: encodedABI
};
web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
var tran = web3.eth.sendSignedTransaction(signed.rawTransaction);
tran.on('confirmation', (confirmationNumber, receipt) => {
console.log('confirmation: ' + confirmationNumber);
});
tran.on('transactionHash', hash => {
console.log('hash');
console.log(hash);
});
tran.on('receipt', receipt => {
console.log('reciept');
console.log(receipt);
});
tran.on('error', console.error);
});
A way to be able to call your contract methods without having to sign the transaction explicitly is this (web3js 1.0.0):
const privateKey = 'e0f3440344e4814d0dea8a65c1b9c488bab4295571c72fb879f5c29c8c861937';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
web3.eth.accounts.wallet.add(account);
web3.eth.defaultAccount = account.address;
// ...
contract = new web3.eth.Contract(JSON_INTERFACE, address);
contract.methods.myMethod(myParam1, myParam2)
.send({
from: this.web3.eth.defaultAccount,
gas: myConfig.gas,
gasPrice: myConfig.gasPrice
})
Here's a complete example of how to sign a transaction without a local wallet account. Especially useful if you are using infura for the transaction. This was written for
'use strict';
const Web3 = require('web3');
const wsAddress = 'wss://rinkeby.infura.io/ws';
const contractJson = '(taken from solc or remix online compiler)';
const privateKey = '0xOOOX';
const contractAddress = '0xOOOX';
const walletAddress = '0xOOOX';
const webSocketProvider = new Web3.providers.WebsocketProvider(wsAddress);
const web3 = new Web3(new Web3.providers.WebsocketProvider(webSocketProvider));
const contract = new web3.eth.Contract(
JSON.parse(contractJson),
contractAddress
);
// change this to whatever contract method you are trying to call, E.G. SimpleStore("Hello World")
const query = contract.methods.SimpleStore('Hello World');
const encodedABI = query.encodeABI();
const tx = {
from: walletAddress,
to: contractAddress,
gas: 2000000,
data: encodedABI,
};
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
console.log(account);
web3.eth.getBalance(walletAddress).then(console.log);
web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
const tran = web3.eth
.sendSignedTransaction(signed.rawTransaction)
.on('confirmation', (confirmationNumber, receipt) => {
console.log('=> confirmation: ' + confirmationNumber);
})
.on('transactionHash', hash => {
console.log('=> hash');
console.log(hash);
})
.on('receipt', receipt => {
console.log('=> reciept');
console.log(receipt);
})
.on('error', console.error);
});
Using
"web3": "1.0.0-beta.30"
This is my implementation using "#truffle/hdwallet-provider": "^2.0.3", "web3": "^1.6.1",
function getWeb3Provider() {
return new HDWalletProvider({
privateKeys: [NFT_MINTER_ACCOUNT_PRIVATE_KEY],
providerOrUrl: BSC_RPC_ENDPOINT,
});
}
const web3 = new Web3(BSC_RPC_ENDPOINT);
const contract = new web3.eth.Contract(
jsonContractABI as unknown as AbiItem[],
NFT_CONTRACT_ADDRESS
);
contract.setProvider(getWeb3Provider());
then in send methods
contract.methods.safeMint(receiverAddress, itemUri).send({
from: NFT_MINTER_ACCOUNT,
});
in call methods
contract.methods.balanceOf(address).call();