โœ‰๏ธ iodine.js - private messages

iodine.js is a miniature encrypted messenger: NIP-17 direct messages sealed and gift wrapped per NIP-59, in about 4kb. A form sends a message to someone's DM relays (their kind 10050 list), and a list shows your inbox, unwrapped and rendered like any other xenon feed. It composes with xenon.js, neon.js and radon.js, and signs and encrypts with any signer that has nip44: a NIP-07 extension, chlorine.js, or helium.js with fluorine.js.

<form nio-send nio-to="npub1..."><textarea name="content"></textarea><button>Send</button></form>
<ol nio-inbox nio-with="npub1...">
  <template><li><b nrn-profile="{pubkey}" nrn-field="name">{npub}</b> <p>{content}</p></li></template>
</ol>

The form wraps each message twice, once for the recipient and once for you, and the list shows your conversation with that npub, newest first.

Attributes

attribute description
nio-send Form that sends its content field as a private message on submit
nio-to Recipient (npub, nprofile or hex). Falls back to a form field named to
nio-inbox Subscribes to your gift wraps (kinds:[1059], #p:[you]) and renders the unwrapped messages with the element's template
nio-with Only keep messages from or to this pubkey (npub or hex)
nio-ignore iodine skips this element and its descendants

The inbox sets nxe-filter and nar-ignore on itself and hands over to xenon, so every nxe-* attribute, template field and nxe:* event works as usual, on the decrypted message. It reads from your own kind 10050 relays when you have them, else from the closest nhy-relay or nhyCfg.relays, which are also where messages go when a recipient has no DM relays.

Events

event cancel to detail
nio:send skip sending rumor (unsigned kind 14, editable), recipients
nio:sent rumor, recipients, results per relay
nio:error error
nio:message skip rendering wrap, rumor (on the inbox)

API

function returns
iodine.send(to, content, relays?) promise of results, after wrapping for to and yourself
iodine.wrap(rumor, pubkey) promise of a signed kind 1059 gift wrap for pubkey
iodine.unwrap(wrap) promise of the rumor, or undefined if it is not for you or does not check out
iodine.relays(pubkey) promise of the DM relays in pubkey's kind 10050 list, [] after 3s

Requires xenon.js and helium.js, fluorine.js for the gift wrap layer, and neon.js for npub recipients.

Caveats

Extensions ask for permission to decrypt, often once per message. Messages are never cached by argon.js, so the inbox decrypts everything again on every load. Metadata privacy comes from the gift wraps: relays see only random keys, randomized times and ciphertext, though each wrap's p tag names its recipient and relays still see your IP address. Messages have no delivery receipts or deletion.

iodine.js (3.9/1.6kb raw/brotli), prefix nio-, needs hydrogen, helium, fluorine, xenon

← ๐Ÿ”Œ chlorine๐Ÿฅ‡ gold →