Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 67 additions & 29 deletions ethereum.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
*
* See Ethereum API documentation for more information:
* http://ethereum.gitbooks.io/frontier-guide/content/rpc.html
*
* >> require: bcmath
*/

require_once(dirname(__FILE__).'/json-rpc.php');

class Ethereum extends JSON_RPC
{
const DO_DECODE_HEX = true;
const NO_DECODE_HEX = false;

private function ether_request($method, $params=array())
{
try
Expand All @@ -24,16 +29,36 @@ private function ether_request($method, $params=array())
}
}

private function decode_hex($input)
public static function decode_hex($input)
{
if(substr($input, 0, 2) == '0x')
if(substr($input, 0, 2) == '0x') {
$input = substr($input, 2);

if(preg_match('/[a-f0-9]+/', $input))
return hexdec($input);
}

if(!preg_match('/[a-f0-9]+/', $input)) {
throw new Exception("invalid hex input");
}

return $input;
$sum = "0";
$len = strlen($input);
for ($i = 0; $i < $len; $i++) {
$c = hexdec($input{$i});
$sum = bcadd(bcmul($sum, 16), $c);
}
return $sum;
}

public static function encode_hex($decimal)
{
$alphabet = '0123456789abcdef';
$hex = [];
$remain = $decimal;
do {
$hex[] = $alphabet{bcmod($remain, 16)};
$remain = bcdiv($remain, 16);
} while (bccomp($remain, 0) > 0);
return '0x' . strrev(implode("", $hex));
}

function web3_clientVersion()
{
Expand Down Expand Up @@ -90,22 +115,22 @@ function eth_accounts()
return $this->ether_request(__FUNCTION__);
}

function eth_blockNumber($decode_hex=FALSE)
function eth_blockNumber($decode_hex=self::DO_DECODE_HEX)
{
$block = $this->ether_request(__FUNCTION__);

if($decode_hex)
$block = $this->decode_hex($block);
if($decode_hex == self::DO_DECODE_HEX)
$block = self::decode_hex($block);

return $block;
}

function eth_getBalance($address, $block='latest', $decode_hex=FALSE)
function eth_getBalance($address, $block='latest', $decode_hex=self::DO_DECODE_HEX)
{
$balance = $this->ether_request(__FUNCTION__, array($address, $block));

if($decode_hex)
$balance = $this->decode_hex($balance);
if($decode_hex == self::DO_DECODE_HEX)
$balance = self::decode_hex($balance);

return $balance;
}
Expand All @@ -115,24 +140,34 @@ function eth_getStorageAt($address, $at, $block='latest')
return $this->ether_request(__FUNCTION__, array($address, $at, $block));
}

function eth_getTransactionCount($address, $block='latest', $decode_hex=FALSE)
function eth_getTransactionCount($address, $block='latest', $decode_hex=self::DO_DECODE_HEX)
{
$count = $this->ether_request(__FUNCTION__, array($address, $block));

if($decode_hex)
$count = $this->decode_hex($count);
if($decode_hex == self::DO_DECODE_HEX)
$count = self::decode_hex($count);

return $count;
}

function eth_getBlockTransactionCountByHash($tx_hash)
function eth_getBlockTransactionCountByHash($tx_hash, $decode_hex=self::DO_DECODE_HEX)
{
return $this->ether_request(__FUNCTION__, array($tx_hash));
$count = $this->ether_request(__FUNCTION__, array($tx_hash));

if ($decode_hex == self::DO_DECODE_HEX)
$count = self::decode_hex($count);

return $count;
}

function eth_getBlockTransactionCountByNumber($tx='latest')
function eth_getBlockTransactionCountByNumber($tx='latest', $decode_hex=self::DO_DECODE_HEX)
{
return $this->ether_request(__FUNCTION__, array($tx));
$count = $this->ether_request(__FUNCTION__, array($tx));

if ($decode_hex == self::DO_DECODE_HEX)
$count = self::decode_hex($count);

return $count;
}

function eth_getUncleCountByBlockHash($block_hash)
Expand Down Expand Up @@ -198,6 +233,9 @@ function eth_getBlockByHash($hash, $full_tx=TRUE)

function eth_getBlockByNumber($block='latest', $full_tx=TRUE)
{
if (is_numeric($block)) {
$block = self::encode_hex($block);
}
return $this->ether_request(__FUNCTION__, array($block, $full_tx));
}

Expand Down Expand Up @@ -251,7 +289,7 @@ function eth_compileSerpent($code)
return $this->ether_request(__FUNCTION__, array($code));
}

function eth_newFilter($filter, $decode_hex=FALSE)
function eth_newFilter($filter, $decode_hex=self::DO_DECODE_HEX)
{
if(!is_a($filter, 'Ethereum_Filter'))
{
Expand All @@ -261,29 +299,29 @@ function eth_newFilter($filter, $decode_hex=FALSE)
{
$id = $this->ether_request(__FUNCTION__, $filter->toArray());

if($decode_hex)
$id = $this->decode_hex($id);
if($decode_hex == self::DO_DECODE_HEX)
$id = self::decode_hex($id);

return $id;
}
}

function eth_newBlockFilter($decode_hex=FALSE)
function eth_newBlockFilter($decode_hex=self::DO_DECODE_HEX)
{
$id = $this->ether_request(__FUNCTION__);

if($decode_hex)
$id = $this->decode_hex($id);
if($decode_hex == self::DO_DECODE_HEX)
$id = self::decode_hex($id);

return $id;
}

function eth_newPendingTransactionFilter($decode_hex=FALSE)
function eth_newPendingTransactionFilter($decode_hex=self::DO_DECODE_HEX)
{
$id = $this->ether_request(__FUNCTION__);

if($decode_hex)
$id = $this->decode_hex($id);
if($decode_hex == self::DO_DECODE_HEX)
$id = self::decode_hex($id);

return $id;
}
Expand Down Expand Up @@ -497,4 +535,4 @@ function toArray()
)
);
}
}
}
56 changes: 56 additions & 0 deletions test/example.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(E_ALL);
require_once(dirname(__DIR__) . '/ethereum.php');

$eth = new Ethereum('127.0.0.1', 8545);

function xlog($x, $prefix = '')
{
$s = var_export($x, true);
printf("%s%s\n", $prefix ? $prefix . ': ' : '', $s);
}

xlog($eth->web3_clientVersion(), 'version');
xlog($eth->web3_sha3('0x68656c6c6f20776f726c64'), 'sha3');

$coinbase = $eth->eth_coinbase();
xlog($coinbase, 'coinbase');

$accounts = $eth->eth_accounts();
xlog($accounts, 'accounts');

$balNum = $eth->eth_getBalance($accounts[0], 'latest');
xlog($balNum, 'balance');

$balHex = $eth->eth_getBalance($accounts[0], 'latest', Ethereum::NO_DECODE_HEX);
xlog($balHex, 'balance in hex');

$blkNum = $eth->eth_blockNumber();
xlog($blkNum, 'block number');

$blkHex = $eth->eth_blockNumber(Ethereum::NO_DECODE_HEX);
xlog($blkHex, 'block number in hex');

$block = $eth->eth_getBlockByNumber(6); #can be 'latest'
xlog($block, 'block');
xlog(Ethereum::decode_hex($block->number), 'block number');
xlog(Ethereum::decode_hex($block->gasLimit), 'gas limit');

$blockByHash = $eth->eth_getBlockByHash($block->hash);
$txCountByHash = $eth->eth_getBlockTransactionCountByHash($block->hash);
xlog($txCountByHash, 'txCountByHash');

$txCountByNum = $eth->eth_getBlockTransactionCountByNumber($block->number);
xlog($txCountByNum, 'txCountByNum');

$arr_tx = $block->transactions;
if (count($arr_tx) > 0) {
$tx = $arr_tx[0];
$txByHash = $eth->eth_getTransactionByHash($tx->hash);
xlog($txByHash, 'tx');
} else {
xlog('no transactions');
}

12 changes: 6 additions & 6 deletions test/test.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function NetVersion()

function IsListening()
{
$this->assertEqual($this->eth->net_listening(), TRUE);
$this->assertEqual($this->eth->net_listening(), Ethereum::DO_DECODE_HEX);
}

function HasPeers()
Expand Down Expand Up @@ -114,7 +114,7 @@ function Accounts()

function BlockNumber()
{
$blkNum = $this->eth->eth_blockNumber(TRUE);
$blkNum = $this->eth->eth_blockNumber(Ethereum::DO_DECODE_HEX);
$blkHex = $this->eth->eth_blockNumber();

$this->assertIsNumeric($blkNum);
Expand All @@ -126,7 +126,7 @@ function BlockNumber()
function AccountBalance()
{
$balHex = $this->eth->eth_getBalance($this->account, 'latest');
$balNum = $this->eth->eth_getBalance($this->account, 'latest', TRUE);
$balNum = $this->eth->eth_getBalance($this->account, 'latest', Ethereum::DO_DECODE_HEX);

$this->assertIsNumeric($balNum);
$this->assertIsHex($balHex);
Expand All @@ -143,7 +143,7 @@ function AccountStorage()
function AddressTransactionCount()
{
$countHex = $this->eth->eth_getTransactionCount($this->account, 'latest');
$countNum = $this->eth->eth_getTransactionCount($this->account, 'latest', TRUE);
$countNum = $this->eth->eth_getTransactionCount($this->account, 'latest', Ethereum::DO_DECODE_HEX);

$this->assertIsNumeric($countNum);
$this->assertIsHex($countHex);
Expand Down Expand Up @@ -179,7 +179,7 @@ function GetBlocks()
function GetTransactions()
{
// Get a recent block with some transactions
$blockNum = $this->eth->eth_blockNumber(TRUE);
$blockNum = $this->eth->eth_blockNumber(Ethereum::DO_DECODE_HEX);
do
{
$block = $this->eth->eth_getBlockByNumber('0x'.dechex(--$blockNum));
Expand Down Expand Up @@ -419,4 +419,4 @@ function errorHandler($errorNumber, $message, $file, $line, $context)
}

foreach(array("TestNetFunctions", "TestEthereumFunctions", "TestWhisperFunctions") as $c)
$t = new $c();
$t = new $c();