calling a smart contract functons as a a string in javascript web3 - javascript

Here is my question: Instead of calling a smart contract function like this
//assuming the name of the contract function is called "balanceOf"
contract.methods.balanceOf("0x", "0x").call(err, balance) => {
console.log({err, balance});
})
i want to know if it is possible to call like this:
var funcName = "balanceOf";
var parameter = "0x, 0x";
contract.methods.funcName(parameter).call(err, balance) => {
console.log({err, balance}];
})
Thank You.

The objects in javascript can be accessed like an array by using the keys as indexes. So in your case it would be:
var funcName = "balanceOf";
var parameter = "0x, 0x";
contract.methods[funcName]("0x", "0x").call(err, balance) => {
console.log({err, balance}];
})
But the way you passing the parameter is not going to work like that. You are just passing a string as a parameter. Think of it like passing parameters to any other function.

Related

Is it possible to provide default parameters with rest operator

I was learning from an ES6 essential course and trying default parameters and rest operator for functions.
I have defined a function sayHi as below with default parameters and then rest operator which does not gives the desired output.
const sayHi = (greetings, ...names) => {
names.forEach(item => {
console.log(`${greetings} ${item}`);
});
}
sayHi('Hi', 'Ahsan', 'Awais', 'Haseeb');
The above snippet works as desired. but when I tried to set a default parameter value for greetings variable it works but gives unwanted result i.e. value 'Ahsan' is taken by the greetings variable.
const sayHi = (greetings = ' Hi', ...names) => {
names.forEach(item => {
console.log(`${greetings} ${item}`);
});
}
sayHi('Ahsan', 'Awais', 'Haseeb');
Is there a way I can set default parameters in function like above before rest operator?
You can't, no. The rest parameter only picks up the "rest" of the parameters not consumed by any previous formal parameters, so greeting will always receive the first argument's value.
Separately, since both the names and the greeting have the same type, you can't provide a default at all if you want to accept the names that way.
A couple of options for you:
A curried function
You could have a function that accepts the greeting and returns a function that uses it with whatever you pass it:
const greet = (greeting = "Hi") => (...names) => {
for (const name of names) {
console.log(`${greeting} ${name}`);
}
};
greet()("Ahsan", "Awais", "Haseeb");
greet("Hello")("Ahsan", "Awais", "Haseeb");
Note how we called that:
greet()("Ahsan", "Awais", "Haseeb");
greet() creates the function using the default greeting. Then we call that function by using ("Ahsan", "Awais", "Haseeb") on it. greet("Hello") creates a function that uses the greeting "Hello" (and then we call it).
(I also took the liberty of using for..of rather than forEach, but it's a matter of style.)
Take names as an array
Another option is to accept the names as an array. That way, we can tell inside the function whether we got a greeting or not:
const greet = (greeting, names) => {
if (Array.isArray(greeting)) {
names = greeting;
greeting = "Hi";
}
for (const name of names) {
console.log(`${greeting} ${name}`);
}
};
greet(["Ahsan", "Awais", "Haseeb"]);
greet("Hello", ["Ahsan", "Awais", "Haseeb"]);
you just have to pass undefined in the 1st parameter to skip optional arg
think of it like this greetings = typeof greetings != 'undefined' ? greetings : "hi" which means that check the value of greetings and if it's undefined (not provided) use the default value
edit: here is the code snippet
const sayHi = (greetings = ' Hi', ...names) => {
names.forEach(item => {
console.log(`${greetings} ${item}`);
});
}
sayHi(undefined, 'Ahsan', 'Awais', 'Haseeb');

Pass a string as a parameter in JS

This is pretty simple, I'm trying to insert a value that has a string as a parameter.
Let's give an example:
const stringName = "User".
and my goal is to activate a function that gonna be called like that
User.find();
I tried the follows without success: stringName.find() but didn't worked and also [stringName].find()
Why I want to do that: I receive a param that is a string, and I want to search with this param in my DB so the real query gonna be something like that: param.findAll({where....})
I'm sure that there is a simple solution like the examples above. hope for help.
You can store User in an object, and then access it with the string.
const myObjects = {
User: User,
// Post: Post, ...
}
const stringName = "User"
myObjects[stringName].find('foo')
You probably could do something like this:
let fncName(clsName) {
if(window[clsName]) {
let cls = new window[clsName]();
cls.find();
}
}
This however requires all classes that you are calling to have a function named find. Probably better to do a switch on the passed in string and go from there.
let fncName(clsName) {
switch(clsName) {
case 'User':
User.find();
default:
...
}
}
You can't simply execute .find() on a string unless you define the find() method in string prototype.
If your goal is to execute some methods of an object, and that object's name you are getting as a string.
If that object is available in your current context:
const param = "User";
this[param].find()
If object is not available in current context:
let objectMap = {
"user": USER
};
let param = "user";
objectMap[param].find();

Global array not updating when I call a Firebase function

I have a few lines of code which retrieve data from a Firebase realtime database. I want them to grab a name from objects stored there and then use this to pick a random name. do this by first retrieving all objects and storing the name values in an array. I then retrieve the number of total objects in that database and use the random function to generate a random number, and then pick that value from the array. I am not sure why this is not behaving as it should. Here is the code I am using:
const dbRefObject = firebase.database().ref().child('names');
dbRefObject.on('value', gotData);
var names = [];
function gotData(data) {
dbRefObject.once('value', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var childData = childSnapshot.val().names;
names.push(childData);
})
namesUpdated(names);
}
)
return names;
}
function namesUpdated(names) {
randomNumber = randomNumberGenerator();
console.log(randomNumber);
console.log(names[randomNumber]);
return names[randomNumber];
}
function randomNumberGenerator() {
dbRefObject.on('value', (snap) => {
var totalRecord = snap.numChildren();
return Math.floor(Math.random() * totalRecord);
});
}
I am not sure why this is not working as when I print out the names array in gotData function it works fine. However when I try to use this in namesUpdated it says the value is undefined. Similarly, the randomNumberGenerator works fine as it returns a value in that function but does not work when I use it in namesUpdated. That function looks fine to me so I am not sure why it isnt working. Thanks in advance for any help.
There are several problems in your code. I'll try to identify the main ones and I would suggest you update your question with a new version.
First, IMHO, you should move the declaration of the names array IN the gotData() function:
function gotData(data) {
var names = [];
Secondly, in the randomNumberGenerator() function you should use once() instead of on(). You should also do return dbRefObject.once('value', (snap) => {...}).
Then, in namesUpdated(), you should note that the call to randomNumberGenerator() returns a Promise, therefore you cannot do var randomNumber = randomNumberGenerator();. You should either use then() or use async/await.
Finally, by separating your code in different functions, you are fetching the database several times, without any added value.

How would I programmatically call an object method? Like MyObject.XVariable(//some function)

I have an object, that takes input from an API call to fill it up.
let MyDog = {
Name: 'Dog',
}
let arrayFunctions;
fetchDogsFunctions(dogAPIUrl).then(res => {
//results is an array that has a list of functions the dog has, like //getStats(), or walkDog()
arrayFunctions = res;
})
Now I want to map through the array results and call the function on my dog like...
arrayFunctions.map(item => {
await MyDog.item(//Params)
})
How can I do this??
Where MyDog is set up from a file, and then depending on the array functions, for each function it programmatically fills in the call to the new function like MyDog.item where item is a variable in an array called "Walk()"
I assumed how your data might have structured. Pls take a look below and you might get the idea of how to call functions dynamically using "await"
const MyDog = {
funA(a) { return Promise.resolve('Function A called with parameter ' + a) }
, funB(b) { return Promise.resolve('Function B called with parameter ' + b) }
}
const arrayFunctions = ['funA', 'funB']
Promise.all(arrayFunctions.map(async (item, i) =>
await MyDog[item](++i))
)
.then(console.log)
I can't see any property name "item" in your MyDog Object
The answer is to do :
MyDog[item]()
within the loop.
I was asking the correct syntax to perform this operation

Lodash map with function: how to pass to function another parameter?

I'm using lodash map in this way
const newCollection = _.map(
responseJson.OldCollection,
AddDetailsToSingleItems
);
having
function AddDetailsToSingleItems (item ) {
...
}
I ask you, please, what's the right syntax to pass a parameter to this function.
I'd like to have
function AddDetailsToSingleItems (item, myNewParam ) {
...
}
(note the myNewParam).
I don't kow how to tell to loadsh map to pass every single item to my function and to pass one more param when calling AddDetailsToSingleItems
You haven't explained where myNewParam is coming from, but I assume you have that data somewhere.
Lodash map (just like normal JavaScript map) accepts a function as its second argument to be run on all elements of the supplied list. You can just pass an anonymous function:
_.map(
responseJson.OldCollection,
item => AddDetailsToSingleItems(item, myNewParam)
);
You can create a function that knows the value of myNewParam, but only accepts the item parameter like this:
var myNewParam = 'param_value';
var AddDetailsFn = function(m) {
return function(item) {
return AddDetailsToSingleItems(item, m);
};
};
const newCollection = _.map(
responseJson.OldCollection,
AddDetailsFn(myNewParam)
);
This way, _.map only sees a function that takes a single parameter. The AddDetailsFn returns a function that takes a single parameter, but already has the value of myNewParam captured. You can also be more succinct with:
const newCollection = _.map(
responseJson.OldCollection,
function(item) { return AddDetailsToSingleItems(item, myNewParam); }
);

Categories