Here's what works for me using getData to populate a transaction data: field
The contract is an array getter setter:
pragma solidity ^0.4.0;
contract SetGetArray {
uint[] someNumbers;
function getArray() public constant returns (uint[]) {
return someNumbers;
}
function setArray(uint[] setNumbers) public {
someNumbers = setNumbers;
}
}
// After Deploying (in Kovan)
txHash:0x1cc74caab5c64c493a67cf8e3a8de656ba0db1d6f59c634e3c68e27a41afe7bf
// Successfully deployed Contract with address:
// 0x1e1300614978efe2bf5c4b532daef69441314205
The gotcha is that if you are changing state your array needs to be in storage and modified with a transaction...
This is a verbose ( includes gas estimation) but hopefully clear way to set it in web3, I am using Node.js and Parity:
console.log('Setting up...');
const solc = require ('solc');
const Web3 = require ('web3');
console.log('Reading abi');
const contractABI = require("./SetGetArray.json");
console.log('Connecting');
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
console.log('Creating contract instance');
var contract = web3.eth.contract(contractABI).at("0x1e1300614978efe2bf5c4b532daef69441314205");
var receiverAddress = '0x1e1300614978efe2bf5c4b532daef69441314205';
var setNumbers = [5,2,4,1];
var setData = contract.setArray.getData(setNumbers);
// console.log(setData);
var gasEstimate = web3.eth.estimateGas({
from: web3.eth.coinbase,
to: receiverAddress,
data: setData
});
var gasPrice = web3.eth.gasPrice;
console.log('gas Price: ' + gasPrice);
console.log('Estimated Transaction gas: ' + gasEstimate);
console.log('unlocking Coinbase account');
const password = "yourPassword";
try {
web3.personal.unlockAccount(web3.eth.coinbase, password);
} catch(e) {
console.log(e);
return;
}
console.log ('sending Transaction to the contract');
const transaction = {
from: web3.eth.coinbase,
to:receiverAddress,
value: '0x00',
gas: gasEstimate + 1,
gasPrice: gasPrice + 1,
data: setData
}
web3.eth.sendTransaction( transaction, function(err, txHash) {
if (err != null) {
console.error("Error while sending transaction: " + err);
}
else{
console.log("Transaction Sent here's you txHash: " + txHash);
}
});
And getting the Array value:
console.log('Setting up...');
const solc = require ('solc');
const Web3 = require ('web3');
console.log('Reading abi');
const contractABI = require("./SetGetArray.json");
console.log('Connecting');
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
console.log('Creating contract instance');
var contract = web3.eth.contract(contractABI).at("0x1e1300614978efe2bf5c4b532daef69441314205");
console.log ('calling contract');
var getArray = contract.getArray();
console.log('Get Array : ' + getArray);
// Get Array : 5,2,4,1
// getArray[2] = 4
You could also just call a contract's function with parameters, but the function needs to be pure, which is not enforced yet( i.e. your compiler might not compile the contract).
function passArray(uint[] otherNumbers) pure public returns (uint[]) {
return otherNumbers;
}
and calling it :
var otherNumbers = [4,3,2,1];
var passArray = contract.passArray(otherNumbers);
console.log('Pass Array : ' + passArray);
// Pass Array : 4,3,2,1
The above works with compilers 0.4.17 and above (just update solc) , below you are back to calling it with a transaction that costs gas...
function passArray(uint[] otherNumbers) public returns (uint[]) {
return otherNumbers;
}
Check both in remix the one on top doesn't incur in gas, while the one in the bottom does.
I was wondering about this exact behaviour the other day but didn't have time to investigate it. The short answer is that Javascript itself doesn't allow for function overloading, so when the contract object is being built from the ABI, functions of the same name get overwritten.
...
The following 'homosignet' (?) contract contains three overloaded functions of the same name, the same JS argument type typeof "0x123" == "string"
but with different ABI argument types, string
, bytes
, address
contract homosignet {
function f(string s) constant returns (string){ return "was string";}
function f(bytes b) constant returns (string){ return "was bytes";}
function f(address a) constant returns (string){return "was address";}
}
We can see in Remix that the three are unique ABI functions having unique function signatures of:
fc68521a f(address)
d45754f8 f(bytes)
91e145ef f(string)
And that all three functions return the expected strings of "was string", "was bytes" and "was address".
However, if I hook the contract using web3.js and call the functions of the resulting JS object from the console, as in the following testcode and case:
<html> <head><script src="web3.js"></script>
<script>
web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
var homosignetContract = web3.eth.contract([{"constant":true,"inputs":[{"name":"s","type":"string"}],"name":"f","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"b","type":"bytes"}],"name":"f","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}]);
k = homosignetContract.at("0x3b3d3de7a3271f0f6bea0b6b99e6f26a64dd3617");
</script></head></html>
> k.f(123)
"was string"
> k.f(0x123)
"was string"
> k.f("0x123")
"was string"
> k.f("test")
"was string"
The return values are all the same and in this case, all arguments are being parsed as type string
, even the number literal.
This makes sense because Javascript does not allow function overloading and when you look at the contract object, indeed only one k.f()
exists.
So it seems that calling overloaded functions requires a low level call with pre-encoded call object :
web3.eth.call(callObject [, defaultBlock] [, callback])
Which looks something like this when calling f(bytes b)
. Then you need to decode the raw return data.
web3.eth.call({to:"0x7db0be9069df82feac77f810b26a6d8011b89a8c", data:"d45754f80000000000000000000000000000000000000000000000000000000000000123"})
Best Answer
If you what to pass a name as string or any other value then you can use jquery like this
When some clicks the button you get the name or number on which the person has clicked. After that you pass this variable (which is string in this case) as the parameter to the function.