| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 | 
							- <?php
 
- namespace App\Services\Web3;
 
- use kornrunner\Keccak;
 
- class Contract
 
- {
 
-     private $address;
 
-     private $abi;
 
-     private $web3;
 
-     private $event;
 
-     private $eventHash;
 
-     private $function;
 
-     private function __construct(Web3 $web3, $abi, $address)
 
-     {
 
-         $this->abi = $abi;
 
-         $this->web3 = $web3;
 
-         $this->address = $address;
 
-         $json = json_decode($this->abi, true);
 
-         foreach ($json as $item) {
 
-             switch ($item['type']) {
 
-                 case 'event':
 
-                     $this->event[$item['name']] = $item;
 
-                     $hash = $this->encodeEventSignature($this->getEventByName($item['name']));
 
-                     $this->eventHash[$hash] = $item['name'];
 
-                     break;
 
-                 case 'function':
 
-                     $this->function[$item['name']] = $item;
 
-                     break;
 
-             }
 
-         }
 
-     }
 
-     public static function at(Web3 $web3, $abi, $address): Contract
 
-     {
 
-         return new Contract($web3, $abi, $address);
 
-     }
 
-     public function getFunctionArrayByName($name)
 
-     {
 
-         return $this->function[$name];
 
-     }
 
-     public function getEventArrayByName($name)
 
-     {
 
-         return $this->event[$name];
 
-     }
 
-     public function getWeb3(): Web3
 
-     {
 
-         return $this->web3;
 
-     }
 
-     public function getAddress()
 
-     {
 
-         return $this->address;
 
-     }
 
-     public function getFunctionByName($name): string
 
-     {
 
-         $inputs = $this->function[$name]['inputs'];
 
-         return $this->extracted($name, $inputs);
 
-     }
 
-     public function getEventByName($name): string
 
-     {
 
-         $inputs = $this->event[$name]['inputs'];
 
-         return $this->extracted($name, $inputs);
 
-     }
 
-     public function getFunctionName(): array
 
-     {
 
-         return array_keys($this->function);
 
-     }
 
-     public function getEventName(): array
 
-     {
 
-         return array_keys($this->event);
 
-     }
 
-     public function decodeEvent($hash)
 
-     {
 
-         if (!array_key_exists($hash, $this->eventHash)) {
 
-             throw  new \Exception("this hash not in the constract");
 
-         }
 
-         return $this->eventHash[$hash];
 
-     }
 
-     public function getAbi()
 
-     {
 
-         return $this->abi;
 
-     }
 
-     /**
 
-      * @throws \Exception
 
-      */
 
-     public function send(Wallet $wallet, $function, array $param, $config = [])
 
-     {
 
-         $data = $this->getData($function, $param, $wallet->getAddress());
 
-         $neirong = $this->web3->estimateGas($data['to'], $data['data'], $data['from'], null, $data['value']);
 
-         // if(isset($neirong['code'])){
 
-         //     return $neirong;
 
-         // }
 
-         $neirong = '0x5480';
 
-         $data['gas'] = dechex(hexdec($neirong) * 1.5);
 
-         $data['gasPrice'] = $this->web3->gasPrice();
 
-         $data['nonce'] = $this->web3->getTransactionCount($wallet->getAddress(), 'pending');
 
-         unset($data['from']);
 
- //        $chainId = $this->web3->chainId();
 
-         $data = array_merge([
 
-             'nonce' => '01',
 
-             'gasPrice' => '',
 
-             'gas' => '',
 
-             'to' => '',
 
-             'value' => '',
 
-             'data' => '',
 
-         ], $data);
 
-         $signature = $wallet->sign(Utils::rawEncode($data));
 
-         $chainId = 0;
 
-         $data['v'] = dechex($signature->recoveryParam + 27 + ($chainId ? $chainId * 2 + 8 : 0));
 
-         $data['r'] = $signature->r->toString('hex');
 
-         $data['s'] = $signature->s->toString('hex');
 
-         $signRaw = Utils::add0x(Utils::rawEncode($data));
 
-         return $this->web3->sendRawTransaction($signRaw);
 
-     }
 
-     /**
 
-      * @param $function
 
-      * @param $param
 
-      * @param null $from
 
-      * @return array
 
-      * @throws \Exception
 
-      */
 
-     private function getData($function, $param, $from = null): array
 
-     {
 
-         if (!array_key_exists($function, $this->function)) {
 
-             throw new \Exception(" function not in contract ");
 
-         }
 
-         $function = $this->getFunctionArrayByName($function);
 
-         if (count($param) != count($function['inputs'])) {
 
-             throw  new  \Exception("please send full param");
 
-         }
 
-         $data = [
 
-             'to' => $this->address,
 
-             'value' => '0x0'
 
-         ];
 
-         if (!empty($from)) {
 
-             $data['from'] = $from;
 
-         }
 
-         $hash = Keccak::hash($this->getFunctionByName($function['name']), 256);
 
-         $hashSub = mb_substr($hash, 0, 8, 'utf-8');
 
-         $data['data'] = '0x' . $hashSub;
 
-         $input = $function['inputs'];
 
-         for ($i = 0; $i < count($param); $i++) {
 
-             $value = '';
 
-             switch ($input[$i]['type']) {
 
-                 case 'address':
 
-                     $value = Utils::remove0x($param[$i]);
 
-                     break;
 
-                 case 'uint8':
 
-                 case 'uint16':
 
-                 case 'uint24':
 
-                 case 'uint32':
 
-                 case 'uint40':
 
-                 case 'uint48':
 
-                 case 'uint56':
 
-                 case 'uint64':
 
-                 case 'uint72':
 
-                 case 'uint80':
 
-                 case 'uint88':
 
-                 case 'uint96':
 
-                 case 'uint104':
 
-                 case 'uint112':
 
-                 case 'uint120':
 
-                 case 'uint128':
 
-                 case 'uint136':
 
-                 case 'uint144':
 
-                 case 'uint152':
 
-                 case 'uint160':
 
-                 case 'uint168':
 
-                 case 'uint176':
 
-                 case 'uint184':
 
-                 case 'uint192':
 
-                 case 'uint200':
 
-                 case 'uint208':
 
-                 case 'uint216':
 
-                 case 'uint224':
 
-                 case 'uint232':
 
-                 case 'uint240':
 
-                 case 'uint248':
 
-                 case 'uint256':
 
-                     $value = Utils::decToHex($param[$i], false);
 
-                     break;
 
-             }
 
-             $data['data'] = $data['data'] . Utils::fill0($value);
 
-         }
 
-         return $data;
 
-     }
 
-     /**
 
-      * encodeEventSignature
 
-      * TODO: Fix same event name with different params
 
-      *
 
-      * @param string|stdClass|array $functionName
 
-      * @return string
 
-      */
 
-     public function encodeEventSignature($functionName)
 
-     {
 
-         if (!is_string($functionName)) {
 
-             $functionName = Utils::jsonMethodToString($functionName);
 
-         }
 
-         return Utils::sha3($functionName);
 
-     }
 
-     public function call($function, $param = [], $quantity = Quantity::latest)
 
-     {
 
-         $data = $this->getData($function, $param);
 
-         return $this->web3->call($data['to'], $data['data'], null, null, null, null, $quantity);
 
-     }
 
-     /**
 
-      * @param $name
 
-      * @param $inputs
 
-      * @return string
 
-      */
 
-     public function extracted($name, $inputs): string
 
-     {
 
-         $res = $name . '(';
 
-         foreach ($inputs as $input) {
 
-             $res .= $input['type'] . ',';
 
-         }
 
-         if (count($inputs) > 0) {
 
-             $res = substr($res, 0, strlen($res) - 1);
 
-         }
 
-         $res .= ')';
 
-         return $res;
 
-     }
 
- }
 
 
  |