├── .gitignore ├── .npmignore ├── README.md ├── TUTORIAL.md ├── build-docs.sh ├── lib └── index.ts ├── package-lock.json ├── package.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | docs/ -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | node_modules/ 3 | tsconfig.json 4 | doc/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Discreet Log Contracts Oracle library (NodeJS) 2 | 3 | This library allows you to easily build oracles for use in Discreet Log Contracts using NodeJS. 4 | 5 | For a step-by-step instruction on how to build an oracle using this library, please see [TUTORIAL.md](TUTORIAL.md) 6 | 7 | See [the examples repository](https://github.com/mit-dci/dlc-oracle-nodejs-samples) for examples using this library. Feel free to contribute any examples you created by submitting a pull request to the samples repository. 8 | 9 | You can find the documentation to the library [here](https://docs.mitdci.org/dlc-oracle-nodejs/classes/_index_.dlcoracle.html) -------------------------------------------------------------------------------- /TUTORIAL.md: -------------------------------------------------------------------------------- 1 | # Building a Discreet Log Contract Oracle in NodeJS 2 | 3 | In 2017, [Tadge Dryja](https://twitter.com/tdryja) published a [paper](https://adiabat.github.io/dlc.pdf) on Discreet Log Contracts. 4 | 5 | By creating a Discreet Log Contract, Alice can form a contract paying Bob some time in the future, based on preset conditions, without committing any details of those conditions to the blockchain. Therefore it is discreet in the sense that no external observer can learn its existence from the public ledger. This contract depends on an external entity or entities publishing a signed message at some point in the future (before the expiration of the contract). The contents of this signed message determine the division of the funds committed to the contract. This external entity is called an “oracle”. Using Discreet Log Contracts, the signature published by the oracle gives each participant of the contract the possibility to claim the amount from the contract that is due him without the need for cooperation from the other party. 6 | 7 | This tutorial will describe you how to build a Discreet Log Contract "oracle". This tutorial describes how to do this in NodeJS, but you can also use [Go](https://github.com/mit-dci/dlc-oracle-go/blob/master/TUTORIAL.md) or [.NET Core](https://github.com/mit-dci/dlc-oracle-dotnet/blob/master/TUTORIAL.md) 8 | 9 | ### Set up a new project 10 | 11 | Firstly, set up a new empty project and include the correct libraries. We start by creating the project folder and add the main program file to it. 12 | 13 | ```bash 14 | cd ~ 15 | mkdir tutorial 16 | cd tutorial 17 | npm init 18 | npm install --save dlc-oracle-nodejs 19 | touch index.js 20 | ``` 21 | 22 | Next, open the file `index.js` in your favorite editor, and add this to it: 23 | 24 | ```javascript 25 | function main() { 26 | 27 | } 28 | 29 | main(); 30 | ``` 31 | 32 | ### Generate and save the oracle's private key 33 | 34 | Next, we'll need to have a private key. This private key is used in conjunction with a unique one-time-signing key for each message. The private key of the oracle never changes, and its public key is incorporated into Discreet Log Contracts that people form. So if we lose access to this key, people's contracts might be unable to settle. In this example, we'll store the key in a simple format on disk. This is not secure, and should not be considered for production scenarios. However, to illustrate the working of the library it is sufficient. 35 | 36 | So we add this function to the `index.js` file: 37 | 38 | ```javascript 39 | function getOrCreateKey() { 40 | let key; 41 | let keyFile = path.join(__dirname,"privkey.hex"); 42 | if(fs.existsSync(keyFile)) { 43 | key = fs.readFileSync(keyFile); 44 | } else { 45 | key = randomBytes(32); 46 | fs.writeFileSync(keyFile, privateKey); 47 | } 48 | return key; 49 | } 50 | ``` 51 | 52 | and then we adjust the `main()` function to use it, add a global variable to keep the key in, and add the necessary imports: 53 | 54 | ```javascript 55 | const randomBytes = require('crypto').randomBytes; 56 | const fs = require('fs'); 57 | const path = require('path'); 58 | 59 | let privateKey; 60 | (...) 61 | 62 | function main() { 63 | privateKey = getOrCreateKey(); 64 | } 65 | 66 | main(); 67 | ``` 68 | 69 | ### Derive and print out the public key 70 | 71 | Next, we'll use the DLC library to generate the public key from the private key and print it out to the console: 72 | 73 | ```javascript 74 | (...) 75 | const DlcOracle = require('dlc-oracle-nodejs').DlcOracle; 76 | 77 | (...) 78 | 79 | function main() { 80 | (...) 81 | 82 | let publicKey = DlcOracle.publicKeyFromPrivateKey(privateKey); 83 | console.log("Oracle Public Key: ",publicKey.toString('hex')); 84 | 85 | } 86 | 87 | (...) 88 | ``` 89 | 90 | In your terminal window, run the application: 91 | 92 | ```bash 93 | node index.js 94 | ``` 95 | 96 | The program should show an output similar to this: 97 | 98 | ``` 99 | Oracle Public Key: 03c0d496ef6656fe102a689abc162ceeae166832d826f8750c94d797c92eedd465 100 | ``` 101 | 102 | ### Create a loop that publishes oracle values 103 | 104 | Next, we'll add a loop to the oracle that will take the following steps: 105 | 106 | * Generate a new one-time signing key 107 | * Print out the public key to that signing key (the "R Point") 108 | * Wait 1 minute 109 | * Sign a random numerical value with the one-time key 110 | * Print out the value and signature 111 | 112 | Using the oracle's public key and the "R Point" (public key to the one-time signing key), people can use LIT to form a Discreet Log Contract, and use your signature when you publish it to settle the contract. 113 | 114 | So for a regular DLC use case, you would publish your oracle's public key and the R-point for each time / value you will publish onto a website or some other form of publication, so that people can obtain the keys and use them in their contracts. When the time arrives you have determined the correct value, and sign it, you publish both the value and your signature so the contract participants can use those values to settle the contract. 115 | 116 | As for the one-time signing key, this has the same security requirements as the oracle's private key. If this key is lost, contracts that depend on it cannot be settled. It is therefore important to save this key somewhere safe. Just keeping it in memory as we do in this example is not good practice for production scenarios. 117 | 118 | One last note on the one-time signing key: The reason that it's named this, is that you can only use it once. Even though there's no technical limitation of you producing two signatures with that key, doing so using the signature scheme DLC uses will allow people to derive your oracle's private key from the data you published. 119 | 120 | OK, back to the code. So, first we add the generation of the one-time signing key and printing out the corresponding public key (R Point). 121 | 122 | ```javascript 123 | (...) 124 | 125 | let oneTimeSigningKey; 126 | 127 | (...) 128 | 129 | func main() { 130 | (...) 131 | generateAndPrintKey(); 132 | } 133 | 134 | function generateAndPrintKey() { 135 | oneTimeSigningKey = DlcOracle.generateOneTimeSigningKey(); 136 | let rPoint = DlcOracle.publicKeyFromPrivateKey(oneTimeSigningKey); 137 | console.log("R-Point for next publication: ",rPoint.toString('hex')); 138 | } 139 | 140 | (...) 141 | ``` 142 | 143 | Go ahead and run it again. You'll see an output similar to this: 144 | 145 | ``` 146 | Oracle Public Key: 03c0d496ef6656fe102a689abc162ceeae166832d826f8750c94d797c92eedd465 147 | R-Point for next publication: 02b46b8e2d1976b1d0f9734617a166165b8d19c7a053159dfe838c5edaeb57c2c7 148 | ``` 149 | 150 | Next step is to actually generate a random value and sign it after waiting for a minute. This wait period is to simulate the time between announcing your public keys and publishing the actual value. In this time people will form contracts that use the values. 151 | 152 | If you want to wait less than a minute, decrease the 60000 (millisecond) value passed to `setTimeout`. 153 | 154 | Using the DLC library, signing values is quite easy: 155 | 156 | ```javascript 157 | (...) 158 | 159 | 160 | function generateAndPrintKey() { 161 | (...) 162 | setTimeout(() => { signValueAndPrint(); }, 60000); 163 | } 164 | 165 | function signValueAndPrint() { 166 | // Generate a random number between 10000-20000 167 | let value = Math.floor(Math.random() * 10000) + 10000; 168 | 169 | // Generate message to sign. Uses the same encoding as expected by LIT when settling the contract 170 | let message = DlcOracle.generateNumericMessage(value); 171 | 172 | // Sign the message 173 | let signature = DlcOracle.computeSignature(privateKey, oneTimeSigningKey, message); 174 | 175 | console.log("Value published: ", value); 176 | console.log("Signature: ", signature.toString('hex')); 177 | 178 | generateAndPrintKey(); 179 | } 180 | ``` 181 | 182 | Next, run your code again. It will print out something like this (you'll have to wait 60 seconds for the value to be published, unless you decreased the `setTimeout` parameter). 183 | 184 | ``` 185 | Oracle Public Key: 03c0d496ef6656fe102a689abc162ceeae166832d826f8750c94d797c92eedd465 186 | R-Point for next publication: 03a0f180839d927aba40f924c369692af4f54ab0611299176dbd46658e452fa750 187 | Value published: 18620 188 | Signature: 7b0238448615cdef48e9d24b61ca776125b84a7fc56edac070b854bdd013a9b9 189 | R-Point for next publication: 03b379049fbba926c4700dfbc43c1452ccfdb4eb4d98cb2ca625f5ed7c59db53b5 190 | ``` 191 | 192 | ### Done! 193 | 194 | And that's all there is to it. Next steps you could take involve changing how you secure the private key(s), how you publish your public key and the R-points (to something other than your console), and to sign actual real-world values using this set-up. If you publish interesting data feeds using this mechanism, people can base real Discreet Log Contracts on them. If you created any cool oracles, feel free to send a pull request to our [samples repository](https://github.com/mit-dci/dlc-oracle-nodejs-samples) so we can include them for other people to enjoy. You'll also find the complete code for this tutorial there as [one of the samples](https://github.com/mit-dci/dlc-oracle-nodejs-samples/tree/master/tutorial) -------------------------------------------------------------------------------- /build-docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | typedoc -out docs/ lib/index.ts -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import { randomBytes, createHash } from 'crypto' 2 | const BN = require('bn.js'); 3 | const EC = require('elliptic').ec; 4 | 5 | // Create and initialize EC context 6 | // (better do it once and reuse it) 7 | const ec = new EC('secp256k1'); 8 | 9 | 10 | class DlcOracle { 11 | 12 | /** 13 | * When converting a number to Hex, add a leading 0 if it does 14 | * not have an even number of characters 15 | * @param hexString The string to pad 16 | */ 17 | private static padHexString(hexString : string) : string { 18 | if(hexString.length % 2 !== 0) { 19 | hexString = "0" + hexString; 20 | } 21 | return hexString; 22 | } 23 | 24 | /** 25 | * Calculates the euclidean modulo over two BN bignums 26 | * @param num1 The dividend 27 | * @param num2 The divisor 28 | */ 29 | private static euclideanMod(num1 : any, num2 : any) : any { 30 | // TODO: Typings 31 | let num20 = new BN(num2); 32 | let neg = false; 33 | if(num1.isNeg()) { 34 | neg = true; 35 | } 36 | num1 = num1.mod(num2); 37 | if(neg) { 38 | if(num2.isNeg()) { 39 | num1 = num1.sub(num2) 40 | } else { 41 | num1 = num1.add(num2) 42 | } 43 | } 44 | return num1; 45 | } 46 | 47 | /** 48 | * Generates a proper byte array (Buffer) for a given numeric value 49 | * This because numeric values are expected to be wrapped in a 32 byte 50 | * message by LIT 51 | * @param value Number to encode 52 | */ 53 | static generateNumericMessage(value : number) : Buffer { 54 | let numberString = value.toString(16) 55 | numberString = new Array(64 - numberString.length + 1).join('0') + numberString 56 | 57 | return Buffer.from(numberString, 'hex') 58 | } 59 | 60 | /** 61 | * Derives the public key to a private key 62 | * @param privateKey The private key to derive the public key for 63 | */ 64 | static publicKeyFromPrivateKey(privateKey : Buffer) : Buffer { 65 | let keyPair = ec.keyFromPrivate(privateKey); 66 | return Buffer.from(keyPair.getPublic(true,'hex'),'hex'); 67 | } 68 | 69 | /** 70 | * Will return a new random private scalar to be used when signing a new message 71 | */ 72 | static generateOneTimeSigningKey() : Buffer { 73 | return randomBytes(32); 74 | } 75 | 76 | /** 77 | * calculates the signature multipled by the generator 78 | * point, for an arbitrary message based on pubkey R and pubkey A. 79 | * Calculates P = pubR - h(msg, pubR)pubA. 80 | * This is used when building settlement transactions and determining the pubkey 81 | * to the oracle's possible signatures beforehand. Can be calculated with just 82 | * public keys, so by anyone. 83 | * @param oracleA The oracle's public key 84 | * @param oracleR The oracle's R-point (public key to the one-time signing key) 85 | * @param message The message to compute the signature pubkey for 86 | */ 87 | static computeSignaturePubKey(oracleA : Buffer, oracleR : Buffer, message : Buffer) : Buffer { 88 | let A = ec.keyFromPublic(oracleA); 89 | let R = ec.keyFromPublic(oracleR); 90 | 91 | let Rx = R.pub.getX(); 92 | let RxString = DlcOracle.padHexString(Rx.toString(16)); 93 | 94 | let e = createHash('sha256'); 95 | e.update(message); 96 | e.update(Buffer.from(RxString,'hex')); 97 | let bigE = new BN(e.digest('hex'),16); 98 | let P = A.pub.mul(bigE); 99 | 100 | let bigY = P.getY(); 101 | bigY = bigY.neg(); 102 | bigY = DlcOracle.euclideanMod(bigY, ec.curve.p); 103 | 104 | let newY = new BN(bigY.toString(16),16); 105 | P = ec.curve.point(P.getX(), newY); 106 | P = P.add(R.pub); 107 | 108 | return Buffer.from(P.encodeCompressed('hex'),'hex'); 109 | } 110 | 111 | /** 112 | * Computes the signature for an arbitrary message based on two private scalars: 113 | * The one-time signing key and the oracle's private key 114 | * @param privateKey The private key to sign with 115 | * @param oneTimeSigningKey The one-time signing key to sign with 116 | * @param message The message to sign 117 | */ 118 | static computeSignature(privateKey : Buffer, oneTimeSigningKey : Buffer, message : Buffer) : Buffer { 119 | let bigPriv = new BN(privateKey.toString('hex'),16); 120 | let bigK = new BN(oneTimeSigningKey.toString('hex'),16); 121 | 122 | let R = ec.g.mul(bigK); 123 | let Rx = R.getX(); 124 | let RxString = DlcOracle.padHexString(Rx.toString(16)); 125 | 126 | let e = createHash('sha256'); 127 | e.update(message); 128 | e.update(Buffer.from(RxString,'hex')) 129 | let eHex = e.digest('hex'); 130 | 131 | let bigE = new BN(eHex,16); 132 | 133 | // TODO: Check e out of range 134 | 135 | let bigS = new BN(bigE); 136 | 137 | bigS = bigS.mul(bigPriv); 138 | bigS = bigK.sub(bigS); 139 | bigS = DlcOracle.euclideanMod(bigS,ec.curve.n); 140 | 141 | // TODO: Check zero 142 | 143 | let numberString = bigS.toString(16) 144 | if(numberString.length < 64) numberString = new Array(64 - numberString.length + 1).join('0') + numberString 145 | 146 | return Buffer.from(numberString, 'hex') 147 | } 148 | } 149 | 150 | export { DlcOracle }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dlc-oracle-nodejs", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/events": { 8 | "version": "1.2.0", 9 | "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", 10 | "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", 11 | "dev": true 12 | }, 13 | "@types/node": { 14 | "version": "10.1.3", 15 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.1.3.tgz", 16 | "integrity": "sha512-GiCx7dRvta0hbxXoJFAUxz+CKX6bZSCKjM5slq2vPp/5zwK01T4ibYZkGr6EN4F2QmxDQR76/ZHg6q+7iFWCWw==", 17 | "dev": true 18 | }, 19 | "@types/ws": { 20 | "version": "5.1.1", 21 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-5.1.1.tgz", 22 | "integrity": "sha512-zf12eIggrJKYkOXood4EbQOsMFaVR8e5W8azkesRH1yFg4GhocS7j4sqE+FesLbvf1FLws4HenWUG6YZQ/LTJQ==", 23 | "dev": true, 24 | "requires": { 25 | "@types/events": "*", 26 | "@types/node": "*" 27 | } 28 | }, 29 | "async-limiter": { 30 | "version": "1.0.0", 31 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", 32 | "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" 33 | }, 34 | "bignumber.js": { 35 | "version": "7.2.1", 36 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", 37 | "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" 38 | }, 39 | "bn.js": { 40 | "version": "4.11.8", 41 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", 42 | "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" 43 | }, 44 | "brorand": { 45 | "version": "1.1.0", 46 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 47 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" 48 | }, 49 | "elliptic": { 50 | "version": "6.4.0", 51 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", 52 | "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", 53 | "requires": { 54 | "bn.js": "^4.4.0", 55 | "brorand": "^1.0.1", 56 | "hash.js": "^1.0.0", 57 | "hmac-drbg": "^1.0.0", 58 | "inherits": "^2.0.1", 59 | "minimalistic-assert": "^1.0.0", 60 | "minimalistic-crypto-utils": "^1.0.0" 61 | } 62 | }, 63 | "hash.js": { 64 | "version": "1.1.3", 65 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", 66 | "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", 67 | "requires": { 68 | "inherits": "^2.0.3", 69 | "minimalistic-assert": "^1.0.0" 70 | } 71 | }, 72 | "hmac-drbg": { 73 | "version": "1.0.1", 74 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 75 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 76 | "requires": { 77 | "hash.js": "^1.0.3", 78 | "minimalistic-assert": "^1.0.0", 79 | "minimalistic-crypto-utils": "^1.0.1" 80 | } 81 | }, 82 | "inherits": { 83 | "version": "2.0.3", 84 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 85 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 86 | }, 87 | "minimalistic-assert": { 88 | "version": "1.0.1", 89 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 90 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" 91 | }, 92 | "minimalistic-crypto-utils": { 93 | "version": "1.0.1", 94 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 95 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" 96 | }, 97 | "typescript": { 98 | "version": "2.8.3", 99 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz", 100 | "integrity": "sha512-K7g15Bb6Ra4lKf7Iq2l/I5/En+hLIHmxWZGq3D4DIRNFxMNV6j2SHSvDOqs2tGd4UvD/fJvrwopzQXjLrT7Itw==", 101 | "dev": true 102 | }, 103 | "ws": { 104 | "version": "5.2.0", 105 | "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.0.tgz", 106 | "integrity": "sha512-c18dMeW+PEQdDFzkhDsnBAlS4Z8KGStBQQUcQ5mf7Nf689jyGk0594L+i9RaQuf4gog6SvWLJorz2NfSaqxZ7w==", 107 | "requires": { 108 | "async-limiter": "~1.0.0" 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dlc-oracle-nodejs", 3 | "version": "0.0.3", 4 | "description": "This library allows you to easily build oracles for use in Discreet Log Contracts using NodeJS", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "prepare": "npm run build", 9 | "build": "tsc", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/mit-dci/dlc-oracle-nodejs.git" 15 | }, 16 | "keywords": [], 17 | "author": "MIT Digital Currency Initiative", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/mit-dci/dlc-oracle-nodejs/issues" 21 | }, 22 | "homepage": "https://github.com/mit-dci/dlc-oracle-nodejs#readme", 23 | "devDependencies": { 24 | "@types/node": "^10.1.3", 25 | "@types/ws": "^5.1.1", 26 | "typescript": "^2.8.3" 27 | }, 28 | "dependencies": { 29 | "bignumber.js": "^7.2.1", 30 | "bn.js": "^4.11.8", 31 | "elliptic": "^6.4.0", 32 | "ws": "^5.2.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom","es2015"], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 12 | // "outFile": "./", /* Concatenate and emit output to single file. */ 13 | "outDir": "./dist", /* Redirect output structure to the directory. */ 14 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 15 | // "removeComments": true, /* Do not emit comments to output. */ 16 | // "noEmit": true, /* Do not emit outputs. */ 17 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 18 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 19 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 20 | 21 | /* Strict Type-Checking Options */ 22 | "strict": true, /* Enable all strict type-checking options. */ 23 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 24 | // "strictNullChecks": true, /* Enable strict null checks. */ 25 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 26 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 27 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 28 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 29 | 30 | /* Additional Checks */ 31 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 32 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 33 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 34 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 35 | 36 | /* Module Resolution Options */ 37 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 38 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 39 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 40 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 41 | // "typeRoots": [], /* List of folders to include type definitions from. */ 42 | // "types": [], /* Type declaration files to be included in compilation. */ 43 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 44 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 45 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 46 | 47 | /* Source Map Options */ 48 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 49 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 50 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 51 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 52 | 53 | /* Experimental Options */ 54 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 55 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 56 | } 57 | } --------------------------------------------------------------------------------