5 Commits

Author SHA1 Message Date
Michilis
9faf7b5cef Update README.md 2025-02-10 05:04:59 +01:00
Michilis
c984601352 Update README.md 2025-02-10 05:04:42 +01:00
Michilis
8cdca7bb8c Update README.md 2025-02-10 04:50:11 +01:00
Michilis
cbf2172fe4 Merge pull request #1 from Michilis/V0.02-ref-login
V0.02 ref login
2025-02-10 04:47:27 +01:00
Michilis
a22040b705 Add files via upload 2025-02-10 04:40:31 +01:00
3 changed files with 57 additions and 32 deletions

View File

@@ -1,12 +1,14 @@
# Noderunners Relay # Noderunners Relay
A high-performance Nostr relay built by Bitcoiners, for Bitcoiners. This project provides a web interface for managing access to the Noderunners relay service. A high-performance Nostr relay built by Bitcoiners, for Bitcoiners. This project provides a web interface for managing access to the Noderunners relay service.
```
wss://relay.noderunners.network
```
![Noderunners Relay](https://cdn.azzamo.net/5cc03420a18166ef7a20b1e6b7dad240ad7d634824649643c80d74a924062258.png) ![Noderunners Relay](https://cdn.azzamo.net/5cc03420a18166ef7a20b1e6b7dad240ad7d634824649643c80d74a924062258.png)
## Features ## Features
- 🚀 Lightning-fast relay performance with strfry v1.0.3
- ⚡ Lightning Network integration for payments - ⚡ Lightning Network integration for payments
- 🔒 Secure authentication with Nostr - 🔒 Secure authentication with Nostr
- 💻 Modern, responsive web interface - 💻 Modern, responsive web interface
@@ -116,20 +118,6 @@ You can combine iframe mode with URL-based authentication:
<iframe src="https://your-relay-domain.com?iframe=1&npub=npub1..." width="100%" height="600px"></iframe> <iframe src="https://your-relay-domain.com?iframe=1&npub=npub1..." width="100%" height="600px"></iframe>
``` ```
## Supported NIPs
The relay supports the following Nostr Implementation Possibilities (NIPs):
- NIP-01: Basic protocol flow description
- NIP-02: Contact List and Petnames
- NIP-04: Encrypted Direct Messages
- NIP-09: Event Deletion
- NIP-11: Relay Information Document
- NIP-22: Event `created_at` Limits
- NIP-28: Public Chat
- NIP-40: Expiration Timestamp
- NIP-70: Relay Payment Info
- NIP-77: Lightning Network Relay Payment
## API Services ## API Services
### LNbits Integration ### LNbits Integration
@@ -156,10 +144,6 @@ The relay supports the following Nostr Implementation Possibilities (NIPs):
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Support
For support, join our [Telegram group](https://t.me/noderunners) or visit [our website](https://noderunners.network).
## Acknowledgments ## Acknowledgments
- Built by the Noderunners community - Built by the Noderunners community

View File

@@ -1,5 +1,5 @@
import React from 'react'; import React, { useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { BrowserRouter as Router, Routes, Route, useSearchParams, useNavigate } from 'react-router-dom';
import { Home } from './pages/Home'; import { Home } from './pages/Home';
import { Login } from './pages/Login'; import { Login } from './pages/Login';
import { Dashboard } from './pages/Dashboard'; import { Dashboard } from './pages/Dashboard';
@@ -7,10 +7,32 @@ import { Payment } from './pages/Payment';
import { ThankYou } from './pages/ThankYou'; import { ThankYou } from './pages/ThankYou';
import { Terms } from './pages/Terms'; import { Terms } from './pages/Terms';
import { Layout } from './components/Layout'; import { Layout } from './components/Layout';
import { useStore } from './store/useStore';
// Wrapper component to handle auto-login logic
function AutoLoginHandler({ children }: { children: React.ReactNode }) {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const { user, setUser } = useStore();
useEffect(() => {
const urlPubkey = searchParams.get('npub') || searchParams.get('pubkey');
const isIframe = searchParams.get('iframe') === '1';
// Auto-login if pubkey/npub is in URL and user isn't already logged in
if (urlPubkey && !user) {
setUser({ pubkey: urlPubkey, isWhitelisted: false });
navigate(isIframe ? '/dashboard?iframe=1' : '/dashboard');
}
}, [searchParams, user, setUser, navigate]);
return <>{children}</>;
}
function App() { function App() {
return ( return (
<Router> <Router>
<AutoLoginHandler>
<Routes> <Routes>
<Route path="/" element={<Layout />}> <Route path="/" element={<Layout />}>
<Route index element={<Home />} /> <Route index element={<Home />} />
@@ -21,6 +43,7 @@ function App() {
<Route path="terms" element={<Terms />} /> <Route path="terms" element={<Terms />} />
</Route> </Route>
</Routes> </Routes>
</AutoLoginHandler>
</Router> </Router>
); );
} }

View File

@@ -10,12 +10,21 @@ export function Login() {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [pubkeyInput, setPubkeyInput] = useState(''); const [pubkeyInput, setPubkeyInput] = useState('');
const isIframe = searchParams.get('iframe') === '1'; const isIframe = searchParams.get('iframe') === '1';
const urlPubkey = searchParams.get('npub') || searchParams.get('pubkey');
useEffect(() => { useEffect(() => {
// Handle URL-based login
if (urlPubkey && !user) {
setUser({ pubkey: urlPubkey, isWhitelisted: false });
navigate(isIframe ? '/dashboard?iframe=1' : '/dashboard');
return;
}
// Regular user redirect
if (user) { if (user) {
navigate(isIframe ? '/dashboard?iframe=1' : '/dashboard'); navigate(isIframe ? '/dashboard?iframe=1' : '/dashboard');
} }
}, [user, navigate, isIframe]); }, [user, navigate, isIframe, urlPubkey, setUser]);
const handleExtensionLogin = async () => { const handleExtensionLogin = async () => {
setIsLoading(true); setIsLoading(true);
@@ -73,6 +82,15 @@ export function Login() {
} }
}; };
// If we're processing URL-based login, show loading state
if (urlPubkey && !user) {
return (
<div className="flex justify-center items-center min-h-[400px]">
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-orange-500"></div>
</div>
);
}
return ( return (
<div className="max-w-md mx-auto bg-gray-800 rounded-lg p-8"> <div className="max-w-md mx-auto bg-gray-800 rounded-lg p-8">
<h1 className="text-2xl font-bold mb-6 text-center">Connect with Nostr</h1> <h1 className="text-2xl font-bold mb-6 text-center">Connect with Nostr</h1>