As of 10-dec-14 this tutorial is no longer up to date with the latest POC 7 feature set - please checkout the updated tutorials starting with this oneIntroduction
This tutorial is the result of many days of studying best practices on how to leverage what's available on Ethereum now, and making the technology available to users
today, several months away from the network go live date (March 2015). For this reason, keep in mind development practices are likely to change heavily throughout the next few months, and the below is in no way indicative of what you should expect from the finished product. I have also kept a very narrow focus and omitted much information. For more advanced documents please instead refer to 'further reading' at the bottom of this page.
And now, onwards to a decentralized web! Please join us on
IRC if you have questions!
The basics
Ethereum enables the decentralized web, referred to as 'web 3'. What makes it different from web 2 is that on Ethereum, there are no webservers, and therefore no middlemen to take commissions, steal your data or offer it to the NSA, and of course nothing to DDoS.
A dapp ('decentralized app') consists of two parts: a frontend, written in HTML or QML, and a backend (think of it as the 'database' for your frontend). We'll focus here on an HTML dapp.
Good news: if you like bootstrap, or any other framework, you can continue using them, as the frontend of dapps have full network access, and CDNs are accessible. In fact, for all intent and purposes, developing a frontend for a dapp written HTML is the exact same as developing a website, and converting from web 2 to web 3 is in many cases trivial.
Even better news: you get reactive programming baked in (which should please angular, meteor and derby fans), by simply using callback functions, and there's no new framework to learn.
Even even better news: because Ethereum relies on cryptographic principles to function, every dapp knows the pseudonymous identity of each user. That's right, users won't need to 'create accounts' or 'log on' to access your dapps, and you can think of this as openID by default, everywhere.
There is no bad news, except maybe for the bad actors from the web 2 world, such as dishonest exchanges running with the money or gambling sites falsifying random number information to make a quick buck. On Ethereum, the backend operations are validated by all nodes on the network, meaning that a backend will always will do what its code says it does. This is why you might have heard people call Ethereum 'trustless' - there's no need for users to trust into a central authority to 'do the right thing'.
Installing the client
Important Note: The client is in a constant state of flux, and the development version which you will be using is updated almost every day. To insure that the tutorial works for you, make sure that you are running the very latest version (it's a simple matter of upgrading every day as a matter of habit, please see the individual tutorials on how to do so).
We'll be using AlethZero, the C++ implementation of Ethereum designed for developers. In particular, we're going to install the 'development' version, which contains all the latest goodies.
OS X users: please follow this
guide. You can stop following the tutorial after you executed the
brew linkapps
command, then come back here.
Ubuntu users: please follow this
guide. While a bit less user-friendly to install than its OS X counterpart, AlethZero is developed on ubuntu and therefore works very well on this platform.
Windows users: while it is
possible to build AlethZero on Windows, at this point in time it is far too complex considering the beginner scope of this tutorial. Instead, if you do not have access to an OS X or linux computer, use a virtual machine and boot Ubuntu.
A quick overview of AlethZero
If all went well, you should see something like this after you start AlethZero, depending on your platform and screen resolution:
If your mileage varies, and not all the interface is visible, manually close all panes in the display by clicking their 'x' symbols until they are all gone, resize the screen to fit your resolution and re-add them manually by right clicking just below the titlebar (and just to the right of the 'refresh' button).
What's going on here? At the center of the screen is a browser window, a Webkit view to be exact. You can browse the existing web from there, just like any other browser, try google for example.
The rest of the panels contain debug and technical information that we'll make use of a bit later. While useful for developers, this is not a very-user friendly interface, so the final Ethereum browser, tentatively called 'Mist' and build on top of the
Go Ethereum implementation, will have a completely different look and feel. In fact, it's likely that once Ethereum is launched, the etherbrowser will look a bit like this:
The above is a concept of a potential look and feel for the etherbrowser, accessing a dapp that itself acts as a dapp store.
As far as options are concerned, feel free to reorganize your screen a bit. You can also drag and drop panels on top of each other to 'stack' them.
So, now that we have made ourselves at home, let's build our frontend, but... what should we build?
Choices, choices
Ethereum is a generalist programming platform. You can build games, financial applications, gambling apps, insurance companies, social networks, well, anything really! That said, it's always good to keep in mind your users' needs first and foremost, so what do you think they are missing from the centralized web? Well, trust of course! (as some iCloud users recently learned the hard way).
So, for today's tutorial we'll write a simple application that functions a bit like a bank, but with a transparent ledger that the whole world can audit. We'll issue 10,000 tokens, and because it wouldn't be much fun to keep all the tokens for ourselves, we'll also create a function that allows us to send them to our friends.
This way, we are issuing our own money (in a very basic way, but still). In the web 2 world it would be similarly trivial to build such an app in PHP and MySql, but your users would have to trust you with being an honest accountant, that your ledger stay consistent, that the government wouldn't 'help' itself with some tokens, that hackers wouldn't break into your server, that your employees would be honest at all times and hadn't planted a backdoor, or that your programmers wouldn't have made a single mistake, ever... well, you get the point.
Our frontend
Note: feel free to grab all the code from
https://github.com/stephantual/firstdapp or copy-paste the examples below.
Let's have a look at our interface:
This is of course pure HTML, but the eagle-eyed amongst you will have noticed we're using the
bootstrap framework to make the layout look a bit nicer.
Here's the full code:
<html>
<head>
<!-- updated 25/10/14 -->
<title>My Token</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js">
<script src="mytoken.js"></script>
</head>
<body>
<div class="header">
<h3 class="text-muted">My Token</h3>
</div>
<div class="jumbotron">
<h1>Balance: <strong id="balance"></strong></h1>
<br>
<div>
<div class="form-group">
<input id="receiverAddress" class="form-control" type="text" placeholder="Receiver address"></input><br>
<input id="amount" class="form-control" type="text" placeholder="Amount"></input><br>
</div>
<button class="btn btn-default" onclick="createTransaction();">Send some tokens!</button>
</div>
</div>
</body>
</html>
The code is straightforward: at the top, a balance placeholder
<strong id="balance"></strong>
, which we'll update dynamically using javascript a bit later on, located in a 'mytoken.js' file.
This is followed by a very simple form, with only two fields and a button. The first,
<input id="receiverAddress">
, will allow us to specify the account address we wish to send our tokens to. The second,
<input id="amount">
, specifies how many tokens will be sent.
Finally, a button that calls the (yet to be written) javascript function
createTransaction();
, which will call our backend and execute the transaction.
To load it in AlethZero, paste the code in a plain text editor and save it as 'myToken.html'. Then simply type the URL of the HTML file on your local hard drive in the AlethZero browser address bar, in my case: file:///Users/stephan/path/to/code/mytoken.html
Our backend
Our backend (referred to as a 'contract' in Ethereum) is going to use a language very similar to Python, amusingly called Serpent. There are several other contract languages you can use when building Ethereum backends, including Mutan (similar to Go), LLL (similar to Lisp) and Solidity (similar to C++). We'll use Serpent because it's easy and has many examples available to learn more from.
As we mentioned above, we're building a little bank, so we'll need to do two things:
1) Instantiate at least one balance with some tokens, to get things rolling when the contract is first created.
2) Build a 'send' function similar to
contract.send(account, amount)
in order to move funds around.
Let's dive in, and feel free to open your favorite text editor to edit your first contract!
def init():
self.storage[msg.sender] = 10000
def code():
to = msg.data[0]
from = msg.sender
value = msg.data[1]
if self.storage[from] >= value:
self.storage[from] = self.storage[from] - value
self.storage[to] = self.storage[to] + value
Don't panic, it's much simpler than it looks. Contracts are divided into two parts. The first section, entitled
init
, is code that initializes the contract, its default parameters during instantiation if you will. That initialisation code gets run only once when the contract is created, and never again.
The second part of the contract is the contract code itself, the stuff that will live forever on the Ethereum network, immutable, and backed by millions of nodes insuring it returns the expected results every time. In our case, it's a simple function that checks that the sender has a large enough balance and, if so, transfers the tokens from one account to the other.
Let's look at this is a bit more detail:
def init():
self.storage[msg.sender] = 10000
This is the initialization of our contract: it will only run once (because it's within the init block), and it does only one thing: initialize one account with a balance of 10,000 tokens. Storage in Ethereum contracts is structured as a key/value pair store: a key identifies where in the contract ledger the account lives, and requesting that key will return its value (in this case, 10,000).
Who's
msg.sender
you ask? Well, it's us! When we ask for the contract to be created we are the sender of the message, hence, we are
msg.sender
. This is a unique identifier on the network that cannot be forged, thanks to the cryptographic laws that Ethereum implements 'under the hood'.
Good, so now we have assigned ourselves an initial balance, let's have a look at the 'send' function, which will be executed each time we call the contract from now on. Note that because our contract in this particular case has only one function, we didn't bother naming the function
send
, it's assumed that every call to the contract will involve sending tokens.
def code():
to = msg.data[0]
from = msg.sender
value = msg.data[1]
if self.storage[from] >= value:
self.storage[from] = self.storage[from] - value
self.storage[to] = self.storage[to] + value
The first three lines are variable definitions: you probably noticed that this time the value of
msg.sender
is assigned to the variable
from
, which makes sense as it's the account calling the contract that is sending tokens.
The value
msg.data[0]
is assigned to the variable
to
. If you've ever written 'batch' programs, and you have a hunch this refers to the first argument that is sent to that contract, you'd be right.
msg.data[0]
represents the first argument sent to the contract, a bit like a the first parameter to a function call. And
msg.data[1]
, as you probably guessed correctly, refers to the second argument.
To send tokens, we first check that the balance of the sender is higher or equal to the amount they are sending. This makes sense, you wouldn't want to send tokens that don't exist would you
This is of course handled by the if statement:
if self.storage[from] >= value:
If the balance checks out, we subtract the amount being sent from the sender balance:
self.storage[from] = self.storage[from] - value
, then add to the balance of the account receiving the tokens:
self.storage[to] = self.storage[to] + value
Voila! Our forum won't allow me to place more text in a single post, so I'm continuing in the comments (see below).
Comments
Don't run out of gas!
Before we go further, there is an important concept you need to understand that will help you master ethereum contracts: gas.Let's peek under the covers: in order to power the decentralized web, Ethereum cannot possibly rely on any centralized authority (because that authority could manipulate the database). Instead, every node that participates on the network hold a copy of a decentralized database, which they audit.
The network nodes process the code that is being executed in the database and come into agreement as to what the correct state of the database is through a vote. Majority always win the vote, and nodes are incentivized to do this verification work. Voting takes place at regular particular intervals, on average every 12.7 seconds.
The contract we have written earlier will be stored in this database. Contracts are triggered and executed when they are called by users or other contracts.
If you're thinking that this necessary approach presents limits in terms of processing speed, you'd be correct. The total processing power of the Ethereum network, regardless of the number of nodes that forms it, is equal to a single smartphone from 1999. This means that you're not going to want to store megabytes of data on the Ethereum network, or render 3d graphics. There are of course workarounds to this, including our storage solution called Swarm and our secure messaging protocol, Whisper, both companion technologies to Ethereum.
It also means that because computing power is limited, it has to be measured carefully so that no single actor can commit evil deeds such as running infinite loops on all the world's Ethereum nodes. This unit of measure is called 'gas'.
Gas comes into play when you try to make a contract do something. You 'call' a function of the contract, which then executes that function. It could be validating an escrow, or 'like' a friend on a decentralized social app, or transfer an amount of contract-specific token to another user, etc. Anything.
In order to execute this function, the contract will need gas, just like your car does. So, as part of the function call, you specify how much 'gas' you want to send to the contract, and how much you're willing to pay for that gas (priced in ether, Ethereum's fuel and unit of account).
The different operations a contract can support are priced differently. One execution cycle cost one gas for example. Others, like writing to storage, cost considerably more (because storage is a very scarce resource).
If you send too much gas to the contract, and it doesn't use all of it, it is refunded to you. If you send too little, the contract stops and rolls back (just like your car when it's 'out of gas').
How gas is priced depends on the global consensus of the community. It's therefore likely operations that have the best priced gas will be executed first on the network, and the rest a bit later.
Let's save our contract
Now that you understand Ethereum's basic principles, and that you have your first contract written up, it's time to save it on the Ethereum network.As mentioned previously, saving this contract or operating it will require ether, which at the moment we have 0 units of. In order to acquire a bit of ether, you need to participate in the voting process which guarantees the integrity of the decentralized database, a process referred to as 'mining'. Here's how:
First, we need to be connected to the network, so click 'Go!' in the menu bar. You should start seeing various tabs come alive with information. An interesting tab to have a look during this process is the 'Blockchain' one - each vote is recorded here and tagged with a number. We'll get back to this shortly.
In order to mine and earn your ether, select the 'Force Mining' option under the 'Debug' dropdown menu of the application bar. This is necessary for now but will probably be removed as the Ethereum clients evolve. Finally, press the 'Mine' button. You should see your balance in the bottom right of the screen increase slowly, denoted in finneys (each equivalent to 0.001 ether).
Once you are the proud holder of say 15000 Finneys, you can stop mining. Click 'mine' again to stop the process, then select again the 'Force Mining' option under the 'Debug' dropdown menu of the application bar to disable it. Now let's save our contract.
Open AlethZero and look for the tab called 'Transact'. If you can't see it, you can make it appear by right clicking below the menu bar and to the right of the 'Refresh' button. Once that's opened, paste the Serpent code we wrote earlier within the 'Data' textarea. It should look a bit like this:
Since we are trying to create a contract and not send ether to another account, you can safely leave all the fields to their default value. We'll be sending 10,000 gas to the contract priced at 10 Szabo each. A Szabo is a another unit of value, equivalent to 0.000001 ether. Since our contract creation code is so simple, we'll be refunded of the majority of this ether as the saving of the contract will not consume all the gas.
Note that Serpent, exactly like Python, is tab-sensitive. If you have used the wrong tabulation, even by just one character or space, the code will not compile. Check carefully, and if you have pasted the contract correctly, you should two messages in the pane just under your contract code. The first one is a message stating there was an LLL parse error, something you can safely dismiss (you wrote your contract in the Serpent language, not the LLL language, so this is normal). Second, a series of assembly-like instructions similar to 'PUSH2 0x27 0x10 CALLER...'. This is your contract code, in its compiled form.
Now that your contract is compiled, you just have to press the 'Execute' to save your contract in the decentralized database. But wait, this is a bit tricky due to a UI limitation in the current client, where information zooms by so fast it will be hard to identify our contract amongst the many others on the test network currently in operation.
Since you're not mining, and the testnet is so quiet at the present time, it's likely your contract creation will be 'pending'. Make sure you have the 'Pending' pane opened and you will see something like this:
Pardon the jargon, press 'Execute' in the transact pane and make a note of the 'creates' field for that particular transaction in the 'pending' pane, in this particular case, '45e3898696c360e6f76e98eb41c97715e4d65184' (it will be different for you, as each contract created has a unique ID).
Note that if the above strategy doesn't work, you could always send some specific amount of ether to the contract (in which case, the ether would belong to the contract itself), then locate it by studying balances in the 'Contracts' pane. A very small but recognisable amount such as 456 weis (the smallest of ether denomination) tends to work nicely.
Regardless of the method used, once you have written this down, press 'mine' again (so that the contract creation does go through) - and this time no need to 'force' mining. Wait for the transaction to disappear from the pending pane and your contract is now live on the Ethereum test network!
Connecting the dots
Now that we understand a bit more about how Ethereum works, we can connect our HTML frontend to our Serpent backend.In order to allow your dapp frontend to interact with the Ethereum network, AlethZero injects a javascript library containing a single object,
web3
, into the HTML of your application.web3
allows you to both inspect and interact with contracts, through functions such asweb3.eth.balanceAt(account)
orweb3.eth.transact(params)
.Here's the javascript code, linked earlier from your HTML. Don't worry, we'll dig in each line of code a bit later:
This style of asynchronous coding should be familiar to the node.js developers amongst you. Say for example you have a function that checks for the value of something that might take a while to return (a database call for example). Because you don't want your javascript to 'hang' and the page to stall while the system waits for a response, you instead pass it a callback method that gets triggered once the data has arrived. The callback method can be issued parameters that the asynchronous function will supply in due time.
If you're not sure you have fully grasped this concept, I recommend you read this short but excellent primer on stackoverflow before going further, as this is a technique that's used everywhere in Ethereum applications.
The first line of javascript simply assigns your newly created contract address to a variable called, well,
contractAddress
. Make sure you paste the address you wrote down earlier in its place, and make sure you carefully prefix it with '0x' as this is an hexadecimal value.Now that this is out of the way, let's have a look at the code that is going to watch our contract internal token balance and auto-update the placeholder we created earlier on: The outermost code 'watches' for changes to our contract referred to by its address,
contractAddress
. We remember that we had stored our token balance within the contract storage denoted using our account address:self.storage[msg.sender] = 10000
. The watch can include many different filters, but in this case we are only interested in changes to the key referring to our first (and only) public account address, retrieve usingweb3.eth.accounts[0]
.The innermost code simply updates
document.getElementById("balance").innerText
, our HTML field. We need to inspect the contract storage for the matching key, which is done usingweb3.eth.stateAt(contractAddress, web3.eth.accounts[0])
. Of course, since we haven't started sending tokens yet, this value is currently 10,000 as specified in our contract initialization and this is what will be displayed in our GUI.Finally, we wrap the return value of this lookup with
web3.toDecimal
, which converts the hexadecimal values stored in contracts to human-readable decimals.Good news, this was the hard part, and it's pretty much smooth sailings from there on. We just need to create the function that will get called when we press the 'Send some tokens' button: We create two variables, receiverAddress and amount, and assign them the value of their respective
input
fields. You could use any technique to retrieve these values, and even use jQuery or similar, but in this case we opted for a simplequerySelector()
.The next step is assembling the data message we'd like to send to our contract. The contract expects an array of value, which is exactly what we will send, creating the array using
var data = [receiverAddress, amount]
Finally, we need to call our and pass it this data message. The method
web3.eth.transact()
is used to send ether to another account, create a new contract or call a contract. It accepts an object of parameters, in this case:to
: the address of our contract, which we had earlier assigned to the variablecontractAddress
.data
: our data message, in the form of an array with two elements.gas
: the amount of gas, in this case 5000, most of it will be refunded to us as we won't use the full amountYou're all set! To try your dapp, use AlethZero to browse the HTML file, enter an account address (not yours of course, and a random string will do for testing purposes), an amount, and press the button. You'll find the amount decreases from your balance.
If you're experiencing problems, note a full set of developer tools are available by right-clicking the webkit pane and selecting 'inspect'. You can also have a brief look at the AlethZero log pane, but might need to increase the debug level by moving the slider within the pane a bit higher up, maybe to level 10 or similar.
Of course, without the EtherBrowser having been released, it's currently not possible to share your dapp with the rest of the world, but you could distribute it as a zip file. In fact, you only need to distribute the HTML and its assets, as there is no need to include the contract code itself, which is now live on the ethereum decentralized database.
Final note, if you'd like to receive tokens from me (let's call them StephanCoins), simply point your HTML at contract address '0x4aff3e4ee940e499e2d83f7f38ca982e1c770aab' , add me on skype at stephan.tual and I'll send you some!
All the code for this tutorial can be found on https://github.com/stephantual/firstdapp - feel free to raise Github issues if you find some (as the API is frequently updated).
Have fun!
Further Reading
Of course, the FAQ is pretty much mandatory reading.To learn more about the Serpent language, please consult its wiki.
To learn more about the Javascript bindings, please refer to this page, part of the C++ implementation's excellent wiki.
To understand how Ethereum works overall, please refer to the whitepaper.
Kenneth Kappler's excellent follow up to this tutorial covers more complex storage strategies.
--
Update history:
05-09-14: Document created
08-09-14: First draft released
14-09-14: Added more code
15-09-14: Cleaned up first half of the tutorial, added new content
17-09-14: Further new content
18-09-14: First public release
19-09-14: Corrected typos, thanks @thehighfiveghost
23-09-14: Updated screenshot of default AZ build, thanks @andygough1974
30-09-14: Minor update for 6.10
08-10-14: Minor update for PoC 7
16-10-14: Minor update to reference Ken Kappler's follow up tutorial
26-10-14: Major update to PoC 7 new Javascript bindings
28-10-14: Pushed tutorial code to github
06-11-14: Ken Kappler amended to reflect new serpent syntax
For anyone having trouble finding addresses for testing, if you double click an address in Owned Accounts (yours) or Accounts (everyone's), it pops them in the clipboard. Right click the toolbar to show/hide these two and all other panels.
Does anyone know how to create additional accounts? The AlethZero vid showed that this was possible in an earlier version at least, but I couldn't find it.
Does the gas price act as some form of transaction fee which in turn implies that all transactions will have at least some amount of ether cost associated with it, which the "consumer" (in this case the person who sends tokens to another account) has to pay?
Also why is the gas price specified by the person who calls a contracts function and not determined by the price of one processed byte? Surely if the gas price was linked to the value of a processed byte the person calling the contract function only needs to specify the total amount of gas he/she is willing to sacrifice for the function to execute and thus it is not necessary to specify the gas price when calling the transaction?
Hope my questions are making sense. I read through the example given on page 16 of the whitepaper but I still can't seem to grasp the use of specifying the gas price when calling a function of a contract.
a) Correct, modifying or adding to the blockchain (ie, seek consensus) cost gas which is currently paid in ether. Reading from it is of course free (as all full nodes have access to all the data locally).
b) The gas price is determined by the caller, and it's very likely we'll see gas price stabilize and be driven by market forces as the network sees more or less usage. The testnet has it set pretty high to prevent abuse. That said, you are correct in your assumption that the amount of gas needed for certain operations vary. Storing data is hundreds of times more expensive than say, doing a 1+1 piece of arithmetic in a contract. This scale is described in the yellow paper (http://gavwood.com/paper.pdf).
I think your question is, "why not just set the gas price to 0.00000000001 ether and be done with it, relying on this aforementioned scale of complexity to define what operation X costs, vs operation Y?"
Well, quite simply because there is a gas limit per block, which defines what a 'standard' CPU today is capable of processing during that timeframe. If ethereum was to become very popular all of a sudden, that fixed price could very well prove fatal to the network as everyone executes millions of contracts, forcing transactions to be postponed to the next block, then the next one, then the next one, etc... Variable gas prices allow for market forces to keep this in check down to what's 'acceptable' to miners.
For that reason, the Ethereum chain should (and will) very likely be used strictly as a consensus mechanism, while static, large data will be better suited for swarm and fast, ephemeral information will sit within whisper.
Would this mean that miners would be able to set a lower limit on what gas prices they find 'acceptable'? And what would be the 'order of execution' when executing the transactions regarding gas price? Would transactions with a higher specified gas price be executed first as this would be more 'profitable' to the miner?
Using POC6, OSX. Can't seem to make this tutorial work. Getting this in the log: "THIS FUNCTIONALITY IS DEPRECATED. DO NOT ASSUME ASCII/BINARY-STRINGS WILL BE ACCEPTED. USE eth.fromAscii()." When I load the html in browser.
I 'think' the contract was initialized and I copied the address from pending before turning on mining again.
Balance field never updates after hitting 'Send some tokens!'.
If the balance fields never updates, make sure you have mining on (not force mining, just mining), make sure your contract address is correctly updated in the HTML, and make sure you contract is online (it should be listed under the 'contracts' pane in AZ.
Serpent contract
init:
contract.storage[((msg.sender * 0x10) + 0x1)] = 0x1
contract.storage[((msg.sender * 0x10) + 0x2)] = 0x1
code:
toAsset = (msg.data[0] * 0x10) + 0x1
toDebt = (msg.data[0] * 0x10) + 0x2
fromAsset = (msg.sender * 0x10) + 0x1
fromDebt = (msg.sender * 0x10) + 0x2
value = msg.data[1]
if contract.storage[fromAsset] >= value:
contract.storage[fromAsset] = contract.storage[fromAsset] - value
else:
contract.storage[fromDebt] = value - contract.storage[fromAsset]
contract.storage[fromAsset] = 0
if contract.storage[toDebt] >= value:
contract.storage[toDebt] = contract.storage[toDebt] - value
else:
value = value - contract.storage[toDebt]
contract.storage[toAsset] = contract.storage[toAsset] + value
contract.storage[toDebt] = 0
HTML
Hours
//change this contract address to the one you have created!
var contractAddress = "0x022a6ef6cbbd383073c2c50feccc9565bd2c8da8"
var assetFrom = eth.secretToAddress(eth.key) + 1
var debtFrom = eth.secretToAddress(eth.key) + 2
function createTransaction() {
var receiverAddress = '0x' + document.querySelector("#receiverAddress").value;
var amount = document.querySelector("#amount").value
var data = eth.pad(receiverAddress, 32) + eth.pad(amount, 32);
eth.transact({from: eth.key, value: 0, to: contractAddress, data: data, gas: 5000, gasPrice: 100000}, function() {})
}
eth.watch({altered: {at: eth.secretToAddress(eth.key), id: contractAddress}}).changed(function() {
document.getElementById("contractAddress").innerText = contractAddress
document.getElementById("assetfrom").innerText = assetFrom
document.getElementById("debtfrom").innerText = debtFrom
document.getElementById("asset").innerText = eth.toDecimal(eth.stateAt(contractAddress, assetFrom))
document.getElementById("debt").innerText = eth.toDecimal(eth.stateAt(contractAddress, debtFrom))
});
Hours
Contract:Assets Account:
Assets: HRS
Debts Account:
Debt: HRS
Send!
View
Thank you for this, I think the tutorial is great.
However I have a problem: my "contract" never appears in the "contracts" pane no matter what I do. Therefore the "Balance" is always "0".
Looks like I did everything according to tutorial:
- created contract with valid example code (no compilation issues)
- added gas and ether to contract
- pressed execute button
- copied "Created" line from "Pending" tab
- enabled mining
The contract dissapears from "Pending" tab in a few seconds but never appears on "Contracts" tab.
What am I doin wrong?
(Please take above negatively by the way, I understand its early days and these things happen in the early days, so its all good)
I tried once again with the tutorial, this time I was not able to see the contract in "Contracts" tab again, but also my AlethZero crashes when I try to load html page from tutorial.
The exception is following:
"file:///home/alexey/ethereum/projects/tutorial/dapp.html"
alethzero: /home/alexey/ethereum/dependencies/libjson-rpc-cpp/src/jsonrpc/json/json_value.cpp:1065: const Json::Value& Json::Value::operator[](const char*) const: Assertion `type_ == nullValue || type_ == objectValue' failed.
Aborted (core dumped)
Looks like something indeed is broken. Surely it'd be nice to have some kind of unit-test system to prevent such regressions. Maybe I should consider contributing )
Could you please notify me when a stable build can be tested?