[internal] Set up Linting (#4040)

* Add ESLint infrastructure.

* Lint auto fixes.

* Lint fixes.

* Lint fixes.

* Add Lint to CI builds.

Co-authored-by: Catenocrypt <catenocrypt@users.noreply.github.com>
This commit is contained in:
Adam R 2020-09-18 16:39:31 +02:00 committed by GitHub
parent e0fc1a1ded
commit 68e0cc6d90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 1010 additions and 140 deletions

9
.eslintignore Normal file
View File

@ -0,0 +1,9 @@
# don't ever lint node_modules
node_modules
# don't lint build output (make sure it's set to your correct build folder name)
dist
# don't lint nyc coverage output
coverage
.eslintrc.js
jest.config.js

12
.eslintrc.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
};

View File

@ -17,3 +17,5 @@ jobs:
run: npm run check run: npm run check
- name: Run test - name: Run test
run: npm t run: npm t
- name: Run lint
run: npm run lint

View File

@ -20,3 +20,5 @@ jobs:
run: npm run check-sanity run: npm run check-sanity
- name: Run test - name: Run test
run: npm t run: npm t
- name: Run lint
run: npm run lint

View File

@ -4,7 +4,7 @@ import { sanityCheckAll } from "./script/action/update-all";
sanityCheckAll().then(([errors, warnings]) => { sanityCheckAll().then(([errors, warnings]) => {
errors.forEach(err => fail(err)); errors.forEach(err => fail(err));
warnings.forEach(err => warn(err)); warnings.forEach(err => warn(err));
if (errors.length > 0 || warnings.length > 0 { if (errors.length > 0 || warnings.length > 0) {
markdown("Please fix the errors/warnings above. Files can be replaced/renamed in this pull request (using command-line, or GitHub Desktop). Alternatively, you may close this pull request and open a new one."); markdown("Please fix the errors/warnings above. Files can be replaced/renamed in this pull request (using command-line, or GitHub Desktop). Alternatively, you may close this pull request and open a new one.");
} }
}); });

861
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,8 @@
"check-sanity": "ts-node ./script/main/check-sanity", "check-sanity": "ts-node ./script/main/check-sanity",
"fix": "ts-node ./script/main/fix", "fix": "ts-node ./script/main/fix",
"fix-sanity": "ts-node ./script/main/fix-sanity", "fix-sanity": "ts-node ./script/main/fix-sanity",
"update": "ts-node ./script/main/update" "update": "ts-node ./script/main/update",
"lint": "npx eslint . --ext .js,.jsx,.ts,.tsx"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -35,11 +36,14 @@
"@types/jest": "^25.2.3", "@types/jest": "^25.2.3",
"@types/jest-expect-message": "^1.0.2", "@types/jest-expect-message": "^1.0.2",
"@types/node": "^13.13.17", "@types/node": "^13.13.17",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"axios": "^0.19.2", "axios": "^0.19.2",
"bip44-constants": "^8.0.49", "bip44-constants": "^8.0.49",
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"danger": "^10.4.0", "danger": "^10.4.0",
"eslint": "^7.9.0",
"ethereum-checksum-address": "0.0.6", "ethereum-checksum-address": "0.0.6",
"eztz-lib": "^0.1.2", "eztz-lib": "^0.1.2",
"image-size": "^0.8.3", "image-size": "^0.8.3",

View File

@ -14,11 +14,10 @@ import {
import { ActionInterface, CheckStepInterface } from "./interface"; import { ActionInterface, CheckStepInterface } from "./interface";
import { formatSortJson } from "../common/json"; import { formatSortJson } from "../common/json";
import * as bluebird from "bluebird"; import * as bluebird from "bluebird";
import { copyFile } from "fs";
async function checkUpdateAllowDenyList(chain: string, checkOnly: boolean ): Promise<[boolean, string[], string[]]> { async function checkUpdateAllowDenyList(chain: string, checkOnly: boolean ): Promise<[boolean, string[], string[]]> {
let errorMsgs: string[] = []; const errorMsgs: string[] = [];
let warningMsgs: string[] = []; const warningMsgs: string[] = [];
const assets = getChainAssetsList(chain); const assets = getChainAssetsList(chain);
const allowlistPath = getChainAllowlistPath(chain); const allowlistPath = getChainAllowlistPath(chain);

View File

@ -8,26 +8,27 @@ import { ActionInterface, CheckStepInterface } from "./interface";
import { getChainAssetsPath } from "../common/repo-structure"; import { getChainAssetsPath } from "../common/repo-structure";
import { Binance } from "../common/blockchains"; import { Binance } from "../common/blockchains";
import { readDirSync } from "../common/filesystem"; import { readDirSync } from "../common/filesystem";
import { readJsonFile } from "../common/json";
import { import {
getChainAssetLogoPath, getChainAssetLogoPath,
getChainDenylistPath getChainDenylistPath
} from "../common/repo-structure"; } from "../common/repo-structure";
const binanceChain = "binance" const binanceChain = "binance";
const binanceUrlTokens2 = config.binanceUrlTokens2; const binanceUrlTokens2 = config.binanceUrlTokens2;
const binanceUrlTokens8 = config.binanceUrlTokens8; const binanceUrlTokens8 = config.binanceUrlTokens8;
const binanceUrlTokenAssets = config.binanceUrlTokenAssets; const binanceUrlTokenAssets = config.binanceUrlTokenAssets;
var cachedAssets = []; let cachedAssets = [];
async function retrieveBep2AssetList(): Promise<any[]> { async function retrieveBep2AssetList(): Promise<unknown[]> {
console.log(` Retrieving token asset infos from: ${binanceUrlTokenAssets}`); console.log(` Retrieving token asset infos from: ${binanceUrlTokenAssets}`);
const { assetInfoList } = await axios.get(binanceUrlTokenAssets).then(r => r.data); const { assetInfoList } = await axios.get(binanceUrlTokenAssets).then(r => r.data);
console.log(` Retrieved ${assetInfoList.length} token asset infos`); console.log(` Retrieved ${assetInfoList.length} token asset infos`);
return assetInfoList return assetInfoList
} }
async function retrieveAssets(): Promise<any[]> { async function retrieveAssets(): Promise<unknown[]> {
// cache results because of rate limit, used more than once // cache results because of rate limit, used more than once
if (cachedAssets.length == 0) { if (cachedAssets.length == 0) {
console.log(` Retrieving token infos (${binanceUrlTokens2}, ${binanceUrlTokens8})`); console.log(` Retrieving token infos (${binanceUrlTokens2}, ${binanceUrlTokens8})`);
@ -54,8 +55,8 @@ function fetchImage(url) {
} }
/// Return: array with images to fetch; {asset, assetImg} /// Return: array with images to fetch; {asset, assetImg}
export function findImagesToFetch(assetInfoList: any, denylist: string[]): any[] { export function findImagesToFetch(assetInfoList: unknown[], denylist: string[]): unknown[] {
let toFetch: any[] = []; const toFetch: unknown[] = [];
console.log(`Checking for asset images to be fetched`); console.log(`Checking for asset images to be fetched`);
assetInfoList.forEach(({asset, assetImg}) => { assetInfoList.forEach(({asset, assetImg}) => {
process.stdout.write(`.${asset} `); process.stdout.write(`.${asset} `);
@ -78,9 +79,9 @@ export function findImagesToFetch(assetInfoList: any, denylist: string[]): any[]
} }
async function fetchMissingImages(toFetch: any[]): Promise<string[]> { async function fetchMissingImages(toFetch: unknown[]): Promise<string[]> {
console.log(`Attempting to fetch ${toFetch.length} asset image(s)`); console.log(`Attempting to fetch ${toFetch.length} asset image(s)`);
let fetchedAssets: string[] = []; const fetchedAssets: string[] = [];
await bluebird.each(toFetch, async ({ asset, assetImg }) => { await bluebird.each(toFetch, async ({ asset, assetImg }) => {
if (assetImg) { if (assetImg) {
const imagePath = getChainAssetLogoPath(binanceChain, asset); const imagePath = getChainAssetLogoPath(binanceChain, asset);
@ -106,7 +107,7 @@ export class BinanceAction implements ActionInterface {
{ {
getName: () => { return "Binance chain; assets must exist on chain"}, getName: () => { return "Binance chain; assets must exist on chain"},
check: async () => { check: async () => {
var errors = []; const errors = [];
const tokenSymbols = await retrieveAssetSymbols(); const tokenSymbols = await retrieveAssetSymbols();
const assets = readDirSync(getChainAssetsPath(Binance)); const assets = readDirSync(getChainAssetsPath(Binance));
assets.forEach(asset => { assets.forEach(asset => {
@ -130,7 +131,7 @@ export class BinanceAction implements ActionInterface {
async update(): Promise<void> { async update(): Promise<void> {
// retrieve missing token images; BEP2 (bep8 not supported) // retrieve missing token images; BEP2 (bep8 not supported)
const bep2InfoList = await retrieveBep2AssetList(); const bep2InfoList = await retrieveBep2AssetList();
const denylist: string[] = require(getChainDenylistPath(binanceChain)); const denylist: string[] = readJsonFile(getChainDenylistPath(binanceChain)) as string[];
const toFetch = findImagesToFetch(bep2InfoList, denylist); const toFetch = findImagesToFetch(bep2InfoList, denylist);
const fetchedAssets = await fetchMissingImages(toFetch); const fetchedAssets = await fetchMissingImages(toFetch);

View File

@ -11,7 +11,7 @@ export class CosmosAction implements ActionInterface {
{ {
getName: () => { return "Cosmos validator assets must have correct format"}, getName: () => { return "Cosmos validator assets must have correct format"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const assets = getChainValidatorsAssets(Cosmos); const assets = getChainValidatorsAssets(Cosmos);
const prefix = "cosmosvaloper1"; const prefix = "cosmosvaloper1";
const expLength = 52; const expLength = 52;

View File

@ -27,12 +27,12 @@ import * as bluebird from "bluebird";
async function formatInfos() { async function formatInfos() {
console.log(`Formatting info files...`); console.log(`Formatting info files...`);
await bluebird.each(ethForkChains, async (chain) => { await bluebird.each(ethForkChains, async (chain) => {
let count: number = 0; let count = 0;
const chainAssets = getChainAssetsList(chain); const chainAssets = getChainAssetsList(chain);
await bluebird.each(chainAssets, async (address) => { await bluebird.each(chainAssets, async (address) => {
if (isChainAssetInfoExistSync(chain, address)) { if (isChainAssetInfoExistSync(chain, address)) {
const chainAssetInfoPath = getChainAssetInfoPath(chain, address); const chainAssetInfoPath = getChainAssetInfoPath(chain, address);
formatJsonFile(chainAssetInfoPath, true); formatJsonFile(chainAssetInfoPath);
++count; ++count;
} }
}) })
@ -69,13 +69,13 @@ export class EthForks implements ActionInterface {
getName(): string { return "Ethereum forks"; } getName(): string { return "Ethereum forks"; }
getSanityChecks(): CheckStepInterface[] { getSanityChecks(): CheckStepInterface[] {
var steps: CheckStepInterface[] = []; const steps: CheckStepInterface[] = [];
ethForkChains.forEach(chain => { ethForkChains.forEach(chain => {
steps.push( steps.push(
{ {
getName: () => { return `Folder structure for chain ${chain} (ethereum fork)`;}, getName: () => { return `Folder structure for chain ${chain} (ethereum fork)`;},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const assetsFolder = getChainAssetsPath(chain); const assetsFolder = getChainAssetsPath(chain);
const assetsList = getChainAssetsList(chain); const assetsList = getChainAssetsList(chain);
console.log(` Found ${assetsList.length} assets for chain ${chain}`); console.log(` Found ${assetsList.length} assets for chain ${chain}`);

View File

@ -29,7 +29,7 @@ export class FoldersFiles implements ActionInterface {
{ {
getName: () => { return "Repository root dir"}, getName: () => { return "Repository root dir"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const dirActualFiles = readDirSync("."); const dirActualFiles = readDirSync(".");
dirActualFiles.forEach(file => { dirActualFiles.forEach(file => {
if (!(rootDirAllowedFiles.indexOf(file) >= 0)) { if (!(rootDirAllowedFiles.indexOf(file) >= 0)) {
@ -42,7 +42,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 () => {
var errors: string[] = []; const errors: string[] = [];
foundChains.forEach(chain => { foundChains.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 +59,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 () => {
var errors: string[] = []; const errors: string[] = [];
await bluebird.each(foundChains, async (chain) => { await bluebird.each(foundChains, async (chain) => {
const chainLogoPath = getChainLogoPath(chain); const chainLogoPath = getChainLogoPath(chain);
if (!isPathExistsSync(chainLogoPath)) { if (!isPathExistsSync(chainLogoPath)) {
@ -76,7 +76,7 @@ export class FoldersFiles implements ActionInterface {
{ {
getName: () => { return "Asset folders contain logo"}, getName: () => { return "Asset folders contain logo"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
foundChains.forEach(chain => { foundChains.forEach(chain => {
const assetsPath = getChainAssetsPath(chain); const assetsPath = getChainAssetsPath(chain);
if (isPathExistsSync(assetsPath)) { if (isPathExistsSync(assetsPath)) {
@ -94,7 +94,7 @@ export class FoldersFiles implements ActionInterface {
{ {
getName: () => { return "Asset folders contain info.json"}, getName: () => { return "Asset folders contain info.json"},
check: async () => { check: async () => {
var warnings: string[] = []; const warnings: string[] = [];
foundChains.forEach(chain => { foundChains.forEach(chain => {
const assetsPath = getChainAssetsPath(chain); const assetsPath = getChainAssetsPath(chain);
if (isPathExistsSync(assetsPath)) { if (isPathExistsSync(assetsPath)) {
@ -112,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 () => {
var errors: string[] = []; const errors: string[] = [];
foundChains.forEach(chain => { foundChains.forEach(chain => {
const assetsPath = getChainAssetsPath(chain); const assetsPath = getChainAssetsPath(chain);
if (isPathExistsSync(assetsPath)) { if (isPathExistsSync(assetsPath)) {

View File

@ -12,7 +12,7 @@ export class JsonAction implements ActionInterface {
{ {
getName: () => { return "Check all JSON files to have valid content"}, getName: () => { return "Check all JSON files to have valid content"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const files = [ const files = [
...findFiles(chainsPath, 'json'), ...findFiles(chainsPath, 'json'),
]; ];

View File

@ -11,7 +11,7 @@ export class KavaAction implements ActionInterface {
{ {
getName: () => { return "Kava validator assets must have correct format"}, getName: () => { return "Kava validator assets must have correct format"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const assets = getChainValidatorsAssets(Kava); const assets = getChainValidatorsAssets(Kava);
const prefix = "kavavaloper1"; const prefix = "kavavaloper1";
const expLength = 50; const expLength = 50;

View File

@ -18,14 +18,14 @@ import { ActionInterface, CheckStepInterface } from "./interface";
// return name of large logo, or empty // return name of large logo, or empty
async function checkDownsize(chains, checkOnly: boolean): Promise<string[]> { async function checkDownsize(chains, checkOnly: boolean): Promise<string[]> {
console.log(`Checking all logos for size ...`); console.log(`Checking all logos for size ...`);
let totalCountChecked: number = 0; let totalCountChecked = 0;
let totalCountTooLarge: number = 0; let totalCountTooLarge = 0;
let totalCountUpdated: number = 0; let totalCountUpdated = 0;
let largePaths: string[] = []; const largePaths: string[] = [];
await bluebird.map(chains, async chain => { await bluebird.map(chains, async chain => {
let countChecked: number = 0; let countChecked = 0;
let countTooLarge: number = 0; let countTooLarge = 0;
let countUpdated: number = 0; let countUpdated = 0;
const path = getChainLogoPath(chain); const path = getChainLogoPath(chain);
countChecked++; countChecked++;

View File

@ -11,7 +11,7 @@ export class TerraAction implements ActionInterface {
{ {
getName: () => { return "Terra validator assets must have correct format"}, getName: () => { return "Terra validator assets must have correct format"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const assets = getChainValidatorsAssets(Terra); const assets = getChainValidatorsAssets(Terra);
const prefix = "terravaloper1"; const prefix = "terravaloper1";
const expLength = 51; const expLength = 51;

View File

@ -57,7 +57,7 @@ async function gen_validators_tezos() {
} }
// Enable baker if has capacity // Enable baker if has capacity
if (freeSpace > 0 && val.hasOwnProperty("status")) { if (freeSpace > 0 && Object.prototype.hasOwnProperty.call(val, "status")) {
delete val.status delete val.status
} }
@ -83,7 +83,7 @@ export class TezosAction implements ActionInterface {
{ {
getName: () => { return "Tezos validator assets must have correct format"}, getName: () => { return "Tezos validator assets must have correct format"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const assets = getChainValidatorsAssets(Tezos); const assets = getChainValidatorsAssets(Tezos);
assets.forEach(addr => { assets.forEach(addr => {
if (!(eztz.crypto.checkAddress(addr))) { if (!(eztz.crypto.checkAddress(addr))) {

View File

@ -25,7 +25,7 @@ export class TronAction implements ActionInterface {
{ {
getName: () => { return "Tron assets should be TRC10 or TRC20, logo of correct size"; }, getName: () => { return "Tron assets should be TRC10 or TRC20, logo of correct size"; },
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const path = getChainAssetsPath(Tron); const path = getChainAssetsPath(Tron);
const assets = readDirSync(path); const assets = readDirSync(path);
await bluebird.each(assets, async (asset) => { await bluebird.each(assets, async (asset) => {
@ -43,7 +43,7 @@ export class TronAction implements ActionInterface {
{ {
getName: () => { return "Tron validator assets must have correct format"}, getName: () => { return "Tron validator assets must have correct format"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const assets = getChainValidatorsAssets(Tron); const assets = getChainValidatorsAssets(Tron);
assets.forEach(addr => { assets.forEach(addr => {
if (!(isTRC20(addr))) { if (!(isTRC20(addr))) {

View File

@ -35,15 +35,15 @@ const actionList: ActionInterface[] = [
const maxErrosFromOneCheck = 5; const maxErrosFromOneCheck = 5;
async function checkStepList(steps: CheckStepInterface[]): Promise<[string[], string[]]> { async function checkStepList(steps: CheckStepInterface[]): Promise<[string[], string[]]> {
var errorsAll: string[] = []; const errorsAll: string[] = [];
var warningsAll: string[] = []; const warningsAll: string[] = [];
await bluebird.each(steps, async (step) => { await bluebird.each(steps, async (step) => {
try { try {
//console.log(` Running check step '${step.getName()}'...`); //console.log(` Running check step '${step.getName()}'...`);
const [errors, warnings] = await step.check(); const [errors, warnings] = await step.check();
if (errors && errors.length > 0) { if (errors && errors.length > 0) {
console.log(`- ${chalk.red('X')} '${step.getName()}': ${errors.length} errors`); console.log(`- ${chalk.red('X')} '${step.getName()}': ${errors.length} errors`);
var cnt = 0; let cnt = 0;
errors.forEach(err => { errors.forEach(err => {
if (cnt < maxErrosFromOneCheck) { if (cnt < maxErrosFromOneCheck) {
console.log(` ${chalk.red('X')} '${err}'`); console.log(` ${chalk.red('X')} '${err}'`);
@ -56,7 +56,7 @@ async function checkStepList(steps: CheckStepInterface[]): Promise<[string[], st
} }
if (warnings && warnings.length > 0) { if (warnings && warnings.length > 0) {
console.log(`- ${chalk.yellow('!')} '${step.getName()}': ${warnings.length} warnings`); console.log(`- ${chalk.yellow('!')} '${step.getName()}': ${warnings.length} warnings`);
var cnt = 0; let cnt = 0;
warnings.forEach(warn => { warnings.forEach(warn => {
if (cnt < maxErrosFromOneCheck) { if (cnt < maxErrosFromOneCheck) {
console.log(` ${chalk.yellow('!')} '${warn}'`); console.log(` ${chalk.yellow('!')} '${warn}'`);
@ -80,8 +80,8 @@ async function checkStepList(steps: CheckStepInterface[]): Promise<[string[], st
async function sanityCheckByActionList(actions: ActionInterface[]): Promise<[string[], string[]]> { async function sanityCheckByActionList(actions: ActionInterface[]): Promise<[string[], string[]]> {
console.log("Running sanity checks..."); console.log("Running sanity checks...");
var errors: string[] = []; const errors: string[] = [];
var warnings: string[] = []; const warnings: string[] = [];
await bluebird.each(actions, async (action) => { await bluebird.each(actions, async (action) => {
try { try {
if (action.getSanityChecks) { if (action.getSanityChecks) {
@ -111,8 +111,8 @@ async function sanityCheckByActionList(actions: ActionInterface[]): Promise<[str
async function consistencyCheckByActionList(actions: ActionInterface[]): Promise<[string[], string[]]> { async function consistencyCheckByActionList(actions: ActionInterface[]): Promise<[string[], string[]]> {
console.log("Running consistency checks..."); console.log("Running consistency checks...");
var errors: string[] = []; const errors: string[] = [];
var warnings: string[] = []; const warnings: string[] = [];
await bluebird.each(actions, async (action) => { await bluebird.each(actions, async (action) => {
try { try {
if (action.getConsistencyChecks) { if (action.getConsistencyChecks) {
@ -193,14 +193,14 @@ export async function consistencyCheckAll(): Promise<[string[], string[]]> {
return await consistencyCheckByActionList(actionList); return await consistencyCheckByActionList(actionList);
} }
export async function sanityFixAll() { export async function sanityFixAll(): Promise<void> {
await sanityFixByList(actionList); await sanityFixByList(actionList);
} }
export async function consistencyFixAll() { export async function consistencyFixAll(): Promise<void> {
await consistencyFixByList(actionList); await consistencyFixByList(actionList);
} }
export async function updateAll() { export async function updateAll(): Promise<void> {
await updateByList(actionList); await updateByList(actionList);
} }

View File

@ -20,7 +20,7 @@ function formatValidators() {
} }
function getChainValidatorsList(chain: string): ValidatorModel[] { function getChainValidatorsList(chain: string): ValidatorModel[] {
return readJsonFile(getChainValidatorsListPath(chain)); return readJsonFile(getChainValidatorsListPath(chain)) as ValidatorModel[];
} }
function isValidatorHasAllKeys(val: ValidatorModel): boolean { function isValidatorHasAllKeys(val: ValidatorModel): boolean {
@ -34,7 +34,7 @@ export class Validators implements ActionInterface {
getName(): string { return "Validators"; } getName(): string { return "Validators"; }
getSanityChecks(): CheckStepInterface[] { getSanityChecks(): CheckStepInterface[] {
var steps: CheckStepInterface[] = [ const steps: CheckStepInterface[] = [
{ {
getName: () => { return "Make sure tests added for new staking chain"}, getName: () => { return "Make sure tests added for new staking chain"},
check: async (): Promise<[string[], string[]]> => { check: async (): Promise<[string[], string[]]> => {
@ -55,7 +55,7 @@ export class Validators implements ActionInterface {
return [[`Not valid Json file at path ${validatorsListPath}`], []]; return [[`Not valid Json file at path ${validatorsListPath}`], []];
} }
var errors: string[] = []; const errors: string[] = [];
const validatorsList = getChainValidatorsList(chain); const validatorsList = getChainValidatorsList(chain);
const chainValidatorsAssetsList = getChainValidatorsAssets(chain); const chainValidatorsAssetsList = getChainValidatorsAssets(chain);
await bluebird.each(validatorsList, async (val: ValidatorModel) => { await bluebird.each(validatorsList, async (val: ValidatorModel) => {

View File

@ -18,7 +18,7 @@ export class WavesAction implements ActionInterface {
{ {
getName: () => { return "Waves validator assets must have correct format"}, getName: () => { return "Waves validator assets must have correct format"},
check: async () => { check: async () => {
var errors: string[] = []; const errors: string[] = [];
const assets = getChainValidatorsAssets(Waves); const assets = getChainValidatorsAssets(Waves);
assets.forEach(addr => { assets.forEach(addr => {
if (!(isWavesAddress(addr))) { if (!(isWavesAddress(addr))) {

View File

@ -9,7 +9,7 @@ function isAssetInfoHasAllKeys(path: string): [boolean, string] {
const info = JSON.parse(readFileSync(path)); const info = JSON.parse(readFileSync(path));
const infoKeys = Object.keys(info); const infoKeys = Object.keys(info);
const hasAllKeys = requiredKeys.every(k => info.hasOwnProperty(k)); const hasAllKeys = requiredKeys.every(k => Object.prototype.hasOwnProperty.call(info, k));
if (!hasAllKeys) { if (!hasAllKeys) {
return [false, `Info at path '${path}' missing next key(s): ${arrayDiff(requiredKeys, infoKeys)}`]; return [false, `Info at path '${path}' missing next key(s): ${arrayDiff(requiredKeys, infoKeys)}`];

View File

@ -1,14 +1,12 @@
import { reverseCase } from "./types"; import { reverseCase } from "./types";
const Web3 = require('web3'); const web3 = new (require('web3'))('ws://localhost:8546');
const web3 = new Web3('ws://localhost:8546');
export const isChecksumEthereum = (address: string): boolean => web3.utils.checkAddressChecksum(address); export const isChecksumEthereum = (address: string): boolean => web3.utils.checkAddressChecksum(address);
export const toChecksumEthereum = (address: string): string => web3.utils.toChecksumAddress(address); export const toChecksumEthereum = (address: string): string => web3.utils.toChecksumAddress(address);
export function toChecksum(address: string, chain: string = "ethereum"): string { export function toChecksum(address: string, chain = "ethereum"): string {
var checksumEthereum = toChecksumEthereum(address); const checksumEthereum = toChecksumEthereum(address);
// special handling for Wanchain // special handling for Wanchain
if (chain.toLowerCase() === "wanchain") { if (chain.toLowerCase() === "wanchain") {
@ -19,7 +17,7 @@ export function toChecksum(address: string, chain: string = "ethereum"): string
return checksumEthereum; return checksumEthereum;
} }
export function isChecksum(address: string, chain: string = "ethereum"): boolean { export function isChecksum(address: string, chain = "ethereum"): boolean {
// special handling for Wanchain // special handling for Wanchain
if (chain.toLowerCase() === "wanchain") { if (chain.toLowerCase() === "wanchain") {
const addressEthereum = reverseCase(address).replace("X", "x"); const addressEthereum = reverseCase(address).replace("X", "x");

View File

@ -5,8 +5,8 @@ import { execSync } from "child_process";
export const getFileName = (name: string): string => path.basename(name, path.extname(name)) export const getFileName = (name: string): string => path.basename(name, path.extname(name))
export const getFileExt = (name: string): string => name.slice((Math.max(0, name.lastIndexOf(".")) || Infinity) + 1) export const getFileExt = (name: string): string => name.slice((Math.max(0, name.lastIndexOf(".")) || Infinity) + 1)
export const readFileSync = (path: string) => fs.readFileSync(path, 'utf8'); export const readFileSync = (path: string): string => fs.readFileSync(path, 'utf8');
export const writeFileSync = (path: string, data: any) => fs.writeFileSync(path, data); export const writeFileSync = (path: string, data: unknown): void => fs.writeFileSync(path, data);
export const readDirSync = (path: string): string[] => fs.readdirSync(path); export const readDirSync = (path: string): string[] => fs.readdirSync(path);
export const isPathExistsSync = (path: string): boolean => fs.existsSync(path); export const isPathExistsSync = (path: string): boolean => fs.existsSync(path);
export const getFileSizeInKilobyte = (path: string): number => fs.statSync(path).size / 1000; export const getFileSizeInKilobyte = (path: string): number => fs.statSync(path).size / 1000;
@ -20,7 +20,7 @@ function gitMoveCommand(oldName: string, newName: string): string {
return `git mv ${oldName} ${newName}-temp && git mv ${newName}-temp ${newName}`; return `git mv ${oldName} ${newName}-temp && git mv ${newName}-temp ${newName}`;
} }
export function gitMove(path: string, oldName: string, newName: string) { export function gitMove(path: string, oldName: string, newName: string): void {
console.log(`Renaming file or folder at path ${path}: ${oldName} => ${newName}`); console.log(`Renaming file or folder at path ${path}: ${oldName} => ${newName}`);
execRename(gitMoveCommand(oldName, newName), path); execRename(gitMoveCommand(oldName, newName), path);
} }
@ -30,7 +30,7 @@ export function findFiles(base: string, ext: string, files: string[] = [], resul
result = result || result; result = result || result;
files.forEach(file => { files.forEach(file => {
var newbase = path.join(base, file); const newbase = path.join(base, file);
if (fs.statSync(newbase).isDirectory()) { if (fs.statSync(newbase).isDirectory()) {
result = findFiles(newbase, ext, fs.readdirSync(newbase), result); result = findFiles(newbase, ext, fs.readdirSync(newbase), result);
} else { } else {

View File

@ -36,7 +36,7 @@ export function calculateTargetSize(srcWidth: number, srcHeight: number, targetW
// check logo dimensions (pixel) and size (kilobytes) // check logo dimensions (pixel) and size (kilobytes)
export async function isLogoOK(path: string): Promise<[boolean, string]> { export async function isLogoOK(path: string): Promise<[boolean, string]> {
var [isOK, msg] = await isLogoDimensionOK(path); let [isOK, msg] = await isLogoDimensionOK(path);
if (!isOK) { if (!isOK) {
return [false, msg]; return [false, msg];
} }
@ -74,7 +74,7 @@ async function isLogoSizeOK(path: string): Promise<[boolean, string]> {
// return if image if too large, and if image has been updated // return if image if too large, and if image has been updated
export async function checkResizeIfTooLarge(path: string, checkOnly: boolean): Promise<[boolean, boolean]> { export async function checkResizeIfTooLarge(path: string, checkOnly: boolean): Promise<[boolean, boolean]> {
let tooLarge = false; let tooLarge = false;
let updated: boolean = false; let updated = false;
const { width: srcWidth, height: srcHeight } = getImageDimensions(path); const { width: srcWidth, height: srcHeight } = getImageDimensions(path);

View File

@ -2,44 +2,40 @@ import {
readFileSync, readFileSync,
writeFileSync writeFileSync
} from "./filesystem"; } from "./filesystem";
import { sortElements, makeUnique } from "./types"; import { sortElements } from "./types";
export function isValidJSON(path: string): boolean { export function isValidJSON(path: string): boolean {
try { try {
let rawdata = readFileSync(path); const rawdata = readFileSync(path);
JSON.parse(rawdata); JSON.parse(rawdata);
return true; return true;
} catch { } catch {
}
return false; return false;
}
} }
export function formatJson(content: any) { export function formatJson(content: unknown): string {
return JSON.stringify(content, null, 4); return JSON.stringify(content, null, 4);
} }
export function formatSortJson(content: any) { export function formatSortJson(content: unknown[]): string {
return JSON.stringify(sortElements(content), null, 4); return JSON.stringify(sortElements(content), null, 4);
} }
export function formatUniqueSortJson(content: any) { export function formatJsonFile(filename: string): void {
return JSON.stringify(makeUnique(sortElements(content)), null, 4);
}
export function formatJsonFile(filename: string, silent: boolean = false) {
writeFileSync(filename, formatJson(JSON.parse(readFileSync(filename)))); writeFileSync(filename, formatJson(JSON.parse(readFileSync(filename))));
console.log(`Formatted json file ${filename}`); console.log(`Formatted json file ${filename}`);
} }
export function formatSortJsonFile(filename: string) { export function formatSortJsonFile(filename: string): void {
writeFileSync(filename, formatSortJson(JSON.parse(readFileSync(filename)))); writeFileSync(filename, formatSortJson(JSON.parse(readFileSync(filename))));
console.log(`Formatted json file ${filename}`); console.log(`Formatted json file ${filename}`);
} }
export function readJsonFile(path: string): any { export function readJsonFile(path: string): unknown {
return JSON.parse(readFileSync(path)); return JSON.parse(readFileSync(path));
} }
export function writeJsonFile(path: string, data: any) { export function writeJsonFile(path: string, data: unknown): void {
writeFileSync(path, JSON.stringify(data, null, 4)); writeFileSync(path, JSON.stringify(data, null, 4));
} }

View File

@ -28,7 +28,7 @@ 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 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) => `${getChainAssetsPath(chain)}/${asset}`; export const getChainAssetPath = (chain: string, asset: string): string => `${getChainAssetsPath(chain)}/${asset}`;
export const getChainAssetLogoPath = (chain: string, asset: string): string => `${getChainAssetPath(chain, asset)}/${logoFullName}`; export const getChainAssetLogoPath = (chain: string, asset: string): string => `${getChainAssetPath(chain, asset)}/${logoFullName}`;
export const getChainAssetInfoPath = (chain: string, asset: string): string => `${getChainAssetPath(chain, asset)}/${infoFullName}`; export const getChainAssetInfoPath = (chain: string, asset: string): string => `${getChainAssetPath(chain, asset)}/${infoFullName}`;
export const getChainAllowlistPath = (chain: string): string => `${getChainPath(chain)}/${allowList}`; export const getChainAllowlistPath = (chain: string): string => `${getChainPath(chain)}/${allowList}`;
@ -40,11 +40,11 @@ export const getChainValidatorsListPath = (chain: string): string => `${getChain
export const getChainValidatorsAssetsPath = (chain: string): string => `${getChainValidatorsPath(chain)}/assets` export const getChainValidatorsAssetsPath = (chain: string): string => `${getChainValidatorsPath(chain)}/assets`
export const getChainValidatorAssetLogoPath = (chain: string, asset: string): string => `${getChainValidatorsAssetsPath(chain)}/${asset}/${logoFullName}` export const getChainValidatorAssetLogoPath = (chain: string, asset: string): string => `${getChainValidatorsAssetsPath(chain)}/${asset}/${logoFullName}`
export const isChainAssetInfoExistSync = (chain: string, address: string) => isPathExistsSync(getChainAssetInfoPath(chain, address)); export const isChainAssetInfoExistSync = (chain: string, address: string): boolean => isPathExistsSync(getChainAssetInfoPath(chain, address));
export const getChainFolderFilesList = (chain: string) => readDirSync(getChainPath(chain)) export const getChainFolderFilesList = (chain: string): string[] => readDirSync(getChainPath(chain))
export const getChainAssetsList = (chain: string): string[] => readDirSync(getChainAssetsPath(chain)); export const getChainAssetsList = (chain: string): string[] => readDirSync(getChainAssetsPath(chain));
export const getChainAssetFilesList = (chain: string, address: string) => readDirSync(getChainAssetPath(chain, address)); export const getChainAssetFilesList = (chain: string, address: string): string[] => readDirSync(getChainAssetPath(chain, address));
export const getChainValidatorsAssets = (chain: string): string[] => readDirSync(getChainValidatorsAssetsPath(chain)); export const getChainValidatorsAssets = (chain: string): string[] => readDirSync(getChainValidatorsAssetsPath(chain));
export const rootDirAllowedFiles = config.foldersRootdirAllowedFiles; export const rootDirAllowedFiles = config.foldersRootdirAllowedFiles;

View File

@ -1,28 +1,18 @@
export const isLowerCase = (str: string): boolean => str.toLowerCase() === str; export const isLowerCase = (str: string): boolean => str.toLowerCase() === str;
export const isUpperCase = (str: string): boolean => str.toUpperCase() === str; export const isUpperCase = (str: string): boolean => str.toUpperCase() === str;
export const mapList = arr => {
return arr.reduce((acm, val) => {
acm[val] = "";
return acm;
}, {});
}
export function mapListTolower(arr: string[]): {} {
return arr.reduce((acm, val) => {
acm[val.toLowerCase()] = "";
return acm;
}, {});
}
// Sort: treat numbers as number, strings as case-insensitive // Sort: treat numbers as number, strings as case-insensitive
export const sortElements = (arr: any[]): any[] => { export function sortElements (arr: unknown[]): unknown[] {
arr.sort((a, b) => { arr.sort((a, b) => {
if (!isNaN(a) && !isNaN(b)) { if (typeof a === "number" && typeof b == "number") {
// numerical comparison // numerical comparison
return a - b; return a - b;
} }
if ((typeof a === 'string' || a instanceof String) && (typeof b === 'string' || b instanceof String)) { if ((typeof a === 'string' || a instanceof String) && (typeof b === 'string' || b instanceof String)) {
if (!isNaN(Number(a)) && !isNaN(Number(b))) {
// numerical comparison
return Number(a) - Number(b);
}
return a.toLowerCase() > b.toLowerCase() ? 1 : -1; return a.toLowerCase() > b.toLowerCase() ? 1 : -1;
} }
return 0; return 0;
@ -30,23 +20,25 @@ export const sortElements = (arr: any[]): any[] => {
return arr; return arr;
} }
export const makeUnique = (arr: any[]): any[] => Array.from(new Set(arr)); export function makeUnique(arr: string[]): string[] {
return Array.from(new Set(arr));
}
// Remove from set A elements of set B. // Remove from set A elements of set B.
export function arrayDiff(a: string[], b: string[]): string[] { export function arrayDiff(a: string[], b: string[]): string[] {
const mappedB = mapList(b); const setB = new Set(b);
return a.filter(e => !mappedB.hasOwnProperty(e)); return a.filter(e => !setB.has(e));
} }
// Remove from set A elements of set B, case insensitive // Remove from set A elements of set B, case insensitive
export function arrayDiffNocase(a: string[], b: string[]): string[] { export function arrayDiffNocase(a: string[], b: string[]): string[] {
const mappedB = mapListTolower(b); const setB = new Set(b.map(e => e.toLowerCase()));
return a.filter(e => !mappedB.hasOwnProperty(e.toLowerCase())); return a.filter(e => !setB.has(e.toLowerCase()));
} }
export function findDuplicates(list: string[]): string[] { export function findDuplicates(list: string[]): string[] {
let m = new Map<string, number>(); const m = new Map<string, number>();
let duplicates: string[] = []; const duplicates: string[] = [];
list.forEach(val => { list.forEach(val => {
if (m.has(val.toLowerCase())) { if (m.has(val.toLowerCase())) {
duplicates.push(val); duplicates.push(val);
@ -64,7 +56,7 @@ export function findCommonElementsOrDuplicates(list1: string[], list2: string[])
} }
// Compare two arrays, order does not matter // Compare two arrays, order does not matter
export function arrayEqual(a1: any[], a2: any[]): boolean { export function arrayEqual(a1: string[], a2: string[]): boolean {
if (a1.length != a2.length) { if (a1.length != a2.length) {
return false; return false;
} }
@ -79,8 +71,8 @@ export function arrayEqual(a1: any[], a2: any[]): boolean {
export function reverseCase(s: string): string { export function reverseCase(s: string): string {
const n = s.length; const n = s.length;
var out: string = ""; let out = "";
for (var i = 0; i < n; ++i) { for (let i = 0; i < n; ++i) {
const c = s[i]; const c = s[i];
if (isLowerCase(c)) { if (isLowerCase(c)) {
out += c.toUpperCase(); out += c.toUpperCase();

View File

@ -1,9 +1,9 @@
export const imageMaxLogoWidth: number = 512; export const imageMaxLogoWidth = 512;
export const imageMaxLogoHeight: number = 512; export const imageMaxLogoHeight = 512;
export const imageMinLogoWidth: number = 64; export const imageMinLogoWidth = 64;
export const imageMinLogoHeight: number = 64; export const imageMinLogoHeight = 64;
export const imageMaxLogoSizeKb: number = 100; export const imageMaxLogoSizeKb = 100;
export const foldersRootdirAllowedFiles: string[] = [".github", "blockchains", "dapps", "media", "node_modules", "script-old", "script", "test", ".gitignore", "azure-pipelines.yml", "jest.config.js", "LICENSE", "package-lock.json", "package.json", "README.md", ".git", "dangerfile.ts", "Gemfile", "Gemfile.lock"]; export const foldersRootdirAllowedFiles: string[] = [".github", "blockchains", "dapps", "media", "node_modules", "script-old", "script", "test", ".gitignore", "azure-pipelines.yml", "jest.config.js", "LICENSE", "package-lock.json", "package.json", "README.md", ".git", "dangerfile.ts", "Gemfile", "Gemfile.lock", ".eslintignore", ".eslintrc.js"];
export const binanceUrlTokens2: string = "https://dex-atlantic.binance.org/api/v1/tokens?limit=1000"; export const binanceUrlTokens2 = "https://dex-atlantic.binance.org/api/v1/tokens?limit=1000";
export const binanceUrlTokens8: string = "https://dex-atlantic.binance.org/api/v1/mini/tokens?limit=1000"; export const binanceUrlTokens8 = "https://dex-atlantic.binance.org/api/v1/mini/tokens?limit=1000";
export const binanceUrlTokenAssets: string = "https://explorer.binance.org/api/v1/assets?page=1&rows=1000"; export const binanceUrlTokenAssets = "https://explorer.binance.org/api/v1/assets?page=1&rows=1000";

View File

@ -1,9 +1,9 @@
import { sanityCheckAll } from "../action/update-all"; import { sanityCheckAll } from "../action/update-all";
export async function main() { export async function main(): Promise<void> {
try { try {
const [errors, warnings] = await sanityCheckAll();
// warnings ignored // warnings ignored
const [errors] = await sanityCheckAll();
process.exit(errors.length); process.exit(errors.length);
} catch(err) { } catch(err) {
console.error(err); console.error(err);

View File

@ -1,11 +1,11 @@
import { sanityCheckAll, consistencyCheckAll } from "../action/update-all"; import { sanityCheckAll, consistencyCheckAll } from "../action/update-all";
export async function main() { export async function main(): Promise<void> {
var returnCode: number = 0; let returnCode = 0;
try { try {
const [errors1, warnings1] = await sanityCheckAll();
// warnings ignored // warnings ignored
const [errors1] = await sanityCheckAll();
if (errors1.length > 0) { if (errors1.length > 0) {
returnCode = errors1.length; returnCode = errors1.length;
} }
@ -15,8 +15,8 @@ export async function main() {
} }
try { try {
const [errors1, warnings1] = await consistencyCheckAll();
// warnings ignored // warnings ignored
const [errors1] = await consistencyCheckAll();
if (errors1.length > 0) { if (errors1.length > 0) {
returnCode = errors1.length; returnCode = errors1.length;
} }

View File

@ -1,6 +1,6 @@
import { sanityFixAll, consistencyFixAll } from "../action/update-all"; import { sanityFixAll } from "../action/update-all";
export async function main() { export async function main(): Promise<void> {
try { try {
await sanityFixAll(); await sanityFixAll();
} catch(err) { } catch(err) {

View File

@ -1,6 +1,6 @@
import { sanityFixAll, consistencyFixAll } from "../action/update-all"; import { sanityFixAll, consistencyFixAll } from "../action/update-all";
export async function main() { export async function main(): Promise<void> {
try { try {
await sanityFixAll(); await sanityFixAll();
} catch(err) { } catch(err) {

View File

@ -1,6 +1,6 @@
import { updateAll } from "../action/update-all"; import { updateAll } from "../action/update-all";
export async function main() { export async function main(): Promise<void> {
try { try {
await updateAll(); await updateAll();
} catch(err) { } catch(err) {

View File

@ -13,8 +13,6 @@ import {
calculateTargetSize calculateTargetSize
} from "../script/common/image"; } from "../script/common/image";
import { import {
mapList,
mapListTolower,
sortElements, sortElements,
makeUnique, makeUnique,
arrayDiff, arrayDiff,
@ -74,15 +72,11 @@ describe("Test image helpers", () => {
}); });
describe("Test type helpers", () => { describe("Test type helpers", () => {
test(`Test mapList`, () => {
expect(mapList(["a", "b", "c"]), `3 elems`).toEqual({"a": "", "b":"", "c": ""});
expect(mapList(["a", "b", "C"]), `3 elems`).toEqual({"a": "", "b":"", "C": ""});
expect(mapListTolower(["a", "b", "C"]), `3 elems`).toEqual({"a": "", "b":"", "c": ""});
});
test(`Test sortElements`, () => { test(`Test sortElements`, () => {
expect(sortElements(["c", "a", "b"]), `3 elems`).toEqual(["a", "b", "c"]); expect(sortElements(["c", "a", "b"]), `3 elems`).toEqual(["a", "b", "c"]);
expect(sortElements(["C", "a", "b"]), `mixed case`).toEqual(["a", "b", "C"]); expect(sortElements(["C", "a", "b"]), `mixed case`).toEqual(["a", "b", "C"]);
expect(sortElements(["1", "2", "11"]), `numerical`).toEqual(["1", "2", "11"]); expect(sortElements(["1", "2", "11"]), `numerical string`).toEqual(["1", "2", "11"]);
expect(sortElements([1, 2, 11]), `numerical`).toEqual([1, 2, 11]);
expect(sortElements(["C", "a", "1", "b", "2", "11"]), `complex`).toEqual(["1", "2", "11", "a", "b", "C"]); expect(sortElements(["C", "a", "1", "b", "2", "11"]), `complex`).toEqual(["1", "2", "11", "a", "b", "C"]);
}); });
test(`Test makeUnique`, () => { test(`Test makeUnique`, () => {
@ -124,8 +118,8 @@ describe("Test type helpers", () => {
describe("Test action binance", () => { describe("Test action binance", () => {
test(`Test findImagesToFetch`, () => { test(`Test findImagesToFetch`, () => {
const assetsInfoListNonexisting: any[] = [{asset: "A1", assetImg: "imgurl1"}, {asset: "A2", assetImg: "imgurl2"}]; const assetsInfoListNonexisting = [{asset: "A1", assetImg: "imgurl1"}, {asset: "A2", assetImg: "imgurl2"}];
const assetsInfoListExisting: any[] = [{asset: "BUSD-BD1", assetImg: "imgurlBUSD"}, {asset: "ETH-1C9", assetImg: "imgurlETH"}]; const assetsInfoListExisting = [{asset: "BUSD-BD1", assetImg: "imgurlBUSD"}, {asset: "ETH-1C9", assetImg: "imgurlETH"}];
const denyListEmpty: string[] = []; const denyListEmpty: string[] = [];
const denyListA1: string[] = ["A1"]; const denyListA1: string[] = ["A1"];
expect(findImagesToFetch(assetsInfoListNonexisting, denyListEmpty), `2 nonexisting`).toEqual(assetsInfoListNonexisting); expect(findImagesToFetch(assetsInfoListNonexisting, denyListEmpty), `2 nonexisting`).toEqual(assetsInfoListNonexisting);