├── run-ts.sh ├── .vscode └── settings.json ├── src ├── constants.ts ├── main.ts └── fetchZksync.ts ├── .gitignore ├── README.md ├── package.json └── tsconfig.json /run-ts.sh: -------------------------------------------------------------------------------- 1 | ts-node -T src/main.ts 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.linting.enabled": true 3 | } -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | 2 | export const PadWechatKey = 'xxxx' // iPad 微信登录接口 token,申请地址:http://pad-local.com/#/login 3 | export const TargetWeixinName = '名字' //你要通知的微信用户昵称 4 | export const TargetWallet = 'xxxxx' //需要监听的钱包地址 5 | export const NomicsAPIKey = 'xxxxxx' //api.nomics.com 自己申请 Key,申请地址:https://p.nomics.com/cryptocurrency-bitcoin-api 6 | export const BaseCurrencySymbol = 'ETH' //最后结算到币本位 or U本位,方便查看总资产是否亏损。可以填写 USD\EUR\CNY 或任何加密货币的 symbol -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | *.swp 10 | 11 | pids 12 | logs 13 | results 14 | tmp 15 | 16 | # Build 17 | public/css/main.css 18 | 19 | # Coverage reports 20 | coverage 21 | 22 | # API keys and secrets 23 | .env 24 | 25 | # Dependency directory 26 | node_modules 27 | bower_components 28 | 29 | # Editors 30 | .idea 31 | *.iml 32 | 33 | # OS metadata 34 | .DS_Store 35 | Thumbs.db 36 | 37 | # Ignore built ts files 38 | dist/**/* 39 | 40 | # ignore yarn.lock 41 | yarn.lock -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zigzag_wechat_bot 2 | 3 | ## 功能 4 | 1. 每隔6.5s 监控做市机器人接单情况,如有新单,会立刻微信通知 5 | 6 | 2. 通过微信远程执行操作,包括当前运行状态、重启做市程序、查看 pm2 list、查看实时微信机器人日志 7 | 8 | 9 | ## 注意事项 10 | 1. ZigZag 做市程序请参考 https://github.com/ZigZagExchange/market-maker 部署。 11 | 2. 需要使用 pm2 开启上面的做市程序 12 | 3. 前往 `constants.ts` 填入自己的配置 13 | 4. 需要 iPad 微信机器人key,前往 http://pad-local.com/#/login 申请 14 | 5. 需要实时币价接口 Key,前往 https://p.nomics.com/cryptocurrency-bitcoin-api 申请 15 | 6. 执行 `pm2 start src/main.ts` 开启微信机器人 16 | 7. 若上述方法不行,可以执行 `pm2 start run-ts.sh` 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "new-ts-bot", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "keywords": [], 7 | "author": "", 8 | "license": "ISC", 9 | "dependencies": { 10 | "node-fetch": "^2.6.7", 11 | "qrcode-terminal": "^0.12.0", 12 | "wechaty": "^1.20.2", 13 | "wechaty-puppet": "^1.20.1", 14 | "wechaty-puppet-padlocal": "^1.11.18" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "^17.0.40", 18 | "@types/react": "^18.0.12", 19 | "@types/request": "^2.48.8", 20 | "cross-env": "^7.0.3", 21 | "ts-node": "^10.7.0", 22 | "typescript": "^4.7.3" 23 | }, 24 | "scripts": { 25 | "bot": "npx ts-node src/main.ts", 26 | "bot-esm": "cross-env NODE_OPTIONS=\"--no-warnings --loader=ts-node/esm\" node src/main.ts" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { Contact, log, ScanStatus, WechatyBuilder } from "wechaty"; 2 | import { PuppetPadlocal } from "wechaty-puppet-padlocal"; 3 | import * as FetchZksync from "./fetchZksync"; 4 | import * as Constant from "./constants"; 5 | 6 | export const LOGPRE = "[cypto_bot]"; 7 | const puppet = new PuppetPadlocal({ 8 | token: Constant.PadWechatKey, 9 | }); 10 | const bot = WechatyBuilder.build({ 11 | name: "cypto_bot", 12 | puppet, 13 | }); 14 | 15 | //与命令行 shell 交互 16 | const exec = require('child_process').exec; 17 | 18 | let _owner: Contact; 19 | export const getOwner = async () => 20 | _owner || 21 | (_owner = (await bot.Contact.find({ name: Constant.TargetWeixinName })) as Contact); 22 | 23 | bot 24 | .on("scan", async (qrcode, status) => { 25 | if (status === ScanStatus.Waiting && qrcode) { 26 | const qrcodeImageUrl = [ 27 | "https://wechaty.js.org/qrcode/", 28 | encodeURIComponent(qrcode), 29 | ].join(""); 30 | log.info( 31 | LOGPRE, 32 | `onScan: ${ScanStatus[status]}(${status}) - ${qrcodeImageUrl}` 33 | ); 34 | require("qrcode-terminal").generate(qrcode, { small: true }); // show qrcode on console 35 | } else { 36 | log.info(LOGPRE, `onScan: ${ScanStatus[status]}(${status})`); 37 | } 38 | }) 39 | .on("login", async (user) => { 40 | console.log("name:", user.name); 41 | 42 | const owner = await getOwner(); 43 | if (!owner) return; 44 | 45 | owner.say(`${user}已登录 iPad 版`); 46 | log.info(LOGPRE, `${user} login`); 47 | 48 | //1. 先获取货币信息 49 | FetchZksync.fetchTokenInfo(); 50 | 51 | //2. 定时爬取接口 52 | const callback = (message: string) => { 53 | owner.say(message); 54 | }; 55 | const hello = () => { 56 | FetchZksync.hello(callback); 57 | }; 58 | setInterval(hello, 6500); // 每隔6.5s轮询 59 | }) 60 | .on("logout", async (user, reason) => { 61 | const owner = await getOwner(); 62 | if (!owner) return; 63 | 64 | owner.say(`${user}已退出 iPad 版`); 65 | log.info(LOGPRE, `${user} logout, reason: ${reason}`); 66 | }) 67 | .on("message", async (message) => { 68 | const owner = await getOwner(); 69 | if (message.listener()?.self() && message.text() === '状态') { 70 | var isOnNodeJs = false; 71 | if (typeof process != 'undefined') { 72 | isOnNodeJs = true 73 | } 74 | await owner.say(`${isOnNodeJs ? "🟢 正在运行" : "🔴 程序停止"}`); 75 | } else if (message.listener()?.self() && message.text() === '重启') { 76 | exec('pm2 restart /root/cypto_bot/run-ts.sh',(error: any, stdout: any, stderr: any) => { 77 | console.log(stdout); 78 | if (stdout !== null) { 79 | owner.say(stdout); 80 | } 81 | console.log(stderr); 82 | if (error !== null) { 83 | console.log(`exec error: ${error}`); 84 | } 85 | }); 86 | } else if (message.listener()?.self() && message.text() === 'list') { 87 | exec('pm2 jlist',(error:any, stdout:any, stderr:any) => { 88 | 89 | if (stdout !== null) { 90 | let json = JSON.parse(stdout) 91 | var output = "" 92 | for(var index in json) { 93 | let value = json[index] 94 | console.log("value:",value) 95 | let name = value["name"] 96 | let status = value["pm2_env"]["status"] //"online" 97 | let mem = `${Number(value["monit"]["memory"]) / 1024 / 1024}MB` 98 | let cpu = `${Number(value["monit"]["cpu"])}%` 99 | output += `${name}-${status}-${mem}-${cpu}\n` 100 | } 101 | owner.say(output); 102 | } 103 | console.log(stderr); 104 | if (error !== null) { 105 | console.log(`exec error: ${error}`); 106 | } 107 | }); 108 | } else if (message.listener()?.self() && message.text() === 'log') { 109 | exec('pm2 logs run-ts --nostream --lines 5',(error:any, stdout:any, stderr:any) => { 110 | if (stdout !== null) { 111 | owner.say(stdout); 112 | } 113 | console.log(stderr); 114 | if (error !== null) { 115 | console.log(`exec error: ${error}`); 116 | } 117 | }); 118 | } else if (message.listener()?.self() && message.text() === 'cmd') { 119 | owner.say('状态\n重启\nlist\nlog'); 120 | } 121 | }) 122 | .on("error", (error) => { 123 | log.error(LOGPRE, `on error: ${error}`); 124 | }); 125 | 126 | bot.start().then(() => { 127 | log.info(LOGPRE, "started."); 128 | }); 129 | -------------------------------------------------------------------------------- /src/fetchZksync.ts: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch"); 2 | import * as Constant from "./constants"; 3 | 4 | // 获取所有 token 信息 5 | let tokenInfo: { [x: string]: any }; 6 | let balances_str = ""; 7 | export async function fetchTokenInfo() { 8 | fetch("https://api.zksync.io/jsrpc", { 9 | headers: { 10 | accept: "application/json, text/plain, */*", 11 | "accept-language": "zh-CN,zh;q=0.9", 12 | "content-type": "application/json", 13 | "sec-fetch-dest": "empty", 14 | "sec-fetch-mode": "cors", 15 | "sec-fetch-site": "cross-site", 16 | "sec-gpc": "1", 17 | Referer: "https://zkscan.io/", 18 | "Referrer-Policy": "strict-origin-when-cross-origin", 19 | }, 20 | body: '{"id":1,"jsonrpc":"2.0","method":"tokens","params":null}', 21 | method: "POST", 22 | }) 23 | .then((response: { json: () => any }) => response.json()) 24 | .then((json: { [x: string]: {} }) => { 25 | tokenInfo = json["result"]; 26 | }) 27 | .catch((error: any) => console.log("error", error)); 28 | } 29 | 30 | let lastNonce = 0; 31 | let all_coin_to_eth_price = 0 //所有币价转换到 eth 的总和,用 eth 衡量总资产 32 | export function hello(callback: (message: string) => void) { 33 | // 获取余额 34 | let balances_raw: { [x: string]: any } = {}; 35 | let balances: { [x: string]: any } = {}; 36 | let hasNewTransition = false; 37 | fetch("https://api.zksync.io/jsrpc", { 38 | headers: { 39 | accept: "application/json, text/plain, */*", 40 | "accept-language": "zh-CN,zh;q=0.9", 41 | "content-type": "application/json", 42 | "sec-fetch-dest": "empty", 43 | "sec-fetch-mode": "cors", 44 | "sec-fetch-site": "cross-site", 45 | "sec-gpc": "1", 46 | Referer: "https://zkscan.io/", 47 | "Referrer-Policy": "strict-origin-when-cross-origin", 48 | }, 49 | body: `{"id":1,"jsonrpc":"2.0","method":"account_info","params":[${Constant.TargetWallet}]}`, 50 | method: "POST", 51 | }) 52 | .then((response: { json: () => any }) => response.json()) 53 | .then((json: { [x: string]: { [x: string]: { [x: string]: any } } }) => { 54 | let newNonce = json["result"]["committed"]["nonce"]; 55 | if (newNonce > lastNonce) { 56 | lastNonce = newNonce; 57 | hasNewTransition = true; 58 | balances_raw = json["result"]["committed"]["balances"]; 59 | balances_str = ""; 60 | for (let key in balances_raw) { 61 | let token_balance = balances_raw[key]; 62 | let token_info = tokenInfo[key]; 63 | let decimals = token_info["decimals"]; 64 | let symbol = token_info["symbol"]; 65 | /* 66 | AAVE 0.12451426904 67 | AVAX 0.4980558464 68 | */ 69 | let price = token_balance / 10 ** decimals 70 | balances_str += ` ${symbol}: ${price}\n`; 71 | balances[symbol] = price 72 | } 73 | } else { 74 | hasNewTransition = false; 75 | } 76 | }) 77 | .then(async () => { 78 | // 获取最新市场价格 79 | let eth_coin_sbls: any = Object.keys(balances) 80 | eth_coin_sbls = eth_coin_sbls.join(',') 81 | 82 | fetch(`https://api.nomics.com/v1/currencies/ticker?key=${Constant.NomicsAPIKey}&ids=${eth_coin_sbls}&interval=1h&convert=${Constant.BaseCurrencySymbol}&per-page=100&page=1`) 83 | .then((response: any) => response.json()) 84 | .then((json: { [x: string]: {} }) => { 85 | // console.log("获取最新市场价格:", json) 86 | var to_eth: { [id: string] : String; } = {}; 87 | for (let index in json) { 88 | let pair:{ [id: string] : String; } = json[index] 89 | let key = String(pair["symbol"]) 90 | to_eth[key] = pair["price"] 91 | } 92 | // console.log("获取最新市场价格dict:\n",to_eth) 93 | 94 | all_coin_to_eth_price = 0 95 | for (let key in balances) { 96 | let value = balances[key] //0.0001 SOL 97 | let toETHPrice = to_eth[key] // 1sol : 0.0012eth 98 | let resultETHPrice = Number(value) * Number(toETHPrice) 99 | all_coin_to_eth_price += resultETHPrice 100 | } 101 | 102 | if (hasNewTransition) { 103 | console.log("发现新交易!"); 104 | getTransition(callback); 105 | } else { 106 | console.log("无新交易"); 107 | } 108 | }) 109 | }) 110 | .catch((error: any) => console.log("error", error)); 111 | } 112 | 113 | // 获取最新交易 114 | function getTransition(callback: (message: string) => void) { 115 | return fetch( 116 | `https://api.zksync.io/api/v0.1/account/${Constant.TargetWallet}/history/0/10`, 117 | { 118 | headers: { 119 | accept: "application/json, text/plain, */*", 120 | "accept-language": "zh-CN,zh;q=0.9", 121 | "sec-fetch-dest": "empty", 122 | "sec-fetch-mode": "cors", 123 | "sec-fetch-site": "cross-site", 124 | "sec-gpc": "1", 125 | Referer: "https://zkscan.io/", 126 | "Referrer-Policy": "strict-origin-when-cross-origin", 127 | }, 128 | body: null, 129 | method: "GET", 130 | } 131 | ) 132 | .then((response: { json: () => any }) => response.json()) 133 | .then((json: any[]) => { 134 | let firstObj = json[0]; 135 | let tx = firstObj["tx"]; 136 | let type = tx["type"]; 137 | let fee = tx["fee"]; 138 | let feeToken_id = tx["feeToken"]; 139 | let nonce = tx["nonce"]; 140 | console.log("nonce:", nonce); 141 | let ordes = tx["orders"]; 142 | let to_object = ordes.find( 143 | (o: { [x: string]: any }) => o["nonce"] === nonce 144 | ); 145 | 146 | let from_object = ordes.find( 147 | (o: { [x: string]: any }) => o["tokenBuy"] === to_object["tokenSell"] 148 | ); 149 | 150 | let from_addr = from_object["recipient"]; 151 | let to_addr = to_object["recipient"]; 152 | let from_amount = from_object["amount"]; 153 | let to_amount = to_object["amount"]; 154 | let from_token_id = from_object["tokenSell"]; 155 | let to_token_id = to_object["tokenSell"]; 156 | 157 | // /1000000 158 | // /1000000000000000000 159 | 160 | let fee_str = null; 161 | let from_amount_str = null; 162 | let to_amount_str = null; 163 | for (let key in tokenInfo) { 164 | let value = tokenInfo[key]; 165 | let id = value["id"]; 166 | if (id == feeToken_id) { 167 | let decimals = value["decimals"]; 168 | let symbol = value["symbol"]; 169 | fee_str = `【fee】: ${fee / 10 ** decimals} ${symbol}`; 170 | } 171 | 172 | if (id == from_token_id) { 173 | let decimals = value["decimals"]; 174 | let symbol = value["symbol"]; 175 | from_amount_str = `${from_amount / 10 ** decimals} ${symbol}`; 176 | } 177 | 178 | if (id == to_token_id) { 179 | let decimals = value["decimals"]; 180 | let symbol = value["symbol"]; 181 | to_amount_str = `${to_amount / 10 ** decimals} ${symbol}`; 182 | } 183 | 184 | if ( 185 | fee_str != null && 186 | from_amount_str != null && 187 | to_amount_str != null 188 | ) { 189 | break; 190 | } 191 | } 192 | 193 | let state_str = `${firstObj["success"] ? "成功" : "失败"} | ${ 194 | firstObj["verified"] ? "已确认" : "未确认" 195 | } | ${firstObj["commited"] ? "已提交" : "未提交"} | ${ 196 | firstObj["fail_reason"] 197 | }`; 198 | let nonce_str = `【nonce】: ${lastNonce}`; 199 | let from_str = `【from】: ${from_addr}`; 200 | let to_str = `【to】: ${to_addr}`; 201 | let amount_str = `【Amount】: ${from_amount_str} -> ${to_amount_str}`; 202 | let final_balances_str = `【余额】:{\n${balances_str}}`; 203 | let all_eth = `【总资产】:${all_coin_to_eth_price} ETH` 204 | 205 | let message = `🍻检测到新交易:${type}\n${state_str}\n${nonce_str}\n${from_str}\n${to_str}\n${amount_str}\n${fee_str}\n${final_balances_str}\n${all_eth}`; 206 | // console.log("最终输出结果:", message); 207 | 208 | callback(message); 209 | 210 | /* 211 | 检测到新交易:Swap 212 | 状态:成功 | 已确认 213 | nonce: 45 214 | from: 0x3df204d52430315c9b56bbe22b6e9c2f1f9b37f7 215 | to: 自己 216 | Amount: 217 | fee: 0.306 USDT 218 | 余额: { 219 | AAVE 0.12451426904 220 | AVAX 0.4980558464 221 | DAI 0.08157772 222 | ETH 0.016354639445 223 | SOL 1.451859896 224 | UNI 3.957894376 225 | USDC 0.252422 226 | USDT 709.223038 227 | } 228 | 总资产: 0.5 ETH 229 | */ 230 | }) 231 | .catch((error: any) => console.log("error", error)); 232 | } 233 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | "rootDir": "./src", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | "outDir": "./dist", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | --------------------------------------------------------------------------------