2025-08-30 18:34:50 +05:30
import * as React from 'react' ;
import { Button } from '@/components/ui/button' ;
import {
Bitcoin ,
Coins ,
Shield ,
ShieldCheck ,
Loader2 ,
AlertCircle ,
} from 'lucide-react' ;
2025-09-03 15:56:00 +05:30
import { useAuth , useAuthActions } from '@/hooks' ;
2025-09-18 11:08:42 +05:30
import { EVerificationStatus } from '@opchan/core' ;
2025-08-30 18:34:50 +05:30
import { useAppKitAccount } from '@reown/appkit/react' ;
2025-09-18 11:08:42 +05:30
import { OrdinalDetails , EnsDetails } from '@opchan/core' ;
2025-08-05 10:51:21 +05:30
interface VerificationStepProps {
onComplete : ( ) = > void ;
onBack : ( ) = > void ;
isLoading : boolean ;
setIsLoading : ( loading : boolean ) = > void ;
}
export function VerificationStep ( {
onComplete ,
onBack ,
isLoading ,
setIsLoading ,
} : VerificationStepProps ) {
2025-09-03 15:56:00 +05:30
const { currentUser , verificationStatus , isAuthenticating } = useAuth ( ) ;
const { verifyWallet } = useAuthActions ( ) ;
2025-08-30 18:34:50 +05:30
2025-08-05 10:51:21 +05:30
// Get account info to determine wallet type
2025-08-30 18:34:50 +05:30
const bitcoinAccount = useAppKitAccount ( { namespace : 'bip122' } ) ;
const ethereumAccount = useAppKitAccount ( { namespace : 'eip155' } ) ;
2025-08-05 10:51:21 +05:30
const isBitcoinConnected = bitcoinAccount . isConnected ;
const isEthereumConnected = ethereumAccount . isConnected ;
2025-08-30 18:34:50 +05:30
const walletType = isBitcoinConnected
? 'bitcoin'
: isEthereumConnected
? 'ethereum'
: undefined ;
2025-08-05 10:51:21 +05:30
const [ verificationResult , setVerificationResult ] = React . useState < {
success : boolean ;
message : string ;
2025-08-30 18:34:50 +05:30
details? : OrdinalDetails | EnsDetails ;
2025-08-05 10:51:21 +05:30
} | null > ( null ) ;
2025-09-05 12:53:15 +05:30
// Watch for changes in user state after verification
React . useEffect ( ( ) = > {
if (
verificationResult ? . success &&
verificationResult . message . includes ( 'Checking ownership' )
) {
// Check if actual ownership was verified
2025-09-11 12:36:06 +05:30
// Treat centralized verification status as source of truth
const isOwnerVerified =
verificationStatus === EVerificationStatus . ENS_ORDINAL_VERIFIED ;
2025-09-05 12:53:15 +05:30
const hasOwnership =
walletType === 'bitcoin'
2025-09-11 12:36:06 +05:30
? isOwnerVerified && ! ! currentUser ? . ordinalDetails
: isOwnerVerified && ! ! currentUser ? . ensDetails ;
2025-09-05 12:53:15 +05:30
if ( hasOwnership ) {
setVerificationResult ( {
success : true ,
message :
walletType === 'bitcoin'
? 'Ordinal ownership verified successfully!'
: 'ENS ownership verified successfully!' ,
details :
walletType === 'bitcoin'
? currentUser ? . ordinalDetails
: currentUser ? . ensDetails ,
} ) ;
} else {
setVerificationResult ( {
success : false ,
message :
walletType === 'bitcoin'
? 'No Ordinal ownership found. You can still participate in the forum with your connected wallet!'
: 'No ENS ownership found. You can still participate in the forum with your connected wallet!' ,
} ) ;
}
}
2025-09-11 12:36:06 +05:30
} , [ currentUser , verificationResult , walletType , verificationStatus ] ) ;
2025-09-05 12:53:15 +05:30
2025-08-05 10:51:21 +05:30
const handleVerify = async ( ) = > {
if ( ! currentUser ) return ;
2025-08-30 18:34:50 +05:30
2025-08-05 10:51:21 +05:30
setIsLoading ( true ) ;
setVerificationResult ( null ) ;
2025-08-30 18:34:50 +05:30
2025-08-05 10:51:21 +05:30
try {
2025-09-03 15:56:00 +05:30
const success = await verifyWallet ( ) ;
2025-08-30 18:34:50 +05:30
2025-08-05 10:51:21 +05:30
if ( success ) {
2025-09-05 12:53:15 +05:30
// For now, just show success - the actual ownership check will be done
// by the useEffect when the user state updates
2025-08-05 10:51:21 +05:30
setVerificationResult ( {
success : true ,
2025-08-30 18:34:50 +05:30
message :
walletType === 'bitcoin'
2025-09-05 12:53:15 +05:30
? 'Verification process completed. Checking ownership...'
: 'Verification process completed. Checking ownership...' ,
details : undefined ,
2025-08-05 10:51:21 +05:30
} ) ;
} else {
setVerificationResult ( {
success : false ,
2025-08-30 18:34:50 +05:30
message :
walletType === 'bitcoin'
? 'No Ordinal ownership found. You can still participate in the forum with your connected wallet!'
: 'No ENS ownership found. You can still participate in the forum with your connected wallet!' ,
2025-08-05 10:51:21 +05:30
} ) ;
}
} catch ( error ) {
setVerificationResult ( {
success : false ,
2025-08-30 18:34:50 +05:30
message : ` Verification failed. Please try again: ${ error } ` ,
2025-08-05 10:51:21 +05:30
} ) ;
} finally {
setIsLoading ( false ) ;
}
} ;
const handleNext = ( ) = > {
onComplete ( ) ;
} ;
const getVerificationType = ( ) = > {
2025-08-18 14:07:01 +05:30
return walletType === 'bitcoin' ? 'Bitcoin Ordinal' : 'Ethereum ENS' ;
2025-08-05 10:51:21 +05:30
} ;
const getVerificationIcon = ( ) = > {
return walletType === 'bitcoin' ? Bitcoin : Coins ;
} ;
const getVerificationColor = ( ) = > {
return walletType === 'bitcoin' ? 'text-orange-500' : 'text-blue-500' ;
} ;
const getVerificationDescription = ( ) = > {
if ( walletType === 'bitcoin' ) {
2025-08-18 14:07:01 +05:30
return "Verify your Bitcoin Ordinal ownership to unlock premium features. If you don't own any Ordinals, you can still participate in the forum with your connected wallet." ;
2025-08-05 10:51:21 +05:30
} else {
2025-08-18 14:07:01 +05:30
return "Verify your Ethereum ENS ownership to unlock premium features. If you don't own any ENS, you can still participate in the forum with your connected wallet." ;
2025-08-05 10:51:21 +05:30
}
} ;
// Show verification result
if ( verificationResult ) {
return (
2025-08-06 17:21:56 +05:30
< div className = "flex flex-col h-full" >
< div className = "flex-1 space-y-4" >
2025-08-30 18:34:50 +05:30
< div
className = { ` p-4 rounded-lg border ${
verificationResult . success
? 'bg-green-900/20 border-green-500/30'
: 'bg-yellow-900/20 border-yellow-500/30'
} ` }
>
2025-08-06 17:21:56 +05:30
< div className = "flex items-center gap-2 mb-2" >
{ verificationResult . success ? (
< ShieldCheck className = "h-5 w-5 text-green-500" / >
2025-08-05 10:51:21 +05:30
) : (
2025-08-06 17:21:56 +05:30
< AlertCircle className = "h-5 w-5 text-yellow-500" / >
2025-08-05 10:51:21 +05:30
) }
2025-08-30 18:34:50 +05:30
< span
className = { ` font-medium ${
verificationResult . success
? 'text-green-400'
: 'text-yellow-400'
} ` }
>
{ verificationResult . success
? 'Verification Complete'
: 'Verification Result' }
2025-08-06 17:21:56 +05:30
< / span >
2025-08-05 10:51:21 +05:30
< / div >
2025-08-06 17:21:56 +05:30
< p className = "text-sm text-neutral-300 mb-2" >
{ verificationResult . message }
< / p >
{ verificationResult . details && (
< div className = "text-xs text-neutral-400" >
{ walletType === 'bitcoin' ? (
2025-08-30 18:34:50 +05:30
< p >
Ordinal ID : { ' ' }
{ typeof verificationResult . details === 'object' &&
'ordinalId' in verificationResult . details
? verificationResult . details . ordinalId
: 'Verified' }
< / p >
2025-08-06 17:21:56 +05:30
) : (
2025-08-30 18:34:50 +05:30
< p >
ENS Name : { ' ' }
{ typeof verificationResult . details === 'object' &&
'ensName' in verificationResult . details
? verificationResult . details . ensName
: 'Verified' }
< / p >
2025-08-06 17:21:56 +05:30
) }
< / div >
) }
< / div >
2025-08-05 10:51:21 +05:30
< / div >
2025-08-30 18:34:50 +05:30
2025-08-06 17:21:56 +05:30
{ /* Action Button */ }
< div className = "mt-auto" >
< Button
onClick = { handleNext }
className = "w-full bg-blue-600 hover:bg-blue-700 text-white"
disabled = { isLoading }
>
Next
< / Button >
< / div >
2025-08-05 10:51:21 +05:30
< / div >
) ;
}
// Show verification status
2025-09-05 13:41:37 +05:30
if ( verificationStatus === EVerificationStatus . ENS_ORDINAL_VERIFIED ) {
2025-08-05 10:51:21 +05:30
return (
2025-08-06 17:21:56 +05:30
< div className = "flex flex-col h-full" >
< div className = "flex-1 space-y-4" >
< div className = "p-4 bg-green-900/20 border border-green-500/30 rounded-lg" >
< div className = "flex items-center gap-2 mb-2" >
< ShieldCheck className = "h-5 w-5 text-green-500" / >
2025-08-30 18:34:50 +05:30
< span className = "text-green-400 font-medium" >
Already Verified
< / span >
2025-08-05 10:51:21 +05:30
< / div >
2025-08-06 17:21:56 +05:30
< p className = "text-sm text-neutral-300 mb-2" >
Your { getVerificationType ( ) } ownership has been verified .
< / p >
{ currentUser && (
< div className = "text-xs text-neutral-400" >
2025-09-03 15:01:57 +05:30
{ walletType === 'bitcoin' && < p > Ordinal ID : Verified < / p > }
{ walletType === 'ethereum' && < p > ENS Name : Verified < / p > }
2025-08-06 17:21:56 +05:30
< / div >
) }
< / div >
2025-08-05 10:51:21 +05:30
< / div >
2025-08-30 18:34:50 +05:30
2025-08-06 17:21:56 +05:30
{ /* Action Button */ }
< div className = "mt-auto" >
< Button
onClick = { handleNext }
className = "w-full bg-blue-600 hover:bg-blue-700 text-white"
disabled = { isLoading }
>
Next
< / Button >
< / div >
2025-08-05 10:51:21 +05:30
< / div >
) ;
}
// Show verification form
return (
2025-08-06 17:21:56 +05:30
< div className = "flex flex-col h-full" >
< div className = "flex-1 space-y-4" >
< div className = "text-center space-y-2" >
< div className = "flex justify-center" >
2025-08-30 18:34:50 +05:30
{ React . createElement ( getVerificationIcon ( ) , {
className : ` h-8 w-8 ${ getVerificationColor ( ) } ` ,
2025-08-06 17:21:56 +05:30
} ) }
< / div >
< h3 className = "text-lg font-semibold text-white" >
Verify { getVerificationType ( ) } Ownership
< / h3 >
< p className = "text-sm text-neutral-400" >
{ getVerificationDescription ( ) }
< / p >
2025-08-05 10:51:21 +05:30
< / div >
2025-08-06 17:21:56 +05:30
< div className = "p-4 bg-neutral-900/50 border border-neutral-700 rounded-lg" >
< div className = "flex items-center gap-2 mb-2" >
< Shield className = "h-4 w-4 text-blue-500" / >
2025-08-30 18:34:50 +05:30
< span className = "text-sm font-medium text-white" >
What happens during verification ?
< / span >
2025-08-06 17:21:56 +05:30
< / div >
< ul className = "text-xs text-neutral-400 space-y-1" >
{ walletType === 'bitcoin' ? (
< >
< li > • We ' ll check your wallet for Bitcoin Ordinal ownership < / li >
< li > • If found , you ' ll get full posting and voting access < / li >
< li > • If not found , you ' ll have read - only access < / li >
< / >
) : (
< >
< li > • We ' ll check your wallet for ENS domain ownership < / li >
< li > • If found , you ' ll get full posting and voting access < / li >
< li > • If not found , you ' ll have read - only access < / li >
< / >
) }
< / ul >
< / div >
< div className = "text-xs text-neutral-500 text-center" >
Verification is required to access posting and voting features
2025-08-05 10:51:21 +05:30
< / div >
< / div >
2025-08-06 17:21:56 +05:30
{ /* Action Buttons */ }
< div className = "mt-auto space-y-3" >
2025-08-05 10:51:21 +05:30
< Button
onClick = { handleVerify }
disabled = { isLoading || isAuthenticating }
className = "w-full bg-blue-600 hover:bg-blue-700 text-white"
>
{ isLoading || isAuthenticating ? (
< >
< Loader2 className = "mr-2 h-4 w-4 animate-spin" / >
Verifying . . .
< / >
) : (
` Verify ${ getVerificationType ( ) } Ownership `
) }
< / Button >
2025-08-30 18:34:50 +05:30
2025-08-05 10:51:21 +05:30
< Button
onClick = { onBack }
variant = "outline"
className = "w-full border-neutral-600 text-neutral-400 hover:bg-neutral-800"
disabled = { isLoading || isAuthenticating }
>
2025-08-06 17:21:56 +05:30
Back
2025-08-05 10:51:21 +05:30
< / Button >
< / div >
< / div >
) ;
2025-08-30 18:34:50 +05:30
}