Skip to content
Open
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
15 changes: 9 additions & 6 deletions src/ppom-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ describe('PPOMController', () => {
}).rejects.toThrow('User has securityAlertsEnabled set to false');
});

it('should throw error if the user is not on ethereum mainnet', async () => {
it('should throw error if the user is not on supported chain id', async () => {
buildFetchSpy();
ppomController = buildPPOMController({
chainId: '0x2',
Expand All @@ -206,7 +206,7 @@ describe('PPOMController', () => {
return Promise.resolve();
});
}).rejects.toThrow(
'Blockaid validation is available only on ethereum mainnet',
'Blockaid validation is not available on selected network',
);
});

Expand Down Expand Up @@ -460,7 +460,7 @@ describe('PPOMController', () => {
await ppomController.updatePPOM();
jest.runOnlyPendingTimers();
await flushPromises();
expect(spy).toHaveBeenCalledTimes(13);
expect(spy).toHaveBeenCalledTimes(12);
});

it('should not re-throw error if file write fails', async () => {
Expand Down Expand Up @@ -493,7 +493,7 @@ describe('PPOMController', () => {
expect(spy).toHaveBeenCalledTimes(6);
jest.advanceTimersByTime(REFRESH_TIME_INTERVAL);
await flushPromises();
expect(spy).toHaveBeenCalledTimes(8);
expect(spy).toHaveBeenCalledTimes(10);
});

it('should delete network more than a week old from chainStatus', async () => {
Expand Down Expand Up @@ -638,11 +638,14 @@ describe('PPOMController', () => {
jest.useFakeTimers().setSystemTime(new Date('2023-01-04'));
callBack({ providerConfig: { chainId: '0x6' } });

expect(Object.keys(ppomController.state.chainStatus)).toHaveLength(5);
jest.useFakeTimers().setSystemTime(new Date('2023-01-04'));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed to add one more because the condition in ppomController for this check to happen is > 5. It doesn't do the check if its <= 5

callBack({ providerConfig: { chainId: '0x8' } });

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

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

expect(ppomController.state.chainStatus['0x1']).toBeUndefined();
});
Expand Down
35 changes: 22 additions & 13 deletions src/ppom-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ const ALLOWED_PROVIDER_CALLS = [
'trace_filter',
];

const ETHEREUM_CHAIN_ID = '0x1';
export const SUPPORTED_CHAIN_IDS = [
'0x1', // ethereum mainnet chain id
'0x38', // bnb chain id
'0x89', // polygon chain id
'0xa4b1', // arbitrum chain id
'0xa', // optimism chain id
'0xa86a', // avalanche chain id
'0xe708', // Linea chain id
];

/**
* @type PPOMFileVersion
Expand Down Expand Up @@ -321,7 +329,7 @@ export class PPOMController extends BaseControllerV2<
if (securityAlertsEnabled) {
this.#updateVersionInfo()
.then(async () => {
await this.#getNewFilesForChain(ETHEREUM_CHAIN_ID);
await this.#getNewFilesForChain(this.#chainId);
// start scheduled task to fetch data files
this.#checkScheduleFileDownloadForAllChains();
})
Expand Down Expand Up @@ -361,7 +369,7 @@ export class PPOMController extends BaseControllerV2<
throw Error('User has securityAlertsEnabled set to false');
}
if (!this.#networkIsSupported(this.#chainId)) {
throw Error('Blockaid validation is available only on ethereum mainnet');
throw Error('Blockaid validation is not available on selected network');
}

await this.#reinitPPOMForNetworkIfRequired();
Expand Down Expand Up @@ -407,11 +415,10 @@ export class PPOMController extends BaseControllerV2<
}

/*
* 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.
* The function check if chainId is supported for validation
*/
#networkIsSupported(chainId: string) {
return chainId === ETHEREUM_CHAIN_ID;
return SUPPORTED_CHAIN_IDS.includes(chainId);
}

/*
Expand Down Expand Up @@ -494,7 +501,7 @@ export class PPOMController extends BaseControllerV2<
this.#updateVersionInfo()
.then(async () => {
this.#checkScheduleFileDownloadForAllChains();
await this.#getNewFilesForChain(ETHEREUM_CHAIN_ID);
await this.#getNewFilesForChain(this.#chainId);
})
.catch((error: Error) => {
console.error(`Error in initialising: ${error.message}`);
Expand Down Expand Up @@ -774,8 +781,9 @@ export class PPOMController extends BaseControllerV2<
const currentTimestamp = new Date().getTime();

const chainIds = Object.keys(this.state.chainStatus).filter(
(id) => id !== ETHEREUM_CHAIN_ID,
(id) => id !== this.#chainId,
);

const oldChaninIds: any[] = chainIds.filter(
(chainId) =>
(this.state.chainStatus[chainId] as any).lastVisited <
Expand Down Expand Up @@ -843,8 +851,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 === ETHEREUM_CHAIN_ID) {
await this.#reinitPPOM(ETHEREUM_CHAIN_ID);
if (fileVersionInfo.chainId === this.#chainId) {
await this.#reinitPPOM(this.#chainId);
}
}
})
Expand Down Expand Up @@ -1000,9 +1008,10 @@ export class PPOMController extends BaseControllerV2<
// thus it is added here to prevent validation from failing.
await this.#initialisePPOM();
const { chainStatus } = this.state;
const versionInfo =
chainStatus[chainId]?.versionInfo ??
this.state.versionInfo.filter(({ chainId: id }) => id === chainId);
const hasVersionInfo = chainStatus[chainId]?.versionInfo?.length;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this part wasn't been called in tests because chainStatus[chainId]?.versionInfo is usually [] not undefined/null. So this check makes sure it works either it's undefined, null or []

const versionInfo = hasVersionInfo
? chainStatus[chainId]?.versionInfo
: this.state.versionInfo.filter(({ chainId: id }) => id === chainId);
if (!versionInfo?.length) {
this.#ppomInitError = `Aborting validation as no files are found for the network with chainId: ${chainId}`;
return undefined;
Expand Down
78 changes: 44 additions & 34 deletions test/test-utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ControllerMessenger } from '@metamask/base-controller';
import * as ControllerUtils from '@metamask/controller-utils';

import { PPOMController } from '../src/ppom-controller';
import { StorageKey } from '../src/ppom-storage';
import { PPOMController, SUPPORTED_CHAIN_IDS } from '../src/ppom-controller';
import { FileMetadata, StorageKey } from '../src/ppom-storage';

export const buildDummyResponse = (
resultType = 'DUMMY_RESULT_TYPE',
Expand All @@ -28,22 +28,25 @@ export const buildStorageBackend = (obj = {}) => {
};
};

export const StorageMetadata = [
{
name: 'data',
chainId: '0x1',
export const StorageMetadata: FileMetadata[] = [];

SUPPORTED_CHAIN_IDS.forEach((chainId) => {
const data = {
name: `${chainId}_data`,
chainId,
version: '1.0.3',
checksum:
'409a7f83ac6b31dc8c77e3ec18038f209bd2f545e0f4177c2e2381aa4e067b49',
},
{
name: 'blob',
chainId: '0x1',
};
const blob = {
name: `${chainId}_blob`,
chainId,
version: '1.0.0',
checksum:
'409a7f83ac6b31dc8c77e3ec18038f209bd2f545e0f4177c2e2381aa4e067b49',
},
];
};
StorageMetadata.push(data, blob);
});

export const simpleStorageBackend = buildStorageBackend();

Expand All @@ -54,28 +57,35 @@ export const storageBackendReturningData = buildStorageBackend({
Promise.resolve(DUMMY_ARRAY_BUFFER_DATA),
});

export const VERSION_INFO = [
{
name: 'blob',
chainId: '0x1',
version: '1.0.0',
checksum:
'409a7f83ac6b31dc8c77e3ec18038f209bd2f545e0f4177c2e2381aa4e067b49',
signature:
'0x304402206d433e9172960de6717d94ae263e47eefacd3584a3274a452f8f9567b3a797db02201b2e423188fb3f9daa6ce6a8723f69df26bd3ceeee81f77250526b91e093614f',
filePath: 'blob',
},
{
name: 'data',
chainId: '0x1',
version: '1.0.3',
checksum:
'409a7f83ac6b31dc8c77e3ec18038f209bd2f545e0f4177c2e2381aa4e067b49',
signature:
'0x304402206d433e9172960de6717d94ae263e47eefacd3584a3274a452f8f9567b3a797db02201b2e423188fb3f9daa6ce6a8723f69df26bd3ceeee81f77250526b91e093614f',
filePath: 'data',
},
];
export const VERSION_INFO: (FileMetadata & {
signature: string;
filePath: string;
})[] = [];

SUPPORTED_CHAIN_IDS.forEach((chainId) => {
VERSION_INFO.push(
{
name: `${chainId}_blob`,
chainId,
version: '1.0.0',
checksum:
'409a7f83ac6b31dc8c77e3ec18038f209bd2f545e0f4177c2e2381aa4e067b49',
signature:
'0x304402206d433e9172960de6717d94ae263e47eefacd3584a3274a452f8f9567b3a797db02201b2e423188fb3f9daa6ce6a8723f69df26bd3ceeee81f77250526b91e093614f',
filePath: `${chainId}_blob`,
},
{
name: `${chainId}_blob`,
chainId,
version: '1.0.3',
checksum:
'409a7f83ac6b31dc8c77e3ec18038f209bd2f545e0f4177c2e2381aa4e067b49',
signature:
'0x304402206d433e9172960de6717d94ae263e47eefacd3584a3274a452f8f9567b3a797db02201b2e423188fb3f9daa6ce6a8723f69df26bd3ceeee81f77250526b91e093614f',
filePath: `${chainId}_data`,
},
);
});

const PPOM_VERSION_PATH = 'https://ppom_cdn_base_url/ppom_version.json';

Expand Down