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: | ||||
|     push: | ||||
|       branches: | ||||
|  | @ -7,7 +7,7 @@ on: | |||
|     pull_request: | ||||
|       branches: [master] | ||||
| jobs: | ||||
|   fix-consistency: | ||||
|   scripts: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|      - uses: actions/checkout@v2 | ||||
|  | @ -16,12 +16,11 @@ jobs: | |||
|          node-version: 12 | ||||
|      - name: Install Dependencies | ||||
|        run: npm ci | ||||
|      - name: Run fix scripts | ||||
|        run: | | ||||
|          npm run resize | ||||
|          npm run format:all | ||||
|          npm run gen:list | ||||
|      - name: Run fix script | ||||
|        run: npm run fix | ||||
|      - name: Show git status (diff) | ||||
|        if: success() | ||||
|        run: git status | ||||
|      - name: Run test | ||||
|        run: npm t | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										12
									
								
								.github/workflows/fix.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/fix.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -3,23 +3,19 @@ on: | |||
|   push: | ||||
|     branches: [ master ] | ||||
| jobs: | ||||
|   fix-consistency: | ||||
|   scripts: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|      - uses: actions/checkout@v2 | ||||
|        with: | ||||
|          token: ${{ secrets.DANGER_GITHUB_API_TOKEN }} | ||||
|      - uses: actions/setup-node@v1 | ||||
|        with: | ||||
|          node-version: 12 | ||||
|      - name: Install Dependencies | ||||
|        run: npm ci | ||||
|      - name: Run fix scripts | ||||
|        run: | | ||||
|          npm run resize | ||||
|          npm run format:all | ||||
|          npm run gen:list | ||||
|      - name: Run fix script | ||||
|        run: npm run fix | ||||
|      - name: Show git status (diff) | ||||
|        if: success() | ||||
|        run: git status | ||||
|      - name: Run test | ||||
|        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) | ||||
|     - cron:  '0 7,19 * * *' | ||||
| jobs: | ||||
|   update: | ||||
|   scripts: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|      - uses: actions/checkout@v2 | ||||
|  | @ -17,10 +17,10 @@ jobs: | |||
|      - name: Install Dependencies | ||||
|        run: npm ci | ||||
|      - name: Run scripts | ||||
|        run: | | ||||
|          npm run gen:validators:tezos | ||||
|          npm run update:bep2 | ||||
|          npm run map:cmc | ||||
|        run: npm run update | ||||
|      - name: Show git status (diff) | ||||
|        if: success() | ||||
|        run: git status | ||||
|      - name: Run test | ||||
|        run: npm t | ||||
|      - name: Commit changes test pased | ||||
|  |  | |||
|  | @ -152,8 +152,8 @@ | |||
|     "TLyqzVGLV1srkB7dToTAEqgDSfPtXRJZYH", | ||||
|     "TMhjbHzJCiMWqa5oqn2DF3mGw5yh9oQNf2", | ||||
|     "TMwFHYXLJaRUPeW6421aqXL4ZEzPRFGkGT", | ||||
|     "TNZXVQUKQ8Gnjq2BqLvt2kC5WbeDQc1q3j", | ||||
|     "TNjt5fShPVJ4YpsLuU4THuBbg58g2bZoLk", | ||||
|     "TNZXVQUKQ8Gnjq2BqLvt2kC5WbeDQc1q3j", | ||||
|     "TPRuU2GbXPwvvSuggE4xKMRtzsfwYfvBWq", | ||||
|     "TQhfmGiZvRt3oe9vKv6W9WXRr4oErxc8RE", | ||||
|     "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", | ||||
|  |  | |||
							
								
								
									
										12
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
									
									
									
									
								
							|  | @ -5,16 +5,8 @@ | |||
|   "main": "index.js", | ||||
|   "scripts": { | ||||
|     "test": "jest", | ||||
|     "update:bep2": "node ./script/updateBEP2", | ||||
|     "checksum": "ts-node ./script/erc20_to_checksum", | ||||
|     "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" | ||||
|     "fix": "ts-node ./script/main/fix", | ||||
|     "update": "ts-node ./script/main/update" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| import { toChecksum } from "../../src/test/helpers" | ||||
| const BluebirbPromise = require("bluebird") | ||||
| const BluebirdPromise = require("bluebird") | ||||
| const axios = require("axios") | ||||
| const chalk = require('chalk') | ||||
| const fs = require("fs") | ||||
|  | @ -20,7 +20,7 @@ import { TickerType, mapTiker, PlatformType } from "../../src/test/models"; | |||
| // 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.
 | ||||
| // 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_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 bnbOriginalSymbolToSymbol = {} // e.g: WISH: WISH-2D5
 | ||||
| 
 | ||||
| run() | ||||
| async function run() { | ||||
|     try { | ||||
|         await Promise.all([initState(), setBinanceTokens()]) | ||||
|         const [totalCrypto, coins] = await Promise.all([getTotalActiveCryptocurrencies(), getTickers()]) | ||||
|         // setBIP44Constants()
 | ||||
|         log(`Found ${totalCrypto} on CMC`, chalk.yellowBright) | ||||
|         await BluebirbPromise.mapSeries(coins, processCoin) | ||||
|         await BluebirdPromise.mapSeries(coins, processCoin) | ||||
| 
 | ||||
|         addCustom() | ||||
|         printContracts() | ||||
|  | @ -351,4 +350,8 @@ function log(string, cb?) { | |||
| //             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 {  | ||||
|     getChainValidatorsList, | ||||
|     getChainValidatorsListPath, | ||||
|     Tezos,  | ||||
|     writeJSONToPath | ||||
| } from "../src/test/helpers"; | ||||
| import { BakingBadBaker } from "../src/test/models"; | ||||
| import axios from "axios"; | ||||
| import { | ||||
|     validatorsList, | ||||
|     getChainValidatorsPath, | ||||
|     getChainValidatorsListPath | ||||
| } from "../common/repo-structure"; | ||||
| import { Tezos } from "../common/blockchains"; | ||||
| 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 bakersMap: {[key: string]: BakingBadBaker} = bakers.reduce((acm, val) => { | ||||
|         acm[val.address] = val | ||||
|  | @ -51,5 +61,9 @@ import { BakingBadBaker } from "../src/test/models"; | |||
|         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", | ||||
|     "media", | ||||
|     "node_modules", | ||||
|     "script-old", | ||||
|     "script", | ||||
|     "src", | ||||
|     ".gitignore", | ||||
|  |  | |||
|  | @ -22,7 +22,6 @@ import { | |||
|     getChainValidatorsList, | ||||
|     findDuplicate, | ||||
|     findCommonElementOrDuplicate, | ||||
|     isChecksum, | ||||
|     isLogoDimensionOK, | ||||
|     isLogoSizeOK, | ||||
|     isLowerCase, | ||||
|  | @ -32,7 +31,6 @@ import { | |||
|     isValidJSON, | ||||
|     isAssetInfoOK, | ||||
|     isValidatorHasAllKeys, | ||||
|     mapList, | ||||
|     pricingFolderPath, | ||||
|     readDirSync, | ||||
|     readFileSync, | ||||
|  | @ -40,7 +38,23 @@ import { | |||
|     stakingChains, | ||||
| } from "./helpers" | ||||
| 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", () => { | ||||
|     const dirActualFiles = readDirSync(".") | ||||
|  | @ -459,3 +473,65 @@ describe("Test helper functions", () => { | |||
|         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
	 Adam R
						Adam R