diff --git a/ethereum.php b/ethereum.php index 16901f7..1d59613 100755 --- a/ethereum.php +++ b/ethereum.php @@ -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 @@ -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() { @@ -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; } @@ -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) @@ -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)); } @@ -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')) { @@ -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; } @@ -497,4 +535,4 @@ function toArray() ) ); } -} \ No newline at end of file +} diff --git a/test/example.php b/test/example.php new file mode 100644 index 0000000..38b80a7 --- /dev/null +++ b/test/example.php @@ -0,0 +1,56 @@ +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'); +} + diff --git a/test/test.php b/test/test.php index 3247fd1..4afae26 100755 --- a/test/test.php +++ b/test/test.php @@ -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() @@ -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); @@ -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); @@ -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); @@ -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)); @@ -419,4 +419,4 @@ function errorHandler($errorNumber, $message, $file, $line, $context) } foreach(array("TestNetFunctions", "TestEthereumFunctions", "TestWhisperFunctions") as $c) - $t = new $c(); \ No newline at end of file + $t = new $c();