$url, CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_AUTOREFERER => true, CURLOPT_HEADER => false, CURLOPT_TIMEOUT => 5, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Accept: application/json', ], CURLOPT_TIMEOUT => $timeout, CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_POSTFIELDS => $rawData, ]; $ch = curl_init(); curl_setopt_array($ch, $options); $rawResp = curl_exec($ch); // $e=curl_error($ch); if ($rawResp === false) { return false; } curl_close($ch); return $rawResp; } /** * Convert to wei * @param string $fund eg: 1eth, 0.1gwei * @return bool|string */ public static function toWei($fund) { $pattern = '/^([\d]+(?:\.\d+)?)([a-zA-Z]+)/i'; if (!preg_match($pattern, $fund, $matches)) { return false; } $fund = $matches[1]; $unit = strtolower($matches[2]); return self::convertUnit($fund, $unit, 'wei'); } /** * Convert to eth * @param string $fund eg: 567wei, 123gwei * @return bool|string */ public static function toEther($fund) { $pattern = '/^([\d]+(?:\.\d+)?)([a-zA-Z]+)/i'; if (!preg_match($pattern, $fund, $matches)) { return false; } $fund = $matches[1]; $unit = strtolower($matches[2]); return self::convertUnit($fund, $unit, 'eth'); } public static function fund2int($fund, $decimal = 18) { $rate = "1" . str_repeat('0', $decimal); return bcmul($fund, $rate); } public static function int2fund($int, $decimal = 18) { $rate = "1" . str_repeat('0', $decimal); $result = bcdiv($int, $rate, 5); if (strpos($result, '.') !== false) { list($int, $dec) = explode('.', $result); $dec = rtrim($dec, '0'); if ($dec !== '') { $result = $int . '.' . $dec; } else { $result = $int; } } return $result; } /** * Ethereum units count against each other * @param string $number * @param string $from * @param string $to * @return bool|string */ public static function convertUnit($number, $from, $to) { $units = [ 'wei' => 0, 'kwei' => 3, 'mwei' => 6, 'gwei' => 9, 'microether' => 12, 'milliether' => 15, 'ether' => 18, 'eth' => 18, ]; if (!isset($units[$from]) || !isset($units[$to])) { return false; } $maxDecimal = max($units); // max scale if ($units[$from] > $units[$to]) { $operator = "1" . str_repeat("0", $units[$from] - $units[$to]); $result = bcmul($number, $operator, $maxDecimal); } elseif ($units[$from] == $units[$to]) { $result = $number; } else { $operator = "1" . str_repeat("0", $units[$to] - $units[$from]); $result = bcdiv($number, $operator, $maxDecimal); } // The number of excess decimal digits after removing the result if (strpos($result, '.') !== false) { list($int, $dec) = explode('.', $result); $dec = rtrim($dec, '0'); if ($dec !== '') { $result = $int . '.' . $dec; } else { $result = $int; } } return $result; } /** * @param $method * @param array $args * @return false|string */ public static function decodeSolMethod($method, $args = []) { $pattern = '/^[a-z0-9]+\(([^\)]+)\)$/i'; if (!preg_match($pattern, $method, $matched)) { return false; } try { $sign = substr(Keccak::hash($method, 256), 0, 8); $params = explode(',', $matched[1]); // 分析参数 foreach ($params as $key => $param) { $arg = $args[$key]; if (strpos($param, 'uint') !== false || strpos($param, 'int') !== false) { $paramSign = substr(self::dec2hex($arg), 2); } elseif (strpos($param, 'address') !== false) { $paramSign = substr(self::fixHex($arg), 2); } else { return false; } $sign .= str_pad($paramSign, 64, '0', STR_PAD_LEFT); } return self::fixHex($sign); } catch (\Exception $e) { return false; } } public static function dec2hex($number) { $hexvalues = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']; $hexval = ''; while ($number != '0') { $hexval = $hexvalues[bcmod($number, '16')] . $hexval; $number = bcdiv($number, '16', 0); } return self::fixHex($hexval); } public static function hex2dec($number) { if (strpos($number, '0x') !== false) { $number = substr($number, 2); } $number = strtoupper($number); $decvalues = [ '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', 'A' => '10', 'B' => '11', 'C' => '12', 'D' => '13', 'E' => '14', 'F' => '15' ]; $decval = '0'; $number = strrev($number); for ($i = 0; $i < strlen($number); $i++) { $decval = bcadd(bcmul(bcpow('16', $i, 0), $decvalues[$number[$i]]), $decval); } return $decval; } public static function prettyNum($number) { if ($number > 10000) { $number = bcdiv($number, "10000", 2) . '万'; } return $number; } }