[Internal] Info type files: accept both casing, in fix make it uppercase (#5762)

* Info type files: accept both casing, in fix make it uppercase.

* Minor, to re-trigger CI

Co-authored-by: Catenocrypt <catenocrypt@users.noreply.github.com>
This commit is contained in:
Adam R 2021-03-01 15:46:10 +01:00 committed by GitHub
parent f615b17656
commit 76ccac3437
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 23 deletions

View File

@ -4,12 +4,9 @@ import {
getChainAssetsPath,
getChainAssetInfoPath
} from "./repo-structure";
import {
readFileSync,
isPathExistsSync
} from "./filesystem";
import { isPathExistsSync } from "./filesystem";
import { arrayDiff } from "./types";
import { isValidJSON } from "../generic/json";
import { isValidJSON, readJsonFile, writeJsonFile } from "../generic/json";
import { ActionInterface, CheckStepInterface } from "../generic/interface";
import { CoinType } from "@trustwallet/wallet-core";
import * as bluebird from "bluebird";
@ -24,7 +21,9 @@ function isAssetInfoHasAllKeys(info: unknown, path: string): [boolean, string] {
return [hasAllKeys, `Info at path '${path}' missing next key(s): ${arrayDiff(requiredKeys, infoKeys)}`];
}
function isAssetInfoValid(info: unknown, path: string, address: string, chain: string): [string, string] {
// return error, warning, and fixed into if applicable
function isAssetInfoValid(info: unknown, path: string, address: string, chain: string, checkOnly: boolean): [string, string, unknown?] {
let fixedInfo: unknown|null = null;
const isKeys1CorrectType =
typeof info['name'] === "string" && info['name'] !== "" &&
typeof info['type'] === "string" && info['type'] !== "" &&
@ -33,15 +32,24 @@ function isAssetInfoValid(info: unknown, path: string, address: string, chain: s
typeof info['status'] === "string" && info['status'] !== ""
;
if (!isKeys1CorrectType) {
return [`Check keys1 '${info['name']}' '${info['type']}' '${info['symbol']}' '${info['decimals']}' '${info['id']}' ${path}`, ""];
return [`Check keys1 '${info['name']}' '${info['type']}' '${info['symbol']}' '${info['decimals']}' '${info['id']}' ${path}`, "", fixedInfo];
}
if (typeof info['type'] !== "string" || chainFromAssetType(info['type']) !== chain ) {
return [`Incorrect type '${info['type']}' '${chain}' '${path}`, ""];
// type
if (typeof info['type'] !== "string") {
return [`Incorrect type for type '${info['type']}' '${chain}' '${path}`, "", fixedInfo];
}
if (typeof info['id'] !== "string" || info['id'] !== address ) {
return [`Incorrect id '${info['id']}' '${path}`, ""];
if (chainFromAssetType(info['type'].toUpperCase()) !== chain ) {
return [`Incorrect value for type '${info['type']}' '${chain}' '${path}`, "", fixedInfo];
}
if (info['type'] !== info['type'].toUpperCase()) {
// type is correct value, but casing is wrong, fix
if (checkOnly) {
return ["", `Wrong casing for type '${info['type']}' '${chain}' '${path}`, fixedInfo];
}
// fix
if (!fixedInfo) { fixedInfo = info; }
fixedInfo['type'] = info['type'].toUpperCase();
}
const isKeys2CorrectType =
@ -50,19 +58,19 @@ function isAssetInfoValid(info: unknown, path: string, address: string, chain: s
typeof info['website'] === "string" && (info['description'] === "-" || info['website'] !== "") &&
typeof info['explorer'] === "string" && info['explorer'] != "";
if (!isKeys2CorrectType) {
return [`Check keys2 '${info['description']}' '${info['website']}' '${info['explorer']}' ${path}`, ""];
return [`Check keys2 '${info['description']}' '${info['website']}' '${info['explorer']}' ${path}`, "", fixedInfo];
}
if (info['description'].length > 500) {
const msg = `Description too long, ${info['description'].length}, ${path}`;
return ["", msg];
return [msg, "", fixedInfo];
}
return ["", ""];
return ["", "", fixedInfo];
}
export function chainFromAssetType(type: string): string {
switch (type.toUpperCase()) {
switch (type) {
case "ERC20": return "ethereum";
case "BEP2": return "binance";
case "BEP20": return "smartchain";
@ -80,6 +88,7 @@ export function chainFromAssetType(type: string): string {
case "NRC20": return "nuls";
case "VET": return "vechain";
case "ONTOLOGY": return "ontology";
default: return "";
}
}
@ -153,7 +162,8 @@ function explorerUrlAlternatives(chain: string, contract: string, name: string):
return altUrls;
}
function isAssetInfoOK(chain: string, address: string, errors: string[], warnings: string[]): void {
// Check the an assets's info.json; for errors/warning. Also does fixes in certain cases
function isAssetInfoOK(chain: string, address: string, errors: string[], warnings: string[], checkOnly: boolean): void {
const assetInfoPath = getChainAssetInfoPath(chain, address);
if (!isPathExistsSync(assetInfoPath)) {
// Info file doesn't exist, no need to check
@ -166,20 +176,26 @@ function isAssetInfoOK(chain: string, address: string, errors: string[], warning
return;
}
const info = JSON.parse(readFileSync(assetInfoPath));
let info: unknown = readJsonFile(assetInfoPath);
let fixedInfo: unknown|null = null;
const [hasAllKeys, msg1] = isAssetInfoHasAllKeys(info, assetInfoPath);
if (!hasAllKeys) {
console.log(msg1);
errors.push(msg1);
}
const [err2, warn2] = isAssetInfoValid(info, assetInfoPath, address, chain);
const [err2, warn2, fixedInfo2] = isAssetInfoValid(info, assetInfoPath, address, chain, checkOnly);
if (err2) {
errors.push(err2);
}
if (warn2) {
warnings.push(warn2);
}
if (fixedInfo2 && !checkOnly) {
info = fixedInfo2;
fixedInfo = fixedInfo2;
}
const hasExplorer = Object.prototype.hasOwnProperty.call(info, 'explorer');
if (!hasExplorer) {
@ -205,6 +221,11 @@ function isAssetInfoOK(chain: string, address: string, errors: string[], warning
}
}
}
if (fixedInfo && !checkOnly) {
writeJsonFile(assetInfoPath, fixedInfo);
console.log(`Done fixes to info.json, ${assetInfoPath}`);
}
}
export class AssetInfos implements ActionInterface {
@ -224,7 +245,7 @@ export class AssetInfos implements ActionInterface {
const assetsList = getChainAssetsList(chain);
//console.log(` Found ${assetsList.length} assets for chain ${chain}`);
await bluebird.each(assetsList, async (address) => {
isAssetInfoOK(chain, address, errors, warnings);
isAssetInfoOK(chain, address, errors, warnings, true);
});
return [errors, warnings];
}
@ -234,4 +255,18 @@ export class AssetInfos implements ActionInterface {
});
return steps;
}
async consistencyFix(): Promise<void> {
bluebird.each(allChains, async chain => {
// only if there is no assets subfolder
if (isPathExistsSync(getChainAssetsPath(chain))) {
const errors: string[] = [];
const warnings: string[] = [];
const assetsList = getChainAssetsList(chain);
await bluebird.each(assetsList, async (address) => {
isAssetInfoOK(chain, address, errors, warnings, false);
});
}
});
}
}

View File

@ -14,8 +14,8 @@ export interface ActionInterface {
getConsistencyChecks?(): CheckStepInterface[];
sanityFix?(): Promise<void>;
consistencyFix?(): Promise<void>;
updateAuto?(): Promise<void>; // For regular automatic updates
updateManual?(): Promise<void>; // For occasional manual updates
updateAuto?(): Promise<void>; // For regular automatic updates (from external source)
updateManual?(): Promise<void>; // For occasional manual updates (from external source)
}
export enum FixCheckMode {

View File

@ -170,7 +170,7 @@ async function consistencyFixByList(actions: ActionInterface[]) {
await bluebird.each(actions, async (action) => {
try {
if (action.consistencyFix) {
console.log(`Sanity fix '${action.getName()}':`);
console.log(`Consistency fix '${action.getName()}':`);
await action.consistencyFix();
}
} catch (error) {