crypto = $crypto; $this->credentials = $credentials; } public function createKey( string $address, int $fee, ?int $timestamp = null, ): SignedTransaction { $timestamp ??= time(); $unsigned = [ 'txtype' => 100, 'time' => $timestamp, 'address' => $address, 'txfee' => $fee, ]; return $this->sign( $unsigned, Binary::u8(100) . Binary::u32($timestamp) . Address::toBytes($address) . Binary::u64($fee), ); } public function boolean( string $storageKey, string $key, bool $value, string $address, int $fee, ?int $timestamp = null, ): SignedTransaction { return $this->value(101, $storageKey, $key, $value, $address, $fee, $timestamp); } public function u8(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(102, $storageKey, $key, $value, $address, $fee, $timestamp); } public function u16(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(103, $storageKey, $key, $value, $address, $fee, $timestamp); } public function u32(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(104, $storageKey, $key, $value, $address, $fee, $timestamp); } public function u64(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(105, $storageKey, $key, $value, $address, $fee, $timestamp); } public function i8(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(108, $storageKey, $key, $value, $address, $fee, $timestamp); } public function i16(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(109, $storageKey, $key, $value, $address, $fee, $timestamp); } public function i32(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(110, $storageKey, $key, $value, $address, $fee, $timestamp); } public function i64(string $storageKey, string $key, int $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value(111, $storageKey, $key, $value, $address, $fee, $timestamp); } public function u128(string $storageKey, string $key, string $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value128(106, $storageKey, $key, $value, $address, $fee, $timestamp); } public function i128(string $storageKey, string $key, string $value, string $address, int $fee, ?int $timestamp = null): SignedTransaction { return $this->value128(112, $storageKey, $key, $value, $address, $fee, $timestamp); } public function string( string $storageKey, string $key, string $value, string $address, string $previousHash, int $fee, ?int $timestamp = null, ): SignedTransaction { $timestamp ??= time(); $key = Binary::fixedText($key, 50, 'Storage data key'); $value = Binary::fixedText($value, 180, 'Storage string value'); $unsigned = [ 'txtype' => 107, 'time' => $timestamp, 'storagekey' => $storageKey, 'key' => $key, 'value' => $value, 'address' => $address, 'previous' => $previousHash, 'txfee' => $fee, ]; $binary = Binary::u8(107) . Binary::u32($timestamp) . RequestBuilder::hash($storageKey, 'Storage key') . $key . $value . Address::toBytes($address) . RequestBuilder::hash($previousHash, 'Previous string transaction hash') . Binary::u64($fee); return $this->sign($unsigned, $binary); } public function delete( string $storageKey, string $key, string $address, int $fee, ?int $timestamp = null, ): SignedTransaction { $timestamp ??= time(); $key = Binary::fixedText($key, 50, 'Storage data key'); $unsigned = [ 'txtype' => 113, 'time' => $timestamp, 'storagekey' => $storageKey, 'key' => $key, 'address' => $address, 'txfee' => $fee, ]; $binary = Binary::u8(113) . Binary::u32($timestamp) . RequestBuilder::hash($storageKey, 'Storage key') . $key . Address::toBytes($address) . Binary::u64($fee); return $this->sign($unsigned, $binary); } private function value( int $type, string $storageKey, string $key, bool|int $value, string $address, int $fee, ?int $timestamp, ): SignedTransaction { $timestamp ??= time(); $key = Binary::fixedText($key, 50, 'Storage data key'); $valueBytes = match ($type) { 101 => Binary::u8($value === true ? 1 : 0), 102 => Binary::u8($this->integer($value)), 103 => Binary::u16($this->integer($value)), 104 => Binary::u32($this->integer($value)), 105 => Binary::u64($this->integer($value)), 108 => Binary::i8($this->integer($value)), 109 => Binary::i16($this->integer($value)), 110 => Binary::i32($this->integer($value)), 111 => Binary::i64($this->integer($value)), default => throw new ProtocolException("Unsupported storage value type $type."), }; $unsigned = [ 'txtype' => $type, 'time' => $timestamp, 'storagekey' => $storageKey, 'key' => $key, 'value' => $value, 'address' => $address, 'txfee' => $fee, ]; $binary = Binary::u8($type) . Binary::u32($timestamp) . RequestBuilder::hash($storageKey, 'Storage key') . $key . $valueBytes . Address::toBytes($address) . Binary::u64($fee); return $this->sign($unsigned, $binary); } private function integer(bool|int $value): int { if (!is_int($value)) { throw new ProtocolException('Numeric storage values must be integers.'); } return $value; } private function value128( int $type, string $storageKey, string $key, string $value, string $address, int $fee, ?int $timestamp, ): SignedTransaction { $timestamp ??= time(); $key = Binary::fixedText($key, 50, 'Storage data key'); $value = trim($value); $valueBytes = $type === 106 ? Binary::u128($value) : Binary::i128($value); // serde_json writes Rust u128/i128 values as unquoted decimal numbers. $json = '{"txtype":' . $type . ',"time":' . $timestamp . ',"storagekey":' . json_encode($storageKey, JSON_THROW_ON_ERROR) . ',"key":' . json_encode($key, JSON_THROW_ON_ERROR) . ',"value":' . $value . ',"address":' . json_encode($address, JSON_THROW_ON_ERROR) . ',"txfee":' . $fee . '}'; $digest = $this->crypto->skein256($json); $signature = $this->crypto->sign( $digest, $this->credentials->privateKey, $this->credentials->publicKey, ); $binary = Binary::u8($type) . Binary::u32($timestamp) . RequestBuilder::hash($storageKey, 'Storage key') . $key . $valueBytes . Address::toBytes($address) . Binary::u64($fee); return new SignedTransaction($binary . $signature, $signature, $json); } }