diff --git a/composer.json b/composer.json index f07d0f1..26de9a6 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,6 @@ "php": "^8.2", "ext-gmp": "*", "ext-bcmath": "*", - "laravel/framework": ">=v7.0.0|>=v10.0.0", "spomky-labs/cbor-php": "^3.0" }, "scripts": { diff --git a/src/AddressValidationServiceProvider.php b/src/AddressValidationServiceProvider.php deleted file mode 100644 index cb0cdcd..0000000 --- a/src/AddressValidationServiceProvider.php +++ /dev/null @@ -1,17 +0,0 @@ -publishes([ - __DIR__.'/../config/address_validation.php' => config_path('address_validation.php'), - ]); - } -} \ No newline at end of file diff --git a/src/Contracts/Validator.php b/src/Contracts/Validator.php index 17ee200..78a58d1 100644 --- a/src/Contracts/Validator.php +++ b/src/Contracts/Validator.php @@ -4,6 +4,8 @@ namespace Merkeleon\PhpCryptocurrencyAddressValidation\Contracts; +use Merkeleon\PhpCryptocurrencyAddressValidation\Exception\AddressValidationException; + interface Validator { public function isValid(?string $address): bool; @@ -16,4 +18,4 @@ public function isValid(?string $address): bool; * @throws AddressValidationException */ public function validate(?string $address): void; -} \ No newline at end of file +} diff --git a/src/DriverConfig.php b/src/DriverConfig.php index d9df244..bd8282a 100644 --- a/src/DriverConfig.php +++ b/src/DriverConfig.php @@ -7,13 +7,10 @@ use Merkeleon\PhpCryptocurrencyAddressValidation\Drivers\AbstractDriver; use function class_exists; -/** - * @template T - */ -readonly class DriverConfig +final readonly class DriverConfig { /** - * @param class-string $driver + * @param class-string $driver * @param array $mainnet * @param array $testnet */ @@ -21,8 +18,7 @@ public function __construct( private string $driver, private array $mainnet = [], private array $testnet = [] - ) - { + ) { } public function makeDriver(bool $isMainNet): ?AbstractDriver @@ -45,13 +41,4 @@ private function getDriverOptions(bool $isMainNet): array ?: $this->mainnet ?: []; } - - public static function __set_state(array $state): DriverConfig - { - return new self( - $state['driver'], - $state['mainnet'], - $state['testnet'] - ); - } } diff --git a/src/Drivers/Base32Driver.php b/src/Drivers/Base32Driver.php index d19194c..44da6bf 100644 --- a/src/Drivers/Base32Driver.php +++ b/src/Drivers/Base32Driver.php @@ -4,7 +4,6 @@ namespace Merkeleon\PhpCryptocurrencyAddressValidation\Drivers; -use Illuminate\Support\Str; use Merkeleon\PhpCryptocurrencyAddressValidation\Utils\Base32Decoder; use RuntimeException; use Throwable; @@ -15,8 +14,8 @@ use function implode; use function pack; use function preg_match; -use function sprintf; use function str_contains; +use function sprintf; use function strtolower; class Base32Driver extends AbstractDriver @@ -45,7 +44,14 @@ public function match(string $address): bool public function check(string $address, array $networks = []): bool { try { - $hasPrefix = Str::contains($address, array_keys($this->options)); + $hasPrefix = false; + + foreach (array_keys($this->options) as $key) { + if (str_contains($address, (string) $key)) { + $hasPrefix = true; + break; + } + } $address = strtolower($address); @@ -111,4 +117,4 @@ protected function decodeVersion(int $version): array return [$scriptType, $hashLength]; } -} \ No newline at end of file +} diff --git a/src/Drivers/CardanoDriver.php b/src/Drivers/CardanoDriver.php index 5db0bd0..af2e181 100644 --- a/src/Drivers/CardanoDriver.php +++ b/src/Drivers/CardanoDriver.php @@ -8,12 +8,10 @@ use Merkeleon\PhpCryptocurrencyAddressValidation\Utils\Bech32Decoder; use function array_keys; use function implode; -use function in_array; use function preg_match; class CardanoDriver extends AbstractDriver { - public function match(string $address): bool { $prefix = implode('|', array_keys($this->options)); @@ -32,4 +30,4 @@ public function check(string $address): bool return false; } } -} \ No newline at end of file +} diff --git a/src/Drivers/CborDriver.php b/src/Drivers/CborDriver.php index 94dea40..c6046e5 100644 --- a/src/Drivers/CborDriver.php +++ b/src/Drivers/CborDriver.php @@ -12,11 +12,11 @@ use CBOR\Tag\GenericTag; use CBOR\Tag\TagManager; use CBOR\Tag\UnsignedBigIntegerTag; -use Illuminate\Support\Str; use Merkeleon\PhpCryptocurrencyAddressValidation\Utils\Base58Decoder; use Throwable; use function array_keys; use function array_values; +use function str_starts_with; class CborDriver extends AbstractDriver { @@ -38,7 +38,13 @@ public function __construct(array $options) public function match(string $address): bool { - return Str::startsWith($address, array_keys($this->options)); + foreach (array_keys($this->options) as $key) { + if (str_starts_with($address, (string) $key)) { + return true; + } + } + + return false; } public function check(string $address): bool @@ -86,4 +92,4 @@ public function check(string $address): bool return false; } } -} \ No newline at end of file +} diff --git a/src/Drivers/KeccakStrictDriver.php b/src/Drivers/KeccakStrictDriver.php index 1807e5d..310c66b 100644 --- a/src/Drivers/KeccakStrictDriver.php +++ b/src/Drivers/KeccakStrictDriver.php @@ -4,15 +4,12 @@ namespace Merkeleon\PhpCryptocurrencyAddressValidation\Drivers; -use InvalidArgumentException; use Merkeleon\PhpCryptocurrencyAddressValidation\Utils\KeccakDecoder; use function intval; -use function is_string; use function preg_match; use function str_replace; use function str_split; use function str_starts_with; -use function strpos; use function strtolower; use function strtoupper; use function substr; @@ -56,4 +53,4 @@ public function isZeroPrefixed(string $value): bool { return str_starts_with(haystack: $value, needle: '0x'); } -} \ No newline at end of file +} diff --git a/src/Exception/AddressValidationException.php b/src/Exception/AddressValidationException.php index b8d283a..34ebe16 100644 --- a/src/Exception/AddressValidationException.php +++ b/src/Exception/AddressValidationException.php @@ -4,7 +4,9 @@ namespace Merkeleon\PhpCryptocurrencyAddressValidation\Exception; -class AddressValidationException extends \RuntimeException +use RuntimeException; + +class AddressValidationException extends RuntimeException { public function __construct(string $chain, string $notValidAddress, bool $matchedPattern) { @@ -12,4 +14,4 @@ public function __construct(string $chain, string $notValidAddress, bool $matche $text .= $matchedPattern ? ": address have wrong encoding" : ": address does not matched pattern"; parent::__construct($text); } -} \ No newline at end of file +} diff --git a/src/Exception/Bech32Exception.php b/src/Exception/Bech32Exception.php index 7e34a5b..202f9d4 100644 --- a/src/Exception/Bech32Exception.php +++ b/src/Exception/Bech32Exception.php @@ -2,7 +2,9 @@ namespace Merkeleon\PhpCryptocurrencyAddressValidation\Exception; -class Bech32Exception extends \Exception +use Exception; + +class Bech32Exception extends Exception { -} \ No newline at end of file +} diff --git a/src/Utils/Base32Decoder.php b/src/Utils/Base32Decoder.php index e4cdd20..78faf20 100644 --- a/src/Utils/Base32Decoder.php +++ b/src/Utils/Base32Decoder.php @@ -15,12 +15,10 @@ use function gmp_init; use function gmp_mul; use function gmp_pow; -use function gmp_strval; use function gmp_xor; use function ord; use function pack; use function strlen; -use function strtolower; use function unpack; class Base32Decoder @@ -304,4 +302,4 @@ protected static function convertBits(array $data, $inLen, $fromBits, $toBits, $ return $ret; } -} \ No newline at end of file +} diff --git a/src/Validator.php b/src/Validator.php index 514d8c9..9cfae35 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -8,21 +8,25 @@ use Merkeleon\PhpCryptocurrencyAddressValidation\Contracts\Driver; use Merkeleon\PhpCryptocurrencyAddressValidation\Enums\CurrencyEnum; use Merkeleon\PhpCryptocurrencyAddressValidation\Exception\AddressValidationException; -use function app; -use function config; -readonly class Validator implements Contracts\Validator +class Validator implements Contracts\Validator { + private const CONFIG_PATH = __DIR__ . '/../config/address_validation.php'; + + /** + * @param DriverConfig[] $options + */ public function __construct( - private string $chain, - private array $options, - private bool $isMainnet = true + private readonly string $chain, + private readonly bool $isMainnet = true, + private ?array $options = null, ) { + $this->options = $options ?? $this->resolveConfigForCurrency(CurrencyEnum::from($this->chain)); } - public static function make(CurrencyEnum $currency): Validator + public static function make(CurrencyEnum $currency, bool $isMainnet = true, ?array $config = null): self { - return new Validator($currency->value, config("address_validation.{$currency->value}"), app()->isProduction()); + return new self($currency->value, $isMainnet, $config); } public function isValid(?string $address): bool @@ -32,6 +36,7 @@ public function isValid(?string $address): bool } $drivers = $this->getDrivers(); + // if there is no drivers we force address to be valid if (null === $drivers || !$drivers->valid()) { return true; @@ -47,6 +52,7 @@ public function validate(?string $address): void } $drivers = $this->getDrivers(); + // if there is no drivers we force address to be valid if (null === $drivers || !$drivers->valid()) { return; @@ -68,7 +74,6 @@ public function validate(?string $address): void */ protected function getDrivers(): ?Generator { - /** @var DriverConfig $driverConfig */ foreach ($this->options as $driverConfig) { if ($driver = $driverConfig->makeDriver($this->isMainnet)) { yield $driver; @@ -78,9 +83,11 @@ protected function getDrivers(): ?Generator return null; } + /** + * @param Driver[] $drivers + */ protected function getDriver(iterable $drivers, string $address): ?Driver { - /** @var Driver $driver */ foreach ($drivers as $driver) { if ($driver->match($address)) { return $driver; @@ -89,4 +96,15 @@ protected function getDriver(iterable $drivers, string $address): ?Driver return null; } -} \ No newline at end of file + + /** + * @return DriverConfig[] + */ + protected function resolveConfigForCurrency(CurrencyEnum $currency): array + { + /** @var array $config */ + $config = require self::CONFIG_PATH; + + return $config[$currency->value]; + } +} diff --git a/tests/KeccakDriverTest.php b/tests/KeccakDriverTest.php index 6bf5fdf..f101464 100644 --- a/tests/KeccakDriverTest.php +++ b/tests/KeccakDriverTest.php @@ -28,7 +28,7 @@ public function test_keccak_driver(string $net, bool $expected, string $address) { $config = [new DriverConfig(KeccakDriver::class)]; - $validator = new Validator(CurrencyEnum::ETHEREUM->value, $config, $net === 'mainnet'); + $validator = new Validator(CurrencyEnum::ETHEREUM->value, $net === 'mainnet', $config); self::assertEquals($expected, $validator->isValid($address)); } @@ -42,4 +42,4 @@ public function addressesProvider(): array 'Ethereum #4' => ['testnet', true, '0x799ad3ff7ef43dfd1473f9b8a8c4237c22d8113f'], ]; } -} \ No newline at end of file +} diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index 527d8ba..f6f5cb4 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -25,11 +25,7 @@ class ValidatorTest extends TestCase */ public function test_currency_validator(CurrencyEnum $currency, string $net, bool $expected, string $address): void { - $config = require __DIR__ . '/../config/address_validation.php'; - - $options = $config[$currency->value]; - - $validator = new Validator($currency->value, $options, $net === 'mainnet'); + $validator = new Validator($currency->value, $net === 'mainnet'); $this->assertEquals( $expected, @@ -120,4 +116,4 @@ public function currencyAddressProvider(): array 'EOS #2' => [CurrencyEnum::EOS, 'mainnet', true, 'bitfinexeos1'], ]; } -} \ No newline at end of file +}