├── .gitignore ├── .env.example ├── package.json ├── README.md ├── accountInfo.json ├── index.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .env 4 | dist -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | SENDER_WALLET_PRIVATE_KEY= 2 | RECEIVER_WALLET_PUBLIC_KEY= -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.ts", 3 | "scripts": { 4 | "build": "tsc", 5 | "start": "ts-node index.ts", 6 | "clean": "tsc --build --clean", 7 | "dev": "tsc && node ./dist/index.js" 8 | }, 9 | "dependencies": { 10 | "@project-serum/anchor": "^0.26.0", 11 | "@solana/spl-token": "^0.4.12", 12 | "@solana/web3.js": "^1.98.0", 13 | "bs58": "^6.0.0", 14 | "dotenv": "^16.4.7", 15 | "typescript": "^5.7.3" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^22.13.4", 19 | "ts-node": "^10.9.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solana Web3 guide project 2 | 3 | This project involves 3 main features - fetch information from various Solana Accounts, transfer SOL, transfer SPL Tokens. 4 | You can check branches for each feature. 5 | 6 | ### Step 1: Setup Environment 7 | - For convenience, let's develop our own code using VS Code. Let's assume that you have installed Node.js (version 18.0 or later). 8 | - Also, we need wallet A and wallet B. To be precise, to send money from wallet A to wallet B, you will need the private key of wallet A and the public key of wallet B. 9 | - Initialize your project using `npm init`. 10 | - Install dependencies using this command: 11 | ```bash 12 | npm install typescript ts-node @solana/web3.js @solana/spl-token dotenv bs58 13 | ``` 14 | - Check `package.json` file and edit script with Run commands. 15 | - Install Typescript environment using `tsc --init` command. 16 | - Edit `tsconfig.json` file like this: 17 | ```json 18 | { 19 | "compilerOptions": { 20 | "target": "es2016", 21 | "module": "commonjs", 22 | "outDir": "./dist", 23 | "esModuleInterop": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "strict": true, 26 | "skipLibCheck": true 27 | } 28 | } 29 | ``` 30 | - .env file 31 | ``` 32 | SENDER_WALLET_PRIVATE_KEY="PRIVATE KEY OF WALLET A" 33 | RECEIVER_WALLET_PUBLIC_KEY="PUBLIC KEY OF WALLET B" 34 | ``` 35 | --- 36 | ### **Step 2: Main code (index.ts)** 37 | You can check main code in index.ts file. 38 | 39 | --- 40 | 41 | ### **Step 3: Run the code** 42 | - In terminal, run this command: 43 | ```bash 44 | npm run start 45 | ``` 46 | - If the transaction is successful, you will receive a transaction link from solscan. 47 | 48 | --- 49 | 50 | ### **📧My contact info** 51 | **Gmail**: saivietthanh0314@gmail.com 52 | [**Telegram**](https://t.me/super_a_a) 53 | -------------------------------------------------------------------------------- /accountInfo.json: -------------------------------------------------------------------------------- 1 | Wallet Address: hYn1ZbfAdhSgwezgVADHR6nNzGWe7F71JGVdFvqk8L3 2 | 3 | Account Info: 4 | { 5 | "data": { 6 | "type": "Buffer", 7 | "data": [] 8 | }, 9 | "executable": false, 10 | "lamports": 101223209, 11 | "owner": "11111111111111111111111111111111", 12 | "rentEpoch": 18446744073709552000, 13 | "space": 0 14 | } 15 | 16 | 17 | Token 2022 Program Address: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb 18 | 19 | Account Info: 20 | { 21 | "data": { 22 | "type": "Buffer", 23 | "data": [ 24 | 2, 25 | 0, 26 | 0, 27 | 0, 28 | 190, 29 | 51, 30 | 145, 31 | 195, 32 | 15, 33 | 69, 34 | 134, 35 | 171, 36 | 198, 37 | 7, 38 | 157, 39 | 157, 40 | 157, 41 | 235, 42 | 231, 43 | 78, 44 | 23, 45 | 201, 46 | 236, 47 | 115, 48 | 99, 49 | 242, 50 | 110, 51 | 99, 52 | 253, 53 | 155, 54 | 110, 55 | 169, 56 | 190, 57 | 110, 58 | 86, 59 | ] 60 | }, 61 | "executable": true, 62 | "lamports": 1141440, 63 | "owner": "BPFLoaderUpgradeab1e11111111111111111111111", 64 | "rentEpoch": 18446744073709552000, 65 | } 66 | 67 | 68 | Mint Account Address: C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR (Devnet) 69 | 70 | Account Info: 71 | { 72 | "data": { 73 | "type": "Buffer", 74 | "data": [ 75 | 1, 76 | 0, 77 | 0, 78 | 0, 79 | 44, 80 | 91, 81 | ... 82 | 106, 83 | 115, 84 | 111, 85 | 110, 86 | 0, 87 | 0, 88 | 0, 89 | 0 90 | ] 91 | }, 92 | "executable": false, 93 | "lamports": 15024176000, 94 | "owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", 95 | "rentEpoch": 18446744073709552000, 96 | "space": 430 97 | } 98 | 99 | 100 | Deserialized Mint Info: C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR (Devnet) 101 | 102 | { 103 | "address": "C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR", 104 | "mintAuthority": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R", 105 | "supply": "0", 106 | "decimals": 2, 107 | "isInitialized": true, 108 | "freezeAuthority": null, 109 | "tlvData": { 110 | "type": "Buffer", 111 | "data": [ 112 | 18, 113 | 0, 114 | 64, 115 | 0, 116 | 44, 117 | 91, 118 | 144, 119 | ... 120 | 115, 121 | 111, 122 | 110, 123 | 0, 124 | 0, 125 | 0, 126 | 0 127 | ] 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | import bs58 from "bs58"; 3 | import { 4 | LAMPORTS_PER_SOL, 5 | Transaction, 6 | SystemProgram, 7 | sendAndConfirmTransaction, 8 | Keypair, 9 | Connection, 10 | PublicKey, 11 | clusterApiUrl, 12 | ComputeBudgetProgram, 13 | TransactionMessage, 14 | VersionedTransaction, 15 | TransactionInstruction 16 | } from "@solana/web3.js"; 17 | import { 18 | createMint, 19 | getOrCreateAssociatedTokenAccount, 20 | getAssociatedTokenAddressSync, 21 | mintTo, 22 | getMint, 23 | createTransferInstruction, 24 | TOKEN_PROGRAM_ID, 25 | TOKEN_2022_PROGRAM_ID, 26 | ASSOCIATED_TOKEN_PROGRAM_ID, 27 | getAssociatedTokenAddress, 28 | createTransferCheckedInstruction, 29 | } from "@solana/spl-token"; 30 | import { BN } from "@project-serum/anchor"; 31 | 32 | dotenv.config(); 33 | 34 | // Keys from .env 35 | const fromWalletPrivateKeyString = process.env 36 | .SENDER_WALLET_PRIVATE_KEY as string; 37 | const receiverPublicKeyString = process.env 38 | .RECEIVER_WALLET_PUBLIC_KEY as string; 39 | 40 | const fromWallet = Keypair.fromSecretKey(bs58.decode(fromWalletPrivateKeyString)); 41 | const toWalletPublicKey = new PublicKey(receiverPublicKeyString); 42 | 43 | // transferSplToken function 44 | async function transferSplToken(mint:PublicKey, transferAmount: number, network: string = "mainnet") { 45 | let connection: Connection; 46 | if (network === "mainnet") { 47 | connection = new Connection("https://api.mainnet-beta.solana.com"); 48 | } else { 49 | connection = new Connection(clusterApiUrl("devnet"), "confirmed"); 50 | } 51 | // Check fromWallet balance 52 | const fromWalletBalance = await connection.getBalance(fromWallet.publicKey); 53 | console.log("From Wallet Balance:", fromWalletBalance / LAMPORTS_PER_SOL, "SOL"); 54 | 55 | if (fromWalletBalance < 0.01 * LAMPORTS_PER_SOL) { 56 | throw new Error("From wallet does not have enough SOL to pay for transaction fees."); 57 | } 58 | 59 | const accountInfo = await connection.getAccountInfo(mint); 60 | const tokenProgramID = accountInfo?.owner; 61 | console.log("Token ProgramID", tokenProgramID); 62 | 63 | // Get token mint info (including decimals) 64 | const mintInfo = await getMint( 65 | connection, 66 | mint, 67 | "confirmed", 68 | tokenProgramID // TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID 69 | ); 70 | console.log("Token Decimals:", mintInfo); 71 | 72 | console.log("ASSOCIATED_TOKEN_PROGRAM_ID: ", ASSOCIATED_TOKEN_PROGRAM_ID); 73 | 74 | // Get the token account of the fromWall address, if it doesn't exist, create it 75 | const fromTokenAccount = await getOrCreateAssociatedTokenAccount( 76 | connection, 77 | fromWallet, 78 | mint, 79 | fromWallet.publicKey, 80 | false, 81 | undefined, 82 | undefined, 83 | tokenProgramID, // TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID 84 | ASSOCIATED_TOKEN_PROGRAM_ID 85 | ); 86 | 87 | //get the token account of the toWallet address, if it does not exist, create it 88 | const toTokenAccount = await getOrCreateAssociatedTokenAccount( 89 | connection, 90 | fromWallet, // payer 91 | mint, 92 | toWalletPublicKey, 93 | false, 94 | undefined, 95 | undefined, 96 | tokenProgramID, // TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID 97 | ASSOCIATED_TOKEN_PROGRAM_ID 98 | ); 99 | 100 | console.log ("fromTokenAccount::", fromTokenAccount.toString()); 101 | 102 | // Check the balance of the fromTokenAccount 103 | const fromTokenAccountBalance = await connection.getTokenAccountBalance(fromTokenAccount.address); 104 | console.log("From Token Account Balance:", fromTokenAccountBalance.value.uiAmount, "tokens"); 105 | 106 | // Ensure the fromTokenAccount has enough tokens for the transfer 107 | // const transferAmount = 0.1; // Adjust this value based on the token's decimals 108 | if (fromTokenAccountBalance.value.uiAmount === null || fromTokenAccountBalance.value.uiAmount < transferAmount) { 109 | throw new Error("Insufficient funds in the fromTokenAccount."); 110 | } 111 | 112 | // // Token Transfer Instruction 113 | let transferInstruction: TransactionInstruction; 114 | 115 | if(String(tokenProgramID) == String(TOKEN_PROGRAM_ID)){ 116 | transferInstruction = createTransferInstruction( 117 | fromTokenAccount.address, 118 | toTokenAccount.address, 119 | fromWallet.publicKey, 120 | transferAmount * Math.pow(10, mintInfo.decimals) 121 | ); 122 | } else { 123 | //tokenProgramID == TOKEN_2022_PROGRAM_ID 124 | transferInstruction = createTransferCheckedInstruction( 125 | fromTokenAccount.address, 126 | mint, 127 | toTokenAccount.address, 128 | fromWallet.publicKey, 129 | new BN(transferAmount * Math.pow(10, mintInfo.decimals)), 130 | mintInfo.decimals, 131 | [], 132 | TOKEN_2022_PROGRAM_ID 133 | ); 134 | } 135 | 136 | // Priority fee instruction 137 | const PRIORITY_FEE_MICRO_LAMPORTS = 200000; // 0.2 lamports per compute unit (adjust as needed) 138 | // Instruction to set the compute unit price for priority fee 139 | const PRIORITY_FEE_INSTRUCTIONS = ComputeBudgetProgram.setComputeUnitPrice({microLamports: PRIORITY_FEE_MICRO_LAMPORTS}); 140 | 141 | // Fetch a fresh blockhash 142 | const latestBlockhash = await connection.getLatestBlockhash(); 143 | 144 | // Compiles and signs the transaction message with the sender's Keypair. 145 | const messageV0 = new TransactionMessage({ 146 | payerKey: fromWallet.publicKey, 147 | recentBlockhash: latestBlockhash.blockhash, 148 | instructions: [PRIORITY_FEE_INSTRUCTIONS, transferInstruction], 149 | }).compileToV0Message(); 150 | 151 | const versionedTransaction = new VersionedTransaction(messageV0); 152 | 153 | // Sign transaction, broadcast, and confirm 154 | versionedTransaction.sign([fromWallet]); 155 | 156 | // Attempts to send the transaction to the network, handling success or failure. 157 | try { 158 | const transactionSignature = await connection.sendTransaction(versionedTransaction, { 159 | maxRetries: 20, 160 | }); 161 | 162 | const confirmation = await connection.confirmTransaction( 163 | { 164 | signature: transactionSignature, 165 | blockhash: latestBlockhash.blockhash, 166 | lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, 167 | }, 168 | "confirmed" 169 | ); 170 | if (confirmation.value.err) { 171 | throw new Error("🚨Transaction not confirmed."); 172 | } 173 | 174 | if(network === "mainnet"){ 175 | console.log( 176 | "Transaction Signature: ", 177 | `https://solscan.io/tx/${transactionSignature}` 178 | ); 179 | } else { 180 | console.log( 181 | "Transaction Signature: ", 182 | `https://solscan.io/tx/${transactionSignature}?cluster=devnet` 183 | ); 184 | } 185 | 186 | } catch (error) { 187 | console.error("Transaction failed", error); 188 | } 189 | } 190 | 191 | // Test 192 | let mint: PublicKey; // Mint Account Address (Token Address) 193 | mint = new PublicKey("C8NEYcW7eoQsrQ7vqeiUTLFxwJQNHgj8LwSc3BUQx6YG"); // Devnet SPL Token 194 | transferSplToken(mint, 1000000, "devnet"); 195 | 196 | mint = new PublicKey("13pkrcqF47rF2oF4kZnBVzH5omQ2f7nF429vzpjgL896"); // Devnet Token2022 SPL Token 197 | transferSplToken(mint, 1000000, "devnet"); 198 | 199 | mint = new PublicKey("7WphEnjwKtWWMbb7eEVYeLDNN2jodCo871tVt8jHpump"); // Mainnet SPL Token 200 | transferSplToken(mint, 10, "mainnet"); 201 | 202 | mint = new PublicKey("HeLp6NuQkmYB4pYWo2zYs22mESHXPQYzXbB8n4V98jwC"); // Mainnet Token2022 SPL Token 203 | transferSplToken(mint, 0.05, "mainnet"); -------------------------------------------------------------------------------- /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 legacy experimental 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": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* 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 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ 40 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 41 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 42 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 43 | // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ 44 | // "resolveJsonModule": true, /* Enable importing .json files. */ 45 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 46 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 47 | 48 | /* JavaScript Support */ 49 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 50 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 51 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 52 | 53 | /* Emit */ 54 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 55 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 56 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 57 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "noEmit": true, /* Disable emitting files from a compilation. */ 60 | // "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. */ 61 | "outDir": "./dist", /* Specify an output folder for all emitted files. */ 62 | // "removeComments": true, /* Disable emitting comments. */ 63 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 64 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 65 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 66 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 67 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 68 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 69 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 70 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 71 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 72 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 73 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 74 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 75 | 76 | /* Interop Constraints */ 77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 79 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ 80 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 81 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 82 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 83 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 84 | 85 | /* Type Checking */ 86 | "strict": true, /* Enable all strict type-checking options. */ 87 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 88 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 89 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 90 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 91 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 92 | // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ 93 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 94 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 95 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 96 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 97 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 98 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 99 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 100 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 101 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 102 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 103 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 104 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 105 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 106 | 107 | /* Completeness */ 108 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 109 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 110 | } 111 | } 112 | --------------------------------------------------------------------------------