mirror of
https://github.com/Instadapp/trustwallet-assets.git
synced 2024-07-29 22:37:31 +00:00
[Internal] Refactored fix builds (#2920)
* Empty infrastructure for new-housekeeping build. * Move updateBEP action to new new-housekeeping build infra. * Remove old updateBEP. * New-housekeeping-dryrun run. * Include new top-level folder name script-new. * Remove update:bep2 from old daily-run. * Use imports instead of require. * Small refactor for testability. * Organize scripts into subfolders. * iUpdateBEP2: refactor and add tests. * Move formatting validators to new-housekeeping,add new helpers. * Move info and black/whitelist fixing to new-housekeeping. * New fix command. * New 'fix' target; Move ETH checksum fix to new-housekeeping. * Move logo size check and resize to new-housekeeping. * Improved async error handling. * Build renames. * Move (old) BEP2 and CMC update to periodic update build. * Rename (add missing). * Rename builds. * Renames ('fix'). * rename * Invoke new scripts (as well) from period-update. * Move cmc update to new-periodic. * Move tezos validator update to new-periodic. * Missing file. * Leftover. * Cleanup * Rename of unused openseacontracts. * CMC should not be run always. * Break main/fixAndUpdate function into two. * Show diff in build after changes. * Cleanup * Rename, script-old. * Cleanup, remove old fix build definitions. * Renames, remove new- prefix. * CMC mapping update. * Config infrastructure; add binance URL to config. * Add image size parameters to config. * Rename. Co-authored-by: Catenocrypt <catenocrypt@users.noreply.github.com> Co-authored-by: Andrew M <35627271+zachzwei@users.noreply.github.com>
This commit is contained in:
parent
515a1a0cbb
commit
079617ac38
13
.github/workflows/fix-dryrun.yml
vendored
13
.github/workflows/fix-dryrun.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: Fixes Dryrun
|
name: Fixes and Consistency Updates - Dry run
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
@ -7,7 +7,7 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
jobs:
|
jobs:
|
||||||
fix-consistency:
|
scripts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -16,12 +16,11 @@ jobs:
|
||||||
node-version: 12
|
node-version: 12
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
- name: Run fix scripts
|
- name: Run fix script
|
||||||
run: |
|
run: npm run fix
|
||||||
npm run resize
|
|
||||||
npm run format:all
|
|
||||||
npm run gen:list
|
|
||||||
- name: Show git status (diff)
|
- name: Show git status (diff)
|
||||||
|
if: success()
|
||||||
run: git status
|
run: git status
|
||||||
- name: Run test
|
- name: Run test
|
||||||
run: npm t
|
run: npm t
|
||||||
|
|
||||||
|
|
12
.github/workflows/fix.yml
vendored
12
.github/workflows/fix.yml
vendored
|
@ -3,23 +3,19 @@ on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
jobs:
|
jobs:
|
||||||
fix-consistency:
|
scripts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
token: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
|
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 12
|
node-version: 12
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
- name: Run fix scripts
|
- name: Run fix script
|
||||||
run: |
|
run: npm run fix
|
||||||
npm run resize
|
|
||||||
npm run format:all
|
|
||||||
npm run gen:list
|
|
||||||
- name: Show git status (diff)
|
- name: Show git status (diff)
|
||||||
|
if: success()
|
||||||
run: git status
|
run: git status
|
||||||
- name: Run test
|
- name: Run test
|
||||||
run: npm t
|
run: npm t
|
||||||
|
|
10
.github/workflows/periodic-update.yml
vendored
10
.github/workflows/periodic-update.yml
vendored
|
@ -4,7 +4,7 @@ on:
|
||||||
# Run twice per day (at 7:00UTC/12amPST, 19:00UTC/12pmPST)
|
# Run twice per day (at 7:00UTC/12amPST, 19:00UTC/12pmPST)
|
||||||
- cron: '0 7,19 * * *'
|
- cron: '0 7,19 * * *'
|
||||||
jobs:
|
jobs:
|
||||||
update:
|
scripts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -17,10 +17,10 @@ jobs:
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
- name: Run scripts
|
- name: Run scripts
|
||||||
run: |
|
run: npm run update
|
||||||
npm run gen:validators:tezos
|
- name: Show git status (diff)
|
||||||
npm run update:bep2
|
if: success()
|
||||||
npm run map:cmc
|
run: git status
|
||||||
- name: Run test
|
- name: Run test
|
||||||
run: npm t
|
run: npm t
|
||||||
- name: Commit changes test pased
|
- name: Commit changes test pased
|
||||||
|
|
|
@ -152,8 +152,8 @@
|
||||||
"TLyqzVGLV1srkB7dToTAEqgDSfPtXRJZYH",
|
"TLyqzVGLV1srkB7dToTAEqgDSfPtXRJZYH",
|
||||||
"TMhjbHzJCiMWqa5oqn2DF3mGw5yh9oQNf2",
|
"TMhjbHzJCiMWqa5oqn2DF3mGw5yh9oQNf2",
|
||||||
"TMwFHYXLJaRUPeW6421aqXL4ZEzPRFGkGT",
|
"TMwFHYXLJaRUPeW6421aqXL4ZEzPRFGkGT",
|
||||||
"TNZXVQUKQ8Gnjq2BqLvt2kC5WbeDQc1q3j",
|
|
||||||
"TNjt5fShPVJ4YpsLuU4THuBbg58g2bZoLk",
|
"TNjt5fShPVJ4YpsLuU4THuBbg58g2bZoLk",
|
||||||
|
"TNZXVQUKQ8Gnjq2BqLvt2kC5WbeDQc1q3j",
|
||||||
"TPRuU2GbXPwvvSuggE4xKMRtzsfwYfvBWq",
|
"TPRuU2GbXPwvvSuggE4xKMRtzsfwYfvBWq",
|
||||||
"TQhfmGiZvRt3oe9vKv6W9WXRr4oErxc8RE",
|
"TQhfmGiZvRt3oe9vKv6W9WXRr4oErxc8RE",
|
||||||
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
||||||
|
|
12
package.json
12
package.json
|
@ -5,16 +5,8 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"update:bep2": "node ./script/updateBEP2",
|
"fix": "ts-node ./script/main/fix",
|
||||||
"checksum": "ts-node ./script/erc20_to_checksum",
|
"update": "ts-node ./script/main/update"
|
||||||
"format:all": "ts-node ./script/format_files_name",
|
|
||||||
"arrange:all": "ts-node ./script/arrange_files",
|
|
||||||
"gen:list": "ts-node ./script/gen_list",
|
|
||||||
"gen:info": "ts-node ./script/gen_info",
|
|
||||||
"gen:validators:tezos": "ts-node ./script/gen_validators_tezos",
|
|
||||||
"resize": "ts-node ./script/resize_images",
|
|
||||||
"map:cmc": "ts-node ./pricing/coinmarketcap/script",
|
|
||||||
"magic": "npm run update:bep2 && npm run checksum && npm run resize && npm run gen:list && npm t"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { toChecksum } from "../../src/test/helpers"
|
import { toChecksum } from "../../src/test/helpers"
|
||||||
const BluebirbPromise = require("bluebird")
|
const BluebirdPromise = require("bluebird")
|
||||||
const axios = require("axios")
|
const axios = require("axios")
|
||||||
const chalk = require('chalk')
|
const chalk = require('chalk')
|
||||||
const fs = require("fs")
|
const fs = require("fs")
|
||||||
|
@ -20,7 +20,7 @@ import { TickerType, mapTiker, PlatformType } from "../../src/test/models";
|
||||||
// Steps required to run this:
|
// Steps required to run this:
|
||||||
// 1. (Optional) CMC API key already setup, use yours if needed. Install script deps "npm i" if hasn't been run before.
|
// 1. (Optional) CMC API key already setup, use yours if needed. Install script deps "npm i" if hasn't been run before.
|
||||||
// 2. Pull down tokens repo https://github.com/trustwallet/assets and point COIN_IMAGE_BASE_PATH and TOKEN_IMAGE_BASE_PATH to it.
|
// 2. Pull down tokens repo https://github.com/trustwallet/assets and point COIN_IMAGE_BASE_PATH and TOKEN_IMAGE_BASE_PATH to it.
|
||||||
// 3. Run: `npm run gen:list`
|
// 3. Run: `npm run update`
|
||||||
|
|
||||||
const CMC_PRO_API_KEY = `df781835-e5f4-4448-8b0a-fe31402ab3af` // Free Basic Plan api key is enough to run script
|
const CMC_PRO_API_KEY = `df781835-e5f4-4448-8b0a-fe31402ab3af` // Free Basic Plan api key is enough to run script
|
||||||
const CMC_LATEST_BASE_URL = `https://pro-api.coinmarketcap.com/v1/global-metrics/quotes/latest?`
|
const CMC_LATEST_BASE_URL = `https://pro-api.coinmarketcap.com/v1/global-metrics/quotes/latest?`
|
||||||
|
@ -61,14 +61,13 @@ const allContracts: mapTiker[] = [] // Temp storage for mapped assets
|
||||||
let bnbOwnerToSymbol = {} // e.g: bnb1tawge8u97slduhhtumm03l4xl4c46dwv5m9yzk: WISH-2D5
|
let bnbOwnerToSymbol = {} // e.g: bnb1tawge8u97slduhhtumm03l4xl4c46dwv5m9yzk: WISH-2D5
|
||||||
let bnbOriginalSymbolToSymbol = {} // e.g: WISH: WISH-2D5
|
let bnbOriginalSymbolToSymbol = {} // e.g: WISH: WISH-2D5
|
||||||
|
|
||||||
run()
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
await Promise.all([initState(), setBinanceTokens()])
|
await Promise.all([initState(), setBinanceTokens()])
|
||||||
const [totalCrypto, coins] = await Promise.all([getTotalActiveCryptocurrencies(), getTickers()])
|
const [totalCrypto, coins] = await Promise.all([getTotalActiveCryptocurrencies(), getTickers()])
|
||||||
// setBIP44Constants()
|
// setBIP44Constants()
|
||||||
log(`Found ${totalCrypto} on CMC`, chalk.yellowBright)
|
log(`Found ${totalCrypto} on CMC`, chalk.yellowBright)
|
||||||
await BluebirbPromise.mapSeries(coins, processCoin)
|
await BluebirdPromise.mapSeries(coins, processCoin)
|
||||||
|
|
||||||
addCustom()
|
addCustom()
|
||||||
printContracts()
|
printContracts()
|
||||||
|
@ -351,4 +350,8 @@ function log(string, cb?) {
|
||||||
// coinName: row[2]
|
// coinName: row[2]
|
||||||
// }
|
// }
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
export async function update() {
|
||||||
|
await run();
|
||||||
|
}
|
||||||
|
|
87
script/action/binance.ts
Normal file
87
script/action/binance.ts
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import * as bluebird from "bluebird";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as chalk from 'chalk';
|
||||||
|
import * as config from "../common/config";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getChainAssetLogoPath,
|
||||||
|
getChainBlacklistPath
|
||||||
|
} from "../common/repo-structure";
|
||||||
|
|
||||||
|
const binanceChain = "binance"
|
||||||
|
const binanceAssetsUrl = config.getConfig("binance_assets_url", "https://explorer.binance.org/api/v1/assets?page=1&rows=1000");
|
||||||
|
|
||||||
|
async function retrieveAssetList() {
|
||||||
|
console.log(`Retrieving assets info from: ${binanceAssetsUrl}`);
|
||||||
|
const { assetInfoList } = await axios.get(binanceAssetsUrl).then(r => r.data);
|
||||||
|
console.log(`Retrieved ${assetInfoList.length} asset infos`);
|
||||||
|
return assetInfoList
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchImage(url) {
|
||||||
|
return axios.get(url, { responseType: "stream" })
|
||||||
|
.then(r => r.data)
|
||||||
|
.catch(err => {
|
||||||
|
throw `Error fetchImage: ${url} ${err.message}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return: array with images to fetch; {asset, assetImg}
|
||||||
|
export function findImagesToFetch(assetInfoList: any, blacklist: string[]): any[] {
|
||||||
|
let toFetch: any[] = [];
|
||||||
|
console.log(`Checking for asset images to be fetched`);
|
||||||
|
assetInfoList.forEach(({asset, assetImg}) => {
|
||||||
|
process.stdout.write(`.${asset} `);
|
||||||
|
if (assetImg) {
|
||||||
|
if (blacklist.indexOf(asset) != -1) {
|
||||||
|
console.log();
|
||||||
|
console.log(`${asset} is blacklisted`);
|
||||||
|
} else {
|
||||||
|
const imagePath = getChainAssetLogoPath(binanceChain, asset);
|
||||||
|
if (!fs.existsSync(imagePath)) {
|
||||||
|
console.log(chalk.red(`Missing image: ${asset}`));
|
||||||
|
toFetch.push({asset, assetImg});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log();
|
||||||
|
console.log(`${toFetch.length} asset image(s) to be fetched`);
|
||||||
|
return toFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function fetchMissingImages(toFetch: any[]): Promise<string[]> {
|
||||||
|
console.log(`Attempting to fetch ${toFetch.length} asset image(s)`);
|
||||||
|
let fetchedAssets: string[] = [];
|
||||||
|
await bluebird.each(toFetch, async ({ asset, assetImg }) => {
|
||||||
|
if (assetImg) {
|
||||||
|
const imagePath = getChainAssetLogoPath(binanceChain, asset);
|
||||||
|
fs.mkdir(path.dirname(imagePath), err => {
|
||||||
|
if (err && err.code != `EEXIST`) throw err;
|
||||||
|
});
|
||||||
|
await fetchImage(assetImg).then(buffer => {
|
||||||
|
buffer.pipe(fs.createWriteStream(imagePath));
|
||||||
|
fetchedAssets.push(asset)
|
||||||
|
console.log(`Fetched image ${asset} ${imagePath} from ${assetImg}`)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log();
|
||||||
|
return fetchedAssets;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function update() {
|
||||||
|
const assetInfoList = await retrieveAssetList();
|
||||||
|
const blacklist: string[] = require(getChainBlacklistPath(binanceChain));
|
||||||
|
|
||||||
|
const toFetch = findImagesToFetch(assetInfoList, blacklist);
|
||||||
|
const fetchedAssets = await fetchMissingImages(toFetch);
|
||||||
|
|
||||||
|
if (fetchedAssets.length > 0) {
|
||||||
|
console.log(`Fetched ${fetchedAssets.length} asset(s):`);
|
||||||
|
fetchedAssets.forEach(asset => console.log(` ${asset}`));
|
||||||
|
}
|
||||||
|
}
|
66
script/action/eth-forks.ts
Normal file
66
script/action/eth-forks.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import { ethForkChains } from "../common/blockchains";
|
||||||
|
import {
|
||||||
|
getChainAssetsPath,
|
||||||
|
getChainAssetsList,
|
||||||
|
getChainAssetPath,
|
||||||
|
getChainAssetInfoPath,
|
||||||
|
getChainAssetFilesList,
|
||||||
|
isChainAssetInfoExistSync,
|
||||||
|
logoName,
|
||||||
|
logoExtension,
|
||||||
|
logoFullName
|
||||||
|
} from "../common/repo-structure";
|
||||||
|
import { formatJsonFile } from "../common/json";
|
||||||
|
import {
|
||||||
|
getFileName,
|
||||||
|
getFileExt,
|
||||||
|
gitMove,
|
||||||
|
readDirSync
|
||||||
|
} from "../common/filesystem";
|
||||||
|
import { isChecksum, toChecksum } from "../common/eth-web3";
|
||||||
|
|
||||||
|
function formatInfos() {
|
||||||
|
console.log(`Formatting info files...`);
|
||||||
|
ethForkChains.forEach(chain => {
|
||||||
|
let count: number = 0;
|
||||||
|
const chainAssets = getChainAssetsList(chain);
|
||||||
|
chainAssets.forEach(address => {
|
||||||
|
if (isChainAssetInfoExistSync(chain, address)) {
|
||||||
|
const chainAssetInfoPath = getChainAssetInfoPath(chain, address);
|
||||||
|
formatJsonFile(chainAssetInfoPath, true);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log(`Formatted ${count} info files for chain ${chain} (total ${chainAssets.length})`);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAddressChecksum(assetsFolderPath: string, address: string) {
|
||||||
|
if (!isChecksum(address)) {
|
||||||
|
const checksumAddress = toChecksum(address);
|
||||||
|
gitMove(assetsFolderPath, address, checksumAddress);
|
||||||
|
console.log(`Renamed to checksum format ${checksumAddress}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAddressChecksums() {
|
||||||
|
console.log(`Checking for checksum formats ...`);
|
||||||
|
ethForkChains.forEach(chain => {
|
||||||
|
const assetsPath = getChainAssetsPath(chain);
|
||||||
|
|
||||||
|
readDirSync(assetsPath).forEach(address => {
|
||||||
|
getChainAssetFilesList(chain, address).forEach(file => {
|
||||||
|
if (getFileName(file) == logoName && getFileExt(file) !== logoExtension) {
|
||||||
|
console.log(`Renaming incorrect asset logo extension ${file} ...`);
|
||||||
|
gitMove(getChainAssetPath(chain, address), file, logoFullName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
checkAddressChecksum(assetsPath, address);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fix() {
|
||||||
|
formatInfos();
|
||||||
|
checkAddressChecksums();
|
||||||
|
}
|
62
script/action/logo-size.ts
Normal file
62
script/action/logo-size.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import * as bluebird from "bluebird";
|
||||||
|
import {
|
||||||
|
chainsPath,
|
||||||
|
getChainLogoPath,
|
||||||
|
getChainAssetsPath,
|
||||||
|
getChainAssetLogoPath,
|
||||||
|
getChainValidatorsListPath,
|
||||||
|
getChainValidatorAssetLogoPath
|
||||||
|
} from "../common/repo-structure";
|
||||||
|
import {
|
||||||
|
readDirSync,
|
||||||
|
readFileSync,
|
||||||
|
isPathExistsSync
|
||||||
|
} from "../common/filesystem";
|
||||||
|
import { resizeIfTooLarge } from "../common/image";
|
||||||
|
|
||||||
|
async function downsize(chains) {
|
||||||
|
console.log(`Checking all logos for downsizing ...`);
|
||||||
|
let totalCountChecked: number = 0;
|
||||||
|
let totalCountUpdated: number = 0;
|
||||||
|
await bluebird.map(chains, async chain => {
|
||||||
|
let countChecked: number = 0;
|
||||||
|
let countUpdated: number = 0;
|
||||||
|
|
||||||
|
const path = getChainLogoPath(chain);
|
||||||
|
countChecked++;
|
||||||
|
countUpdated += await resizeIfTooLarge(path) ? 1 : 0;
|
||||||
|
|
||||||
|
// Check and resize if needed chain assets
|
||||||
|
const assetsPath = getChainAssetsPath(chain);
|
||||||
|
if (isPathExistsSync(assetsPath)) {
|
||||||
|
await bluebird.mapSeries(readDirSync(assetsPath), async asset => {
|
||||||
|
const path = getChainAssetLogoPath(chain, asset);
|
||||||
|
countChecked++;
|
||||||
|
countUpdated += await resizeIfTooLarge(path) ? 1 : 0;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check and resize if needed chain validators image
|
||||||
|
const chainValidatorsList = getChainValidatorsListPath(chain);
|
||||||
|
if (isPathExistsSync(chainValidatorsList)) {
|
||||||
|
const validatorsList = JSON.parse(readFileSync(getChainValidatorsListPath(chain)));
|
||||||
|
await bluebird.mapSeries(validatorsList, async ({ id }) => {
|
||||||
|
const path = getChainValidatorAssetLogoPath(chain, id);
|
||||||
|
countChecked++;
|
||||||
|
countUpdated += await resizeIfTooLarge(path) ? 1 : 0;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
totalCountChecked += countChecked;
|
||||||
|
totalCountUpdated += countUpdated;
|
||||||
|
if (countUpdated > 0) {
|
||||||
|
console.log(`Checking logos on chain ${chain} completed, ${countChecked} checked, ${countUpdated} logos updated`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(`Checking logos completed, ${totalCountChecked} logos checked, ${totalCountUpdated} logos updated`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fix() {
|
||||||
|
const foundChains = readDirSync(chainsPath);
|
||||||
|
await downsize(foundChains);
|
||||||
|
}
|
|
@ -1,13 +1,23 @@
|
||||||
const axios = require('axios')
|
import axios from "axios";
|
||||||
import {
|
import {
|
||||||
getChainValidatorsList,
|
validatorsList,
|
||||||
getChainValidatorsListPath,
|
getChainValidatorsPath,
|
||||||
Tezos,
|
getChainValidatorsListPath
|
||||||
writeJSONToPath
|
} from "../common/repo-structure";
|
||||||
} from "../src/test/helpers";
|
import { Tezos } from "../common/blockchains";
|
||||||
import { BakingBadBaker } from "../src/test/models";
|
import { readFileSync } from "../common/filesystem";
|
||||||
|
import { writeJsonFile } from "../common/json";
|
||||||
|
|
||||||
(async function(){
|
import {
|
||||||
|
BakingBadBaker,
|
||||||
|
ValidatorModel
|
||||||
|
} from "../../src/test/models";
|
||||||
|
|
||||||
|
function getChainValidatorsList(chain: string): ValidatorModel[] {
|
||||||
|
return JSON.parse(readFileSync(`${(getChainValidatorsPath(chain))}/${validatorsList}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gen_validators_tezos() {
|
||||||
const bakers: BakingBadBaker[] = await axios.get(`https://api.baking-bad.org/v2/bakers`).then(res => res.data)
|
const bakers: BakingBadBaker[] = await axios.get(`https://api.baking-bad.org/v2/bakers`).then(res => res.data)
|
||||||
const bakersMap: {[key: string]: BakingBadBaker} = bakers.reduce((acm, val) => {
|
const bakersMap: {[key: string]: BakingBadBaker} = bakers.reduce((acm, val) => {
|
||||||
acm[val.address] = val
|
acm[val.address] = val
|
||||||
|
@ -51,5 +61,9 @@ import { BakingBadBaker } from "../src/test/models";
|
||||||
return acm
|
return acm
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
writeJSONToPath(getChainValidatorsListPath(Tezos), newbakers)
|
writeJsonFile(getChainValidatorsListPath(Tezos), newbakers)
|
||||||
})()
|
}
|
||||||
|
|
||||||
|
export async function update() {
|
||||||
|
await gen_validators_tezos();
|
||||||
|
}
|
22
script/action/update-all.ts
Normal file
22
script/action/update-all.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import * as eth_forks from "./eth-forks";
|
||||||
|
import * as logo_size from "./logo-size";
|
||||||
|
import * as validators from "./validators";
|
||||||
|
import * as whitelists from "./whitelists";
|
||||||
|
import * as binance from "./binance";
|
||||||
|
import * as coinmarketcap from "../../pricing/coinmarketcap/script";
|
||||||
|
import * as tezos from "./tezos";
|
||||||
|
|
||||||
|
export function fixAll() {
|
||||||
|
console.log("Running fixes...");
|
||||||
|
eth_forks.fix();
|
||||||
|
logo_size.fix();
|
||||||
|
validators.fix();
|
||||||
|
whitelists.fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateAll() {
|
||||||
|
console.log("Running updates (using external data sources) ...");
|
||||||
|
tezos.update();
|
||||||
|
binance.update();
|
||||||
|
coinmarketcap.update();
|
||||||
|
}
|
14
script/action/validators.ts
Normal file
14
script/action/validators.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { stakingChains } from "../common/blockchains";
|
||||||
|
import { getChainValidatorsListPath } from "../common/repo-structure";
|
||||||
|
import { formatSortJsonFile } from "../common/json";
|
||||||
|
|
||||||
|
function formatValidators() {
|
||||||
|
stakingChains.forEach(chain => {
|
||||||
|
const validatorsPath = getChainValidatorsListPath(chain);
|
||||||
|
formatSortJsonFile(validatorsPath);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fix() {
|
||||||
|
formatValidators();
|
||||||
|
}
|
39
script/action/whitelists.ts
Normal file
39
script/action/whitelists.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { chainsWithBlacklist } from "../common/blockchains";
|
||||||
|
import { getChainAssetsList, getChainWhitelistPath, getChainBlacklistPath } from "../common/repo-structure";
|
||||||
|
import { readFileSync, writeFileSync } from "../common/filesystem";
|
||||||
|
import { sortElements, makeUnique, arrayDiff } from "../common/types";
|
||||||
|
|
||||||
|
function formatWhiteBlackList() {
|
||||||
|
chainsWithBlacklist.forEach(async chain => {
|
||||||
|
const assets = getChainAssetsList(chain);
|
||||||
|
|
||||||
|
const whitelistPath = getChainWhitelistPath(chain);
|
||||||
|
const blacklistPath = getChainBlacklistPath(chain);
|
||||||
|
|
||||||
|
const currentWhitelist = JSON.parse(readFileSync(whitelistPath));
|
||||||
|
const currentBlacklist = JSON.parse(readFileSync(blacklistPath));
|
||||||
|
|
||||||
|
let newBlackList = [];
|
||||||
|
// Some chains required pulling lists from other sources
|
||||||
|
// switch (chain) {
|
||||||
|
// case Ethereum:
|
||||||
|
// const nftList = await getOpenseaCollectionAddresses()
|
||||||
|
// newBlackList = currentBlacklist.concat(nftList)
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// newBlackList = newBlackList.concat(currentBlacklist)
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const removedAssets = arrayDiff(currentWhitelist, assets);
|
||||||
|
newBlackList = currentBlacklist.concat(removedAssets);
|
||||||
|
|
||||||
|
writeFileSync(whitelistPath, JSON.stringify(sortElements(assets), null, 4));
|
||||||
|
writeFileSync(blacklistPath, JSON.stringify(makeUnique(sortElements(newBlackList)), null, 4));
|
||||||
|
console.log(`Updated white and blacklists for chain ${chain}`);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fix() {
|
||||||
|
formatWhiteBlackList();
|
||||||
|
}
|
25
script/common/blockchains.ts
Normal file
25
script/common/blockchains.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { CoinType } from "@trustwallet/wallet-core";
|
||||||
|
|
||||||
|
export const getChainName = (id: CoinType): string => CoinType.id(id); // 60 => ethereum
|
||||||
|
export const Binance = getChainName(CoinType.binance);
|
||||||
|
export const Classic = getChainName(CoinType.classic);
|
||||||
|
export const Cosmos = getChainName(CoinType.cosmos);
|
||||||
|
export const Ethereum = getChainName(CoinType.ethereum);
|
||||||
|
export const GoChain = getChainName(CoinType.gochain);
|
||||||
|
export const IoTeX = getChainName(CoinType.iotex);
|
||||||
|
export const NEO = getChainName(CoinType.neo);
|
||||||
|
export const NULS = getChainName(CoinType.nuls);
|
||||||
|
export const POA = getChainName(CoinType.poa);
|
||||||
|
export const Tezos = getChainName(CoinType.tezos);
|
||||||
|
export const ThunderCore = getChainName(CoinType.thundertoken);
|
||||||
|
export const Terra = getChainName(CoinType.terra);
|
||||||
|
export const TomoChain = getChainName(CoinType.tomochain);
|
||||||
|
export const Tron = getChainName(CoinType.tron);
|
||||||
|
export const Kava = getChainName(CoinType.kava);
|
||||||
|
export const Wanchain = getChainName(CoinType.wanchain);
|
||||||
|
export const Waves = getChainName(CoinType.waves);
|
||||||
|
export const Solana = getChainName(CoinType.solana);
|
||||||
|
|
||||||
|
export const ethForkChains = [Ethereum, Classic, POA, TomoChain, GoChain, Wanchain, ThunderCore];
|
||||||
|
export const stakingChains = [Tezos, Cosmos, IoTeX, Tron, Waves, Kava, Terra];
|
||||||
|
export const chainsWithBlacklist = ethForkChains.concat(Tron, Terra, NEO, NULS);
|
15
script/common/config.ts
Normal file
15
script/common/config.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
const configFileName = "../config.json";
|
||||||
|
const configData = require(configFileName);
|
||||||
|
|
||||||
|
export function getConfig(key: string, defaultValue: any): any {
|
||||||
|
if (!configData) {
|
||||||
|
console.log(`Missing config, config file: ${configFileName}`);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
if (!(key in configData)) {
|
||||||
|
console.log(`Missing config entry, key ${key}, config file: ${configFileName}`);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return configData[key];
|
||||||
|
}
|
6
script/common/eth-web3.ts
Normal file
6
script/common/eth-web3.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
const Web3 = require('web3');
|
||||||
|
|
||||||
|
const web3 = new Web3('ws://localhost:8546');
|
||||||
|
|
||||||
|
export const isChecksum = (address: string): boolean => web3.utils.checkAddressChecksum(address);
|
||||||
|
export const toChecksum = (address: string): string => web3.utils.toChecksumAddress(address);
|
26
script/common/filesystem.ts
Normal file
26
script/common/filesystem.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
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 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;
|
||||||
|
|
||||||
|
export function execRename(command: string, cwd: string) {
|
||||||
|
console.log(`Running command ${command}`);
|
||||||
|
execSync(command, {encoding: "utf-8", cwd: cwd});
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
console.log(`Renaming file or folder at path ${path}: ${oldName} => ${newName}`);
|
||||||
|
execRename(gitMoveCommand(oldName, newName), path);
|
||||||
|
}
|
73
script/common/image.ts
Normal file
73
script/common/image.ts
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import * as sharp from "sharp";
|
||||||
|
import * as tinify from "tinify";
|
||||||
|
import * as image_size from "image-size";
|
||||||
|
import {
|
||||||
|
writeFileSync,
|
||||||
|
getFileSizeInKilobyte
|
||||||
|
} from "./filesystem";
|
||||||
|
import * as chalk from 'chalk';
|
||||||
|
import * as config from "../common/config";
|
||||||
|
|
||||||
|
//export const minLogoWidth = 64;
|
||||||
|
//export const minLogoHeight = 64;
|
||||||
|
export const maxLogoWidth = config.getConfig("image_max_logo_width", 512);
|
||||||
|
export const maxLogoHeight = config.getConfig("image_max_logo_height", 512);
|
||||||
|
export const maxLogoSizeInKilobyte = config.getConfig("image_logo_size_kb", 100);
|
||||||
|
|
||||||
|
export function isDimensionTooLarge(width: number, height: number): boolean {
|
||||||
|
return (width > maxLogoWidth) || (height > maxLogoHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateTargetSize(srcWidth: number, srcHeight: number, targetWidth: number, targetHeight: number): {width: number, height: number} {
|
||||||
|
if (srcWidth == 0 || srcHeight == 0) {
|
||||||
|
return {width: targetWidth, height: targetHeight};
|
||||||
|
}
|
||||||
|
const ratio = Math.min(targetWidth / srcWidth, targetHeight / srcHeight);
|
||||||
|
return {
|
||||||
|
width: Math.round(srcWidth * ratio),
|
||||||
|
height: Math.round(srcHeight * ratio)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const getImageDimensions = (path: string) => image_size.imageSize(path);
|
||||||
|
|
||||||
|
async function compressTinyPNG(path: string) {
|
||||||
|
console.log(`Compressing image via tinypng at path ${path}`);
|
||||||
|
const source = await tinify.fromFile(path);
|
||||||
|
await source.toFile(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if image updated
|
||||||
|
export async function resizeIfTooLarge(path: string): Promise<boolean> {
|
||||||
|
let updated: boolean = false;
|
||||||
|
|
||||||
|
const { width: srcWidth, height: srcHeight } = getImageDimensions(path);
|
||||||
|
if (isDimensionTooLarge(srcWidth, srcHeight)) {
|
||||||
|
const { width, height } = calculateTargetSize(srcWidth, srcHeight, maxLogoWidth, maxLogoHeight);
|
||||||
|
console.log(`Resizing image at ${path} from ${srcWidth}x${srcHeight} => ${width}x${height}`)
|
||||||
|
await sharp(path).resize(width, height).toBuffer()
|
||||||
|
.then(data => {
|
||||||
|
writeFileSync(path, data);
|
||||||
|
updated = true;
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.log(chalk.red(e.message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If file size > max limit, compress with tinypng
|
||||||
|
const sizeKilobyte = getFileSizeInKilobyte(path);
|
||||||
|
if (sizeKilobyte > maxLogoSizeInKilobyte) {
|
||||||
|
console.log(`Resizing image at path ${path} from ${sizeKilobyte} kB`);
|
||||||
|
await compressTinyPNG(path)
|
||||||
|
.then(() => {
|
||||||
|
updated = true;
|
||||||
|
console.log(`Resized image at path ${path} from ${sizeKilobyte} kB => ${getFileSizeInKilobyte(path)} kB`);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.log(chalk.red(e.message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated;
|
||||||
|
}
|
23
script/common/json.ts
Normal file
23
script/common/json.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import {
|
||||||
|
readFileSync,
|
||||||
|
writeFileSync
|
||||||
|
} from "./filesystem";
|
||||||
|
import { sortElements } from "./types";
|
||||||
|
|
||||||
|
export function formatJsonFile(filename: string, silent: boolean = false) {
|
||||||
|
const jsonContent = JSON.parse(readFileSync(filename));
|
||||||
|
writeFileSync(filename, JSON.stringify(jsonContent, null, 4));
|
||||||
|
if (!silent) {
|
||||||
|
console.log(`Formatted json file ${filename}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatSortJsonFile(filename: string) {
|
||||||
|
const jsonContent = JSON.parse(readFileSync(filename));
|
||||||
|
writeFileSync(filename, JSON.stringify(sortElements(jsonContent), null, 4));
|
||||||
|
console.log(`Formatted json file ${filename}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeJsonFile(path: string, data: any) {
|
||||||
|
writeFileSync(path, JSON.stringify(data, null, 4));
|
||||||
|
}
|
36
script/common/repo-structure.ts
Normal file
36
script/common/repo-structure.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import * as path from "path";
|
||||||
|
import {
|
||||||
|
isPathExistsSync,
|
||||||
|
readDirSync
|
||||||
|
} from "./filesystem";
|
||||||
|
|
||||||
|
export const logoName = `logo`;
|
||||||
|
export const infoName = `info`;
|
||||||
|
export const listName = `list`
|
||||||
|
export const logoExtension = "png";
|
||||||
|
export const jsonExtension = "json";
|
||||||
|
export const logoFullName = `${logoName}.${logoExtension}`;
|
||||||
|
export const infoFullName = `${infoName}.${jsonExtension}`;
|
||||||
|
const whiteList = `whitelist.${jsonExtension}`;
|
||||||
|
const blackList = `blacklist.${jsonExtension}`;
|
||||||
|
export const validatorsList = `${listName}.${jsonExtension}`
|
||||||
|
|
||||||
|
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 getChainAssetLogoPath = (chain: string, asset: string): string => `${getChainAssetPath(chain, asset)}/${logoFullName}`;
|
||||||
|
export const getChainAssetInfoPath = (chain: string, asset: string): string => `${getChainAssetPath(chain, asset)}/${infoFullName}`;
|
||||||
|
export const getChainWhitelistPath = (chain: string): string => `${getChainPath(chain)}/${whiteList}`;
|
||||||
|
export const getChainBlacklistPath = (chain: string): string => `${getChainPath(chain)}/${blackList}`;
|
||||||
|
|
||||||
|
export const getChainValidatorsPath = (chain: string): string => `${getChainPath(chain)}/validators`;
|
||||||
|
export const getChainValidatorsListPath = (chain: string): string => `${getChainValidatorsPath(chain)}/list.${jsonExtension}`;
|
||||||
|
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 getChainAssetsList = (chain: string): string[] => readDirSync(getChainAssetsPath(chain));
|
||||||
|
export const getChainAssetFilesList = (chain: string, address: string) => readDirSync(getChainAssetPath(chain, address));
|
29
script/common/types.ts
Normal file
29
script/common/types.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
export const mapList = arr => {
|
||||||
|
return arr.reduce((acm, val) => {
|
||||||
|
acm[val] = "";
|
||||||
|
return acm;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort: treat numbers as number, strings as case-insensitive
|
||||||
|
export const sortElements = (arr: any[]): any[] => {
|
||||||
|
arr.sort((a, b) => {
|
||||||
|
if (!isNaN(a) && !isNaN(b)) {
|
||||||
|
// numerical comparison
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
if ((typeof a === 'string' || a instanceof String) && (typeof b === 'string' || b instanceof String)) {
|
||||||
|
return a.toLowerCase() > b.toLowerCase() ? 1 : -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makeUnique = (arr: any[]): any[] => 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));
|
||||||
|
}
|
6
script/config.json
Normal file
6
script/config.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"image_max_logo_width": 512,
|
||||||
|
"image_max_logo_height": 512,
|
||||||
|
"image_logo_size_kb": 100,
|
||||||
|
"binance_assets_url": "https://explorer.binance.org/api/v1/assets?page=1&rows=1000"
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
import { ethSidechains, readDirSync, getChainAssetsPath } from "../src/test/helpers"
|
|
||||||
import { checksumAssetsFolder } from './format_files_name'
|
|
||||||
|
|
||||||
ethSidechains.forEach(chain => {
|
|
||||||
const chainAssetsPath = getChainAssetsPath(chain)
|
|
||||||
|
|
||||||
readDirSync(chainAssetsPath).forEach(addr => {
|
|
||||||
checksumAssetsFolder(chainAssetsPath, addr)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,42 +0,0 @@
|
||||||
import {
|
|
||||||
ethSidechains,
|
|
||||||
readDirSync,
|
|
||||||
getChainAssetsPath,
|
|
||||||
getChainAssetFilesList,
|
|
||||||
isChecksum,
|
|
||||||
toChecksum,
|
|
||||||
getFileName,
|
|
||||||
getFileExt,
|
|
||||||
getMoveCommandFromTo,
|
|
||||||
execRename,
|
|
||||||
logoName,
|
|
||||||
logoExtension,
|
|
||||||
logo,
|
|
||||||
getChainAssetPath
|
|
||||||
} from "../src/test/helpers"
|
|
||||||
|
|
||||||
ethSidechains.forEach(chain => {
|
|
||||||
const assetsPath = getChainAssetsPath(chain)
|
|
||||||
|
|
||||||
readDirSync(assetsPath).forEach(address => {
|
|
||||||
getChainAssetFilesList(chain, address).forEach(file => {
|
|
||||||
if (getFileName(file) == logoName && getFileExt(file) !== logoExtension) {
|
|
||||||
console.log(`Renaming incorrect asset logo extension ${file} ...`)
|
|
||||||
renameAndMove(getChainAssetPath(chain, address), file, logo)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
checksumAssetsFolder(assetsPath, address)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
export function checksumAssetsFolder(assetsFolderPath: string, addr: string) {
|
|
||||||
if (!isChecksum(addr)) {
|
|
||||||
renameAndMove(assetsFolderPath, addr, toChecksum(addr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renameAndMove(path: string, oldName: string, newName: string) {
|
|
||||||
console.log(` Renaming file or folder at path ${path}: ${oldName} => ${newName}`)
|
|
||||||
execRename(path, getMoveCommandFromTo(oldName, newName))
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
const fs = require('fs')
|
|
||||||
import { getOpenseaCollectionAddresses } from "./opesea_contrats"
|
|
||||||
|
|
||||||
import {
|
|
||||||
Ethereum, Terra, Tron,
|
|
||||||
getChainAssetInfoPath,
|
|
||||||
getChainAssetsList,
|
|
||||||
ethSidechains,
|
|
||||||
getChainBlacklistPath,
|
|
||||||
getChainValidatorsListPath,
|
|
||||||
getChainWhitelistPath,
|
|
||||||
getUnique,
|
|
||||||
isChainAssetInfoExistSync,
|
|
||||||
isChainBlacklistExistSync,
|
|
||||||
isChainWhitelistExistSync,
|
|
||||||
mapList,
|
|
||||||
readFileSync,
|
|
||||||
sortDesc,
|
|
||||||
stakingChains,
|
|
||||||
writeFileSync,
|
|
||||||
} from '../src/test/helpers'
|
|
||||||
|
|
||||||
formatWhiteBlackList()
|
|
||||||
formatValidators()
|
|
||||||
formatInfo()
|
|
||||||
|
|
||||||
function formatWhiteBlackList() {
|
|
||||||
ethSidechains.concat(Tron, Terra, "neo", 'nuls').forEach(async chain => {
|
|
||||||
const assets = getChainAssetsList(chain)
|
|
||||||
|
|
||||||
const whitelistPath = getChainWhitelistPath(chain)
|
|
||||||
const blacklistPath = getChainBlacklistPath(chain)
|
|
||||||
|
|
||||||
//Create inital lists if they do not exists
|
|
||||||
if (!isChainWhitelistExistSync(chain)) {
|
|
||||||
writeFileSync(whitelistPath, `[]`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isChainBlacklistExistSync(chain)) {
|
|
||||||
writeFileSync(blacklistPath, `[]`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentWhitelist = JSON.parse(readFileSync(whitelistPath))
|
|
||||||
const currentBlacklist = JSON.parse(readFileSync(blacklistPath))
|
|
||||||
|
|
||||||
let newBlackList = []
|
|
||||||
// Some chains required pulling lists from other sources
|
|
||||||
// switch (chain) {
|
|
||||||
// case Ethereum:
|
|
||||||
// const nftList = await getOpenseaCollectionAddresses()
|
|
||||||
// newBlackList = currentBlacklist.concat(nftList)
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// newBlackList = newBlackList.concat(currentBlacklist)
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
const removedAssets = getRemovedAddressesFromAssets(assets, currentWhitelist)
|
|
||||||
newBlackList = currentBlacklist.concat(removedAssets)
|
|
||||||
|
|
||||||
fs.writeFileSync(whitelistPath, JSON.stringify(sortDesc(assets), null, 4))
|
|
||||||
fs.writeFileSync(blacklistPath, JSON.stringify(getUnique(sortDesc(newBlackList)), null, 4))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatValidators() {
|
|
||||||
stakingChains.forEach(chain => {
|
|
||||||
const validatorsPath = getChainValidatorsListPath(chain)
|
|
||||||
const currentValidatorsList = JSON.parse(readFileSync(validatorsPath))
|
|
||||||
|
|
||||||
fs.writeFileSync(validatorsPath, JSON.stringify(currentValidatorsList, null, 4))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatInfo() {
|
|
||||||
ethSidechains.forEach(chain => {
|
|
||||||
const chainAssets = getChainAssetsList(chain)
|
|
||||||
chainAssets.forEach(address => {
|
|
||||||
if (isChainAssetInfoExistSync(chain, address)) {
|
|
||||||
const chainAssetInfoPath = getChainAssetInfoPath(chain, address)
|
|
||||||
const currentAssetInfo = JSON.parse(readFileSync(chainAssetInfoPath))
|
|
||||||
fs.writeFileSync(chainAssetInfoPath, JSON.stringify(currentAssetInfo, null, 4))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRemovedAddressesFromAssets(assets: string[], whiteList: string[]): string[] {
|
|
||||||
const mappedAssets = mapList(assets)
|
|
||||||
const removed = whiteList.filter(a => !mappedAssets.hasOwnProperty(a))
|
|
||||||
return removed
|
|
||||||
}
|
|
12
script/main/fix.ts
Normal file
12
script/main/fix.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { fixAll } from "../action/update-all";
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
try {
|
||||||
|
fixAll();
|
||||||
|
} catch(err) {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
12
script/main/update.ts
Normal file
12
script/main/update.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { updateAll } from "../action/update-all";
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
try {
|
||||||
|
updateAll();
|
||||||
|
} catch(err) {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
|
@ -1,101 +0,0 @@
|
||||||
import {
|
|
||||||
maxLogoWidth,
|
|
||||||
maxLogoHeight,
|
|
||||||
readDirSync,
|
|
||||||
chainsFolderPath,
|
|
||||||
getChainLogoPath,
|
|
||||||
calculateAspectRatioFit,
|
|
||||||
getImageDimensions,
|
|
||||||
getChainAssetsPath,
|
|
||||||
getChainAssetLogoPath,
|
|
||||||
isPathExistsSync,
|
|
||||||
writeFileSync,
|
|
||||||
readFileSync,
|
|
||||||
getChainValidatorsListPath,
|
|
||||||
getChainValidatorAssetLogoPath,
|
|
||||||
maxAssetLogoSizeInKilobyte,
|
|
||||||
getFileSizeInKilobyte
|
|
||||||
} from "../src/test/helpers"
|
|
||||||
const sharp = require('sharp')
|
|
||||||
const bluebird = require("bluebird")
|
|
||||||
const foundChains = readDirSync(chainsFolderPath)
|
|
||||||
const tinify = require("tinify");
|
|
||||||
tinify.key = "MXxhvmhjMkMM6CVccGrfyQm2RHpTf1G7"; // Key is free to get, gives 500 uploads per month
|
|
||||||
|
|
||||||
function downsize() {
|
|
||||||
console.log(`Start resizing`)
|
|
||||||
bluebird.map(foundChains, async chain => {
|
|
||||||
console.log(`Resizing assets on chain ${chain}`)
|
|
||||||
const chainLogoPath = getChainLogoPath(chain)
|
|
||||||
const { width: srcWidth, heigth: srcHeight } = getImageDimensions(chainLogoPath)
|
|
||||||
|
|
||||||
// Check and resize if needed chain logo
|
|
||||||
if (isDownsizing(srcWidth, srcHeight)) {
|
|
||||||
await resize(srcWidth, srcHeight, chainLogoPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check and resize if needed chain assets
|
|
||||||
const assetsPath = getChainAssetsPath(chain)
|
|
||||||
if (isPathExistsSync(assetsPath)) {
|
|
||||||
bluebird.mapSeries(readDirSync(assetsPath), async asset => {
|
|
||||||
const assetPath = getChainAssetLogoPath(chain, asset)
|
|
||||||
const { width: srcWidth, height: srcHeight } = getImageDimensions(assetPath)
|
|
||||||
if (isDownsizing(srcWidth, srcHeight)) {
|
|
||||||
await resize(srcWidth, srcHeight, assetPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If size still > max limit, compress with tinypng
|
|
||||||
const sizeKilobyte = getFileSizeInKilobyte(assetPath)
|
|
||||||
if (sizeKilobyte > maxAssetLogoSizeInKilobyte) {
|
|
||||||
await compressTinyPNG(assetPath)
|
|
||||||
console.log(`Successfully resized iamge at path ${assetPath} from ${sizeKilobyte} => ${getFileSizeInKilobyte(assetPath)}`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Check and resize if needed chain validators image
|
|
||||||
const chainValidatorsList = getChainValidatorsListPath(chain)
|
|
||||||
if (isPathExistsSync(chainValidatorsList)) {
|
|
||||||
const validatorsList = JSON.parse(readFileSync(getChainValidatorsListPath(chain)))
|
|
||||||
bluebird.mapSeries(validatorsList, async ({ id }) => {
|
|
||||||
const path = getChainValidatorAssetLogoPath(chain, id)
|
|
||||||
const { width: srcWidth, height: srcHeight } = getImageDimensions(path)
|
|
||||||
if (isDownsizing(srcWidth, srcHeight)) {
|
|
||||||
await resize(srcWidth, srcHeight, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If size still > max limit, compress with tinypng
|
|
||||||
const sizeKilobyte = getFileSizeInKilobyte(path)
|
|
||||||
if (sizeKilobyte > maxAssetLogoSizeInKilobyte) {
|
|
||||||
await compressTinyPNG(path)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(` Resizing assets on chain ${chain} completed`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
downsize()
|
|
||||||
|
|
||||||
function isDownsizing(srcWidth: number, srcHeight: number): boolean {
|
|
||||||
return (srcWidth > maxLogoWidth) || (srcHeight > maxLogoHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resize(srcWidth: number, srcHeight: number, path: string) {
|
|
||||||
const { width, height } = calculateAspectRatioFit(srcWidth, srcHeight, maxLogoWidth, maxLogoHeight)
|
|
||||||
console.log(` Resizing image at ${path} from ${srcWidth}x${srcHeight} => ${width}x${height}`)
|
|
||||||
await sharp(path).resize(width, height).toBuffer()
|
|
||||||
.then(data => writeFileSync(path, data))
|
|
||||||
.catch(e => {
|
|
||||||
console.log(e.message)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function compressTinyPNG(path: string) {
|
|
||||||
console.log(`Compressing image via tinypng at path ${path}`)
|
|
||||||
const source = await tinify.fromFile(path);
|
|
||||||
await source.toFile(path);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
const axios = require("axios")
|
|
||||||
const bluebird = require("bluebird")
|
|
||||||
const fs = require("fs")
|
|
||||||
const path = require("path")
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const blacklist = require('../blockchains/binance/blacklist.json')
|
|
||||||
|
|
||||||
;(async () => {
|
|
||||||
const { assetInfoList } = await axios.get(`https://explorer.binance.org/api/v1/assets?page=1&rows=1000`).then(r => r.data)
|
|
||||||
|
|
||||||
await bluebird.each(assetInfoList, async ({ asset, assetImg }) => {
|
|
||||||
if (assetImg && blacklist.indexOf(asset) == -1) {
|
|
||||||
const binanceDir = path.join(__dirname, `../blockchains/binance`)
|
|
||||||
const imagePath = `${binanceDir}/assets/${asset}/logo.png`
|
|
||||||
|
|
||||||
if (fs.existsSync(imagePath)) {
|
|
||||||
console.log(chalk.green(`${asset}`))
|
|
||||||
} else {
|
|
||||||
console.log(chalk.red(`${asset}`))
|
|
||||||
fs.mkdir(`${binanceDir}/assets/${asset}`, err => {
|
|
||||||
if (err && err.code != `EEXIST`) throw err
|
|
||||||
})
|
|
||||||
|
|
||||||
await fetchImage(assetImg).then(buffer => {
|
|
||||||
buffer.pipe(fs.createWriteStream(imagePath))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
function fetchImage(url) {
|
|
||||||
return axios.get(url, { responseType: "stream" }).then(r => r.data).catch(err => {
|
|
||||||
throw `Error fetchImage: ${url} ${err.message}`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})().catch(err => {
|
|
||||||
console.error(err)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
|
@ -318,6 +318,7 @@ export const rootDirAllowedFiles = [
|
||||||
"dapps",
|
"dapps",
|
||||||
"media",
|
"media",
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
"script-old",
|
||||||
"script",
|
"script",
|
||||||
"src",
|
"src",
|
||||||
".gitignore",
|
".gitignore",
|
||||||
|
|
|
@ -22,7 +22,6 @@ import {
|
||||||
getChainValidatorsList,
|
getChainValidatorsList,
|
||||||
findDuplicate,
|
findDuplicate,
|
||||||
findCommonElementOrDuplicate,
|
findCommonElementOrDuplicate,
|
||||||
isChecksum,
|
|
||||||
isLogoDimensionOK,
|
isLogoDimensionOK,
|
||||||
isLogoSizeOK,
|
isLogoSizeOK,
|
||||||
isLowerCase,
|
isLowerCase,
|
||||||
|
@ -32,7 +31,6 @@ import {
|
||||||
isValidJSON,
|
isValidJSON,
|
||||||
isAssetInfoOK,
|
isAssetInfoOK,
|
||||||
isValidatorHasAllKeys,
|
isValidatorHasAllKeys,
|
||||||
mapList,
|
|
||||||
pricingFolderPath,
|
pricingFolderPath,
|
||||||
readDirSync,
|
readDirSync,
|
||||||
readFileSync,
|
readFileSync,
|
||||||
|
@ -40,7 +38,23 @@ import {
|
||||||
stakingChains,
|
stakingChains,
|
||||||
} from "./helpers"
|
} from "./helpers"
|
||||||
import { ValidatorModel, mapTiker, TickerType } from "./models";
|
import { ValidatorModel, mapTiker, TickerType } from "./models";
|
||||||
import { getHandle } from "../../script/gen_info";
|
import { getHandle } from "../../script-old/gen_info";
|
||||||
|
|
||||||
|
import {
|
||||||
|
isChecksum,
|
||||||
|
toChecksum
|
||||||
|
} from "../../script/common/eth-web3";
|
||||||
|
import {
|
||||||
|
isDimensionTooLarge,
|
||||||
|
calculateTargetSize
|
||||||
|
} from "../../script/common/image";
|
||||||
|
import {
|
||||||
|
mapList,
|
||||||
|
sortElements,
|
||||||
|
makeUnique,
|
||||||
|
arrayDiff
|
||||||
|
} from "../../script/common/types";
|
||||||
|
import { findImagesToFetch } from "../../script/action/binance";
|
||||||
|
|
||||||
describe("Check repository root dir", () => {
|
describe("Check repository root dir", () => {
|
||||||
const dirActualFiles = readDirSync(".")
|
const dirActualFiles = readDirSync(".")
|
||||||
|
@ -459,3 +473,65 @@ describe("Test helper functions", () => {
|
||||||
expect(findCommonElementOrDuplicate([], []), `Empty lists`).toBe(null)
|
expect(findCommonElementOrDuplicate([], []), `Empty lists`).toBe(null)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Test eth-web3 helpers", () => {
|
||||||
|
test(`Test isChecksum`, () => {
|
||||||
|
expect(isChecksum("0x7Bb09bC8aDE747178e95B1D035ecBeEBbB18cFee"), `checksum`).toBe(true);
|
||||||
|
expect(isChecksum("0x7bb09bc8ade747178e95b1d035ecbeebbb18cfee"), `lowercase`).toBe(false);
|
||||||
|
expect(isChecksum("0x7Bb09bC8aDE747178e95B1D035ecBe"), `too short`).toBe(false);
|
||||||
|
});
|
||||||
|
test(`Test toChecksum`, () => {
|
||||||
|
expect(toChecksum("0x7bb09bc8ade747178e95b1d035ecbeebbb18cfee"), `from lowercase`).toEqual("0x7Bb09bC8aDE747178e95B1D035ecBeEBbB18cFee");
|
||||||
|
expect(toChecksum("0x7Bb09bC8aDE747178e95B1D035ecBeEBbB18cFee"), `from checksum`).toEqual("0x7Bb09bC8aDE747178e95B1D035ecBeEBbB18cFee");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Test image helpers", () => {
|
||||||
|
test(`Test isDimensionTooLarge`, () => {
|
||||||
|
expect(isDimensionTooLarge(256, 256), `256x256`).toBe(false);
|
||||||
|
expect(isDimensionTooLarge(64, 64), `64x64`).toBe(false);
|
||||||
|
expect(isDimensionTooLarge(800, 800), `800x800`).toBe(true);
|
||||||
|
expect(isDimensionTooLarge(256, 800), `256x800`).toBe(true);
|
||||||
|
expect(isDimensionTooLarge(800, 256), `800x256`).toBe(true);
|
||||||
|
});
|
||||||
|
test(`Test calculateReducedSize`, () => {
|
||||||
|
expect(calculateTargetSize(256, 256, 512, 512), `small 1.0`).toEqual({width: 512, height: 512});
|
||||||
|
expect(calculateTargetSize(800, 800, 512, 512), `large 1.0`).toEqual({width: 512, height: 512});
|
||||||
|
expect(calculateTargetSize(200, 100, 512, 512), `small 2.0`).toEqual({width: 512, height: 256});
|
||||||
|
expect(calculateTargetSize(100, 200, 512, 512), `small 0.5`).toEqual({width: 256, height: 512});
|
||||||
|
expect(calculateTargetSize(1200, 600, 512, 512), `small 2.0`).toEqual({width: 512, height: 256});
|
||||||
|
expect(calculateTargetSize(600, 1200, 512, 512), `small 0.5`).toEqual({width: 256, height: 512});
|
||||||
|
expect(calculateTargetSize(256, 0, 512, 512), `zero`).toEqual({width: 512, height: 512});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Test type helpers", () => {
|
||||||
|
test(`Test mapList`, () => {
|
||||||
|
expect(mapList(["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(["C", "a", "1", "b", "2", "11"]), `complex`).toEqual(["1", "2", "11", "a", "b", "C"]);
|
||||||
|
});
|
||||||
|
test(`Test makeUnique`, () => {
|
||||||
|
expect(makeUnique(["a", "b", "c", "b"]), `4 elems with 1 duplicate`).toEqual(["a", "b", "c"]);
|
||||||
|
});
|
||||||
|
test(`Test arrayDiff`, () => {
|
||||||
|
expect(arrayDiff(["a", "b", "c"], ["c"]), `4 elems with 1 duplicate`).toEqual(["a", "b"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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 blackListEmpty: string[] = [];
|
||||||
|
const blackListA1: string[] = ["A1"];
|
||||||
|
expect(findImagesToFetch(assetsInfoListNonexisting, blackListEmpty), `2 nonexisting`).toEqual(assetsInfoListNonexisting);
|
||||||
|
expect(findImagesToFetch(assetsInfoListNonexisting, blackListA1), `2 nonexisting with 1 blacklisted`).toEqual([{asset: "A2", assetImg: "imgurl2"}]);
|
||||||
|
expect(findImagesToFetch(assetsInfoListExisting, blackListEmpty), `2 existing`).toEqual([]);
|
||||||
|
expect(findImagesToFetch([], []), `empty`).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user