enjin / php-blockchain-tools
Tools for handling hex numbers and decoding contract data.
Installs: 18 645
Dependents: 2
Suggesters: 0
Security: 0
Stars: 3
Watchers: 7
Forks: 2
Open Issues: 0
Requires
- php: ^8.0|^8.1
- kornrunner/keccak: ^1.0
- phpseclib/phpseclib: ^3.0
Requires (Dev)
- fakerphp/faker: ^1.18
- mockery/mockery: ^1.5
- nette/php-generator: ^v3.6
- phpunit/phpunit: ^9.5
- symfony/var-dumper: ^6.0
This package is auto-updated.
Last update: 2025-03-01 00:29:57 UTC
README
Hex Data
HexConverter
See: Enjin\BlockchainTools\HexConverter
Contains static utility functions for handling decimal and hex data.
Conversion Method Reference
Method | From | To |
---|---|---|
hexToInt |
signed int (base 16) | signed int (base 10) |
intToHex |
signed int (base 10) | signed int (base 16) |
intToHexPrefixed |
0x prefixed |
|
hexToUInt |
unsigned int (base 16) | unsigned int (base 10) |
uIntToHex |
unsigned int (base 10) | unsigned int (base 16) |
uIntToHexPrefixed |
0x prefixed |
|
hexToString |
hex encoded string (base 16) | decoded string |
stringToHex |
decoded string | hex encoded string (base 16) |
stringToHexPrefixed |
0x prefixed |
|
hexToBytes |
hex encoded bytes (base 16) | array of bytes |
bytesToHex |
array of bytes | hex encoded bytes (base 16) |
bytesToHexPrefixed |
0x prefixed |
|
hexToAddress |
hex string | address |
hexToAddressPrefixed |
0x prefixed |
|
addressToEventTopic |
address | address padded to event topic |
addressToEventTopicPrefixed |
0x prefixed |
BigHex
See: Enjin\BlockchainTools\BigHex
Object for handling large hex numbers.
$longHex = '0xabc1234...'; $hex = new BigHex($longHex); $hex->toStringPrefixed(); // '0xabc1234...' $hex->toStringUnPrefixed(); // 'abc1234...' // convert to phpseclib\Math\BigInteger $bigInt = $hex->toBigInt();
HexUInt Classes
Classes to represent and convert all valid UInt values are in the HexNumber\HexUInt
namespace.
// ways to create a HexNumber instance // all will throw an exception if an invalid value is provided // the value must be within the min/max range // if it is a hex it must have the correct number of characters $hexUInt16 = new HexUInt16('0x1234'); $hexUInt16 = HexUInt16::fromHex('0x1234'); $hexUInt16 = HexUInt::fromHexUInt16('0x1234'); $hexUInt16 = HexUInt::fromHexUIntBitSize(16, '0x1234'); // creating from a base 10 decimal value $hexUInt16 = HexUInt16::fromUInt('4660'); $hexUInt16 = HexUInt::fromUIntBitSize(16, '4660'); $hexUInt16->toPrefixed(); // '0x1234' $hexUInt16->toUnPrefixed(); // '1234' $hexUInt16->toDecimal(); // '4660' $hexUInt16->toHexUInt64(); // '0x0000000000001234' // can only convert to top/bottom of lower bit sizes HexUInt16::fromHex('0x1200')->toHexInt8Top(); // '0x12' HexUInt16::fromHex('0x0034')->toHexInt8Bottom(); // '0x34' // returned exactly as provided (with our without prefix) $hexUInt16->toHex(); // '0x1234' // note that prefix remains intact when provided HexUInt::fromHexUInt24('123456')->toHexUInt64(); // '0000000000123456' HexUInt::fromHexUInt24('0x123456')->toHexUInt64(); // '0x0000000000123456' // provide a hex without left padded zeroes $paddedHex = HexUInt16::padLeft('0x12'); // '0x0012'
HexInt Classes
Classes to represent and convert all valid Int values are in the HexNumber\HexInt
namespace.
// ways to create a HexNumber instance // all will throw an exception if an invalid value is provided // the value must be within the min/max range // if it is a hex it must have the correct number of characters $hexInt16 = new HexInt16('0xfefc'); $hexInt16 = HexInt16::fromHex('0xfefc'); $hexInt16 = HexInt::fromHexInt16('0xfefc'); $hexInt16 = HexInt::fromHexIntBitSize(16, '0xfefc'); // creating from a base 10 decimal value $hexInt16 = HexInt16::fromInt('-260'); $hexInt16 = HexInt::fromIntBitSize(16, '-260'); $hexInt16->toPrefixed(); // '0xfefc' $hexInt16->toUnPrefixed(); // 'fefc' $hexInt16->toDecimal(); // '-260' $hexInt16->toHexInt64(); // '0x000000000000fefc' // can only convert to top/bottom of lower bit sizes HexInt16::fromHex('0xfe00')->toHexInt8Top(); // '0xfe' HexInt16::fromHex('0x00fc')->toHexInt8Bottom(); // '0xfc' // returned exactly as provided (with our without prefix) $hexInt16->toHex(); // '0xfefc' // note that prefix remains intact when provided HexInt::fromHexInt24('123456')->toHexInt64(); // '0000000000123456' HexInt::fromHexInt24('0x123456')->toHexInt64(); // '0x0000000000123456' // provide a hex without left padded zeroes $paddedHex = HexInt16::padLeft('0x12'); // '0x0012'
ABI Contracts
Contract Data Types not currently supported
- string[]
- bytes[]
- multi-dimensional arrays (uint16[][])
- tuple
- fixed
- ufixed
ContractStore
Used to lazy load and re-use parsed abi json data. Create and re-use an instance of this class in your application to lazy load and cache processed abi files.
See: Enjin\BlockchainTools\Ethereum\ABI\ContractStore
use Enjin\BlockchainTools\Ethereum\ABI\ContractStore; $store = new ContractStore(); $store->registerContracts([ [ 'name' => 'my-contract', 'address' => '0xabc...', 'jsonFile' => '/path/to/abi/json/file' ] ]); // OR $store->registerContract('my-contract', '0xabc...', '/path/to/abi/json/file'); $contract = $store->contract('my-contract'); $contract = $store->contractByAddress('0xabc...');
Custom Contract Serializers
Custom serializers may be registered for contracts or specific functions/events.
See: Enjin\BlockchainTools\Ethereum\ABI\DataBlockDecoder
See: Enjin\BlockchainTools\Ethereum\ABI\DataBlockDecoder
See: Enjin\BlockchainTools\Ethereum\ABI\DataBlockDecoder\BasicDecoder
See: Enjin\BlockchainTools\Ethereum\ABI\DataBlockDecoder\BasicEncoder
use Enjin\BlockchainTools\Ethereum\ABI\ContractStore; use Enjin\BlockchainTools\Ethereum\ABI\Serializer; use Enjin\BlockchainTools\Ethereum\ABI\DataBlockDecoder\BasicDecoder; use Enjin\BlockchainTools\Ethereum\ABI\DataBlockEncoder\BasicEncoder; $default = Serializer::makeDefault(); // make a serializer instance with a custom decoder/encoder classes // basic decoder/encoder converts: // - string to/from hex // - bytes to/from array of bytes to hex // - php bool to/from hex // - address to/from hex (converted to correct length with prefix removed) $basic = new Serializer( BasicDecoder::class, BasicEncoder::class ); $store = new ContractStore(); $serializers = [ // default for all functions and events 'default' => $default, 'functions' => [ 'myFunction1' => [ // replaces contract default // default for input and output of myFunction 'default' => $basic, // replaces function default for input 'input' => $default, // replaces function default for output 'output' => $basic, ], 'myFunction2' => [ 'default' => $basic, ], // ... ], 'events' => [ // events only have input and only decode // so are assigned serializers directly 'myEvent1' => $basic, 'myEvent2' => $basic, // ... ] ]; $store->registerContracts([ [ 'name' => 'my-contract', 'address' => '0xabc...', 'jsonFile' => '/path/to/abi/json/file', 'serializers' => $serializers, ] ]); $store->registerContract('my-contract', '0xabc...', '/path/to/abi/json/file', $serializers);
Contract
Interface to interact with an ABI contract.
See: Enjin\BlockchainTools\Ethereum\ABI\Contract
$contract = $contractStore->contract('contract-name'); $name = $contract->name(); $address = $contract->address(); /* Functions */ $arrayOfFunctions = $contract->functions(); $function = $contract->function('function-name'); // first 8 characters of encoded input/output $methodId = '...'; $function = $contract->findFunctionByMethodId($methodId); $encodedInput = '...'; // looks up method from first 8 characters of encoded string and decodes $decoded = $contract->decodeFunctionInput($encodedInput); $decoded = $contract->decodeFunctionOutput($encodedInput); /* Events */ $arrayOfEvents = $contract->events(); $event = $contract->event('event-name'); // topic[0] event signature $signatureTopic = '...'; $event = $contract->findEventBySignatureTopic($signatureTopic); $topics = []; $data = '...'; // lookup event by topic[0] and decode input $decoded = $contract->decodeEventInput($topics, $data);
ContractFunction
Represents an ABI contract function.
See: Enjin\BlockchainTools\Ethereum\ABI\Contract\ContractFunction
$contract = $contractStore->contract('contract-name'); $function = $contract->function('function-name'); $name = $function->name(); $constant = $function->constant(); $payable = $function->payable(); $stateMutability = $function->stateMutability(); // signature example: myFunction(uint16,string) $signature = $function->signature(); // first 4 bytes of Keccak hashed signature $methodId = $function->methodId(); $arrayOfInputs = $function->inputs(); $arrayOfOutputs = $function->outputs(); $data = [ 'foo' => 'bar', 'key' => 'value', ]; $dataBlock = $function->encodeInput($data); // or $dataBlock = $function->encodeOutput($data); // methodId from function $dataBlock->methodId(); // convert to encoded string $dataBlock->toString(); // convert to array of 64 character chunks (excluding methodId) $dataBlock->toArray(); // convert to array of 64 character chunks with metadata about each chunk (helps with debugging) $dataBlock->toArrayWithMeta(); // data string with or without methodId at the start $dataString = '...'; // returns key value pairs as array $decoded = $function->decodeInput($dataString); $decoded = $function->decodeOutput($dataString);
ContractEvent
Represents an ABI contract event.
See: Enjin\BlockchainTools\Ethereum\ABI\Contract\ContractEvent
$contract = $contractStore->contract('contract-name'); $event = $contract->event('event-name'); $name = $event->name(); $anonymous = $event->anonymous(); // signature example: myFunction(uint16,string) $signature = $event->signature(); // Keccak hashed signature found in topic[0] of encoded event input $methodId = $event->signatureTopic(); $arrayOfInputs = $event->inputs(); $input = $event->input('input-name'); $topics = ['...']; $data = '...'; // convert event to array of key-value pairs $decoded = $event->decodeInput($topics, $data);
Generated Classes
The following classes are generated by running php ./bin/generate-classes.php
:
\Enjin\BlockchainTools\HexNumber\HexInt
\Enjin\BlockchainTools\HexNumber\HexUInt
\Enjin\BlockchainTools\HexNumber\HexInt\HexInt*
\Enjin\BlockchainTools\HexNumber\HexUInt\HexUInt*
To generate the HexUInt
and HexInt