NAME

Net::Nostr::Bech32 - NIP-19 bech32-encoded entities

SYNOPSIS

use Net::Nostr::Bech32 qw(
    encode_npub decode_npub
    encode_nsec decode_nsec
    encode_note decode_note
    encode_nprofile decode_nprofile
    encode_nevent   decode_nevent
    encode_naddr    decode_naddr
    decode_bech32_entity
);

# Bare keys and ids
my $npub = encode_npub('7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e');
# npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg

my $hex = decode_npub($npub);
# 7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e

my $nsec = encode_nsec($privkey_hex);
my $note = encode_note($event_id_hex);

# TLV entities with metadata
my $nprofile = encode_nprofile(
    pubkey => $hex_pubkey,
    relays => ['wss://relay1.com', 'wss://relay2.com'],
);
my $data = decode_nprofile($nprofile);
# { pubkey => '...', relays => ['wss://relay1.com', 'wss://relay2.com'] }

my $nevent = encode_nevent(
    id     => $event_id_hex,
    relays => ['wss://relay.com'],
    author => $pubkey_hex,
    kind   => 1,
);
my $data = decode_nevent($nevent);
# { id => '...', relays => [...], author => '...', kind => 1 }

my $naddr = encode_naddr(
    identifier => 'my-article',
    pubkey     => $hex_pubkey,
    kind       => 30023,
    relays     => ['wss://relay.com'],
);
my $data = decode_naddr($naddr);
# { identifier => 'my-article', pubkey => '...', kind => 30023, relays => [...] }

# Auto-detect and decode any NIP-19 entity
my $result = decode_bech32_entity($any_bech32_string);
say $result->{type};  # 'npub', 'nsec', 'note', 'nprofile', 'nevent', 'naddr'
say $result->{data};  # hex string for bare types, hashref for TLV types

DESCRIPTION

Implements NIP-19 bech32-encoded entities for human-friendly display of Nostr keys, event IDs, and shareable identifiers with metadata.

These encodings are for display and sharing only. They MUST NOT be used in NIP-01 event fields or filters - use hex format there.

Uses bech32 (not bech32m) encoding per the NIP-19 specification.

FUNCTIONS

All functions are exportable. None are exported by default.

encode_npub

my $npub = encode_npub($hex_pubkey);

Encodes a 64-char hex public key as an npub bech32 string.

my $npub = encode_npub('7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e');
# npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg

decode_npub

my $hex = decode_npub($npub);

Decodes an npub bech32 string to a 64-char hex public key. Croaks if the prefix is not npub.

my $hex = decode_npub('npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg');
# 7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e

encode_nsec

my $nsec = encode_nsec($hex_privkey);

Encodes a 64-char hex private key as an nsec bech32 string.

my $nsec = encode_nsec('67dea2ed018072d675f5415ecfaed7d2597555e202d85b3d65ea4e58d2d92ffa');
# nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5

decode_nsec

my $hex = decode_nsec($nsec);

Decodes an nsec bech32 string to a 64-char hex private key. Croaks if the prefix is not nsec.

encode_note

my $note = encode_note($hex_event_id);

Encodes a 64-char hex event ID as a note bech32 string.

my $note = encode_note('a' x 64);

decode_note

my $hex = decode_note($note);

Decodes a note bech32 string to a 64-char hex event ID. Croaks if the prefix is not note.

encode_nprofile

my $nprofile = encode_nprofile(pubkey => $hex, relays => \@relays);

Encodes a profile identifier with optional relay hints using TLV format. pubkey is required. relays is optional.

my $nprofile = encode_nprofile(
    pubkey => '3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d',
    relays => ['wss://r.x.com', 'wss://djbas.sadkb.com'],
);

decode_nprofile

my $data = decode_nprofile($nprofile);
# { pubkey => '...', relays => [...] }

Decodes an nprofile bech32 string. Returns a hashref with pubkey and relays (arrayref, possibly empty). Unknown TLV types are ignored.

encode_nevent

my $nevent = encode_nevent(id => $hex, relays => \@r, author => $hex, kind => $int);

Encodes an event identifier with optional metadata. id is required. relays, author, and kind are optional.

my $nevent = encode_nevent(
    id     => $event_id,
    relays => ['wss://relay.com'],
    author => $pubkey_hex,
    kind   => 1,
);

decode_nevent

my $data = decode_nevent($nevent);
# { id => '...', relays => [...], author => '...' or undef, kind => N or undef }

Decodes an nevent bech32 string. Returns a hashref. author and kind are undef if not present in the encoding.

encode_naddr

my $naddr = encode_naddr(
    identifier => $d_tag, pubkey => $hex, kind => $int, relays => \@r,
);

Encodes an addressable event coordinate. identifier, pubkey, and kind are required. relays is optional. Use empty string for identifier for normal replaceable events.

my $naddr = encode_naddr(
    identifier => 'my-article',
    pubkey     => $pubkey_hex,
    kind       => 30023,
);

decode_naddr

my $data = decode_naddr($naddr);
# { identifier => '...', pubkey => '...', kind => N, relays => [...] }

Decodes an naddr bech32 string.

decode_bech32_entity

my $result = decode_bech32_entity($bech32_string);
say $result->{type};  # 'npub', 'nsec', 'note', 'nprofile', 'nevent', 'naddr'
say $result->{data};  # hex string or hashref

Auto-detects the entity type from the bech32 prefix and decodes it. For bare types (npub, nsec, note), data is a hex string. For TLV types (nprofile, nevent, naddr), data is a hashref.

my $r = decode_bech32_entity('npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg');
say $r->{type};  # 'npub'
say $r->{data};  # '7e7e9c42...'

SEE ALSO

Net::Nostr, Net::Nostr::Key, Bitcoin::Crypto::Bech32