diff --git a/prisma/migrations/20250215184313_add_platform_lnaddress_and_nip05/migration.sql b/prisma/migrations/20250215184313_add_platform_lnaddress_and_nip05/migration.sql
new file mode 100644
index 0000000..97a7ce4
--- /dev/null
+++ b/prisma/migrations/20250215184313_add_platform_lnaddress_and_nip05/migration.sql
@@ -0,0 +1,63 @@
+/*
+ Warnings:
+
+ - You are about to drop the `LightningAddress` table. If the table is not empty, all the data it contains will be lost.
+ - You are about to drop the `Nip05` table. If the table is not empty, all the data it contains will be lost.
+
+*/
+-- DropForeignKey
+ALTER TABLE "LightningAddress" DROP CONSTRAINT "LightningAddress_userId_fkey";
+
+-- DropForeignKey
+ALTER TABLE "Nip05" DROP CONSTRAINT "Nip05_userId_fkey";
+
+-- AlterTable
+ALTER TABLE "User" ADD COLUMN "lud16" TEXT,
+ADD COLUMN "nip05" TEXT;
+
+-- DropTable
+DROP TABLE "LightningAddress";
+
+-- DropTable
+DROP TABLE "Nip05";
+
+-- CreateTable
+CREATE TABLE "PlatformNip05" (
+ "id" TEXT NOT NULL,
+ "userId" TEXT NOT NULL,
+ "pubkey" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+
+ CONSTRAINT "PlatformNip05_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "PlatformLightningAddress" (
+ "id" TEXT NOT NULL,
+ "userId" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "allowsNostr" BOOLEAN NOT NULL DEFAULT true,
+ "description" TEXT,
+ "maxSendable" INTEGER NOT NULL DEFAULT 10000000,
+ "minSendable" INTEGER NOT NULL DEFAULT 1,
+ "invoiceMacaroon" TEXT NOT NULL,
+ "lndCert" TEXT,
+ "lndHost" TEXT NOT NULL,
+ "lndPort" TEXT NOT NULL DEFAULT '8080',
+
+ CONSTRAINT "PlatformLightningAddress_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "PlatformNip05_userId_key" ON "PlatformNip05"("userId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "PlatformLightningAddress_userId_key" ON "PlatformLightningAddress"("userId");
+
+-- AddForeignKey
+ALTER TABLE "PlatformNip05" ADD CONSTRAINT "PlatformNip05_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "PlatformLightningAddress" ADD CONSTRAINT "PlatformLightningAddress_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
diff --git a/prisma/migrations/20250215194519_consolidate_user_fields/migration.sql b/prisma/migrations/20250215194519_consolidate_user_fields/migration.sql
new file mode 100644
index 0000000..d9be833
--- /dev/null
+++ b/prisma/migrations/20250215194519_consolidate_user_fields/migration.sql
@@ -0,0 +1,10 @@
+/*
+ Warnings:
+
+ - You are about to drop the column `image` on the `User` table. All the data in the column will be lost.
+ - You are about to drop the column `name` on the `User` table. All the data in the column will be lost.
+
+*/
+-- AlterTable
+ALTER TABLE "User" DROP COLUMN "image",
+DROP COLUMN "name";
diff --git a/prisma/migrations/20250217173901_millisat_bigint/migration.sql b/prisma/migrations/20250217173901_millisat_bigint/migration.sql
new file mode 100644
index 0000000..94cde92
--- /dev/null
+++ b/prisma/migrations/20250217173901_millisat_bigint/migration.sql
@@ -0,0 +1,5 @@
+-- AlterTable
+ALTER TABLE "PlatformLightningAddress" ALTER COLUMN "maxSendable" SET DEFAULT 10000000000,
+ALTER COLUMN "maxSendable" SET DATA TYPE BIGINT,
+ALTER COLUMN "minSendable" SET DEFAULT 1000,
+ALTER COLUMN "minSendable" SET DATA TYPE BIGINT;
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 8e917db..23486b9 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -13,15 +13,12 @@ generator client {
provider = "prisma-client-js"
}
-// todo name and username?
model User {
id String @id @default(uuid())
pubkey String? @unique
privkey String?
- name String?
email String? @unique
emailVerified DateTime?
- image String?
username String? @unique
avatar String?
purchased Purchase[]
@@ -36,8 +33,10 @@ model User {
updatedAt DateTime @updatedAt
userLessons UserLesson[]
userCourses UserCourse[]
- nip05 Nip05?
- lightningAddress LightningAddress?
+ nip05 String?
+ lud16 String?
+ platformNip05 PlatformNip05?
+ platformLightningAddress PlatformLightningAddress?
userBadges UserBadge[]
}
@@ -226,7 +225,7 @@ model UserCourse {
@@unique([userId, courseId])
}
-model Nip05 {
+model PlatformNip05 {
id String @id @default(uuid())
userId String @unique
user User @relation(fields: [userId], references: [id])
@@ -236,16 +235,15 @@ model Nip05 {
updatedAt DateTime @updatedAt
}
-model LightningAddress {
+model PlatformLightningAddress {
id String @id @default(uuid())
userId String @unique
user User @relation(fields: [userId], references: [id])
name String
allowsNostr Boolean @default(true)
description String?
- // todo: change to BigInt to support native millisats
- maxSendable Int @default(10000000)
- minSendable Int @default(1)
+ maxSendable BigInt @default(10000000000)
+ minSendable BigInt @default(1000)
invoiceMacaroon String
lndCert String?
lndHost String
diff --git a/src/components/content/courses/CombinedLesson.js b/src/components/content/courses/CombinedLesson.js
index 96149a2..ce06358 100644
--- a/src/components/content/courses/CombinedLesson.js
+++ b/src/components/content/courses/CombinedLesson.js
@@ -213,7 +213,7 @@ const CombinedLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
By{' '}
- {lesson.author?.username || lesson.author?.name || lesson.author?.pubkey}
+ {lesson.author?.username || lesson.author?.pubkey}
diff --git a/src/components/content/courses/CourseLesson.js b/src/components/content/courses/CourseLesson.js
index a0a1c1f..2b04dd8 100644
--- a/src/components/content/courses/CourseLesson.js
+++ b/src/components/content/courses/CourseLesson.js
@@ -86,7 +86,7 @@ const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid }) => {
Created by{' '}
- {lesson.author?.username || lesson.author?.name || lesson.author?.pubkey}
+ {lesson.author?.username || lesson.author?.pubkey}
diff --git a/src/components/content/courses/DocumentLesson.js b/src/components/content/courses/DocumentLesson.js
index 4c96b4d..bd98df4 100644
--- a/src/components/content/courses/DocumentLesson.js
+++ b/src/components/content/courses/DocumentLesson.js
@@ -127,7 +127,7 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
By{' '}
- {lesson.author?.username || lesson.author?.name || lesson.author?.pubkey}
+ {lesson.author?.username || lesson.author?.pubkey}
diff --git a/src/components/content/courses/DraftCourseLesson.js b/src/components/content/courses/DraftCourseLesson.js
index 970f356..8638837 100644
--- a/src/components/content/courses/DraftCourseLesson.js
+++ b/src/components/content/courses/DraftCourseLesson.js
@@ -78,7 +78,7 @@ const DraftCourseLesson = ({ lesson, course }) => {
Created by{' '}
- {lesson.author?.username || lesson.author?.name || lesson.author?.pubkey}
+ {lesson.author?.username || lesson.author?.pubkey}
diff --git a/src/components/content/courses/VideoLesson.js b/src/components/content/courses/VideoLesson.js
index 455126e..d2b9fb8 100644
--- a/src/components/content/courses/VideoLesson.js
+++ b/src/components/content/courses/VideoLesson.js
@@ -189,7 +189,7 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted
Created by{' '}
- {lesson.author?.username || lesson.author?.name || lesson.author?.pubkey}
+ {lesson.author?.username || lesson.author?.pubkey}
diff --git a/src/components/navbar/user/UserAvatar.js b/src/components/navbar/user/UserAvatar.js
index f25c1fb..4d056f7 100644
--- a/src/components/navbar/user/UserAvatar.js
+++ b/src/components/navbar/user/UserAvatar.js
@@ -56,7 +56,7 @@ const UserAvatar = () => {
return null; // Or return a loader/spinner/placeholder
} else if (user && Object.keys(user).length > 0) {
// User exists, show username or pubkey
- const displayName = user.username || user?.name || user?.email || user?.pubkey.slice(0, 10) + '...' || "Anon";
+ const displayName = user?.username || user?.email || user?.pubkey?.slice(0, 10) + '...' || "Anon";
const items = [
{
diff --git a/src/components/profile/UserAccountLinking.js b/src/components/profile/UserAccountLinking.js
index 13339e6..398b044 100644
--- a/src/components/profile/UserAccountLinking.js
+++ b/src/components/profile/UserAccountLinking.js
@@ -79,6 +79,9 @@ const LinkAccountsCard = ({ session }) => {
});
if (response.ok) {
+ // clear the local storage of the users ephemeral keys
+ localStorage.removeItem('anonymousPrivkey');
+ localStorage.removeItem('anonymousPubkey');
showToast('success', 'Success', 'Nostr account linked successfully');
// Refresh the session to get updated user data
await update();
@@ -181,7 +184,7 @@ const LinkAccountsCard = ({ session }) => {
icon="pi pi-github"
onClick={handleGithubLink}
disabled={isGithubLinked}
- className={`text-[#f8f8ff] w-[250px] mx-auto`}
+ className={`text-[#f8f8ff] w-[250px]`}
rounded
/>
@@ -190,7 +193,7 @@ const LinkAccountsCard = ({ session }) => {
icon={ }
onClick={handleNostrLink}
disabled={isNostrLinked}
- className={`text-[#f8f8ff] w-[250px] mx-auto flex items-center justify-center`}
+ className={`text-[#f8f8ff] w-[250px]`}
rounded
/>
@@ -199,7 +202,7 @@ const LinkAccountsCard = ({ session }) => {
icon="pi pi-envelope"
onClick={handleEmailLink}
disabled={isEmailLinked}
- className={`text-[#f8f8ff] w-[250px] mx-auto`}
+ className={`text-[#f8f8ff] w-[250px]`}
rounded
/>
diff --git a/src/components/profile/UserProfileCard.js b/src/components/profile/UserProfileCard.js
index 386046a..af37210 100644
--- a/src/components/profile/UserProfileCard.js
+++ b/src/components/profile/UserProfileCard.js
@@ -70,7 +70,7 @@ const UserProfileCard = ({ user }) => {
className="rounded-full m-2 mt-0 object-cover max-w-[100px] max-h-[100px]"
/>
- {user.username || user?.name || user?.email || "Anon"}
+ {user.username || user?.email || "Anon"}
{
@@ -98,13 +98,17 @@ const UserProfileCard = ({ user }) => {
- {user?.lightningAddress ? (
+ {user?.platformLightningAddress ? (
- Lightning Address: {user.lightningAddress.name}@plebdevs.com copyToClipboard(user.lightningAddress.name + "@plebdevs.com")} />
+ Lightning Address: {user.platformLightningAddress.name}@plebdevs.com copyToClipboard(user.platformLightningAddress.name + "@plebdevs.com")} />
+
+ ) : user?.lud16 ? (
+
+ Lightning Address: {user.lud16} copyToClipboard(user.lud16)} />
) : (
-
+
Lightning Address: None
{
/>
)}
- {user?.nip05 ? (
+ {user?.platformNip05 ? (
- NIP-05: {user.nip05.name}@plebdevs.com copyToClipboard(user.nip05.name + "@plebdevs.com")} />
+ NIP-05: {' '}
+ {user.platformNip05.name}@plebdevs.com{' '}
+ copyToClipboard(`${user.platformNip05.name}@plebdevs.com`)}
+ />
+
+ ) : user?.nip05 ? (
+
+ NIP-05: {' '}
+ {user.nip05}{' '}
+ copyToClipboard(user.nip05)}
+ />
) : (
@@ -125,9 +143,9 @@ const UserProfileCard = ({ user }) => {
NIP-05: None
@@ -169,7 +187,7 @@ const UserProfileCard = ({ user }) => {
/>
- {user.username || user?.name || user?.email || "Anon"}
+ {user.username || user?.email || "Anon"}
{
user?.pubkey && (
@@ -193,10 +211,14 @@ const UserProfileCard = ({ user }) => {
)}
-
- {user?.lightningAddress ? (
-
- Lightning Address: {user.lightningAddress.name}@plebdevs.com copyToClipboard(user.lightningAddress.name + "@plebdevs.com")} />
+
+ {user?.platformLightningAddress ? (
+
+ Lightning Address: {user.platformLightningAddress.name}@plebdevs.com copyToClipboard(user.platformLightningAddress.name + "@plebdevs.com")} />
+
+ ) : user?.lud16 ? (
+
+ Lightning Address: {user.lud16} copyToClipboard(user.lud16)} />
) : (
@@ -211,9 +233,23 @@ const UserProfileCard = ({ user }) => {
/>
)}
- {user?.nip05 ? (
+ {user?.platformNip05 ? (
- NIP-05: {user.nip05.name}@plebdevs.com copyToClipboard(user.nip05.name + "@plebdevs.com")} />
+ NIP-05: {' '}
+ {user.platformNip05.name}@plebdevs.com{' '}
+ copyToClipboard(`${user.platformNip05.name}@plebdevs.com`)}
+ />
+
+ ) : user?.nip05 ? (
+
+ NIP-05: {' '}
+ {user.nip05}{' '}
+ copyToClipboard(user.nip05)}
+ />
) : (
diff --git a/src/components/profile/subscription/LightningAddressForm.js b/src/components/profile/subscription/LightningAddressForm.js
index 6dca2a9..8224dc0 100644
--- a/src/components/profile/subscription/LightningAddressForm.js
+++ b/src/components/profile/subscription/LightningAddressForm.js
@@ -14,8 +14,8 @@ const LightningAddressForm = ({ visible, onHide }) => {
const [existingLightningAddress, setExistingLightningAddress] = useState(null);
const [name, setName] = useState('');
const [description, setDescription] = useState('');
- const [maxSendable, setMaxSendable] = useState(10000000);
- const [minSendable, setMinSendable] = useState(1);
+ const [maxSendable, setMaxSendable] = useState(10000000000);
+ const [minSendable, setMinSendable] = useState(1000);
const [invoiceMacaroon, setInvoiceMacaroon] = useState('');
const [lndCert, setLndCert] = useState('');
const [lndHost, setLndHost] = useState('');
@@ -26,18 +26,18 @@ const LightningAddressForm = ({ visible, onHide }) => {
const { showToast } = useToast();
useEffect(() => {
- if (session && session?.user && !session?.user?.lightningAddress) {
- setName(session.user.name || '');
- } else if (session && session?.user && session?.user?.lightningAddress) {
- setExistingLightningAddress(session.user.lightningAddress);
- setName(session.user.lightningAddress.name || '');
- setDescription(session.user.lightningAddress.description || '');
- setMaxSendable(session.user.lightningAddress.maxSendable || 10000000);
- setMinSendable(session.user.lightningAddress.minSendable || 1);
- setInvoiceMacaroon(session.user.lightningAddress.invoiceMacaroon || '');
- setLndCert(session.user.lightningAddress.lndCert || '');
- setLndHost(session.user.lightningAddress.lndHost || '');
- setLndPort(session.user.lightningAddress.lndPort || '8080');
+ if (session && session?.user && !session?.user?.platformLightningAddress) {
+ setName(session.user.username || '');
+ } else if (session && session?.user && session?.user?.platformLightningAddress) {
+ setExistingLightningAddress(session.user.platformLightningAddress);
+ setName(session.user.platformLightningAddress.name || '');
+ setDescription(session.user.platformLightningAddress.description || '');
+ setMaxSendable(Number(session.user.platformLightningAddress.maxSendable) || 10000000000);
+ setMinSendable(Number(session.user.platformLightningAddress.minSendable) || 1000);
+ setInvoiceMacaroon(session.user.platformLightningAddress.invoiceMacaroon || '');
+ setLndCert(session.user.platformLightningAddress.lndCert || '');
+ setLndHost(session.user.platformLightningAddress.lndHost || '');
+ setLndPort(session.user.platformLightningAddress.lndPort || '8080');
}
}, [session]);
@@ -46,10 +46,21 @@ const LightningAddressForm = ({ visible, onHide }) => {
try {
let response;
const lowercaseName = name.toLowerCase();
+ const data = {
+ name: lowercaseName,
+ description,
+ maxSendable: BigInt(maxSendable).toString(),
+ minSendable: BigInt(minSendable).toString(),
+ invoiceMacaroon,
+ lndCert,
+ lndHost,
+ lndPort
+ };
+
if (existingLightningAddress) {
- response = await axios.put(`/api/users/${session.user.id}/lightning-address`, { name: lowercaseName, description, maxSendable, minSendable, invoiceMacaroon, lndCert, lndHost, lndPort });
+ response = await axios.put(`/api/users/${session.user.id}/lightning-address`, data);
} else {
- response = await axios.post(`/api/users/${session.user.id}/lightning-address`, { name: lowercaseName, description, maxSendable, minSendable, invoiceMacaroon, lndCert, lndHost, lndPort });
+ response = await axios.post(`/api/users/${session.user.id}/lightning-address`, data);
}
if (!existingLightningAddress && response.status === 201) {
showToast('success', 'Lightning Address Claimed', 'Your Lightning Address has been claimed');
@@ -101,10 +112,9 @@ const LightningAddressForm = ({ visible, onHide }) => {
Description
setDescription(e.target.value)} tooltip='This is your Lightning Address description, it will be displayed as the description LUD16 lnurlp endpoint' />
Max Sendable
- {/* Todo: max is 2,147,483 sats until i imlement bigInt for sat amounts */}
- setMaxSendable(e.target.value)} max={2147483647} min={1000} tooltip='This is the maximum amount of sats that can be sent to your Lightning Address (currently denominated in sats NOT msat)' />
+ setMaxSendable(e.value)} min={1000} tooltip='Maximum amount in millisats (1000 millisats = 1 sat)' />
Min Sendable
- setMinSendable(e.target.value)} min={1} max={2147483647} tooltip='This is the minimum amount of sats that can be sent to your Lightning Address (currently denominated in sats NOT msat)' />
+ setMinSendable(e.value)} min={1} tooltip='Minimum amount in millisats (1000 millisats = 1 sat)' />
Invoice Macaroon
setInvoiceMacaroon(e.target.value)} tooltip='This is your LND Invoice Macaroon, it is used to create invoices for your Lightning Address but DOES NOT grant access to move funds from your LND node' />
LND Cert
diff --git a/src/components/profile/subscription/Nip05Form.js b/src/components/profile/subscription/Nip05Form.js
index bd6c92d..cf6831a 100644
--- a/src/components/profile/subscription/Nip05Form.js
+++ b/src/components/profile/subscription/Nip05Form.js
@@ -19,13 +19,13 @@ const Nip05Form = ({ visible, onHide }) => {
const { showToast } = useToast();
useEffect(() => {
- if (session && session?.user && !session?.user?.nip05) {
+ if (session && session?.user && !session?.user?.platformNip05) {
setPubkey(session.user.pubkey || '');
- setName(session.user.name || '');
- } else if (session && session?.user && session?.user?.nip05) {
- setExistingNip05(session.user.nip05);
- setPubkey(session.user.nip05.pubkey || '');
- setName(session.user.nip05.name || '');
+ setName(session.user.username || '');
+ } else if (session && session?.user && session?.user?.platformNip05) {
+ setExistingNip05(session.user.platformNip05);
+ setPubkey(session.user.platformNip05.pubkey || '');
+ setName(session.user.platformNip05.name || '');
}
}, [session]);
diff --git a/src/components/profile/subscription/SubscribeModal.js b/src/components/profile/subscription/SubscribeModal.js
index 1ec752b..97bf3ac 100644
--- a/src/components/profile/subscription/SubscribeModal.js
+++ b/src/components/profile/subscription/SubscribeModal.js
@@ -7,7 +7,6 @@ import { useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import { useToast } from '@/hooks/useToast';
import { Card } from 'primereact/card';
-import { Badge } from 'primereact/badge';
import GenericButton from '@/components/buttons/GenericButton';
import { Menu } from "primereact/menu";
import { Message } from "primereact/message";
@@ -104,14 +103,14 @@ const SubscribeModal = ({ user }) => {
},
},
{
- label: session?.user?.lightningAddress ? "Update PlebDevs Lightning Address" : "Claim PlebDevs Lightning Address",
+ label: session?.user?.platformLightningAddress ? "Update PlebDevs Lightning Address" : "Claim PlebDevs Lightning Address",
icon: "pi pi-bolt",
command: () => {
setLightningAddressVisible(true);
},
},
{
- label: session?.user?.nip05 ? "Update PlebDevs Nostr NIP-05" : "Claim PlebDevs Nostr NIP-05",
+ label: session?.user?.platformNip05?.name ? "Update PlebDevs Nostr NIP-05" : "Claim PlebDevs Nostr NIP-05",
icon: "pi pi-at",
command: () => {
setNip05Visible(true);
@@ -152,14 +151,14 @@ const SubscribeModal = ({ user }) => {
{subscribed && !user?.role?.nwc && (
-
Thank you for your support 🎉
+
Thank you for your support 🎉
Pay-as-you-go subscription will renew on {subscribedUntil.toLocaleDateString()}
)}
{subscribed && user?.role?.nwc && (
-
Thank you for your support 🎉
+
Thank you for your support 🎉
Recurring subscription will AUTO renew on {subscribedUntil.toLocaleDateString()}
)}
@@ -168,7 +167,7 @@ const SubscribeModal = ({ user }) => {
setVisible(true)}
/>
@@ -232,7 +231,7 @@ const SubscribeModal = ({ user }) => {
visible={calendlyVisible}
onHide={() => setCalendlyVisible(false)}
userId={session?.user?.id}
- userName={session?.user?.name || user?.kind0?.username}
+ userName={session?.user?.username || user?.kind0?.username}
userEmail={session?.user?.email}
/>
{
const { data: session, update } = useSession();
const { showToast } = useToast();
- const router = useRouter();
const windowWidth = useWindowWidth();
- const menu = useRef(null);
const [user, setUser] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
const [subscribed, setSubscribed] = useState(false);
@@ -178,8 +175,8 @@ const UserSubscription = () => {
setCalendlyVisible(true)} />
- setNip05Visible(true)} />
- } onClick={() => setLightningAddressVisible(true)} />
+ setNip05Visible(true)} />
+ } onClick={() => setLightningAddressVisible(true)} />
)}
@@ -225,7 +222,7 @@ const UserSubscription = () => {
visible={calendlyVisible}
onHide={() => setCalendlyVisible(false)}
userId={session?.user?.id}
- userName={session?.user?.name || user?.kind0?.username}
+ userName={session?.user?.username || user?.kind0?.username}
userEmail={session?.user?.email}
/>
{
- return await prisma.lightningAddress.findMany();
+ return await prisma.platformLightningAddress.findMany();
};
export const getLightningAddressByName = async (name) => {
- return await prisma.lightningAddress.findFirst({
+ return await prisma.platformLightningAddress.findFirst({
where: { name },
});
};
export const getLightningAddress = async (userId) => {
- return await prisma.lightningAddress.findUnique({
+ return await prisma.platformLightningAddress.findUnique({
where: { userId },
});
};
export const createLightningAddress = async (userId, name, description, maxSendable, minSendable, invoiceMacaroon, lndCert, lndHost, lndPort) => {
try {
- return await prisma.lightningAddress.create({
+ return await prisma.platformLightningAddress.create({
data: {
userId,
name,
@@ -38,14 +38,14 @@ export const createLightningAddress = async (userId, name, description, maxSenda
};
export const updateLightningAddress = async (userId, data) => {
- return await prisma.lightningAddress.update({
+ return await prisma.platformLightningAddress.update({
where: { userId },
data,
});
};
export const deleteLightningAddress = async (userId) => {
- return await prisma.lightningAddress.delete({
+ return await prisma.platformLightningAddress.delete({
where: { userId },
});
};
diff --git a/src/db/models/nip05Models.js b/src/db/models/nip05Models.js
index df738d9..1e1a549 100644
--- a/src/db/models/nip05Models.js
+++ b/src/db/models/nip05Models.js
@@ -1,36 +1,36 @@
import prisma from "@/db/prisma";
export const getAllNip05s = async () => {
- return await prisma.nip05.findMany();
+ return await prisma.platformNip05.findMany();
};
export const getNip05ByName = async (name) => {
- return await prisma.nip05.findFirst({
+ return await prisma.platformNip05.findFirst({
where: { name },
});
};
export const getNip05 = async (userId) => {
- return await prisma.nip05.findUnique({
+ return await prisma.platformNip05.findUnique({
where: { userId },
});
};
export const createNip05 = async (userId, pubkey, name) => {
- return await prisma.nip05.create({
+ return await prisma.platformNip05.create({
data: { userId, pubkey, name },
});
};
export const updateNip05 = async (userId, data) => {
- return await prisma.nip05.update({
+ return await prisma.platformNip05.update({
where: { userId },
data,
});
};
export const deleteNip05 = async (userId) => {
- return await prisma.nip05.delete({
+ return await prisma.platformNip05.delete({
where: { userId },
});
};
diff --git a/src/db/models/userModels.js b/src/db/models/userModels.js
index 7ec5328..12b00be 100644
--- a/src/db/models/userModels.js
+++ b/src/db/models/userModels.js
@@ -50,8 +50,8 @@ export const getUserById = async (id) => {
lesson: true,
},
},
- nip05: true,
- lightningAddress: true,
+ platformNip05: true,
+ platformLightningAddress: true,
userBadges: {
include: {
badge: true
@@ -82,8 +82,8 @@ export const getUserByPubkey = async (pubkey) => {
lesson: true,
},
},
- nip05: true,
- lightningAddress: true,
+ platformNip05: true,
+ platformLightningAddress: true,
userBadges: {
include: {
badge: true
@@ -278,8 +278,8 @@ export const getUserByEmail = async (email) => {
lesson: true,
},
},
- nip05: true,
- lightningAddress: true,
+ platformNip05: true,
+ platformLightningAddress: true,
userBadges: {
include: {
badge: true
diff --git a/src/pages/api/auth/[...nextauth].js b/src/pages/api/auth/[...nextauth].js
index 2f99aff..abaace9 100644
--- a/src/pages/api/auth/[...nextauth].js
+++ b/src/pages/api/auth/[...nextauth].js
@@ -33,14 +33,19 @@ const syncNostrProfile = async (pubkey) => {
let dbUser = await getUserByPubkey(pubkey);
if (dbUser) {
- // Update existing user if kind0 fields differ
- if (fields.avatar !== dbUser.avatar || fields.username !== dbUser.username) {
+ // Update existing user if any of the kind0 fields differ
+ if (fields.avatar !== dbUser.avatar ||
+ fields.username !== dbUser.username ||
+ fields.lud16 !== dbUser.lud16 ||
+ fields.nip05 !== dbUser.nip05) {
+
const updates = {
...(fields.avatar !== dbUser.avatar && { avatar: fields.avatar }),
...(fields.username !== dbUser.username && {
- username: fields.username,
- name: fields.username
- })
+ username: fields.username
+ }),
+ ...(fields.lud16 !== dbUser.lud16 && { lud16: fields.lud16 }),
+ ...(fields.nip05 !== dbUser.nip05 && { nip05: fields.nip05 })
};
await updateUser(dbUser.id, updates);
dbUser = await getUserByPubkey(pubkey);
@@ -48,11 +53,14 @@ const syncNostrProfile = async (pubkey) => {
} else {
// Create new user
const username = fields.username || pubkey.slice(0, 8);
+ const lud16 = fields.lud16 || null;
+ const nip05 = fields.nip05 || null;
const payload = {
pubkey,
username,
avatar: fields.avatar,
- name: username
+ lud16,
+ nip05
};
dbUser = await createUser(payload);
@@ -126,8 +134,7 @@ export const authOptions = {
if (!user) {
user = await createUser({
...keys,
- username: `anon-${keys.pubkey.slice(0, 8)}`,
- name: `anon-${keys.pubkey.slice(0, 8)}`
+ username: `anon-${keys.pubkey.slice(0, 8)}`
});
}
return { ...user, privkey: keys.privkey };
@@ -157,7 +164,7 @@ export const authOptions = {
id: profile.id.toString(),
pubkey: keys.pubkey,
privkey: keys.privkey,
- name: profile.login,
+ username: profile.login,
email: profile.email,
avatar: profile.avatar_url
};
@@ -194,8 +201,8 @@ export const authOptions = {
purchased: true,
userCourses: true,
userLessons: true,
- nip05: true,
- lightningAddress: true,
+ platformNip05: true,
+ platformLightningAddress: true,
userBadges: true
}
});
@@ -232,7 +239,6 @@ export const authOptions = {
username: user.email.split('@')[0],
email: user.email,
avatar: user.image,
- name: user.email.split('@')[0],
}
// Update the user with the new keypair
@@ -256,7 +262,15 @@ export const authOptions = {
if (userData) {
const fullUser = await getUserById(userData.id);
-
+ // Convert BigInt values to strings if they exist
+ if (fullUser.platformLightningAddress) {
+ fullUser.platformLightningAddress = {
+ ...fullUser.platformLightningAddress,
+ maxSendable: fullUser.platformLightningAddress.maxSendable?.toString(),
+ minSendable: fullUser.platformLightningAddress.minSendable?.toString()
+ };
+ }
+
// Get the user's GitHub account if it exists
const githubAccount = await prisma.account.findFirst({
where: {
@@ -273,13 +287,14 @@ export const authOptions = {
role: fullUser.role,
username: fullUser.username,
avatar: fullUser.avatar,
- name: fullUser.name,
email: fullUser.email,
userCourses: fullUser.userCourses,
userLessons: fullUser.userLessons,
purchased: fullUser.purchased,
nip05: fullUser.nip05,
- lightningAddress: fullUser.lightningAddress,
+ lud16: fullUser.lud16,
+ platformNip05: fullUser.platformNip05,
+ platformLightningAddress: fullUser.platformLightningAddress,
githubUsername: token.githubUsername,
createdAt: fullUser.createdAt,
userBadges: fullUser.userBadges
@@ -300,15 +315,22 @@ export const authOptions = {
return session;
},
async jwt({ token, user, account, profile, session }) {
+ // Convert BigInt values to strings if they exist
+ if (user?.platformLightningAddress) {
+ user.platformLightningAddress = {
+ ...user.platformLightningAddress,
+ maxSendable: user.platformLightningAddress.maxSendable?.toString(),
+ minSendable: user.platformLightningAddress.minSendable?.toString()
+ };
+ }
+
// If we are linking a github account to an existing email or anon account (we have privkey)
if (account?.provider === "github" && user?.id && user?.pubkey && user?.privkey) {
try {
// First update the user's profile with GitHub info
const updatedUser = await updateUser(user.id, {
- name: profile?.login || profile?.name,
username: profile?.login || profile?.name,
avatar: profile?.avatar_url,
- image: profile?.avatar_url,
});
// Get the updated user
@@ -341,10 +363,8 @@ export const authOptions = {
if (!existingGithubAccount) {
// Update user profile with GitHub info
const updatedUser = await updateUser(user.id, {
- name: profile?.login || profile?.name,
username: profile?.login || profile?.name,
avatar: profile?.avatar_url,
- image: profile?.avatar_url,
email: profile?.email // Add email if user wants it
});
diff --git a/src/pages/api/lightning-address/callback/[slug].js b/src/pages/api/lightning-address/callback/[slug].js
index 1e3116a..b434544 100644
--- a/src/pages/api/lightning-address/callback/[slug].js
+++ b/src/pages/api/lightning-address/callback/[slug].js
@@ -60,16 +60,21 @@ export default async function handler(req, res) {
descriptionHash = Buffer.from(hash, 'hex').toString('base64');
}
- // Convert amount from millisatoshis to satoshis
- if (amount < (foundAddress.minSendable)) {
+ // Check amount against BigInt min/max values
+ if (amount < foundAddress.minSendable) {
res.status(400).json({ error: 'Amount too low' });
return;
- } else if (amount > (foundAddress.maxSendable || Number.MAX_SAFE_INTEGER)) {
+ } else if (amount > foundAddress.maxSendable) {
res.status(400).json({ error: 'Amount too high' });
return;
} else {
try {
- const response = await axios.post(`${BACKEND_URL}/api/lightning-address/lnd`, { amount: amount, description_hash: descriptionHash, name: slug, zap_request: queryParams?.nostr ? queryParams.nostr : null }, {
+ const response = await axios.post(`${BACKEND_URL}/api/lightning-address/lnd`, {
+ amount: amount,
+ description_hash: descriptionHash,
+ name: slug,
+ zap_request: queryParams?.nostr ? queryParams.nostr : null
+ }, {
headers: {
'Authorization': PLEBDEVS_API_KEY
}
diff --git a/src/pages/api/lightning-address/lnurlp/[slug].js b/src/pages/api/lightning-address/lnurlp/[slug].js
index f084a18..172f6a0 100644
--- a/src/pages/api/lightning-address/lnurlp/[slug].js
+++ b/src/pages/api/lightning-address/lnurlp/[slug].js
@@ -35,8 +35,8 @@ export default async function handler(req, res) {
res.status(200).json({
callback: `${BACKEND_URL}/api/lightning-address/callback/${foundAddress.name}`,
- maxSendable: foundAddress.maxSendable || 10000000000,
- minSendable: foundAddress.minSendable || 1000,
+ maxSendable: parseInt(foundAddress.maxSendable),
+ minSendable: parseInt(foundAddress.minSendable),
metadata: JSON.stringify(metadata),
tag: 'payRequest',
allowsNostr: true,
diff --git a/src/pages/api/users/[slug]/lightning-address.js b/src/pages/api/users/[slug]/lightning-address.js
index 8c55657..a5fe4cb 100644
--- a/src/pages/api/users/[slug]/lightning-address.js
+++ b/src/pages/api/users/[slug]/lightning-address.js
@@ -30,9 +30,23 @@ export default async function handler(req, res) {
case 'POST':
try {
const { name, description, maxSendable, minSendable, invoiceMacaroon, lndCert, lndHost, lndPort } = req.body;
- const lightningAddress = await createLightningAddress(userId, name, description, maxSendable, minSendable, invoiceMacaroon, lndCert, lndHost, lndPort);
+ const lightningAddress = await createLightningAddress(
+ userId,
+ name,
+ description,
+ BigInt(maxSendable),
+ BigInt(minSendable),
+ invoiceMacaroon,
+ lndCert,
+ lndHost,
+ lndPort
+ );
- res.status(201).json(lightningAddress);
+ res.status(201).json({
+ ...lightningAddress,
+ maxSendable: lightningAddress.maxSendable.toString(),
+ minSendable: lightningAddress.minSendable.toString()
+ });
} catch (error) {
console.error('Error creating Lightning Address:', error);
res.status(500).json({ error: 'Error creating Lightning Address', errorMessage: error.message });
diff --git a/src/pages/auth/signin.js b/src/pages/auth/signin.js
index b6761b6..bc422f0 100644
--- a/src/pages/auth/signin.js
+++ b/src/pages/auth/signin.js
@@ -17,7 +17,7 @@ export default function SignIn() {
const handleEmailSignIn = async (e) => {
e.preventDefault()
- await signIn("email", { email, callbackUrl: '/' })
+ await signIn("email", { email, callbackUrl: '/profile' })
}
const handleNostrSignIn = async (e) => {
@@ -28,7 +28,7 @@ export default function SignIn() {
try {
const user = await ndk.signer.user()
const pubkey = user?._pubkey
- signIn("nostr", { pubkey })
+ signIn("nostr", { pubkey, callbackUrl: '/profile' })
} catch (error) {
console.error("Error signing Nostr event:", error)
}
@@ -46,7 +46,7 @@ export default function SignIn() {
pubkey: storedPubkey,
privkey: storedPrivkey,
redirect: false,
- callbackUrl: '/'
+ callbackUrl: '/profile'
});
if (result?.ok) {
@@ -59,7 +59,7 @@ export default function SignIn() {
if (session?.user?.pubkey && session?.user?.privkey) {
localStorage.setItem('anonymousPubkey', session.user.pubkey);
localStorage.setItem('anonymousPrivkey', session.user.privkey);
- router.push('/');
+ router.push('/profile');
} else {
console.error("Session data incomplete:", session);
}
@@ -77,11 +77,11 @@ export default function SignIn() {
const result = await signIn("recovery", {
nsec,
redirect: false,
- callbackUrl: '/'
+ callbackUrl: '/profile'
});
if (result?.ok) {
- router.push('/');
+ router.push('/profile');
} else {
console.error("Recovery login failed:", result?.error);
}
@@ -93,7 +93,7 @@ export default function SignIn() {
useEffect(() => {
// Redirect if already signed in
if (session?.user) {
- router.push('/');
+ router.push('/profile');
}
}, [session, router]);
diff --git a/src/pages/draft/[slug]/index.js b/src/pages/draft/[slug]/index.js
index df9f0f3..b189c18 100644
--- a/src/pages/draft/[slug]/index.js
+++ b/src/pages/draft/[slug]/index.js
@@ -327,7 +327,7 @@ export default function Draft() {
Created by{' '}
- {user?.username || user?.name || user?.pubkey.slice(0, 10)}{'... '}
+ {user?.username || user?.pubkey.slice(0, 10)}{'... '}
)}
diff --git a/src/pages/subscribe.js b/src/pages/subscribe.js
index bb72f5e..56949bf 100644
--- a/src/pages/subscribe.js
+++ b/src/pages/subscribe.js
@@ -101,12 +101,12 @@ const Subscribe = () => {
command: () => setCalendlyVisible(true),
},
{
- label: session?.user?.lightningAddress ? "Update PlebDevs Lightning Address" : "Claim PlebDevs Lightning Address",
+ label: session?.user?.platformLightningAddress ? "Update PlebDevs Lightning Address" : "Claim PlebDevs Lightning Address",
icon: "pi pi-bolt",
command: () => setLightningAddressVisible(true),
},
{
- label: session?.user?.nip05 ? "Update PlebDevs Nostr NIP-05" : "Claim PlebDevs Nostr NIP-05",
+ label: session?.user?.platformNip05?.name ? "Update PlebDevs Nostr NIP-05" : "Claim PlebDevs Nostr NIP-05",
icon: "pi pi-at",
command: () => setNip05Visible(true),
},
@@ -122,23 +122,6 @@ const Subscribe = () => {
},
];
- const subscriptionCardTitleAndButton = (
-
- Plebdevs Subscription
- menu.current.toggle(e)}
- >
-
-
- );
-
- const subscriptionCardTitle = (
-
- Plebdevs Subscription
-
- );
-
return (
{windowWidth < 768 && (
@@ -242,8 +225,8 @@ const Subscribe = () => {
setCalendlyVisible(true)} />
- setNip05Visible(true)} />
- } onClick={() => setLightningAddressVisible(true)} />
+ setNip05Visible(true)} />
+ } onClick={() => setLightningAddressVisible(true)} />
@@ -296,7 +279,7 @@ const Subscribe = () => {
visible={calendlyVisible}
onHide={() => setCalendlyVisible(false)}
userId={session?.user?.id}
- userName={session?.user?.name || user?.kind0?.username}
+ userName={session?.user?.username || user?.kind0?.username}
userEmail={session?.user?.email}
/>
{
fields.lud16 = lud16;
}
+ const nip05 = findTruthyPropertyValue(kind0, ['nip05']);
+
+ if (nip05) {
+ fields.nip05 = nip05;
+ }
+
return fields;
}