diff --git a/package.json b/package.json index 0eb59071..a57fddc3 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "lucide-react": "^0.447.0", "next": "^15.0.2", "next-auth": "^5.0.0-beta.25", - "node-cache": "^5.1.2", "prism-react-renderer": "^2.4.0", "react": "^19.0.0-rc-fb9a90fa48-20240614", "react-copy-to-clipboard": "^5.1.0", diff --git a/prisma/migrations/20241106020243_add_table_wallet_nonce/migration.sql b/prisma/migrations/20241106020243_add_table_wallet_nonce/migration.sql new file mode 100644 index 00000000..7f0f6379 --- /dev/null +++ b/prisma/migrations/20241106020243_add_table_wallet_nonce/migration.sql @@ -0,0 +1,13 @@ +-- CreateTable +CREATE TABLE "wallet_nonce" ( + "id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + "address" TEXT NOT NULL, + "nonce" TEXT NOT NULL, + + CONSTRAINT "wallet_nonce_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "wallet_nonce_address_key" ON "wallet_nonce"("address"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f374e734..5d1c9069 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -25,6 +25,16 @@ model User { @@map(name: "user") } +model WalletNonce { + id String @id @default(cuid()) + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @updatedAt @map(name: "updated_at") + address String @unique @map(name: "address") + nonce String + + @@map(name: "wallet_nonce") +} + model Collection { id String @id @default(cuid()) createdAt DateTime @default(now()) @map(name: "created_at") diff --git a/src/hooks/use-wallet.ts b/src/hooks/use-wallet.ts index 9cc5139c..00d72009 100644 --- a/src/hooks/use-wallet.ts +++ b/src/hooks/use-wallet.ts @@ -51,11 +51,11 @@ export const useWallet = create((set, get) => ({ } if (isNil(session)) { - const nonce = await getNonceByAddress(address); - if (isNil(nonce) || nonce === "") { - throw new Error("Cant get nonce"); + const { data, result, message } = await getNonceByAddress(address); + if (!result || isNil(data)) { + throw new Error(message); } - const signature = await browserWallet.signData(nonce); + const signature = await browserWallet.signData(data); if (isNil(signature)) { throw new Error("Cant get signature"); } diff --git a/src/instrumentation.ts b/src/instrumentation.ts deleted file mode 100644 index 4f7a2ebc..00000000 --- a/src/instrumentation.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type NodeCache from "node-cache"; - -export async function register() { - if (process.env.NEXT_RUNTIME === "nodejs") { - const NodeCache = (await import("node-cache")).default; - const config: NodeCache.Options = { - stdTTL: 300, - }; - - global.cacheConfigs = new NodeCache(config); - global.cacheUser = new NodeCache(config); - } -} diff --git a/src/lib/auth/config.ts b/src/lib/auth/config.ts index 79ee4ec9..06a4b5e1 100644 --- a/src/lib/auth/config.ts +++ b/src/lib/auth/config.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { checkSignature, DataSignature } from "@meshsdk/core"; +import { checkSignature, DataSignature, generateNonce } from "@meshsdk/core"; import { NextAuthConfig } from "next-auth"; import CredentialProvider from "next-auth/providers/credentials"; import prisma from "@/lib/prisma"; @@ -25,11 +25,15 @@ const authConfig = { if (isNil(wallet) || isNil(address) || isNil(signature)) { throw new Error("Invalid credentials"); } - const walletNonce = await global.cacheUser.get(`nonce-${address}`); - if (isNil(walletNonce)) { + const walletNonce = await prisma.walletNonce.findFirst({ + where: { + address, + }, + }); + if (isNil(walletNonce) || isNil(walletNonce.nonce)) { throw new Error("Nonce not found"); } - const isSignatureValid = checkSignature(walletNonce, signature); + const isSignatureValid = checkSignature(walletNonce.nonce, signature); if (!isSignatureValid) { throw new Error("Invalid signature"); @@ -53,18 +57,15 @@ const authConfig = { ], callbacks: { async signIn({ user }: any) { - await global.cacheUser.del(`nonce-${user.address}`); - const result = await prisma.user.upsert({ + await prisma.walletNonce.update({ where: { address: user.address, }, - create: { - address: user.address, + data: { + nonce: generateNonce("signin to cip68 nft "), }, - update: {}, }); - - return !isNil(result); + return true; }, async redirect() { return "/dashboard"; diff --git a/src/services/auth/get-nonce.ts b/src/services/auth/get-nonce.ts index bc154cd4..2fef7e18 100644 --- a/src/services/auth/get-nonce.ts +++ b/src/services/auth/get-nonce.ts @@ -1,38 +1,46 @@ "use server"; + +import prisma from "@/lib/prisma"; import { generateNonce } from "@meshsdk/core"; import { isNil } from "lodash"; export const getNonceByAddress = async (address: string) => { - if (isNil(address)) { - throw new Error("Stake address is required"); - } + try { + if (isNil(address)) { + throw new Error("Stake address is required"); + } - if (!/^[a-z0-9_]+$/.test(address)) { - throw new Error("Invalid address"); - } + if (!/^[a-z0-9_]+$/.test(address)) { + throw new Error("Invalid address"); + } - // const nonce = generateNonce("signin to cip68 nft"); - // const walletNonce = await prisma.walletNonce.upsert({ - // where: { - // address: address, - // }, - // create: { - // address: address, - // nonce: nonce, - // }, - // update: { - // nonce: nonce, - // }, - // }); + const nonce = generateNonce("signin to cip68 nft"); + const walletNonce = await prisma.walletNonce.upsert({ + where: { + address: address, + }, + create: { + address: address, + nonce: nonce, + }, + update: { + nonce: nonce, + }, + }); + if (!walletNonce) { + throw new Error("Cannot get the nonce"); + } - const nonce = await global.cacheUser.get(`nonce-${address}`); - if (nonce) { - return nonce; - } - const newNonce = generateNonce("signin to cip68 nft"); - const setCache = await global.cacheUser.set(`nonce-${address}`, newNonce); - if (!setCache) { - throw new Error("Cannot get the nonce"); + return { + data: nonce, + result: true, + message: "Nonce generated successfully", + }; + } catch (e) { + return { + data: null, + result: false, + message: e instanceof Error ? e.message : "unknown error", + }; } - return newNonce; }; diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 8f85c0ef..3e6cb115 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/no-empty-object-type */ -/* eslint-disable no-var */ import { Icons } from "@/components/common/icons"; import { BrowserWallet } from "@meshsdk/core"; import { StaticImageData } from "next/image"; @@ -11,10 +10,6 @@ declare module "next-auth" { wallet?: string; } } -declare global { - var cacheConfigs: NodeCache; - var cacheUser: NodeCache; -} export type JsonValue = string | number | boolean | JsonObject | JsonArray; export interface JsonObject {