Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ID-2517 Fixed session activity call not firing with device flow #2218

Merged
merged 4 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading