1- import { useState , ChangeEvent } from 'react' ;
2- import { Container , Button , Stack , Text , TextField , useTheme } from '@interchain-ui/react' ;
1+ import { useState , useEffect } from 'react' ;
2+ import { Container , Button , Stack , Text , useTheme } from '@interchain-ui/react' ;
33import { useChain } from '@interchain-kit/react' ;
44import { useChainStore } from '@/contexts' ;
55import { useToast } from '@/hooks' ;
66
77export default function SignMessage ( ) {
88 const [ message , setMessage ] = useState ( '' ) ;
9- const [ signature , setSignature ] = useState ( '' ) ;
10- const [ isValid , setIsValid ] = useState < boolean | null > ( null ) ;
11- const [ verifying , setVerifying ] = useState ( false ) ;
9+ const [ loading , setLoading ] = useState ( false ) ;
10+ const [ signingIn , setSigningIn ] = useState ( false ) ;
1211 const { selectedChain } = useChainStore ( ) ;
1312 const { address, wallet, chain } = useChain ( selectedChain ) ;
1413 const { toast } = useToast ( ) ;
1514 const { theme } = useTheme ( ) ;
1615
17- const handleSign = async ( ) => {
18- if ( ! wallet || ! address || ! chain . chainId ) {
16+ useEffect ( ( ) => {
17+ // Load the authentication message when component mounts
18+ fetchAuthMessage ( ) ;
19+ } , [ ] ) ;
20+
21+ const fetchAuthMessage = async ( ) => {
22+ try {
23+ setLoading ( true ) ;
24+ const response = await fetch ( '/api/generate-auth-message' ) ;
25+ const data = await response . json ( ) ;
26+
27+ if ( ! response . ok ) {
28+ throw new Error ( data . error || 'Failed to fetch authentication message' ) ;
29+ }
30+
31+ setMessage ( data . message ) ;
32+ } catch ( error ) {
33+ console . error ( 'Error fetching auth message:' , error ) ;
1934 toast ( {
2035 title : 'Error' ,
21- description : 'Please connect your wallet first ' ,
36+ description : 'Failed to fetch authentication message ' ,
2237 type : 'error'
2338 } ) ;
24- return ;
39+ } finally {
40+ setLoading ( false ) ;
2541 }
42+ } ;
2643
27- try {
28- setSignature ( '' ) ;
29- setIsValid ( null ) ;
30- const result = await wallet . signArbitrary ( chain . chainId , address , message ) ;
31- setSignature ( result . signature ) ;
32- } catch ( error ) {
33- console . error ( 'Error signing message:' , error ) ;
44+ const handleSignAndLogin = async ( ) => {
45+ if ( ! wallet || ! address || ! chain . chainId ) {
3446 toast ( {
3547 title : 'Error' ,
36- description : 'Failed to sign message: ' + ( error instanceof Error ? error . message : String ( error ) ) ,
48+ description : 'Please connect your wallet first' ,
3749 type : 'error'
3850 } ) ;
51+ return ;
3952 }
40- } ;
41-
42- const handleVerify = async ( ) => {
43- if ( ! signature || ! address || ! chain . chainId ) return ;
4453
4554 try {
46- setVerifying ( true ) ;
55+ setSigningIn ( true ) ;
56+
57+ // Sign the message
58+ const result = await wallet . signArbitrary ( chain . chainId , address , message ) ;
59+
60+ // Get the public key
4761 const account = await wallet ?. getAccount ( chain . chainId ) ;
4862 if ( ! account ?. pubkey ) {
4963 throw new Error ( 'Failed to get public key' ) ;
5064 }
5165
66+ // Submit to API directly
5267 const response = await fetch ( '/api/verify-signature' , {
5368 method : 'POST' ,
5469 headers : {
5570 'Content-Type' : 'application/json' ,
5671 } ,
5772 body : JSON . stringify ( {
5873 message,
59- signature,
74+ signature : result . signature ,
6075 publicKey : Buffer . from ( account . pubkey ) . toString ( 'base64' ) ,
6176 signer : address
6277 } ) ,
6378 } ) ;
6479
6580 const data = await response . json ( ) ;
66- setIsValid ( data . success ) ;
81+
82+ if ( ! response . ok ) {
83+ throw new Error ( data . error || 'Login failed' ) ;
84+ }
85+
86+ if ( ! data . success && data . message ?. includes ( 'expired' ) ) {
87+ toast ( {
88+ title : 'Authentication expired' ,
89+ description : 'Authentication expired, please try again' ,
90+ type : 'error'
91+ } ) ;
92+ handleRefreshMessage ( ) ;
93+ return ;
94+ }
95+
96+ if ( data . success ) {
97+ toast ( {
98+ title : 'Success' ,
99+ description : 'Authentication successful' ,
100+ type : 'success'
101+ } ) ;
102+ // Handle successful login - redirect or update UI state
103+ // You can add navigation or state management here
104+ } else {
105+ throw new Error ( data . message || 'Authentication failed' ) ;
106+ }
67107 } catch ( error ) {
68- console . error ( 'Error verifying signature :' , error ) ;
108+ console . error ( 'Error signing in :' , error ) ;
69109 toast ( {
70110 title : 'Error' ,
71- description : 'Failed to verify signature' ,
111+ description : 'Failed to sign in: ' + ( error instanceof Error ? error . message : String ( error ) ) ,
72112 type : 'error'
73113 } ) ;
74114 } finally {
75- setVerifying ( false ) ;
115+ setSigningIn ( false ) ;
76116 }
77117 } ;
78118
79- const handleMessageChange = ( e : ChangeEvent < HTMLInputElement > ) => {
80- setMessage ( e . target . value ) ;
81- setSignature ( '' ) ;
82- setIsValid ( null ) ;
119+ const handleRefreshMessage = ( ) => {
120+ fetchAuthMessage ( ) ;
83121 } ;
84122
85123 return (
@@ -93,64 +131,51 @@ export default function SignMessage() {
93131 >
94132 < Stack direction = "vertical" space = "$12" >
95133 < Text as = "h1" fontSize = "$xl" fontWeight = "$semibold" >
96- Sign Arbitrary Message
134+ Sign Authentication Message
97135 </ Text >
98136
99137 < Stack direction = "vertical" space = "$8" >
100138 < Text as = "label" fontSize = "$md" >
101- Message to Sign
139+ Authentication Message
102140 </ Text >
103- < TextField
104- id = "message"
105- placeholder = "Enter your message here"
106- value = { message }
107- onChange = { handleMessageChange }
108- />
141+ < Container
142+ attributes = { {
143+ p : '$16' ,
144+ backgroundColor : theme === 'light' ? '$gray100' : '$gray900' ,
145+ borderRadius : '$md'
146+ } }
147+ >
148+ { loading ? (
149+ < Text > Loading authentication message...</ Text >
150+ ) : (
151+ < Text
152+ fontSize = "$sm"
153+ fontFamily = "$mono"
154+ whiteSpace = "pre-wrap"
155+ attributes = { { whiteSpace : 'pre-line' } } // This ensures line breaks are preserved
156+ >
157+ { message }
158+ </ Text >
159+ ) }
160+ </ Container >
161+ < Button
162+ intent = "secondary"
163+ onClick = { handleRefreshMessage }
164+ size = "sm"
165+ disabled = { loading || signingIn }
166+ >
167+ Refresh Message
168+ </ Button >
109169 </ Stack >
110170
111171 < Button
112- intent = "tertiary"
113- onClick = { handleSign }
114- disabled = { ! message || ! wallet }
172+ intent = "primary"
173+ onClick = { handleSignAndLogin }
174+ disabled = { ! message || ! wallet || loading }
175+ isLoading = { signingIn }
115176 >
116- Sign Message
177+ Sign and Login
117178 </ Button >
118-
119- { signature && (
120- < Stack direction = "vertical" space = "$8" >
121- < Text fontWeight = "$semibold" > Signature:</ Text >
122- < Container
123- attributes = { {
124- p : '$16' ,
125- backgroundColor : theme === 'light' ? '$gray100' : '$gray900' ,
126- borderRadius : '$md'
127- } }
128- >
129- < Text fontSize = "$sm" fontFamily = "$mono" >
130- { signature }
131- </ Text >
132- </ Container >
133-
134- < Button
135- intent = "primary"
136- onClick = { handleVerify }
137- disabled = { verifying }
138- isLoading = { verifying }
139- >
140- Verify Signature
141- </ Button >
142-
143- { isValid !== null && (
144- < Text
145- fontSize = "$md"
146- color = { isValid ? '$green500' : '$red500' }
147- fontWeight = "$medium"
148- >
149- Signature is { isValid ? 'valid' : 'invalid' }
150- </ Text >
151- ) }
152- </ Stack >
153- ) }
154179 </ Stack >
155180 </ Container >
156181 </ >
0 commit comments