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(){ }
Related
The common process we follow today to get the data on client script:
OnChange client script:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var user = g_form.getValue('u_user');
//Call script include
var ga = new GlideAjax('global.sampleUtils'); //Scriptinclude
ga.addParam('sysparm_name', 'getUserDetails'); //Method
ga.addParam('userId',user); //Parameters
ga.getXMLAnswer(getResponse);
function getResponse(response){
console.log(response);
var res = JSON.parse(response);
console.log(res);
g_form.setValue('u_phone',res.mobile_phone);
g_form.setValue('u_email',res.email);
}
}
Script include:
var sampleUtils = Class.create();
sampleUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getUserDetails: function(){ //Function
var userId = this.getParameter('userId'); //Params
obj = {};
var grSysUser = new GlideRecord('sys_user');
if (grSysUser.get(userId)) {
obj.mobile_phone = grSysUser.getValue('mobile_phone');
obj.email = grSysUser.getValue('email');
}
gs.addInfoMessage(obj+JSON.stringify(obj));
return JSON.stringify(obj);
},
type: 'sampleUtils'
});
DEMO Link: https://youtu.be/nNUsfglmj_M
As an alternative to glideAjax you can EfficientGlideRecord
new EfficientGlideRecord('sys_user')
.addQuery('sys_id', newValue) //On Change client script, we will get sys_id of user in newValue variable
.addField('mobile_phone', true) //Get display value
.query(function (egrSysUser) {
if(egrSysUser.next()) {
g_form.setValue('phone', egrSysUser.getDisplayValue('mobile_phone'));
}
});
What is EfficientGlideRecord?
EfficientGlideRecord is the best alternate way to use GlideAjax.
It is a client-side API class from which you can perform asynchronous client-side GlideRecord-style queries while maximizing performance.
Benefits:
Low code configuration with Huge performance improvement.
No need to worry about security loopholes, because it enforces ACLs.
No more concerns about creating new client callable script includes and maintaining
the logic there.
Dependencies:
To use the EfficientGlideRecord we need to commit the attached update-set or find the latest version from the given link https://github.com/thisnameissoclever/ServiceNow-EfficientGlideRecord/releases.
Add the package to Portal record -> JS Includes.
and that's it, and you are good at using the EfficientGlideRecord syntax.
To know more about EfficientGlideRecord, Refer the below link(s):
https://snprotips.com/efficientgliderecord
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)));
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;
I'm trying to return window.performance object from the web page back to casper's scope with the following code but I'm getting null. Can someone explain why?
performance = casper.evaluate ->
return window.performance
#echo performance
PhantomJS 1.x doesn't implement window.performance, so you can't use it.
PhantomJS 2.0.0 implements it, but it doesn't implement the window.performance.toJSON() function. The problem with PhantomJS is that you have to access this information through evaluate(), but it has the following limitation:
Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.
Closures, functions, DOM nodes, etc. will not work!
You will have to find your own way of serializing this in the page context and passing it to the outside (JavaScript):
var performance = casper.evaluate(function(){
var t = window.performance.timing;
var n = window.performance.navigation;
return {
timing: {
connectStart: t.connectStart,
connectEnd: t.connectEnd,
...
},
navigation: {
type: n.type,
redirectCount: n.redirectCount
},
...
};
});
or look for a deep copy algorithm that produces a serializable object (from here):
var perf = casper.evaluate(function(){
function cloneObject(obj) {
var clone = {};
for(var i in obj) {
if(typeof(obj[i])=="object" && obj[i] != null)
clone[i] = cloneObject(obj[i]);
else
clone[i] = obj[i];
}
return clone;
}
return cloneObject(window.performance);
});
console.log(JSON.stringify(perf, undefined, 4));
I have a situation which has to be simple to solve, I would guess. Surely people are using Backbone Relational with CoffeeScript out there...
Here's a model I have:
class MyCompany.Models.Establishment extends Backbone.RelationalModel
defaults:
name: null
class MyCompany.Collections.EstablishmentsCollection extends Backbone.Collection
model: MyCompany.Models.Establishment
url: '/establishments'
I haven't even added any relationships yet, just extended RelationalModel. Now through the console when I issue a destroy on an instance of the model it successfully destroys the model on the server, but when complete it fails with the trace:
Uncaught TypeError: Object #<Establishment> has no method 'getCollection'
_.extend.unregister
Backbone.Events.trigger
Backbone.RelationalModel.Backbone.Model.extend.trigger
_.extend.destroy.options.success
jQuery.extend._Deferred.deferred.resolveWith
done
jQuery.ajaxTransport.send.callback
It's dying in line 235 of backbone-relational.js 0.4.0 because "this" is the model, I guess, instead of whatever it's supposed to be, and the model doesn't have a method "getCollection".
Any ideas what I'm doing wrong, or should I report a bug? For reference, here's the Javascript coffee generates:
(function() {
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor;
child.__super__ = parent.prototype;
return child;
};
MyCompany.Models.Establishment = (function() {
__extends(Establishment, Backbone.RelationalModel);
function Establishment() {
Establishment.__super__.constructor.apply(this, arguments);
}
Establishment.prototype.defaults = {
name: null
};
return Establishment;
})();
MyCompany.Collections.EstablishmentsCollection = (function() {
__extends(EstablishmentsCollection, Backbone.Collection);
function EstablishmentsCollection() {
EstablishmentsCollection.__super__.constructor.apply(this, arguments);
}
EstablishmentsCollection.prototype.model = MyCompany.Models.Establishment;
EstablishmentsCollection.prototype.url = '/establishments';
return EstablishmentsCollection;
})();
}).call(this);
You need to update the underlying Backbone.js version. Here's why:
Your error comes from this having the wrong value when unregister is called. unregister is called in response to an event bound from register:
model.bind( 'destroy', this.unregister, this );
That third argument sets the context. But that feature was only added as recently as Backbone 0.5.2, as the changelog shows.