├── .env.example ├── .gitignore ├── package.json ├── README.md ├── LICENSE ├── tutorial-2.ts ├── tutorial-3.ts ├── tutorial-1.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | PIMLICO_API_KEY= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pimlico-tutorials", 3 | "version": "1.0.0", 4 | "description": "A repository containing the full code for the Pimlico tutorials (https://docs.pimlico.io/permissionless)", 5 | "main": "index.ts", 6 | "type": "module", 7 | "scripts": { 8 | "tutorial-1": "tsx tutorial-1.ts", 9 | "tutorial-2": "tsx tutorial-2.ts", 10 | "tutorial-3": "tsx tutorial-3.ts" 11 | }, 12 | "author": "", 13 | "license": "MIT", 14 | "dependencies": { 15 | "dotenv": "^16.3.1", 16 | "permissionless": "0.2.0-rc-5", 17 | "viem": "2.20.0" 18 | }, 19 | "devDependencies": { 20 | "@types/node": "^20.11.0", 21 | "tsx": "^3.13.0" 22 | } 23 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pimlico Tutorials 2 | 3 | This repository contains the full code for [Pimlico tutorials](https://docs.pimlico.io/tutorial) in the Pimlico documentation. 4 | 5 | To set up the repository, clone it, copy the .env.example file to .env and fill in your Pimlico API key (use the [quick start guide](https://docs.pimlico.io/how-to/quick-start) to generate one), install the dependencies, and run `npm run tutorial-1`! 6 | 7 | If you are looking to run the tutorial code for [tutorial 2](https://docs.pimlico.io/tutorial/tutorial-2), in addition to filling the Pimlico API key, you will also need to generate a private key and replace the `privateKey` variable at the start of `tutorial-2.ts` with it before running `npm run tutorial-2`. 8 | 9 | ```bash 10 | npm install 11 | cp .env.example .env 12 | # fill in your Pimlico API key in .env 13 | npm run tutorial-1 14 | ``` 15 | 16 | If everything works correctly, you should deploy a User Operation as per the flow of the tutorial. 17 | 18 | Good luck! 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Pimlico 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /tutorial-2.ts: -------------------------------------------------------------------------------- 1 | import "dotenv/config"; 2 | import { createSmartAccountClient } from "permissionless"; 3 | import { toSafeSmartAccount } from "permissionless/accounts"; 4 | import { createPimlicoClient } from "permissionless/clients/pimlico"; 5 | import { 6 | createPublicClient, 7 | getAddress, 8 | Hex, 9 | http, 10 | maxUint256, 11 | parseAbi, 12 | } from "viem"; 13 | import { 14 | entryPoint07Address, 15 | EntryPointVersion, 16 | } from "viem/account-abstraction"; 17 | import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; 18 | import { baseSepolia } from "viem/chains"; 19 | import { writeFileSync } from "fs"; 20 | 21 | const usdc = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; 22 | const paymaster = "0x0000000000000039cd5e8ae05257ce51c473ddd1"; 23 | 24 | const apiKey = process.env.PIMLICO_API_KEY; 25 | const pimlicoUrl = `https://api.pimlico.io/v2/${baseSepolia.id}/rpc?apikey=${apiKey}`; 26 | 27 | const privateKey = 28 | (process.env.PRIVATE_KEY as Hex) ?? 29 | (() => { 30 | const pk = generatePrivateKey(); 31 | writeFileSync(".env", `PRIVATE_KEY=${pk}`); 32 | return pk; 33 | })(); 34 | 35 | const publicClient = createPublicClient({ 36 | chain: baseSepolia, 37 | transport: http("https://sepolia.base.org"), 38 | }); 39 | 40 | const pimlicoClient = createPimlicoClient({ 41 | chain: baseSepolia, 42 | transport: http(pimlicoUrl), 43 | entryPoint: { 44 | address: entryPoint07Address, 45 | version: "0.7" as EntryPointVersion, 46 | }, 47 | }); 48 | 49 | const account = await toSafeSmartAccount({ 50 | client: publicClient, 51 | owners: [privateKeyToAccount(privateKey)], 52 | version: "1.4.1", 53 | }); 54 | 55 | const smartAccountClient = createSmartAccountClient({ 56 | account, 57 | chain: baseSepolia, 58 | bundlerTransport: http(pimlicoUrl), 59 | paymaster: pimlicoClient, 60 | userOperation: { 61 | estimateFeesPerGas: async () => { 62 | return (await pimlicoClient.getUserOperationGasPrice()).fast; 63 | }, 64 | }, 65 | }); 66 | 67 | console.log( 68 | `Smart account address: https://sepolia.basescan.org/address/${account.address}`, 69 | ); 70 | 71 | const senderUsdcBalance = await publicClient.readContract({ 72 | abi: parseAbi(["function balanceOf(address account) returns (uint256)"]), 73 | address: usdc, 74 | functionName: "balanceOf", 75 | args: [account.address], 76 | }); 77 | 78 | if (senderUsdcBalance < 1_000_000n) { 79 | throw new Error( 80 | `insufficient USDC balance for counterfactual wallet address ${account.address}: ${ 81 | Number(senderUsdcBalance) / 1_000_000 82 | } USDC, required at least 1 USDC. Load up balance at https://faucet.circle.com/`, 83 | ); 84 | } 85 | 86 | let txHash = await smartAccountClient.sendTransaction({ 87 | calls: [ 88 | { 89 | to: getAddress(usdc), 90 | abi: parseAbi(["function approve(address,uint)"]), 91 | functionName: "approve", 92 | args: [paymaster, maxUint256], 93 | }, 94 | { 95 | to: getAddress("0xd8da6bf26964af9d7eed9e03e53415d37aa96045"), 96 | data: "0x1234" as Hex, 97 | }, 98 | ], 99 | paymasterContext: { 100 | token: usdc, 101 | }, 102 | }); 103 | 104 | console.log(`transactionHash: ${txHash}`); 105 | -------------------------------------------------------------------------------- /tutorial-3.ts: -------------------------------------------------------------------------------- 1 | import "dotenv/config" 2 | import { writeFileSync } from "fs" 3 | import { createSmartAccountClient } from "permissionless" 4 | import { toSafeSmartAccount } from "permissionless/accounts" 5 | import { createPimlicoClient } from "permissionless/clients/pimlico" 6 | import { Hex, createPublicClient, encodeFunctionData, http, parseAbiItem } from "viem" 7 | import { entryPoint07Address } from "viem/account-abstraction" 8 | import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" 9 | import { sepolia } from "viem/chains" 10 | 11 | const erc20PaymasterAddress = "0x000000000041F3aFe8892B48D88b6862efe0ec8d" as const 12 | const usdcAddress = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" 13 | 14 | const privateKey = 15 | (process.env.PRIVATE_KEY as Hex) ?? 16 | (() => { 17 | const pk = generatePrivateKey() 18 | writeFileSync(".env", `PRIVATE_KEY=${pk}`) 19 | return pk 20 | })() 21 | 22 | const publicClient = createPublicClient({ 23 | chain: sepolia, 24 | transport: http("https://rpc.ankr.com/eth_sepolia"), 25 | }) 26 | 27 | const apiKey = process.env.PIMLICO_API_KEY // REPLACE THIS 28 | const pimlicoUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}` 29 | 30 | const pimlicoClient = createPimlicoClient({ 31 | transport: http(pimlicoUrl), 32 | entryPoint: { 33 | address: entryPoint07Address, 34 | version: "0.7", 35 | }, 36 | }) 37 | 38 | const account = await toSafeSmartAccount( { 39 | client: publicClient, 40 | owner: privateKeyToAccount(privateKey), 41 | version: "1.4.1", 42 | setupTransactions: [ 43 | { 44 | to: usdcAddress, 45 | value: 0n, 46 | data: encodeFunctionData({ 47 | abi: [parseAbiItem("function approve(address spender, uint256 amount)")], 48 | args: [ 49 | erc20PaymasterAddress, 50 | 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn, 51 | ], 52 | }), 53 | }, 54 | ], 55 | }) 56 | 57 | console.log(`Smart account address: https://sepolia.etherscan.io/address/${account.address}`) 58 | 59 | const senderUsdcBalance = await publicClient.readContract({ 60 | abi: [parseAbiItem("function balanceOf(address account) returns (uint256)")], 61 | address: usdcAddress, 62 | functionName: "balanceOf", 63 | args: [account.address], 64 | }) 65 | 66 | if (senderUsdcBalance < 1_000_000n) { 67 | throw new Error( 68 | `insufficient USDC balance for counterfactual wallet address ${account.address}: ${ 69 | Number(senderUsdcBalance) / 1000000 70 | } USDC, required at least 1 USDC. Load up balance at https://faucet.circle.com/`, 71 | ) 72 | } 73 | 74 | console.log(`Smart account USDC balance: ${Number(senderUsdcBalance) / 1000000} USDC`) 75 | 76 | const smartAccountClient = createSmartAccountClient({ 77 | client: publicClient, 78 | account, 79 | chain: sepolia, 80 | bundlerTransport: http(pimlicoUrl), 81 | paymaster: { 82 | async getPaymasterData(parameters) { 83 | const gasEstimates = await pimlicoClient.estimateUserOperationGas({ 84 | ...parameters, 85 | paymaster: erc20PaymasterAddress, 86 | }) 87 | return { 88 | paymaster: erc20PaymasterAddress, 89 | paymasterData: "0x" as Hex, 90 | paymasterPostOpGasLimit: gasEstimates.paymasterPostOpGasLimit ?? 0n, 91 | paymasterVerificationGasLimit: gasEstimates.paymasterVerificationGasLimit ?? 0n, 92 | } 93 | }, 94 | async getPaymasterStubData(parameters) { 95 | const gasEstimates = await pimlicoClient.estimateUserOperationGas({ 96 | ...parameters, 97 | paymaster: erc20PaymasterAddress 98 | }) 99 | return { 100 | paymaster: erc20PaymasterAddress, 101 | paymasterData: "0x" as Hex, 102 | paymasterPostOpGasLimit: gasEstimates.paymasterPostOpGasLimit ?? 0n, 103 | paymasterVerificationGasLimit: gasEstimates.paymasterVerificationGasLimit ?? 0n 104 | } 105 | } 106 | }, 107 | userOperation: { 108 | estimateFeesPerGas: async () => { 109 | return (await pimlicoClient.getUserOperationGasPrice()).fast 110 | }, 111 | } 112 | }) 113 | 114 | const txHash = await smartAccountClient.sendTransaction({ 115 | to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", 116 | value: 0n, 117 | data: "0x1234", 118 | }) 119 | 120 | console.log(`User operation included: https://sepolia.etherscan.io/tx/${txHash}`) 121 | -------------------------------------------------------------------------------- /tutorial-1.ts: -------------------------------------------------------------------------------- 1 | import "dotenv/config" 2 | import { writeFileSync } from "fs" 3 | import { toSafeSmartAccount } from "permissionless/accounts" 4 | import { Hex, createPublicClient, getContract, http } from "viem" 5 | import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" 6 | import { sepolia } from "viem/chains" 7 | import { createPimlicoClient } from "permissionless/clients/pimlico" 8 | import { createBundlerClient, entryPoint07Address } from "viem/account-abstraction" 9 | import { createSmartAccountClient } from "permissionless" 10 | 11 | const apiKey = process.env.PIMLICO_API_KEY 12 | if (!apiKey) throw new Error("Missing PIMLICO_API_KEY") 13 | 14 | const privateKey = 15 | (process.env.PRIVATE_KEY as Hex) ?? 16 | (() => { 17 | const pk = generatePrivateKey() 18 | writeFileSync(".env", `PRIVATE_KEY=${pk}`) 19 | return pk 20 | })() 21 | 22 | export const publicClient = createPublicClient({ 23 | chain: sepolia, 24 | transport: http("https://rpc.ankr.com/eth_sepolia"), 25 | }) 26 | 27 | const account = await toSafeSmartAccount({ 28 | client: publicClient, 29 | owner: privateKeyToAccount(privateKey), 30 | entryPoint: { 31 | address: entryPoint07Address, 32 | version: "0.7" 33 | }, // global entrypoint 34 | version: "1.4.1", 35 | }) 36 | 37 | console.log({ 38 | accountAddress: await account.getAddress(), 39 | }) 40 | 41 | console.log(`Smart account address: https://sepolia.etherscan.io/address/${account.address}`) 42 | 43 | const pimlicoUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}` 44 | 45 | const pimlicoClient = createPimlicoClient({ 46 | transport: http(pimlicoUrl), 47 | entryPoint: { 48 | address: entryPoint07Address, 49 | version: "0.7", 50 | } 51 | }) 52 | 53 | { 54 | const smartAccountClient = createSmartAccountClient({ 55 | account, 56 | chain: sepolia, 57 | bundlerTransport: http(pimlicoUrl), 58 | paymaster: pimlicoClient, 59 | userOperation: { 60 | estimateFeesPerGas: async () => { 61 | return (await pimlicoClient.getUserOperationGasPrice()).fast 62 | }, 63 | } 64 | }) 65 | 66 | const txHash = await smartAccountClient.sendTransaction({ 67 | to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", 68 | value: 0n, 69 | data: "0x1234", 70 | 71 | }) 72 | 73 | console.log(`User operation with single transaction included: https://sepolia.etherscan.io/tx/${txHash}`) 74 | 75 | const contract = getContract({ 76 | address: "0x6D7A849791a8E869892f11E01c2A5f3b25a497B6", 77 | abi: [{"inputs":[],"name":"getLastGreeter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"greet","outputs":[],"stateMutability":"nonpayable","type":"function"}], 78 | client: { 79 | public: publicClient, 80 | wallet: smartAccountClient, 81 | } 82 | }) 83 | 84 | const txHash2 = await contract.write.greet() 85 | 86 | console.log(`User operation with contract call included: https://sepolia.etherscan.io/tx/${txHash2}`) 87 | 88 | const txHashMultiple = await smartAccountClient.sendTransaction({ 89 | calls: [ 90 | { 91 | to: "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", 92 | value: 0n, 93 | data: "0x1234", 94 | }, 95 | { 96 | abi: [{"inputs":[],"name":"getLastGreeter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"greet","outputs":[],"stateMutability":"nonpayable","type":"function"}], 97 | functionName: "greet", 98 | args: [], 99 | to: "0x6D7A849791a8E869892f11E01c2A5f3b25a497B6" 100 | } 101 | ], 102 | }) 103 | 104 | console.log(`User operation with multiple transactions included: https://sepolia.etherscan.io/tx/${txHashMultiple}`) 105 | } 106 | 107 | { 108 | const bundlerClient = createBundlerClient({ 109 | account, 110 | chain: sepolia, 111 | transport: http(pimlicoUrl), 112 | paymaster: pimlicoClient, 113 | userOperation: { 114 | estimateFeesPerGas: async () => { 115 | return (await pimlicoClient.getUserOperationGasPrice()).fast 116 | }, 117 | } 118 | }) 119 | 120 | const userOpHash = await bundlerClient.sendUserOperation({ 121 | calls: [{ 122 | to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", 123 | value: 0n, 124 | data: "0x1234", 125 | }] 126 | }) 127 | 128 | const receipt = await bundlerClient.waitForUserOperationReceipt({ 129 | hash: userOpHash, 130 | }) 131 | 132 | console.log(`User operation included: https://sepolia.etherscan.io/tx/${receipt.receipt.transactionHash}`) 133 | 134 | const txHashMultiple = await bundlerClient.sendUserOperation({ 135 | calls: [ 136 | { 137 | to: "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", 138 | value: 0n, 139 | data: "0x1234", 140 | }, 141 | { 142 | to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", 143 | value: 0n, 144 | data: "0x1234", 145 | } 146 | ], 147 | }) 148 | 149 | const receipt2 = await bundlerClient.getUserOperationReceipt({ 150 | hash: txHashMultiple, 151 | }) 152 | 153 | console.log(`User operation included: https://sepolia.etherscan.io/tx/${receipt2.receipt.transactionHash}`) 154 | } 155 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | /* Projects */ 5 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 6 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 7 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 8 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 9 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 10 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 11 | /* Language and Environment */ 12 | "target": "ES2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 13 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 14 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 15 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 16 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 17 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 18 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 19 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 20 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 21 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 22 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 23 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 24 | /* Modules */ 25 | "module": "ES2022", /* Specify what module code is generated. */ 26 | // "rootDir": "./", /* Specify the root folder within your source files. */ 27 | "moduleResolution": "Node", /* Specify how TypeScript looks up a file from a given module specifier. */ 28 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 29 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 30 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 31 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 32 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 33 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 34 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 35 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 36 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 37 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 38 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 39 | // "resolveJsonModule": true, /* Enable importing .json files. */ 40 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 41 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 42 | /* JavaScript Support */ 43 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 44 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 45 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 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 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 52 | // "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. */ 53 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 54 | // "removeComments": true, /* Disable emitting comments. */ 55 | // "noEmit": true, /* Disable emitting files from a compilation. */ 56 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 57 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 58 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 59 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 60 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 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 | /* Interop Constraints */ 71 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 72 | // "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. */ 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 | /* Type Checking */ 78 | "strict": true, /* Enable all strict type-checking options. */ 79 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 80 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 81 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 82 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 83 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 84 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 85 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 86 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 87 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 88 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 89 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 90 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 91 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 92 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 93 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 94 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 95 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 96 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | }, 101 | } --------------------------------------------------------------------------------