Comparing version 0.1.0 to 0.1.1
646
index.js
@@ -10,8 +10,9 @@ /** | ||
if (NODE_JS) { | ||
var request = require("sync-request"); | ||
var XHR2 = require("xhr2"); | ||
} | ||
var http = require("http"); | ||
var url = require("url"); | ||
var BigNumber = require("bignumber.js"); | ||
var request = (NODE_JS) ? require("sync-request") : null; | ||
var abi = require("augur-abi"); | ||
var errors = require("./errors"); | ||
var log = console.log; | ||
@@ -59,2 +60,4 @@ BigNumber.config({ MODULO_MODE: BigNumber.EUCLID }); | ||
defaultGas: "0x2fd618", | ||
nodes: ["http://eth1.augur.net:8545"], | ||
@@ -64,2 +67,4 @@ | ||
notifications: {}, | ||
unmarshal: function (string, returns, stride, init) { | ||
@@ -240,5 +245,22 @@ var elements, array, position; | ||
post: function (rpc_url, command, returns, callback) { | ||
var req = null; | ||
var req, self = this; | ||
if (NODE_JS) { | ||
req = new XHR2(); | ||
var rpc_obj = url.parse(rpc_url); | ||
req = http.request({ | ||
host: rpc_obj.hostname, | ||
port: rpc_obj.port, | ||
path: '/', | ||
method: "POST", | ||
headers: {"Content-type": "application/json"} | ||
}, function (response) { | ||
var str = ''; | ||
response.on('data', function (chunk) { | ||
str += chunk; | ||
}); | ||
response.on('end', function () { | ||
if (str) self.parse(str, returns, callback); | ||
}); | ||
}); | ||
req.write(command); | ||
req.end(); | ||
} else { | ||
@@ -250,11 +272,11 @@ if (window.XMLHttpRequest) { | ||
} | ||
req.onreadystatechange = function () { | ||
if (req.readyState === 4) { | ||
self.parse(req.responseText, returns, callback); | ||
} | ||
}; | ||
req.open("POST", rpc_url, true); | ||
req.setRequestHeader("Content-type", "application/json"); | ||
req.send(command); | ||
} | ||
req.onreadystatechange = function () { | ||
if (req.readyState === 4) { | ||
this.parse(req.responseText, returns, callback); | ||
} | ||
}.bind(this); | ||
req.open("POST", rpc_url, true); | ||
req.setRequestHeader("Content-type", "application/json"); | ||
req.send(command); | ||
}, | ||
@@ -322,4 +344,600 @@ | ||
return payload; | ||
}, | ||
/****************************** | ||
* Ethereum JSON-RPC bindings * | ||
******************************/ | ||
raw: function (command, params, f) { | ||
return this.broadcast(this.marshal(command, params, "null"), f); | ||
}, | ||
eth: function (command, params, f) { | ||
return this.broadcast(this.marshal(command, params), f); | ||
}, | ||
net: function (command, params, f) { | ||
return this.broadcast(this.marshal(command, params, "net_"), f); | ||
}, | ||
web3: function (command, params, f) { | ||
return this.broadcast(this.marshal(command, params, "web3_"), f); | ||
}, | ||
leveldb: function (command, params, f) { | ||
return this.broadcast(this.marshal(command, params, "db_"), f); | ||
}, | ||
shh: function (command, params, f) { | ||
return this.broadcast(this.marshal(command, params, "shh_"), f); | ||
}, | ||
sha3: function (data, f) { | ||
return this.broadcast(this.marshal("sha3", data.toString(), "web3_"), f); | ||
}, | ||
hash: function (data, f) { | ||
return this.broadcast(this.marshal("sha3", data.toString(), "web3_"), f); | ||
}, | ||
gasPrice: function (f) { | ||
return this.broadcast(this.marshal("gasPrice"), f); | ||
}, | ||
blockNumber: function (f) { | ||
if (f) { | ||
this.broadcast(this.marshal("blockNumber"), f); | ||
} else { | ||
return parseInt(this.broadcast(this.marshal("blockNumber"))); | ||
} | ||
}, | ||
balance: function (address, block, f) { | ||
return this.broadcast( | ||
this.marshal("getBalance", [ | ||
address || this.eth("coinbase"), block || "latest" | ||
]), f | ||
); | ||
}, | ||
getBalance: function (address, block, f) { | ||
return this.broadcast( | ||
this.marshal("getBalance", [ | ||
address || this.eth("coinbase"), block || "latest" | ||
]), f | ||
); | ||
}, | ||
txCount: function (address, f) { | ||
return this.broadcast( | ||
this.marshal("getTransactionCount", address || this.eth("coinbase")), f | ||
); | ||
}, | ||
getTransactionCount: function (address, f) { | ||
return this.broadcast( | ||
this.marshal("getTransactionCount", address || this.eth("coinbase")), f | ||
); | ||
}, | ||
sendEther: function (to, value, from, onSent, onSuccess, onFailed) { | ||
from = from || this.web.account.address || this.broadcast(this.marshal("coinbase")); | ||
var tx, txhash; | ||
if (to && to.value) { | ||
value = to.value; | ||
if (to.from) from = to.from; | ||
if (to.onSent) onSent = to.onSent; | ||
if (to.onSuccess) onSuccess = to.onSuccess; | ||
if (to.onFailed) onFailed = to.onFailed; | ||
to = to.to; | ||
} | ||
tx = { | ||
from: from, | ||
to: to, | ||
value: abi.bignum(value).mul(this.constants.ETHER).toFixed() | ||
}; | ||
if (onSent) { | ||
this.sendTx(tx, function (txhash) { | ||
if (txhash) { | ||
onSent(txhash); | ||
if (onSuccess) | ||
this.txNotify(0, value, tx, txhash, null, onSent, onSuccess, onFailed); | ||
} | ||
}.bind(this)); | ||
} else { | ||
txhash = this.sendTx(tx); | ||
if (txhash) { | ||
if (onSuccess) | ||
this.txNotify(0, value, tx, txhash, null, onSent, onSuccess, onFailed); | ||
return txhash; | ||
} | ||
} | ||
}, | ||
sign: function (address, data, f) { | ||
return this.broadcast(this.marshal("sign", [address, data]), f); | ||
}, | ||
getTx: function (hash, f) { | ||
return this.broadcast(this.marshal("getTransactionByHash", hash), f); | ||
}, | ||
getTransaction: function (hash, f) { | ||
return this.broadcast(this.marshal("getTransactionByHash", hash), f); | ||
}, | ||
peerCount: function (f) { | ||
if (f) { | ||
this.broadcast(this.marshal("peerCount", [], "net_"), f); | ||
} else { | ||
return parseInt(this.broadcast(this.marshal("peerCount", [], "net_"))); | ||
} | ||
}, | ||
accounts: function (f) { | ||
return this.broadcast(this.marshal("accounts"), f); | ||
}, | ||
mining: function (f) { | ||
return this.broadcast(this.marshal("mining"), f); | ||
}, | ||
hashrate: function (f) { | ||
if (f) { | ||
this.broadcast(this.marshal("hashrate"), f); | ||
} else { | ||
return parseInt(this.broadcast(this.marshal("hashrate"))); | ||
} | ||
}, | ||
getBlockByHash: function (hash, full, f) { | ||
return this.broadcast(this.marshal("getBlockByHash", [hash, full || false]), f); | ||
}, | ||
getBlock: function (number, full, f) { | ||
return this.broadcast(this.marshal("getBlockByNumber", [number, full || false]), f); | ||
}, | ||
getBlockByNumber: function (number, full, f) { | ||
return this.broadcast(this.marshal("getBlockByNumber", [number, full || false]), f); | ||
}, | ||
version: function (f) { | ||
return this.broadcast(this.marshal("version", [], "net_"), f); | ||
}, | ||
netVersion: function (f) { | ||
return this.broadcast(this.marshal("version", [], "net_"), f); | ||
}, | ||
// estimate a transaction's gas cost | ||
estimateGas: function (tx, f) { | ||
tx.to = tx.to || ""; | ||
return this.broadcast(this.marshal("estimateGas", tx), f); | ||
}, | ||
// execute functions on contracts on the blockchain | ||
call: function (tx, f) { | ||
tx.to = tx.to || ""; | ||
tx.gas = (tx.gas) ? abi.prefix_hex(tx.gas.toString(16)) : this.defaultGas; | ||
return this.broadcast(this.marshal("call", tx), f); | ||
}, | ||
sendTx: function (tx, f) { | ||
tx.to = tx.to || ""; | ||
tx.gas = (tx.gas) ? abi.prefix_hex(tx.gas.toString(16)) : this.defaultGas; | ||
return this.broadcast(this.marshal("sendTransaction", tx), f); | ||
}, | ||
sendTransaction: function (tx, f) { | ||
tx.to = tx.to || ""; | ||
tx.gas = (tx.gas) ? abi.prefix_hex(tx.gas.toString(16)) : this.defaultGas; | ||
return this.broadcast(this.marshal("sendTransaction", tx), f); | ||
}, | ||
// IN: RLP(tx.signed(privateKey)) | ||
// OUT: txhash | ||
sendRawTx: function (rawTx, f) { | ||
return this.broadcast(this.marshal("sendRawTransaction", rawTx), f); | ||
}, | ||
sendRawTransaction: function (rawTx, f) { | ||
return this.broadcast(this.marshal("sendRawTransaction", rawTx), f); | ||
}, | ||
receipt: function (txhash, f) { | ||
return this.broadcast(this.marshal("getTransactionReceipt", txhash), f); | ||
}, | ||
getTransactionReceipt: function (txhash, f) { | ||
return this.broadcast(this.marshal("getTransactionReceipt", txhash), f); | ||
}, | ||
// publish a new contract to the blockchain (from the coinbase account) | ||
publish: function (compiled, f) { | ||
return this.sendTx({ from: this.eth("coinbase"), data: compiled }, f); | ||
}, | ||
// Read the code in a contract on the blockchain | ||
read: function (address, block, f) { | ||
return this.broadcast(this.marshal("getCode", [address, block || "latest"]), f); | ||
}, | ||
getCode: function (address, block, f) { | ||
return this.broadcast(this.marshal("getCode", [address, block || "latest"]), f); | ||
}, | ||
listening: function () { | ||
try { | ||
return this.net("listening"); | ||
} catch (e) { | ||
return false; | ||
} | ||
}, | ||
/** | ||
* Invoke a function from a contract on the blockchain. | ||
* | ||
* Input tx format: | ||
* { | ||
* from: <sender's address> (hexstring; optional, coinbase default) | ||
* to: <contract address> (hexstring) | ||
* method: <function name> (string) | ||
* signature: <function signature, e.g. "iia"> (string) | ||
* params: <parameters passed to the function> (optional) | ||
* returns: <"number[]", "int", "BigNumber", or "string" (default)> | ||
* send: <true to sendTransaction, false to call (default)> | ||
* } | ||
*/ | ||
invoke: function (itx, f) { | ||
var tx, data_abi, packaged, invocation, invoked; | ||
if (itx) { | ||
if (itx.send && itx.invoke && itx.invoke.constructor === Function) { | ||
return itx.invoke.call(this, itx, f); | ||
} else { | ||
tx = abi.copy(itx); | ||
if (tx.params !== undefined) { | ||
if (tx.params.constructor === Array) { | ||
for (var i = 0, len = tx.params.length; i < len; ++i) { | ||
if (tx.params[i] !== undefined && | ||
tx.params[i].constructor === BigNumber) { | ||
tx.params[i] = tx.params[i].toFixed(); | ||
} | ||
} | ||
} else if (tx.params.constructor === BigNumber) { | ||
tx.params = tx.params.toFixed(); | ||
} | ||
} | ||
if (tx.to) tx.to = abi.prefix_hex(tx.to); | ||
if (tx.from) tx.from = abi.prefix_hex(tx.from); | ||
data_abi = abi.encode(tx); | ||
if (data_abi) { | ||
packaged = { | ||
from: tx.from || this.eth("coinbase"), | ||
to: tx.to, | ||
data: data_abi | ||
}; | ||
if (tx.value) packaged.value = tx.value; | ||
if (tx.returns) packaged.returns = tx.returns; | ||
invocation = (tx.send) ? this.sendTx : this.call; | ||
invoked = true; | ||
return invocation.call(this, packaged, f); | ||
} | ||
} | ||
} | ||
if (!invoked) { | ||
if (f) { | ||
f(errors.TRANSACTION_FAILED); | ||
} else { | ||
return errors.TRANSACTION_FAILED; | ||
} | ||
} | ||
}, | ||
/** | ||
* Batched RPC commands | ||
*/ | ||
batch: function (txlist, f) { | ||
var num_commands, rpclist, callbacks, tx, data_abi, packaged, invocation; | ||
if (txlist.constructor === Array) { | ||
num_commands = txlist.length; | ||
rpclist = new Array(num_commands); | ||
callbacks = new Array(num_commands); | ||
for (var i = 0; i < num_commands; ++i) { | ||
tx = abi.copy(txlist[i]); | ||
if (tx.params !== undefined) { | ||
if (tx.params.constructor === Array) { | ||
for (var j = 0, len = tx.params.length; j < len; ++j) { | ||
if (tx.params[j] !== undefined && | ||
tx.params[j] !== null && | ||
tx.params[j].constructor === BigNumber) { | ||
tx.params[j] = tx.params[j].toFixed(); | ||
} | ||
} | ||
} else if (tx.params.constructor === BigNumber) { | ||
tx.params = tx.params.toFixed(); | ||
} | ||
} | ||
if (tx.from) tx.from = abi.prefix_hex(tx.from); | ||
tx.to = abi.prefix_hex(tx.to); | ||
data_abi = abi.encode(tx); | ||
if (data_abi) { | ||
if (tx.callback && tx.callback.constructor === Function) { | ||
callbacks[i] = tx.callback; | ||
delete tx.callback; | ||
} | ||
packaged = { | ||
from: tx.from || this.eth("coinbase"), | ||
to: tx.to, | ||
data: data_abi | ||
}; | ||
if (tx.value) packaged.value = tx.value; | ||
if (tx.returns) packaged.returns = tx.returns; | ||
invocation = (tx.send) ? "sendTransaction" : "call"; | ||
rpclist[i] = this.marshal(invocation, packaged); | ||
} else { | ||
log("unable to package commands for batch RPC"); | ||
return rpclist; | ||
} | ||
} | ||
if (f) { | ||
if (f.constructor === Function) { // callback on whole array | ||
this.broadcast(rpclist, f); | ||
} else if (f === true) { | ||
this.broadcast(rpclist, function (res) { | ||
if (res) { | ||
if (res.constructor === Array && res.length) { | ||
for (j = 0; j < num_commands; ++j) { | ||
if (res[j] && callbacks[j]) { | ||
callbacks[j](res[j]); | ||
} | ||
} | ||
} else { | ||
if (callbacks.length && callbacks[0]) { | ||
callbacks[0](res); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
} else { | ||
return this.broadcast(rpclist, f); | ||
} | ||
} else { | ||
log("expected array for batch RPC, invoking instead"); | ||
return this.invoke(txlist, f); | ||
} | ||
}, | ||
clearNotifications: function (id) { | ||
for (var i = 0, len = this.notifications.length; i < len; ++i) { | ||
clearTimeout(this.notifications[id][i]); | ||
this.notifications[id] = []; | ||
} | ||
}, | ||
encodeResult: function (result, returns) { | ||
if (result) { | ||
if (returns === "null") { | ||
result = null; | ||
} else if (returns === "address" || returns === "address[]") { | ||
result = abi.prefix_hex(abi.remove_leading_zeros(result)); | ||
} else { | ||
if (this.bignumbers && returns !== "string") { | ||
result = abi.bignum(result); | ||
} | ||
if (!this.bignumbers) { | ||
if (!returns || returns === "hash[]" || returns === "hash") { | ||
result = abi.bignum(result, "hex"); | ||
} else if (returns === "number") { | ||
result = abi.bignum(result, "string"); | ||
} | ||
} | ||
} | ||
} | ||
return result; | ||
}, | ||
errorCodes: function (tx, response) { | ||
if (response && response.constructor === Array) { | ||
for (var i = 0, len = response.length; i < len; ++i) { | ||
response[i] = this.errorCodes(tx.method, response[i]); | ||
} | ||
} else { | ||
if (errors[response]) { | ||
response = { | ||
error: response, | ||
message: errors[response] | ||
}; | ||
} else { | ||
if (tx.returns && tx.returns !== "string" || | ||
(response && response.constructor === String && | ||
response.slice(0,2) === "0x")) | ||
{ | ||
var response_number = abi.bignum(response); | ||
if (response_number) { | ||
response_number = abi.bignum(response).toFixed(); | ||
if (errors[tx.method] && errors[tx.method][response_number]) { | ||
response = { | ||
error: response_number, | ||
message: errors[tx.method][response_number] | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return response; | ||
}, | ||
fire: function (itx, callback) { | ||
var tx = abi.copy(itx); | ||
if (callback) { | ||
this.invoke(tx, function (res) { | ||
callback(this.encodeResult( | ||
this.errorCodes(tx, res), | ||
itx.returns | ||
)); | ||
}.bind(this)); | ||
} else { | ||
return this.encodeResult( | ||
this.errorCodes(tx, this.invoke(tx)), | ||
itx.returns | ||
); | ||
} | ||
}, | ||
/*************************************** | ||
* Send-call-confirm callback sequence * | ||
***************************************/ | ||
checkBlockHash: function (tx, callreturn, itx, txhash, returns, count, onSent, onSuccess, onFailed) { | ||
if (tx && tx.blockHash && abi.bignum(tx.blockHash).toNumber() !== 0) { | ||
this.clearNotifications(txhash); | ||
tx.callReturn = this.encodeResult(callreturn, returns); | ||
tx.txHash = tx.hash; | ||
delete tx.hash; | ||
if (onSuccess && onSuccess.constructor === Function) onSuccess(tx); | ||
} else { | ||
if (count !== undefined) { | ||
if (count < this.constants.TX_POLL_MAX) { | ||
if (count === 0) { | ||
this.notifications[txhash] = [setTimeout(function () { | ||
this.txNotify(count + 1, callreturn, itx, txhash, returns, onSent, onSuccess, onFailed); | ||
}.bind(this), this.constants.TX_POLL_INTERVAL)]; | ||
} else { | ||
this.notifications[txhash].push(setTimeout(function () { | ||
this.txNotify(count + 1, callreturn, itx, txhash, returns, onSent, onSuccess, onFailed); | ||
}.bind(this), this.constants.TX_POLL_INTERVAL)); | ||
} | ||
} else { | ||
if (onFailed && onFailed.constructor === Function) { | ||
onFailed(errors.TRANSACTION_NOT_CONFIRMED); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
txNotify: function (count, callreturn, itx, txhash, returns, onSent, onSuccess, onFailed) { | ||
this.getTx(txhash, function (tx) { | ||
if (tx === null) { | ||
if (returns) itx.returns = returns; | ||
} else { | ||
this.checkBlockHash(tx, callreturn, itx, txhash, returns, count, onSent, onSuccess, onFailed); | ||
} | ||
}.bind(this)); | ||
}, | ||
confirmTx: function (tx, txhash, returns, onSent, onSuccess, onFailed) { | ||
var self = this; | ||
if (tx && txhash) { | ||
this.notifications[txhash] = []; | ||
if (errors[txhash]) { | ||
if (onFailed) onFailed({ | ||
error: txhash, | ||
message: errors[txhash] | ||
}); | ||
} else { | ||
this.getTx(txhash, function (sent) { | ||
if (returns !== "null") { | ||
self.call({ | ||
from: sent.from || self.eth("coinbase"), | ||
to: sent.to || tx.to, | ||
value: sent.value || tx.value, | ||
data: sent.input | ||
}, function (callReturn) { | ||
if (callReturn) { | ||
callReturn = JSON.stringify({ result: callReturn }); | ||
// transform callReturn to a number | ||
var numReturn = self.parse(callReturn, "number"); | ||
// check if numReturn is an error object | ||
if (numReturn.constructor === Object && numReturn.error) { | ||
if (onFailed) onFailed(numReturn); | ||
} else if (errors[numReturn]) { | ||
if (onFailed) onFailed({ | ||
error: numReturn, | ||
message: errors[numReturn] | ||
}); | ||
} else { | ||
try { | ||
// check if numReturn is an error code | ||
if (numReturn && numReturn.constructor === BigNumber) { | ||
numReturn = numReturn.toFixed(); | ||
} | ||
if (numReturn && errors[tx.method] && errors[tx.method][numReturn]) { | ||
if (onFailed) onFailed({ | ||
error: numReturn, | ||
message: errors[tx.method][numReturn] | ||
}); | ||
} else { | ||
// no errors found, so transform to the requested | ||
// return type, specified by "returns" parameter | ||
callReturn = self.parse(callReturn, returns); | ||
// send the transaction hash and return value back | ||
// to the client, using the onSent callback | ||
onSent({ | ||
txHash: txhash, | ||
callReturn: self.encodeResult(callReturn, returns) | ||
}); | ||
// if an onSuccess callback was supplied, then | ||
// poll the network until the transaction is | ||
// included in a block (i.e., has a non-null | ||
// blockHash field) | ||
if (onSuccess) { | ||
self.txNotify( | ||
0, | ||
callReturn, | ||
tx, | ||
txhash, | ||
returns, | ||
onSent, | ||
onSuccess, | ||
onFailed | ||
); | ||
} | ||
} | ||
// something went wrong :( | ||
} catch (e) { | ||
if (onFailed) onFailed(e); | ||
} | ||
} | ||
} | ||
}); | ||
// if returns type is null, skip the intermediate call | ||
} else { | ||
onSent({ | ||
txHash: txhash, | ||
callReturn: null | ||
}); | ||
if (onSuccess) { | ||
self.txNotify( | ||
0, | ||
null, | ||
tx, | ||
txhash, | ||
returns, | ||
onSent, | ||
onSuccess, | ||
onFailed | ||
); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
}, | ||
transact: function (tx, onSent, onSuccess, onFailed) { | ||
var returns = tx.returns; | ||
tx.send = true; | ||
delete tx.returns; | ||
if (onSent && onSent.constructor === Function) { | ||
this.invoke(tx, function (txhash) { | ||
txhash = abi.prefix_hex(abi.pad_left(abi.strip_0x(txhash))); | ||
this.confirmTx(tx, txhash, returns, onSent, onSuccess, onFailed); | ||
}.bind(this)); | ||
} else { | ||
return this.invoke(tx); | ||
} | ||
} | ||
}; |
{ | ||
"name": "ethrpc", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "Ethereum JSON RPC", | ||
@@ -9,3 +9,3 @@ "main": "index.js", | ||
"lint": "jshint index.js && jshint test/*.js", | ||
"coverage": "istanbul cover -x **/lib/** ./node_modules/mocha/bin/_mocha test/*.js" | ||
"coverage": "istanbul cover ./node_modules/mocha/bin/_mocha test/*.js" | ||
}, | ||
@@ -23,16 +23,13 @@ "repository": { | ||
"dependencies": { | ||
"augur-abi": "^0.1.0", | ||
"bignumber.js": "^2.0.7", | ||
"sync-request": "^2.0.1", | ||
"xhr2": "^0.1.3" | ||
"augur-abi": "^0.1.1", | ||
"bignumber.js": "^2.0.7" | ||
}, | ||
"browser": { | ||
"sync-request": false, | ||
"xhr2": false | ||
}, | ||
"devDependencies": { | ||
"augur-contracts": "^0.1.0", | ||
"browserify": "^11.0.1", | ||
"chai": "^3.2.0", | ||
"coveralls": "^2.11.4", | ||
"del": "^1.2.1", | ||
"gulp": "^3.9.0", | ||
"istanbul": "^0.3.18", | ||
"it-each": "^0.3.1", | ||
@@ -42,3 +39,9 @@ "jshint": "^2.8.0", | ||
"uglify-js": "^2.4.24" | ||
}, | ||
"optionalDependencies": { | ||
"sync-request": "^2.0.1" | ||
}, | ||
"browser": { | ||
"sync-request": false | ||
} | ||
} |
@@ -7,4 +7,4 @@ ethrpc | ||
[](https://nodei.co/npm/ethrpc/) | ||
Basic JSON RPC methods for Ethereum. | ||
@@ -21,3 +21,3 @@ | ||
```javascript | ||
> var ethrpc = require("ethrpc"); | ||
var ethrpc = require("ethrpc"); | ||
``` | ||
@@ -24,0 +24,0 @@ A minified, browserified file `dist/ethrpc.min.js` is included for use in the browser. Including this file simply attaches the `ethrpc` object to `window`: |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
1187942
3
9
24001
11
6
- Removedsync-request@^2.0.1
- Removedxhr2@^0.1.3
- Removedxhr2@0.1.4(transitive)
Updatedaugur-abi@^0.1.1