olifanton / interop
Olifanton interop 库
Requires
- php: >=8.1
- ext-mbstring: *
- brick/math: >=0.10
- myclabs/deep-copy: ^1.11
- olifanton/typed-arrays: ^1.0.2
Requires (Dev)
- jetbrains/phpstorm-attributes: ^1.0
- overtrue/phplint: 9.3.1
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.5
Suggests
- ext-bcmath: *
- ext-hash: *
- ext-sodium: *
README
安装
composer require olifanton/interop
文档
入门
通过 Composer 安装 olifanton/interop
包并包含自动加载脚本
<?php declare(strict_types=1); require __DIR__ . "/vendor/autoload.php"; use Olifanton\Interop\Boc\BitString; use Olifanton\Interop\Boc\Cell; // Now you can use Interop classes
组件
地址
Olifanton\Interop\Address
Address
是一个类,允许您在 TON 网络中处理智能合约地址。有关地址的更多信息,请参阅官方 文档。
Address 构造函数
/** * @param string | \Olifanton\Interop\Address $anyForm */ public function __construct(string | Address $anyForm)
参数
$anyForm
— 支持形式中的地址。支持值包括- 友好格式(base64 编码,URL 安全或不安全):
EQBvI0aFLnw2QbZgjMPCLRdtRHxhUyinQudg6sdiohIwg5jL
; - 原始格式:
-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260
; - 其他
Address
实例,在这种情况下,新实例将是其他地址的不可变副本。
- 友好格式(base64 编码,URL 安全或不安全):
根据传递的值,地址实例将存储关于输入地址标志的信息。
如果输入值不是一个有效的地址,则将抛出 \InvalidArgumentException
。
Address 静态方法
isValid(string | \Olifanton\Interop\Address $anyForm): bool
检查传递的值是否为任何形式的有效地址。
Address 方法
toString(): string
/** * @param bool|null $isUserFriendly User-friendly flag * @param bool|null $isUrlSafe URL safe encoded flag * @param bool|null $isBounceable Bounceable address flag * @param bool|null $isTestOnly Testnet Only flag */ public function toString(?bool $isUserFriendly = null, ?bool $isUrlSafe = null, ?bool $isBounceable = null, ?bool $isTestOnly = null): string
返回地址的字符串表示形式。
如果所有参数都保留为默认值,则地址将使用在构造函数中识别的相同标志进行格式化。
getWorkchain(): int
返回工作链 ID。对于 Masterchain 返回 -1
,对于基本工作链返回 0
。
getHashPart(): Uint8Array
返回地址账户 ID。
isTestOnly(): bool
如果地址具有 isTestnetOnly
标志,则返回 true。
isBounceable(): bool
如果地址具有 isBounceable
标志,则返回 true。
isUserFriendly(): bool
如果地址是用户友好的,则返回 true。
isUrlSafe(): bool
如果地址仅使用 URL 安全字符进行编码,则返回 true。
位字符串
Olifanton\Interop\Boc\BitString
BitString
是一个类,允许您操作二进制数据。BitString
是 PHP 中 TVM 单元的表示核心。BitString 对存储二进制数据进行了内存优化。内部,BitString 使用由 olifanton/typed-arrays
包提供的 Uint8Array
实现来操作,并作为在 Olifanton 库的不同部分之间传输二进制数据的基本类型。
BitString 实例使用严格固定的长度创建。`write%`(writeBit,writeUint,...)方法移动内部游标。如果您尝试写入超出空闲位长度的值,将抛出 BitStringException
异常。
BitString 构造函数
/** * @param int $length */ public function __construct(int $length)
参数
$length
— Uint8Array 的长度。TVM 单元的默认值:1023(文档)
BitString 方法
getFreeBits(): int
返回 BitString 的未使用位长度。
getUsedBits(): int
返回 BitString 的已使用位长度。
getUsedBytes(): int
返回BitString使用的字节长度。
get(): bool
/** * @param int $n Position */ public function get(int $n): bool
返回位于$n
位置的位值。
on(): void
/** * @param int $n Position */ public function on(int $n): void
将位置$n
的位值设置为1。
off(): void
/** * @param int $n Position */ public function off(int $n): void
将位置$n
的位值设置为0。
toggle(): void
/** * @param int $n Position */ public function toggle(int $n): void
切换(取反)位置$n
的位值。
iterate(): \Generator
返回已使用位的生成器。
示例
<?php declare(strict_types=1); use Olifanton\Interop\Boc\BitString; $bs = new BitString(4); $bs->writeBit(1); $bs->writeBit(0); $bs->writeBit(1); $bs->writeBit(1); foreach ($bs->iterate() as $b) { echo (int)$b; } // Prints "1011"
writeBit(): void
/** * @param int|bool $b */ public function writeBit(int | bool $b): void
写入位并增加BitString内部游标。
writeBitArray(): void
/** * @param array<int | bool> $ba Array of bits */ public function writeBitArray(array $ba): void
写入位数组。
示例
<?php declare(strict_types=1); use Olifanton\Interop\Boc\BitString; $bs = new BitString(4); $bs->writeBitArray([1, false, 0, true]); foreach ($bs->iterate() as $b) { echo (int)$b; } // Prints "1001"
writeUint(): void
/** * @param int|\Brick\Math\BigInteger $number Unsigned integer * @param int $bitLength Integer size (8, 16, 32, ...) */ public function writeUint(int | BigInteger $number, int $bitLength): void
写入$bitLength位的无符号整数。
writeInt(): void
/** * @param int|\Brick\Math\BigInteger $number Signed integer * @param int $bitLength Integer size (8, 16, 32, ...) */ public function writeInt(int | BigInteger $number, int $bitLength): void
写入$bitLength位的有符号整数。
writeUint8(): void
是writeUint()
方法的别名,具有预定义的$bitLength参数值。
writeBytes(): void
/** * @param \Olifanton\TypedArrays\Uint8Array $ui8 Byte array */ public function writeBytes(Uint8Array $ui8): void
写入无符号8位整数数组。
writeString(): void
/** * @param string $value */ public function writeString(string $value): void
写入UTF-8字符串。
writeCoins(): void
/** * @param int|\Brick\Math\BigInteger $amount */ public function writeCoins(int | BigInteger $amount): void;
以纳诺吨币的形式写入币(1 TON === 1000000000 (10^9) 纳诺吨币)。
writeAddress(): void
/** * @param \Olifanton\Interop\Address|null $address TON Address */ public function writeAddress(?Address $address): void
写入TON地址
writeBitString(): void
/** * @param \Olifanton\Interop\Boc\BitString $anotherBitString BitString instance */ public function writeBitString(BitString $anotherBitString): void
将另一个BitString写入此BitString。
clone(): BitString
克隆此BitString并返回新的BitString实例。
toHex(): string
返回BitString的十六进制字符串表示。
getImmutableArray(): Uint8Array
返回内部Uint8Array的不变副本。
getLength(): int
返回BitString的位数大小。
Cell
Olifanton\Interop\Boc\Cell
Cell
是一个类,它实现了PHP中的TVM Cells的概念。为了创建新的和处理从区块链接收的消息,您将使用Cell类的实例。
Cell构造函数
无参数。
Cell方法
fromBoc(): Array<Cell>
/** * @param string|Uint8Array $serializedBoc Serialized BoC * @return Cell[] */ public static function fromBoc(string|Uint8Array $serializedBoc): array
从字节数组或十六进制字符串创建Cell数组。
oneFromBoc(): Cell
/** * @param string|Uint8Array $serializedBoc Serialized BoC * @param bool $isBase64 Base64-serialized flag, default false */ public static function oneFromBoc(string|Uint8Array $serializedBoc, bool $isBase64 = false): Cell
从字节数组或十六进制字符串获取一个根Cell。
writeCell(): void
/** * @param Cell $anotherCell Another cell * @return Cell This Cell */ public function writeCell(Cell $anotherCell): self
将另一个Cell写入此Cell并返回此Cell。可变方法。
getMaxDepth(): int
返回子Cells的最大深度。
getBits(): BitString
返回用于写入和读取的内部BitString实例。
getRefs(): ArrayObject<Cell>
返回子Cells的类似数组对象。
hash(): Uint8Array
返回此Cell的SHA-256哈希值。
print(): string
递归打印单元格的内容,类似于Fift。
toBoc(): Uint8Array
/** * @param bool $has_idx Default _true_ * @param bool $hash_crc32 Default _true_ * @param bool $has_cache_bits Default _false_ * @param int $flags Default _0_ */ public function toBoc(bool $has_idx = true, bool $hash_crc32 = true, bool $has_cache_bits = false, int $flags = 0): Uint8Array
创建BoC字节数组。
Slice
Olifanton\Interop\Boc\Slice
Slice
是单元格切片的类型。可以将单元格转换为切片,然后可以通过从切片中加载它们来获取单元格中的数据位和其他单元格的引用。
load%
(loadBit,loadUint,...)方法移动Slice内部游标。如果您尝试读取超出空闲位长度的值,将抛出SliceException
异常。
Slice构造函数
/** * @param \Olifanton\TypedArrays\Uint8Array $array * @param int $length * @param \Olifanton\Interop\Boc\Slice[] $refs */ public function __construct(Uint8Array $array, int $length, array $refs)
参数
$array
— Uint8Array,它是Cell的BitString表示$length
— BitString长度$refs
— 子Cells切片
Slice方法
getFreeBits(): int
根据内部游标返回未读取的位。
get(): bool
/** * @param int $n */ public function get(int $n): bool
返回位置$n
的位值。
loadBit(): bool
读取位并移动游标。
loadBits(): Uint8Array
/** * @param int $bitLength */ public function loadBits(int $bitLength): Uint8Array
读取位数组。
loadUint(): BigInteger
/** * @param int $bitLength */ public function loadUint(int $bitLength): BigInteger
读取无符号整数。
loadInt(): BigInteger
/** * @param int $bitLength */ public function loadInt(int $bitLength): BigInteger
读取有符号整数。
loadVarUint(): BigInteger
/** * @param int $bitLength */ public function loadVarUint(int $bitLength): BigInteger
loadCoins(): BigInteger
读取TON金额(以纳诺吨币计)。
loadAddress(): ?Address
读取地址。
loadRef(): Slice
读取一个子Cell。
Builder
Olifanton\Interop\Boc\Builder
Builder允许您快速创建单元格(在BitString实例内操作)。Builder类的所有实例都是可变的,并且所有方法都返回相同的实例。在大多数情况下,Builder接口与BitString类的接口相同。
Hashmap
Olifanton\Interop\Boc\Hashmap
Hashmap
类是 PHP 中对 TL-B 字典结构的表示。
使用 Hashmap 类时,需要考虑以下特性:
- 键的内部状态始终是一个位数组;
- 值的内部状态始终是 Cell;
- 键的长度总是固定的。
由于内部状态的特性,在 Hashmap 中使用不同类型的键和值可能并不总是方便。为了简化字典的使用,可以将特殊闭包(作为 DictSerializers
的实例)传递给 Hashmap 类的构造函数,这些闭包简化了键到位数组的转换以及值到 Cells 的转换。
以下是一个使用字典的示例。键是一个有符号 32 位整数,值是一个无符号 128 位 BigInteger
use Olifanton\Interop\Boc\Hashmap; use Olifanton\Interop\Boc\DictSerializers; use Olifanton\Interop\Boc\Builder; use Olifanton\Interop\Boc\Cell; use Brick\Math\BigInteger; $dict = new Hashmap( 32, // Key size, // KV marshalling setup new DictSerializers( // closure converts a number into a bit array, using an intermediate cell (created by Builder) and toBitsA() helper method of BitString class keySerializer: static fn(int $userFriendlyKey, int $keySize): array => (new Builder())->writeInt($userFriendlyKey, $keySize)->cell()->bits->toBitsA(), // closure converts a bit array into a number, using an intermediate cell (created by Builder) keyDeserializer: static fn(array $bitsKey, int $keySize): int => (new Builder())->writeBitArray($bitsKey)->cell()->beginParse()->loadInt($keySize)->toInt(), // closure writes BigInteger value into Cell valueSerializer: static fn(BigInteger $userFriendlyValue): Cell => (new Builder())->writeUint($userFriendlyValue, 128)->cell(), // closure loads BigInteger value from Cell valueDeserializer: static fn(Cell $internalValue): BigInteger => $internalValue->beginParse()->loadUint(128), ) ); // add value to dictionary $dict->set(1, BigInteger::fromBase("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)); // now, internal Hashmap storage contains record with key [00000000000000000000000000000001] and Cell value var_dump($dict->get(1)->toBase(10)); // 340282366920938463463374607431768211455
在开发过程中,您可以实现任何闭包,以便将您的标量 KV 类型转换为键数组和值 Cells。您还可以使用在 DictSerializers
类的静态构造函数中提供的预定义序列化器
DictSerializers::uintKey()
DictSerializers::intKey()
DictSerializers::addressKey()
DictSerializers::intValue()
DictSerializers::uintValue()
我们可以将示例重写为使用预定义序列化器并减少代码量
$dict = new Hashmap( 32, DictSerializers::uintKey(isBigInt: false)->combine(DictSerializers::uintValue(128)), ); $dict->set(1, BigInteger::fromBase("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)); var_dump($dict->get(1)->toBase(10)); // 340282366920938463463374607431768211455
测试
composer run test
贡献
在提交 pull request 之前,请务必阅读 Olifanton 贡献指南。
设置环境
为开发准备您的环境。
请注意,说明描述了在 *nix 系统(Linux 和可能 macOS)上工作,Windows 上的开发可能很困难,并且这些说明中不会涉及。
您需要
- 最小 PHP 版本:8.1;
sodium
扩展;hash
扩展。
分支仓库
在您的 GitHub 账户中创建仓库分支。
克隆您的仓库
git clone git@github.com:<YOUR_GITHUB_NAME>/interop.git cd interop
创建 feature/
(或 hotfix/
)分支
git branch feature/<FEATURE_NAME> git checkout feature/<FEATURE_NAME>
创建 pull request
在您的本地分支实现新的功能(或热修复)后,您应该提交并推送更改到您的分支仓库。然后您可以创建 pull-request。
许可证
MIT