UPDATE: I have created a for you to play around with that showcases most of the stuff covered in this article.
I routinely build web applications that use and I think I take for granted the amazing toolset that I use every day. Our ecosystem is growing rapidly and I think a lot of newcomers are feeling overwhelmed. Ethereum is an amazing technology, but it is also nascent and there simply hasn’t been enough time for expertise to sufficiently permeate. I want people to know that Ethereum development is actually very compatible with modern web developer workflows — it’s relatively easy to integrate Ethereum functionality into any web application, and you can start today.
Because I fancy myself a champion of Ethereum on a mission to show mainstream developers the light, I have decided to put a bunch of scattered knowledge into one place (not very decentralized, I know). You will of course need to consult the proper documentation at each step, but my hope is that this article will show you how everything, more or less, fits together. If you’re ready to learn, please let me be your spirit guide. Come join the Ethereum ecosystem and help us conquer the world.There are lots of clients to choose from, but I suggest not yet worrying about vs vs (the up and coming python client — represent!). For everyone who just wants a freaking blockchain so they can start building stuff (e.g. you), I suggest for all your development needs. Once you have it installed, you can start it with:
testrpcCongratulations, you now have a blockchain. Note that by default testrpc does not mine blocks, but the -b
flag allows you to specify a block interval (e.g. 1 second). I like this configuration for a bunch of reasons I won’t get into, but just keep in mind that it is available.
Once you have your blockchain spinning, you need a way to talk to it. You have probably already downloaded . If you haven’t, you must be really new. Well, go ahead and make sure you have web3 installed, then open up a config.js
file and put this in it:
The X
(i.e. whatever web3 API function you want) can be found .
I’ll save you some time here: you’re going to be using to write smart contracts. If you think smart contracting is scary, don’t. For many applications, it’s actually really easy as long as you follow one rule: keep your contracts simple.
There are 2 reasons you want to always always always keep your contracts as absolutely stupid simple as is humanly possible:
If you haven’t heard of , you should definitely check that out now. I like to manage my tester contracts in a truffle directory. The neat thing about this is that you can easily work it into your testing framework. Consider this script in package.json:
Note that your truffle tests are “special” in that they inject a bunch of cool blockchainy stuff into your testing scope. There are a variety of ways to pass this information to the rest of your test suite. I personally use a truffle test to save the contract addresses into a config file and then import that config into my regular mocha tests. As long as I have the proper addresses, I can interact with my contracts in any test via web3.js. Anyway, you’ll figure out what works best for you.
Back to the main show. You can deploy your smart contract(s) by going to your truffle directory and typing: truffle deployNote that testrpc must be running in another window!
This will print the address of your freshly deployed contract, which you will need later. As I mentioned, you can always save this address programmatically in a truffle test, but for now you can just copy and paste it into your config.js
file:
The first thing to note is that everything must be in hex (see appendix for more details). Numbers, strings, etc. The second thing to note is that words in Ethereum are 256 bits. This means you need to left-pad everything with zeros to 64 characters. The third thing to note is that types must be declared canonically in the function definition.
Okay this is getting really neckbeardy. Let’s go through an example:
Let’s say you want to add 1
and 2
. Here’s how you call this function:
1: Take the first 4 bytes of the keccak 256 hash of your tightly packed, canonical function definition.
Say what? Well, I didn’t make this up, but you can just type your function declaration into and take the first 8 characters. What do I mean by canonical? Well, in Ethereum there are canonical types and shorthand types (e.g. uint256
is uint
’s canonical type). I actually don’t know where they’re all defined, but check out the for examples as well as .
2: Pad your parameters to 256 bits
This one’s a little easier to get a grasp on: x=1 is: 0000000000000000000000000000000000000000000000000000000000000001 y=2 is: 0000000000000000000000000000000000000000000000000000000000000002 And together they are: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023: Pack everything together and add a _0x_
prefix
After that, you should get back 3
for res
. Actually, you’ll get a BigNumber
object:
You should probably to learn more about why you should use BigNumber
s throughout your app.
Wait, we’re not done yet! I have only just shown you how to call a contract. But what if you want to write to it (i.e. update state)? The above will not work! You need to sign a transaction with your private key, but before that, you need some ether.
Important note: we are actually sending _1 ether_
which is the same as _10^18 wei_
. We always make calls/transactions with wei values.
To keep things simple, let’s just pretend I have this variable hardcoded in my ever growing config.js
:
Obligatory reminder: never share your private key, upload it to github, or publish it on Medium if there is or will ever be any money on it.
Back to the test, you can see that ether is being moved from accounts[0]
, which by default has a bunch of ether, to me.addr
, which is in your config file.
value
payable
modifier in solidity) — value
will be sent and you will also have to pay for gas.
Note the second _if_
statement, which is necessary because adding and subtracting in solidity can lead to numerical overflow and underflow — be careful! Also note the undeclared _msg_
object living in your function scope. This has all sorts of neat stuff you can reference in your function.
The balance of
msg.sender
's account, within the scope of this contract, has been increased bybalance
.
We don’t have the power to update state ourselves, so we need a miner to do it for us. We pay him or her for this service with gas
, which translates to ether.
And we use this data to form an unsigned transaction:
As mentioned above, gas
is required to make a transaction (i.e. update the state). gas * gasPrice
is the amount of wei the miner can possibly spend to execute your transaction. If the operations cost more than what you provided, the transaction will not update the state and the miner will keep all your gas money. If less than the gas provided is used, you are refunded the remainder.
If we submit this object to the network, it will fail because there has been no proof that I am actually authorizing this transaction. Who knows, some stranger could be updating my balance to 1 billion (although it’s unclear why anyone would do that).
Anyway, what I need to do is sign the transaction with my private key. Remember that old thing hanging out in your config file that I told you not to share with anyone? Do this with it:
var Tx = require('ethereumjs-tx');
Now, finally, we can submit this to the blockchain via web3. It will return a transaction hash that is simply a hash of the transaction provided (this is, very importantly, not proof that the transaction was successful!)
var txHash = config.web3.eth.sendRawTransaction(raw_txn); Which looks something like this: 0xac8914ecb06b333a9e655a85a0cd0cccddb8ac627098e7c40877d27a130a7293 Now there’s one last step, which is strictly speaking optional, but important to verify that your transaction has been accepted and processed: getting your transaction receipt. var txReceipt = config.web3.eth.getTransactionReceipt(txHash);If this returns null
your transaction was not picked up (perhaps you signed with the wrong private key?). If it’s not null
, there may still be various other clues that your transaction failed that I won’t get into now.
Okay, just one clue — if your _gasUsed_
is equal to the total _gas_
sent, it means your function call failed. This means either 1. you didn’t provide enough gas and/or 2. your contract encountered a _throw_
.
If you liked this article, or come . Also check out my company, , because we do awesome stuff as well as my project, , which is using Ethereum to change the future of energy. If you want to join our mailing list, you can subscribe here:
—
Hex strings:
I realized I didn’t choose the best example for hexadecimal numbers (since 1
is the same value in both hex and base10 notation). If you were to instead call our add
function with this as one of the parameters:
You would actually be adding 256
. So probably what’s good practice for any function call is to do the following:
Keys and profiles
If you’re stuck on how to generate keys, you can go ahead and look at this file I use in my apps:
This will save a keystore that you name in a file called test/keys.json
. You can run it with plain old node keygen.js <account_name>
and you should be good. I use this for test accounts, but you can reuse the functions if you need to e.g. automatically generate accounts.