Nehmen wir einen sehr einfachen Smart Contract, der eine Funktion hat, bei der Sie eine Zahl senden und das Quadrat zurückgeben. Es hat eine andere Funktion, die eine feste Zeichenfolge zurückgibt.
contract MyContract {
uint public version;
address public previousPublishedVersion;
function ping() returns (string param){
param = "pong";
}
function squareNumber(uint num) returns (uint256 numSqr) {
numSqr = (num * num);
}
}
Nun zur Bereitstellung des Vertrags, den ich verwende
myContract.new({
data: MyContract.compiled_code,
gas: gasNeeded * ethConfig.gas_factor,
from: ethConfig.primary_address
}, (err, myContract) => {
if(!err) {
if(!myContract.address) {
console.log('contract trasnaction hash ' + myContract.transactionHash)
} else {
console.log('contract address ' + myContract.address)
resolve({
primary_address: ethConfig.primary_address,
contract_address: myContract.address,
gas_estimate: gasNeeded
})
}
} else {
reject(err)
}
});
Dies löst zwei Rückrufe aus, einen mit dem Transaktions-Hash und einen mit der Adresse, sobald sie abgebaut wurde. Diese Methode ist jedoch nicht für sendTransaction
. Ich habe gelesen, dass die Verwendung getTransactionReceipt
oder Überprüfung von Blocknummern eine gute Möglichkeit ist, um zu überprüfen, ob die Transaktion abgebaut wurde oder nicht.
myContract.ping.call(null, (err, data) => {
if (err) {
reject(err)
} else {
resolve({
primary_address: ethConfig.primary_address,
returnValue: data
})
}
})
Aber zum Quadrieren der Zahl verwende ich
myContract.squareNumber.estimateGas(10, (err, gasNeeded) => {
if (err) reject(err)
myContract.squareNumber.sendTransaction(
10,
{
gas: gasNeeded * config.ethConfig.gas_factor,
from: config.ethConfig.primary_address
}, (err, data) => {
if (err) reject(err)
resolve({
primary_address: config.ethConfig.primary_address,
numSquare : data
})
})
})
Nun, für eine call
Funktion kann ich die Daten direkt abrufen, ohne dass Mining durchgeführt werden muss, aber die Dokumente sagen, dass der von sendTransaction() zurückgegebene Wert der Hash davon ist, und dann müssen wir verwenden getTransactionReceipt()
, um tatsächlich zu bestätigen, wann der Block abgebaut wurde .
Meine Frage ist einfach, wie genau strukturiere ich meinen web3js
Code, um den zurückgegebenen Wert (10*10) von der solidity-Funktion zu erhalten squareNumber()
.
Ich habe alle oben gezeigten APIs in Versprechen verpackt, aber diesen Teil einfach übersprungen, da er lang ist und in keiner Weise mit web3js zusammenhängt.
Nach dem Hinzufügen eines Ereignisses wie SquareComputed
(siehe So erhalten Sie Werte, die von nicht konstanten Transaktionsfunktionen zurückgegeben werden? ) und des Beispiels für web3.js- Vertragsereignisse
var event = myContractInstance.MyEvent({valueA: 23} [, additionalFilterObject])
// watch for changes
event.watch(function(error, result){
if (!error)
console.log(result);
});
dies würde zu Code führen wie:
var event = myContractInstance.SquareComputed({});
// watch for changes
event.watch(function(error, result){
if (!error)
resolve({
primary_address: config.ethConfig.primary_address,
numSquare : result // need to access the properties of result to obtain the actual square
})
event.stopWatching();
});
Machen Sie vorher das oben Gesagte myContractInstance.squareNumber.sendTransaction
. Das resolve({numSquare:...})
im Originalcode sollte watch
wie oben in das Innere verschoben werden.
Andere web3.js-APIs wie z. B. web3.eth.filter
können ebenfalls verwendet werden (siehe Wie rufe ich die Voted-Ereignisse von The DAO ab ).
Diese Frage lautet: "Wie genau strukturiere ich meinen web3js-Code, um den zurückgegebenen Wert (10*10) von der Solidity-Funktion squareNumber() zu erhalten", ansonsten siehe Was ist der Unterschied zwischen einer Transaktion und einem Aufruf? .
Mit Web3.js v1.0.0 können Sie das Ereignis erhalten, das von Ihrer SquareComputed-Transaktion ausgelöst wird ( sendTransation()
äquivalente Methode ist jetzt send()
), siehe send() return
in der Dokumentation
Varun Agarwal
event.watch
wird die Verwendung problematisch, da alle ausgelösten Ereignisprotokolle erfasst werden.eth
event[i] = myContractInstance[i].SquareComputed({})
. Eine andere Möglichkeit besteht darin, einen indizierten Parameter für das Ereignis wie userId zu haben und danach zu filtern wieevent = myContractInstance.MyEvent({userId: 23}
(Muss möglicherweise eine separate Frage stellen, wenn wir zu abstrakt werden und spezifisch sein müssen.)