Skip to content

Commit

Permalink
- Added SerialzedType "XchainBridge"
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderBuzz committed Nov 23, 2023
1 parent b568a3b commit e692ba8
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 0 deletions.
138 changes: 138 additions & 0 deletions src/Core/RippleBinaryCodec/Types/XchainBridge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php declare(strict_types=1);
/**
* XRPL-PHP
*
* Copyright (c) Alexander Busse | Hardcastle Technologies
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace XRPL_PHP\Core\RippleBinaryCodec\Types;

use Exception;
use XRPL_PHP\Core\Buffer;
use XRPL_PHP\Core\RippleBinaryCodec\Serdes\BinaryParser;

class XchainBridge extends SerializedType
{
public const TYPE_ORDER = [
[ 'name' => 'LockingChainDoor', 'type' => AccountId::class ],
[ 'name' => 'LockingChainIssue', 'type' => Issue::class ],
[ 'name' => 'IssuingChainDoor', 'type' => AccountId::class ],
[ 'name' => 'IssuingChainIssue', 'type' => Issue::class ]
];
/**
* Class for serializing/Deserializing a cross-chain bridge
*
* @param Buffer|null $bytes
* @throws Exception
*/
public function __construct(?Buffer $bytes = null)
{
if (!$bytes) {
$bytes = Buffer::concat([
Buffer::from([0x14]),
Buffer::alloc(40),
Buffer::from([0x14]),
Buffer::from([0x14])
]);
}

parent::__construct($bytes);
}

/**
* Construct a cross-chain bridge from a BinaryParser
*
* @param BinaryParser $parser
* @param int|null $lengthHint
* @return SerializedType
* @throws Exception
*/
public static function fromParser(BinaryParser $parser, ?int $lengthHint = null): SerializedType
{
$bufferArray = [];
foreach (self::TYPE_ORDER as $item) {
[$type] = [$item['type']];
if ($type === AccountId::class) {
$parser->skip(1);
$bufferArray[] = Buffer::from([0x14]);
}
$object = call_user_func($type .'::fromParser', $parser);
$bufferArray[] = $object->toBytes();
}

return new XchainBridge(Buffer::concat($bufferArray));
}

/**
* Construct a cross-chain bridge from a JSON string
*
* @param string $serializedJson
* @return SerializedType
* @throws Exception
*/
public static function fromJson(string $serializedJson): SerializedType
{
$json = json_decode($serializedJson, true);

if (!self::isXchainBridgeObject($json)) {
throw new Exception('Invalid type to construct an XChainBridge');
}

$bufferArray = [];
foreach (self::TYPE_ORDER as $item) {
[$name, $type] = [$item['name'], $item['type']];
if ($type === AccountId::class) {
$bufferArray[] = Buffer::from([0x14]);
}
$object = call_user_func($type . '::fromJson', is_string($json[$name]) ? $json[$name] : json_encode($json[$name]));
$bufferArray[] = $object->toBytes();
}

return new XchainBridge(Buffer::concat($bufferArray));
}

/**
* Returns the JSON representation of this XChainBridge as an array
*
* @return string|array
* @throws Exception
*/
public function toJson(): string|array
{
$parser = new BinaryParser($this->toHex());
$json = [];
foreach (self::TYPE_ORDER as $item) {
[$name, $type] = [$item['name'], $item['type']];
if ($type === AccountId::class) {
$parser->skip(1);
}
$object = call_user_func($type .'::fromParser', $parser)->toJson();
$json[$name] = $object;
}

return $json;
}

/**
* Type guard for XchainBridge object
*
* @param array $json
* @return bool
*/
private static function isXchainBridgeObject(array $json): bool
{
$keys = array_keys($json);
sort($keys);

return (
count($keys) === 4 &&
$keys[0] === 'IssuingChainDoor' &&
$keys[1] === 'IssuingChainIssue' &&
$keys[2] === 'LockingChainDoor' &&
$keys[3] === 'LockingChainIssue'
);
}
}
34 changes: 34 additions & 0 deletions tests/Core/RippleBinaryCodec/Types/XchainBridgeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php declare(strict_types=1);

namespace XRPL_PHP\Test\Core\RippleBinaryCodec\Types;

use PHPUnit\Framework\TestCase;
use XRPL_PHP\Core\RippleBinaryCodec\Types\XchainBridge;

final class XchainBridgeTest extends TestCase
{
private string $hex = "14AF80285F637EE4AF3C20378F9DFB12511ACB8D27000000000000000000000000000000000000000014550FC62003E785DC231A1058A05E56E3F09CF4E60000000000000000000000000000000000000000";

private array $json = [
"LockingChainDoor" => "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL",
"LockingChainIssue" => ["currency" => "XRP"],
"IssuingChainDoor" => "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV",
"IssuingChainIssue" => ["currency" => "XRP"]
];

public function testDecode(): void
{
$this->assertEquals(
$this->json,
XchainBridge::fromHex($this->hex)->toJson()
);
}

public function testEncode(): void
{
$this->assertEquals(
$this->hex,
XchainBridge::fromJson(json_encode($this->json))->toHex()
);
}
}

0 comments on commit e692ba8

Please sign in to comment.