selaz / substrate-codec-php
For substrate scale codec
Requires
- php: >=8.0
- ext-gmp: *
- ext-json: *
- ext-sodium: *
- bitwasp/buffertools: dev-master
- phpoption/phpoption: 1.9.x-dev
Requires (Dev)
- phpunit/phpunit: ^5.7 || ^9.3.0
- squizlabs/php_codesniffer: 3.*
This package is not auto-updated.
Last update: 2024-11-11 14:07:58 UTC
README
Substrate scale codec
PHP SCALE Codec For substrate
Installation
composer require gmajor/substrate-codec-php
Basic Usage
Autoloading
Codec supports PSR-4
autoloaders.
<?php # When installed via composer require_once 'vendor/autoload.php';
Decode
<?php use Codec\ScaleBytes; use Codec\Base; use Codec\Types\ScaleInstance; $codec = new ScaleInstance(Base::create()); // Uint Support U8, U16, U32, U64, U128 $codec->process("U8", new ScaleBytes("64")); $codec->process("U16", new ScaleBytes("0300")); $codec->process("U32", new ScaleBytes("64000000")); $codec->process("U64", new ScaleBytes("471b47acc5a70000")); $codec->process("U128", new ScaleBytes("e52d2254c67c430a0000000000000000")); // Compact Support Compact int or other Mixed type, like Compact<Balance> // Compact decode always return GMP type $codec->process("Compact", new ScaleBytes("02093d00")); // Address Support Address/Account Id/MultiAddress $codec->process("Address", new ScaleBytes("ff1fa9d1bd1db014b65872ee20aee4fd4d3a942d95d3357f463ea6c799130b6318")); // Option $codec->process("Option<bool>", new ScaleBytes("02")); // String $codec->process("String", new ScaleBytes("1054657374")); // Bytes $codec->process("Bytes", new ScaleBytes("08ffff")); // Vec $codec->process("Vec<(u32, u32, u16)>", new ScaleBytes("08cc0200000000ce0200000001")); $codec->process("Vec<u8>", new ScaleBytes("08ffff")); // Enum with value list $codec =$codec->createTypeByTypeString("Enum"); $codec->valueList = [0, 1, 49, 50]; $codec->init(new ScaleBytes("02")); $codec->decode(); // Enum with struct $codec->typeStruct = ["int" => "u8", "bool" => "bool"]; $codec->init(new ScaleBytes("0x002a")); $codec->decode(); // Struct $codec =$codec->createTypeByTypeString("Struct"); $codec->typeStruct = ["a" => "Compact<u32>", "b" => "Compact<u32>"]; $codec->init(new ScaleBytes("0c00")); $codec->decode(); // Tuple $codec->process("(u8, u16, u32)", new ScaleBytes("01900100350c00")); // Result $codec->process("Result<u8, bool>", new ScaleBytes("0x002a")); $codec->process("Result<u8, bool>", new ScaleBytes("0x0100"));
Encode
<?php use Codec\Base; use Codec\Types\ScaleInstance; $codec = new ScaleInstance(Base::create()); // uint, encode support U8, U16, U32, U64, U128, Note that php int type support needs to be less than 9223372036854775807, // if it exceeds, it needs to be changed to string type $codec->createTypeByTypeString("U8")->encode(300); $codec->createTypeByTypeString("U16")->encode(5000); $codec->createTypeByTypeString("U32")->encode(100100100); $codec->createTypeByTypeString("U64")->encode(184467440737095); $codec->createTypeByTypeString("U128")->encode(739571955075788261); // Compact // Compact encode only support Int/GMP, if value is greater than 1073741823 (2**30-1), please use GMP type // https://www.php.net/manual/en/function.gmp-init.php $codec->createTypeByTypeString("Compact")->encode(2503000000000000000); // Address $codec->createTypeByTypeString("Address")->encode("1fa9d1bd1db014b65872ee20aee4fd4d3a942d95d3357f463ea6c799130b6318"); // Option $codec->createTypeByTypeString("option<Compact>")->encode(63); // String $codec->createTypeByTypeString("String")->encode("Test"); // Bytes $codec->createTypeByTypeString("Bytes")->encode("0xffff"); // Vec $codec->createTypeByTypeString("Vec<u32>")->encode([1, 2, 3, 4]); // Enum with value list $codec =$codec->createTypeByTypeString("Enum"); $codec->valueList = [0, 1, 49, 50]; $codec->encode(49); // Enum with struct $codec->typeStruct = ["int" => "u8", "bool" => "bool"]; $codec->encode(["bool" => true]); // Struct $codec = $codec->createTypeByTypeString("Struct"); $codec->typeStruct = ["a" => "Compact", "b" => "Compact"]; $codec->encode(["a" => 3, "b" => 0]); // Tuple $codec->createTypeByTypeString("(u8, u16, u32)")->encode([1, 400, 800000]); // Result $codec->createTypeByTypeString("Result<u8, bool>")->encode(["Err" => false]);
Custom types
All substrate Pallet types will be registered by default, refer to https://github.com/polkadot-js/api/tree/master/packages/types/src/interfaces, because the substrate itself is updated frequently, so https://github.com/gmajor-encrypt/php-scale-codec/tree/m2/src/Codec/interfaces will also be updated frequently here.
There are more than 50 polkadot-related applications so far, here are some custom types that need to be registered, here are some examples for reference
About custom type of documentation can be found here
<?php use Codec\Base; use Codec\ScaleBytes; use Codec\Types\ScaleInstance; $generator = Base::create(); Base::regCustom($generator,[ // direct "a"=> "balance", // struct "b"=> ["b1"=>"u8","b2"=>"vec<u32>"], // enum "c"=> ["_enum"=>["c1","c2","c3"]], // tuple "d"=> "(u32, bool)", // fixed "e"=> "[u32; 5]", // set "f"=> ["_set"=>["_bitLength"=>64,"f1"=>1,"f2"=>2,"f3"=>4,"f4"=>8]] ]); $codec = new ScaleInstance($generator); // inherit $this->assertEquals($codec->process("a", new ScaleBytes($codec->createTypeByTypeString("a")->encode(gmp_init(739571955075788261)))), gmp_init(739571955075788261)); // struct $this->assertEquals($codec->process("b", new ScaleBytes($codec->createTypeByTypeString("b")->encode(["b1" => 1, "b2" => [1, 2]]))), ["b1" => 1, "b2" => [1, 2]]); // enum $this->assertEquals($codec->process("c", new ScaleBytes($codec->createTypeByTypeString("c")->encode("c2"))), "c2"); // tuple $this->assertEquals($codec->process("d", new ScaleBytes($codec->createTypeByTypeString("d")->encode([1, true]))), [1, true]); // fixed $this->assertEquals($codec->process("e", new ScaleBytes($codec->createTypeByTypeString("e")->encode([1, 2, 3, 4, 5]))), [1, 2, 3, 4, 5]); // set $this->assertEquals($codec->process("f", new ScaleBytes($codec->createTypeByTypeString("f")->encode(["f1", "f2"]))), ["f1", "f2"]); ?>
Metadata
For more information on metadata, please refer to https://substrate.dev/docs/en/knowledgebase/runtime/metadata#metadata-formats
Currently, metadata decode/encode only supports v12/13/v14 More test you can found here https://github.com/gmajor-encrypt/php-scale-codec/blob/master/test/Codec/Test/MetadataTest.php
<?php use Codec\Base; use Codec\ScaleBytes; use Codec\Types\ScaleInstance; $metadataV13 = "..."; // from json rpc state_getMetadata $codec = new ScaleInstance(Base::create()); // decode $metadataInstant = $codec->process("metadata", new ScaleBytes($metadataV13)); // encode $codec->createTypeByTypeString("metadata")->encode($metadataInstant); print_r($metadataInstant); ?>
Extrinsic
For more information on Extrinsic, please refer to https://substrate.dev/docs/en/knowledgebase/learn-substrate/extrinsics
More test you can found here https://github.com/gmajor-encrypt/php-scale-codec/blob/master/test/Codec/Test/ExtrinsicTest.php
<?php use Codec\Base; use Codec\ScaleBytes; use Codec\Types\ScaleInstance; $metadataV13 = "..."; // from json rpc state_getMetadata $codec = new ScaleInstance(Base::create()); $metadataInstant = $codec->process("metadata", new ScaleBytes($metadataV13)); // decode $decodeExtrinsic = $codec->process("Extrinsic", new ScaleBytes("0x280403000b819fc2837a01"), $metadataInstant); // encode $codec->createTypeByTypeString("Extrinsic")->setMetadata($metadataInstant["metadata"])->encode($decodeExtrinsic); ?>
Event
For more information on Event, please refer to https://substrate.dev/docs/en/knowledgebase/runtime/events
More test you can found here https://github.com/gmajor-encrypt/php-scale-codec/blob/master/test/Codec/Test/EventTest.php
<?php use Codec\Base; use Codec\ScaleBytes; use Codec\Types\ScaleInstance; $metadataV13 = "..."; // from json rpc state_getMetadata $codec = new ScaleInstance(Base::create()); $metadataInstant = $codec->process("metadata", new ScaleBytes($metadataV13)); $decodeExtrinsic = $codec->process("Vec<EventRecord>", new ScaleBytes("0x080000000000000050e90b0b000000000200000001000000000080b2e60e00000000020000"), $metadataInstant); ?>
Example
More examples can refer to the test file https://github.com/gmajor-encrypt/php-scale-codec/tree/master/test/Codec/Test
Test
make test
Resources
License
The package is available as open source under the terms of the MIT License