wallet tron transactions
This commit is contained in:
330
sdk/Wallet/Tools/Utils.php
Normal file
330
sdk/Wallet/Tools/Utils.php
Normal file
@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
namespace Sdk\Wallet\Tools;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use kornrunner\Keccak;
|
||||
use phpseclib\Math\BigInteger;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* SHA3_NULL_HASH
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const SHA3_NULL_HASH = 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470';
|
||||
|
||||
/**
|
||||
* NEGATIVE1
|
||||
* Cannot work, see: http://php.net/manual/en/language.constants.syntax.php
|
||||
*
|
||||
* @const
|
||||
*/
|
||||
// const NEGATIVE1 = new BigInteger(-1);
|
||||
|
||||
/**
|
||||
* construct
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// public function __construct() {}
|
||||
|
||||
/**
|
||||
* toHex
|
||||
* Encoding string or integer or numeric string(is not zero prefixed) or big number to hex.
|
||||
*
|
||||
* @param string|int|BigInteger $value
|
||||
* @param bool $isPrefix
|
||||
* @return string
|
||||
*/
|
||||
public static function toHex($value, $isPrefix = false)
|
||||
{
|
||||
if (is_numeric($value)) {
|
||||
// turn to hex number
|
||||
$bn = self::toBn($value);
|
||||
$hex = $bn->toHex(true);
|
||||
$hex = preg_replace('/^0+(?!$)/', '', $hex);
|
||||
} elseif (is_string($value)) {
|
||||
$value = self::stripZero($value);
|
||||
$hex = implode('', unpack('H*', $value));
|
||||
} elseif ($value instanceof BigInteger) {
|
||||
$hex = $value->toHex(true);
|
||||
$hex = preg_replace('/^0+(?!$)/', '', $hex);
|
||||
} else {
|
||||
throw new InvalidArgumentException('The value to toHex function is not support.');
|
||||
}
|
||||
if ($isPrefix) {
|
||||
return '0x' . $hex;
|
||||
}
|
||||
return $hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* hexToBin
|
||||
*
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
public static function hexToBin($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidArgumentException('The value to hexToBin function must be string.');
|
||||
}
|
||||
if (self::isZeroPrefixed($value)) {
|
||||
$count = 1;
|
||||
$value = str_replace('0x', '', $value, $count);
|
||||
}
|
||||
return pack('H*', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* isZeroPrefixed
|
||||
*
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
public static function isZeroPrefixed($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidArgumentException('The value to isZeroPrefixed function must be string.');
|
||||
}
|
||||
return (strpos($value, '0x') === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* stripZero
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function stripZero($value)
|
||||
{
|
||||
if (self::isZeroPrefixed($value)) {
|
||||
$count = 1;
|
||||
return str_replace('0x', '', $value, $count);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* isNegative
|
||||
*
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
public static function isNegative($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidArgumentException('The value to isNegative function must be string.');
|
||||
}
|
||||
return (strpos($value, '-') === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* isAddress
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAddress($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidArgumentException('The value to isAddress function must be string.');
|
||||
}
|
||||
if (preg_match('/^(0x|0X)?[a-f0-9A-F]{40}$/', $value) !== 1) {
|
||||
return false;
|
||||
} elseif (preg_match('/^(0x|0X)?[a-f0-9]{40}$/', $value) === 1 || preg_match('/^(0x|0X)?[A-F0-9]{40}$/', $value) === 1) {
|
||||
return true;
|
||||
}
|
||||
return self::isAddressChecksum($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* isAddressChecksum
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAddressChecksum($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidArgumentException('The value to isAddressChecksum function must be string.');
|
||||
}
|
||||
$value = self::stripZero($value);
|
||||
$hash = self::stripZero(self::sha3(mb_strtolower($value)));
|
||||
|
||||
for ($i = 0; $i < 40; $i++) {
|
||||
if (
|
||||
(intval($hash[$i], 16) > 7 && mb_strtoupper($value[$i]) !== $value[$i]) ||
|
||||
(intval($hash[$i], 16) <= 7 && mb_strtolower($value[$i]) !== $value[$i])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* isHex
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function isHex($value)
|
||||
{
|
||||
return (is_string($value) && preg_match('/^(0x)?[a-f0-9A-F]*$/', $value) === 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha3
|
||||
* keccak256
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function sha3($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidArgumentException('The value to sha3 function must be string.');
|
||||
}
|
||||
if (strpos($value, '0x') === 0) {
|
||||
$value = self::hexToBin($value);
|
||||
}
|
||||
$hash = Keccak::hash($value, 256);
|
||||
|
||||
if ($hash === self::SHA3_NULL_HASH) {
|
||||
return null;
|
||||
}
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* toBn
|
||||
* Change number or number string to BigInteger.
|
||||
*
|
||||
* @param BigInteger|string|int $number
|
||||
* @return array|BigInteger
|
||||
*/
|
||||
public static function toBn($number)
|
||||
{
|
||||
if ($number instanceof BigInteger) {
|
||||
$bn = $number;
|
||||
} elseif (is_int($number)) {
|
||||
$bn = new BigInteger($number);
|
||||
} elseif (is_numeric($number)) {
|
||||
$number = (string) $number;
|
||||
|
||||
if (self::isNegative($number)) {
|
||||
$count = 1;
|
||||
$number = str_replace('-', '', $number, $count);
|
||||
$negative1 = new BigInteger(-1);
|
||||
}
|
||||
if (strpos($number, '.') > 0) {
|
||||
$comps = explode('.', $number);
|
||||
|
||||
if (count($comps) > 2) {
|
||||
throw new InvalidArgumentException('toBn number must be a valid number.');
|
||||
}
|
||||
$whole = $comps[0];
|
||||
$fraction = $comps[1];
|
||||
|
||||
return [
|
||||
new BigInteger($whole),
|
||||
new BigInteger($fraction),
|
||||
strlen($comps[1]),
|
||||
isset($negative1) ? $negative1 : false
|
||||
];
|
||||
} else {
|
||||
$bn = new BigInteger($number);
|
||||
}
|
||||
if (isset($negative1)) {
|
||||
$bn = $bn->multiply($negative1);
|
||||
}
|
||||
} elseif (is_string($number)) {
|
||||
$number = mb_strtolower($number);
|
||||
|
||||
if (self::isNegative($number)) {
|
||||
$count = 1;
|
||||
$number = str_replace('-', '', $number, $count);
|
||||
$negative1 = new BigInteger(-1);
|
||||
}
|
||||
if (self::isZeroPrefixed($number) || preg_match('/[a-f]+/', $number) === 1) {
|
||||
$number = self::stripZero($number);
|
||||
$bn = new BigInteger($number, 16);
|
||||
} elseif (empty($number)) {
|
||||
$bn = new BigInteger(0);
|
||||
} else {
|
||||
throw new InvalidArgumentException('toBn number must be valid hex string.');
|
||||
}
|
||||
if (isset($negative1)) {
|
||||
$bn = $bn->multiply($negative1);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidArgumentException('toBn number must be BigInteger, string or int.');
|
||||
}
|
||||
return $bn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据精度展示资产
|
||||
* @param $number
|
||||
* @param int $decimals
|
||||
* @return string
|
||||
*/
|
||||
public static function toDisplayAmount($number, int $decimals)
|
||||
{
|
||||
$number = number_format($number,0,'.','');//格式化
|
||||
$bn = self::toBn($number);
|
||||
$bnt = self::toBn(pow(10, $decimals));
|
||||
|
||||
return self::divideDisplay($bn->divide($bnt), $decimals);
|
||||
}
|
||||
|
||||
public static function divideDisplay(array $divResult, int $decimals)
|
||||
{
|
||||
list($bnq, $bnr) = $divResult;
|
||||
$ret = "$bnq->value";
|
||||
if ($bnr->value > 0) {
|
||||
$ret .= '.' . rtrim(sprintf("%0{$decimals}d", $bnr->value), '0');
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function toMinUnitByDecimals($number, int $decimals)
|
||||
{
|
||||
$bn = self::toBn($number);
|
||||
$bnt = self::toBn(pow(10, $decimals));
|
||||
|
||||
if (is_array($bn)) {
|
||||
// fraction number
|
||||
list($whole, $fraction, $fractionLength, $negative1) = $bn;
|
||||
|
||||
$whole = $whole->multiply($bnt);
|
||||
|
||||
switch (MATH_BIGINTEGER_MODE) {
|
||||
case $whole::MODE_GMP:
|
||||
static $two;
|
||||
$powerBase = gmp_pow(gmp_init(10), (int) $fractionLength);
|
||||
break;
|
||||
case $whole::MODE_BCMATH:
|
||||
$powerBase = bcpow('10', (string) $fractionLength, 0);
|
||||
break;
|
||||
default:
|
||||
$powerBase = pow(10, (int) $fractionLength);
|
||||
break;
|
||||
}
|
||||
$base = new BigInteger($powerBase);
|
||||
$fraction = $fraction->multiply($bnt)->divide($base)[0];
|
||||
|
||||
if ($negative1 !== false) {
|
||||
return $whole->add($fraction)->multiply($negative1);
|
||||
}
|
||||
return $whole->add($fraction);
|
||||
}
|
||||
|
||||
return $bn->multiply($bnt);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user