From 2c0315df6703013fbcb55bc04f79bf37fc2fde27 Mon Sep 17 00:00:00 2001 From: Sebastix Date: Tue, 29 Oct 2024 12:32:06 +0100 Subject: [PATCH] NIP-19 work in progress --- src/Examples/bech32-encoded-entities.php | 22 +++++- src/Message/RequestMessage.php | 1 - src/Nip19/Nip19Helper.php | 94 +++++++++++++++++++++--- src/Nip19/TLVEnum.php | 8 +- 4 files changed, 106 insertions(+), 19 deletions(-) diff --git a/src/Examples/bech32-encoded-entities.php b/src/Examples/bech32-encoded-entities.php index 3aa848c..d67d92e 100644 --- a/src/Examples/bech32-encoded-entities.php +++ b/src/Examples/bech32-encoded-entities.php @@ -34,19 +34,35 @@ // TODO: // Encode to nevent with TLV data - // Encode it bech32 encoded nevent ID, - // $nevent = $nip19->encodeEvent($id); + $nevent = $nip19->encodeEvent($id, ['wss://nostr.sebastix.dev'], $pubkey, 1); // Expected result: // nevent1qqsy87cyyfzhc8ada35vttgcx79tktrzd44hsausjulg3rgfnrmva4qey0p0j // print $nevent . PHP_EOL; - // Encode to nprofile with TLV data + // Encode to pubkey profile with TLV data + $pubkey = '3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d'; + $relays = ['wss://r.x.com', 'wss://djbas.sadkb.com']; + $nprofile = $nip19->encodeProfile($pubkey, $relays); + // Expected result with TLV items: + // - pubkey: 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d + // - relay: wss://r.x.com + // - relay: wss://djbas.sadkb.com + // TODO // Encode to naddr with TLV data + // TODO // Decode a bech32 encoded entity to an event ID. $nevent = ''; + // TODO + // Decode to event with TLV data + $profile_id = 'nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p'; + // Expected result with TLV items: + // - pubkey: 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d + // - relay: wss://r.x.com + // - relay: wss://djbas.sadkb.com + } catch (Exception $e) { print $e->getMessage() . PHP_EOL; } diff --git a/src/Message/RequestMessage.php b/src/Message/RequestMessage.php index a5d48fa..e78970a 100644 --- a/src/Message/RequestMessage.php +++ b/src/Message/RequestMessage.php @@ -5,7 +5,6 @@ namespace swentel\nostr\Message; use swentel\nostr\MessageInterface; -use swentel\nostr\Filter; class RequestMessage implements MessageInterface { diff --git a/src/Nip19/Nip19Helper.php b/src/Nip19/Nip19Helper.php index 2833996..e204f94 100644 --- a/src/Nip19/Nip19Helper.php +++ b/src/Nip19/Nip19Helper.php @@ -6,6 +6,7 @@ use BitWasp\Bech32\Exception\Bech32Exception; use swentel\nostr\Key\Key; +use swentel\nostr\Nip19\TLVEnum; use function BitWasp\Bech32\convertBits; use function BitWasp\Bech32\encode; @@ -24,7 +25,9 @@ class Nip19Helper */ protected $prefix; - public function __construct() {} + public function __construct() + { + } public function decode(string $bech32string) { @@ -58,23 +61,61 @@ public function encodeNote(string $event_hex): string return $this->convertToBech32($event_hex, 'note'); } - public function encodeEvent(string $event_hex): string + /** + * @param string $event_hex + * @param array $relays + * @param string $author + * @param int $kind + * @return string + * @throws \Exception + */ + public function encodeEvent(string $event_hex, array $relays = [], string $author = '', int $kind = null): string { - $hexInBin = hex2bin($event_hex); // Convert hex formatted string to binary string. - if (strlen($hexInBin) !== 32) { - throw new \Exception(sprintf('This is an invalid ID: %s', $event_hex)); + $data = ''; + $prefix = 'nevent'; + $event_hex_in_bin = hex2bin($event_hex); // Convert hex formatted pubkey string to binary string. + if (strlen($event_hex_in_bin) !== 32) { + throw new \Exception(sprintf('This is an invalid event ID: %s', $event_hex)); + } + // TODO: process TLV entries + $tlvEntry = $this->writeTLVEntry(TLVEnum::Special, $event_hex_in_bin); + // Optional + if (!(empty($relays))) { + foreach ($relays as $relay) { + // Encode as ascii. + //$relay = implode('', unpack('C*', $relay)); + // Alternative which requires the icon PHP extension installed on the host machine. + // $relay = iconv('UTF-8', 'ASCII', $relay); + // decode ascii relay string + $tlvEntry .= $this->writeTLVEntry(TLVEnum::Relay, urlencode($relay)); + } + } + // Optional + if (!(empty($author))) { + if (strlen(hex2bin($author)) !== 32) { + throw new \Exception(sprintf('This is an invalid author ID: %s', $event_hex)); + } + // Convert hex formatted pubkey to 32-bit binary value. + $tlvEntry .= $this->writeTLVEntry(TLVEnum::Author, hex2bin($author)); } - // todo process TLV - return $this->convertToBech32($event_hex, 'nevent'); + // Optional + if ($kind !== null) { + // Convert kint int to unsigned integer, big-endian. + $v = pack('N', $kind); + $tlvEntry .= $this->writeTLVEntry(TLVEnum::Kind, $v); + } + $data = $tlvEntry; + + return $this->encodeBech32($data, $prefix); } - public function encodeProfile(string $profile_hex): string + public function encodeProfile(string $pubkey, array $relays = []): string { // todo return ''; } - public function encodeAddr(string $event_hex): string + public function encodeAddr(string $event_hex, int $kind, string $DTag, array $relays = []): string { // todo return ''; @@ -100,6 +141,19 @@ public function encodeNsec(string $seckey): string return $key->convertPrivateKeyToBech32($seckey); } + public function encodeBech32(string $value, string $prefix): string + { + // TODO + $bytes = []; + return encode($prefix, $bytes); + } + + /** + * @param string $key + * @param string $prefix + * @return string + * @throws Bech32Exception + */ private function convertToBech32(string $key, string $prefix): string { $str = ''; @@ -115,7 +169,25 @@ private function convertToBech32(string $key, string $prefix): string return $str; } - private function readTLVEntry($value) {} + private function readTLVEntry(string $data, TLVEnum $type) + { + } - private function writeTLVEntry($value, string $type) {} + /** + * @param \swentel\nostr\Nip19\TLVEnum $type + * @param string $value + * Binary string. + * @return string + */ + private function writeTLVEntry(TLVEnum $type, string $value) + { + // TODO + return $value; + } + + private function encodeTLV(Object $TLV): array + { + + return []; + } } diff --git a/src/Nip19/TLVEnum.php b/src/Nip19/TLVEnum.php index 069f159..4f02345 100644 --- a/src/Nip19/TLVEnum.php +++ b/src/Nip19/TLVEnum.php @@ -9,8 +9,8 @@ */ enum TLVEnum: int { - case TLVDefault = 0; - case TLVRelay = 1; - case TLVAuthor = 2; - case TLVKind = 3; + case Special = 0; + case Relay = 1; + case Author = 2; + case Kind = 3; } \ No newline at end of file