diff --git a/src/Utils.php b/src/Utils.php index 73536f1..fbcf188 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -62,6 +62,14 @@ class Utils 'tether' => '1000000000000000000000000000000' ]; + /** + * NEGATIVE1 + * Cannot work, see: http://php.net/manual/en/language.constants.syntax.php + * + * @const + */ + // const NEGATIVE1 = new BigNumber(-1); + /** * construct * @@ -126,7 +134,7 @@ class Utils public static function isZeroPrefixed($value) { if (!is_string($value)) { - throw new InvalidArgumentException('The value to zeroPrefixed function must be string.'); + throw new InvalidArgumentException('The value to isZeroPrefixed function must be string.'); } return (strpos($value, '0x') === 0); } @@ -146,6 +154,20 @@ class Utils 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 * @@ -415,23 +437,61 @@ class Utils * Change number or number string to bignumber. * * @param BigNumber|string|int $number - * @return \phpseclib\Math\BigInteger + * @return array|\phpseclib\Math\BigInteger */ public static function toBn($number) { - if (is_numeric($number)) { + if ($number instanceof BigNumber){ + $bn = $number; + } elseif (is_int($number)) { $bn = new BigNumber($number); - } elseif (is_string($number)) { - $number = mb_strtolower($number); + } elseif (is_numeric($number)) { + $number = (string) $number; - if (self::isZeroPrefixed($number) || preg_match('/[a-f]+/', $number) === 1) { - $number = self::stripZero($number); - $bn = new BigNumber($number, 16); + if (self::isNegative($number)) { + $count = 1; + $number = str_replace('-', '', $number, $count); + $negative1 = new BigNumber(-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 BigNumber($whole), + new BigNumber($fraction), + isset($negative1) ? $negative1 : false + ]; } else { $bn = new BigNumber($number); } - } elseif ($number instanceof BigNumber){ - $bn = $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 BigNumber(-1); + } + if (self::isZeroPrefixed($number) || preg_match('/[a-f]+/', $number) === 1) { + $number = self::stripZero($number); + $bn = new BigNumber($number, 16); + } elseif (empty($number)) { + $bn = new BigNumber(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 BigNumber, string or int.'); } diff --git a/test/unit/UtilsTest.php b/test/unit/UtilsTest.php index 96e3ddd..a519ab4 100644 --- a/test/unit/UtilsTest.php +++ b/test/unit/UtilsTest.php @@ -448,6 +448,20 @@ class UtilsTest extends TestCase $this->assertFalse($isHex); } + /** + * testIsNegative + * + * @return void + */ + public function testIsNegative() + { + $isNegative = Utils::isNegative('-1'); + $this->assertTrue($isNegative); + + $isNegative = Utils::isNegative('1'); + $this->assertFalse($isNegative); + } + /** * testToBn * @@ -455,18 +469,65 @@ class UtilsTest extends TestCase */ public function testToBn() { + $bn = Utils::toBn(''); + $this->assertEquals($bn->toString(), '0'); + $bn = Utils::toBn(11); $this->assertEquals($bn->toString(), '11'); $bn = Utils::toBn('0x12'); $this->assertEquals($bn->toString(), '18'); + $bn = Utils::toBn('-0x12'); + $this->assertEquals($bn->toString(), '-18'); + $bn = Utils::toBn(0x12); $this->assertEquals($bn->toString(), '18'); $bn = Utils::toBn('ae'); $this->assertEquals($bn->toString(), '174'); + $bn = Utils::toBn('-ae'); + $this->assertEquals($bn->toString(), '-174'); + + $bn = Utils::toBn('-1'); + $this->assertEquals($bn->toString(), '-1'); + + $bn = Utils::toBn('-0.1'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '0'); + $this->assertEquals($bn[1]->toString(), '1'); + $this->assertEquals($bn[2]->toString(), '-1'); + + $bn = Utils::toBn(-0.1); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '0'); + $this->assertEquals($bn[1]->toString(), '1'); + $this->assertEquals($bn[2]->toString(), '-1'); + + $bn = Utils::toBn('0.1'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '0'); + $this->assertEquals($bn[1]->toString(), '1'); + $this->assertEquals($bn[2], false); + + $bn = Utils::toBn('-1.69'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '1'); + $this->assertEquals($bn[1]->toString(), '69'); + $this->assertEquals($bn[2]->toString(), '-1'); + + $bn = Utils::toBn(-1.69); + $this->assertEquals($bn[0]->toString(), '1'); + $this->assertEquals($bn[1]->toString(), '69'); + $this->assertEquals($bn[2]->toString(), '-1'); + + $bn = Utils::toBn('1.69'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '1'); + $this->assertEquals($bn[1]->toString(), '69'); + $this->assertEquals($bn[2], false); + $bn = Utils::toBn(new BigNumber(1)); $this->assertEquals($bn->toString(), '1');