@@ -77,6 +77,12 @@ export class ZkEvmProvider implements Provider {
7777
7878 #signerInitialisationError: unknown | undefined ;
7979
80+ /**
81+ * Cache for the user registration promise to prevent race conditions
82+ * when multiple eth_requestAccounts calls happen concurrently
83+ */
84+ #userRegistrationPromise?: Promise < string > | undefined ;
85+
8086 public readonly isPassport : boolean = true ;
8187
8288 constructor ( {
@@ -133,9 +139,17 @@ export class ZkEvmProvider implements Provider {
133139
134140 #handleLogout = ( ) => {
135141 this . #ethSigner = undefined ;
142+ this . #userRegistrationPromise = undefined ;
136143 this . #providerEventEmitter. emit ( ProviderEvent . ACCOUNTS_CHANGED , [ ] ) ;
137144 } ;
138145
146+ /**
147+ * Clear the cached user registration promise
148+ */
149+ #clearUserRegistrationCache = ( ) => {
150+ this . #userRegistrationPromise = undefined ;
151+ } ;
152+
139153 /**
140154 * This method is called by `eth_requestAccounts` and asynchronously initialises the signer.
141155 * The signer is stored in a promise so that it can be retrieved by the provider
@@ -247,18 +261,32 @@ export class ZkEvmProvider implements Provider {
247261 if ( ! isZkEvmUser ( user ) ) {
248262 flow . addEvent ( 'startUserRegistration' ) ;
249263
250- const ethSigner = await this . #getSigner( ) ;
251- flow . addEvent ( 'ethSignerResolved' ) ;
264+ // Check if registration is already in progress to prevent race conditions
265+ if ( ! this . #userRegistrationPromise) {
266+ const ethSigner = await this . #getSigner( ) ;
267+ flow . addEvent ( 'ethSignerResolved' ) ;
268+
269+ // Cache the registration promise to prevent concurrent registrations
270+ this . #userRegistrationPromise = registerZkEvmUser ( {
271+ ethSigner,
272+ authManager : this . #authManager,
273+ multiRollupApiClients : this . #multiRollupApiClients,
274+ accessToken : user . accessToken ,
275+ rpcProvider : this . #rpcProvider,
276+ flow,
277+ } ) ;
278+ }
252279
253- userZkEvmEthAddress = await registerZkEvmUser ( {
254- ethSigner,
255- authManager : this . #authManager,
256- multiRollupApiClients : this . #multiRollupApiClients,
257- accessToken : user . accessToken ,
258- rpcProvider : this . #rpcProvider,
259- flow,
260- } ) ;
261- flow . addEvent ( 'endUserRegistration' ) ;
280+ try {
281+ userZkEvmEthAddress = await this . #userRegistrationPromise;
282+ flow . addEvent ( 'endUserRegistration' ) ;
283+ // Clear the cache after successful registration so future calls get fresh user data
284+ this . #clearUserRegistrationCache( ) ;
285+ } catch ( error ) {
286+ // Clear the cached promise on error so it can be retried
287+ this . #clearUserRegistrationCache( ) ;
288+ throw error ;
289+ }
262290 } else {
263291 userZkEvmEthAddress = user . zkEvm . ethAddress ;
264292 }
0 commit comments