feat: new chain
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Chain;
|
||||
|
||||
use kornrunner\Keccak;
|
||||
use RuntimeException;
|
||||
|
||||
final class EthAddress
|
||||
{
|
||||
public static function fromUncompressedPublicKey(string $publicKeyHex): string
|
||||
{
|
||||
$hex = strtolower($publicKeyHex);
|
||||
if (str_starts_with($hex, '0x')) {
|
||||
$hex = substr($hex, 2);
|
||||
}
|
||||
if (str_starts_with($hex, '04')) {
|
||||
$hex = substr($hex, 2);
|
||||
}
|
||||
if (strlen($hex) !== 128) {
|
||||
throw new RuntimeException('Expected uncompressed secp256k1 public key');
|
||||
}
|
||||
|
||||
$hash = Keccak::hash(hex2bin($hex), 256);
|
||||
|
||||
return '0x'.substr($hash, -40);
|
||||
}
|
||||
|
||||
public static function isValid(string $address): bool
|
||||
{
|
||||
return (bool) preg_match('/^0x[0-9a-fA-F]{40}$/', trim($address));
|
||||
}
|
||||
|
||||
public static function normalize(string $address): string
|
||||
{
|
||||
return strtolower(trim($address));
|
||||
}
|
||||
|
||||
/** 20-byte address without 0x, left-padded to 32 bytes for ABI. */
|
||||
public static function toWord(string $address): string
|
||||
{
|
||||
$hex = self::normalize($address);
|
||||
if (str_starts_with($hex, '0x')) {
|
||||
$hex = substr($hex, 2);
|
||||
}
|
||||
if (strlen($hex) !== 40) {
|
||||
throw new RuntimeException('Invalid ETH address');
|
||||
}
|
||||
|
||||
return str_pad($hex, 64, '0', STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user