mirror of
				https://github.com/Instadapp/trustwallet-assets.git
				synced 2024-07-29 22:37:31 +00:00 
			
		
		
		
	[internal] Assets checks: Info.json check for every chain (was for eth forks only). (#4524)
* Assets checks: Info.json check for every chain (was for eth forks only). * Rename. * Minor refinement. * Add one missing TRC20 token explorer. * Add check for explorerUrl, incl. content. * Rename tronscan.org to tronscan.io * Revert "Rename tronscan.org to tronscan.io" This reverts commit 4de796d7825a7a04a06204040bed7298418aaf33. * Revert "Add check for explorerUrl, incl. content." This reverts commit fedcb8b3e611234da07241d0d55d198e38a1b1d0. Co-authored-by: Catenocrypt <catenocrypt@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									fca4ecb41e
								
							
						
					
					
						commit
						3429636c87
					
				|  | @ -7,6 +7,7 @@ | |||
|     "white_paper": "https://bridge.link/Bridge_White_Paper.pdf", | ||||
|     "short_description": "First Ever Public Oracle System on TRON Network", | ||||
|     "description": "First Ever Public Oracle System on TRON Network", | ||||
|     "explorer": "https://tronscan.io/#/token20/TJvqNiWUN2v2NBG12UhfV7WSvReJkRP3VC", | ||||
|     "socials": [ | ||||
|       { | ||||
|         "name": "Twitter", | ||||
|  | @ -19,4 +20,4 @@ | |||
|         "handle": "Bridge Oracle" | ||||
|       } | ||||
|     ] | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -1,45 +0,0 @@ | |||
| import { getChainAssetInfoPath } from "./repo-structure"; | ||||
| import { readFileSync, isPathExistsSync } from "./filesystem"; | ||||
| import { arrayDiff } from "./types"; | ||||
| import { isValidJSON } from "../generic/json"; | ||||
| 
 | ||||
| const requiredKeys = ["explorer", "name", "website", "short_description"]; | ||||
| 
 | ||||
| function isAssetInfoHasAllKeys(path: string): [boolean, string] { | ||||
|     const info = JSON.parse(readFileSync(path)); | ||||
|     const infoKeys = Object.keys(info); | ||||
| 
 | ||||
|     const hasAllKeys = requiredKeys.every(k => Object.prototype.hasOwnProperty.call(info, k)); | ||||
| 
 | ||||
|     if (!hasAllKeys) { | ||||
|         return [false, `Info at path '${path}' missing next key(s): ${arrayDiff(requiredKeys, infoKeys)}`]; | ||||
|     } | ||||
| 
 | ||||
|     const isKeysCorrentType =  | ||||
|         typeof info.explorer === "string" && info.explorer != "" | ||||
|         && typeof info.name === "string" && info.name != "" | ||||
|         && typeof info.website === "string" | ||||
|         && typeof info.short_description === "string"; | ||||
|      | ||||
|     return [isKeysCorrentType, `Check keys '${requiredKeys}' vs. '${infoKeys}'`]; | ||||
| } | ||||
| 
 | ||||
| export function isAssetInfoOK(chain: string, address: string): [boolean, string] { | ||||
|     const assetInfoPath = getChainAssetInfoPath(chain, address); | ||||
|     if (!isPathExistsSync(assetInfoPath)) { | ||||
|         return [true, `Info file doesn't exist, no need to check`] | ||||
|     } | ||||
| 
 | ||||
|     if (!isValidJSON(assetInfoPath)) { | ||||
|         console.log(`JSON at path: '${assetInfoPath}' is invalid`); | ||||
|         return [false, `JSON at path: '${assetInfoPath}' is invalid`]; | ||||
|     } | ||||
| 
 | ||||
|     const [hasAllKeys, msg] = isAssetInfoHasAllKeys(assetInfoPath); | ||||
|     if (!hasAllKeys) { | ||||
|         console.log(msg); | ||||
|         return [false, msg]; | ||||
|     } | ||||
| 
 | ||||
|     return [true, '']; | ||||
| } | ||||
							
								
								
									
										86
									
								
								script/generic/asset-infos.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								script/generic/asset-infos.ts
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | |||
| import { | ||||
|     allChains, | ||||
|     getChainAssetsList, | ||||
|     getChainAssetsPath, | ||||
|     getChainAssetInfoPath | ||||
| } from "./repo-structure"; | ||||
| import { | ||||
|     readFileSync, | ||||
|     isPathExistsSync | ||||
| } from "./filesystem"; | ||||
| import { arrayDiff } from "./types"; | ||||
| import { isValidJSON } from "../generic/json"; | ||||
| import { ActionInterface, CheckStepInterface } from "../generic/interface"; | ||||
| import * as bluebird from "bluebird"; | ||||
| 
 | ||||
| const requiredKeys = ["explorer", "name", "website", "short_description"]; | ||||
| 
 | ||||
| function isAssetInfoHasAllKeys(path: string): [boolean, string] { | ||||
|     const info = JSON.parse(readFileSync(path)); | ||||
|     const infoKeys = Object.keys(info); | ||||
| 
 | ||||
|     const hasAllKeys = requiredKeys.every(k => Object.prototype.hasOwnProperty.call(info, k)); | ||||
| 
 | ||||
|     if (!hasAllKeys) { | ||||
|         return [false, `Info at path '${path}' missing next key(s): ${arrayDiff(requiredKeys, infoKeys)}`]; | ||||
|     } | ||||
| 
 | ||||
|     const isKeysCorrentType =  | ||||
|         typeof info.explorer === "string" && info.explorer != "" | ||||
|         && typeof info.name === "string" && info.name != "" | ||||
|         && typeof info.website === "string" | ||||
|         && typeof info.short_description === "string"; | ||||
|      | ||||
|     return [isKeysCorrentType, `Check keys '${requiredKeys}' vs. '${infoKeys}'`]; | ||||
| } | ||||
| 
 | ||||
| function isAssetInfoOK(chain: string, address: string): [boolean, string] { | ||||
|     const assetInfoPath = getChainAssetInfoPath(chain, address); | ||||
|     if (!isPathExistsSync(assetInfoPath)) { | ||||
|         return [true, `Info file doesn't exist, no need to check`] | ||||
|     } | ||||
| 
 | ||||
|     if (!isValidJSON(assetInfoPath)) { | ||||
|         console.log(`JSON at path: '${assetInfoPath}' is invalid`); | ||||
|         return [false, `JSON at path: '${assetInfoPath}' is invalid`]; | ||||
|     } | ||||
| 
 | ||||
|     const [hasAllKeys, msg] = isAssetInfoHasAllKeys(assetInfoPath); | ||||
|     if (!hasAllKeys) { | ||||
|         console.log(msg); | ||||
|         return [false, msg]; | ||||
|     } | ||||
| 
 | ||||
|     return [true, '']; | ||||
| } | ||||
| 
 | ||||
| export class AssetInfos implements ActionInterface { | ||||
|     getName(): string { return "Asset Infos"; } | ||||
|      | ||||
|     getSanityChecks(): CheckStepInterface[] { | ||||
|         const steps: CheckStepInterface[] = []; | ||||
|         allChains.forEach(chain => { | ||||
|             // only if there is no assets subfolder
 | ||||
|             if (isPathExistsSync(getChainAssetsPath(chain))) { | ||||
|                 steps.push( | ||||
|                     { | ||||
|                         getName: () => { return `Info.json's for chain ${chain}`;}, | ||||
|                         check: async () => { | ||||
|                             const errors: string[] = []; | ||||
|                             const assetsList = getChainAssetsList(chain); | ||||
|                             //console.log(`     Found ${assetsList.length} assets for chain ${chain}`);
 | ||||
|                             await bluebird.each(assetsList, async (address) => { | ||||
|                                 const [isInfoOK, infoMsg] = isAssetInfoOK(chain, address); | ||||
|                                 if (!isInfoOK) { | ||||
|                                     errors.push(infoMsg); | ||||
|                                 } | ||||
|                             }); | ||||
|                             return [errors, []]; | ||||
|                         }     | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         }); | ||||
|         return steps; | ||||
|     } | ||||
| } | ||||
|  | @ -21,7 +21,6 @@ import { | |||
| } from "../generic/filesystem"; | ||||
| import { toChecksum } from "../generic/eth-address"; | ||||
| import { ActionInterface, CheckStepInterface } from "../generic/interface"; | ||||
| import { isAssetInfoOK } from "../generic/asset-info"; | ||||
| import * as bluebird from "bluebird"; | ||||
| 
 | ||||
| async function formatInfos() { | ||||
|  | @ -92,10 +91,6 @@ export class EthForks implements ActionInterface { | |||
|                             if (!isPathExistsSync(assetLogoPath)) { | ||||
|                                 errors.push(`Missing file at path '${assetLogoPath}'`); | ||||
|                             } | ||||
|                             const [isInfoOK, infoMsg] = isAssetInfoOK(chain, address); | ||||
|                             if (!isInfoOK) { | ||||
|                                 errors.push(infoMsg); | ||||
|                             } | ||||
|                         }); | ||||
|                         return [errors, []]; | ||||
|                     }     | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import { | |||
| } from "../generic/filesystem"; | ||||
| import { CheckStepInterface, ActionInterface } from "../generic/interface"; | ||||
| import { | ||||
|     chainsPath, | ||||
|     allChains, | ||||
|     getChainLogoPath, | ||||
|     getChainAssetsPath, | ||||
|     getChainAssetPath, | ||||
|  | @ -18,8 +18,6 @@ import { isLogoOK } from "../generic/image"; | |||
| import { isLowerCase } from "../generic/types"; | ||||
| import * as bluebird from "bluebird"; | ||||
| 
 | ||||
| const foundChains = readDirSync(chainsPath) | ||||
| 
 | ||||
| export class FoldersFiles implements ActionInterface { | ||||
|     getName(): string { return "Folders and Files"; } | ||||
|      | ||||
|  | @ -42,7 +40,7 @@ export class FoldersFiles implements ActionInterface { | |||
|                 getName: () => { return "Chain folders are lowercase, contain only predefined list of files"}, | ||||
|                 check: async () => { | ||||
|                     const errors: string[] = []; | ||||
|                     foundChains.forEach(chain => { | ||||
|                     allChains.forEach(chain => { | ||||
|                         if (!isLowerCase(chain)) { | ||||
|                             errors.push(`Chain folder must be in lowercase "${chain}"`); | ||||
|                         } | ||||
|  | @ -59,7 +57,7 @@ export class FoldersFiles implements ActionInterface { | |||
|                 getName: () => { return "Chain folders have logo, and correct size"}, | ||||
|                 check: async () => { | ||||
|                     const errors: string[] = []; | ||||
|                     await bluebird.each(foundChains, async (chain) => { | ||||
|                     await bluebird.each(allChains, async (chain) => { | ||||
|                         const chainLogoPath = getChainLogoPath(chain); | ||||
|                         if (!isPathExistsSync(chainLogoPath)) { | ||||
|                             errors.push(`File missing at path "${chainLogoPath}"`); | ||||
|  | @ -76,7 +74,7 @@ export class FoldersFiles implements ActionInterface { | |||
|                 getName: () => { return "Asset folders contain logo"}, | ||||
|                 check: async () => { | ||||
|                     const errors: string[] = []; | ||||
|                     foundChains.forEach(chain => { | ||||
|                     allChains.forEach(chain => { | ||||
|                         const assetsPath = getChainAssetsPath(chain); | ||||
|                         if (isPathExistsSync(assetsPath)) { | ||||
|                             readDirSync(assetsPath).forEach(address => { | ||||
|  | @ -95,7 +93,7 @@ export class FoldersFiles implements ActionInterface { | |||
|                 getName: () => { return "Asset folders contain info.json"}, | ||||
|                 check: async () => { | ||||
|                     const warnings: string[] = []; | ||||
|                     foundChains.forEach(chain => { | ||||
|                     allChains.forEach(chain => { | ||||
|                         const assetsPath = getChainAssetsPath(chain); | ||||
|                         if (isPathExistsSync(assetsPath)) { | ||||
|                             readDirSync(assetsPath).forEach(address => { | ||||
|  | @ -114,7 +112,7 @@ export class FoldersFiles implements ActionInterface { | |||
|                 getName: () => { return "Asset folders contain only predefined set of files"}, | ||||
|                 check: async () => { | ||||
|                     const errors: string[] = []; | ||||
|                     foundChains.forEach(chain => { | ||||
|                     allChains.forEach(chain => { | ||||
|                         const assetsPath = getChainAssetsPath(chain); | ||||
|                         if (isPathExistsSync(assetsPath)) { | ||||
|                             readDirSync(assetsPath).forEach(address => { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import * as bluebird from "bluebird"; | ||||
| import { | ||||
|     chainsPath, | ||||
|     allChains, | ||||
|     getChainLogoPath, | ||||
|     getChainAssetsPath, | ||||
|     getChainAssetLogoPath, | ||||
|  | @ -80,8 +80,7 @@ export class LogoSize implements ActionInterface { | |||
|             { | ||||
|                 getName: () => { return "Check that logos are not too large"}, | ||||
|                 check: async () => { | ||||
|                     const foundChains = readDirSync(chainsPath); | ||||
|                     const largePaths = await checkDownsize(foundChains, true); | ||||
|                     const largePaths = await checkDownsize(allChains, true); | ||||
|                     const errors: string[] = largePaths.map(p => `Logo too large: ${p}`); | ||||
|                     return [errors, []]; | ||||
|                 } | ||||
|  | @ -90,7 +89,6 @@ export class LogoSize implements ActionInterface { | |||
|     } | ||||
| 
 | ||||
|     async sanityFix(): Promise<void> { | ||||
|         const foundChains = readDirSync(chainsPath); | ||||
|         await checkDownsize(foundChains, false); | ||||
|         await checkDownsize(allChains, false); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ export const chainFolderAllowedFiles = [ | |||
| ] | ||||
| export const chainsPath: string = path.join(process.cwd(), '/blockchains'); | ||||
| export const getChainPath = (chain: string): string => `${chainsPath}/${chain}`; | ||||
| export const allChains = readDirSync(chainsPath); | ||||
| export const getChainLogoPath = (chain: string): string => `${getChainPath(chain)}/info/${logoFullName}`; | ||||
| export const getChainAssetsPath = (chain: string): string => `${getChainPath(chain)}/assets`; | ||||
| export const getChainAssetPath = (chain: string, asset: string): string => `${getChainAssetsPath(chain)}/${asset}`; | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| import { BinanceAction } from "../blockchain/binance"; | ||||
| import { CosmosAction } from "../blockchain/cosmos"; | ||||
| import { AssetInfos } from "../generic/asset-infos"; | ||||
| import { EthForks } from "../generic/eth-forks"; | ||||
| import { FoldersFiles } from "../generic/folders-and-files"; | ||||
| import { JsonAction } from "../generic/json-format"; | ||||
|  | @ -18,6 +19,7 @@ import * as bluebird from "bluebird"; | |||
| 
 | ||||
| const actionList: ActionInterface[] = [ | ||||
|     new FoldersFiles(), | ||||
|     new AssetInfos(), | ||||
|     new EthForks(), | ||||
|     new LogoSize(), | ||||
|     new Allowlists(), | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Adam R
						Adam R