From c67ec3ccaaf5a17c77550208fd6a4b5dc04b069b Mon Sep 17 00:00:00 2001 From: sc0Vu Date: Tue, 2 Jan 2018 11:54:57 +0800 Subject: [PATCH] Contract send. --- src/Contract.php | 66 +++++++++++++++++++++++++++++- src/Contracts/Ethabi.php | 6 +-- test/unit/ContractTest.php | 83 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 146 insertions(+), 9 deletions(-) diff --git a/src/Contract.php b/src/Contract.php index f4bd113..993180c 100644 --- a/src/Contract.php +++ b/src/Contract.php @@ -25,6 +25,8 @@ use Web3\Contracts\Types\Bytes; use Web3\Contracts\Types\Integer; use Web3\Contracts\Types\Str; use Web3\Contracts\Types\Uinteger; +use Web3\Validators\AddressValidator; +use Web3\Formatters\Address as AddressFormatter; class Contract { @@ -145,9 +147,7 @@ class Contract // if (empty($this->provider)) { // throw new \RuntimeException('Please set provider first.'); // } - // $class = explode('\\', get_class()); - // if (preg_match('/^[a-zA-Z0-9]+$/', $name) === 1) { // } // } @@ -259,6 +259,23 @@ class Contract return $this->eth; } + /** + * at + * + * @param string $address + * @return $this + */ + public function at($address) + { + if (AddressValidator::validate($address) === false) { + var_dump($address); + throw new InvalidArgumentException('Please make sure address is valid.'); + } + $this->toAddress = AddressFormatter::format($address); + + return $this; + } + /** * new * Deploy a contruct with params. @@ -297,4 +314,49 @@ class Contract }); } } + + /** + * send + * Send function method. + * + * @param mixed + * @return void + */ + public function send() + { + if (isset($this->functions)) { + $arguments = func_get_args(); + $method = array_splice($arguments, 0, 1)[0]; + $callback = array_pop($arguments); + + if (!is_string($method) && !isset($this->functions[$method])) { + throw new InvalidArgumentException('Please make sure the method is existed.'); + } + $function = $this->functions[$method]; + + if (count($arguments) < count($function['inputs'])) { + throw new InvalidArgumentException('Please make sure you have put all function params and callback.'); + } + if (is_callable($callback) !== true) { + throw new \InvalidArgumentException('The last param must be callback function.'); + } + $params = array_splice($arguments, 0, count($function['inputs'])); + $data = $this->ethabi->encodeParameters($function, $params); + $functionSignature = $this->ethabi->encodeFunctionSignature($function['name']); + $transaction = []; + + if (count($arguments) > 0) { + $transaction = $arguments[0]; + } + $transaction['to'] = $this->toAddress; + $transaction['data'] = $functionSignature . Utils::stripZero($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/src/Contracts/Ethabi.php b/src/Contracts/Ethabi.php index 2ac02c0..c826d7d 100644 --- a/src/Contracts/Ethabi.php +++ b/src/Contracts/Ethabi.php @@ -135,9 +135,6 @@ class Ethabi */ public function encodeParameters($types, $params) { - if (count($types) !== count($params)) { - throw new InvalidArgumentException('encodeParameters number of types must equal to number of params.'); - } // change json to array if ($types instanceof stdClass && isset($types->inputs)) { $types = Utils::jsonToArray($types, 2); @@ -152,6 +149,9 @@ class Ethabi } } } + if (count($types) !== count($params)) { + throw new InvalidArgumentException('encodeParameters number of types must equal to number of params.'); + } $typesLength = count($types); $solidityTypes = array_fill(0, $typesLength, 0); diff --git a/test/unit/ContractTest.php b/test/unit/ContractTest.php index 399b4a6..e1aa678 100644 --- a/test/unit/ContractTest.php +++ b/test/unit/ContractTest.php @@ -277,6 +277,13 @@ class ContractTest extends TestCase */ protected $accounts; + /** + * contractAddress + * + * @var string + */ + protected $contractAddress; + /** * setUp * @@ -286,8 +293,8 @@ class ContractTest extends TestCase { parent::setUp(); - // $this->contract = new Contract('http://localhost:8545', $this->testAbi); - $this->contract = new Contract($this->web3->provider, $this->testAbi); + $this->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)) { @@ -307,14 +314,82 @@ class ContractTest extends TestCase { $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 + 'from' => $account, + 'gas' => '0x200b20' + ], 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) { + $this->contractAddress = $transaction->result->contractAddress; + echo "\nTransaction has mind:) block number: " . $transaction->result->blockNumber . "\n"; + } + }); + }); + } + + /** + * testSend + * + * @return void + */ + public function testSend() + { + $contract = $this->contract; + + if (!isset($this->accounts[0])) { + $fromAccount = '0x407d73d8a49eeb85d32cf465507dd71d507100c1'; + } else { + $fromAccount = $this->accounts[0]; + } + if (!isset($this->accounts[1])) { + $toAccount = '0x407d73d8a49eeb85d32cf465507dd71d507100c2'; + } else { + $toAccount = $this->accounts[1]; + } + $contract->new(10000, 'Game Token', 1, 'GT', [ + 'from' => $fromAccount, + 'gas' => '0x200b20' + ], 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) { + $this->contractAddress = $transaction->result->contractAddress; + echo "\nTransaction has mind:) block number: " . $transaction->result->blockNumber . "\n"; + } + }); + }); + $contract->at($this->contractAddress)->send('transfer', $toAccount, 100, [ + 'from' => $fromAccount ], function ($err, $result) use ($contract) { if ($err !== null) { // infura api gg