Skip to content

Commit

Permalink
PPOM instance to stay when user switch the network (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpuri authored Dec 5, 2023
1 parent 7d91def commit c25ceb9
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 181 deletions.
156 changes: 9 additions & 147 deletions src/ppom-controller.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
PPOMClass,
VERSION_INFO,
buildDummyResponse,
buildFetchSpy,
Expand Down Expand Up @@ -369,59 +368,6 @@ describe('PPOMController', () => {
'Aborting validation as not all files could not be downloaded for the network with chainId: 0x1',
);
});

it('should reset PPOM when network is switched', async () => {
buildFetchSpy();
let callBack: any;
const freeMock = jest.fn();
ppomController = buildPPOMController({
storageBackend: buildStorageBackend({
read: async (): Promise<any> => {
throw new Error('not found');
},
}),
onNetworkChange: (func: any) => {
callBack = func;
},
chainId: '0x2',
ppomProvider: {
ppomInit: () => undefined,
PPOM: new PPOMClass(undefined, freeMock),
},
});
callBack({ providerConfig: { chainId: '0x1' } });
await flushPromises();
jest.runOnlyPendingTimers();
await flushPromises();
callBack({ providerConfig: { chainId: '0x2' } });
await flushPromises();
expect(freeMock).toHaveBeenCalledTimes(1);
});

it('should not throw error if PPOM init on network changs fails', async () => {
buildFetchSpy();
let callBack: any;
const newMock = jest.fn().mockImplementation(() => {
throw Error('test');
});
ppomController = buildPPOMController({
onNetworkChange: (func: any) => {
callBack = func;
},
chainId: '0x1',
ppomProvider: {
ppomInit: () => undefined,
PPOM: new PPOMClass(newMock),
},
});
callBack({ providerConfig: { chainId: '0x2' } });
await flushPromises();
jest.runOnlyPendingTimers();
await flushPromises();
callBack({ providerConfig: { chainId: '0x1' } });
await flushPromises();
expect(newMock).toHaveBeenCalledTimes(1);
});
});

describe('updatePPOM', () => {
Expand Down Expand Up @@ -479,25 +425,6 @@ describe('PPOMController', () => {
expect(spy).toHaveBeenCalledTimes(9);
});

it('should set dataFetched to true for supported chainIds in chainStatus', async () => {
buildFetchSpy();
let callBack: any;
ppomController = buildPPOMController({
onNetworkChange: (func: any) => {
callBack = func;
},
});
jest.runOnlyPendingTimers();
callBack({ providerConfig: { chainId: '0x2' } });
await ppomController.updatePPOM();
jest.runOnlyPendingTimers();
await flushPromises();
const chainIdData1 = ppomController.state.chainStatus['0x1'];
const chainIdData2 = ppomController.state.chainStatus['0x2'];
expect(chainIdData1.dataFetched).toBe(true);
expect(chainIdData2.dataFetched).toBe(false);
});

it('should get files for only supported chains in chainStatus', async () => {
const spy = buildFetchSpy({
status: 200,
Expand Down Expand Up @@ -566,20 +493,21 @@ describe('PPOMController', () => {
buildFetchSpy();
let callBack: any;
ppomController = buildPPOMController({
chainId: '0x2',
onNetworkChange: (func: any) => {
callBack = func;
},
});
jest.runOnlyPendingTimers();
await flushPromises();
const chainIdData1 = ppomController.state.chainStatus['0x1'];
const chainIdData1 = ppomController.state.chainStatus['0x2'];
expect(chainIdData1).toBeDefined();
callBack({ providerConfig: { chainId: '0x2' } });
callBack({ providerConfig: { chainId: '0x3' } });
callBack({ providerConfig: { chainId: '0x4' } });
jest.advanceTimersByTime(NETWORK_CACHE_DURATION);
jest.runOnlyPendingTimers();
await flushPromises();
const chainIdData2 = ppomController.state.chainStatus['0x1'];
const chainIdData2 = ppomController.state.chainStatus['0x2'];
expect(chainIdData2).toBeUndefined();
});

Expand All @@ -599,48 +527,6 @@ describe('PPOMController', () => {
await flushPromises();
expect(spy).toHaveBeenCalledTimes(6);
});

it('should re-init ppom when new set of files are fetched', async () => {
buildFetchSpy();
const newMock = jest.fn();
ppomController = buildPPOMController({
ppomProvider: {
ppomInit: () => undefined,
PPOM: new PPOMClass(newMock),
},
fileFetchScheduleDuration: 0,
});
await flushPromises();
jest.advanceTimersByTime(REFRESH_TIME_INTERVAL);
await flushPromises();
expect(newMock).toHaveBeenCalledTimes(1);

buildFetchSpy(
{
status: 200,
json: () => [
...VERSION_INFO,
{
name: 'data2',
chainId: '0x1',
version: '1.0.3',
checksum:
'409a7f83ac6b31dc8c77e3ec18038f209bd2f545e0f4177c2e2381aa4e067b49',
filePath: 'data2',
},
],
},
undefined,
2,
);
await flushPromises();

jest.advanceTimersByTime(REFRESH_TIME_INTERVAL);
await flushPromises();
jest.advanceTimersByTime(1);
await flushPromises();
expect(newMock).toHaveBeenCalledTimes(3);
});
});

describe('onNetworkChange', () => {
Expand Down Expand Up @@ -687,6 +573,7 @@ describe('PPOMController', () => {
buildFetchSpy();
let callBack: any;
ppomController = buildPPOMController({
chainId: '0x2',
onNetworkChange: (func: any) => {
callBack = func;
},
Expand All @@ -695,50 +582,25 @@ describe('PPOMController', () => {
expect(Object.keys(ppomController.state.chainStatus)).toHaveLength(1);

jest.useFakeTimers().setSystemTime(new Date('2023-01-02'));
callBack({ providerConfig: { chainId: '0x2' } });
callBack({ providerConfig: { chainId: '0x3' } });

jest.useFakeTimers().setSystemTime(new Date('2023-01-05'));
callBack({ providerConfig: { chainId: '0x5' } });

jest.useFakeTimers().setSystemTime(new Date('2023-01-03'));
callBack({ providerConfig: { chainId: '0x3' } });
callBack({ providerConfig: { chainId: '0x4' } });

jest.useFakeTimers().setSystemTime(new Date('2023-01-04'));
callBack({ providerConfig: { chainId: '0x4' } });
callBack({ providerConfig: { chainId: '0x6' } });

expect(Object.keys(ppomController.state.chainStatus)).toHaveLength(5);

jest.useFakeTimers().setSystemTime(new Date('2023-01-06'));
callBack({ providerConfig: { chainId: '0x6' } });
callBack({ providerConfig: { chainId: '0x7' } });
expect(Object.keys(ppomController.state.chainStatus)).toHaveLength(5);

expect(ppomController.state.chainStatus['0x1']).toBeUndefined();
});

it('should reset PPOM when network is changed', async () => {
buildFetchSpy();
const freeMock = jest.fn().mockReturnValue('abc');
let callBack: any;
ppomController = buildPPOMController({
onNetworkChange: (func: any) => {
callBack = func;
},
chainId: '0x1',
ppomProvider: {
ppomInit: () => undefined,
PPOM: new PPOMClass(undefined, freeMock),
},
});

await flushPromises();
jest.advanceTimersByTime(REFRESH_TIME_INTERVAL);
await flushPromises();

expect(freeMock).toHaveBeenCalledTimes(0);
callBack({ providerConfig: { chainId: '0x2' } });
callBack({ providerConfig: { chainId: '0x1' } });
expect(freeMock).toHaveBeenCalledTimes(1);
});
});

describe('onPreferencesChange', () => {
Expand Down
40 changes: 6 additions & 34 deletions src/ppom-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,6 @@ export class PPOMController extends BaseControllerV2<
}
// delete chains more than a week old
this.#deleteOldChainIds();
// If none of the networks in chainStatus are supported we stop fetching data files
// and inactivate functionality by reseting PPOM
if (!this.#chainStatusIncludeSupportedNetworks()) {
this.#resetToInactiveState();
return;
}

await this.#updatePPOM();
}

Expand Down Expand Up @@ -398,17 +391,6 @@ export class PPOMController extends BaseControllerV2<
}
}

/*
* The function check if ethereum mainnet is in list of recent networks
*/
#chainStatusIncludeSupportedNetworks() {
const networkIsSupported = this.#networkIsSupported.bind(this);
return (
this.state?.chainStatus &&
Object.keys(this.state?.chainStatus)?.some(networkIsSupported)
);
}

/*
* The function check if ethereum chainId is supported for validation
* Currently it checks for only Ethereum Mainnet but it will include more networks in future.
Expand Down Expand Up @@ -467,7 +449,6 @@ export class PPOMController extends BaseControllerV2<
const id = addHexPrefix(networkControllerState.providerConfig.chainId);
let chainStatus = { ...this.state.chainStatus };
const existingNetworkObject = chainStatus[id];
const oldChainId = this.#chainId;
this.#chainId = id;
chainStatus = {
...chainStatus,
Expand All @@ -483,15 +464,6 @@ export class PPOMController extends BaseControllerV2<
});
this.#deleteOldChainIds();
this.#checkScheduleFileDownloadForAllChains();
if (oldChainId !== id) {
if (chainStatus[id]?.dataFetched) {
this.#reinitPPOM().catch(() => {
console.error('Error in re-init of PPOM');
});
} else {
this.#resetPPOM();
}
}
}

/*
Expand Down Expand Up @@ -765,7 +737,9 @@ export class PPOMController extends BaseControllerV2<
}
const currentTimestamp = new Date().getTime();

const chainIds = Object.keys(this.state.chainStatus);
const chainIds = Object.keys(this.state.chainStatus).filter(
(id) => id !== ETHEREUM_CHAIN_ID,
);
const oldChaninIds: any[] = chainIds.filter(
(chainId) =>
(this.state.chainStatus[chainId] as any).lastVisited <
Expand Down Expand Up @@ -833,7 +807,8 @@ export class PPOMController extends BaseControllerV2<
if (isLastFileOfNetwork) {
// if this was last file for the chainId set dataFetched for chainId to true
await this.#setChainIdDataFetched(fileVersionInfo.chainId);
if (fileVersionInfo.chainId === this.#chainId) {
// if (fileVersionInfo.chainId === this.#chainId) {
if (fileVersionInfo.chainId === ETHEREUM_CHAIN_ID) {
await this.#reinitPPOM();
}
}
Expand Down Expand Up @@ -1055,10 +1030,7 @@ export class PPOMController extends BaseControllerV2<
* starts the scheduled periodic task to fetch files for all the chains.
*/
#checkScheduleFileDownloadForAllChains(): void {
if (
this.#securityAlertsEnabled &&
this.#chainStatusIncludeSupportedNetworks()
) {
if (this.#securityAlertsEnabled) {
if (!this.#refreshDataInterval) {
this.#onDataUpdateDuration();
this.#refreshDataInterval = setInterval(
Expand Down

0 comments on commit c25ceb9

Please sign in to comment.