Call deployed smart contract from node.js - node.js

I have small test smart contract, which is deployed to my test network. And I want to use a server to call the function in the contract. Here is the code:
payontime.sol
pragma solidity ^0.4.0;
contract payontime{
address public remitter;
address private remittee;
uint value;
bool public start;
/*Only owner can use these function*/
modifier onlyOwner(){
if(msg.sender != remitter) throw;
_;
}
/*Initialize the owner*/
function payontime(address receiver) payable{
remitter = msg.sender;
value = msg.value;
remittee = receiver;
start = true;
if(!remittee.send(value)){
throw;
}
}
function wakeUp() public returns (string){
return "success" ;
}
function getContractAddr() public returns(address){
return this;
}
/*Get the remittee*/
function getRemitee() public returns(address){
return remittee;
}
}
I use truffle serve and a webpage to new the contract.
app.js
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import payontime_artifacts from '../../build/contracts/payontime.json'
var payontime = contract(payontime_artifacts);
window.App = {
sendCoin : function(){
var sender = web3.eth.accounts[0];
var receiver = document.getElementById('receiver').value;
var amount = parseInt(document.getElementById('amount').value);
web3.eth.getBalance(receiver,function(error,result){
if(!error){
consol.log("Before transfer: " + result );
}else{
console.log("Error: " + error);
}
});
var newContract = payontime.new(receiver,{from:sender, value:amount}).then(
function(myPay){
console.log(myPay.getContractAddr.call());
}).then(
function(){
web3.eth.getBalance(receiver,function(error,result){
if(!error){
console.log("After transfer: " + result );
}else{
console.log("Error: " + error);
}
});
});
}
}
window.addEventListener('load', function() {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
// Use Mist/MetaMask's provider
window.web3 = new Web3(web3.currentProvider);
} else {
console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
payontime.setProvider(web3.currentProvider);
});
app.js logs the address 0x1d379f2ab48ad20319e9f81cb45af415aa6f2966 , and I want to use this address to call the wakeUp() in the payontime.sol through another application index.js.
const Web3 = require('web3');
/* Connect to ethereum node */
const etherUrl = "http://localhost:8545";
const abi = [{"constant":false,"inputs":[],"name":"wakeUp","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getContractAddr","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"remitter","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getRemitee","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"receiver","type":"address"}],"payable":true,"type":"constructor"}];
let web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider(etherUrl));
/*Call the function which already deployed on ethereum network
Notice: ABI have to modifeid when the smart contract code change*/
var contractInstance = web3.eth.contract(abi).at('0x1d379f2ab48ad20319e9f81cb45af415aa6f2966');
var reply = "false";
reply = contractInstance.wakeUp.call(function(error,result){
if(error){
console.log("Error");
throw error;
}else{
return result;
}
});
console.log(reply);
But there is an error message:
BigNumber Error: new BigNumber() not a base 16 number
I found it might be caused by not fully synced. I think it have some problem when I call the function in a deployed contract. So how can I call a deployed contract from web.js?

contractInstance.wakeUp.call is calling the function as constant, but the function is not defined as constant:
function wakeUp() public returns (string){
return "success" ;
}
has to be:
function wakeUp() public constant returns (string){
return "success" ;
}
If your Solidity function doesn't change the blockchain state and is just reading data, you should define it as constant.

As well as putting your console log within the call back, you can fix the big number error with:
console.log(result.toNumber());

Related

How to use TransparentUpgradeableProxy as Transparent Proxy

I'm Solidity Newbie.
I'm learning how to implement Transparent Proxy using Openzeppelin's TransparentUpgradeableProxy contract, but am having some problems.
Step 1: I tried to deploy a simple contract MyConV0, then implemented deploy and call method, everything is fine.
// File MyConV0.sol
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract MyConV0 {
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
console.log(_symbol);
}
function symbol() public view returns (string memory) {
console.log(_symbol);
return _symbol;
}
function name() public view returns (string memory) {
console.log('Name: ');
console.log(_name);
return _name;
}
function getVersion() pure external returns(uint256) {
return 0;
}
}
Step 2: I tried to upgrade to MyConV1 to be able to Upgradable with TransparentUpgradeableProxy but failed.
// File: MyConV1
pragma solidity ^0.8.0;
import "#openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "#openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "#openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "hardhat/console.sol";
contract MyConV1 is Initializable, OwnableUpgradeable {
string private _name;
string private _symbol;
function initialize(string memory name_, string memory symbol_) initializer public {
__Ownable_init();
_name = name_;
_symbol = symbol_;
console.log(_symbol);
}
function symbol() public view returns (string memory) {
console.log('Symbol: ');
console.log(_symbol);
return _symbol;
}
function name() public view returns (string memory) {
console.log('Name: ');
console.log(_name);
return _name;
}
function getVersion() pure external returns(uint256) {
return 1;
}
}
Refer TransparentUpgradableProxy: https://docs.openzeppelin.com/contracts/4.x/api/proxy#TransparentUpgradeableProxy
// The test file in JS using ethers.js and Hardhat environment
async function main() {
let t0, t1, t2, t3, t4, v1, v2, v3, v4;
const [owner, proxyAdmin, user, other] = await ethers.getSigners();
// --- 0. Deploy MyConV0
let input0 = [ 'TotoName', 'Toto' ];
let con0 = await deploy_verify_contract("MyConV0", input0);
t0 = await con0.symbol() ;
console.log(t0); // worked -> Toto
// --- 1. Deploy MyConV1
let input1 = [ ];
let con1 = await deploy_verify_contract("MyConV1", input1);
// --- 2. get data
let abi = [ `function initialize( string name_,
string symbol_,
)` ];
let iface = new ethers.utils.Interface(abi);
let data = iface.encodeFunctionData("initialize", [ 'TotoName', 'Toto' ]);
// --- 3. deploy trans proxy
let input2 = [ con1.address, owner.address, data ];
let con2 = await deploy_verify_contract("TransparentUpgradeableProxy1", input2);
// --- 4. call proxy method
t2 = await con2.implementation();
console.log(t2); // DO NOT WORK, t2 is object tx, and do not contains the results like step 0
// --- 5. call MyConV1 contact via proxy -> ERROR: "TypeError: con2.symbol is not a function"
t3 = await con2.symbol();
console.log(t3);
}
async function deploy_verify_contract(contractName, input, lib = {}){
const _contract = await hre.ethers.getContractFactory(contractName, lib);
const contract = await _contract.deploy(...input);
await contract.deployed();
console.log( contractName + " deployed to:", contract.address );
return contract;
}
I used Hardhat's console.log function and it seems to have successfully deployed the Proxy, and sent the correct data to the MyConV1.initialize function, but don't know how to call the proxy properly. Specifically with the above code, I don't understand a few points:
Have I deployed the proxy correctly?
Why can't I get the correct return data of the proxy's implementation() function?
Why can't I call MyConV1's function through the proxy?
Hope you guys can help me how to correct the code, I have not been able to solve this problem for a few days.
You are not calling UpgradeTo() on proxy contract to set the implementation contract's address. After you have set the implementation contract in proxy you have to initialise the implementation contract via proxy contract only! not any other way or directly calling it on implementation contract (it wont work!!)

Unable to fetch private data from collection. Getting blank response

I am trying to explore private data collection and I have written the chaincode in javascript. I am passing the proper collections file while instantiating the chaincode and while invoking the chaincode I am adding the transient data in request payload which looks like this :
const proposal_request = {
chaincodeId: chaincodeId,
fcn: functionName,
args: args,
chainId: channelCode,
txId: tx_id,
transientMap : { "private" : "test data"}
};
My chaincode file looks like this :
const shim = require('fabric-shim');
const util = require('util');
var PrivateDataChaincode = class {
// Initialize the chaincode
async Init(stub) {
console.log('<================> ::Private Data Chaincode Instantion:: <=================>');
return shim.success();
}
async Invoke(stub) {
console.log('<================> ::Private Data Chaincode Invocation:: <=================>');
let ret = stub.getFunctionAndParameters();
console.info(ret);
let method = this[ret.fcn];
console.info('methodName');
console.info(method);
if (!method) {
console.error('No method of name:' + ret.fcn + ' found');
return shim.error('No method of name:' + ret.fcn + ' found. \n UNKNOWN FUNCTION INVOCATION: ' + ret.fcn);
}
console.info('\nCalling method : ' + ret.fcn);
try {
let payload = await method(stub, ret.params);
return shim.success(payload);
} catch (err) {
console.log(err);
return shim.error(err);
}
}
async createPrivateDataInCollection(stub, args) {
if (args.length != 2) {
throw new Error('Incorrect number of arguments. Expecting 2');
}
// arg[0] has the collection name
// arg[1] has the key
console.info("============= START : Create Private data ===========");
// get the transient map
let transientData = stub.getTransient();
await stub.putPrivateData(args[0], args[1], transientData.map.private.value);
console.info('============= END : Create private data ===========');
}
async queryPrivateDataInCollection(stub, args) {
console.info('============= START : Query private Data ===========');
// arg[0] has the collection name
// arg[1] has the key
// query private data with argument
let allResults = await stub.getPrivateData(args[0], args[1]);
if (!allResults) {
throw shim.error("Can't get data from state");
}
console.log(allResults);
return allResults;
}
};
shim.start(new PrivateDataChaincode());
I am storing data using the createPrivateDataInCollection method and fetching the data using queryPrivateDataInCollection. The private data is getting stored correctly when I cross checked in the couch DB. The problem I am facing is that I am getting a blank response when I am querying the private data using queryPrivateDataInCollection method on some occasions. Sometimes I am able to see the data, while sometimes I am getting a blank response. Am I missing something important?

Metamask chrome extension gives error. How do I fix this?

I got this error from metamask.
It was working fine couple of hours ago. I have tried reinstalling/ disable and re-enabling again but nothing worked.
Also,
My smart contract is fully functional (Tested in Remix Browser based IDE) and no other errors or logs are present anywhere. I also restarted Ganache and re-compiled and re-migrated my contracts with no luck.
Here is my solidity code:
pragma solidity ^0.4.18;
contract Voting {
address mainAddress;
bytes32[] candidateNames;
mapping(bytes32 => uint) candidateVotes;
mapping(bytes32 => bytes32) candidatesDetails;
function Voting() public {
mainAddress = msg.sender;
}
modifier isMainAddress {
if (msg.sender == mainAddress) {
_;
}
}
function getAllCandidates() public view returns (bytes32[]) {
return candidateNames;
}
function setCandidate(bytes32 newCandidate) isMainAddress public {
candidateNames.push(newCandidate);
}
function setVote(bytes32 candidate) public {
candidateVotes[candidate] = candidateVotes[candidate] + 1;
}
function getVote(bytes32 candidate) public view returns (uint) {
return candidateVotes[candidate];
}
function setDescrption(bytes32 candidateName, bytes32 candidatesDesc) isMainAddress public {
candidatesDetails[candidateName] = candidatesDesc;
}
function getDescription(bytes32 candidateName) public view returns (bytes32){
return candidatesDetails[candidateName];
}
}
And I am calling these functions like :
let votingContractInstance;
const contract = require('truffle-contract')
const votingContract = contract(VotingContract)
votingContract.setProvider(this.state.web3.currentProvider)
this.state.web3.eth.getAccounts((error, accounts) => {
votingContract.deployed().then((instance) => {
votingContractInstance = instance
return votingContractInstance.setVote(this.state.candidateName);
}).then((result) => {
this.setState(() => ({
allCandidates: result
}));
})
})
All of the calls are made by this way only.
I am using one of the truffle boxes (REACT box) and no logs/errors are present in console either.
Did you figure this out? Can you just call this.setState({ allcandidates: result })
Also, the result from setVote isn't anything because you don't have it return anything in the solc contract.

RFCommConnectionTrigger in Windows Universal Apps To detect Incoming Bluetooth Connection

I am working on a Windows Universal App. I Want to get the Data from a Bluetooth Device to the Windows Phone. I am Using the Concept of RFCommCommunicationTrigger for this Purpose.
Here's the code Snippet I am Using
var rfTrigger = new RfcommConnectionTrigger();
// Specify what the service ID is
rfTrigger.InboundConnection.LocalServiceId = RfcommServiceId.FromUuid(new Guid("<some_base_guid>"));
//Register RFComm trigger
var rfReg = RegisterTaskOnce(
"HWRFCommTrigger",
"BackgroundLibrary.RFBackgroundTask",
rfTrigger, null
);
SetCompletedOnce(rfReg, OnTaskCompleted);
Here the Function of RegisterTaskOnce
static private IBackgroundTaskRegistration RegisterTaskOnce(string taskName, string entryPoint, IBackgroundTrigger trigger, params IBackgroundCondition[] conditions)
{
// Validate
if (string.IsNullOrEmpty(taskName)) throw new ArgumentException("taskName");
if (string.IsNullOrEmpty(entryPoint)) throw new ArgumentException("entryPoint");
if (trigger == null) throw new ArgumentNullException("trigger");
// Look to see if the name is already registered
var existingReg = (from reg in BackgroundTaskRegistration.AllTasks
where reg.Value.Name == taskName
select reg.Value).FirstOrDefault();
Debug.WriteLine("Background task "+ taskName+" is already running in the Background");
// If already registered, just return the existing registration
if (existingReg != null)
{
return existingReg;
}
// Create the builder
var builder = new BackgroundTaskBuilder();
builder.TaskEntryPoint = entryPoint;
builder.Name = taskName;
builder.SetTrigger(trigger);
// Conditions?
if (conditions != null)
{
foreach (var condition in conditions)
{
builder.AddCondition(condition);
}
}
// Register
return builder.Register();
}
Here's the code for SetCompletedOnce this will add a Handler only once
static private void SetCompletedOnce(IBackgroundTaskRegistration reg, BackgroundTaskCompletedEventHandler handler)
{
// Validate
if (reg == null) throw new ArgumentNullException("reg");
if (handler == null) throw new ArgumentNullException("handler");
// Unsubscribe in case already subscribed
reg.Completed -= handler;
// Subscribe
reg.Completed += handler;
}
I have also Written the BackgroundLibrary.RFBackgroundTask.cs
public sealed class RFBackgroundTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
try
{
Debug.WriteLine(taskInstance.TriggerDetails.GetType());
taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
Debug.WriteLine("RFComm Task Running");
Debug.WriteLine(taskInstance.TriggerDetails.GetType().ToString());
}
catch (System.Exception e)
{
Debug.WriteLine("RFComm Task Error: {0}", e.Message);
}
deferral.Complete();
}
}
The Run Method is Invoked Every Time The Device tries to Open the Connection.
The type of the Trigger that is obtained (the type I am debugging in the run method of the RFBackgroundTask.cs) is printed as
Windows.Devices.Bluetooth.Background.RfcommConnectionTriggerDetails
But I am Unable use that because I dont have this Class in the BackgroundLibrary project.
The Documentation says that this Provides information about the Bluetooth device that caused this trigger to fire.
It has Variables like Socket,RemoteDevice etc.
I think I am Missing something very simple
Can you please help me out .
Once your background task is launched, simply cast the TriggerDetails object to an RfcommConnectionTriggerDetails object:
public sealed class RFBackgroundTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
try
{
taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
RfcommConnectionTriggerDetails details = (RfcommConnectionTriggerDetails)taskInstance.TriggerDetails;
StreamSocket = details.Socket; // Rfcomm Socket
// Access other properties...
}
catch (System.Exception e)
{
Debug.WriteLine("RFComm Task Error: {0}", e.Message);
}
deferral.Complete();
}
}

Inheritance in Node.JS

I am using node.js and programming based on express.js. I have tried to use util.inherits to implement inheritance in JavaScript. What I've tried is as follows:
//request.js
function Request() {
this.target = 'old';
console.log('Request Target: ' + this.target);
}
Request.prototype.target = undefined;
Request.prototype.process = function(callback) {
if (this.target === 'new')
return true;
return false;
}
module.exports = Request;
//create.js
function Create() {
Create.super_.call(this);
this.target = 'new';
}
util.inherits(Create, Request);
Create.prototype.process = function(callback) {
if (Create.super_.prototype.process.call(this, callback)) {
return callback({ message: "Target is 'new'" });
} else {
return callback({ message: "Target is not 'new'" });
}
}
module.exports = Create;
//main.js
var create = new (require('./create'))();
create.process(function(msg) {
console.log(msg);
});
My scenario is :
I have Request as base class and Create as child class. Request has field target that initialize old in Request constructor.
Now, I create Create class object which first call Request constructor and then initialize target field with new. When I call process function of Create, I expect to get message of target is 'new' but it returns another!
I searched similar threads for this, but all are what i tried! Can any one explain what was wrong?
Thanks in advance :)
util.inherits has really awkward super_... anyway, this should work:
Create.super_.prototype.process.call(this, callback);
But really,
var super_ = Request.prototype;
And then the syntax becomes almost convenient:
super_.process.call(this, callback);

Resources