diff --git a/client/app/api/transactions/route.ts b/client/app/api/transactions/route.ts index ff76317e..e0f02fbd 100644 --- a/client/app/api/transactions/route.ts +++ b/client/app/api/transactions/route.ts @@ -14,6 +14,8 @@ import { transactionIntentPromptTemplate, } from "@/prompts/prompts"; import { StringOutputParser } from "@langchain/core/output_parsers"; +import prisma from "@/lib/db"; +import { TxType } from "@prisma/client"; const llm = new ChatOpenAI({ model: "gpt-4", @@ -151,6 +153,61 @@ async function getTransactionIntentFromOpenAI( } } +async function getOrCreateTransactionChat(userId: string) { + try { + const chat = await prisma.chat.create({ + data: { + userId, + type: "TRANSACTION", + }, + }) + return chat + } catch (error) { + console.error("Error creating transaction chat:", error) + throw error + } +} + +async function storeTransaction(userId: string, type: string, metadata: any) { + try { + const transaction = await prisma.transaction.create({ + data: { + userId, + type: type as TxType, + metadata, + }, + }) + return transaction + } catch (error) { + console.error("Error storing transaction:", error) + throw error + } +} + +async function storeMessage({ + content, + chatId, + userId, +}: { + content: any[] + chatId: string + userId: string +}) { + try { + const message = await prisma.message.create({ + data: { + content, + chatId, + userId, + }, + }) + return message + } catch (error) { + console.error("Error storing message:", error) + throw error + } +} + export async function POST(request: NextRequest) { try { const body = await request.json(); @@ -163,6 +220,18 @@ export async function POST(request: NextRequest) { ); } + let user = await prisma.user.findFirst({ + where: { address }, + }) + + if (!user) { + user = await prisma.user.create({ + data: { address }, + }) + } + + const chat = await getOrCreateTransactionChat(user.id) + try { const transactionIntent = await getTransactionIntentFromOpenAI( prompt, @@ -170,6 +239,13 @@ export async function POST(request: NextRequest) { chainId, messages ); + + await storeMessage({ + content: [{ role: "user", content: prompt }], + chatId: chat.id, + userId: user.id, + }) + console.log( "Processed Transaction Intent from OPENAI:", JSON.stringify(transactionIntent, null, 2) @@ -187,6 +263,24 @@ export async function POST(request: NextRequest) { processedTx.receiver = address; } + const transaction = await storeTransaction(user.id, transactionIntent.action, { + ...processedTx, + chainId, + originalIntent: transactionIntent, + }) + + await storeMessage({ + content: [ + { + role: "assistant", + content: JSON.stringify(processedTx), + transactionId: transaction.id, + }, + ], + chatId: chat.id, + userId: user.id, + }) + return NextResponse.json({ result: [ { diff --git a/client/prisma/schema.prisma b/client/prisma/schema.prisma index 9ece3f55..006ff052 100644 --- a/client/prisma/schema.prisma +++ b/client/prisma/schema.prisma @@ -11,8 +11,10 @@ model User { id String @id @default(uuid()) email String? @unique name String? + address String? @unique chats Chat[] messages Message[] + transactions Transaction[] } model Chat { @@ -20,6 +22,7 @@ model Chat { title String? metadata Json? userId String? + type ChatType @default(GENERAL) User User? @relation(fields: [userId], references: [id]) Message Message[] } @@ -31,11 +34,45 @@ model Message { replyTo String? chatId String userId String + createdAt DateTime @default(now()) Chat Chat @relation(fields: [chatId], references: [id]) User User @relation(fields: [userId], references: [id]) } +model Transaction { + id String @id @default(uuid()) + type TxType + status TxStatus @default(PENDING) + metadata Json? + hash String? + userId String + createdAt DateTime @default(now()) + completedAt DateTime? + User User @relation(fields: [userId], references: [id]) +} + enum Role { USER ASSISTANT } + +enum ChatType { + GENERAL + TRANSACTION + ASK +} + +enum TxType { + SWAP + TRANSFER + BRIDGE + DEPOSIT + WITHDRAW +} + +enum TxStatus { + PENDING + COMPLETED + FAILED +} +