@@ -19,12 +19,15 @@ import {
1919 normalizeEnsDomainName ,
2020 REGISTER_CONTRACT_ABI ,
2121 REGISTER_CONTRACT_ADDRESSES ,
22+ buildReverseRegistrarSignatureDigest ,
2223} from 'apps/web/src/utils/usernames' ;
2324import { Dispatch , SetStateAction , useCallback , useMemo , useState } from 'react' ;
2425import { encodeFunctionData , namehash } from 'viem' ;
2526import { useAccount } from 'wagmi' ;
2627import { secondsInYears } from 'apps/web/src/utils/secondsInYears' ;
2728import L2ReverseRegistrarAbi from 'apps/web/src/abis/L2ReverseRegistrarAbi' ;
29+ import { type AbiFunction } from 'viem' ;
30+ import { useSignMessage } from 'wagmi' ;
2831
2932type UseRegisterNameCallbackReturnType = {
3033 callback : ( ) => Promise < void > ;
@@ -50,6 +53,8 @@ export function useRegisterNameCallback(
5053 const { paymasterService : paymasterServiceEnabled } = useCapabilitiesSafe ( {
5154 chainId : basenameChain . id ,
5255 } ) ;
56+ const { signMessageAsync, status : signMessageStatus } = useSignMessage ( ) ;
57+ const signMessageIsLoading = signMessageStatus === 'pending' ;
5358
5459 // If user has a basename, reverse record is set to false
5560 const { data : baseEnsName , isLoading : baseEnsNameIsLoading } = useBaseEnsName ( {
@@ -62,6 +67,7 @@ export function useRegisterNameCallback(
6267 ) ;
6368
6469 const [ reverseRecord , setReverseRecord ] = useState < boolean > ( ! hasExistingBasename ) ;
70+ const [ signatureError , setSignatureError ] = useState < Error | null > ( null ) ;
6571
6672 // Transaction with paymaster enabled
6773 const { initiateBatchCalls, batchCallsStatus, batchCallsIsLoading, batchCallsError } =
@@ -85,9 +91,30 @@ export function useRegisterNameCallback(
8591 const normalizedName = normalizeEnsDomainName ( name ) ;
8692 const isDiscounted = Boolean ( discountKey && validationData ) ;
8793
94+ const signMessageForReverseRecord = useCallback ( async ( ) => {
95+ if ( ! address ) throw new Error ( 'No address' ) ;
96+ const reverseRegistrar = USERNAME_L2_REVERSE_REGISTRAR_ADDRESSES [ basenameChain . id ] ;
97+
98+ const functionAbi = L2ReverseRegistrarAbi . find (
99+ ( f ) => f . type === 'function' && f . name === 'setNameForAddrWithSignature' ,
100+ ) as unknown as AbiFunction ;
101+ const signatureExpiry = BigInt ( Math . floor ( Date . now ( ) / 1000 ) + 5 * 60 ) ;
102+ const { digest, coinTypes } = buildReverseRegistrarSignatureDigest ( {
103+ reverseRegistrar,
104+ functionAbi,
105+ address,
106+ chainId : basenameChain . id ,
107+ name,
108+ signatureExpiry,
109+ } ) ;
110+ const signature = await signMessageAsync ( { message : { raw : digest } } ) ;
111+ return { coinTypes, signatureExpiry, signature } as const ;
112+ } , [ address , basenameChain . id , name , signMessageAsync ] ) ;
113+
88114 // Callback
89115 const registerName = useCallback ( async ( ) => {
90116 if ( ! address ) return ;
117+ setSignatureError ( null ) ;
91118
92119 const addressData = encodeFunctionData ( {
93120 abi : L2ResolverAbi ,
@@ -114,16 +141,36 @@ export function useRegisterNameCallback(
114141 ] ,
115142 } ) ;
116143
144+ let coinTypesForRequest : readonly bigint [ ] = [ ] ;
145+ let signatureExpiryForRequest = 0n ;
146+ let signatureForRequest : `0x${string } ` = '0x' ;
147+
148+ if ( ! paymasterServiceEnabled && reverseRecord ) {
149+ try {
150+ const payload = await signMessageForReverseRecord ( ) ;
151+ coinTypesForRequest = payload . coinTypes ;
152+ signatureExpiryForRequest = payload . signatureExpiry ;
153+ signatureForRequest = payload . signature ;
154+ } catch ( e ) {
155+ logError ( e , 'Reverse record signature step failed' ) ;
156+ const msg = e instanceof Error && e . message ? e . message : 'Unknown error' ;
157+ setSignatureError ( new Error ( `Could not prepare reverse record signature: ${ msg } ` ) ) ;
158+ return ;
159+ }
160+ }
161+
162+ const reverseRecordForRequest = paymasterServiceEnabled ? false : reverseRecord ;
163+
117164 const registerRequest = {
118165 name : normalizedName , // The name being registered.
119166 owner : address , // The address of the owner for the name.
120167 duration : secondsInYears ( years ) , // The duration of the registration in seconds.
121168 resolver : UPGRADEABLE_L2_RESOLVER_ADDRESSES [ basenameChain . id ] , // The address of the resolver to set for this name.
122169 data : [ addressData , baseCointypeData , nameData ] , // Multicallable data bytes for setting records in the associated resolver upon registration.
123- reverseRecord, // Bool to decide whether to set this name as the "primary" name for the `owner` .
124- coinTypes : [ ] ,
125- signatureExpiry : 0 ,
126- signature : '0x' ,
170+ reverseRecord : reverseRecordForRequest , // When using paymaster (atomic batch), set via separate call instead of signature flow .
171+ coinTypes : coinTypesForRequest ,
172+ signatureExpiry : signatureExpiryForRequest ,
173+ signature : signatureForRequest ,
127174 } ;
128175
129176 try {
@@ -177,15 +224,16 @@ export function useRegisterNameCallback(
177224 normalizedName ,
178225 paymasterServiceEnabled ,
179226 reverseRecord ,
227+ signMessageForReverseRecord ,
180228 validationData ,
181229 value ,
182230 years ,
183231 ] ) ;
184232
185233 return {
186234 callback : registerName ,
187- isPending : registerNameIsLoading || batchCallsIsLoading ,
188- error : registerNameError ?? batchCallsError ,
235+ isPending : registerNameIsLoading || batchCallsIsLoading || signMessageIsLoading ,
236+ error : signatureError ?? registerNameError ?? batchCallsError ,
189237 reverseRecord,
190238 setReverseRecord,
191239 hasExistingBasename,
0 commit comments