getAddress(); self::$token = self::$kit->$type($contact); self::$decimal = $decimal; self::$blockTimeArea = Config::get('blockchain.' . $chain)['blockTimeArea'] ?? 1; } /** * @param $token * @return Web3Service * @throws Exception */ public static function instance($chain, $token, $private_key = ''): Web3Service { if ($chain != 'bsc' && $chain != 'eth') { throw new Exception('暂不支持该链'); } if (!get_token_info($chain, $token, 'address')) { throw new Exception('未定义Token'); } return new self($chain, get_token_info($chain, $token, 'address'), get_token_info($chain, $token, 'decimal'), get_token_info($chain, $token, 'type'), $private_key ?: get_token_info($chain, $token, 'private_key')); } public function createAddress() { $address = Credential::create(); return [ 'address' => $address->getAddress(), 'private_key' => $address->getPrivateKey() ]; } /** * 签名转地址 * @param $str * @param $sign * @return string * @throws Exception */ public function signToAddress($str, $sign) { $util = new Util(); if (strlen($sign) != 132) { throw new Exception('签名格式错误,类型:001'); } if (!$util->isHex($sign)) { throw new Exception('签名格式错误,类型:002'); } $sign_str = $util->stripZero($sign); $r = substr($sign_str, 0, 64); $s = substr($sign_str, 64, 64); $v = substr($sign_str, 128, 2); $message = $util->hashPersonalMessage($str); $public_key = $util->recoverPublicKey($message, $r, $s, hexdec($v) - 27); return strtolower($util->publicKeyToAddress($public_key)); } /** * 获取地址 * @return string */ public function getAddress() { return self::$address; } public function getBalance($address) { return bcdiv(self::$kit->balanceOf($address)->toString(), bcpow(10, 18), 18); } public function getTokenBalance($address) { return bcdiv(self::$token->balanceOf($address)->toString(), bcpow(10, self::$decimal), self::$decimal); } public function getLastTransfer($from = [], $to = [], $last_time = 0) { if ($last_time <= 0) $last_time = time() - 5000; $time_area = bcsub(time(), $last_time); $num = bcdiv($time_area, self::$blockTimeArea, 0); if ($num <= 0) $num = 0; if ($num > 10000) $num = 10000; return self::$token->getTransferEvents($from, $to, $num ? bcsub(self::$token->getBlockNumber(), $num) : 'latest'); } public function getBlockTransfer($block, $transferHash) { $res = self::$token->getTransferEvents([], [], $block, $block); $ress = []; foreach ($res as $v) { if ($v->transactionHash == $transferHash) { $ress[] = $v; } } return $ress; } public function getTransferInfo($tx_hash) { return self::$token->getTransactionReceipt($tx_hash); } public function transferToken($to, $amount) { return self::$token->transfer($to, bcmul($amount, bcpow(10, self::$decimal))); } public function transfer($to, $amount) { $num = bcmul($amount, bcpow(10, 18)); $num = '0x' . (new BigInteger($num))->toHex(); return self::$kit->transfer($to, $num); } public function getBNBTransferInfo($tx_hash) { return self::$token->getTransactionReceipt($tx_hash); } public function estimateTransferGas($to, $amount) { $cb = new Callback(); self::$token->estimateGas("transfer", self::$address, $to, bcmul($amount, bcpow(10, self::$decimal)), $cb); return $cb->result->toString(); } public function getData($name, ...$args) { $data = self::$token->getData($name, ...$args); $tx = [ 'data' => '0x' . $data, 'to' => self::$token->getToAddress() ]; return $tx; } public function totalSupply() { $data = self::$token->totalSupply(); $value = $data->toString(); return bcdiv($value, bcpow(10, self::$decimal), self::$decimal); } }