This commit fixes an issue where the Damus relay (Or other bootstrap relays) would be added to the user's relay list even though they explicitly removed it. The root cause of the issue lies in the way we load bootstrap relays. The default bootstrap relays would be initially loaded even though the user already has a bootstrap list stored, just in case all the relays on the user list fails. This would cause the app to inadvertently connect to relays that the user did not select whenever there is a connectivity issue with all their listed relays. The fix is to simply not add the default bootstrap list when the user already has a list stored. We do not need to use bootstrap relays in order to get our relay list, because that list is already stored in both UserDefaults as well as on NostrDB through the user's contact list event. (A contact list which is also locally loaded on startup since the fix related to https://github.com/damus-io/damus/issues/2057) Issue reproduction + Testing ---------------------------- Procedure: 1. Disconnect from all relays, and disconnect from the Damus relay last. 2. Connect to a local relay (that you control). Connection should be successful. 3. Quit the app completely. 4. Stop the local relay. 5. Restart the app. 6. Go to the relay list view. 7. Check the relay list. It should list the one local relay selected by the user Issue reproduction: - Device: iPhone 15 simulator - iOS: 17.4 - Damus: 1.8 (`97169f4fa276723bfab28ca304953ec206c904d2`) - Result: ISSUE REPRODUCED - Details: On step 7, the relay list only lists the Damus relay Fix test: - Device: iPhone 15 simulator - iOS: 17.4 - Damus: This commit - Result: PASS - Details: On step 7, the local relay is listed even though connection is unsuccessful. No notes are loaded since no relays were able to connect successfully Quick regression check ---------------------- PASS Device: iPhone 15 simulator iOS: 17.4 Damus: This commit Steps: 1. Reinstall app from scratch 2. Create a new account, go through onboarding 3. Make sure that new account connects to bootstrap relays. PASS 4. Sign out 5. Sign in with previously existing account (The one from the previous test) (Notice no UserDefaults exists for this user at that point) 6. Make sure relay list is loaded to the latest relay list known to the bootstrap relays (i.e. connects only to the Damus relay) (It cannot recover the latest relay list pointing only to the local relay, since the bootstrap relays have no knowledge about that relay or the contact lists stored there.). PASS Note: The behavior on step 6 is not a bug, it is an expected limitation. In fact, this behavior is privacy protecting, as the user may not want those public relays from knowing about its connection preference to the local relay (and its address) Other information ------------------ Q: How is this test using local relays related or equivalent to Tor relay list described in #2186? A: Those Tor relays need dedicated software (such as Orbot VPN) to be running successfully in order for Damus to make a successful connection to them. If at any moment that VPN stops working, it would trigger the same situation as described in the test above, where all relay connections fail at once. Q: In #2186, the user reports that the Damus relay is added, but does not describe the Damus relay replacing existing relays. What is the difference? A: I believe the difference is in the order in which relays are added or removed. We have to remember that the relay we just disconnected from will likely still have version N-1 of our contact list event, where it still includes itself on that list. Changelog-Fixed: Fix issue where bootstrap relays would inadvertently be added to the user's list on connectivity issues Closes: https://github.com/damus-io/damus/issues/2186 Signed-off-by: Daniel D’Aquino <daniel@daquino.me> Reviewed-by: William Casarin <jb55@jb55.com>
damus
A twitter-like nostr client for iPhone, iPad and MacOS.
How is Damus better than twitter?
There are no toxic algorithms.
You can send or receive zaps (satoshis) without asking for permission.
There is no central database. Therefore, Damus is censorship resistant.
There are no ads.
You don't have to reveal sensitive personal information to sign up.
No email is required.
No phone number is required.
Damus is free and open source software.
There is no Big Tech moat. Therefore, seamless interoperability with thousands or millions of other nostr apps is possible, and is how Damus and nostr win.
If there are no ads, how is Damus funded?
Damus offers a paid subscription 🟣 purple 🟣 https://damus.io/purple/.
Initial benefits include a unique subscriber number, subscriber badge, and auto-translate powered by DeepL.
Damus has also graciously received donations or grants from hundreds of Damus users, Opensats, and the Human Rights Foundation.
Spec Compliance
damus implements the following Nostr Implementation Possibilities
- NIP-01: Basic protocol flow
- NIP-04: Encrypted direct message
- NIP-08: Mentions
- NIP-10: Reply conventions
- NIP-12: Generic tag queries (hashtags)
- NIP-19: bech32-encoded entities
- NIP-21: nostr: URI scheme
- NIP-25: Reactions
- NIP-42: Authentication of clients to relays
- NIP-56: Reporting
Getting Started on Damus
Damus iOS
- Get the Damus app on the iOS App Store: https://apps.apple.com/ca/app/damus/id1628663131
⚙️ Settings (gear icon, top right)
- Relays: You can add more relays to send your notes to by tapping the "+".
- Find more relays to add: https://nostr.info/relays/
- Public Key (pubkey): Your public, personal address and how people can find and tag you
- Secret Key: Your private key unique to you. Never share your private key publicly and share with other clients at your own risk!
- Save your keys somewhere safe
- Log out
🏠 Personal Feed (home icon, bottom navigation)
- Feed from everyone you follow
- Can post notes by tapping the blue + button
Notes (under 🏠 Personal Feed)
- Sending a Note is easy and it goes to both your 🏠 Personal and 🔍 Global Feeds
- To tag a user you must grab their pubkey:
- Search their username in the search bar at the top of the 🔍 Global Feed and click their profile
- Tap the 🔑 icon which will copy their pubkey to your clipboard
- Go back to your 🏠 Personal Feed and tap the blue + button to compose your Note
- Add @ directly followed by the pubkey (e.g.,
@npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s)
- You can also tap the ellipsis menu of a Note (three dots in top right of note) to grab their User ID aka pubkey or Note ID to link directly to a Note.
- Currently you can't delete your Notes in the iOS app
- Share images by pasting the image url which you can grab from nostr.build, imgbb, imgur, etc. (i.e.,
https://i.ibb.co/2SHZbwm/alpha60.jpg). Currently images only load for people you follow in the 🏠 Personal Feed. Images are not automatically loaded in 🔍 Global Feed - Engaging with Notes
- 💬 Replying to a Note: Tap the chat icon underneath the note. This will show up in the users’ notifications and in your 🏠 Personal and 🔍 Global Feeds
- ♺ Reposts: Tap the repost icon which will show up in your 🏠 Personal and 🔍 Global Feeds
- ♡ Likes: Tap the heart icon. Users will not get a notification, and cannot see who liked their note (currently, web clients can see your pfp only)
💬 Encrypted DMs (chat app, bottom navigation)
- Tap the chat icon and you'll notice there's nothing to see at first. Go to a user profile and tap the 💬 chat icon next to the follow button to begin a DM
🔍 Global Feed (magnify glass, bottom navigation)
- View the Global Feed from all the relays you've added in ⚙️ Settings. Currently you can only search hashtags and user names and pubkeys
🔔 Notifications
- All your notifications except 💬 DMs
👤 Change Your Profile (PFP) and Bio
- Go to your Profile Page on Damus app
- Tap on Edit button at the top
- You will see text fields to update your information and bio
- For PFP, insert a URL containing your image (support video: https://cdn.jb55.com/vid/pfp-editor.mp4)
- Save
⚡️ Request Sats
Paste an invoice from your favorite LN wallet. (Sats or Satoshis are the smallest denomination of bitcoin)
Alby (browser extension)
- Get the Alby browser extension and create your Alby address [yourname]@getalby.com or connect your existing Lightning wallet
- Convert your Damus secret key from nsec to hex at https://damus.io/key then go to Settings in Alby and under the Nostr section at the bottom of the page add your private hex key. You can also generate new address in the extension
- Click the Alby extension > click Receive > enter the amount of Sats > click Get Invoice > click Copy > then paste into Damus
- Note: On Damus Web it will appear as a string of characters but on Damus iOS it will appear as a clickable image
Zeus (mobile app)
- Download Zeus app (iOS, Google, APK)
- Tap Get Started button > tap Connect a node > click on + sign (top right) > select Indhub > press Scan Lndhub QR > (from the Alby browser extension… click your account on the top left > click Manage Accounts > click 3-dot menu to right of your account and click Export Account to get a QR code then go back to Zeus app) > scan the QR Code and tap Save Node Config button
- To create an invoice tap Lightning > tap Receive > type in amount > tap Create Invoice > tap Copy Invoice > paste into a new Damus note
Contributing
Contributors welcome! Start by examining known issues: https://github.com/damus-io/damus/issues.
Mailing lists
We have a few mailing lists that anyone can join to get involved in damus development:
- dev - development discussions
- patches - code submission and review
- product - product discussions
- design - design discussions
Contributing
Privacy
Your internet protocol (IP) address is exposed to the relays you connect to, and third party media hosters (e.g. nostr.build, imgur.com, giphy.com, youtube.com etc.) that render on Damus. If you want to improve your privacy, consider utilizing a service that masks your IP address (e.g. a VPN) from trackers online.
The relay also learns which public keys you are requesting, meaning your public key will be tied to your IP address.
It is public information which other profiles (npubs) you are exchanging DMs with. The content of the DMs is encrypted.
Translations
Translators welcome! Join the Transifex project.
All user-facing strings must have a comment in order to provide context to translators. If a SwiftUI component has a comment parameter, use that. Otherwise, wrap your string with NSLocalizedString with the comment field populated.
Awards
Damus lead dev and founder Will awards developers with satoshis! There may be nostr badges awarded for contributors in the future... :)
First contributors:
- @randymcmillan
- @jcarucci27
git log bot
npub1fjtdwclt9lspjy8huu3qklr7eklp5uq90u6yh8mec290pqxraccqlufnas