├── .gitignore ├── Dockerfile ├── README.md ├── config-overrides.js ├── mime.types ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.css ├── App.test.tsx ├── App.tsx ├── ergo-related │ ├── explorer.js │ ├── rest.js │ └── serializer.js ├── index.css ├── index.tsx ├── logo.svg ├── my-ergo-page.js ├── react-app-env.d.ts ├── reportWebVitals.ts └── setupTests.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | .eslintcache 25 | .idea 26 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/node-frontend:10 as build-stage 2 | WORKDIR /app 3 | COPY package*.json /app/ 4 | RUN npm install 5 | COPY ./ /app/ 6 | RUN npm run build 7 | FROM nginx:1.15 8 | COPY --from=build-stage /app/build/ /usr/share/nginx/html 9 | COPY --from=build-stage /nginx.conf /etc/nginx/conf.d/default.conf 10 | COPY /mime.types /etc/nginx/mime.types 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Ergo](https://ergoplatform.org/) JS Template - Entry Point to Ergo dApp Development 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). It contains [ergo-ts](https://github.com/coinbarn/ergo-ts) and [ergo-lib](https://github.com/ergoplatform/sigma-rust) libraries as dependencies 4 | and some examples to present how to use these libraries. 5 | 6 | ## Goal 7 | The goal of this template is to bootstrap JS dApp development for Ergo Blockchain. 8 | Ergo libraries, WASM support and several examples are already available in this template. 9 | These simple examples should help devs to get on board faster and start developing their ideas right away. 10 | 11 | Since the template is structurally identical to an empty React project created by CRA, 12 | devs can simply and without any ergo-related barriers clone the project and build on top of it. 13 | 14 | ## Examples 15 | Available examples include: 16 | * Interacting with the explorer 17 | * Encoding different data types 18 | * Decoding fields (registers) of tokens 19 | 20 | These examples are simple intentionally to be newcomer-friendly. These should help you 21 | to understand how to use ergo libraries and start developing your dApp. 22 | 23 | ## Deploy Your dApp 24 | To facilitate deploying your React app, docker file is already available for this template. 25 | 26 | Just build your docker image locally using: 27 | ```bash 28 | docker build -t mydapp 29 | ``` 30 | Or configure [Dockerhub](https://hub.docker.com/) to build the image automatically for you when you push to a specific branch. 31 | 32 | Then you can run/deploy your dApp easily using: 33 | ```bash 34 | docker run -p 80:80 mydapp 35 | ``` 36 | 37 | ## Available Scripts 38 | 39 | In the project directory, you can run: 40 | 41 | ### `npm start` 42 | 43 | Runs the app in the development mode.\ 44 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 45 | 46 | The page will reload if you make edits.\ 47 | You will also see any lint errors in the console. 48 | 49 | ### `npm test` 50 | 51 | Launches the test runner in the interactive watch mode.\ 52 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 53 | 54 | ### `npm run build` 55 | 56 | Builds the app for production to the `build` folder.\ 57 | It correctly bundles React in production mode and optimizes the build for the best performance. 58 | 59 | The build is minified and the filenames include the hashes.\ 60 | Your app is ready to be deployed! 61 | 62 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 63 | 64 | ## Learn React 65 | 66 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 67 | 68 | To learn React, check out the [React documentation](https://reactjs.org/). 69 | -------------------------------------------------------------------------------- /config-overrides.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function override(config, env) { 4 | const wasmExtensionRegExp = /\.wasm$/; 5 | 6 | config.resolve.extensions.push('.wasm'); 7 | 8 | config.module.rules.forEach(rule => { 9 | (rule.oneOf || []).forEach(oneOf => { 10 | if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) { 11 | // make file-loader ignore WASM files 12 | oneOf.exclude.push(wasmExtensionRegExp); 13 | } 14 | }); 15 | }); 16 | 17 | // add a dedicated loader for WASM 18 | config.module.rules.push({ 19 | test: wasmExtensionRegExp, 20 | include: path.resolve(__dirname, 'src'), 21 | use: [{ loader: require.resolve('wasm-loader'), options: {} }] 22 | }); 23 | 24 | return config; 25 | }; 26 | -------------------------------------------------------------------------------- /mime.types: -------------------------------------------------------------------------------- 1 | 2 | types { 3 | text/html html htm shtml; 4 | text/css css; 5 | text/xml xml; 6 | image/gif gif; 7 | image/jpeg jpeg jpg; 8 | application/javascript js; 9 | application/atom+xml atom; 10 | application/rss+xml rss; 11 | 12 | text/mathml mml; 13 | text/plain txt; 14 | text/vnd.sun.j2me.app-descriptor jad; 15 | text/vnd.wap.wml wml; 16 | text/x-component htc; 17 | 18 | image/png png; 19 | image/svg+xml svg svgz; 20 | image/tiff tif tiff; 21 | image/vnd.wap.wbmp wbmp; 22 | image/webp webp; 23 | image/x-icon ico; 24 | image/x-jng jng; 25 | image/x-ms-bmp bmp; 26 | 27 | font/woff woff; 28 | font/woff2 woff2; 29 | 30 | application/wasm wasm; 31 | application/java-archive jar war ear; 32 | application/json json; 33 | application/mac-binhex40 hqx; 34 | application/msword doc; 35 | application/pdf pdf; 36 | application/postscript ps eps ai; 37 | application/rtf rtf; 38 | application/vnd.apple.mpegurl m3u8; 39 | application/vnd.google-earth.kml+xml kml; 40 | application/vnd.google-earth.kmz kmz; 41 | application/vnd.ms-excel xls; 42 | application/vnd.ms-fontobject eot; 43 | application/vnd.ms-powerpoint ppt; 44 | application/vnd.oasis.opendocument.graphics odg; 45 | application/vnd.oasis.opendocument.presentation odp; 46 | application/vnd.oasis.opendocument.spreadsheet ods; 47 | application/vnd.oasis.opendocument.text odt; 48 | application/vnd.openxmlformats-officedocument.presentationml.presentation 49 | pptx; 50 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 51 | xlsx; 52 | application/vnd.openxmlformats-officedocument.wordprocessingml.document 53 | docx; 54 | application/vnd.wap.wmlc wmlc; 55 | application/x-7z-compressed 7z; 56 | application/x-cocoa cco; 57 | application/x-java-archive-diff jardiff; 58 | application/x-java-jnlp-file jnlp; 59 | application/x-makeself run; 60 | application/x-perl pl pm; 61 | application/x-pilot prc pdb; 62 | application/x-rar-compressed rar; 63 | application/x-redhat-package-manager rpm; 64 | application/x-sea sea; 65 | application/x-shockwave-flash swf; 66 | application/x-stuffit sit; 67 | application/x-tcl tcl tk; 68 | application/x-x509-ca-cert der pem crt; 69 | application/x-xpinstall xpi; 70 | application/xhtml+xml xhtml; 71 | application/xspf+xml xspf; 72 | application/zip zip; 73 | 74 | application/octet-stream bin exe dll; 75 | application/octet-stream deb; 76 | application/octet-stream dmg; 77 | application/octet-stream iso img; 78 | application/octet-stream msi msp msm; 79 | 80 | audio/midi mid midi kar; 81 | audio/mpeg mp3; 82 | audio/ogg ogg; 83 | audio/x-m4a m4a; 84 | audio/x-realaudio ra; 85 | 86 | video/3gpp 3gpp 3gp; 87 | video/mp2t ts; 88 | video/mp4 mp4; 89 | video/mpeg mpeg mpg; 90 | video/quicktime mov; 91 | video/webm webm; 92 | video/x-flv flv; 93 | video/x-m4v m4v; 94 | video/x-mng mng; 95 | video/x-ms-asf asx asf; 96 | video/x-ms-wmv wmv; 97 | video/x-msvideo avi; 98 | } 99 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ergo-template", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "ergo-lib-wasm-browser": "^0.4.4", 7 | "@coinbarn/ergo-ts": "^0.3.0", 8 | "@testing-library/jest-dom": "^5.11.9", 9 | "@testing-library/react": "^11.2.3", 10 | "@testing-library/user-event": "^12.6.0", 11 | "@types/jest": "^26.0.20", 12 | "@types/node": "^12.19.14", 13 | "@types/react": "^16.14.2", 14 | "@types/react-dom": "^16.9.10", 15 | "react": "^17.0.1", 16 | "react-dom": "^17.0.1", 17 | "react-scripts": "4.0.1", 18 | "typescript": "^4.1.3", 19 | "web-vitals": "^0.2.4" 20 | }, 21 | "scripts": { 22 | "start": "react-app-rewired start", 23 | "build": "react-app-rewired build", 24 | "test": "react-app-rewired test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | }, 45 | "devDependencies": { 46 | "react-app-rewired": "^2.1.8", 47 | "wasm-loader": "^1.3.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anon-real/ergo-js-template/2f0711027bb227152dee6bb1bc0b4f401ff13c75/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anon-real/ergo-js-template/2f0711027bb227152dee6bb1bc0b4f401ff13c75/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anon-real/ergo-js-template/2f0711027bb227152dee6bb1bc0b4f401ff13c75/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | import {currentHeight} from "./ergo-related/explorer"; 5 | import MyErgoPage from "./my-ergo-page"; 6 | 7 | function App() { 8 | return ( 9 |
10 |
11 | 12 | 18 | Learn React 19 | 20 |
21 |
22 | ); 23 | } 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /src/ergo-related/explorer.js: -------------------------------------------------------------------------------- 1 | import { get } from './rest'; 2 | 3 | export const trueAddress = '4MQyML64GnzMxZgm'; // dummy address to get unsigned tx from node, we only care about the boxes though in this case 4 | export const explorerApi = 'https://api.ergoplatform.com/api/v0'; 5 | 6 | async function getRequest(url) { 7 | return get(explorerApi + url).then(res => { 8 | return { data: res }; 9 | }); 10 | } 11 | 12 | export async function currentHeight() { 13 | return getRequest('/blocks?limit=1') 14 | .then(res => res.data) 15 | .then(res => res.items[0].height); 16 | } 17 | 18 | export function unspentBoxesFor(address) { 19 | return getRequest(`/transactions/boxes/byAddress/unspent/${address}`).then( 20 | (res) => res.data 21 | ); 22 | } 23 | 24 | export function boxById(id) { 25 | return getRequest(`/transactions/boxes/${id}`).then((res) => res.data); 26 | } 27 | 28 | export function txById(id) { 29 | return getRequest(`/transactions/${id}`).then((res) => res.data); 30 | } 31 | 32 | export async function getSpendingTx(boxId) { 33 | const data = getRequest(`/transactions/boxes/${boxId}`); 34 | return data 35 | .then((res) => res.data) 36 | .then((res) => res.spentTransactionId) 37 | .catch((_) => null); 38 | } 39 | 40 | export function getUnconfirmedTxsFor(addr) { 41 | return getRequest( 42 | `/transactions/unconfirmed/byAddress/${addr}` 43 | ) 44 | .then((res) => res.data) 45 | .then((res) => res.items); 46 | } 47 | 48 | export function getTokenBox(addr) { 49 | return getRequest( 50 | `/assets/${addr}/issuingBox` 51 | ) 52 | .then((res) => res.data[0]) 53 | } 54 | 55 | export function getBalanceFor(addr, token = null) { 56 | return getRequest( 57 | `/addresses/${addr}` 58 | ) 59 | .then((res) => res.data) 60 | .then((res) => res.transactions) 61 | .then(res => { 62 | if (!token) return res.confirmedBalance; 63 | let tok = res.confirmedTokensBalance.filter(tok => tok.tokenId === token); 64 | if (tok.length === 0) return 0; 65 | else return tok[0].amount; 66 | }); 67 | } 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/ergo-related/rest.js: -------------------------------------------------------------------------------- 1 | export async function post(url, body = {}, apiKey = '') { 2 | return await fetch(url, { 3 | method: 'POST', 4 | headers: { 5 | Accept: 'application/json', 6 | 'Content-Type': 'application/json', 7 | api_key: apiKey, 8 | }, 9 | body: JSON.stringify(body), 10 | }); 11 | } 12 | export async function get(url, apiKey = '') { 13 | return await fetch(url, { 14 | headers: { 15 | Accept: 'application/json', 16 | 'Content-Type': 'application/json', 17 | api_key: apiKey, 18 | }, 19 | }).then(res => res.json()); 20 | } 21 | -------------------------------------------------------------------------------- /src/ergo-related/serializer.js: -------------------------------------------------------------------------------- 1 | import {Serializer} from "@coinbarn/ergo-ts"; 2 | 3 | let ergolib = import('ergo-lib-wasm-browser') 4 | 5 | export async function encodeNum(n, isInt = false) { 6 | if (isInt) return (await ergolib).Constant.from_i32(n).encode_to_base16() 7 | else return (await ergolib).Constant.from_i64((await ergolib).I64.from_str(n)).encode_to_base16() 8 | } 9 | 10 | export async function decodeNum(n, isInt = false) { 11 | if (isInt) return (await ergolib).Constant.decode_from_base16(n).to_i32() 12 | else return (await ergolib).Constant.decode_from_base16(n).to_i64().to_str() 13 | 14 | } 15 | 16 | export async function encodeHex(reg) { 17 | return (await ergolib).Constant.from_byte_array(Buffer.from(reg, 'hex')).encode_to_base16() 18 | } 19 | 20 | export async function encodeStr(str) { 21 | return encodeHex(Serializer.stringToHex(str)) 22 | } 23 | 24 | function toHexString(byteArray) { 25 | return Array.from(byteArray, function(byte) { 26 | return ('0' + (byte & 0xFF).toString(16)).slice(-2); 27 | }).join('') 28 | } 29 | 30 | export async function decodeString(encoded) { 31 | return Serializer.stringFromHex(toHexString((await ergolib).Constant.decode_from_base16(encoded).to_byte_array())) 32 | } 33 | 34 | export function ergToNano(erg) { 35 | if (erg === undefined) return 0 36 | if (erg.startsWith('.')) return parseInt(erg.slice(1) + '0'.repeat(9 - erg.length + 1)) 37 | let parts = erg.split('.') 38 | if (parts.length === 1) parts.push('') 39 | if (parts[1].length > 9) return 0 40 | return parseInt(parts[0] + parts[1] + '0'.repeat(9 - parts[1].length)) 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/my-ergo-page.js: -------------------------------------------------------------------------------- 1 | import React, {Fragment} from 'react'; 2 | import {currentHeight, getTokenBox} from "./ergo-related/explorer"; 3 | import {decodeNum, decodeString, encodeNum, encodeStr} from "./ergo-related/serializer"; 4 | 5 | 6 | export default class MyErgoPage extends React.Component { 7 | constructor(props) { 8 | super(props); 9 | this.state = { 10 | height: NaN, 11 | tokenId: '01004ddddd67da4b34ab2a5a99f2fed6f1f280e3289508ed5b44ae2d948279ee' 12 | }; 13 | this.decodeToken = this.decodeToken.bind(this) 14 | } 15 | 16 | componentDidMount() { 17 | currentHeight().then(res => { 18 | this.setState({height: res}) 19 | }) 20 | this.decodeToken(this.state.tokenId) 21 | } 22 | 23 | async decodeToken(tokenId) { 24 | let box = await getTokenBox(tokenId) 25 | if (!box) return 26 | let name = await decodeString(box.additionalRegisters.R4) 27 | let description = await decodeString(box.additionalRegisters.R5) 28 | let decimals = await decodeString(box.additionalRegisters.R6) 29 | this.setState({name: name, description: description, decimals: decimals}) 30 | } 31 | 32 | render() { 33 | return ( 34 | 35 |

Current Blockchain Height: {this.state.height}

36 |

37 | Encode Number: encodeNum(e.target.value).then(res => this.setState({encodedNum: res}))} 39 | type='number' step="1" placeholder='Enter a number'/> {this.state.encodedNum} 40 |

41 |

42 | Encode String: encodeStr(e.target.value).then(res => this.setState({encodedStr: res}))} 44 | type='text' step="1" placeholder='Enter text'/> {this.state.encodedStr} 45 |

46 |

47 | Decode Token Fields: { 51 | this.setState({tokenId: e.target.value}) 52 | this.decodeToken(e.target.value) 53 | }} 54 | type='text' placeholder='Enter token ID'/> 55 |

token's name: {this.state.name}

56 |

token's description: {this.state.description}

57 |

token's decimals: {this.state.decimals}

58 |

59 |
60 |
61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | --------------------------------------------------------------------------------