Solidity Contract Calls issue - aion

I created a dummy solidity contract (https://learn.aion.network/docs/deploy-a-smart-contract-using-web3) and deployed it.The issue occurs when I try to make a call using aion-web3.
const contract = require('aion-web3-eth-contract');
contract.setProvider("https://aion.api.nodesmith.io/v1/mastery/jsonrpc?apiKey=*");
const Web3 = require('aion-web3');
const web3 = new Web3(new Web3.providers.HttpProvider("https://aion.api.nodesmith.io/v1/mastery/jsonrpc?apiKey=*"));
const account = web3.eth.accounts.privateKeyToAccount("****");
let myContract = new contract([...], "0xa0e1166A455a0d75CFC2bfa32D7f76f0e1852c106b981Acf59EDE327CFD36811");
// console.log("C a",myContract.options.address);
myContract.methods.getCount().call({from: account.address}, function (error, result) {
if (error){
console.log("err=>", error)
} else {
console.log("res=>", result)
}
});
I expect 0 because it the first call but its throwing the below error:
TypeError: myContract.methods.getCount is not a function

It looks like the way you're trying to call the function isn't quite correct. Instead of creating a myContract object, try just putting the contract address into a transaction object, and then calling that:
let transactionCall = {
from: account.address,
to: "0xa0bf00624C2E81de745A826052D635f5c35515F0B55df6E4b1BAaCe785C124B9",
gas: 54321,
data: contractInst.methods.getCount().encodeABI()
};
web3.eth.call(transactionCall).then((res) => console.log(web3.utils.hexToNumber(res)));
Also, make sure that your account has coins in it. There's a faucet you can use here: https://faucets.blockxlabs.com/aion
Also, welcome to StackOverflow!

Try use the following to create a contract instance:
let myContract = new web3.eth.Contract(["compile contract abi info"])
And
web3.eth.call({to:YourContractAddress, data:myContract.methods.getCount().encodeABI()}).then((res) => console.log(web3.utils.hexToNumber(res)));

Related

Cannot destructure property `interface` of 'undefined' or 'null'

When I do npm run test I get back this error :
Cannot destructure property interface of 'undefined' or 'null'
I've been trying to fix this error for a cupple of days with no result. I've seen in some other posts that it's usually related with compile.js file... I think its all ok so i cannot find the issue.
I'll paste all my code (nottice I'm triyng to work with the very last version of solidity, in order to learn new functionalities... maybe there's my error...)
THANKYOU!!!
My compile.js:
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const lotteryPath = path.resolve(__dirname, 'contracts', 'Lottery.sol');
const source = fs.readFileSync(lotteryPath, 'utf8');
module.exports = solc.compile(source, 1).contracts[':Lottery'];
.sol:
pragma solidity ^0.5.1;
contract Lottery {
address public manager;
address payable [] public players;
constructor() public payable {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint){
return uint(keccak256(abi.encode(block.difficulty, now, players)));
}
function getPlayers() public view returns (address payable[] memory){
return players;
}
function pickWinner() public payable restricted{
uint index = random() % players.length;
address(players[index]).transfer(address(this).balance);
players = new address payable[](0);
}
modifier restricted(){
require(msg.sender==manager);
_;
}
}
TEST:
const assert = require ('assert');
const ganache = require ('ganache-cli');
const Web3 = require ('web3');
const provider = ganache.provider();
const web3 = new Web3(provider);
const { interface, bytecode } = require ('../compile');
let lottery;
let accounts;
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
lottery = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode })
.send({ from: accounts[0], gas: '1000000' });
});
describe('Lottery Contract', () =>{
it('deploys a contract', () =>{
assert.ok(lottery.options.address);
});
});
Heres how I fixed it:
I had the similar error when running 'npm run test'. What seemed to work for me is uninstalling your current version of solc
and running npm install --save solc#0.4.25
make the following amends in your contract and the test will run just fine.
pragma solidity ^0.4.17; //make change here
contract Lottery{
address public manager;
address[] public players;
function Lottery()public{
manager = msg.sender;
} // use this instead of using constructor
function enter() public payable{
require(msg.value>.1 ether);
players.push(msg.sender);
}
function random() private view returns(uint){
return uint(keccak256(block.difficulty, now, players));
} // make change here
function pickWinner()public{
require(msg.sender==manager);
uint index = random() % players.length;
players[index].transfer(address(this).balance);
players = new address[](0);
}
function getPlayers()public view returns(address[]){
return players;
}
}
you might have made this contract amends to make it compilable in remix but V#0.4.17 does not support this.
the same issue occur when i am trying to running a test
you can try two things:
1:try lower version of solidity. maybe V0.4.17 help you
npm uninstall solc //to uninstall existing solc version
npm i --save solc#0.4.17 //to re-install solc with lower version
2: try console.log() statement in compile.js file to check that contract is compiling or not
console.log(solc.compile(source, 1));
if the output is undefined than maybe there is some issue with your contract.
I had the exact same issue. The problem comes with the solidity compiler you are using. In my particular case I was trying 0.5.4 and for some reason I experienced the same error.
"The contract compilation is different in solc 0.5.0 and above"
one possible solution is using a lower solc version: like 0.4.25 (in my case this works fine).
The problem surges when the compilation takes place, the operation returns null, so there isn't any output and that's why you get an error telling you about the null variable.
use this in Lottery.sol :
pragma solidity >=0.4.21 <0.7.0;
contract Lottery {
address public manager;
address[] public players;
constructor() public {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > 0.01 ether);
players.push(msg.sender);
}
function random() private view returns (uint) {
return uint(keccak256(abi.encodePacked(block.difficulty,now,players)));
}
function pickWinner() public restricted {
uint index = random() % players.length;
address(players[index]).transfer(address(this).balance);
players = new address[](0);
}
modifier restricted() {
require(msg.sender == manager);
_;
}
function getPlayers()public view returns(address[]){
return players;
}
}
For anyone having this issue still, make sure to console.log(solc.compile(source, 1))
Issue for me was that I named a contract something different then what I was passing as an input to .contracts[] array.
Make sure name you're passing to .contracts[] equals the name of a contract class, you can get it by consol logging the solc.compile(source, 1).
The problem is not in the js file it's in the .sol file
Make sure that you are using solidity and solc version 0.4.17
Make sure that you are not using any functions of the new solidity version in your old version like constructor
It can be a basic syntax error in your compile.js file or .sol file
Try changing the constructor function to
function Lottery() public(){ }

How to query firestore with the Dialogflow inline editor to get information

I am using the inline editor within Dialogflow with the aim of making queries to the database I have created within Firestore.
In short, the user requests a list of courses, I'd like the chatbot to then grab that information form the db and display that back to the user.
Below I have tried to create a function that will do this, I want to take the user input, say "Art Courses" and have my db return those results.
So far, I have created a function that is triggered when the intent is matched, like so;
function getCourses(agent){
let courseRequest = agent.parameters.courseRequest;
if (getCourses){
console.log('Here is the list you requested for ${getCourses}' + parameters.courseRequest);
return admin.firestore().collection('Course_Information').doc.where('CoureTypes').get();
}
}
Are there any notable things I need to add to my function to perform what I wish to achieve?
Thank you.
UPDATE
This code deploys fine, but when I communicate with my bot and trigger the CourseEnquiry intent, cloud Functions shows this error:
admin.collection is not a function
Whilst this seems self explanatory I can't make sure of what it means, I thought declaring const admin = require('firebase-admin');enables me to use admin.collection
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const admin = require('firebase-admin');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function getDate(agent){
var today = new Date();
}
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function test(agent){
agent.add("The test is successful");
}
function getCourses(agent){
// Get the database collection and document
const getCourseDoc = admin.collection('Course_Information').doc('Course_Types');
return getCourseDoc.get()
.then(doc => {
if (!doc.exists) {
agent.add('No data found in the database!');
} else {
agent.add(doc.data().entry);
}
return Promise.resolve('Here is the information you wanted');
}).catch(() => {
agent.add('Error reading entry from the Firestore database.');
});
}
function getSubmissionDateSep(agent){
agent.add('Your next submission date is for coursework 1 is');
}
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Test_Test', test);
intentMap.set('CourseEnquiry', getCourses);
intentMap.set('Submission_Dates - sept', getSubmissionDateSep);
agent.handleRequest(intentMap);
});
UPDATE #2
Hey guys, still not got anywhere with this, I have tried adding:
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
According to this document but I get this error when deploying:
The deployment of your Cloud Function failed:
Function load error: Code in file index.js can't be loaded.
Is there a syntax error in your code?
Detailed stack trace: Error: Firebase config variables are not available. Please use the latest version of the Firebase CLI to deploy this function.
You don't show how you're responding to the user with your results, but you'll want to make sure you handle that as part of the then() clause in a Promise. Since the get() in the firestore collection returns a Promise, and you are returning it from your function, you need to make sure that the calling function treats it as a Promise, has a then() clause, and sends back the result as part of something inside this clause.

Unable to Save ParseObject with User ACL in Cloud Code

I have an issue saving changes to an object from a Cloud Code function.
I have a collection called Character and one record inside it.
This Character record has an ACL with Public Read, and Private Write Access by a specific ParseUser (6MwfSLdAxd).
In Unity, I authenticated the user and I then call the Cloud Code function as follows:
ParseCloud.CallFunctionAsync<Character>("startBattle", null).ContinueWith(t =>
{
Debug.Log("I got here...");
Debug.Log(t.Result.ClassName);
});
In my Cloud Code function, I grab the first character in the collection (ignoring checking if it belongs to this user, because at the moment there is only one and it DOES belong to this user - there's only one user too).
var Character = Parse.Object.extend("Character");
Parse.Cloud.define("startBattle", function (request, response) {
var user = request.user;
if (user == null)
{
return response.error("You must login before you can battle!");
}
var characterQuery = new Parse.Query(Character);
characterQuery.first()
.then(
function (character) {
character.set("name", "Cloud Code sucka");
character.save().then(function(character) {
return response.success(character);
});
},
function (error) {
return response.error("You must create a character before you can battle! " + error);
}
)
});
However, I simply cannot save any changes to this character. All the documentation and forum posts I've found suggest that if you call a Cloud Code function when authenticated then that function should have the same level permissions as the user calling it.
The only time this code works is if I set the ACL of the character to Public Write.
Does anyone have any ideas why this wouldn't be working?
Note: Worth noting that I can see in the server logs that the Cloud Code function IS being called by the authenticated user 6MwfSLdAxd as I get this error (if I add a response.error call):
error: Failed running cloud function startBattle for user 6MwfSLdAxd with:
Input: {}
Error: {"code":141,"message":"Messed up: [object Object]"} functionName=startBattle, code=141, message=Messed up: [object Object], , user=6MwfSLdAxd
error: Error generating response. ParseError { code: 141, message: 'Messed up: [object Object]' } code=141, message=Messed up: [object Object]
[object Object]
[object Object]
After some extensive searching I've now found the solution to this.
For anyone else encountering the same issues, you should be aware that whilst Parse.com used to run Cloud Code functions in the context of the user that called them (afaik), self-hosted Parse Servers do not.
In order to call queries or saves in the context of a user you must pass their session token as shown below. I hope this saves someone the hours of confusion I went through!
var MyObject = Parse.Object.extend("MyObject");
Parse.Cloud.define("myCloudFunction", function (request, response) {
var user = request.user;
var sessionToken = user.getSessionToken();
var query = new Parse.Query(MyObject)
.find({ sessionToken: sessionToken })
.then(
function (object) {
object.set("someKey", "someValue");
return object.save(null, { sessionToken: sessionToken });
}
)
.then(
function (object) {
return response.success(object);
},
function (error) {
return response.error(error.message);
}
);
});
For further context see:
https://github.com/ParsePlatform/parse-server/wiki/Compatibility-with-Hosted-Parse#cloud-code

Not able to encrypt a string with a public key in Protractor

I am trying call the encrypt function mentioned below:
var encryptor = require("./jsencrypt.js");
this.encrypt = function () {
var key="LxVtiqZV6g2D493gDBfG0BfV6sAhteG6hOCAu48qO00Z99OpiaIG5vZxVtiqZV8C7bpwIDAQAB";
encryptor = new JSEncrypt();
encryptor.setPublicKey(key);
var newString = encryptor.encrypt('Password');
console.log("Encrypted password =",newString);
}
Initially I was getting Reference Error for undefined JSEncrypt.
So I downoaded jsencrypt.js file and added var encryptor = require("./jsencrypt.js");at the begining. Now I am getting following error:
Message:
ReferenceError: navigator is not defined
Stacktrace:
ReferenceError: navigator is not defined
at e:\Praveen Data\Projects\ECP\CentralRegistryUI\TestScripts\Utils\jsencrypt.js:73:13
at Object.<anonymous> (e:\Praveen Data\Projects\ECP\CentralRegistryUI\TestScripts\Utils\jsencrypt.js:4342:3)
at require (module.js:385:17)
Tried using windows.navigator in jsencrypt.js, but didn't work.
Protractor tests are not run in browser environment but in node.js, because of that navigator object is not available there. JSEncrypt relies on it to work on the client side across different browsers and versions.
It's referenced in many places in the JSEncrypt code so my best bet would be to either switch to a server side encryption library that would work for you or if not possible mock a global navigator json object with all expected properties/methods as if it was a Chrome browser - node.js runs on chrome's js engine so should work fine.
One of my colleague helped me with the solution.
So here I have a function for encryption:
this.initializeEncryptedPassword = () => {
//console.log("before calling encrypt... ");
browser.executeScript(() => {
//console.log("Starting to return encryptor...");
return window.loginEncryptor.encrypt(window.loginPassword);
}).then((encryptedPassword) => {
this.encryptedPassword = encryptedPassword;
});
//console.log("after calling encrypt...");
}
This function is being called by:
export default class Encryptor {
constructor($window, $http) {
'ngInject';
this.encryptor = new $window.JSEncrypt();
//Need to use HTTP here instead of resource since the resource does not return plain text.
//Getting Public Key by hitting a rest uri.
$http({method: "GET", url: "/xyz/authenticate"}).success((item) => {
this.encryptor.setPublicKey(item);
//set the current encryptor on the window so that testing can use it
$window.loginEncryptor = this.encryptor;
});
}
encryptPassword(credentials) {
credentials.password = this.encryptor.encrypt(credentials.password);
}
}
Hope this help others.
before require('jsencrypt') you can write first:
const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
const { window } = jsdom;
global.window = window;
global.document = window.document;
global.navigator ={userAgent: 'node.js'};
const { JSEncrypt } = require('jsencrypt')
You can mock by doing the following:
global.navigator = { appName: 'protractor' };
global.window = {};
const JSEncrypt = require('JSEncrypt').default;

Asynchronous Request to Facebook API with Redux

I am using Redux and trying to make a call to Facebook API with their JS SDK. I've only ever used promises with Redux and so since the method FB.getLoginStatus just returns a simple JS object, I'm not sure how to ensure that the payload doesn't return undefined.
With redux-promise, you add it to the applyMiddleware(ReduxPromise)... and then it ensures nothing is returned until the promise resolves. But I don't know how to do that here.
I've also used async/await functions with React Native without an issue, but I tried using them here and for some reason the code still returns the payload, before the asynchronous request (await ...) is finished. So I tried working with redux-await, but couldn't get it to work.
export function getLoginStatus() {
var res = FB.getLoginStatus(function(res) {
console.log(res);
});
console.log("res ", res);
return {
type: GET_LOGIN_STATUS,
payload: res
}
}
Hm, things can get a little tricky as I've not used redux-promise. And I can't tell exactly what else you have tried. But this would be my first shot:
async function _getLoginStatus() {
var payload = new Promise( (resolve, fail) => {
FB.getLoginStatus((res)=>resolve(res));
});
return {
type: GET_LOGIN_STATUS,
payload: payload
}
}
// Last time I exported an async function I needed this HYMMV
export let getLoginStatus = _getLoginStatus;
And then elsewhere in the code:
import {getLoginStatus} from 'whatever.js';
var payloadResult = await getLoginStatus();