From ba28abe22f5f8410eb5bacab04e4aeb39faea0e5 Mon Sep 17 00:00:00 2001 From: zgrguric Date: Thu, 28 Mar 2024 18:47:04 +0100 Subject: [PATCH] Util currencyToSymbol --- phpunit.xml.dist | 4 +-- src/Utilities/Util.php | 67 ++++++++++++++++++++++++++++++++--------- tests/Unit/UtilTest.php | 10 ++++-- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7e823ce..213d863 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,8 +2,8 @@ - ./tests/Unit - + ./tests/Unit + ./tests/Feature diff --git a/src/Utilities/Util.php b/src/Utilities/Util.php index 8f09835..c087f86 100644 --- a/src/Utilities/Util.php +++ b/src/Utilities/Util.php @@ -25,24 +25,23 @@ public static function currencyToSymbol($currencycode, $malformedUtf8ReturnStrin if(\substr($currencycode,0,2) == '01') { //demurrage, convert it to utf8 for display - - //let bytes = Buffer.from(demurrageCode, "hex") $bytes = \array_values(unpack("C*", \hex2bin($currencycode))); //let code = String.fromCharCode(bytes[1]) + String.fromCharCode(bytes[2]) + String.fromCharCode(bytes[3]); $code = \chr($bytes[1]).\chr($bytes[2]).\chr($bytes[3]); //OK - //let interest_start = (bytes[4] << 24) + (bytes[5] << 16) + (bytes[6] << 8) + (bytes[7]); //$interest_start = (int)(($bytes[4] << 24) . ($bytes[5] << 16) . ($bytes[6] << 8) . $bytes[7]); //let interest_period = ieee754Float.fromBytes(bytes.slice(8, 16)); $interest_period = self::ieee754FloatFromBytes(\array_slice($bytes,8,8)); - dd($interest_period); + if($interest_period === null || $interest_period === true) { + return $code.' (?% pa)'; + } //const year_seconds = 31536000; // By convention, the XRP Ledger's interest/demurrage rules use a fixed number of seconds per year (31536000), which is not adjusted for leap days or leap seconds $year_seconds = 31536000; //let interest_after_year = precision(Math.pow(Math.E, (interest_start+year_seconds - interest_start) / interest_period), 14); - $interest_after_year = $year_seconds / $interest_period; - dd($interest_start,$interest_after_year); - return 'DE '.$currencycode; + $interest_after_year = \pow(\exp(1), $year_seconds / $interest_period); + $interest = ($interest_after_year*100) - 100; + return $code.' ('.$interest.'% pa)'; } $r = \trim(\hex2bin($currencycode)); @@ -61,17 +60,57 @@ public static function currencyToSymbol($currencycode, $malformedUtf8ReturnStrin } /** - * IEEE 754 floating-point. + * IEEE754 floating-point. * * Supports single- or double-precision */ - public static function ieee754FloatFromBytes(array $bytes) + public static function ieee754FloatFromBytes(array $bytes): float|null|bool { - dd($bytes,pack('h', $bytes)); - $data = unpack('f', pack('i', $bytes)); - if($data === false) - throw new \Exception('Unable to extract ieee754FloatFromBytes'); - return \array_values($data)[0]; + $b = ''; + $n = count($bytes); + for ($i = 0; $i < $n; $i++) { + $bits = base_convert((string)($bytes[$i] & 0xff),10,2);//.toString(2); + if(strlen($bits)<8) $bits = \str_pad($bits,8,'0',STR_PAD_LEFT); + $b = $b.$bits; + } + + // Determine configuration. This could have all been precomputed but it is fast enough. + $exponentBits = count($bytes) === 4 ? 4 : 11; + $mantissaBits = (count($bytes) * 8) - $exponentBits - 1; + $bias = \pow(2,$exponentBits - 1) - 1; + $minExponent = 1 - $bias - $mantissaBits; + // Break up the binary representation into its pieces for easier processing. + $s = $b[0]; + $e = \substr($b,1,$exponentBits); + $m = \substr($b,$exponentBits+1); + $value = 0; + $multiplier = ($s === '0' ? 1 : -1); + + if(\preg_match('/^0+$/', $e)) { //regexp: allzeros + // Zero or denormalized + if(\preg_match('/^0+$/', $m)) { //regexp: allzeros + // Value is zero + } else { + $value = \intval($m, 2) * \pow(2, $minExponent); + } + } else if (\preg_match('/^1+$/', $e)) { //regexp: allones + // Infinity or NaN + if(\preg_match('/^0+$/', $m)) { //regexp: allones + $value = true; //Infinity + } else { + $value = null; //NaN + } + } else { + // Normalized + $exponent = \intval($e,2) - $bias; + $mantissa = \intval($m,2); + $value = (1+($mantissa * \pow(2,-$mantissaBits))) * \pow(2,$exponent); + } + if($value === false) return false; + if($value === null) return null; + return $value * $multiplier; + + } } \ No newline at end of file diff --git a/tests/Unit/UtilTest.php b/tests/Unit/UtilTest.php index 6527543..2ccddfc 100644 --- a/tests/Unit/UtilTest.php +++ b/tests/Unit/UtilTest.php @@ -10,7 +10,6 @@ class XRPLParserUtilUtilTest extends TestCase public function testConvertCurrencyToSymbolDemurrage() { $this->assertEquals('XAU (-0.5% pa)',Util::currencyToSymbol('0158415500000000C1F76FF6ECB0BAC600000000')); - } public function testConvertCurrencyToSymbolISO() @@ -23,10 +22,15 @@ public function testConvertCurrencyToSymbolISO() $this->assertEquals('123',Util::currencyToSymbol('123')); } + public function testConvertCurrencyToSymbol() + { + $this->assertEquals('SOLO',Util::currencyToSymbol('534F4C4F00000000000000000000000000000000')); + $this->assertEquals('GOLD',Util::currencyToSymbol('80474F4C44000000000000000000000000000000')); //"GOLD" after cleanup + $this->assertEquals('ABCD',Util::currencyToSymbol('ABCD')); + } + public function testConvertCurrencyToSymbolLP() { $this->assertEquals('LP 03B20F3A7D26D33C6DA3503E5CCE3E67B102D4D2',Util::currencyToSymbol('03B20F3A7D26D33C6DA3503E5CCE3E67B102D4D2')); } - - } \ No newline at end of file