A React + TypeScript demonstration of integrating with Rizful's OAuth-like flow to obtain Nostr Wallet Connect (NWC) URIs and Lightning addresses.
This flow has already been integrated with the Nostr application Jumble.social -- see how it works here: https://docs.megalithic.me/using-rizful/use-jumble#the-easy-way
Look at the green "get code" button in the screenshot above. (You can rename the buttons in your application, of course.) When the user clicks "get code", if the authorization is successful, you will see an NWC code and a Lightning Address written to the screen. (Look for <strong>NWC URI:</strong> in the code.)
For this demo, the NWC code and Lightning Address are written to the screen, but in YOUR application, you should...
- Save the NWC code so the user can use it to make Lightning payments.. remember a NWC code is sensitive, never write this to your server unless you are really sure you can do it securely.. ideally it never leaves the user's device!
- Apply the Lightning Address to the user's profile (LUD), and sync that with Nostr relays as the user's metadata.
- Use the Lightning Address also as the Nip-05 for the user's profile, and sync that with Nostr relays as the user's metadata. (If you want.)
Some existing wallet services identify users by nostr public/private keys, and allow signup without an email address or other means for the user to recover their funds.
Our view is that this is totally dangerous for normies, who:
- Will likely reveal their nsec to lots of sketchy apps
- Will likely misplace their nsec
- Will forget where their sats are actually stored, and have no record of it in their email or elsewhere.
In all these cases, their funds will disappear.
Rizful's approach is more conservative:
- We think that a user's funds should NOT be connected to their nsec.
- We allow "burner" emails and VPNs, but DO require email/password login, with optional 2FA.
Since the user has an email in their inbox from Rizful, a user should never lose access to his/her funds, as their password can be reset by email.
It's not 100% cyberpunk, but it's practical and the right way to onboard normies to zaps (in our opinion.)
- Secure Authentication Flow: OAuth-like process without exposing private keys
- NWC URI Generation: Get Nostr Wallet Connect URI
- Lightning Address Retrieval: Obtain Lightning address for receiving payments
The application implements a three-step authentication flow:
- New users can create a Rizful account by clicking "Sign up for Rizful"
- Opens Rizful's signup page in a popup window
- Existing users can skip this step
- Users click "Get Code" to open Rizful's token generation page
- They authorize the integration and receive a one-time code
- This code is time-limited and single-use for security
- Users paste their one-time code into the demo app
- Users provide their Nostr public key (hex format, 64 characters)
- The app exchanges these credentials with Rizful's server
- On success, receives:
- NWC URI: For making Bitcoin transactions
- Lightning Address: For receiving payments
- Confirmed Public Key: Verification of the provided key
User → Sign up for Rizful → Get Code From Rizful → Exchange code for Credentials
- GET
https://rizful.com/nostr_onboarding_auth_token/get_token- Get authorization code - POST
https://rizful.com/nostr_onboarding_auth_token/post_for_secrets- Exchange for credentials
- Node.js 22.12 or higher
- npm or yarn package manager
-
Clone and install dependencies:
git clone <repository-url> cd rizful-integration-demo npm install
-
Configure Rizful URL:
Create a .env file in the project root:
VITE_RIZFUL_ORIGIN=https://rizful.com-
Start development server:
npm run dev
-
Open in browser: Navigate to
http://localhost:3008
POST rizful.com/nostr_onboarding_auth_token/post_for_secrets
Request:
{
"secret_code": "one-time-code-from-rizful",
"nostr_public_key": "64-character-hex-public-key"
}Response:
{
"nwc_uri": "nostr+walletconnect://...",
"lightning_address": "[email protected]",
"nostr_public_key": "64-character-hex-public-key"
}npm run dev # Start development server with hot reload

