[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:
Adam R 2020-10-20 00:51:47 +02:00 committed by GitHub
parent fca4ecb41e
commit 3429636c87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 64 deletions

View File

@ -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"
}
]
}
}

View File

@ -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, ''];
}

View 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;
}
}

View File

@ -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, []];
}

View File

@ -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 => {

View File

@ -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);
}
}

View File

@ -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}`;

View File

@ -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(),