<?php

use kornrunner\Keccak;

if( !isset($globalsSet)) {
// Enforcing strict complience with file inclusion
exit('User should not call this file directly.');
}

if( !class_exists('kornrunner\Keccak',false) ) {

//error_log( 'LOADING KECCAK FILE: root: '.$theRootDir );

// This file is in the dsn directory
require_once($theRootDir.'/dsn/keccak.php');
//include 'keccak.php';

} //else {
//error_log( 'NOT LOADING KECCAK FILE: root: '.$theRootDir );
//}

/*
// This file is in the dsn directory
require_once($theRootDir.'/dsn/keccak.php');
//include 'keccak.php';
use kornrunner\Keccak;
*/

function callRpc($data)
{
	$url = "https://eth-rpc-api.thetatoken.org/rpc";
	$postdata = json_encode($data);

	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
	$result = curl_exec($ch);
	curl_close($ch);
	
	return $result;
}

function hex2decimal($numstring)
{
	$frombase = 16;
	$tobase = 10;
	$chars = "0123456789abcdefghijklmnopqrstuvwxyz";
	$tostring = substr($chars, 0, $tobase);
	$length = strlen($numstring);
	$result = '';
	for ($i = 0; $i < $length; $i++)
	{
		$number[$i] = strpos($chars, $numstring[$i]);
	}
	do
	{
		$divide = 0;
		$newlen = 0;
		for ($i = 0; $i < $length; $i++)
		{
			$divide = $divide * $frombase + $number[$i];
			if ($divide >= $tobase)
		{
			$number[$newlen++] = (int)($divide / $tobase);
			$divide = $divide % $tobase;
			} elseif ($newlen > 0)
			{
			$number[$newlen++] = 0;
			}
		}
		$length = $newlen;
		$result = $tostring[$divide] . $result;
	} while ($newlen != 0);
	return $result;
}

function decimal2hex($numstring)
{
	$frombase = 10;
	$tobase = 16;
	$chars = "0123456789abcdefghijklmnopqrstuvwxyz";
	$tostring = substr($chars, 0, $tobase);
	$length = strlen($numstring);
	$result = '';
	for ($i = 0; $i < $length; $i++)
	{
		$number[$i] = strpos($chars, $numstring[$i]);
	}
	do
	{
		$divide = 0;
		$newlen = 0;
		for ($i = 0; $i < $length; $i++)
		{
			$divide = $divide * $frombase + $number[$i];
			if ($divide >= $tobase)
		{
			$number[$newlen++] = (int)($divide / $tobase);
			$divide = $divide % $tobase;
			} elseif ($newlen > 0)
			{
			$number[$newlen++] = 0;
			}
		}
		$length = $newlen;
		$result = $tostring[$divide] . $result;
	} while ($newlen != 0);
	return $result;
}

function getBetween($string, $start = "", $end = ""){
    if (strpos($string, $start)) { // required if $start not exist in $string
        $startCharCount = strpos($string, $start) + strlen($start);
        $firstSubStr = substr($string, $startCharCount, strlen($string));
        $endCharCount = strpos($firstSubStr, $end);
        if ($endCharCount == 0) {
            $endCharCount = strlen($firstSubStr);
        }
        return substr($firstSubStr, 0, $endCharCount);
    } else {
        return '';
    }
}

function chainId()
{
	$data = array("jsonrpc" => "2.0","method" => "eth_chainId","params"=>[],"id"=>"1");
	$result = callRpc($data);
	$details = json_decode($result, true);
	$output= hex2decimal(substr($details['result'],2));
	return $output; 
}

function getBalance($address)
{
	
	$data = array("jsonrpc" => "2.0","method" => "eth_getBalance","params"=>array("$address","latest"),"id"=>"1");
	$result = callRpc($data);
	$details = json_decode($result, true);
	$output= number_format(hex2decimal(substr($details['result'],2))/1000000000000000000,2, '.', '');
	return $output; 
}

function gasPrice()
{
	$data = array("jsonrpc" => "2.0","method" => "eth_gasPrice","params"=>[],"id"=>"1");
	$result = callRpc($data);
	$details = json_decode($result, true);
	$output= hex2decimal(substr($details['result'],2));
	return $output; 
}

function blockNumber()
{
	$data = array("jsonrpc" => "2.0","method" => "eth_blockNumber","params"=>[],"id"=>"1");
	$result = callRpc($data);
	$details = json_decode($result, true);
	$output= hex2decimal(substr($details['result'],2));
	return $output; 
}

function getTransactionCount($address)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_getTransactionCount","params"=>array("$address","latest"),"id"=>"1");
	$result = callRpc($data);
	$details = json_decode($result, true);
	$output= hex2decimal(substr($details['result'],2));
	return $output; 
}

function sign($address,$message)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_sign","params"=>array("$address","$message"),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function signTransaction($from,$to,$gas,$gasPrice,$value,$data,$nonce)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_signTransaction","params"=>array("data"=>"$data","from"=>"$from","gas"=>"$gas","gasPrice"=>"$gasPrice","to"=>"$to","value"=>"$value"),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function sendTransaction($from,$to,$gas,$gasPrice,$value,$data,$nonce)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_sendTransaction","params"=>array("data"=>"$data","from"=>"$from","gas"=>"$gas","gasPrice"=>"$gasPrice","to"=>"$to","value"=>"$value"),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function sendRawTransaction($data)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_sendRawTransaction","params"=>array("data"=>"$data"),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function estimateGas($from,$to,$gas,$gasPrice,$value,$data,$nonce)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_estimateGas","params"=>array("data"=>"$data","from"=>"$from","gas"=>"$gas","gasPrice"=>"$gasPrice","to"=>"$to","value"=>"$value"),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function getBlockByHash($hash)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_getBlockByHash","params"=>array("$hash"),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function getBlockByNumber($block)
{
	$hexBlock = "0x". decimal2hex($block);
	$data = array("jsonrpc" => "2.0","method" => "eth_getBlockByNumber","params"=>array("$hexBlock",true),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function getTransactionReceipt($data)
{
	$data = array("jsonrpc" => "2.0","method" => "eth_getTransactionReceipt","params"=>array("$data"),"id"=>"1");
	$result = callRpc($data);
	return $result; 
}

function callFunction($contract,$function,$params)
{
	$function = str_replace(" ","",$function);
	$inputs = getBetween($function,"(",")");
	$inputsArray = explode (",", $inputs); 
	$paramsArray = explode (",", $params); 
	$count = count($inputsArray);
	$i = 0;
	foreach ($inputsArray as $input) {
		if ($input == "address"){ $dataArray[$i] = "000000000000000000000000".substr($paramsArray[$i],2); }
		if (substr($input, 0, 4) == "uint"){ $dataArray[$i] = str_pad(decimal2hex($paramsArray[$i]),64,"0",STR_PAD_LEFT); }
		if ($input == "bool"){ 
			if ($paramsArray[$i] == "true" ){ 	
				$dataArray[$i] = "0000000000000000000000000000000000000000000000000000000000000001";
			}else{
				$dataArray[$i] = "0000000000000000000000000000000000000000000000000000000000000000";
			}
		}
		if ($input == "string"){ $dataArray[$i] = str_pad(bin2hex($paramsArray[$i]),64,"0",STR_PAD_RIGHT); }
		if (substr($input, 0, 5) == "bytes"){ 
			if (is_numeric($paramsArray[$i]) == 1) {
				$dataArray[$i] = str_pad(decimal2hex($paramsArray[$i]),64,"0",STR_PAD_LEFT); 
			}else{
				$dataArray[$i] = str_pad(bin2hex($paramsArray[$i]),64,"0",STR_PAD_RIGHT); 	
			}
		}
	$i++;
	}

	$contractData = "0x".substr( (string) Keccak::hash($function, 256),0,8);
	foreach ($dataArray as $outputData) {
		$contractData = $contractData.$outputData;
	}	

	$data = array("jsonrpc" => "2.0","method" => "eth_call","params"=>[array("data"=>"$contractData","to"=>"$contract"),"latest"],"id"=>"1");
	$result = callRpc($data);
	$details = json_decode($result, true);
	$output = $details['result'];
	if (substr($output, 0, 66) == "0x0000000000000000000000000000000000000000000000000000000000000020"){
		if (substr($output, 65, 64) == "0000000000000000000000000000000000000000000000000000000000000000"){
			$output = hex2bin(substr($output, 130, 64));
		}
	}else if (strlen($output) == 66){
		if (substr($output, 2, 4) == 0){
			$output = hex2decimal(substr($output,2,64));
		} else {
			$output = hex2bin(substr($output,2,64));
		}			
	}	

	return  $output; 
}

?>