<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/src/dm.js, branch master</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=master</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-10-09T15:48:06Z</updated>
<entry>
<title>DMs: a linked nostr login whose signer hadn't resumed yet (a reload before the bunker reconnected, a session just dropped) counted as "every key is here", so each wrap sealed to the login npub was tried on the wallet key alone, given up after ~40 s and logged as opened — never asked for again (a phone kept 9 of 186 messages). Since b06bbb4 the check only passes with no login or a live signer that decrypts (or Amber); a drain without one waits for the signer instead of re-running the wallet key, and the slow retry is rescheduled in finally so an early return can't end it. "All promises were rejected" (every relay refused the bunker request) and "not open anymore" count as try-later, not "not ours". Heal v2 re-opens every wrap the relays still hold, marked done only once nothing it re-opened is still waiting for the signer</title>
<updated>2026-10-09T15:48:06Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-09T15:48:06Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=e1e6665910f77009d61947528dcf4a0a528e03fc'/>
<id>urn:sha1:e1e6665910f77009d61947528dcf4a0a528e03fc</id>
<content type='text'>
Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MgAFLnkF7KrdhuyCLMNgtL
</content>
</entry>
<entry>
<title>Custom emoji in chat: :shortcodes: render as pictures, packs sync with Vector.</title>
<updated>2026-09-15T16:27:45Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-15T16:27:45Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=c90d0f3c600802b5b4b43959df5fd2d02f78012c'/>
<id>urn:sha1:c90d0f3c600802b5b4b43959df5fd2d02f78012c</id>
<content type='text'>
A message from Vector says :pika_wave: and carries a NIP-30
["emoji", code, url] tag for it; coinos showed the bare shortcode. Now the
bubble shows the picture (in rooms, DMs, the feed and the public /chat
page), a bubble that is only one to three of them shows them big, and a
:code: reaction chip is a picture too.

Sending: every :code: you type that resolves travels with its tag, so the
other side renders it whether or not they hold the pack. Shortcodes come
from packs you hold (NIP-51 kind 30030 sets) and from what you've seen in
chat, so anyone can answer a :pika_wave: with one. The composer
autocompletes on ":pi" (Tab/Enter takes the first), the reaction picker
lists custom emoji first, and Vector's pack share link renders with an
Add button; a pasted naddr works too.

Packs live on your kind 10030 list — the one Vector reads and writes — so
a pack added in either app appears in both. tools/emoji-test.js drives the
real coinos room headlessly and checks all of the above.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
</content>
</entry>
<entry>
<title>A picture can be sent to a channel or a DM, encrypted, and read by Vector.</title>
<updated>2026-09-15T02:25:06Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-15T02:25:06Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=b363da843ffcaea89a9ec11ce0cacc180a824f00'/>
<id>urn:sha1:b363da843ffcaea89a9ec11ce0cacc180a824f00</id>
<content type='text'>
The composer grows a paper clip. A picked file is encrypted under a
fresh AES-GCM key and 16-byte nonce, the ciphertext uploaded to a public
Blossom host that takes anonymous blobs (blossom.ditto.pub, then
nostr.download as a fallback copy), and the pointer posted the way
Vector posts it: a kind-9 with empty content and a NIP-92 imeta tag
carrying url, mime, key, nonce, both hashes, size and dimensions. In a
DM it is a NIP-17 kind-15 file message with the same fields as flat
tags and the url as content, wrapped to the peer and to ourselves.
Kind-15 file messages are now accepted on receive too, rendered like
any attachment, and previewed as a photo in the thread list.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Messages sent while the app was away arrive when it comes back.</title>
<updated>2026-09-15T01:05:05Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-15T01:05:05Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=4c4917b3697050e0a83d6977d76a76e6f436d5b7'/>
<id>urn:sha1:4c4917b3697050e0a83d6977d76a76e6f436d5b7</id>
<content type='text'>
Two ways a DM or a room message went missing. A phone freezing the tab
errors the relay sockets, and an errored socket is one the pool gives up
on — so every wrap subscription died silently and nothing sent after the
freeze ever arrived, until a reload. Coming back from the background (or
back online) now rebuilds the DM and room subscriptions; their windows
overlap what is held and seen wraps are dropped before any decryption.

And a remote signer that never answered was read as "this wrap isn't
ours": three such silences and the wrap was remembered as seen and lost
on that device for good. Silence now means "try later" — uncounted — and
the drain stops at the first one rather than burning tries on the rest.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
</content>
</entry>
<entry>
<title>The tap-a-bubble action sheet works in DMs too: reactions + Reply + Copy (no Delete — a gift-wrapped DM can't be retracted from the peer's relays). DM reactions ride the kind-7-in-a-gift-wrap shape 0xchat uses (makeDMReaction in dm.js), sent to the peer and echoed to our own inbox so other devices fold them in; inbound kind-7 rumors land in dmReacts keyed by the reacted message's id — no thread lookup, so a reaction arriving before its message still sticks. Replies e-tag the quoted kind-14 (makeDMRumor grew extraTags) and render the same accent-bar quote as community chat; the composer gets the same replying-to bar. Chips are joinable and your own reaction is highlighted/replaceable, all optimistic with rollback. Round-trip verified: reply and reaction rumors wrap/unwrap with tags intact</title>
<updated>2026-09-04T22:25:06Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-04T22:25:06Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=b9987703de8b3ca89f93dbd9995412c9f47f7de2'/>
<id>urn:sha1:b9987703de8b3ca89f93dbd9995412c9f47f7de2</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
</content>
</entry>
<entry>
<title>Google accounts can speak: the DM seal signs with the present for remote signers (the pomegranate FROST operators refuse backdated events, and NIP-59's tweak on the seal protects nothing — only the recipient ever sees that layer; the public-facing wrap keeps its tweak under our own ephemeral key), and the registrar welcomes each PERSON once instead of once per key — the Google flow's two claims (wallet key, then real npub with the wallet as manager) were earning the same inbox two identical greetings</title>
<updated>2026-08-31T06:01:26Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-31T06:01:26Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=b775d2b29bcc2964cbc374771f86ce39d83cb8b7'/>
<id>urn:sha1:b775d2b29bcc2964cbc374771f86ce39d83cb8b7</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
</content>
</entry>
<entry>
<title>A message sends the instant you let go of it: the rumor hashes synchronously onto the screen as a dimmed bubble, crypto and relays catch up in the background, and one small tick marks the moment a relay takes it</title>
<updated>2026-08-18T19:06:04Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-18T19:06:04Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=a0374566a5c69d87e5a156f5fabecf5b9b45d6f9'/>
<id>urn:sha1:a0374566a5c69d87e5a156f5fabecf5b9b45d6f9</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
</content>
</entry>
<entry>
<title>Chat v2: DMs, invites, and multi-community — coinos is the default, not the only</title>
<updated>2026-08-02T20:40:54Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-02T20:40:54Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=95263c02a13a825a8d02dbe760f2a74de8f93f77'/>
<id>urn:sha1:95263c02a13a825a8d02dbe760f2a74de8f93f77</id>
<content type='text'>
- NIP-17 private DMs (src/dm.js): kind-14 rumors in sender-signed seals under
  ephemeral wraps; interops with other nostr DM clients. Login signers gained
  encryptTo/decryptFrom so extensions and bunkers can seal to a peer; the
  inbox listens for both the login npub and the wallet key and publishes a
  kind-10050 DM-relay list for the wallet key when none exists.
- Concord invites (CORD-05): mint shareable links (33301 bundle on relays,
  keys only in the URL fragment), join by pasting a link or opening
  v3.coinos.io/invite/…, and direct invites giftwrapped to an npub with the
  k-tag index hint. Bundles self-certify the founder before anything joins.
- Multi-community: home view lists DM threads and communities; found your own
  community in-app (owner-signed genesis). coinos stays baked in as default.
- Welcome DM: the names registrar DMs every first-time registrant from Adam's
  npub on claim (config: welcome{sk,message}; deduped in registrar state).
  Every new wallet auto-claims a payment address, so every new user gets one.
- relay.coinos.io write policy now allows 33301/13302/13303.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
</content>
</entry>
</feed>
