-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from sasatech-gk/devin/1735276554-nft-verse-apis
feat: implement Web3-powered Waka poetry creation service
- Loading branch information
Showing
20 changed files
with
7,212 additions
and
774 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"$schema": "https://ui.shadcn.com/schema.json", | ||
"style": "default", | ||
"rsc": true, | ||
"tsx": true, | ||
"tailwind": { | ||
"config": "tailwind.config.ts", | ||
"css": "src/app/globals.css", | ||
"baseColor": "slate", | ||
"cssVariables": true | ||
}, | ||
"aliases": { | ||
"components": "@/components", | ||
"utils": "@/lib/utils" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,76 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
:root { | ||
--background: #ffffff; | ||
--foreground: #171717; | ||
} | ||
|
||
@media (prefers-color-scheme: dark) { | ||
|
||
@layer base { | ||
:root { | ||
--background: #0a0a0a; | ||
--foreground: #ededed; | ||
--background: 0 0% 100%; | ||
--foreground: 222.2 84% 4.9%; | ||
|
||
--card: 0 0% 100%; | ||
--card-foreground: 222.2 84% 4.9%; | ||
|
||
--popover: 0 0% 100%; | ||
--popover-foreground: 222.2 84% 4.9%; | ||
|
||
--primary: 222.2 47.4% 11.2%; | ||
--primary-foreground: 210 40% 98%; | ||
|
||
--secondary: 210 40% 96.1%; | ||
--secondary-foreground: 222.2 47.4% 11.2%; | ||
|
||
--muted: 210 40% 96.1%; | ||
--muted-foreground: 215.4 16.3% 46.9%; | ||
|
||
--accent: 210 40% 96.1%; | ||
--accent-foreground: 222.2 47.4% 11.2%; | ||
|
||
--destructive: 0 84.2% 60.2%; | ||
--destructive-foreground: 210 40% 98%; | ||
|
||
--border: 214.3 31.8% 91.4%; | ||
--input: 214.3 31.8% 91.4%; | ||
--ring: 222.2 84% 4.9%; | ||
|
||
--radius: 0.5rem; | ||
} | ||
|
||
.dark { | ||
--background: 222.2 84% 4.9%; | ||
--foreground: 210 40% 98%; | ||
|
||
--card: 222.2 84% 4.9%; | ||
--card-foreground: 210 40% 98%; | ||
|
||
--popover: 222.2 84% 4.9%; | ||
--popover-foreground: 210 40% 98%; | ||
|
||
--primary: 210 40% 98%; | ||
--primary-foreground: 222.2 47.4% 11.2%; | ||
|
||
--secondary: 217.2 32.6% 17.5%; | ||
--secondary-foreground: 210 40% 98%; | ||
|
||
--muted: 217.2 32.6% 17.5%; | ||
--muted-foreground: 215 20.2% 65.1%; | ||
|
||
--accent: 217.2 32.6% 17.5%; | ||
--accent-foreground: 210 40% 98%; | ||
|
||
--destructive: 0 62.8% 30.6%; | ||
--destructive-foreground: 210 40% 98%; | ||
|
||
--border: 217.2 32.6% 17.5%; | ||
--input: 217.2 32.6% 17.5%; | ||
--ring: 212.7 26.8% 83.9%; | ||
} | ||
} | ||
|
||
body { | ||
color: var(--foreground); | ||
background: var(--background); | ||
font-family: Arial, Helvetica, sans-serif; | ||
|
||
@layer base { | ||
* { | ||
@apply border-border; | ||
} | ||
body { | ||
@apply bg-background text-foreground; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
import { WakaSchema } from "../schema/waka-schema"; | ||
import { addLowerVerse, verifySignature, getVerse } from "../utils/web3"; | ||
import { ethers } from "ethers"; | ||
import { getProvider } from "../utils/web3"; | ||
|
||
export async function POST(request: NextRequest) { | ||
try { | ||
const body = await request.json(); | ||
// Validate the request body against the schema | ||
const { tokenId, lowerVerse, signature, signerAddress } = WakaSchema.lowerVerse.parse(body); | ||
|
||
// Verify the signature | ||
const message = `Add lower verse to ${tokenId}: ${lowerVerse}`; | ||
if (!verifySignature(message, signature, signerAddress)) { | ||
return NextResponse.json( | ||
{ error: "Invalid signature" }, | ||
{ status: 400 } | ||
); | ||
} | ||
|
||
// Get the verse information to verify it exists and is incomplete | ||
const provider = getProvider(); | ||
const verseInfo = await getVerse(provider, tokenId); | ||
|
||
if (!verseInfo || verseInfo.isComplete) { | ||
return NextResponse.json( | ||
{ error: "Verse not found or already completed" }, | ||
{ status: 400 } | ||
); | ||
} | ||
|
||
// Create wallet from signature for contract interaction | ||
const wallet = new ethers.Wallet(signature); | ||
|
||
// Add lower verse and mint NFT | ||
const { txHash } = await addLowerVerse(wallet, tokenId, lowerVerse); | ||
|
||
return NextResponse.json({ | ||
tokenId, | ||
txHash, | ||
lowerVerse, | ||
signerAddress, | ||
status: "completed", | ||
message: "Lower verse added successfully" | ||
}, { status: 201 }); | ||
} catch (error) { | ||
console.error("Error creating lower verse:", error); | ||
return NextResponse.json( | ||
{ error: "Failed to create lower verse" }, | ||
{ status: 400 } | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
import { WakaSchema } from "../schema/waka-schema"; | ||
import { createUpperVerse, verifySignature } from "../utils/web3"; | ||
import { ethers } from "ethers"; | ||
|
||
export async function POST(request: NextRequest) { | ||
try { | ||
const body = await request.json(); | ||
// Validate the request body against the schema | ||
const { upperVerse, signature, signerAddress } = WakaSchema.upperVerse.parse(body); | ||
|
||
// Verify the signature | ||
const message = `Create upper verse: ${upperVerse}`; | ||
if (!verifySignature(message, signature, signerAddress)) { | ||
return NextResponse.json( | ||
{ error: "Invalid signature" }, | ||
{ status: 400 } | ||
); | ||
} | ||
|
||
// Create wallet from signature for contract interaction | ||
const wallet = new ethers.Wallet(signature); | ||
|
||
// Create upper verse on-chain | ||
const { tokenId, txHash } = await createUpperVerse(wallet, upperVerse); | ||
|
||
return NextResponse.json({ | ||
tokenId, | ||
txHash, | ||
upperVerse, | ||
signerAddress, | ||
collaborationUrl: `/waka/${tokenId}/complete` | ||
}, { status: 201 }); | ||
} catch (error) { | ||
console.error("Error creating upper verse:", error); | ||
return NextResponse.json( | ||
{ error: "Failed to create upper verse" }, | ||
{ status: 400 } | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { z } from "zod"; | ||
|
||
export const WakaSchema = { | ||
upperVerse: z.object({ | ||
upperVerse: z.string() | ||
.min(1, "Upper verse is required") | ||
.max(100, "Upper verse must be less than 100 characters"), | ||
signature: z.string() | ||
.min(1, "Signature is required") | ||
.describe("Ethereum signature of the upper verse"), | ||
signerAddress: z.string() | ||
.min(1, "Signer address is required") | ||
.describe("Ethereum address of the signer"), | ||
}), | ||
|
||
lowerVerse: z.object({ | ||
tokenId: z.string() | ||
.min(1, "Token ID is required"), | ||
lowerVerse: z.string() | ||
.min(1, "Lower verse is required") | ||
.max(100, "Lower verse must be less than 100 characters"), | ||
signature: z.string() | ||
.min(1, "Signature is required") | ||
.describe("Ethereum signature of the lower verse"), | ||
signerAddress: z.string() | ||
.min(1, "Signer address is required") | ||
.describe("Ethereum address of the signer"), | ||
}), | ||
|
||
completeWaka: z.object({ | ||
tokenId: z.string(), | ||
upperVerse: z.string(), | ||
lowerVerse: z.string(), | ||
upperCreator: z.string(), | ||
lowerCreator: z.string(), | ||
txHash: z.string(), | ||
createdAt: z.string(), | ||
completedAt: z.string(), | ||
}), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { customAlphabet } from "nanoid"; | ||
|
||
// Create a custom ID generator with a specific alphabet | ||
const nanoid = customAlphabet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 16); | ||
|
||
export function generateId(): string { | ||
return nanoid(); | ||
} |
Oops, something went wrong.