diff --git a/README.md b/README.md index 3a245b01f02150ee7afab6bd298f8f6586c3285d..855001c2521c1933003a37f4098c224ab987bb6e 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,43 @@ +**WARNING: This code is NOT intended or ready for production use. Bad things will happen if you use it as is!** + ## About -The idea is described in more detail [here](https://cloud.lab10.io/s/Z3cKDm4asf4BPdc). +This is the first PoC implementation of Streems (read more about it [here](https://artis.eco/en/blog/detail/streaming-money-1)). +It includes a contract, a minimal web interface and an interactive test web interface. + +Note that most of this was written in mid 2017, thus targets Solidity v0.4.13. +It still compiles (last version tested: v0.4.23), but with a lot of warnings. That's because Solidity has become a safer language since, allowing for and also demanding more explicit expression of intentions. See [Solidity Changelog](https://github.com/ethereum/solidity/blob/develop/Changelog.md). + +The goal of this code was to proof feasibilty of continuous transfers (a kind of on-chain value streaming). +Core logic is in ` Streem.sol` which implements a minimal [ERC20 token](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) (to be more precise - a subset of it as it lacks implementation of `transferFrom()`, `approve()` and `allowance()`). + +The contracts allow only one outgoing and one incoming Streem per account in order to keep things simple. +This has the side effect of making **nested cycles** impossible to build up. +**Simple cycles** are supposed to be handled correctly by this implementation (no proof given though). + +This approach was not further pursued, because I found no simple solution for how to avoid the building up of uncomputable dependency graphs. +While Streems can be chained, such chains make computing the balance at the end of such a Streem chain expensive (as it recurses through that chain) - to a point where it could exceed the block gas limit and thus become effectively uncomputable on-chain. Which would also mean that the last Streem of such a chain couldn't be closed anymore, because closing requires on-chain computation of the balance. +Since I didn't find a satisfying solution to this problem, this PoC wasn't developed further, instead we switched focus the concept of **Basic Streems** (as described [here](https://artis.eco/en/blog/detail/streaming-money-2)). + +We also decided to limit Solidity implementations to PoCs and testing purposes and started a native implementation of Basic Streems in [Parity](https://github.com/paritytech/parity). +Such a native implementation allows for considerably reduced transaction costs and makes the basic unit of Account (ETH/ATS) streamable without wrapper. + +There's no conventional tests ([like e.g. here](https://github.com/lab10-coop/Play4Privacy/tree/master/blockchain/test)) included. Instead I used a kind of interactive test app in `test.[html|js]` in order to quickly iterate various cases coming to my mind. -## Status +## How to run -PoC of the concept including an ERC-20 compatible token contract and a minimal web interface for opening, closing and observing streams. +Needs [truffle](http://truffleframework.com/) ganache-cli installed: `npm install -g truffle ganache-cli` +Start dev chain: `ganache-cli` +Then, in another tab, enter the backend directory and run `./deploy.sh` which will deploy the contract to the dev testnet and update frontend bindings. +TODO: Add watcher option. -## Next +You can now interact with the contract in various ways +* using `truffle console` +* using [remix](http://remix.ethereum.org/) (connect it to the local testnet, paste the contract code and load the contract at the deployed address) +* with the web app at `streem.html` +* with the interactive test web app at `test.html` -Next steps would be: -* Make the contract multi-stream capable (accounts can have both multiple instreams and outstreams). This probably requires something like `mapping (address => (uint => Stream)) [in|out]streams`. - * How can existing streams be referenced from outside? Should it be possible to name them when opening? -* Decide on a set of possible semantics and design the interface accordingly. E.g. - * Streams which auto-close when running out of funds - * Streams which guarantee a specified per-warning time before running out of stream (blocking outgoing transfers if balance too low) - * Streams with close date already predetermined - * Advanced: Streams depending on oracle data (dependents: speed, open state) - * Streams which can be closed by the receiver (should probably always be allowed) -* Events -* Check interoperability with various ERC-20 wallets. -* Figure out the issuance and governance mechanics and implement them. - -Further a lot of attention needs to go into robustness of the contracts (special cases, error handling, gas economics). +In order to use the web apps, you need a webserver which can serve the static content in frontend directory. +Now you can point a browser to `streem.html` or `test.html`. In order to have the Apps connect to the locally running ganache-cli, the browser should not inject web3 (e.g. if you have Metamask installed, disabled it). -When enough is known, consider the overall contract architecture (e.g. a token contract and an issuance contract). Should anything be upgradable? Any kind of emergeny mechanism? \ No newline at end of file +The contract can of course also be deployed to a public testnet (there's for example a [deployment on Rinkeby](https://rinkeby.etherscan.io/address/0xf73f6bd052061bb84913be57d5f7565b0aa38827)). In order to access such a contract via the web frontend, hardcode the address in the Javascript file and open it in a browser with web3 injected and connected to the respective network. \ No newline at end of file diff --git a/backend/README.md b/backend/README.md deleted file mode 100644 index eadc75a9c5c5a908bceafa561946e41ef43ba0e7..0000000000000000000000000000000000000000 --- a/backend/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# How to run - -Needs truffle and testrpc installed: `npm install -g truffle ethereumjs-testrpc` -Start testrpc: `testrpc` -Then, in another tab run `./contract-changed.sh` whenever the contract should be re-compiled JS bindings updated. -TODO: Add watcher option. - -# The dynamic challenge - -When checking the balance of a receiving address or closing an incoming stream, it's not enough to just look at the static balance of the sender. - -**Sender has incoming stream(s)**: In this case looking at only staticBalance may return a too low result and lead to unnecessary drying of the stream. - -**Sender has outgoing stream(s)**: In this case looking at only staticBalance may return a too high result, leading to a drying stream not being noticed. - -Also, when doing a discrete transfer, it may now happen that the staticBalance is smaller than balance. Thus the amount can't just be subtracted from staticBalance. -Can we make staticBalance an int or would that introduce other issues? - -## Options - -### Only one stream per account - -In this case an account could have only either an outgoing or an incoming stream. -Thus a receiver could rely on the sender not having any other stream, thus looking at staticBalance alone would be enough. - -### Max one incoming and one outgoing stream - -In this case a receiver could rely on the sender not having any other stream draining staticBalance. -Still she'd need for account for a potential parallel incoming stream. - -Problem: there could be a circular relationship. E.g. A streams to B and B streams to A. -How to implement this without the potential for an endless recursion? - -* Avoid creation of such a constellation (e.g. have *openStream()* check it) -* Find a way to implement it safely (should be possible, but I don't yet have an idea how) - -Either way, we still need to protect from the risk of running out of gas due to many dependencies. -A possible solution could be a kind of maintenance cronjob which regularly creates kind of snapshots which cut down the dependencies on other streams. -That could be achieved by some kind of transient staticBalance reflecting a snapshot (what if all streams were closed at this point in time). -Such a value would increase the probability of receivers not needing to check incoming streams of the sender in case the transient staticBalance minus outgoing streams remained above the required threshold. -However for calculating the remaining runway for a stream, this may not help (?) - (does the gas limit apply for local execution?) - -### Limited number of streams per account - -This could probably be implemented with arrays. -Would need a clear strategy (or multiple) for how to deal with dry streams - similar to how insolvencies are dealt with. -Basic strategies are: -* first come first serve (e.g. older streams are served first) -* proportional: needs to know the point in time starting from which streams are underfunded / dry -* priority classes: could be combined with either the first come first serve or proportional strategy - -Guess: Allowing 2 incoming and 2 outgoing streams would allow to construct all compositions possible with arbitrary number of streams by using *intermediate* accounts for aggregation or splitting. - -### Arbitrary number of streams per account - -Logically identical to the *limited number of streams* option. -But probably a considerably bigger implementation challenge in terms of complexity and gas cost. E.g. fixed size array nomore an option. - -A possibility could be to have *openStream()* measure the complexity of the dependencies based on the involved addresses and not execute if it exceeds some safety threshold. - -## Basic strategy - -Whenever a transaction takes place, it can be used for some bookkeeping. -Most importantly, a kind of intermediate settlement can be done for open streams. This can be seen as persisting the results of calculations. -Since dynamically calculated status snapshots depending on the current time are guaranteed / final, such states can as well be persisted. diff --git a/backend/contracts/Streem.sol b/backend/contracts/Streem.sol index 464b1680b1a20aac45887cdf58f53cdec7c0fe00..a9e477a92b07eca6ee885f95f7d5d31a067f8c11 100644 --- a/backend/contracts/Streem.sol +++ b/backend/contracts/Streem.sol @@ -55,7 +55,7 @@ contract Streem { // ERC-20 compliant function for discrete transfers // TODO: the standard seems to require bool return value - function transfer(address _to, uint256 _value) { + function transfer(address _to, uint256 _value) returns (bool) { assert(_value > 0 && balanceOf(msg.sender) >= _value); // if the settled balance doesn't suffice, settle the available funds of the ingoing stream. @@ -73,6 +73,7 @@ contract Streem { settledBalances[msg.sender] -= int(_value); settledBalances[_to] += int(_value); Transfer(msg.sender, _to, _value); + return true; } /* @@ -134,10 +135,10 @@ contract Streem { settledBalances[s.sender] -= int(settleBal); settledBalances[s.receiver] += int(settleBal); // inS.receiver == msg.sender - // TODO: make sure we really don't need an extra field for this intermediate settlement. + // TODO: make sure we don't need an extra field if invoking this for open streams. // For correct behaviour, it's irrelevant what the start time of the stream is. // Applications can rely on the StreamOpened-Event for the UI. - // Still, the field may need a name better reflecting this flexible use. + // Still, the field may need a name better reflecting this semantics. s.startTimestamp += dt; // TODO: disable checks in prod if they cost gas and the logic is proofed assert(s.startTimestamp <= now); @@ -154,7 +155,7 @@ contract Streem { // ################## Internal constant functions ################### - // Solidity (so far) has no simple null check, using startTimestamp as guard (assuming 1970 will not come back). + // Solidity (so far) has no simple null check, using startTimestamp as guard (assuming we'll not overflow back to 1970). function exists(Stream s) internal constant returns (bool) { return s.startTimestamp != 0; } @@ -187,13 +188,12 @@ contract Streem { * returns the "real" (based on sender solvency) balance of a stream. * This takes the perspective of the sender, making the stream under investigation an outgoingStream. * Implements min(outgoingStreamBalance, staticBalance + incomingStreamBalance) - * TODO: due to the involved recursion, this will lead to an endless loop in circular relations, e.g. A -> B, B -> A */ function streamBalance(Stream s, Stream origin, uint hops) internal constant returns (uint256) { // naming: osb -> outgoingStreamBalance, isb -> incomingStreamBalance, sb -> static balance uint256 osb = naiveStreamBalance(s); - if (equals(s, origin) && hops > 1) { // special case: break on circular dependency. TODO: proof correctness + if (equals(s, origin) && hops > 1) { // special case: stop when detecting a cycle. TODO: proof correctness return osb; } else { var inS = getInStreamOf(s.sender); @@ -210,7 +210,7 @@ contract Streem { // ####################### dev / testing helpers ######################### - // TODO: this is just for the test token. Issuance mechanism for mainnet token to be decided. + // TODO: this is just for the test token function dev_issueTo(address receiver, uint256 amount) { require(msg.sender == owner); settledBalances[receiver] += int(amount); diff --git a/backend/contracts/StreemERC20.sol b/backend/contracts/StreemERC20.sol deleted file mode 100644 index 0662d6e65a551272eaa46280525e634d4c7edaf7..0000000000000000000000000000000000000000 --- a/backend/contracts/StreemERC20.sol +++ /dev/null @@ -1,128 +0,0 @@ -pragma solidity ^0.4.13; - -import "./Streem.sol"; - -// inspired by https://github.com/mattdf/payment-channel/blob/master/channel.sol - -// just the interface we need -// TODO: use "interface" keyword (with solc 0.4.15) -contract IERC20Token { - function balanceOf(address _owner) constant returns (uint balance); - function transfer(address _to, uint _value) returns (bool success); -} - -// TransferAccount instances hold the deposits of tokens converted to streamable tokens. -// Dumb contract which only contains a proxy transfer function -// also see https://github.com/bancorprotocol/contracts/blob/master/solidity/contracts/TokenHolder.sol -contract TransferAccount { - address owner; - - function TransferAccount() { - owner = msg.sender; - } - - // this just forwards a transfer request. Needs to be done by the contract itself in order to have msg.sender correct. - // TODO: could this also take an ERC20 object as param instead of address? - function transfer(address tokenAddr, address receiver, uint256 amount) returns (bool) { - assert(msg.sender == owner); - var token = IERC20Token(tokenAddr); - return token.transfer(receiver, amount); - } -} - -// one instance represents one ERC20 token, the rest is very similar to the normal Streem contract. -// a model where a contract exists per user would offer more implicit security, but be less efficient (?) -contract StreemERC20 is Streem { - event Withdrawal(address sender, uint amount); - - address owner; - IERC20Token token; - address tokenAddr; - mapping (address => TransferAccount) transferAccounts; - - event TransferAccountCreated(address forAccount, address transferAddr); - - // constructor. TODO: dynamically configure - function StreemERC20(address _tokenAddr) Streem(0, "Streaming Token", "STOK", 0) { - tokenAddr = tokenAddr; - token = IERC20Token(_tokenAddr); - } - - // ################## Public functions ################### - - function createTransferAccount() returns (address) { - var tAcc = new TransferAccount(); - transferAccounts[msg.sender] = tAcc; - TransferAccountCreated(msg.sender, tAcc); - return address(transferAccounts[msg.sender]); - } - - // override - function transfer(address _to, uint256 _value) { - poolTransferAccountFor(msg.sender); - super.transfer(_to, _value); - } - - // override - function openStream(address receiver, uint256 perSecond) { - poolTransferAccountFor(msg.sender); - super.openStream(receiver, perSecond); - } - - // override - function closeStream() { - poolTransferAccountFor(msg.sender); - super.closeStream(); - } - - // withdrawal of owner tokens - function withdraw(uint256 amount) { - poolTransferAccountFor(msg.sender); - - // following the Checks-Effects-Interaction Pattern - assert(balanceOf(msg.sender) >= amount); - settledBalances[msg.sender] -= int(amount); - totalSupply -= amount; - assert(token.transfer(msg.sender, amount)); - Withdrawal(msg.sender, amount); - } - - // ################## Public constant functions ################### - - function tokenAddress() constant returns(address) { - return address(token); - } - - function getTransferAccount() constant returns (address) { - return transferAccounts[msg.sender]; - } - - // override - function balanceOf(address addr) constant returns (uint256) { - var baseBal = super.balanceOf(addr); - var transferAddr = address(transferAccounts[addr]); - if(transferAddr != 0) { - return baseBal + token.balanceOf(transferAddr); - } else { - return baseBal; - } - } - - // ################## Internal functions ################### - - // If there's funds in an associated transfer account, transfer it to this contract (pool) - // returns the amount moved over - function poolTransferAccountFor(address addr) internal returns(uint) { - if(address(transferAccounts[addr]) != 0) { - var tBal = token.balanceOf(address(transferAccounts[addr])); - if(tBal >= 0) { - // TODO: is assert a reasonable strategy here? - assert(transferAccounts[addr].transfer(address(token), this, tBal)); - totalSupply += tBal; - settledBalances[addr] += int(tBal); - return tBal; - } - } - return 0; - } -} \ No newline at end of file diff --git a/backend/contracts/StreemETH.sol b/backend/contracts/StreemETH.sol deleted file mode 100644 index 785a06fa20d50090e235f08e2f154d2bcbcbcd7d..0000000000000000000000000000000000000000 --- a/backend/contracts/StreemETH.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity ^0.4.13; - -import "./Streem.sol"; - -contract StreemETH is Streem { - event Deposit(address sender, uint amount); - event Withdrawal(address sender, uint amount); - - // constructor: just call the base constructor with the right args - function StreemETH() Streem(0, "Streaming Ether", "SETH", 18) {} - - // conversion from StreemETH to ETH - function withdraw(uint256 amount) { - // following the Checks-Effects-Interaction Pattern - assert(balanceOf(msg.sender) >= amount); - settledBalances[msg.sender] -= int(amount); - totalSupply -= amount; - msg.sender.transfer(amount); - Withdrawal(msg.sender, amount); - } - // conversion from ETH to StreemETH - function() payable { - settledBalances[msg.sender] += int(msg.value); - totalSupply += msg.value; - Deposit(msg.sender, msg.value); - } -} \ No newline at end of file diff --git a/backend/contract-changed.sh b/backend/deploy.sh similarity index 63% rename from backend/contract-changed.sh rename to backend/deploy.sh index 8b6385ff450c6cb10f7d30aa0c865ff367f252aa..0eabebd306594b8f5aaa83bdb04e761b6dfae270 100755 --- a/backend/contract-changed.sh +++ b/backend/deploy.sh @@ -1,5 +1,6 @@ #!/bin/bash +# Quick'n dirty way to deploy the last version of the contract and keep frontend bindings in sync (ABI and address) # Invokes 'truffle migrate' (compile, re-deploy) # and tells the node script in frontend to update the JS file representing the contract @@ -10,5 +11,5 @@ set -u truffle migrate --reset node apply_contract_update.js build/contracts/Streem.json ../frontend/js/streem_contract.js -node apply_contract_update.js build/contracts/StreemETH.json ../frontend/js/streemETH_contract.js +#node apply_contract_update.js build/contracts/StreemETH.json ../frontend/js/streemETH_contract.js echo "update applied" diff --git a/backend/migrations/2_deploy_contracts.js b/backend/migrations/2_deploy_contracts.js index be44d7a003954fb5cc92739f3e8773931fa27808..23ecfec2107127f9f9e3a0940b5c46701ba8f780 100644 --- a/backend/migrations/2_deploy_contracts.js +++ b/backend/migrations/2_deploy_contracts.js @@ -1,13 +1,9 @@ var Streem = artifacts.require("./Streem.sol"); -//var Streemify = artifacts.require("./Streemify.sol"); -var StreemETH = artifacts.require("./StreemETH.sol"); +//var StreemETH = artifacts.require("./StreemETH.sol"); module.exports = function(deployer) { deployer.deploy([ - [Streem, 100000000], // the second param is for the contract constructor - StreemETH -]); - -// deployer.deploy(Streemify); - //deployer.deploy(StreemETH); + [Streem, 100000000, "STREEM", "STR", 0] +// StreemETH + ]); }; diff --git a/backend/test/TestStreem.sol b/backend/test/TestStreem.sol deleted file mode 100644 index c73902f87d425de50d1ebcf5e2650a3f3884e11a..0000000000000000000000000000000000000000 --- a/backend/test/TestStreem.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma solidity ^0.4.2; - -import "truffle/Assert.sol"; -import "truffle/DeployedAddresses.sol"; -import "../contracts/Streem.sol"; - -contract TestStreem { - - address owner; - - function testInitialBalanceUsingDeployedContract() { - owner = tx.origin; - Streem streem = Streem(DeployedAddresses.Streem()); - - uint expected = 10000; - - //// issue some tokens to the owner - //streem.dev_issueTo(owner, expected); - //streem.dev_issueTo(tx.origin, 10000); - //uint balance = streem.balanceOf(tx.origin); - - Assert.equal(streem.balanceOf(tx.origin), expected, "Owner should have 10000 STR initially"); - } - - function testTotalSupplyWithNewContract() { - uint expected = 10000; - Streem streem = new Streem(expected, "UnitTestStreem", "TEST-STR", 0); - - Assert.equal(streem.totalSupply(), expected, "totalSupply should be 10000"); - } - - // TODO: test actual streaming functionality -} diff --git a/backend/truffle.js b/backend/truffle.js index 91b2caf5f50f4c28cd84a8b7eab346458d334664..2491c7c8dea8a432f6e428b1b298c27f65ce5d8e 100644 --- a/backend/truffle.js +++ b/backend/truffle.js @@ -4,16 +4,6 @@ module.exports = { host: "localhost", port: 8545, network_id: "*" // Match any network id - }, - rinkeby: { - host: "rinkeby.eth.lab10.io", // Connect to geth on the specified - port: 80, - //from: "0xc6aa5459ef1cbbc4dce38c7bba5e01fd12b521a4", // default address to use for any transaction Truffle makes during migrations - from: "0xc6AA5459eF1CBBc4DcE38C7bBa5E01Fd12B521a4", // default address to use for any transaction Truffle makes during migrations - // needed to be unlocked permanently (timeout 0) in geth: personal.unlockAccount("0xc6aa5459ef1cbbc4dce38c7bba5e01fd12b521a4", "bernhard", 0) - network_id: 4, - // gas: 4612388 // Gas limit used for deploys - gas: 4700000 // Gas limit used for deploys } } }; diff --git a/frontend/js/streem.js b/frontend/js/streem.js index ad92358e6a15270a8e34b63cd40366b9ea833f94..f1d0259174ffc3265f00eb61937ef0fe02f7178a 100644 --- a/frontend/js/streem.js +++ b/frontend/js/streem.js @@ -4,13 +4,14 @@ function initContract() { const abi = contract.abi; // get address - in case of multiple network entries, the last seems to be a safe bet - /* for(let networkId in contract.networks) { //console.log(contract.networks[networkId]) var address = contract.networks[networkId].address } - */ - var address = '0xf73f6bd052061bb84913be57d5f7565b0aa38827' + + // in order to hardcode an address (e.g. of a public testnet), + // comment out the loop above, set the address in next line and uncomment + // var address = '0xf73f6bd052061bb84913be57d5f7565b0aa38827' // rinkeby deployment var Web3 = require('web3'); @@ -68,6 +69,12 @@ function initContract() { }) } +/* +NOTE: gas amounts for contract calls are hardcoded to an arbitrary value. +Should instead be inferred via gas estimation upfront. +*/ +const GASLIMIT = 200000 + function onOpenStreamButton() { console.log("open stream clicked") @@ -75,23 +82,24 @@ function onOpenStreamButton() { const speed = document.getElementById('speed').value console.log(`opening stream to ${rcv} with speed ${speed}`) - streem.openStream(rcv, speed, {gas: 200000}, txHandler) // TODO: gas is just a guess to make it working on testrpc + streem.openStream(rcv, speed, {gas: GASLIMIT}, txHandler) } // TODO: first test locally if it can be executed function onCloseStreamButton() { console.log("close stream clicked") - streem.closeStream({gas: 200000}, txHandler) // TODO: gas is just a guess to make it working on testrpc + streem.closeStream({gas: GASLIMIT}, txHandler) } function onTransferButton() { console.log("transfer clicked") const rcv = document.getElementById('transfer-receiver').value const amount = document.getElementById('transfer-amount').value - streem.transfer(rcv, amount, {gas: 200000}, txHandler) // TODO: gas is just a guess to make it working on testrpc + streem.transfer(rcv, amount, {gas: GASLIMIT}, txHandler) } // TODO: how to detect failure of a transaction? See https://ethereum.stackexchange.com/questions/6007/how-can-the-transaction-status-from-a-thrown-error-be-detected-when-gas-can-be-e +// update: this was written pre-byzantium. TBD with check of status field now function txHandler(err, txHash) { if(err) { console.log(`transfer failed: ${err}`) diff --git a/frontend/js/streemETH.js b/frontend/js/streemETH.js deleted file mode 100644 index fcfd3d7385ebe00fdda0d47d74dc3cb90dc37ff0..0000000000000000000000000000000000000000 --- a/frontend/js/streemETH.js +++ /dev/null @@ -1,257 +0,0 @@ -// for contract metadata (format as produced by truffle) -function initContract() { - return new Promise( (resolve, reject) => { - const abi = contract.abi; - - // get address - in case of multiple network entries, the last seems to be a safe bet - /* - for(let networkId in contract.networks) { - //console.log(contract.networks[networkId]) - var address = contract.networks[networkId].address - } - */ - window.address = '0x03d675a91c375c0cede9bacc8add46824ee7b483' - - var Web3 = require('web3'); - - if (typeof web3 !== 'undefined') { - // Mist / Metamask - console.log('web3 connects to provider') - web3 = new Web3(web3.currentProvider); - } else { - // standalone - //alert("This Dapp needs web3 injected (e.g. through the Metamask plugin."); - console.log('web3 connects to rpc') - web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) - } - web3.eth.getAccounts((err, ret) => { - if (!err) web3.eth.defaultAccount = ret[0] - if (web3.eth.defaultAccount == undefined) { - alert("no Ethereum account found") - } else { - console.log(`defaultAccount: ${web3.eth.defaultAccount}`) - - // contract is the contract template based on our abi - const StreemETH = web3.eth.contract(abi); - streemETH = StreemETH.at(address); - - streemETH.totalSupply( (err, ret) => { - if(err/* || ret == 0*/) { // TODO: find another way to test existence - alert(`Cannot communicate with contract at given address ${address}`) - } else { - console.log(`contract loaded at ${address}`) - - web3.version.getNetwork( (err, ret) => { - resolve({ contractaddr: address, networkid: ret}) - }) - } - }) - } - }) - - // callback on block advance - web3.eth.filter('latest').watch((err, hash) => { - console.log(`new block: ${hash}`) - if (typeof onNextBlock == 'function') { - onNextBlock(hash) - } - }) - - // callback on pending transactions - /* - // the address filter seems not to work - web3.eth.filter({address: web3.eth.defaultAccount}).watch((err, ret) => { - console.log(`filtered event: ${JSON.stringify(ret)}`) - getReceipt(ret.transactionHash) - }) - */ - }) -} - -function onOpenStreamButton() { - console.log("open stream clicked") - - const rcv = document.getElementById('receiver').value - const speed = document.getElementById('speed').value - - console.log(`opening stream to ${rcv} with speed ${speed}`) - streemETH.openStream(rcv, web3.toWei(speed), {gas: 200000}, txHandler) // TODO: gas is just a guess to make it working on testrpc -} - -// TODO: first test locally if it can be executed -function onCloseStreamButton() { - console.log("close stream clicked") - streemETH.closeStream({gas: 200000}, txHandler) // TODO: gas is just a guess to make it working on testrpc -} - -function onWithdrawButton() { - console.log("withdraw clicked") - const amount = document.getElementById('withdraw-amount').value - streemETH.withdraw(web3.toWei(amount), {gas: 200000}, txHandler) // TODO: gas is just a guess to make it working on testrpc -} - -function onDepositButton() { - console.log("deposit clicked") - const amount = document.getElementById('deposit-amount').value - console.log(`sending ${web3.toWei(amount)} wei to ${window.address}`) - web3.eth.sendTransaction({to: window.address, value: web3.toWei(amount), gas: 200000}, txHandler) // TODO: gas is just a guess to make it working on testrpc -} - -// TODO: how to detect failure of a transaction? See https://ethereum.stackexchange.com/questions/6007/how-can-the-transaction-status-from-a-thrown-error-be-detected-when-gas-can-be-e -function txHandler(err, txHash) { - if(err) { - console.log(`transfer failed: ${err}`) - alert(`transaction failed: ${err}`) - } else { - console.log(`new pending transaction: ${txHash}`) - window.pendingTx = txHash - document.getElementById('pendingtx').innerHTML = `<a href="${network.explorer}/tx/${txHash}" target="_blank">${txHash}</a>` - function incrementCounter(startTime) { - window.setTimeout(() => { - document.getElementById('pendingtxcounter').innerHTML = Math.floor(Date.now() / 1000) - startTime - if(window.pendingTx) { - incrementCounter(startTime) - } else { - document.getElementById('pendingtxcounter').innerHTML = '' - } - }, 1000) - } - incrementCounter(Math.floor(Date.now() / 1000)) - } -} - -function getReceipt(txHash) { - console.log(`getReceipt for tx ${txHash}`) - web3.eth.getTransactionReceipt(txHash, (err, ret) => { - if(err) { - console.log(`getTransactionReceipt failed: ${err}`) - } else { - console.log(`receipt: ${JSON.stringify(ret)}`) - } - }) -} - -// shows the balance of <address> by calling the function <updateUi> with the balance as parameter -function showBalance(address, updateUi) { - streemETH.balanceOf(address, (err, ret) => { - window.balance = ret - const bal = web3.fromWei(web3.toDecimal(ret)) - updateUi(bal) - }) -} - -// callback for new block event -function onNextBlock() { - web3.eth.getBlockNumber((err, ret) => { - document.getElementById('blocknr').innerHTML = ret - }) - web3.eth.getBalance(web3.eth.defaultAccount, (err, ret) => { - if(! err) { - window.balance = ret - const balWei = web3.fromWei(web3.toDecimal(ret)) - document.getElementById('etherbalance').innerHTML = balWei - } else { - alert("Something went wront: can't read Ether balance. Blockchain node connected?") - } - }) - showBalance(web3.eth.defaultAccount, (bal) => { - document.getElementById('streemethbalance').innerHTML = bal - } ) - const receiverAddr = document.getElementById('receiver').value - if(receiverAddr != "") { -// showBalance(receiverAddr, (bal) => { document.getElementById('somebalance-result').innerHTML = bal } ) - } - - streemETH.dev_inStream((err, ret) => { - const sender = ret[0], speed = web3.fromWei(web3.toDecimal(ret[1])), age = web3.toDecimal(ret[2]) - document.getElementById('in-sender').innerHTML = speed != 0 ? `<a href="${network.explorer}/token/${contractaddr}?a=${sender}" target="_blank">${sender}</a>` : '-' - document.getElementById('in-speed').innerHTML = speed != 0 ? speed: '-' - document.getElementById('in-age').innerHTML = speed != 0 ? age : '-' - - if(speed != 0) { - streemETH.balanceOf(sender, (err, ret) => { - const bal = web3.fromWei(web3.toDecimal(ret)) - const runway = Math.floor(bal / speed) - document.getElementById(`in-runway`).innerHTML = runway - }) - } else { - document.getElementById(`in-runway`).innerHTML = '-' - } - }) - - streemETH.dev_outStream((err, ret) => { - const receiver = ret[0], speed = web3.fromWei(web3.toDecimal(ret[1])), age = web3.toDecimal(ret[2]) - document.getElementById('out-receiver').innerHTML = speed != 0 ? `<a href="${network.explorer}/token/${contractaddr}?a=${receiver}" target="_blank">${receiver}</a>` : '-' - document.getElementById('out-speed').innerHTML = speed != 0 ? speed: '-' - document.getElementById('out-age').innerHTML = speed != 0 ? age : '-' - - if(speed != 0) { - streemETH.balanceOf(web3.eth.defaultAccount, (err, ret) => { - const bal = web3.fromWei(web3.toDecimal(ret)) - const runway = Math.floor(bal / speed) - document.getElementById(`out-runway`).innerHTML = runway - }) - } else { - document.getElementById(`out-runway`).innerHTML = '-' - } - }) -} - -// trigger block creation every <blocktime> seconds by transferring 1 wei (useful for testrpc). -function keepBlockchainAlive(blocktime) { - window.setTimeout( () => { - web3.eth.sendTransaction( {to: web3.eth.accounts[0], value: 1}) - keepBlockchainAlive(blocktime) - }, blocktime * 1000) -} - -// UI init -document.addEventListener('DOMContentLoaded', () => { - console.log('DOM loaded') - - document.querySelector('#open-stream').onclick = onOpenStreamButton - document.querySelector('#close-stream').onclick = onCloseStreamButton - document.querySelector('#withdraw').onclick = onWithdrawButton - document.querySelector('#deposit').onclick = onDepositButton -}) - -window.addEventListener('load', () => { - console.log('window loaded') - - initContract().then( ret => { - this.contractaddr = ret.contractaddr - const networks = {1: 'mainnet', 3: 'ropsten', 4: {name: 'rinkeby', explorer: 'http://rinkeby.etherscan.io'}} - this.network = networks[ret.networkid] ? networks[ret.networkid] : {name: 'unknown', explorer: ''} - - console.log(`network-id: ${ret.networkid}`) - document.getElementById('network').innerHTML = `id ${ret.networkid} <a href="${network.explorer}" target="_blank">${network.name}</a>` - - document.getElementById('contractaddr').innerHTML = `<a href="${network.explorer}/token/${contractaddr}" target="_blank">${contractaddr}</a>` - document.getElementById('ownaddr').innerHTML = `<a href="${network.explorer}/token/${contractaddr}?a=${web3.eth.defaultAccount}" target="_blank">${web3.eth.defaultAccount}</a>` - - web3.version.getNode( (err, ret) => { - if(ret.toLocaleLowerCase().indexOf("testrpc") != -1) { - console.log('starting timer for dummy transaction in order to keep the chain going...') - keepBlockchainAlive(5) - } - }) - - streemETH.Transfer().watch( (err, ret) => { - console.log(`Transfer event: ${JSON.stringify(ret)}`) - }) - - streemETH.allEvents().watch( (err, ret) => { - console.log(`Event: ${JSON.stringify(ret)}`) - // example value of ret: - // {"address":"0xf73f6bd052061bb84913be57d5f7565b0aa38827","blockNumber":693587,"transactionHash":"0xf97f95ae04c98fb1be277ba6888e6bf8b77d360b1196f774c6e91cc9f8bba115","transactionIndex":0,"blockHash":"0x570a4102cdd5a9f30efbac1a8ff00f6054d4af4f9b092c1dda8d705904d8d957","logIndex":0,"removed":false,"event":"StreamOpened","args":{"_from":"0x1e8a58eaab8c001022921d60010ddeb57f01b674","_to":"0x54717fdd2d61dda38f60cf822c225fe65fc18e64","_perSecond":"2"}} - if(ret.transactionHash == window.pendingTx) { - document.getElementById('pendingtx').innerHTML = '' - window.pendingTx = null - document.getElementById('executedtx').innerHTML = `<a href="${network.explorer}/tx/${ret.transactionHash}" target="_blank">${ret.transactionHash}</a>` - } - }) - - // trigger once manually in order to init some of the UI fields - onNextBlock() - }) -}) \ No newline at end of file diff --git a/frontend/js/streemETH_contract.js b/frontend/js/streemETH_contract.js deleted file mode 100644 index 515a9c571437538138342cfe2eb2c86570c4495c..0000000000000000000000000000000000000000 --- a/frontend/js/streemETH_contract.js +++ /dev/null @@ -1,370 +0,0 @@ - -// !!! this is autogenerated by a setup script. Changes will be overwritten !!! -const contract = { - "contract_name": "StreemETH", - "abi": [ - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "decimals", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_settledBalance", - "outputs": [ - { - "name": "", - "type": "int256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "receiver", - "type": "address" - }, - { - "name": "perSecond", - "type": "uint256" - } - ], - "name": "openStream", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "a", - "type": "uint256" - }, - { - "name": "b", - "type": "uint256" - } - ], - "name": "min", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "closeStream", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_streamsLength", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "receiver", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "name": "dev_issueTo", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_outStream", - "outputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_inStream", - "outputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "dev_reset", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "inputs": [], - "payable": false, - "type": "constructor" - }, - { - "payable": true, - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "name": "amount", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - ], - "unlinked_binary": "0x606060405234156200001057600080fd5b5b6000604080519081016040908152600f82527f53747265616d696e67204574686572000000000000000000000000000000000060208301528051908101604052600481527f5345544800000000000000000000000000000000000000000000000000000000602082015260125b600084116200008957fe5b6003805461010060a860020a03191661010033600160a060020a03169081029190911790915560009081526004602052604081208590558490556001838051620000d8929160200190620001b1565b506002828051620000ee929160200190620001b1565b506003805460ff191660ff8316179055600780546001810162000112838262000237565b916000526020600020906004020160005b60806040519081016040908152600080835260208301819052908201819052606082015291905081518154600160a060020a031916600160a060020a03919091161781556020820151600182018054600160a060020a031916600160a060020a039290921691909117905560408201518160020155606082015181600301555050505b505050505b620002d9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001f457805160ff191683800117855562000224565b8280016001018555821562000224579182015b828111156200022457825182559160200191906001019062000207565b5b50620002339291506200026c565b5090565b815481835581811511620002665760040281600402836000526020600020918201910162000266919062000290565b5b505050565b6200028d91905b8082111562000233576000815560010162000273565b5090565b90565b6200028d91905b8082111562000233578054600160a060020a031990811682556001820180549091169055600060028201819055600382015560040162000297565b5090565b90565b61126580620002e96000396000f300606060405236156100e35763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde03811461015957806318160ddd146101e45780632e1a7d4d14610209578063313ce567146102215780635cc8ce331461024a57806364a80c0c1461026f57806370a08231146102935780637ae2b5c7146102c457806395d89b41146102ef5780639dad93821461037a578063a1365fda1461038f578063a9059cbb146103b4578063e13e2ecf146103d8578063e61b959e146103fc578063e8f8889014610445578063f408ebe91461048e575b6101575b33600160a060020a038116600090815260046020526040808220805434908101909155825481019092557fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c92919051600160a060020a03909216825260208201526040908101905180910390a15b565b005b341561016457600080fd5b61016c6104a3565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101a95780820151818401525b602001610190565b50505050905090810190601f1680156101d65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101ef57600080fd5b6101f7610541565b60405190815260200160405180910390f35b341561021457600080fd5b610157600435610547565b005b341561022c57600080fd5b6102346105f0565b60405160ff909116815260200160405180910390f35b341561025557600080fd5b6101f76105f9565b60405190815260200160405180910390f35b341561027a57600080fd5b610157600160a060020a0360043516602435610616565b005b341561029e57600080fd5b6101f7600160a060020a03600435166107f4565b60405190815260200160405180910390f35b34156102cf57600080fd5b6101f7600435602435610a18565b60405190815260200160405180910390f35b34156102fa57600080fd5b61016c610a32565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101a95780820151818401525b602001610190565b50505050905090810190601f1680156101d65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561038557600080fd5b610157610ad0565b005b341561039a57600080fd5b6101f7610be7565b60405190815260200160405180910390f35b34156103bf57600080fd5b610157600160a060020a0360043516602435610bee565b005b34156103e357600080fd5b610157600160a060020a0360043516602435610c78565b005b341561040757600080fd5b61040f610cc1565b6040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390f35b341561045057600080fd5b61040f610cfb565b6040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390f35b341561049957600080fd5b610157610d32565b005b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105395780601f1061050e57610100808354040283529160200191610539565b820191906000526020600020905b81548152906001019060200180831161051c57829003601f168201915b505050505081565b60005481565b80610551336107f4565b101561055957fe5b600160a060020a03331660008181526004602052604080822080548590039055815484900390915582156108fc0290839051600060405180830381858888f1935050505015156105a857600080fd5b7f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b653382604051600160a060020a03909216825260208201526040908101905180910390a15b50565b60035460ff1681565b600160a060020a0333166000908152600460205260409020545b90565b600061066461062433610e43565b608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610e85565b1561066b57fe5b6106b761062484610e96565b608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610e85565b156106be57fe5b60006106c9336107f4565b10156106d157fe5b6001600780548060010182816106e7919061119c565b916000526020600020906004020160005b60806040519081016040908152600160a060020a03338116835289166020830152810187905242606082015291905081518154600160a060020a031916600160a060020a03919091161781556020820151600182018054600160a060020a031916600160a060020a039290921691909117905560408201518160020155606082015160039091015550600160a060020a0333811660008181526005602090815260408083209690950395869055928816808252600690935283902084905592935091907f4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde06869085905190815260200160405180910390a35b505050565b600080600080600061080586610e96565b935061084b84608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610e85565b6108565760006108de565b6108de84608060405190810160409081528254600160a060020a039081168352600184015416602083015260028301548183015260039092015460608201529086906080905190810160409081528254600160a060020a0390811683526001808501549091166020840152600284015491830191909152600390920154606082015290610ed8565b5b92506108ea86610e43565b915061093082608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610e85565b61093b5760006109c3565b6109c382608060405190810160409081528254600160a060020a039081168352600184015416602083015260028301548183015260039092015460608201529084906080905190810160409081528254600160a060020a0390811683526001808501549091166020840152600284015491830191909152600390920154606082015290610ed8565b5b600160a060020a03871660009081526004602052604081205491925090840182900312156109ee57fe5b600160a060020a038616600090815260046020526040902054830181900394505b50505050919050565b6000818310610a275781610a29565b825b90505b92915050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105395780601f1061050e57610100808354040283529160200191610539565b820191906000526020600020905b81548152906001019060200180831161051c57829003601f168201915b505050505081565b6000806000610ade33610e43565b9250610b2483608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610e85565b1515610b2c57fe5b610b7083608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152611005565b60018501546002860154929450909250600160a060020a039081169133909116907f96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a190858560405180848152602001838152602001828152602001935050505060405180910390a36107ef336110d6565b5b505050565b6007545b90565b600081118015610c06575080610c03336107f4565b10155b1515610c0e57fe5b600160a060020a033381166000818152600460205260408082208054869003905592851680825290839020805485019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9084905190815260200160405180910390a35b5050565b60035433600160a060020a039081166101009092041614610c9857600080fd5b600160a060020a03821660009081526004602052604081208054830190558054820190555b5050565b600080600080610cd033610e43565b600181015460028201546003830154600160a060020a03909216965094504203925090505b50909192565b600080600080610d0a33610e96565b805460028201546003830154600160a060020a03909216965094504203925090505b50909192565b600160a060020a033381166000818152600460209081526040808320839055600582528083208390556006909152812055600354610100900490911614156101555760008054600160a060020a033316825260046020526040822055610d9a906007906111ce565b6007805460018101610dac838261119c565b916000526020600020906004020160005b60806040519081016040908152600080835260208301819052908201819052606082015291905081518154600160a060020a031916600160a060020a03919091161781556020820151600182018054600160a060020a031916600160a060020a039290921691909117905560408201518160020155606082015181600301555050505b5b565b600160a060020a038116600090815260056020526040812054600780549091908110610e6b57fe5b906000526020600020906004020160005b5090505b919050565b60008160600151151590505b919050565b600160a060020a038116600090815260066020526040812054600780549091908110610e6b57fe5b906000526020600020906004020160005b5090505b919050565b6000806000806000610ee98861113e565b9350610ef58888611155565b8015610f015750600186115b15610f0e57839450610ff9565b610f188851610e96565b9250610f5e83608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610e85565b610f69576000610fb8565b610fb883608060405190810160409081528254600160a060020a039081168352600180850154909116602084015260028401549183019190915260039092015460608201529089908901610ed8565b5b9150600460008951600160a060020a03168152602081019190915260400160009081205491508282011215610fea57fe5b610ff684838301610a18565b94505b5b505050509392505050565b60008060008060008061101a87886001610ed8565b935086604001518481151561102b57fe5b0492508660400151830291506110408761113e565b905081600460008951600160a060020a0316600160a060020a031681526020019081526020016000206000828254039250508190555081600460008960200151600160a060020a0316815260208101919091526040016000208054909101905582606088018181510190525042606088015111156110ba57fe5b808211156110c457fe5b81828203955095505b50505050915091565b600160a060020a03811660009081526005602052604090205460078054829081106110fd57fe5b906000526020600020906004020160005b508054600160a060020a0319908116825560018201805490911690556000600282018190556003909101555b5050565b60008160400151826060015142030290505b919050565b60008151600160a060020a03168351600160a060020a0316148015610a2957508160200151600160a060020a03168360200151600160a060020a0316145b90505b92915050565b8154818355818115116107ef576004028160040283600052602060002091820191016107ef91906111f3565b5b505050565b50805460008255600402906000526020600020908101906105ed91906111f3565b5b50565b61061391905b80821115611232578054600160a060020a03199081168255600182018054909116905560006002820181905560038201556004016111f9565b5090565b905600a165627a7a723058203f7a2124b2dd97ceb20e54d263206eaaf9f63dcfb87b1758e633c9cb402beeed0029", - "networks": {}, - "schema_version": "0.0.5", - "updated_at": 1502660913795 -} \ No newline at end of file diff --git a/frontend/js/streem_contract.js b/frontend/js/streem_contract.js deleted file mode 100644 index a87f11266d2bef93eb35710f12ff74cdf1f60821..0000000000000000000000000000000000000000 --- a/frontend/js/streem_contract.js +++ /dev/null @@ -1,991 +0,0 @@ - -// !!! this is autogenerated by a setup script. Changes will be overwritten !!! -const contract = { - "contract_name": "Streem", - "abi": [ - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "decimals", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_settledBalance", - "outputs": [ - { - "name": "", - "type": "int256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "receiver", - "type": "address" - }, - { - "name": "perSecond", - "type": "uint256" - } - ], - "name": "openStream", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "a", - "type": "uint256" - }, - { - "name": "b", - "type": "uint256" - } - ], - "name": "min", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "closeStream", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_streamsLength", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "receiver", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "name": "dev_issueTo", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_outStream", - "outputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dev_inStream", - "outputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "dev_reset", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "inputs": [ - { - "name": "initialSupply", - "type": "uint256" - } - ], - "payable": false, - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - ], - "unlinked_binary": "0x6060604052341561000f57600080fd5b604051602080611182833981016040528080519150505b60018054600160a060020a03191633600160a060020a03169081178255600090815260026020526040812083905582905560058054909181016100698382610103565b916000526020600020906004020160005b60806040519081016040908152600080835260208301819052908201819052606082015291905081518154600160a060020a031916600160a060020a03919091161781556020820151600182018054600160a060020a031916600160a060020a039290921691909117905560408201518160020155606082015181600301555050505b5061017b565b81548183558181151161012f5760040281600402836000526020600020918201910161012f9190610135565b5b505050565b61017891905b80821115610174578054600160a060020a031990811682556001820180549091169055600060028201819055600382015560040161013b565b5090565b90565b610ff88061018a6000396000f300606060405236156100d85763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100dd57806318160ddd14610168578063313ce5671461018d5780635cc8ce33146101b657806364a80c0c146101db57806370a08231146101ff5780637ae2b5c71461023057806395d89b411461025b5780639dad9382146102e6578063a1365fda146102fb578063a9059cbb14610320578063e13e2ecf14610344578063e61b959e14610368578063e8f88890146103b1578063f408ebe9146103fa575b600080fd5b34156100e857600080fd5b6100f061040f565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561012d5780820151818401525b602001610114565b50505050905090810190601f16801561015a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561017357600080fd5b61017b610446565b60405190815260200160405180910390f35b341561019857600080fd5b6101a061044c565b60405160ff909116815260200160405180910390f35b34156101c157600080fd5b61017b610451565b60405190815260200160405180910390f35b34156101e657600080fd5b6101fd600160a060020a036004351660243561046e565b005b341561020a57600080fd5b61017b600160a060020a03600435166105f8565b60405190815260200160405180910390f35b341561023b57600080fd5b61017b60043560243561081c565b60405190815260200160405180910390f35b341561026657600080fd5b6100f0610836565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561012d5780820151818401525b602001610114565b50505050905090810190601f16801561015a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156102f157600080fd5b6101fd61086d565b005b341561030657600080fd5b61017b610984565b60405190815260200160405180910390f35b341561032b57600080fd5b6101fd600160a060020a036004351660243561098b565b005b341561034f57600080fd5b6101fd600160a060020a0360043516602435610a15565b005b341561037357600080fd5b61037b610a59565b6040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390f35b34156103bc57600080fd5b61037b610a93565b6040518084600160a060020a0316600160a060020a03168152602001838152602001828152602001935050505060405180910390f35b341561040557600080fd5b6101fd610aca565b005b60408051908101604052600681527f53747265656d0000000000000000000000000000000000000000000000000000602082015281565b60005481565b600081565b600160a060020a0333166000908152600260205260409020545b90565b60006104bc61047c33610bd6565b608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610c18565b156104c357fe5b60006104ce336105f8565b10156104d657fe5b6001600580548060010182816104ec9190610f2f565b916000526020600020906004020160005b60806040519081016040908152600160a060020a03338116835289166020830152810187905242606082015291905081518154600160a060020a031916600160a060020a03919091161781556020820151600182018054600160a060020a031916600160a060020a0392909216919091179055604082015181600201556060820151600391820155600160a060020a03338116600081815260209384526040808220979096039687905591891680835260049093529084902085905593945092917f4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde0686915085905190815260200160405180910390a35b505050565b600080600080600061060986610c29565b935061064f84608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610c18565b61065a5760006106e2565b6106e284608060405190810160409081528254600160a060020a039081168352600184015416602083015260028301548183015260039092015460608201529086906080905190810160409081528254600160a060020a0390811683526001808501549091166020840152600284015491830191909152600390920154606082015290610c6b565b5b92506106ee86610bd6565b915061073482608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610c18565b61073f5760006107c7565b6107c782608060405190810160409081528254600160a060020a039081168352600184015416602083015260028301548183015260039092015460608201529084906080905190810160409081528254600160a060020a0390811683526001808501549091166020840152600284015491830191909152600390920154606082015290610c6b565b5b600160a060020a03871660009081526002602052604081205491925090840182900312156107f257fe5b600160a060020a038616600090815260026020526040902054830181900394505b50505050919050565b600081831061082b578161082d565b825b90505b92915050565b60408051908101604052600381527f5354520000000000000000000000000000000000000000000000000000000000602082015281565b600080600061087b33610bd6565b92506108c183608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610c18565b15156108c957fe5b61090d83608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610d98565b60018501546002860154929450909250600160a060020a039081169133909116907f96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a190858560405180848152602001838152602001828152602001935050505060405180910390a36105f333610e69565b5b505050565b6005545b90565b6000811180156109a35750806109a0336105f8565b10155b15156109ab57fe5b600160a060020a033381166000818152600260205260408082208054869003905592851680825290839020805485019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9084905190815260200160405180910390a35b5050565b60015433600160a060020a03908116911614610a3057600080fd5b600160a060020a03821660009081526002602052604081208054830190558054820190555b5050565b600080600080610a6833610bd6565b600181015460028201546003830154600160a060020a03909216965094504203925090505b50909192565b600080600080610aa233610c29565b805460028201546003830154600160a060020a03909216965094504203925090505b50909192565b600160a060020a0333811660008181526002602090815260408083208390556003825280832083905560049091528120556001549091161415610bd35760008054600160a060020a033316825260026020526040822055610b2d90600590610f61565b6005805460018101610b3f8382610f2f565b916000526020600020906004020160005b60806040519081016040908152600080835260208301819052908201819052606082015291905081518154600160a060020a031916600160a060020a03919091161781556020820151600182018054600160a060020a031916600160a060020a039290921691909117905560408201518160020155606082015181600301555050505b5b565b600160a060020a038116600090815260036020526040812054600580549091908110610bfe57fe5b906000526020600020906004020160005b5090505b919050565b60008160600151151590505b919050565b600160a060020a038116600090815260046020526040812054600580549091908110610bfe57fe5b906000526020600020906004020160005b5090505b919050565b6000806000806000610c7c88610ed1565b9350610c888888610ee8565b8015610c945750600186115b15610ca157839450610d8c565b610cab8851610c29565b9250610cf183608060405190810160409081528254600160a060020a03908116835260018401541660208301526002830154908201526003909101546060820152610c18565b610cfc576000610d4b565b610d4b83608060405190810160409081528254600160a060020a039081168352600180850154909116602084015260028401549183019190915260039092015460608201529089908901610c6b565b5b9150600260008951600160a060020a03168152602081019190915260400160009081205491508282011215610d7d57fe5b610d898483830161081c565b94505b5b505050509392505050565b600080600080600080610dad87886001610c6b565b9350866040015184811515610dbe57fe5b049250866040015183029150610dd387610ed1565b905081600260008951600160a060020a0316600160a060020a031681526020019081526020016000206000828254039250508190555081600260008960200151600160a060020a031681526020810191909152604001600020805490910190558260608801818151019052504260608801511115610e4d57fe5b80821115610e5757fe5b81828203955095505b50505050915091565b600160a060020a0381166000908152600360205260409020546005805482908110610e9057fe5b906000526020600020906004020160005b508054600160a060020a0319908116825560018201805490911690556000600282018190556003909101555b5050565b60008160400151826060015142030290505b919050565b60008151600160a060020a03168351600160a060020a031614801561082d57508160200151600160a060020a03168360200151600160a060020a0316145b90505b92915050565b8154818355818115116105f3576004028160040283600052602060002091820191016105f39190610f86565b5b505050565b5080546000825560040290600052602060002090810190610f829190610f86565b5b50565b61046b91905b80821115610fc5578054600160a060020a0319908116825560018201805490911690556000600282018190556003820155600401610f8c565b5090565b905600a165627a7a723058201701b6f1ba321331904375c9b7854d54f3bac56fa58c9d0fa519fa96f9008a1f0029", - "networks": { - "1500075197859": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - } - }, - "links": {}, - "address": "0x76c03c6b2fdff9e8e844d11f0378a8643f81445d", - "updated_at": 1500075248696 - }, - "1500076416500": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - } - }, - "links": {}, - "address": "0x7ccc84ae4e768c5236aea82c813e64b3959364dc", - "updated_at": 1500076430467 - }, - "1500328320998": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - "0x4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde0686": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - "0x96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a1": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - }, - "links": {}, - "address": "0x4fca1817c62482043aa5bb40f2a27c648189b0fc", - "updated_at": 1500330211886 - }, - "1500330430153": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - "0x4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde0686": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - "0x96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a1": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - }, - "links": {}, - "address": "0x08bf3bd538dbb8b0fcc1fc788bb514bade1848c6", - "updated_at": 1500330441330 - }, - "1500332143283": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - "0x4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde0686": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - "0x96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a1": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - }, - "links": {}, - "address": "0x4728135ad6078113537b473580b6d78448fe578d", - "updated_at": 1500332157181 - }, - "1501276036887": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde0686": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - "0x96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a1": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - }, - "links": {}, - "address": "0x0a037b287e417f1bcf20a672c62a518406fdef65", - "updated_at": 1501276125961 - }, - "1502015414746": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde0686": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - "0x96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a1": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - }, - "links": {}, - "address": "0x32301368794b10e2bdeb4514aa816e652a8fb80d", - "updated_at": 1502016946186 - }, - "1502030354068": { - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x4baaa557c21346b70bdc9482890b5d7e315f6a2123611e74004857ebecde0686": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - } - ], - "name": "StreamOpened", - "type": "event" - }, - "0x96c5271ec05cb2683bdc50cf109341f5a4e45b02907df1c23a8855bddbe030a1": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_perSecond", - "type": "uint256" - }, - { - "indexed": false, - "name": "_settledBalance", - "type": "uint256" - }, - { - "indexed": false, - "name": "_outstandingBalance", - "type": "uint256" - } - ], - "name": "StreamClosed", - "type": "event" - } - }, - "links": {}, - "address": "0x9e655462bc832ba58f92031ee2e6cf354caa1571", - "updated_at": 1502180973953 - } - }, - "schema_version": "0.0.5", - "updated_at": 1502180973953 -} \ No newline at end of file diff --git a/frontend/js/test.js b/frontend/js/test.js index c8f63317ce5e180764358c1774c80cbe4e040ff2..1f93dd50e639490117223c60f81dce6b13e57e4f 100644 --- a/frontend/js/test.js +++ b/frontend/js/test.js @@ -152,10 +152,16 @@ window.addEventListener('load', () => { // ############################################################################ +/* +NOTE: gas amounts for contract calls are hardcoded to an arbitrary value. +Should instead be inferred via gas estimation upfront. +*/ +const GASLIMIT = 200000 + // closes the outgoing streams of the test accounts // this will throw an expection for accounts without outstream. Doesn't hurt us. function close() { - applyForTestAccs(addr => {streem.closeStream({from: addr, gas: 200000}, (err, ret) => { + applyForTestAccs(addr => {streem.closeStream({from: addr, gas: GASLIMIT}, (err, ret) => { if(err) console.log(`closeStream failed for ${addr}`) })}) } @@ -169,28 +175,28 @@ function freeze() { function reset() { console.log('resetting...') - applyForTestAccs(addr => streem.dev_reset( {from: addr, gas: 2000000} )) //note that this is more gas! + applyForTestAccs(addr => streem.dev_reset( {from: addr, gas: GASLIMIT * 10} )) } // test: balances are correct function test1() { console.log('open stream1: speed 1 from addr0 to addr1') - streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('open stream2: speed 1 from addr1 to addr2') - streem.openStream(web3.eth.accounts[2], 1, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[2], 1, {from: web3.eth.accounts[1], gas: GASLIMIT}) } -// test: dryed out stream +// test: underfunded stream function test1a() { // ... console.log('closing stream1') - streem.closeStream({from: web3.eth.accounts[0], gas: 200000}) + streem.closeStream({from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('waiting 20 sec...') setTimeout( () => { console.log('closing stream2') - streem.closeStream({from: web3.eth.accounts[1], gas: 200000}) + streem.closeStream({from: web3.eth.accounts[1], gas: GASLIMIT}) }, 20000) // assert: bal(addr1) is 0, stream2 stalls } @@ -198,10 +204,10 @@ function test1a() { // test: underfunded stream function test2() { console.log('open stream1: speed 1 from addr0 to addr1') - streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('open stream2: speed 2 from addr1 to addr2') - streem.openStream(web3.eth.accounts[2], 2, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[2], 2, {from: web3.eth.accounts[1], gas: GASLIMIT}) // wait 10 // assert: bal(addr1) is 0, lab(addr2) is 5 @@ -212,54 +218,54 @@ function test2() { function test3() { console.log('open stream1: speed 1 from addr0 to addr1') - streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('open stream2: speed 1 from addr1 to addr0') - streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[1], gas: GASLIMIT}) } function test3a() { console.log('open stream1: speed 1 from addr0 to addr1') - streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('open stream2: speed 2 from addr1 to addr0') - streem.openStream(web3.eth.accounts[0], 2, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[0], 2, {from: web3.eth.accounts[1], gas: GASLIMIT}) } function test3b() { console.log('open stream1: speed 2 from addr0 to addr1') - streem.openStream(web3.eth.accounts[1], 2, {from: web3.eth.accounts[0], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 2, {from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('open stream2: speed 1 from addr1 to addr0') - streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[1], gas: GASLIMIT}) } function test3c() { console.log('open stream1: speed 2 from addr1 to addr2') - streem.openStream(web3.eth.accounts[2], 2, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[2], 2, {from: web3.eth.accounts[1], gas: GASLIMIT}) console.log('open stream2: speed 1 from addr2 to addr1') - streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[2], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[2], gas: GASLIMIT}) } function test4() { console.log('open stream1: speed 1 from addr0 to addr1') - streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('open stream2: speed 1 from addr1 to addr2') - streem.openStream(web3.eth.accounts[2], 1, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[2], 1, {from: web3.eth.accounts[1], gas: GASLIMIT}) console.log('open stream3: speed 1 from addr2 to addr0') - streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[2], gas: 200000}) + streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[2], gas: GASLIMIT}) } function test4a() { console.log('open stream1: speed 1 from addr0 to addr1') - streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: 200000}) + streem.openStream(web3.eth.accounts[1], 1, {from: web3.eth.accounts[0], gas: GASLIMIT}) console.log('open stream2: speed 2 from addr1 to addr2') - streem.openStream(web3.eth.accounts[2], 2, {from: web3.eth.accounts[1], gas: 200000}) + streem.openStream(web3.eth.accounts[2], 2, {from: web3.eth.accounts[1], gas: GASLIMIT}) console.log('open stream3: speed 1 from addr2 to addr0') - streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[2], gas: 200000}) + streem.openStream(web3.eth.accounts[0], 1, {from: web3.eth.accounts[2], gas: GASLIMIT}) } \ No newline at end of file