ethereum-web3-plus
Advanced tools
Comparing version 0.1.2 to 0.1.3
274
index.js
console.log("Intitializing ethereum-web3-plus"); | ||
console.log("Intitializing ethereum-web3-plus - Local dev"); | ||
var Web3 = require('web3'); | ||
//######################################################################################### | ||
// ETHEREUM FUNCTIONS | ||
// Created by G. de Cadoudal - march 2017 | ||
// adds functions and objects to the web3 instance by modifying Web3 prototype | ||
//######################################################################################### | ||
var DeployedLib ={ | ||
MapString:"0x48f59e9fbce7880a11acd90dc2f99b28accc47f6", | ||
MapAddress:"0xdb3d0da48c1962f5e31abd9f9904160729da9358", | ||
MapAddressWithProps:"0x87614301dd92d49447b926941940c85533b7e147"}; | ||
// assumes that the web3 variable is initialized outside this package and connected to a node. | ||
if(!module.parent) {console.log("use require() to load this package"); return; } | ||
//console.log("loading web3"); | ||
var Web3 = module.parent.require('web3'); | ||
//console.log("loaded web3 on parent", Web3); | ||
//Web3.prototype.testNewMethod = function() {} | ||
var DictContract= {}; | ||
var LibToken={}; | ||
var compiled ; | ||
exports.compileSol = function(source) { | ||
var eth=web3.eth; | ||
var SolidityCompiler = function(web3) { | ||
this.web3 = web3; // instance of the connection to the geth node | ||
this.DeployedLib = {} ; // a map of library name to their deployed address | ||
this.DictContract= {} ; // a map with the result of the compilation and what is needed for the initialization | ||
this.LibToken={}; // a map of the library name to their token in the compiled class to do the replacing | ||
this.MissingLibs={}; // a map with the tokens found in the code after replacement | ||
} | ||
SolidityCompiler.prototype.compile = function(source) { | ||
var eth=this.web3.eth; | ||
var filled = "________________________________________"; // used for lib token creation below | ||
compiled = eth.compile.solidity('import "'+source+'";'); | ||
var compiled = eth.compile.solidity('import "'+source+'";'); | ||
for( var obj in compiled ) { | ||
var name=obj.split(":")[1]; | ||
DictContract[name] = { | ||
abi: compiled[obj].info.abiDefinition, | ||
code: compiled[obj].code, | ||
this.DictContract[name] = { | ||
abi: compiled[obj].info.abiDefinition, | ||
code: compiled[obj].code, | ||
contract: eth.contract(compiled[obj].info.abiDefinition) }; | ||
LibToken[name]= ("__"+obj.substr(0,36)+filled).substr(0,40); // 40 is the size of the target address | ||
this.LibToken[name]= ("__"+obj.substr(0,36)+filled).substr(0,40); // 40 is the size of the target address | ||
} | ||
for(name in DictContract) | ||
for(lib in DeployedLib) { | ||
var rex=RegExp(LibToken[lib], "g"); // match "__<source of the lib cut at 36 char>__" | ||
DictContract[name].code= DictContract[name].code.replace(rex, DeployedLib[lib].replace("0x","")); | ||
// replacing the lib totens with their address in all compiled contracts | ||
var reLib = /_+.*?_+/g; | ||
for(name in this.DictContract) { | ||
for(lib in this.DeployedLib) { | ||
var rex=RegExp(this.LibToken[lib], "g"); // match "__<source of the lib cut at 36 char>__" | ||
this.DictContract[name].code=this.DictContract[name].code.replace(rex, this.DeployedLib[lib].replace("0x","")); | ||
} | ||
for(e in DictContract) console.log("Compiled", e, "code length:", DictContract[e].code.length); | ||
var m=reLib.exec(this.DictContract[name].code); | ||
while(m) { | ||
if(!this.MissingLibs[m[0]]) this.MissingLibs[m[0]]={count:0, contracts:[]}; | ||
this.MissingLibs[m[0]].count++; | ||
if(this.MissingLibs[m[0]].contracts.indexOf(name)<0) | ||
this.MissingLibs[m[0]].contracts.push(name); | ||
m = reLib.exec(m["input"]); // find next | ||
} | ||
} | ||
} | ||
SolidityCompiler.prototype.displaySizes = function() { | ||
for(e in this.DictContract) | ||
console.log("Compiled", e, "code length:", this.DictContract[e].code.length-2); // remove length of "0x" | ||
} | ||
SolidityCompiler.prototype.displayMissingLibs = function() { | ||
for(l in this.MissingLibs) | ||
console.log("Missing library:", l, "in", this.MissingLibs[l].contracts.join(", ")); | ||
} | ||
SolidityCompiler.prototype.addDeployedLib = function(lib, address) { | ||
if(!lib) return false; | ||
if(!address) return delete this.DeployedLib[lib]; | ||
this.DeployedLib[lib]=address; | ||
return true; | ||
} | ||
SolidityCompiler.prototype.displayDeployedLibs = function() { | ||
for(l in this.DeployedLib) | ||
console.log("Library", l, ":",this.DeployedLib[l]); | ||
} | ||
SolidityCompiler.prototype.getCode = function(contract) { | ||
if(!contract) return null; | ||
if(!this.DictContract[contract]) return null; | ||
return this.DictContract[contract].code; | ||
} | ||
SolidityCompiler.prototype.getContract = function(contract) { | ||
if(!contract) return null; | ||
if(!this.DictContract[contract]) return null; | ||
return this.DictContract[contract].contract; | ||
} | ||
Web3.prototype.solidityCompiler = function() { // here this is the Web3 instance | ||
this.solidityCompiler = new SolidityCompiler(this); | ||
return this.solidityCompiler; | ||
} | ||
// should be called with | ||
// 1: contract name | ||
// 2..N: the contract constructor parameters | ||
// returns the txHash to be watched with waitFor | ||
Web3.prototype.newInstanceTx = function(){ | ||
var args=Array.prototype.slice.call(arguments); | ||
var name=args.shift(); // extract the name and leave the rest | ||
if(typeof this.solidityCompiler !== 'object') return null; // the compiler has not been created | ||
var c = this.solidityCompiler.getContract(name); | ||
if(!c) return null; | ||
// add the ethereum attributes | ||
args.push({ data:this.solidityCompiler.getCode(name), gas:this.eth.getBlock('latest').gasLimit }); | ||
//console.log("args for new", args); | ||
// call the new function. there is no callback so the return value is the TxHash | ||
var tx= c.new.apply(c, args); | ||
return tx.transactionHash; | ||
} | ||
Web3.prototype.instanceAt = function(name, address) { | ||
if(typeof this.solidityCompiler !== 'object') return null; // the compiler has not been created | ||
var c = this.solidityCompiler.getContract(name); | ||
if(!c) return null; | ||
return c.at(address); | ||
} | ||
var isFunction = function (object) { | ||
return typeof object === 'function'; | ||
}; | ||
var isObject = function (object) { | ||
return typeof object === 'object'; | ||
}; | ||
var extractCallback = function (args) { | ||
if (isFunction(args[args.length - 1])) { | ||
return args.pop(); // modify the args array! | ||
} | ||
}; | ||
var extractOptions = function (args) { | ||
var options = { // set the default | ||
canonicalAfter:0, | ||
dropAfter:99999999 } | ||
if (isObject(args[args.length - 1])) { | ||
var opt = args.pop(); // modify the args array! | ||
if( opt.canonicalAfter ) options.canonicalAfter=opt.canonicalAfter; | ||
if( options.dropAfter ) options.dropAfter=opt.dropAfter; | ||
} | ||
return options; | ||
}; | ||
var BlockWatcher = function(web3, bindEnvironment) { | ||
var self=this; | ||
this.web3 = web3 | ||
this.tx_wait={}; // dictionary txHash => {gas: <requested gas>, args: [p1, p2], cb:<callback>} | ||
this.filter; | ||
this.newBlock = | ||
bindEnvironment(function(err, blockHash) { | ||
if(err) { | ||
console.log("error captured in the block watcher. stop and restart.", err); | ||
self.stop(); | ||
self.start(); | ||
} else { | ||
//console.log("new block ", blockHash); | ||
var block = self.web3.eth.getBlock(blockHash, false); | ||
for(var i=0; i<block.transactions.length; i++) { | ||
var txHash=block.transactions[i]; | ||
if(self.tx_wait[txHash]) {// the tx Hash exists in the dictionary | ||
var txwait = self.tx_wait[txHash]; | ||
console.log("transaction watched found", txHash, "waiting",txwait.canonicalAfter,"block(s)"); | ||
txwait.startBlock=block.number; | ||
} // end if tx exists in the wait dictionary | ||
} // end for each transaction | ||
// go through all waiting transactions and check those that should be processed | ||
for(tx in self.tx_wait) { | ||
var txwait = self.tx_wait[tx]; | ||
if(block.number >= txwait.startBlock + txwait.canonicalAfter) { | ||
var receipt=self.web3.eth.getTransactionReceipt(tx); | ||
var callback = txwait.cb; | ||
var cb_args = txwait.args; | ||
cb_args.unshift(tx); | ||
cb_args.push(receipt.contractAddress || receipt.to); | ||
if(txwait.gas<=receipt.gasUsed) | ||
cb_args.push("full gas used:"+receipt.gasUsed) | ||
else if(receipt.contractAddress | ||
&& self.web3.eth.getCode(receipt.contractAddress)=="0x") | ||
cb_args.push("created contract has no bytecodes"); | ||
// remove the txHash from the wait dictionary | ||
delete self.tx_wait[tx]; | ||
// call the callback | ||
callback.apply(null, cb_args); | ||
} else if(block.number >= self.tx_wait[tx].startBlock+self.tx_wait[tx].dropAfter) { | ||
console.log("transaction watched timeout", txHash, "after",self.tx_wait[tx].dropAfter,"blocks"); | ||
var cb_args = self.tx_wait[tx].args; | ||
cb_args.unshift(tx); | ||
cb_args.push(null); // no contract address | ||
cb_args.push("number of blocks waiting reached. Tx still not mined!"); | ||
// remove the txHash from the wait dictionary | ||
delete self.tx_wait[tx]; | ||
// call the callback | ||
callback.apply(null, cb_args); | ||
} | ||
} | ||
} // end if no error | ||
}); | ||
this.start = function() { | ||
if(!this.filter) this.filter = this.web3.eth.filter('latest'); | ||
this.filter.stopWatching(); | ||
console.log("Starting the block watcher"); | ||
this.filter.watch(this.newBlock); | ||
} | ||
this.stop = function() { | ||
this.filter.stopWatching(); | ||
this.filter=null; | ||
} | ||
this.waitFor = function(txHash, gas, args, callback, options) { | ||
this.tx_wait[txHash]={gas: gas, args: args, cb: callback, | ||
startBlock:this.web3.eth.blockNumber, | ||
canonicalAfter: options.canonicalAfter || 0, | ||
dropAfter:options.dropAfter || 99999999 }; | ||
console.log("Transaction",txHash, "added to the watch"); | ||
return txHash; | ||
} | ||
} | ||
Web3.prototype.blockWatcher=null; | ||
// function to be called back when the txHash (first argument) is mined in a block | ||
// accepts as many parameters that are all passed to the callback | ||
// eg waitFor(txHash, p1, p2, callback, options) will call callback(txHash, p1, p2, contractAddress, error) | ||
// error checked are the "out of gas" and the non creation of object "code=0x00" | ||
// optional options is { canonicalAfter: 0, dropAfter: 99999999} with those default values | ||
// calls the callback only canonicalAfter blocks after the block of the mining of the tx | ||
// stop waiting this transation after dropAfter blocs and call the callback with an error | ||
Web3.prototype.waitFor = function() { | ||
// callback expected is function(txHash, rest of the args passed to this functions before the callback) | ||
var args=Array.prototype.slice.call(arguments); | ||
var options = extractOptions(args); | ||
var callback = extractCallback(args); | ||
if(!callback) return false; // no point in doing something there is no callback | ||
var txHash = args.shift() ; // first param is the tx Hash | ||
var tx=this.eth.getTransaction(this.toHex(txHash)); | ||
if(!tx) { // the first argument is not an existing txHash !! | ||
args.unshift(txHash); | ||
args.push(null); | ||
args.push("the provided txHash does not exists in the geth node. Check your code."); | ||
return callback.apply(null,args); | ||
} | ||
var gas=tx.gas; // the requested max gas that will be compared to the gasUsed of the transaction receipt | ||
if(!this.blockWatcher) {; | ||
args.unshift(txHash); | ||
args.push(null); | ||
args.push("the blockWatcher has not been created yet. Use BlockWatcherStart();"); | ||
return callback.apply(null,args); | ||
} | ||
return this.blockWatcher.waitFor(txHash, gas, args, callback, options); | ||
} | ||
Web3.prototype.BlockWatcherStart = function(bindEnvironment) { | ||
// in case no environment binding is provided, use an identity one | ||
if(!bindEnvironment) bindEnvironment=function(f) { return function() { return f.apply(f, arguments); } } | ||
if(!this.blockWatcher) this.blockWatcher = new BlockWatcher(this, bindEnvironment); | ||
this.blockWatcher.start(); | ||
return this.blockWatcher; | ||
} | ||
{ | ||
"name": "ethereum-web3-plus", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "Adds some simplifications to the web3 package such as compilation, instance creation, call sequencing", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
16136
3
236
1
109
1