Skip to content

Commit bad6607

Browse files
committed
cache register user promise
1 parent 29ec917 commit bad6607

1 file changed

Lines changed: 39 additions & 11 deletions

File tree

packages/passport/sdk/src/zkEvm/zkEvmProvider.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)