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",
|
"white_paper": "https://bridge.link/Bridge_White_Paper.pdf",
|
||||||
"short_description": "First Ever Public Oracle System on TRON Network",
|
"short_description": "First Ever Public Oracle System on TRON Network",
|
||||||
"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": [
|
"socials": [
|
||||||
{
|
{
|
||||||
"name": "Twitter",
|
"name": "Twitter",
|
||||||
|
@ -19,4 +20,4 @@
|
||||||
"handle": "Bridge Oracle"
|
"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";
|
} from "../generic/filesystem";
|
||||||
import { toChecksum } from "../generic/eth-address";
|
import { toChecksum } from "../generic/eth-address";
|
||||||
import { ActionInterface, CheckStepInterface } from "../generic/interface";
|
import { ActionInterface, CheckStepInterface } from "../generic/interface";
|
||||||
import { isAssetInfoOK } from "../generic/asset-info";
|
|
||||||
import * as bluebird from "bluebird";
|
import * as bluebird from "bluebird";
|
||||||
|
|
||||||
async function formatInfos() {
|
async function formatInfos() {
|
||||||
|
@ -92,10 +91,6 @@ export class EthForks implements ActionInterface {
|
||||||
if (!isPathExistsSync(assetLogoPath)) {
|
if (!isPathExistsSync(assetLogoPath)) {
|
||||||
errors.push(`Missing file at path '${assetLogoPath}'`);
|
errors.push(`Missing file at path '${assetLogoPath}'`);
|
||||||
}
|
}
|
||||||
const [isInfoOK, infoMsg] = isAssetInfoOK(chain, address);
|
|
||||||
if (!isInfoOK) {
|
|
||||||
errors.push(infoMsg);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return [errors, []];
|
return [errors, []];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
} from "../generic/filesystem";
|
} from "../generic/filesystem";
|
||||||
import { CheckStepInterface, ActionInterface } from "../generic/interface";
|
import { CheckStepInterface, ActionInterface } from "../generic/interface";
|
||||||
import {
|
import {
|
||||||
chainsPath,
|
allChains,
|
||||||
getChainLogoPath,
|
getChainLogoPath,
|
||||||
getChainAssetsPath,
|
getChainAssetsPath,
|
||||||
getChainAssetPath,
|
getChainAssetPath,
|
||||||
|
@ -18,8 +18,6 @@ import { isLogoOK } from "../generic/image";
|
||||||
import { isLowerCase } from "../generic/types";
|
import { isLowerCase } from "../generic/types";
|
||||||
import * as bluebird from "bluebird";
|
import * as bluebird from "bluebird";
|
||||||
|
|
||||||
const foundChains = readDirSync(chainsPath)
|
|
||||||
|
|
||||||
export class FoldersFiles implements ActionInterface {
|
export class FoldersFiles implements ActionInterface {
|
||||||
getName(): string { return "Folders and Files"; }
|
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"},
|
getName: () => { return "Chain folders are lowercase, contain only predefined list of files"},
|
||||||
check: async () => {
|
check: async () => {
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
foundChains.forEach(chain => {
|
allChains.forEach(chain => {
|
||||||
if (!isLowerCase(chain)) {
|
if (!isLowerCase(chain)) {
|
||||||
errors.push(`Chain folder must be in lowercase "${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"},
|
getName: () => { return "Chain folders have logo, and correct size"},
|
||||||
check: async () => {
|
check: async () => {
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
await bluebird.each(foundChains, async (chain) => {
|
await bluebird.each(allChains, async (chain) => {
|
||||||
const chainLogoPath = getChainLogoPath(chain);
|
const chainLogoPath = getChainLogoPath(chain);
|
||||||
if (!isPathExistsSync(chainLogoPath)) {
|
if (!isPathExistsSync(chainLogoPath)) {
|
||||||
errors.push(`File missing at path "${chainLogoPath}"`);
|
errors.push(`File missing at path "${chainLogoPath}"`);
|
||||||
|
@ -76,7 +74,7 @@ export class FoldersFiles implements ActionInterface {
|
||||||
getName: () => { return "Asset folders contain logo"},
|
getName: () => { return "Asset folders contain logo"},
|
||||||
check: async () => {
|
check: async () => {
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
foundChains.forEach(chain => {
|
allChains.forEach(chain => {
|
||||||
const assetsPath = getChainAssetsPath(chain);
|
const assetsPath = getChainAssetsPath(chain);
|
||||||
if (isPathExistsSync(assetsPath)) {
|
if (isPathExistsSync(assetsPath)) {
|
||||||
readDirSync(assetsPath).forEach(address => {
|
readDirSync(assetsPath).forEach(address => {
|
||||||
|
@ -95,7 +93,7 @@ export class FoldersFiles implements ActionInterface {
|
||||||
getName: () => { return "Asset folders contain info.json"},
|
getName: () => { return "Asset folders contain info.json"},
|
||||||
check: async () => {
|
check: async () => {
|
||||||
const warnings: string[] = [];
|
const warnings: string[] = [];
|
||||||
foundChains.forEach(chain => {
|
allChains.forEach(chain => {
|
||||||
const assetsPath = getChainAssetsPath(chain);
|
const assetsPath = getChainAssetsPath(chain);
|
||||||
if (isPathExistsSync(assetsPath)) {
|
if (isPathExistsSync(assetsPath)) {
|
||||||
readDirSync(assetsPath).forEach(address => {
|
readDirSync(assetsPath).forEach(address => {
|
||||||
|
@ -114,7 +112,7 @@ export class FoldersFiles implements ActionInterface {
|
||||||
getName: () => { return "Asset folders contain only predefined set of files"},
|
getName: () => { return "Asset folders contain only predefined set of files"},
|
||||||
check: async () => {
|
check: async () => {
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
foundChains.forEach(chain => {
|
allChains.forEach(chain => {
|
||||||
const assetsPath = getChainAssetsPath(chain);
|
const assetsPath = getChainAssetsPath(chain);
|
||||||
if (isPathExistsSync(assetsPath)) {
|
if (isPathExistsSync(assetsPath)) {
|
||||||
readDirSync(assetsPath).forEach(address => {
|
readDirSync(assetsPath).forEach(address => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as bluebird from "bluebird";
|
import * as bluebird from "bluebird";
|
||||||
import {
|
import {
|
||||||
chainsPath,
|
allChains,
|
||||||
getChainLogoPath,
|
getChainLogoPath,
|
||||||
getChainAssetsPath,
|
getChainAssetsPath,
|
||||||
getChainAssetLogoPath,
|
getChainAssetLogoPath,
|
||||||
|
@ -80,8 +80,7 @@ export class LogoSize implements ActionInterface {
|
||||||
{
|
{
|
||||||
getName: () => { return "Check that logos are not too large"},
|
getName: () => { return "Check that logos are not too large"},
|
||||||
check: async () => {
|
check: async () => {
|
||||||
const foundChains = readDirSync(chainsPath);
|
const largePaths = await checkDownsize(allChains, true);
|
||||||
const largePaths = await checkDownsize(foundChains, true);
|
|
||||||
const errors: string[] = largePaths.map(p => `Logo too large: ${p}`);
|
const errors: string[] = largePaths.map(p => `Logo too large: ${p}`);
|
||||||
return [errors, []];
|
return [errors, []];
|
||||||
}
|
}
|
||||||
|
@ -90,7 +89,6 @@ export class LogoSize implements ActionInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
async sanityFix(): Promise<void> {
|
async sanityFix(): Promise<void> {
|
||||||
const foundChains = readDirSync(chainsPath);
|
await checkDownsize(allChains, false);
|
||||||
await checkDownsize(foundChains, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ export const chainFolderAllowedFiles = [
|
||||||
]
|
]
|
||||||
export const chainsPath: string = path.join(process.cwd(), '/blockchains');
|
export const chainsPath: string = path.join(process.cwd(), '/blockchains');
|
||||||
export const getChainPath = (chain: string): string => `${chainsPath}/${chain}`;
|
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 getChainLogoPath = (chain: string): string => `${getChainPath(chain)}/info/${logoFullName}`;
|
||||||
export const getChainAssetsPath = (chain: string): string => `${getChainPath(chain)}/assets`;
|
export const getChainAssetsPath = (chain: string): string => `${getChainPath(chain)}/assets`;
|
||||||
export const getChainAssetPath = (chain: string, asset: string): string => `${getChainAssetsPath(chain)}/${asset}`;
|
export const getChainAssetPath = (chain: string, asset: string): string => `${getChainAssetsPath(chain)}/${asset}`;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { BinanceAction } from "../blockchain/binance";
|
import { BinanceAction } from "../blockchain/binance";
|
||||||
import { CosmosAction } from "../blockchain/cosmos";
|
import { CosmosAction } from "../blockchain/cosmos";
|
||||||
|
import { AssetInfos } from "../generic/asset-infos";
|
||||||
import { EthForks } from "../generic/eth-forks";
|
import { EthForks } from "../generic/eth-forks";
|
||||||
import { FoldersFiles } from "../generic/folders-and-files";
|
import { FoldersFiles } from "../generic/folders-and-files";
|
||||||
import { JsonAction } from "../generic/json-format";
|
import { JsonAction } from "../generic/json-format";
|
||||||
|
@ -18,6 +19,7 @@ import * as bluebird from "bluebird";
|
||||||
|
|
||||||
const actionList: ActionInterface[] = [
|
const actionList: ActionInterface[] = [
|
||||||
new FoldersFiles(),
|
new FoldersFiles(),
|
||||||
|
new AssetInfos(),
|
||||||
new EthForks(),
|
new EthForks(),
|
||||||
new LogoSize(),
|
new LogoSize(),
|
||||||
new Allowlists(),
|
new Allowlists(),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user