Skip to content

Commit

Permalink
fix: ID-2517 Fixed session activity call not firing with device flow (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
haydenfowler authored Sep 24, 2024
1 parent 4af9b41 commit 4f52795
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 13 deletions.
110 changes: 103 additions & 7 deletions packages/passport/sdk/src/zkEvm/zkEvmProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { RelayerClient } from './relayerClient';
import { Provider, RequestArguments } from './types';
import { PassportEventMap, PassportEvents } from '../types';
import TypedEventEmitter from '../utils/typedEventEmitter';
import { mockUserZkEvm, testConfig } from '../test/mocks';
import { mockUser, mockUserZkEvm, testConfig } from '../test/mocks';
import { signTypedDataV4 } from './signTypedDataV4';
import MagicAdapter from '../magicAdapter';

Expand Down Expand Up @@ -62,13 +62,91 @@ describe('ZkEvmProvider', () => {
return new ZkEvmProvider(constructorParameters as ZkEvmProviderInput);
};

describe('eth_requestAccounts', () => {
it('constructor tries to automatically connect existing user session when provider is instantiated', async () => {
authManager.getUser.mockReturnValue(Promise.resolve(mockUserZkEvm));
getProvider();
expect(authManager.getUser).toHaveBeenCalledTimes(1);
describe('constructor', () => {
describe('when an application session exists', () => {
it('initialises the signer', async () => {
authManager.getUser.mockResolvedValue(mockUserZkEvm);
getProvider();

await new Promise(process.nextTick); // https://immutable.atlassian.net/browse/ID-2516

expect(authManager.getUser).toBeCalledTimes(1);
expect(magicAdapter.login).toBeCalledTimes(1);
expect(Web3Provider).toBeCalledTimes(1);
});

describe('and the user has not registered before', () => {
it('does not call session activity', async () => {
const onAccountsRequested = jest.fn();
passportEventEmitter.on(PassportEvents.ACCOUNTS_REQUESTED, onAccountsRequested);
authManager.getUser.mockResolvedValue(mockUser);
getProvider();

await new Promise(process.nextTick); // https://immutable.atlassian.net/browse/ID-2516

expect(authManager.getUser).toBeCalledTimes(1);
expect(onAccountsRequested).not.toHaveBeenCalled();
});
});
describe('and the user has registered before', () => {
it('calls session activity', async () => {
const onAccountsRequested = jest.fn();
passportEventEmitter.on(PassportEvents.ACCOUNTS_REQUESTED, onAccountsRequested);
authManager.getUser.mockResolvedValue(mockUserZkEvm);
getProvider();

await new Promise(process.nextTick); // https://immutable.atlassian.net/browse/ID-2516

expect(authManager.getUser).toBeCalledTimes(1);
expect(onAccountsRequested).toHaveBeenCalledTimes(1);
});
});
});

describe('when a login occurs outside of the zkEvm provider', () => {
beforeEach(() => {
authManager.getUser.mockResolvedValue(null);
});

it('initialises the signer', async () => {
getProvider();
passportEventEmitter.emit(PassportEvents.LOGGED_IN, mockUserZkEvm);

await new Promise(process.nextTick); // https://immutable.atlassian.net/browse/ID-2516

expect(magicAdapter.login).toBeCalledTimes(1);
expect(Web3Provider).toBeCalledTimes(1);
});

describe('and the user has not registered before', () => {
it('does not call session activity', async () => {
const onAccountsRequested = jest.fn();
passportEventEmitter.on(PassportEvents.ACCOUNTS_REQUESTED, onAccountsRequested);
getProvider();
passportEventEmitter.emit(PassportEvents.LOGGED_IN, mockUser);

await new Promise(process.nextTick); // https://immutable.atlassian.net/browse/ID-2516

expect(onAccountsRequested).not.toHaveBeenCalled();
});

describe('and the user has registered before', () => {
it('calls session activity', async () => {
const onAccountsRequested = jest.fn();
passportEventEmitter.on(PassportEvents.ACCOUNTS_REQUESTED, onAccountsRequested);
getProvider();
passportEventEmitter.emit(PassportEvents.LOGGED_IN, mockUserZkEvm);

await new Promise(process.nextTick); // https://immutable.atlassian.net/browse/ID-2516

expect(onAccountsRequested).toHaveBeenCalledTimes(1);
});
});
});
});
});

describe('eth_requestAccounts', () => {
it('should return the ethAddress if already logged in', async () => {
authManager.getUser.mockReturnValue(Promise.resolve(mockUserZkEvm));
const provider = getProvider();
Expand Down Expand Up @@ -103,7 +181,7 @@ describe('ZkEvmProvider', () => {

it('should throw an error if the signer initialisation fails', async () => {
authManager.getUserOrLogin.mockReturnValue(mockUserZkEvm);
authManager.getUser.mockReturnValue(Promise.resolve(mockUserZkEvm));
authManager.getUser.mockResolvedValue(mockUserZkEvm);

(Web3Provider as unknown as jest.Mock).mockImplementation(() => ({
getSigner: () => {
Expand All @@ -117,6 +195,24 @@ describe('ZkEvmProvider', () => {
new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Something went wrong'),
);
});

it('should not reinitialise the ethSigner when it has been set during the constructor', async () => {
authManager.getUser.mockResolvedValue(mockUserZkEvm);
const provider = getProvider();

await new Promise(process.nextTick); // https://immutable.atlassian.net/browse/ID-2516

expect(magicAdapter.login).toBeCalledTimes(1);
expect(Web3Provider).toBeCalledTimes(1);

await provider.request({ method: 'eth_requestAccounts' });

// Add a delay so that we can check if the ethSigner is initialised again
await new Promise(process.nextTick);

expect(magicAdapter.login).toBeCalledTimes(1);
expect(Web3Provider).toBeCalledTimes(1);
});
});

describe('eth_sendTransaction', () => {
Expand Down
20 changes: 14 additions & 6 deletions packages/passport/sdk/src/zkEvm/zkEvmProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,20 @@ export class ZkEvmProvider implements Provider {

// Automatically connect an existing user session to Passport
this.#authManager.getUser().then((user) => {
if (user && isZkEvmUser(user)) {
if (user) {
this.#initialiseEthSigner(user);
if (isZkEvmUser(user)) {
this.#callSessionActivity(user.zkEvm.ethAddress);
}
}
}).catch(() => {
// User does not exist, don't initialise an eth signer
});
}).catch(); // User does not exist, don't initialise an eth signer

passportEventEmitter.on(PassportEvents.LOGGED_IN, (user: User) => this.#initialiseEthSigner(user));
passportEventEmitter.on(PassportEvents.LOGGED_IN, (user: User) => {
this.#initialiseEthSigner(user);
if (isZkEvmUser(user)) {
this.#callSessionActivity(user.zkEvm.ethAddress);
}
});
passportEventEmitter.on(PassportEvents.LOGGED_OUT, this.#handleLogout);
passportEventEmitter.on(
PassportEvents.ACCOUNTS_REQUESTED,
Expand Down Expand Up @@ -231,7 +237,9 @@ export class ZkEvmProvider implements Provider {
const user = await this.#authManager.getUserOrLogin();
flow.addEvent('endGetUserOrLogin');

this.#initialiseEthSigner(user);
if (!this.#ethSigner) {
this.#initialiseEthSigner(user);
}

let userZkEvmEthAddress;

Expand Down

0 comments on commit 4f52795

Please sign in to comment.