Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions app/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useSession } from 'next-auth/react'
import { redirect } from 'next/navigation'
import type { UserProfile } from '@/lib/api-schema'
import ProfileForm from '@/components/profile/ProfileForm'
import ContractDemo from '@/components/web3/ContractDemo'

const fetchProfile = async (): Promise<UserProfile> => {
const res = await fetch('/api/profile')
Expand All @@ -13,7 +14,6 @@ const fetchProfile = async (): Promise<UserProfile> => {
}

export default function ProfilePage() {
// Protect the route
const { status } = useSession({
required: true,
onUnauthenticated() {
Expand All @@ -36,8 +36,15 @@ export default function ProfilePage() {

return (
<main className='container mx-auto max-w-2xl py-12'>
<h1 className='text-3xl font-bold mb-8'>Edit Your Profile</h1>
{profile && <ProfileForm profile={profile} />}
<div>
<h1 className='text-3xl font-bold mb-8'>Edit Your Profile</h1>
{profile && <ProfileForm profile={profile} />}
</div>

<div>
<h2 className='text-2xl font-bold mb-4'>Web3 Contract Interaction</h2>
<ContractDemo />
</div>
</main>
)
}
95 changes: 95 additions & 0 deletions components/web3/ContractDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
'use client'

import { proofOfFandomContract } from '@/lib/contracts'
import {
useAccount,
useReadContract,
useWriteContract,
useWaitForTransactionReceipt,
} from 'wagmi'
import { useState } from 'react'

export default function ContractDemo() {
const { address, isConnected } = useAccount()
const [minted, setMinted] = useState(false)

const { data: balance, isLoading: isBalanceLoading } = useReadContract({
...proofOfFandomContract,
functionName: 'balanceOf',
args: [address!],
query: {
enabled: isConnected,
},
})

const { data: hash, writeContract, isPending } = useWriteContract()

const { isLoading: isConfirming, isSuccess: isConfirmed } =
useWaitForTransactionReceipt({
hash,
})

const handleMint = () => {
writeContract({
...proofOfFandomContract,
functionName: 'mint',
args: [],
})
}

if (isConfirmed && !minted) {
setMinted(true)
}

if (!isConnected) {
return (
<p className='text-center text-gray-500'>
Please connect your wallet to interact with the contract.
</p>
)
}

return (
<div className='p-6 border rounded-lg space-y-4'>
<h3 className='text-xl font-bold'>Proof of Fandom Contract</h3>

<div>
<p>Your Fandom Token Balance:</p>
{isBalanceLoading ? (
<span className='text-gray-400'>Loading...</span>
) : (
<span className='text-2xl font-mono'>
{balance?.toString() ?? '0'}
</span>
)}
</div>

<div className='flex flex-col items-start space-y-2'>
<button
onClick={handleMint}
disabled={isPending || isConfirming}
className='bg-blue-600 hover:bg-blue-800 text-white font-bold py-2 px-4 rounded disabled:bg-gray-400'
>
{isPending
? 'Check Wallet...'
: isConfirming
? 'Minting...'
: 'Mint a Fandom Token'}
</button>
{hash && (
<p className='text-sm text-gray-500'>
Transaction Hash: {`${hash.slice(0, 6)}...${hash.slice(-4)}`}
</p>
)}
{minted && (
<p className='text-green-500 font-bold'>Minted Successfully!</p>
)}
</div>
<p className='text-xs text-gray-400'>
Note: This interacts with a dummy contract address. The transaction will
be sent but is expected to fail on-chain. This demo is to verify the
frontend flow.
</p>
</div>
)
}
28 changes: 28 additions & 0 deletions lib/abi/ProofOfFandom.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
12 changes: 12 additions & 0 deletions lib/abi/contracts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import proofOfFandomAbi from './abi/ProofOfFandom.json'
import { flare, songbird } from './chains'

const proofOfFandomAddress =
'0x1234567890123456789012345678901234567890' as const

export const proofOfFandomContract = {
address: proofOfFandomAddress,
abi: proofOfFandomAbi,

chains: [flare.id, songbird.id],
}
Loading