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