diff --git a/api/nostr.py b/api/nostr.py index ada3513b..54c9ceb4 100644 --- a/api/nostr.py +++ b/api/nostr.py @@ -27,6 +27,7 @@ class Nostr: # Add relays and connect await client.add_relay("ws://localhost:7777") + await client.add_relay("ws://localhost:7778") await client.connect() robot_name = await self.get_robot_name(order) diff --git a/docker/strfry/strfry.conf b/docker/strfry/strfry.conf index 01fb191a..05061fc6 100644 --- a/docker/strfry/strfry.conf +++ b/docker/strfry/strfry.conf @@ -44,7 +44,7 @@ relay { bind = "0.0.0.0" # Port to open for the nostr websocket protocol (restart required) - port = 7777 + port = 7778 # Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set) (restart required) nofiles = 1000000 diff --git a/frontend/src/components/BookTable/BookControl.tsx b/frontend/src/components/BookTable/BookControl.tsx index 53909023..f07ab883 100644 --- a/frontend/src/components/BookTable/BookControl.tsx +++ b/frontend/src/components/BookTable/BookControl.tsx @@ -56,6 +56,9 @@ const BookControl = ({ const handleHostChange = function (e: React.ChangeEvent): void { const coordinator = String(e.target.value); + if (coordinator === 'any') { + federation.refreshBookHosts(coordinator !== 'any'); + } setFav({ ...fav, coordinator }); }; diff --git a/frontend/src/contexts/FederationContext.tsx b/frontend/src/contexts/FederationContext.tsx index cf336399..04d75896 100644 --- a/frontend/src/contexts/FederationContext.tsx +++ b/frontend/src/contexts/FederationContext.tsx @@ -35,7 +35,7 @@ export const FederationContext = createContext(initialFe export const FederationContextProvider = ({ children, }: FederationContextProviderProps): JSX.Element => { - const { settings, page, origin, hostUrl, open, torStatus, client } = + const { settings, page, origin, hostUrl, open, torStatus, client, fav } = useContext(AppContext); const { setMaker, garage } = useContext(GarageContext); const [federation] = useState(new Federation(origin, settings, hostUrl)); @@ -57,7 +57,7 @@ export const FederationContextProvider = ({ if (client !== 'mobile' || torStatus === 'ON' || !settings.useProxy) { void federation.updateUrl(origin, settings, hostUrl); void federation.loadLimits(); - federation.setConnection(settings); + federation.setConnection(settings, fav.coordinator); } }, [settings.network, settings.useProxy, torStatus, settings.connection]); diff --git a/frontend/src/models/Federation.model.ts b/frontend/src/models/Federation.model.ts index 14e45818..efb597ea 100644 --- a/frontend/src/models/Federation.model.ts +++ b/frontend/src/models/Federation.model.ts @@ -78,24 +78,28 @@ export class Federation { public roboPool: RoboPool; - setConnection = (settings: Settings): void => { + setConnection = (settings: Settings, coordinator: string): void => { this.connection = settings.connection; + this.loading = true; + this.book = {}; + this.exchange.loadingCache = this.roboPool.relays.length; if (this.connection === 'nostr') { this.roboPool.connect(); - this.loadBookNostr(); + this.loadBookNostr(coordinator !== 'any'); } else { this.roboPool.close(); void this.loadBook(); } }; - loadBookNostr = (): void => { - this.loading = true; - this.book = {}; + refreshBookHosts: (robosatsOnly: boolean) => void = (robosatsOnly) => { + if (this.connection === 'nostr') { + this.loadBookNostr(robosatsOnly); + } + }; - this.exchange.loadingCache = this.roboPool.relays.length; - - this.roboPool.subscribeBook({ + loadBookNostr = (robosatsOnly: boolean): void => { + this.roboPool.subscribeBook(robosatsOnly, { onevent: (event) => { const { dTag, publicOrder } = eventToPublicOrder(event); if (publicOrder) { diff --git a/frontend/src/services/RoboPool/index.ts b/frontend/src/services/RoboPool/index.ts index 60321a63..9c5c487f 100644 --- a/frontend/src/services/RoboPool/index.ts +++ b/frontend/src/services/RoboPool/index.ts @@ -98,10 +98,12 @@ class RoboPool { }); }; - subscribeBook = (events: RoboPoolEvents): void => { - const authors = [...Object.values(defaultFederation), ...Object.values(thirdParties)] - .map((f) => f.nostrHexPubkey) - .filter((item) => item !== undefined); + subscribeBook = (robosatsOnly: boolean, events: RoboPoolEvents): void => { + let scope = Object.values(defaultFederation); + if (!robosatsOnly) { + scope = [...scope, ...Object.values(thirdParties)]; + } + const authors = scope.map((f) => f.nostrHexPubkey).filter((item) => item !== undefined); const requestPending = [ 'REQ', @@ -134,11 +136,9 @@ class RoboPool { }; subscribeRatings = (events: RoboPoolEvents, coordinators?: string[]): void => { - const pubkeys = - coordinators ?? - [...Object.values(defaultFederation), ...Object.values(thirdParties)] - .map((f) => f.nostrHexPubkey) - .filter((item) => item !== undefined); + const pubkeys = Object.values(defaultFederation) + .map((f) => f.nostrHexPubkey) + .filter((item) => item !== undefined); const requestRatings = [ 'REQ', diff --git a/frontend/static/federation/avatars/mostro.small.webp b/frontend/static/federation/avatars/mostro.small.webp new file mode 100644 index 00000000..2af35322 Binary files /dev/null and b/frontend/static/federation/avatars/mostro.small.webp differ diff --git a/frontend/static/federation/avatars/mostro.webp b/frontend/static/federation/avatars/mostro.webp new file mode 100644 index 00000000..f260ca8a Binary files /dev/null and b/frontend/static/federation/avatars/mostro.webp differ diff --git a/frontend/static/federation/avatars/peach.small.webp b/frontend/static/federation/avatars/peach.small.webp new file mode 100644 index 00000000..0af26243 Binary files /dev/null and b/frontend/static/federation/avatars/peach.small.webp differ diff --git a/frontend/static/federation/avatars/peach.webp b/frontend/static/federation/avatars/peach.webp new file mode 100644 index 00000000..5bf97c44 Binary files /dev/null and b/frontend/static/federation/avatars/peach.webp differ diff --git a/frontend/static/federation/pgp/48339A19645E2E53488E0E5479E1B270FACD1BD2.asc b/frontend/static/federation/pgp/48339A19645E2E53488E0E5479E1B270FACD1BD2.asc new file mode 100644 index 00000000..c4085155 --- /dev/null +++ b/frontend/static/federation/pgp/48339A19645E2E53488E0E5479E1B270FACD1BD2.asc @@ -0,0 +1,15 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: 4833 9A19 645E 2E53 488E 0E54 79E1 B270 FACD 1BD2 +Comment: hello@peachbitcoin.com + +xjMEYiOtWhYJKwYBBAHaRw8BAQdAsOKDD90QG9Fsr2TQomq1plxf0QGlQdL8OXCS +TTjE+vjNL2hlbGxvQHBlYWNoYml0Y29pbi5jb20gPGhlbGxvQHBlYWNoYml0Y29p +bi5jb20+wo8EEBYKACAFAmIjrVoGCwkHCAMCBBUICgIEFgIBAAIZAQIbAwIeAQAh +CRB54bJw+s0b0hYhBEgzmhlkXi5TSI4OVHnhsnD6zRvSDwIA/A2Z1td84Fos0L8Y +180evwOWDdbbI+8N0Y7GgkoU6iUqAQCgqMyBknoPYF9pvE2RLsYYjh52tWrV9mSI +zEMoH38JAc44BGIjrVoSCisGAQQBl1UBBQEBB0AMyWxwd2kF+8Kn5A6OuYCt8OQv +YbzwKJN3Jvnr4Z+ARgMBCAfCeAQYFggACQUCYiOtWgIbDAAhCRB54bJw+s0b0hYh +BEgzmhlkXi5TSI4OVHnhsnD6zRvSw7UBAIb3PAWG2iIXEapRxLVDkEuQ+RRVn/FU +rSwNRLsCJBsqAQDI9SNIkJuqT2RcP7qeQMj0tcZk9dBV+M48OL9XqPTEDA== +=HMiR +-----END PGP PUBLIC KEY BLOCK----- diff --git a/frontend/static/thirdparties.json b/frontend/static/thirdparties.json index e5aeaebf..129f75c2 100644 --- a/frontend/static/thirdparties.json +++ b/frontend/static/thirdparties.json @@ -9,8 +9,42 @@ "email": null, "telegram": "https://t.me/p2plightning", "simplex": null, - "nostr": null, - "website": "https://lnp2pbot.com" + "nostr": "https://njump.me/nprofile1qqs0es4q4yl3t7txceldxjrwkjfk6gdm88q5m6f68qff7683s8udrmqs874xa", + "website": "https://lnp2pbot.com", + "pgp": null, + "fingerprint": null + } + }, + "peach": { + "longAlias": "Peach", + "federated": false, + "shortAlias": "peach", + "nostrHexPubkey": "a47457722e10ba3a271fbe7040259a3c4da2cf53bfd1e198138214d235064fc2", + "description": "The easiest way to buy & sell Bitcoin peer-to-peer.", + "contact": { + "email": "hello@peachbitcoin.com", + "telegram": "https://t.me/peachtopeach", + "simplex": null, + "nostr": "https://njump.me/nprofile1qqs2gazhwghppw36yu0muuzqykdrcndzeafml50pnqfcy9xjx5rylsss0wkz7", + "website": "https://peachbitcoin.com", + "pgp": "/static/federation/pgp/48339A19645E2E53488E0E5479E1B270FACD1BD2.asc", + "fingerprint": "48339A19645E2E53488E0E5479E1B270FACD1BD2" + } + }, + "mostro": { + "longAlias": "Mostro", + "federated": false, + "shortAlias": "mostro", + "nostrHexPubkey": "82fa8cb978b43c79b2156585bac2c011176a21d2aead6d9f7c575c005be88390", + "description": "Peer-to-peer Lightning Network platform over nostr .", + "contact": { + "email": null, + "telegram": "https://t.me/mostrop2p", + "simplex": null, + "nostr": "https://njump.me/npub1m0str0d7z2ww8rdh20t2n9lx520xjwhaq24p68umqp06wwrwtsnqen40un", + "website": "https://mostro.network", + "pgp": null, + "fingerprint": null } } }