[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
- name: Run test
run: npm t
- name: Run lint
run: npm run lint

View File

@ -20,3 +20,5 @@ jobs:
run: npm run check-sanity
- name: Run test
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]) => {
errors.forEach(err => fail(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.");
}
});

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",
"fix": "ts-node ./script/main/fix",
"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": {
"type": "git",
@ -35,11 +36,14 @@
"@types/jest": "^25.2.3",
"@types/jest-expect-message": "^1.0.2",
"@types/node": "^13.13.17",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"axios": "^0.19.2",
"bip44-constants": "^8.0.49",
"bluebird": "^3.7.2",
"chalk": "^4.1.0",
"danger": "^10.4.0",
"eslint": "^7.9.0",
"ethereum-checksum-address": "0.0.6",
"eztz-lib": "^0.1.2",
"image-size": "^0.8.3",

View File

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

View File

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

View File

@ -27,12 +27,12 @@ import * as bluebird from "bluebird";
async function formatInfos() {
console.log(`Formatting info files...`);
await bluebird.each(ethForkChains, async (chain) => {
let count: number = 0;
let count = 0;
const chainAssets = getChainAssetsList(chain);
await bluebird.each(chainAssets, async (address) => {
if (isChainAssetInfoExistSync(chain, address)) {
const chainAssetInfoPath = getChainAssetInfoPath(chain, address);
formatJsonFile(chainAssetInfoPath, true);
formatJsonFile(chainAssetInfoPath);
++count;
}
})
@ -69,13 +69,13 @@ export class EthForks implements ActionInterface {
getName(): string { return "Ethereum forks"; }
getSanityChecks(): CheckStepInterface[] {
var steps: CheckStepInterface[] = [];
const steps: CheckStepInterface[] = [];
ethForkChains.forEach(chain => {
steps.push(
{
getName: () => { return `Folder structure for chain ${chain} (ethereum fork)`;},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
const assetsFolder = getChainAssetsPath(chain);
const assetsList = getChainAssetsList(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"},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
const dirActualFiles = readDirSync(".");
dirActualFiles.forEach(file => {
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"},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
foundChains.forEach(chain => {
if (!isLowerCase(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"},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
await bluebird.each(foundChains, async (chain) => {
const chainLogoPath = getChainLogoPath(chain);
if (!isPathExistsSync(chainLogoPath)) {
@ -76,7 +76,7 @@ export class FoldersFiles implements ActionInterface {
{
getName: () => { return "Asset folders contain logo"},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
foundChains.forEach(chain => {
const assetsPath = getChainAssetsPath(chain);
if (isPathExistsSync(assetsPath)) {
@ -94,7 +94,7 @@ export class FoldersFiles implements ActionInterface {
{
getName: () => { return "Asset folders contain info.json"},
check: async () => {
var warnings: string[] = [];
const warnings: string[] = [];
foundChains.forEach(chain => {
const assetsPath = getChainAssetsPath(chain);
if (isPathExistsSync(assetsPath)) {
@ -112,7 +112,7 @@ export class FoldersFiles implements ActionInterface {
{
getName: () => { return "Asset folders contain only predefined set of files"},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
foundChains.forEach(chain => {
const assetsPath = getChainAssetsPath(chain);
if (isPathExistsSync(assetsPath)) {

View File

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

View File

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

View File

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

View File

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

View File

@ -57,7 +57,7 @@ async function gen_validators_tezos() {
}
// Enable baker if has capacity
if (freeSpace > 0 && val.hasOwnProperty("status")) {
if (freeSpace > 0 && Object.prototype.hasOwnProperty.call(val, "status")) {
delete val.status
}
@ -83,7 +83,7 @@ export class TezosAction implements ActionInterface {
{
getName: () => { return "Tezos validator assets must have correct format"},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
const assets = getChainValidatorsAssets(Tezos);
assets.forEach(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"; },
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
const path = getChainAssetsPath(Tron);
const assets = readDirSync(path);
await bluebird.each(assets, async (asset) => {
@ -43,7 +43,7 @@ export class TronAction implements ActionInterface {
{
getName: () => { return "Tron validator assets must have correct format"},
check: async () => {
var errors: string[] = [];
const errors: string[] = [];
const assets = getChainValidatorsAssets(Tron);
assets.forEach(addr => {
if (!(isTRC20(addr))) {

View File

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

View File

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

View File

@ -9,7 +9,7 @@ function isAssetInfoHasAllKeys(path: string): [boolean, string] {
const info = JSON.parse(readFileSync(path));
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) {
return [false, `Info at path '${path}' missing next key(s): ${arrayDiff(requiredKeys, infoKeys)}`];

View File

@ -1,14 +1,12 @@
import { reverseCase } from "./types";
const Web3 = require('web3');
const web3 = new Web3('ws://localhost:8546');
const web3 = new (require('web3'))('ws://localhost:8546');
export const isChecksumEthereum = (address: string): boolean => web3.utils.checkAddressChecksum(address);
export const toChecksumEthereum = (address: string): string => web3.utils.toChecksumAddress(address);
export function toChecksum(address: string, chain: string = "ethereum"): string {
var checksumEthereum = toChecksumEthereum(address);
export function toChecksum(address: string, chain = "ethereum"): string {
const checksumEthereum = toChecksumEthereum(address);
// special handling for Wanchain
if (chain.toLowerCase() === "wanchain") {
@ -19,7 +17,7 @@ export function toChecksum(address: string, chain: string = "ethereum"): string
return checksumEthereum;
}
export function isChecksum(address: string, chain: string = "ethereum"): boolean {
export function isChecksum(address: string, chain = "ethereum"): boolean {
// special handling for Wanchain
if (chain.toLowerCase() === "wanchain") {
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 getFileExt = (name: string): string => name.slice((Math.max(0, name.lastIndexOf(".")) || Infinity) + 1)
export const readFileSync = (path: string) => fs.readFileSync(path, 'utf8');
export const writeFileSync = (path: string, data: any) => fs.writeFileSync(path, data);
export const readFileSync = (path: string): string => fs.readFileSync(path, 'utf8');
export const writeFileSync = (path: string, data: unknown): void => fs.writeFileSync(path, data);
export const readDirSync = (path: string): string[] => fs.readdirSync(path);
export const isPathExistsSync = (path: string): boolean => fs.existsSync(path);
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}`;
}
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}`);
execRename(gitMoveCommand(oldName, newName), path);
}
@ -30,7 +30,7 @@ export function findFiles(base: string, ext: string, files: string[] = [], resul
result = result || result;
files.forEach(file => {
var newbase = path.join(base, file);
const newbase = path.join(base, file);
if (fs.statSync(newbase).isDirectory()) {
result = findFiles(newbase, ext, fs.readdirSync(newbase), result);
} else {

View File

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

View File

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

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 getChainLogoPath = (chain: string): string => `${getChainPath(chain)}/info/${logoFullName}`;
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 getChainAssetInfoPath = (chain: string, asset: string): string => `${getChainAssetPath(chain, asset)}/${infoFullName}`;
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 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 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 rootDirAllowedFiles = config.foldersRootdirAllowedFiles;

View File

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

View File

@ -1,9 +1,9 @@
export const imageMaxLogoWidth: number = 512;
export const imageMaxLogoHeight: number = 512;
export const imageMinLogoWidth: number = 64;
export const imageMinLogoHeight: number = 64;
export const imageMaxLogoSizeKb: number = 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 binanceUrlTokens2: string = "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 binanceUrlTokenAssets: string = "https://explorer.binance.org/api/v1/assets?page=1&rows=1000";
export const imageMaxLogoWidth = 512;
export const imageMaxLogoHeight = 512;
export const imageMinLogoWidth = 64;
export const imageMinLogoHeight = 64;
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", ".eslintignore", ".eslintrc.js"];
export const binanceUrlTokens2 = "https://dex-atlantic.binance.org/api/v1/tokens?limit=1000";
export const binanceUrlTokens8 = "https://dex-atlantic.binance.org/api/v1/mini/tokens?limit=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";
export async function main() {
export async function main(): Promise<void> {
try {
const [errors, warnings] = await sanityCheckAll();
// warnings ignored
const [errors] = await sanityCheckAll();
process.exit(errors.length);
} catch(err) {
console.error(err);

View File

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

View File

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

View File

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

View File

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