| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 | <?phpnamespace App\Helpers;use App\Helpers\TronHelper;class TronRawSerializer{    public static function serializeRawData(array $rawData): string    {        $bin = '';        // timestamp (field number = 1, wire type = 0)        $bin .= self::encodeKey(1, 0);        $bin .= self::encodeVarint($rawData['timestamp']);                // ref_block_bytes (2, wire type = 2)        $bin .= self::encodeKey(2, 2);        $refBlockBytes = hex2bin($rawData['ref_block_bytes']);        $bin .= self::encodeLengthDelimited($refBlockBytes);                // ref_block_hash (3, wire type = 2)        $bin .= self::encodeKey(3, 2);        $refBlockHash = hex2bin($rawData['ref_block_hash']);        $bin .= self::encodeLengthDelimited($refBlockHash);                // expiration (4, wire type = 0)        $bin .= self::encodeKey(4, 0);        $bin .= self::encodeVarint($rawData['expiration']);                // contract (5, repeated embedded message)        foreach ($rawData['contract'] as $contract) {            $bin .= self::encodeKey(5, 2);            $contractBin = self::serializeContract($contract);            $bin .= self::encodeLengthDelimited($contractBin);        }        // fee_limit (18, wire type = 0) — optional        if (isset($rawData['fee_limit'])) {            $bin .= self::encodeKey(18, 0);            $bin .= self::encodeVarint($rawData['fee_limit']);        }        return $bin;    }    protected static function serializeContract(array $contract): string    {        $bin = '';        // type (1, wire type = 0)        $bin .= self::encodeKey(1, 0);        $bin .= self::encodeVarint($contract['type']);        // parameter (2, embedded)        $bin .= self::encodeKey(2, 2);        $parameterBin = self::serializeParameter($contract['parameter']);        $bin .= self::encodeLengthDelimited($parameterBin);        return $bin;    }    protected static function serializeParameter(array $param): string    {        $bin = '';        if (isset($param['type_url'])) {            // type_url (1)            $bin .= self::encodeKey(1, 2);            $bin .= self::encodeLengthDelimited($param['type_url']);        }        if (isset($param['value'])) {            // value (2)            $bin .= self::encodeKey(2, 2);            $valueBin = self::serializeTriggerSmartContract($param['value']);            $bin .= self::encodeLengthDelimited($valueBin);        }        return $bin;    }    protected static function serializeTriggerSmartContract(array $value): string    {        $bin = '';        // owner_address (1)        $bin .= self::encodeKey(1, 2);        $bin .= self::encodeLengthDelimited(hex2bin($value['owner_address']));                // contract_address (2)        $bin .= self::encodeKey(2, 2);        $bin .= self::encodeLengthDelimited(hex2bin($value['contract_address']));         // call_value (3) — not used in TRC20        // data (4)        if (isset($value['data'])) {            $bin .= self::encodeKey(4, 2);            $bin .= self::encodeLengthDelimited(hex2bin($value['data']));        }        return $bin;    }    protected static function encodeKey($fieldNumber, $wireType): string    {        return self::encodeVarint(($fieldNumber << 3) | $wireType);    }    protected static function encodeVarint($value): string    {        $value = is_numeric($value) ? (int)$value : 0;        $bin = '';        while (true) {            if (($value & ~0x7F) === 0) {                $bin .= chr($value);                break;            } else {                $bin .= chr(($value & 0x7F) | 0x80);                $value >>= 7;            }        }        return $bin;    }    protected static function encodeLengthDelimited(string $data): string    {        return self::encodeVarint(strlen($data)) . $data;    }}
 |