brew install node
npm install -g ethereumjs-testrpc
package.json:
{
"dependencies": {
"web3": "0.17.0-alpha"
}
}
testrpc // http://localhost:8545
node // node console
var Web3 = require("web3")
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
web3.eth.accounts
package.json:
{
"dependencies": {
"web3": "0.17.0-alpha",
"ethereumjs-util": "4.5.0"
}
}
testrpc // http://localhost:8545
node // node console
var Web3 = require("web3")
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
web3.sha3("This is my secret")
// '0x754cd47e34c9f614f9f395463a016ee13a774ea969e17fc345d4dc57685fcb15' // private key
node ./keypairs.js 754cd47e34c9f614f9f395463a016ee13a774ea969e17fc345d4dc57685fcb15
// 0x2c84edeffb46141befe2bffe3ae510acecabfcb1 // Ethereum address
// keypairs.js
var EthUtil = require("ethereumjs-util")
var hexToBytes = function(hex) {
for (var bytes = [], c = 0; c < hex.length; c+=2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
var privateKeyToAddress = function(privateKey) {
return `0x${EthUtil.privateToAddress(hexToBytes(privateKey)).toString('hex')}`
}
console.log(privateKeyToAddress(process.argv[2]))
- http://gavwood.com/paper.pdf
- http://ethereum.stackexchange.com/questions/119/what-opcodes-are-available-for-the-ethereum-evm
- https://docs.google.com/spreadsheets/d/1m89CVujrQe5LAFJ8-YAUCcNK950dUzMQPMJBxRtGCqs/edit // op codes prices
- http://ethstats.net // gas price
web3.toWei(20, "gwei")
web3.fromWei(100000, "ether")
package.json:
{
"dependencies": {
"web3": "0.17.0-alpha",
"ethereumjs-util": "4.5.0",
"ethereumjs-tx": "1.1.2"
}
}
testrpc // http://localhost:8545
node // node console
var Web3 = require("web3")
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
web3.eth.getBalance(web3.eth.accounts[0])
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]), "ether")
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]), "ether").toNumber()
web3.eth.sendTransaction({
from: web3.eth.accounts[0],
to: web3.eth.accounts[1],
value: web3.toWei(1, "ether"),
gasLimit: 21000,
gasPrice: 20000000000
})
// '0x2dad8a5f98d1c3d1571a88fe1b2576988d2a104f88c894a8500cc4f06f6a1fea' // transaction id
web3.eth.getTransaction("0x2dad8a5f98d1c3d1571a88fe1b2576988d2a104f88c894a8500cc4f06f6a1fea")
web3.eth.getTransactionCount(web3.eth.accounts[0]) // could be used as next nonce value
var EthTx = require("etheremjs-tx")
var pKey1x = new Buffer("c16d3d2ff6bd28f830f26a69e85db439cb131c51e4c37fb9ef5278e003761d35", "hex")
var rawTx = {
nonce: web3.toHex(web3.eth.getTransactionCount(web3.eth.accounts[0])),
to: web3.eth.accounts[1],
gasPrice: web3.toHex(20000000000),
gasLimit: web3.toHex(21000),
value: web3.toHex(web3.toWei(25, "ether")),
data:""
}
var tx = new EthTx(rawTx)
tx.sign(pKey1x)
tx.serialize().toString("hex")
web3.eth.sendRawTransaction(`0x${tx.serialize().toString("hex")}`, (error, transactionId) => {})
- https://etherscan.io/
- https://www.myetherwallet.com/
- https://metamask.io/
- https://www.shapeshift.io/
Use an endpoint generated by infura.io to get access to main Etehreum network. Use https://etherscan.io/ to browse through transactions.
package.json:
{
"dependencies": {
"web3": "0.17.0-alpha",
"solc": "^0.4.4"
}
}
testrpc // http://localhost:8545
node // node console
var Web3 = require("web3")
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
var solc = require("solc")
// HelloWorld.sol
contract HelloWorld {
function displayMessage() constant returns (string) {
return "Hello from a smart contract";
}
}
var source = "" // contract source code
var compiled = solc.compile(source)
compiled.contracts[':HelloWorld'].bytecode // EVM bytecode
compiled.contracts[':HelloWorld].opcodes
var abi = JSON.parse(compiled.contracts[':HelloWorld].interface)
var helloWorldContract = web3.eth.contract(abi)
// deploy contract to testrpc
var deployed = helloWorldContract.new({
from: web3.eth.accounts[0],
data: compiled.contracts.HelloWorld.bytecode,
gas: 4700000, // use https://github.com/ethereum/browser-solidity
gasPrice: 20000000000,
}, (error, contract) => {})
deployed.address // Deployed contract will have its own address (see testrpc output)
deployed.displayMessage.call()
package.json:
{
"dependencies": {
"web3": "0.17.0-alpha",
"solc": "^0.4.4"
}
}
// Escrow.sol
contract Escrow {
address public buyer;
address public seller;
address public arbiter;
function Escrow(address _seller, address _arbiter) {
buyer = msg.sender;
seller = _seller;
arbiter = _arbiter;
}
function payoutToSeller() {
if(msg.sender == buyer || msg.sender == arbiter) {
seller.send(this.balance);
}
}
function refundToBuyer() {
if(msg.sender == seller || msg.sender == arbiter) {
buyer.send(this.balance);
}
}
function getBalance() constant returns (uint) {
return this.balance;
}
}
var source = "" // contract source code
var buyer = web3.eth.accounts[0]
var seller = web3.eth.accounts[1]
var arbiter = web3.eth.accounts[2]
var compiled = solc.compile(source)
var bytecode = compiled.contracts[':Escrow'].bytecode
var abi = JSON.parse(compiled.contracts[':Escrow'].interface)
var escrowContract = web3.eth.contract(abi)
var deployed = escrowContract.new(seller, arbiter, {
from: buyer,
data: bytecode,
gas: 4700000,
gasPrice: 20000000000,
value: web3.toWei(5, "ether")
}, (error, contract) => {})
deployed.address
deployed.buyer.call() // calling public getter
var balance = (account) => { return web3.fromWei(web3.eth.getBalance(account), "ether").toNumber() }
balance(deployed.address)
deployed.payoutToSeller({ from: buyer })
// Config
global.config = {
rpc: {
host: "localhost",
port: "8545"
}
}
// Load Libraries
global.solc = require("solc")
global.fs = require("fs")
global.Web3 = require("web3")
// Connect Web3 Instance
global.web3 = new Web3(new Web3.providers.HttpProvider(`http://${global.config.rpc.host}:${global.config.rpc.port}`))
// Global Account Accessors
global.acct1 = web3.eth.accounts[0]
global.acct2 = web3.eth.accounts[1]
global.acct3 = web3.eth.accounts[2]
global.acct4 = web3.eth.accounts[3]
global.acct5 = web3.eth.accounts[4]
// Helper Functions
class Helpers {
contractName(source) {
var re1 = /contract.*{/g
var re2 = /\s\w+\s/
return source.match(re1).pop().match(re2)[0].trim()
}
createContract(source, options={}) {
var compiled = solc.compile(source)
var contractName = this.contractName(source)
var contractToDeploy = compiled.contracts[`:${contractName}`]
var bytecode = contractToDeploy.bytecode
var abi = JSON.parse(contractToDeploy.interface)
var contract = global.web3.eth.contract(abi)
var gasEstimate = global.web3.eth.estimateGas({ data: bytecode })
var deployed = contract.new(Object.assign({
from: global.web3.eth.accounts[0],
data: bytecode,
gas: gasEstimate,
gasPrice: 5
}, options), (error, result) => { })
return deployed
}
loadContract(name) {
var path = `./${name.toLowerCase()}.sol`
return fs.readFileSync(path, 'utf8')
}
deployContract(name, options={}) {
var source = this.loadContract(name)
return this.createContract(source, options)
}
etherBalance(contract) {
switch(typeof(contract)) {
case "object":
if(contract.address) {
return global.web3.fromWei(global.web3.eth.getBalance(contract.address), 'ether').toNumber()
} else {
return new Error("cannot call getEtherBalance on an object that does not have a property 'address'")
}
break
case "string":
return global.web3.fromWei(global.web3.eth.getBalance(contract), 'ether').toNumber()
break
}
}
}
// Load Helpers into Decypher namespace
global.decypher = new Helpers()
// Start repl
require('repl').start({})
contract Flipper {
enum GameState {noWager, wagerMade, wagerAccepted}
GameState public currentState;
modifier onlyState(GameState expectedState) { if(expectedState == currentState) { _; } else { throw; } }
function Flipper() {
currentState = GameState.noWager;
}
function makeWager() onlyState(GameState.noWager) returns (bool) {
// ...
currentState = GameState.wagerMade;
return true;
}
function acceptWager() onlyState(GameState.wagerMade) returns (bool) {
// ...
currentState = GameState.wagerAccepted;
return true;
}
function resolveBet() onlyState(GameState.wagerAccepted) returns (bool) {
// ...
currentState = GameState.noWager;
return true;
}
}
web3.eth.blockNumber
web3.eth.getBlock(3)
contract Flipper {
enum GameState {noWager, wagerMade, wagerAccepted}
GameState public currentState;
uint public wager;
address public player1;
address public player2;
uint public seedBlockNumber;
modifier onlyState(GameState expectedState) { if(expectedState == currentState) { _; } else { throw; } }
function Flipper() {
currentState = GameState.noWager;
}
function makeWager() onlyState(GameState.noWager) payable returns (bool) {
wager = msg.value;
player1 = msg.sender;
currentState = GameState.wagerMade;
return true;
}
function acceptWager() onlyState(GameState.wagerMade) payable returns (bool) {
if(msg.value == wager) {
player2 = msg.sender;
seedBlockNumber = block.number;
currentState = GameState.wagerAccepted;
return true;
} else {
throw;
}
}
function resolveBet() onlyState(GameState.wagerAccepted) returns (bool) {
uint256 blockValue = uint256(block.blockhash(seedBlockNumber));
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
uint256 coinFlip = uint256(uint256(blockValue) / FACTOR); // Either 0 or 1 (50%/50%)
if(coinFlip == 0) {
player1.send(this.balance);
} else {
player2.send(this.balance);
}
currentState = GameState.noWager;
return true;
}
}