From b833dfebb70fc9ffa7420b53d0b8786990e9c00d Mon Sep 17 00:00:00 2001 From: sc0Vu Date: Fri, 29 Dec 2017 18:23:56 +0800 Subject: [PATCH] Contract new method. --- src/Contract.php | 300 ++++++++++++++++++++++++++++++++ test/unit/ContractTest.php | 339 +++++++++++++++++++++++++++++++++++++ 2 files changed, 639 insertions(+) create mode 100644 src/Contract.php create mode 100644 test/unit/ContractTest.php diff --git a/src/Contract.php b/src/Contract.php new file mode 100644 index 0000000..f4bd113 --- /dev/null +++ b/src/Contract.php @@ -0,0 +1,300 @@ + + * + * @author Peter Lai + * @license MIT + */ + +namespace Web3; + +use InvalidArgumentException; +use Web3\Providers\Provider; +use Web3\Providers\HttpProvider; +use Web3\RequestManagers\RequestManager; +use Web3\RequestManagers\HttpRequestManager; +use Web3\Utils; +use Web3\Eth; +use Web3\Contracts\Ethabi; +use Web3\Contracts\Types\Address; +use Web3\Contracts\Types\Boolean; +use Web3\Contracts\Types\Bytes; +use Web3\Contracts\Types\Integer; +use Web3\Contracts\Types\Str; +use Web3\Contracts\Types\Uinteger; + +class Contract +{ + /** + * provider + * + * @var \Web3\Providers\Provider + */ + protected $provider; + + /** + * abi + * + * @var array + */ + protected $abi; + + /** + * constructor + * + * @var array + */ + protected $constructor = []; + + /** + * functions + * + * @var array + */ + protected $functions = []; + + /** + * events + * + * @var array + */ + protected $events = []; + + /** + * toAddress + * + * @var string + */ + protected $toAddress; + + /** + * eth + * + * @var \Web3\Eth + */ + protected $eth; + + /** + * ethabi + * + * @var \Web3\Contracts\Ethabi + */ + protected $ethabi; + + /** + * construct + * + * @param mixed string | Web3\Providers\Provider $provider + * @param mixed string | stdClass | array $abi + * @param string $toAddress + * @return void + */ + public function __construct($provider, $abi, $toAddress='') + { + if (is_string($provider) && (filter_var($provider, FILTER_VALIDATE_URL) !== false)) { + // check the uri schema + if (preg_match('/^https?:\/\//', $provider) === 1) { + $requestManager = new HttpRequestManager($provider); + + $this->provider = new HttpProvider($requestManager); + } + } else if ($provider instanceof Provider) { + $this->provider = $provider; + } + $abi = Utils::jsonToArray($abi, 5); + + foreach ($abi as $item) { + if (isset($item['type'])) { + if ($item['type'] === 'function') { + $this->functions[$item['name']] = $item; + } elseif ($item['type'] === 'constructor') { + $this->constructor = $item; + } elseif ($item['type'] === 'event') { + $this->events[$item['name']] = $item; + } + } + } + $this->abi = $abi; + + if (is_string($toAddress)) { + $this->toAddress = $toAddress; + } + $this->eth = new Eth($this->provider); + $this->ethabi = new Ethabi([ + 'address' => new Address, + 'bool' => new Boolean, + 'bytes' => new Bytes, + 'int' => new Integer, + 'string' => new Str, + 'uint' => new Uinteger, + ]); + } + + /** + * call + * + * @param string $name + * @param array $arguments + * @return void + */ + // public function __call($name, $arguments) + // { + // if (empty($this->provider)) { + // throw new \RuntimeException('Please set provider first.'); + // } + + // $class = explode('\\', get_class()); + + // if (preg_match('/^[a-zA-Z0-9]+$/', $name) === 1) { + // } + // } + + /** + * get + * + * @param string $name + * @return mixed + */ + public function __get($name) + { + $method = 'get' . ucfirst($name); + + if (method_exists($this, $method)) { + return call_user_func_array([$this, $method], []); + } + } + + /** + * set + * + * @param string $name + * @param mixed $value + * @return bool + */ + public function __set($name, $value) + { + $method = 'set' . ucfirst($name); + + if (method_exists($this, $method)) { + return call_user_func_array([$this, $method], [$value]); + } + return false; + } + + /** + * getProvider + * + * @return \Web3\Providers\Provider + */ + public function getProvider() + { + return $this->provider; + } + + /** + * setProvider + * + * @param $provider + * @return bool + */ + public function setProvider($provider) + { + if ($provider instanceof Provider) { + $this->provider = $provider; + return true; + } + return false; + } + + /** + * getFunctions + * + * @return array + */ + public function getFunctions() + { + return $this->functions; + } + + /** + * getEvents + * + * @return array + */ + public function getEvents() + { + return $this->events; + } + + /** + * getConstructor + * + * @return array + */ + public function getConstructor() + { + return $this->constructor; + } + + /** + * getAbr + * + * @return array + */ + public function getAbi() + { + return $this->abi; + } + + /** + * getEth + * + * @return \Web3\Eth + */ + public function getEth() + { + return $this->eth; + } + + /** + * new + * Deploy a contruct with params. + * + * @param mixed + * @return void + */ + public function new() + { + if (isset($this->constructor)) { + $constructor = $this->constructor; + $arguments = func_get_args(); + $callback = array_pop($arguments); + + if (count($arguments) < count($constructor['inputs'])) { + throw new InvalidArgumentException('Please make sure you have put all constructor params and callback.'); + } + if (is_callable($callback) !== true) { + throw new \InvalidArgumentException('The last param must be callback function.'); + } + $params = array_splice($arguments, 0, count($constructor['inputs'])); + $data = $this->ethabi->encodeParameters($constructor, $params); + $transaction = []; + + if (count($arguments) > 0) { + $transaction = $arguments[0]; + } + $transaction['to'] = ''; + $transaction['data'] = $data; + + $this->eth->sendTransaction($transaction, function ($err, $transaction) use ($callback){ + if ($err !== null) { + return call_user_func($callback, $err, null); + } + return call_user_func($callback, null, $transaction); + }); + } + } +} \ No newline at end of file diff --git a/test/unit/ContractTest.php b/test/unit/ContractTest.php new file mode 100644 index 0000000..399b4a6 --- /dev/null +++ b/test/unit/ContractTest.php @@ -0,0 +1,339 @@ +contract = new Contract('http://localhost:8545', $this->testAbi); + $this->contract = new Contract($this->web3->provider, $this->testAbi); + $this->contract->eth->accounts(function ($err, $accounts) { + if ($err === null) { + if (isset($accounts->result)) { + $this->accounts = $accounts->result; + return; + } + } + }); + } + + /** + * testDeploy + * + * @return void + */ + public function testDeploy() + { + $contract = $this->contract; + + // var_dump($this->contract->constructor); + if (!isset($this->accounts[0])) { + $account = '0x407d73d8a49eeb85d32cf465507dd71d507100c1'; + } else { + $account = $this->accounts[0]; + } + $contract->new(10000, 'Game Token', 1, 'GT', [ + 'from' => $account + ], function ($err, $result) use ($contract) { + if ($err !== null) { + // infura api gg + return $this->assertTrue($err !== null); + } + if ($result->result) { + echo "\nTransaction has made:) id: " . $result->result . "\n"; + } + $transactionId = $result->result; + $this->assertTrue((preg_match('/^0x[a-f0-9]{64}$/', $transactionId) === 1)); + + $contract->eth->getTransactionReceipt($transactionId, function ($err, $transaction) { + if ($err !== null) { + return $this->fail($err); + } + if ($transaction->result) { + echo "\nTransaction has mind:) block number: " . $transaction->result->blockNumber . "\n"; + } + }); + }); + } +} \ No newline at end of file