| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- <?php
- namespace blockchain;
- use BI\BigInteger;
- use blockchain\web3\Bep20;
- use blockchain\web3\Bep721;
- use blockchain\web3\Callback;
- use blockchain\web3\Credential;
- use blockchain\web3\Kit;
- use blockchain\web3\NodeClient;
- use think\Config;
- use think\Exception;
- use Web3p\EthereumUtil\Util;
- class Web3Service
- {
- /** @var Bep20|Bep721 $token */
- private static $token;
- private static $decimal;
- private static $address;
- private static $kit;
- private static $blockTimeArea;
- public function __construct($chain, $contact, $decimal, $type, $private_key)
- {
- $node = NodeClient::create($chain, 'mainNet');
- $credential = Credential::fromKey($private_key);
- self::$kit = new Kit($node, $credential);
- self::$address = $credential->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);
- }
- }
|