├── .gitignore ├── LICENSE ├── README.md ├── docs ├── README.md └── connectors │ ├── README.md │ ├── argentx.md │ └── braavos.md ├── lerna.json ├── package.json ├── packages ├── abstract-connector │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── declarations.ts │ │ └── index.ts │ └── tsconfig.json ├── argentx-connector │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── declarations.ts │ │ ├── index.ts │ │ └── types.ts │ └── tsconfig.json ├── braavos-connector │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── declarations.ts │ │ ├── index.ts │ │ └── types.ts │ └── tsconfig.json ├── core │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── manager.ts │ │ ├── normalizers.ts │ │ ├── provider.tsx │ │ └── types.ts │ ├── test │ │ ├── normalizers.test.ts │ │ └── provider.test.tsx │ └── tsconfig.json └── types │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ └── tsconfig.json ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | .rts2_cache_cjs 6 | .rts2_cache_esm 7 | .rts2_cache_umd 8 | .rts2_cache_system 9 | dist 10 | .env 11 | out -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 dhruvkelawala 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # web3-starknet-react 🚀 2 | 3 | _A simple, maximally extensible, dependency minimized framework for building Starknet dApps_ 4 | 5 | _Provides easy access to Starknet Interface all over the React App. Inspired from_ [web3-react](https://github.com/NoahZinsmeister/web3-react/tree/v6) 6 | 7 |
8 | 9 | [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org/) 10 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) 11 | 12 | | Packages | `@latest` version | Size | Description | 13 | | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | 14 | | 🏝 **Core** | | | | 15 | | `@web3-starknet-react/core` | [![npm version](https://img.shields.io/npm/v/@web3-starknet-react/core/latest.svg)](https://www.npmjs.com/package/@web3-starknet-react/core/v/latest) | [![minzip](https://img.shields.io/bundlephobia/minzip/@web3-starknet-react/core/latest.svg)](https://bundlephobia.com/result?p=@web3-starknet-react/core@latest) | [React](https://reactjs.org/) hooks and context for accessing Starknet | 16 | | 🔌 **Connectors** | | | | 17 | | _Browser Extension/dApp Browser_ | | | | 18 | | `@web3-starknet-react/braavos-connector` | [![npm version](https://img.shields.io/npm/v/@web3-starknet-react/braavos-connector/latest.svg)](https://www.npmjs.com/package/@web3-starknet-react/braavos-connector/v/latest) | [![minzip](https://img.shields.io/bundlephobia/minzip/@web3-starknet-react/braavos-connector/latest.svg)](https://bundlephobia.com/result?p=@web3-starknet-react/braavos-connector@latest) | [Braavos Wallet](https://chrome.google.com/webstore/detail/braavos-wallet/jnlgamecbpmbajjfhmmmlhejkemejdma) connector | 19 | | `@web3-starknet-react/argentx-connector` | [![npm version](https://img.shields.io/npm/v/@web3-starknet-react/argentx-connector/latest.svg)](https://www.npmjs.com/package/@web3-starknet-react/argentx-connector/v/latest) | [![minzip](https://img.shields.io/bundlephobia/minzip/@web3-starknet-react/argentx-connector/latest.svg)](https://bundlephobia.com/result?p=@web3-starknet-react/argentx-connector@latest) | [ArgentX Wallet](https://github.com/argentlabs/argent-x) connector | 20 | | 🔫 **Low Level** | | | | 21 | | `@web3-starknet-react/abstract-connector` | [![npm version](https://img.shields.io/npm/v/@web3-starknet-react/abstract-connector/latest.svg)](https://www.npmjs.com/package/@web3-starknet-react/abstract-connector/v/latest) | [![minzip](https://img.shields.io/bundlephobia/minzip/@web3-starknet-react/abstract-connector/latest.svg)](https://bundlephobia.com/result?p=@web3-starknet-react/abstract-connector@latest) | Low Level implementation of connector | 22 | | `@web3-starknet-react/types` | [![npm version](https://img.shields.io/npm/v/@web3-starknet-react/types/latest.svg)](https://www.npmjs.com/package/@web3-starknet-react/types/v/latest) | [![minzip](https://img.shields.io/bundlephobia/minzip/@web3-starknet-react/types/latest.svg)](https://bundlephobia.com/result?p=@web3-starknet-react/types@latest) | Shared [TypeScript](https://www.typescriptlang.org/) Types | 23 | 24 |
25 | 26 | # 27 | 28 | ## ⭐️ [Documentation](docs) 29 | 30 | ## Projects using `web3-starknet-react` 31 | 32 | _Open a PR to add your starknet project to the list_ 33 | 34 | - [JediSwap](https://app.testnet.jediswap.xyz/#/swap) 35 | 36 | ## Local Development 37 | 38 | - Clone repo \ 39 | `git clone https://github.com/dhruvkelawala/web3-starknet-react` 40 | 41 | - Install top-level dependencies \ 42 | `yarn` 43 | 44 | - Install sub-dependencies \ 45 | `yarn bootstrap` 46 | 47 | - Build and watch for changes \ 48 | `yarn start` 49 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # `web3-starknet-react` Documentation 2 | 3 | - [Overview](#overview) 4 | - [Install](#install) 5 | - [web3-starknet-react@core API Reference](#web3-starknet-reactcore-api-reference) 6 | - [StarknetReactProvider](#starknetreactprovider) 7 | - [Props](#props) 8 | - [Example](#example) 9 | - [useStarknetReact](#usestarknetreact) 10 | - [Arguments](#arguments) 11 | - [Example](#example-1) 12 | - [createStarknetReactRoot](#createstarknetreactroot) 13 | - [Arguments](#arguments-1) 14 | - [Example](#example-2) 15 | - [getStarknetReactContext](#getstarknetreactcontext) 16 | - [Arguments](#arguments-2) 17 | - [Example](#example-3) 18 | - [UnsupportedChainIdError](#unsupportedchainiderror) 19 | - [Example](#example-4) 20 | - [Understanding Error Bubbling](#understanding-error-bubbling) 21 | 22 | ## Overview 23 | 24 | At a high level, `web3-starknet-react` is a state machine which ensures that certain key pieces of Starknet related data (the user's current account, account address, chainId, etc. ) relevant to your dApp are kept-up-to-date. To help with this, `web3-starknet-react` uses React's [Context](https://reactjs.org/docs/context.html) API to efficiently store this data, and inject it wherever you need it in your react app. 25 | 26 | The data conforms to the following interface: 27 | 28 | ```typescript 29 | interface StarknetReactContextInterface { 30 | activate: ( 31 | connector: AbstractConnector, 32 | onError?: (error: Error | unknown) => void, 33 | throwsError?: boolean 34 | ) => Promise 35 | setError: (error: Error) => void 36 | deactivate: () => void 37 | 38 | connector?: AbstractConnectorInterface 39 | library?: T 40 | chainId?: number 41 | account?: AccountInterface | null 42 | connectedAddress?: string | null 43 | 44 | active: boolean 45 | error?: Error 46 | } 47 | ``` 48 | 49 | The documentation that follows is for `@web3-starknet-react/core`, the package responsible for managing this context. To understand where data itself comes from, head over to the [connectors/folder](connectors/) 50 | 51 | ## Install 52 | 53 | - Add `react@>=16.8` to your project \ 54 | `yarn add react` 55 | 56 | - Then install `web3-starknet-react` \ 57 | `yarn add @web3-starknet-react/core` 58 | 59 | ## `web3-starknet-react@core` API Reference 60 | 61 | ### StarknetReactProvider 62 | 63 | `web3-starknet-react` relies on the existence of a `StarknetReactProvider` at the root of your application (or more accurately, at the root of the subtree which you which you'd like to have Starknet functionality). It requires a single `getLibrary` prop which is responsible for instantiating `starknet.js` library. 64 | 65 | Note: `web3-react` library gives the flexibility of using `web3.js` or `ethers.js` library. However, on Starknet, there is only `starknet.js` library. The `getLibrary` prop on `web3-starknet-react`, therefore, only support `starknet.js` provider. If a new library is emerges in future, we will have flexibility to support it by just making very small changes. 66 | 67 | #### Props 68 | 69 | ```typescript 70 | // Use starknet.js provider 71 | getLibrary: (provider?: Provider, connector?: AbstractConnectorInterface) => any 72 | ``` 73 | 74 | #### Example 75 | 76 | ```javascript 77 | import { StarknetReactProvider } from '@web3-starknet-react/core' 78 | 79 | // import starknet.js 80 | import { Provider } from 'starknet' 81 | 82 | function getLibrary(provider, connector) { 83 | return new Provider(provider) 84 | } 85 | 86 | function App() { 87 | return {/* <...> */} 88 | } 89 | ``` 90 | 91 | ### useStarknetReact 92 | 93 | If you're using Hooks (😇), useStarknetReact will be your best friend. Call it from within any function component to access context variables, just like that. It accepts an optional key argument, if you're using multiple roots. 94 | 95 | #### Arguments 96 | 97 | ```typescript 98 | key?: string 99 | ``` 100 | 101 | #### Example 102 | 103 | ```javascript 104 | import { useStarknetReact } from '@web3-starknet-react/core' 105 | 106 | function Component() { 107 | const starknetReact = useStarknetReact() 108 | // ... 109 | } 110 | ``` 111 | 112 | ### createStarknetReactRoot 113 | 114 | In some cases, your dApp may want to maintain >1 active Starknet connections simultaneously. 115 | 116 | In cases like these, you'll likely want to create a second (or maybe even third, but probably not fourth) root, which will function exactly like another [StarknetReactProvider](#starknetreactprovider) (in fact, StarknetReactProvider uses createStarknetReactRoot under the hood). It requires a `key` argument, used to identify the root to [usStarknetReact](#usestarknetreact) (or [getStarknetReactContext](#getstarknetreactcontext)). 117 | 118 | #### Arguments 119 | 120 | ```typescript 121 | key: string 122 | ``` 123 | 124 | #### Example 125 | 126 | ```javascript 127 | import { StarknetReactProvider, createStarknetReactRoot } from '@web3-starknet-react/core' 128 | 129 | // import starknet.js 130 | import { Provider } from 'starknet' 131 | 132 | function getLibrary(provider, connector) { 133 | return new Provider(provider) 134 | } 135 | 136 | const StarknetReactProviderReloaded = createStarknetReactRoot('anotherOne') 137 | 138 | function App() { 139 | return ( 140 | 141 | {/* <...> */} 142 | 143 | ) 144 | } 145 | ``` 146 | 147 | ### getStarknetReactContext 148 | 149 | If you're not using Hooks (why?😳), getStarknetReactContext is your savior. It gives direct access to the context returned by [createContext](https://reactjs.org/docs/context.html#reactcreatecontext), which will unlock the use of [contextType](https://reactjs.org/docs/context.html#classcontexttype) in class components, the [Context.Consumer](https://reactjs.org/docs/context.html#contextconsumer) pattern, or whatever other render prop/HOC/etc. shenanigans your manager whose personal site still runs on PHP is making you write. It accepts an optional `key` argument to identify the root. 150 | 151 | #### Arguments 152 | 153 | ```typescript 154 | key?: string 155 | ``` 156 | 157 | #### Example 158 | 159 | ```javascript 160 | import { getStarknetReactContext } from '@web3-starknet-react/core' 161 | 162 | const starknetReactContext = getStarknetReactContext() 163 | 164 | // ... 165 | ``` 166 | 167 | ### UnsupportedChainIdError 168 | 169 | This is an error which can be used to inform users that they're connected to an unsupported network. 170 | 171 | #### Example 172 | 173 | ```javascript 174 | import { UnsupportedChainIdError } from '@web3-starknet-react/core' 175 | // ... 176 | 177 | function Component() { 178 | const { error } = useStarknetReact() 179 | const isUnsupportedChainIdError = error instanceof UnsupportedChainIdError 180 | // ... 181 | } 182 | ``` 183 | 184 | ## Understanding Error Bubbling 185 | 186 | Errors that occur during the initial activation of a connector (i.e. inside activate), are are handled in 1 of 4 ways: 187 | 188 | 1. In the case where there's been 1 or more other updates to the `web3-starknet-react` context between when activate was called and when it resolved with the data required to complete the activation, errors are silently suppressed (in development mode, a warning will be logged to the console). This should really only happen in cases where activation takes a very long time and the user does something in the intervening time, such as activating another connector, deactivating the current connector, etc. 189 | 2. If `throwErrors` (the third argument to activate) is passed, errors will be thrown and should be handled in a .catch. No updates to the `web3-starknet-react` context will occur. 190 | 3. If `onError` (the second argument to activate) is passed, that function is called with the error. No updates to the `web3-starknet-react` context will occur. 191 | 4. Otherwise, the error will be set in the `web3-starknet-react` context (along with the connector). 192 | 193 | Errors that occur while a connector is set are handled in 1 of 2 ways: 194 | 195 | 1. If an `onError` function was passed, this function is called with the error. No updates to the `web3-starknet-react` context will occur. 196 | 2. Otherwise, the error will be set in the `web3-starknet-react` context. 197 | 198 | In all of these scenarios, note that calling setError will update the `web3-starknet-react` context. This can be called any time a connector is set, and it can be useful for e.g. manually triggering your app's handling of the `web3-starknet-react` error property. 199 | 200 | Note: if an error is ever set in the `web3-starknet-react` context, and a connector triggers an update, the manager will attempt to revalidate all properties as if activate was called again, to recover from the error state. 201 | -------------------------------------------------------------------------------- /docs/connectors/README.md: -------------------------------------------------------------------------------- 1 | # `web3-starknet-react` Documentation - Connectors 2 | 3 | Connectors are standalone packages that interface with `web3-starknet-react` and manage connections to a single type of Starknet node or wallet. To give an example: it's quite common for dApp users to rely on browser extensions such as [ArgentX](https://github.com/argentlabs/argent-x/) or [Braavos](https://chrome.google.com/webstore/detail/braavos-wallet/jnlgamecbpmbajjfhmmmlhejkemejdma) to manage their account for them. So, `web3-starknet-react` defines a connector that's responsible for interfacing with browser extensions. The current list of first-party `web3-starknet-react` connectors can be found in the [top-level README.md](../../README.md). 4 | 5 | Currently, we support both Braavos & ArgentX connectors. As and when new wallets emerges on Starknet like Ledger and Walletconnect, I will add them. Feel free to create an issue, if you want some wallet added. 6 | 7 | One enormous benefit to `web3-starknet-react` is that it's incredibly easy to extend existing/create new connectors! They're very simple Javascript class objects which simply need to define a few functions to be fully compatible with the rest of `web3-starknet-react`. 8 | 9 | For more information on specific first-party connectors, see the individual files in this folder. 10 | -------------------------------------------------------------------------------- /docs/connectors/argentx.md: -------------------------------------------------------------------------------- 1 | # `web3-react` Documentation - ArgentX 2 | 3 | - [Install](#install) 4 | - [Arguments](#arguments) 5 | - [Example](#example) 6 | - [Errors](#errors) 7 | - [NoStarknetProviderError](#nostarknetprovidererror) 8 | - [Example](#example-1) 9 | - [UserRejectedRequestError](#userrejectedrequesterror) 10 | - [Example](#example-2) 11 | 12 | ## Install 13 | 14 | `yarn add @web3-starknet-react/argentx-connector` 15 | 16 | ## Arguments 17 | 18 | ```typescript 19 | supportedChainIds?: number[] 20 | ``` 21 | 22 | **NOTE**: Currently only Goerli (chainId: 5) is supported. As soon as ArgentX supports mainnet (chainId: 1), I will add support for that. 23 | 24 | ## Example 25 | 26 | ```javascript 27 | import { ArgentXConnector } from '@web3-starknet-react/argentx-connector' 28 | 29 | const argentx = new ArgentXConnector({ supportedChainIds: [5] }) 30 | ``` 31 | 32 | ## Errors 33 | 34 | ### NoEthereumProviderError 35 | 36 | #### Example 37 | 38 | ```javascript 39 | import { NoStarknetProviderError } from '@web3-starknet-react/argentx-connector' 40 | 41 | function Component() { 42 | const { error } = useStarknetReact() 43 | const isNoStarknetProviderError = error instanceof NoStarknetProviderError 44 | // ... 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/connectors/braavos.md: -------------------------------------------------------------------------------- 1 | # `web3-react` Documentation - Braavos 2 | 3 | - [Install](#install) 4 | - [Arguments](#arguments) 5 | - [Example](#example) 6 | - [Errors](#errors) 7 | - [NoStarknetProviderError](#nostarknetprovidererror) 8 | - [Example](#example-1) 9 | - [UserRejectedRequestError](#userrejectedrequesterror) 10 | - [Example](#example-2) 11 | 12 | ## Install 13 | 14 | `yarn add @web3-starknet-react/braavos-connector` 15 | 16 | ## Arguments 17 | 18 | ```typescript 19 | supportedChainIds?: number[] 20 | ``` 21 | 22 | ## Example 23 | 24 | ```javascript 25 | import { BraavosWallet } from '@web3-starknet-react/braavos-connector' 26 | 27 | const wallet = new BraavosWallet({ supportedChainIds: [5] }) 28 | ``` 29 | 30 | ## Errors 31 | 32 | ### NoEthereumProviderError 33 | 34 | #### Example 35 | 36 | ```javascript 37 | import { NoStarknetProviderError } from '@web3-starknet-react/braavos-connector' 38 | 39 | function Component() { 40 | const { error } = useStarknetReact() 41 | const isNoStarknetProviderError = error instanceof NoStarknetProviderError 42 | // ... 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "2.1.2", 6 | "npmClient": "yarn", 7 | "useWorkspaces": true 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "web3-starknet-react", 4 | "description": "A Starknet React Provider and Connectors inspired by web3-react library", 5 | "keywords": [ 6 | "react", 7 | "react-hooks", 8 | "hooks", 9 | "ethereum", 10 | "javascript", 11 | "typescript", 12 | "web3", 13 | "starknet", 14 | "frontend", 15 | "dapp", 16 | "argentx", 17 | "braavos" 18 | ], 19 | "author": "Dhruv Kelawala ", 20 | "repository": { 21 | "type": "git", 22 | "url": "git://github.com/dhruvkelawala/web3-starknet-react.git" 23 | }, 24 | "scripts": { 25 | "bootstrap": "lerna bootstrap", 26 | "publish:lerna": "lerna bootstrap && yarn build && lerna publish", 27 | "clean": "lerna clean --yes && lerna exec -- rimraf yarn.lock dist/ .rts2_cache_{cjs,esm}/", 28 | "build": "lerna run build", 29 | "start": "lerna run --parallel --no-bail start -- --noClean", 30 | "lint": "lerna run lint --parallel", 31 | "test": "lerna run test --parallel" 32 | }, 33 | "workspaces": [ 34 | "packages/*" 35 | ], 36 | "devDependencies": { 37 | "@types/jest": "^24.0.21", 38 | "@types/react": "^16.9.11", 39 | "@types/react-dom": "^16.9.4", 40 | "lerna": "^3.19.0", 41 | "react": ">=16.8", 42 | "react-dom": ">=16.8", 43 | "rimraf": "^3.0.1", 44 | "tsdx": "^0.11.0" 45 | }, 46 | "dependencies": { 47 | "starknet": "^3.12.3", 48 | "tiny-invariant": "^1.2.0", 49 | "tiny-warning": "^1.0.3" 50 | }, 51 | "license": "GPL-3.0-or-later", 52 | "prettier": { 53 | "semi": false, 54 | "singleQuote": true, 55 | "printWidth": 120 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/abstract-connector/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | .rts2_cache_cjs 6 | .rts2_cache_esm 7 | .rts2_cache_umd 8 | .rts2_cache_system 9 | dist 10 | -------------------------------------------------------------------------------- /packages/abstract-connector/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 dhruvkelawala 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. 22 | -------------------------------------------------------------------------------- /packages/abstract-connector/README.md: -------------------------------------------------------------------------------- 1 | # @web3-starknet-react/abstract-connector 2 | 3 | Please visit the [parent `web3-starknet-react` repository](https://github.com/dhruvkelawala/web3-starknet-react/) for documentation and details on this package. 4 | -------------------------------------------------------------------------------- /packages/abstract-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@web3-starknet-react/abstract-connector", 3 | "version": "2.1.0", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "author": "Dhruv Kelawala ", 8 | "main": "dist/index.js", 9 | "module": "dist/abstract-connector.esm.js", 10 | "typings": "dist/index.d.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "start": "tsdx watch", 16 | "build": "tsdx build", 17 | "test": "tsdx test --env=jsdom", 18 | "lint": "tsdx lint" 19 | }, 20 | "peerDependencies": { 21 | "react": ">=16" 22 | }, 23 | "husky": { 24 | "hooks": { 25 | "pre-commit": "tsdx lint" 26 | } 27 | }, 28 | "prettier": { 29 | "printWidth": 80, 30 | "semi": true, 31 | "singleQuote": true, 32 | "trailingComma": "es5" 33 | }, 34 | "dependencies": { 35 | "@web3-starknet-react/types": "^2.1.0" 36 | }, 37 | "gitHead": "b893495a21b7d761d895aac9e89666875c315e7b" 38 | } 39 | -------------------------------------------------------------------------------- /packages/abstract-connector/src/declarations.ts: -------------------------------------------------------------------------------- 1 | declare const __DEV__: boolean; 2 | -------------------------------------------------------------------------------- /packages/abstract-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events'; 2 | import { 3 | AbstractConnectorArguments, 4 | ConnectorEvent, 5 | ConnectorUpdate, 6 | } from '@web3-starknet-react/types'; 7 | import { AccountInterface, Provider } from 'starknet'; 8 | 9 | export abstract class AbstractConnector extends EventEmitter { 10 | public readonly supportedChainIds?: number[]; 11 | 12 | constructor({ supportedChainIds }: AbstractConnectorArguments = {}) { 13 | super(); 14 | 15 | this.supportedChainIds = supportedChainIds; 16 | } 17 | 18 | public abstract activate(): Promise; 19 | public abstract getProvider(): Promise; 20 | public abstract getSigner(): AccountInterface | undefined; 21 | public abstract getChainId(): Promise; 22 | public abstract getAccount(): AccountInterface | undefined; 23 | public abstract getConnectedAddress(): string | null; 24 | public abstract deactivate(): void; 25 | 26 | protected emitUpdate(update: ConnectorUpdate) { 27 | if (__DEV__) { 28 | console.log(`Emitting '${ConnectorEvent.Update}' with payload `, update); 29 | } 30 | 31 | this.emit(ConnectorEvent.Update, update); 32 | } 33 | 34 | protected emitError(error: Error) { 35 | if (__DEV__) { 36 | console.log(`Emitting '${ConnectorEvent.Error}' with payload`, error); 37 | } 38 | 39 | this.emit(ConnectorEvent.Error, error); 40 | } 41 | 42 | protected emitDeactivate(): void { 43 | if (__DEV__) { 44 | console.log(`Emitting '${ConnectorEvent.Deactivate}'`); 45 | } 46 | this.emit(ConnectorEvent.Deactivate); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/abstract-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "rootDir": "./", 6 | "baseUrl": "./", 7 | "paths": { 8 | "*": ["src/*", "node_modules/*"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/argentx-connector/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | .rts2_cache_cjs 6 | .rts2_cache_esm 7 | .rts2_cache_umd 8 | .rts2_cache_system 9 | dist 10 | -------------------------------------------------------------------------------- /packages/argentx-connector/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 dhruvkelawala 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. -------------------------------------------------------------------------------- /packages/argentx-connector/README.md: -------------------------------------------------------------------------------- 1 | # @web3-starknet-react/argentx-connector 2 | 3 | Please visit the [parent `web3-starknet-react` repository](https://github.com/dhruvkelawala/web3-starknet-react/) for documentation and details on this package. 4 | -------------------------------------------------------------------------------- /packages/argentx-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@web3-starknet-react/argentx-connector", 3 | "publishConfig": { 4 | "access": "public" 5 | }, 6 | "version": "2.1.2", 7 | "author": "Dhruv Kelawala ", 8 | "main": "dist/index.js", 9 | "module": "dist/argentx-connector.esm.js", 10 | "typings": "dist/index.d.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "start": "tsdx watch", 16 | "build": "tsdx build", 17 | "test": "tsdx test --env=jsdom", 18 | "lint": "tsdx lint" 19 | }, 20 | "peerDependencies": { 21 | "react": ">=16" 22 | }, 23 | "husky": { 24 | "hooks": { 25 | "pre-commit": "tsdx lint" 26 | } 27 | }, 28 | "prettier": { 29 | "printWidth": 80, 30 | "semi": true, 31 | "singleQuote": true, 32 | "trailingComma": "es5" 33 | }, 34 | "dependencies": { 35 | "@web3-starknet-react/abstract-connector": "^2.1.0", 36 | "@web3-starknet-react/types": "^2.1.0" 37 | }, 38 | "gitHead": "b893495a21b7d761d895aac9e89666875c315e7b" 39 | } 40 | -------------------------------------------------------------------------------- /packages/argentx-connector/src/declarations.ts: -------------------------------------------------------------------------------- 1 | declare const __DEV__: boolean; 2 | -------------------------------------------------------------------------------- /packages/argentx-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AbstractConnector } from '@web3-starknet-react/abstract-connector'; 2 | import { 3 | AbstractConnectorArguments, 4 | ConnectorUpdate, 5 | } from '@web3-starknet-react/types'; 6 | import { AccountInterface } from 'starknet'; 7 | 8 | export class NoStarknetProviderError extends Error { 9 | public constructor() { 10 | super(); 11 | this.name = this.constructor.name; 12 | this.message = 'No Starknet Provider was found on window object'; 13 | } 14 | } 15 | 16 | export class ArgentXConnector extends AbstractConnector { 17 | constructor(kwargs: AbstractConnectorArguments) { 18 | super(kwargs); 19 | 20 | this.handleAccountsChanged = this.handleAccountsChanged.bind(this); 21 | } 22 | 23 | public async activate(): Promise { 24 | if (!window.starknet) { 25 | throw new NoStarknetProviderError(); 26 | } 27 | if (window.starknet?.on) { 28 | window.starknet.on('accountsChanged', this.handleAccountsChanged); 29 | } 30 | 31 | // const { ...provider } = this.starknet.signer; 32 | 33 | let account: AccountInterface | undefined, connectedAddress; 34 | 35 | // const isPreAuthorized = await window.starknet.isPreauthorized(); 36 | 37 | connectedAddress = window.starknet.selectedAddress; 38 | account = window.starknet.account; 39 | 40 | if (!account) { 41 | [connectedAddress] = await window.starknet.enable(); 42 | account = window.starknet.account; 43 | } 44 | 45 | return { 46 | provider: window.starknet.provider, 47 | chainId: 5, 48 | ...(account ? { account } : {}), 49 | ...(connectedAddress ? { connectedAddress } : {}), 50 | }; 51 | } 52 | 53 | private handleAccountsChanged(accountAddresses: string[]) { 54 | if (__DEV__) { 55 | console.log( 56 | "Handling 'accountsChanged' event with payload", 57 | accountAddresses 58 | ); 59 | } 60 | 61 | if (accountAddresses.length === 0) { 62 | this.emitDeactivate(); 63 | } else { 64 | this.emitUpdate({ connectedAddress: accountAddresses[0] }); 65 | } 66 | } 67 | 68 | public async getProvider(): Promise { 69 | return window.starknet?.provider; 70 | } 71 | 72 | /** 73 | * @deprecated Use getAccount() 74 | * @returns AccountInterface 75 | */ 76 | public getSigner(): AccountInterface | undefined { 77 | if (!window.starknet) { 78 | throw new NoStarknetProviderError(); 79 | } 80 | 81 | return window.starknet.account; 82 | } 83 | 84 | public async getChainId(): Promise { 85 | if (!window.starknet) { 86 | throw new NoStarknetProviderError(); 87 | } 88 | 89 | // Temporary 90 | return 5; 91 | } 92 | 93 | public getAccount(): AccountInterface | undefined { 94 | if (!window.starknet) { 95 | throw new NoStarknetProviderError(); 96 | } 97 | 98 | return window.starknet.account; 99 | } 100 | 101 | public getConnectedAddress(): string | null { 102 | if (!window.starknet) { 103 | throw new NoStarknetProviderError(); 104 | } 105 | 106 | const address = window.starknet.selectedAddress; 107 | 108 | return address ? address : null; 109 | } 110 | 111 | public deactivate(): void { 112 | if (window.starknet) { 113 | this.handleAccountsChanged([]); 114 | } 115 | } 116 | 117 | public async isAuthorized(): Promise { 118 | let account; 119 | if (!window.starknet) { 120 | return false; 121 | } else if (window.starknet.selectedAddress) { 122 | account = window.starknet.selectedAddress; 123 | } else { 124 | [account] = await window.starknet.enable(); 125 | } 126 | 127 | return !!account; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /packages/argentx-connector/src/types.ts: -------------------------------------------------------------------------------- 1 | export type EventHandler = (accounts: string[]) => void; 2 | 3 | interface WatchAssetParameters { 4 | type: 'ERC20'; // The asset's interface, e.g. 'ERC20' 5 | options: { 6 | address: string; // The hexadecimal StarkNet address of the token contract 7 | symbol?: string; // A ticker symbol or shorthand, up to 5 alphanumerical characters 8 | decimals?: number; // The number of asset decimals 9 | image?: string; // A string url of the token logo 10 | name?: string; // The name of the token - not in spec 11 | }; 12 | } 13 | 14 | export type RpcMessage = { 15 | type: 'wallet_watchAsset'; 16 | params: WatchAssetParameters; 17 | }; 18 | 19 | // eslint-disable-next-line @typescript-eslint/interface-name-prefix 20 | // interface IStarknetWindowObject { 21 | // enable: () => Promise; 22 | // on: (method: 'accountsChanged', handleEvent: EventHandler) => void; 23 | // off: (event: 'accountsChanged', handleEvent: EventHandler) => void; 24 | // signer?: import('@jediswap/starknet').SignerInterface; 25 | // provider: import('@jediswap/starknet').Provider; 26 | // selectedAddress?: string; 27 | // request: (call: RpcMessage) => Promise; 28 | // } 29 | 30 | interface IStarknetWindowObject { 31 | request: (call: RpcMessage) => Promise; 32 | enable: (options?: { showModal?: boolean }) => Promise; 33 | isPreauthorized: () => Promise; 34 | on: (event: 'accountsChanged', handleEvent: EventHandler) => void; 35 | off: (event: 'accountsChanged', handleEvent: EventHandler) => void; 36 | account?: import('starknet').AccountInterface; 37 | provider: import('starknet').Provider; 38 | selectedAddress?: string; 39 | version: string; 40 | } 41 | 42 | interface ConnectedStarknetWindowObject extends IStarknetWindowObject { 43 | isConnected: true; 44 | account: import('starknet').AccountInterface; 45 | selectedAddress: string; 46 | } 47 | 48 | interface DisconnectedStarknetWindowObject extends IStarknetWindowObject { 49 | isConnected: false; 50 | } 51 | 52 | export type StarknetWindowObject = 53 | | ConnectedStarknetWindowObject 54 | | DisconnectedStarknetWindowObject; 55 | 56 | declare global { 57 | interface Window { 58 | starknet?: StarknetWindowObject; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/argentx-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "rootDir": "./", 6 | "baseUrl": "./", 7 | "paths": { 8 | "*": ["src/*", "node_modules/*"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/braavos-connector/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | .rts2_cache_cjs 6 | .rts2_cache_esm 7 | .rts2_cache_umd 8 | .rts2_cache_system 9 | dist 10 | .idea 11 | -------------------------------------------------------------------------------- /packages/braavos-connector/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | ----------- 3 | 4 | Copyright (c) 2022 avimak 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /packages/braavos-connector/README.md: -------------------------------------------------------------------------------- 1 | # @web3-starknet-react/braavos-connector 2 | 3 | Please visit the [parent `web3-starknet-react` repository](https://github.com/dhruvkelawala/web3-starknet-react/) for documentation and details on this package. 4 | -------------------------------------------------------------------------------- /packages/braavos-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@web3-starknet-react/braavos-connector", 3 | "publishConfig": { 4 | "access": "public" 5 | }, 6 | "version": "2.1.1", 7 | "author": "avimak@braavos.app", 8 | "main": "dist/index.js", 9 | "module": "dist/braavos-connector.esm.js", 10 | "typings": "dist/index.d.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "start": "tsdx watch", 16 | "build": "tsdx build", 17 | "test": "tsdx test --env=jsdom", 18 | "lint": "tsdx lint" 19 | }, 20 | "peerDependencies": { 21 | "react": ">=16" 22 | }, 23 | "husky": { 24 | "hooks": { 25 | "pre-commit": "tsdx lint" 26 | } 27 | }, 28 | "prettier": { 29 | "printWidth": 80, 30 | "semi": true, 31 | "singleQuote": true, 32 | "trailingComma": "es5" 33 | }, 34 | "dependencies": { 35 | "@web3-starknet-react/abstract-connector": "^2.1.0", 36 | "@web3-starknet-react/types": "^2.1.0" 37 | }, 38 | "devDependencies": { 39 | "get-starknet": "^1.0.0" 40 | }, 41 | "gitHead": "b893495a21b7d761d895aac9e89666875c315e7b" 42 | } 43 | -------------------------------------------------------------------------------- /packages/braavos-connector/src/declarations.ts: -------------------------------------------------------------------------------- 1 | declare const __DEV__: boolean; 2 | -------------------------------------------------------------------------------- /packages/braavos-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AbstractConnector } from '@web3-starknet-react/abstract-connector'; 2 | import { ConnectorUpdate } from '@web3-starknet-react/types'; 3 | import { AccountInterface } from 'starknet'; 4 | import { IStarknetWindowObject } from 'get-starknet'; 5 | 6 | export class NoStarknetProviderError extends Error { 7 | public constructor() { 8 | super(); 9 | this.name = this.constructor.name; 10 | this.message = 'No Starknet Provider was found on window object'; 11 | } 12 | } 13 | 14 | export class BraavosConnector extends AbstractConnector { 15 | public async activate(): Promise { 16 | const wallet = this.getBraavosWallet(); 17 | 18 | if (!wallet) { 19 | throw new NoStarknetProviderError(); 20 | } 21 | 22 | wallet.on('accountsChanged', this.handleAccountsChanged); 23 | 24 | let account: AccountInterface | undefined = wallet.account; 25 | let connectedAddress: string | undefined = wallet.selectedAddress; 26 | 27 | if (!connectedAddress) { 28 | [connectedAddress] = (await wallet.enable()) ?? []; 29 | account = wallet.account; 30 | } 31 | 32 | return { 33 | provider: wallet.provider, 34 | chainId: 5, 35 | ...(account ? { account } : {}), 36 | ...(connectedAddress ? { connectedAddress } : {}), 37 | }; 38 | } 39 | 40 | private handleAccountsChanged = (accountAddresses: string[]) => { 41 | if (__DEV__) { 42 | console.log( 43 | "Handling 'accountsChanged' event with payload", 44 | accountAddresses 45 | ); 46 | } 47 | 48 | if (accountAddresses.length === 0) { 49 | this.emitDeactivate(); 50 | } else { 51 | this.emitUpdate({ connectedAddress: accountAddresses[0] }); 52 | } 53 | }; 54 | 55 | public async getProvider(): Promise { 56 | return this.getBraavosWallet()?.provider; 57 | } 58 | 59 | /** 60 | * @deprecated Use getAccount() 61 | * @returns AccountInterface 62 | */ 63 | public getSigner(): AccountInterface | undefined { 64 | return this.getAccount(); 65 | } 66 | 67 | public async getChainId(): Promise { 68 | const wallet = this.getBraavosWallet(); 69 | if (!wallet) { 70 | throw new NoStarknetProviderError(); 71 | } 72 | 73 | // Temporary 74 | return 5; 75 | } 76 | 77 | public getAccount(): AccountInterface | undefined { 78 | const wallet = this.getBraavosWallet(); 79 | if (!wallet) { 80 | throw new NoStarknetProviderError(); 81 | } 82 | 83 | return wallet.account; 84 | } 85 | 86 | public getConnectedAddress(): string | null { 87 | const wallet = this.getBraavosWallet(); 88 | if (!wallet) { 89 | throw new NoStarknetProviderError(); 90 | } 91 | 92 | return wallet.selectedAddress || null; 93 | } 94 | 95 | public deactivate(): void { 96 | if (this.getBraavosWallet()) { 97 | this.handleAccountsChanged([]); 98 | } 99 | } 100 | 101 | public async isAuthorized(): Promise { 102 | const wallet = this.getBraavosWallet(); 103 | return wallet?.isPreauthorized() ?? false; 104 | } 105 | 106 | private getBraavosWallet = (): IStarknetWindowObject | undefined => 107 | [window.starknet, window.starknet_braavos].find( 108 | obj => obj?.id === 'braavos' 109 | ); 110 | } 111 | -------------------------------------------------------------------------------- /packages/braavos-connector/src/types.ts: -------------------------------------------------------------------------------- 1 | import { IStarknetWindowObject } from 'get-starknet'; 2 | 3 | declare global { 4 | interface Window { 5 | starknet?: IStarknetWindowObject; 6 | starknet_braavos?: IStarknetWindowObject; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/braavos-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "rootDir": "./", 6 | "baseUrl": "./", 7 | "paths": { 8 | "*": ["src/*", "node_modules/*"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | .rts2_cache_cjs 6 | .rts2_cache_esm 7 | .rts2_cache_umd 8 | .rts2_cache_system 9 | dist 10 | -------------------------------------------------------------------------------- /packages/core/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 dhruvkelawala 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. 22 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | # @web3-starknet-react/core 2 | 3 | Please visit the [parent `web3-starknet-react` repository](https://github.com/dhruvkelawala/web3-starknet-react/) for documentation and details on this package. 4 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@web3-starknet-react/core", 3 | "publishConfig": { 4 | "access": "public" 5 | }, 6 | "version": "2.1.0", 7 | "author": "Dhruv Kelawala ", 8 | "main": "dist/index.js", 9 | "module": "dist/core.esm.js", 10 | "typings": "dist/index.d.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "start": "tsdx watch", 16 | "build": "tsdx build", 17 | "test": "tsdx test --env=jsdom", 18 | "lint": "tsdx lint" 19 | }, 20 | "peerDependencies": { 21 | "react": ">=16" 22 | }, 23 | "husky": { 24 | "hooks": { 25 | "pre-commit": "tsdx lint" 26 | } 27 | }, 28 | "prettier": { 29 | "printWidth": 80, 30 | "semi": true, 31 | "singleQuote": true, 32 | "trailingComma": "es5" 33 | }, 34 | "dependencies": { 35 | "@web3-starknet-react/abstract-connector": "^2.1.0", 36 | "@web3-starknet-react/types": "^2.1.0" 37 | }, 38 | "gitHead": "b893495a21b7d761d895aac9e89666875c315e7b" 39 | } 40 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | createStarknetReactRoot, 3 | StarknetReactProvider, 4 | useStarknetReact, 5 | getStarknetReactContext, 6 | PRIMARY_KEY, 7 | } from './provider'; 8 | export { UnsupportedChainIdError } from './manager'; 9 | export { normalizeAccount, normalizeChainId } from './normalizers'; 10 | -------------------------------------------------------------------------------- /packages/core/src/manager.ts: -------------------------------------------------------------------------------- 1 | import { AbstractConnector } from '@web3-starknet-react/abstract-connector'; 2 | import { AccountInterface, Provider } from 'starknet'; 3 | import { useReducer, useEffect, useCallback, useRef } from 'react'; 4 | import { ConnectorUpdate, ConnectorEvent } from '@web3-starknet-react/types'; 5 | import warning from 'tiny-warning'; 6 | 7 | import { StarknetReactManagerReturn } from './types'; 8 | import { normalizeAccount, normalizeChainId } from './normalizers'; 9 | 10 | class StaleConnectorError extends Error { 11 | constructor() { 12 | super(); 13 | this.name = this.constructor.name; 14 | } 15 | } 16 | 17 | export class UnsupportedChainIdError extends Error { 18 | public constructor( 19 | unsupportedChainId: number, 20 | supportedChainIds?: readonly number[] 21 | ) { 22 | super(); 23 | this.name = this.constructor.name; 24 | this.message = `Unsupported chain id: ${unsupportedChainId}. Supported chain ids are: ${supportedChainIds}.`; 25 | } 26 | } 27 | 28 | interface StarknetReactManagerState { 29 | connector?: AbstractConnector; 30 | provider?: Provider; 31 | chainId?: number; 32 | account?: AccountInterface | null; 33 | connectedAddress?: string | null; 34 | 35 | onError?: (error: Error | unknown) => void; 36 | 37 | error?: Error; 38 | } 39 | 40 | enum ActionType { 41 | ACTIVATE_CONNECTOR, 42 | UPDATE, 43 | UPDATE_FROM_ERROR, 44 | ERROR, 45 | ERROR_FROM_ACTIVATION, 46 | DEACTIVATE_CONNECTOR, 47 | } 48 | 49 | interface Action { 50 | type: ActionType; 51 | payload?: any; 52 | } 53 | 54 | function reducer( 55 | state: StarknetReactManagerState, 56 | { type, payload }: Action 57 | ): StarknetReactManagerState { 58 | switch (type) { 59 | case ActionType.ACTIVATE_CONNECTOR: { 60 | const { 61 | connector, 62 | provider, 63 | chainId, 64 | account, 65 | connectedAddress, 66 | onError, 67 | } = payload; 68 | return { 69 | connector, 70 | provider, 71 | chainId, 72 | account, 73 | connectedAddress, 74 | onError, 75 | }; 76 | } 77 | case ActionType.UPDATE: { 78 | const { provider, chainId, account, connectedAddress } = payload; 79 | return { 80 | ...state, 81 | ...(provider === undefined ? {} : { provider }), 82 | ...(chainId === undefined ? {} : { chainId }), 83 | ...(account === undefined ? {} : { account }), 84 | ...(connectedAddress === undefined ? {} : { connectedAddress }), 85 | }; 86 | } 87 | case ActionType.UPDATE_FROM_ERROR: { 88 | const { provider, chainId, account, connectedAddress } = payload; 89 | return { 90 | ...state, 91 | ...(provider === undefined ? {} : { provider }), 92 | ...(chainId === undefined ? {} : { chainId }), 93 | ...(account === undefined ? {} : { account }), 94 | ...(connectedAddress === undefined ? {} : { connectedAddress }), 95 | error: undefined, 96 | }; 97 | } 98 | case ActionType.ERROR: { 99 | const { error } = payload; 100 | const { connector, onError } = state; 101 | return { 102 | connector, 103 | error, 104 | onError, 105 | }; 106 | } 107 | case ActionType.ERROR_FROM_ACTIVATION: { 108 | const { connector, error } = payload; 109 | return { 110 | connector, 111 | error, 112 | }; 113 | } 114 | case ActionType.DEACTIVATE_CONNECTOR: { 115 | return {}; 116 | } 117 | } 118 | } 119 | 120 | async function augmentConnectorUpdate( 121 | connector: AbstractConnector, 122 | update: ConnectorUpdate 123 | ): Promise> { 124 | const provider = 125 | update.provider === undefined 126 | ? await connector.getProvider() 127 | : update.provider; 128 | const [_chainId, _account, _connectedAddress] = (await Promise.all([ 129 | update.chainId === undefined ? connector.getChainId() : update.chainId, 130 | update.account === undefined ? connector.getAccount() : update.account, 131 | update.connectedAddress === undefined 132 | ? connector.getConnectedAddress() 133 | : update.connectedAddress, 134 | ])) as [ 135 | Required['chainId'], 136 | Required['account'], 137 | Required['connectedAddress'] 138 | ]; 139 | 140 | const chainId = normalizeChainId(_chainId); 141 | if ( 142 | !!connector.supportedChainIds && 143 | !connector.supportedChainIds.includes(chainId) 144 | ) { 145 | throw new UnsupportedChainIdError(chainId, connector.supportedChainIds); 146 | } 147 | const connectedAddress = 148 | _connectedAddress === null 149 | ? _connectedAddress 150 | : normalizeAccount(_connectedAddress); 151 | 152 | return { 153 | provider, 154 | chainId, 155 | account: _account, 156 | connectedAddress, 157 | }; 158 | } 159 | 160 | export function useStarknetReactManager(): StarknetReactManagerReturn { 161 | const [state, dispatch] = useReducer(reducer, {}); 162 | const { 163 | connector, 164 | provider, 165 | chainId, 166 | account, 167 | connectedAddress, 168 | onError, 169 | error, 170 | } = state; 171 | 172 | const updateBusterRef = useRef(-1); 173 | updateBusterRef.current += 1; 174 | 175 | const activate = useCallback( 176 | async ( 177 | connector: AbstractConnector, 178 | onError?: (error: Error | unknown) => void, 179 | throwErrors: boolean = false 180 | ): Promise => { 181 | const updateBusterInitial = updateBusterRef.current; 182 | 183 | let activated = false; 184 | try { 185 | const update = await connector.activate().then( 186 | (update): ConnectorUpdate => { 187 | activated = true; 188 | return update; 189 | } 190 | ); 191 | 192 | const augmentedUpdate = await augmentConnectorUpdate(connector, update); 193 | 194 | if (updateBusterRef.current > updateBusterInitial) { 195 | throw new StaleConnectorError(); 196 | } 197 | dispatch({ 198 | type: ActionType.ACTIVATE_CONNECTOR, 199 | payload: { connector, ...augmentedUpdate, onError }, 200 | }); 201 | } catch (error) { 202 | if (error instanceof StaleConnectorError) { 203 | activated && connector.deactivate(); 204 | warning(false, `Suppressed stale connector activation ${connector}`); 205 | } else if (throwErrors) { 206 | activated && connector.deactivate(); 207 | throw error; 208 | } else if (onError) { 209 | activated && connector.deactivate(); 210 | onError(error); 211 | } else { 212 | // we don't call activated && connector.deactivate() here because it'll be handled in the useEffect 213 | dispatch({ 214 | type: ActionType.ERROR_FROM_ACTIVATION, 215 | payload: { connector, error }, 216 | }); 217 | } 218 | } 219 | }, 220 | [] 221 | ); 222 | 223 | const setError = useCallback((error: Error): void => { 224 | dispatch({ type: ActionType.ERROR, payload: { error } }); 225 | }, []); 226 | 227 | const deactivate = useCallback((): void => { 228 | dispatch({ type: ActionType.DEACTIVATE_CONNECTOR }); 229 | }, []); 230 | 231 | const handleUpdate = useCallback( 232 | async (update: ConnectorUpdate): Promise => { 233 | if (!connector) { 234 | throw Error( 235 | "This should never happen, it's just so Typescript stops complaining" 236 | ); 237 | } 238 | 239 | const updateBusterInitial = updateBusterRef.current; 240 | 241 | // updates are handled differently depending on whether the connector is active vs in an error state 242 | if (!error) { 243 | const chainId = 244 | update.chainId === undefined 245 | ? undefined 246 | : normalizeChainId(update.chainId); 247 | if ( 248 | chainId !== undefined && 249 | !!connector.supportedChainIds && 250 | !connector.supportedChainIds.includes(chainId) 251 | ) { 252 | const error = new UnsupportedChainIdError( 253 | chainId, 254 | connector.supportedChainIds 255 | ); 256 | onError 257 | ? onError(error) 258 | : dispatch({ type: ActionType.ERROR, payload: { error } }); 259 | } else { 260 | const connectedAddress = 261 | typeof update.connectedAddress === 'string' 262 | ? normalizeAccount(update.connectedAddress) 263 | : update.connectedAddress; 264 | dispatch({ 265 | type: ActionType.UPDATE, 266 | payload: { 267 | provider: update.provider, 268 | account: update.account, 269 | connectedAddress, 270 | chainId, 271 | }, 272 | }); 273 | } 274 | } else { 275 | try { 276 | const augmentedUpdate = await augmentConnectorUpdate( 277 | connector, 278 | update 279 | ); 280 | 281 | if (updateBusterRef.current > updateBusterInitial) { 282 | throw new StaleConnectorError(); 283 | } 284 | dispatch({ 285 | type: ActionType.UPDATE_FROM_ERROR, 286 | payload: augmentedUpdate, 287 | }); 288 | } catch (error) { 289 | if (error instanceof StaleConnectorError) { 290 | warning( 291 | false, 292 | `Suppressed stale connector update from error state ${connector} ${update}` 293 | ); 294 | } else { 295 | // though we don't have to, we're re-circulating the new error 296 | onError 297 | ? onError(error) 298 | : dispatch({ type: ActionType.ERROR, payload: { error } }); 299 | } 300 | } 301 | } 302 | }, 303 | [connector, error, onError] 304 | ); 305 | const handleError = useCallback( 306 | (error: Error): void => { 307 | onError 308 | ? onError(error) 309 | : dispatch({ type: ActionType.ERROR, payload: { error } }); 310 | }, 311 | [onError] 312 | ); 313 | const handleDeactivate = useCallback((): void => { 314 | dispatch({ type: ActionType.DEACTIVATE_CONNECTOR }); 315 | }, []); 316 | 317 | // ensure that connectors which were set are deactivated 318 | useEffect((): (() => void) => { 319 | return () => { 320 | if (connector) { 321 | connector.deactivate(); 322 | } 323 | }; 324 | }, [connector]); 325 | 326 | // ensure that events emitted from the set connector are handled appropriately 327 | useEffect((): (() => void) => { 328 | if (connector) { 329 | connector 330 | .on(ConnectorEvent.Update, handleUpdate) 331 | .on(ConnectorEvent.Error, handleError) 332 | .on(ConnectorEvent.Deactivate, handleDeactivate); 333 | } 334 | 335 | return () => { 336 | if (connector) { 337 | connector 338 | .off(ConnectorEvent.Update, handleUpdate) 339 | .off(ConnectorEvent.Error, handleError) 340 | .off(ConnectorEvent.Deactivate, handleDeactivate); 341 | } 342 | }; 343 | }, [connector, handleUpdate, handleError, handleDeactivate]); 344 | 345 | return { 346 | connector, 347 | provider, 348 | chainId, 349 | account, 350 | connectedAddress, 351 | activate, 352 | setError, 353 | deactivate, 354 | error, 355 | }; 356 | } 357 | -------------------------------------------------------------------------------- /packages/core/src/normalizers.ts: -------------------------------------------------------------------------------- 1 | import invariant from 'tiny-invariant'; 2 | import { validateAndParseAddress } from 'starknet'; 3 | 4 | export function normalizeChainId(chainId: string | number): number { 5 | if (typeof chainId === 'string') { 6 | chainId = chainId.replace(/^Ox/, '0x'); 7 | 8 | const parsedChainId = Number.parseInt( 9 | chainId, 10 | chainId.trim().substring(0, 2) === '0x' ? 16 : 10 11 | ); 12 | invariant( 13 | !Number.isNaN(parsedChainId), 14 | `chainId ${chainId} is not an integer` 15 | ); 16 | return parsedChainId; 17 | } else { 18 | invariant( 19 | Number.isInteger(chainId), 20 | `chainId ${chainId} is not an integer` 21 | ); 22 | return chainId; 23 | } 24 | } 25 | 26 | export function normalizeAccount(address: string): string { 27 | const starknetAddress = validateAndParseAddress(address); 28 | 29 | return starknetAddress; 30 | } 31 | -------------------------------------------------------------------------------- /packages/core/src/provider.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext, useMemo } from 'react'; 2 | import invariant from 'tiny-invariant'; 3 | 4 | import { StarknetReactContextInterface } from './types'; 5 | import { useStarknetReactManager } from './manager'; 6 | import { Provider } from 'starknet'; 7 | 8 | export const PRIMARY_KEY = 'primary'; 9 | 10 | const CONTEXTS: { 11 | [key: string]: React.Context; 12 | } = {}; 13 | 14 | interface StarknetReactProviderArguments { 15 | getLibrary: ( 16 | provider?: Provider, 17 | connector?: Required['connector'] 18 | ) => Provider; 19 | children: any; 20 | } 21 | 22 | export function createStarknetReactRoot( 23 | key: string 24 | ): (args: StarknetReactProviderArguments) => JSX.Element { 25 | invariant(!CONTEXTS[key], `A root already exists for provided key ${key}`); 26 | 27 | CONTEXTS[key] = createContext({ 28 | activate: async () => { 29 | invariant(false, 'No found'); 30 | }, 31 | setError: () => { 32 | invariant(false, 'No found.'); 33 | }, 34 | deactivate: () => { 35 | invariant(false, 'No found.'); 36 | }, 37 | active: false, 38 | }); 39 | 40 | CONTEXTS[key].displayName = `StarknetReactContext - ${key}`; 41 | 42 | const Provider = CONTEXTS[key].Provider; 43 | 44 | return function StarknetReactProvider({ 45 | getLibrary, 46 | children, 47 | }: StarknetReactProviderArguments): JSX.Element { 48 | const { 49 | connector, 50 | provider, 51 | chainId, 52 | account, 53 | connectedAddress, 54 | activate, 55 | setError, 56 | deactivate, 57 | error, 58 | } = useStarknetReactManager(); 59 | 60 | const active = 61 | connector !== undefined && 62 | chainId !== undefined && 63 | account !== undefined && 64 | !!!error; 65 | 66 | const library = useMemo( 67 | () => 68 | active && 69 | chainId !== undefined && 70 | Number.isInteger(chainId) && 71 | !!connector 72 | ? getLibrary(provider, connector) 73 | : undefined, 74 | [active, getLibrary, provider, connector, chainId] 75 | ); 76 | 77 | const starknetReactContext: StarknetReactContextInterface = { 78 | connector, 79 | library, 80 | activate, 81 | active, 82 | deactivate, 83 | setError, 84 | account, 85 | connectedAddress, 86 | chainId, 87 | error, 88 | }; 89 | 90 | return {children}; 91 | }; 92 | } 93 | 94 | export const StarknetReactProvider = createStarknetReactRoot(PRIMARY_KEY); 95 | 96 | export function getStarknetReactContext( 97 | key: string = PRIMARY_KEY 98 | ): React.Context> { 99 | invariant(Object.keys(CONTEXTS).includes(key), `Invalid key ${key}`); 100 | return CONTEXTS[key]; 101 | } 102 | 103 | export function useStarknetReact( 104 | key?: string 105 | ): StarknetReactContextInterface { 106 | return useContext(getStarknetReactContext(key)); 107 | } 108 | -------------------------------------------------------------------------------- /packages/core/src/types.ts: -------------------------------------------------------------------------------- 1 | import { AbstractConnector } from '@web3-starknet-react/abstract-connector'; 2 | import { Provider, AccountInterface } from 'starknet'; 3 | 4 | export interface StarknetReactManagerFunction { 5 | activate: ( 6 | connector: AbstractConnector, 7 | onError?: (error: Error | unknown) => void, 8 | throwsError?: boolean 9 | ) => Promise; 10 | setError: (error: Error) => void; 11 | deactivate: () => void; 12 | } 13 | 14 | export interface StarknetReactManagerReturn 15 | extends StarknetReactManagerFunction { 16 | connector?: AbstractConnector; 17 | provider?: Provider; 18 | chainId?: number; 19 | account?: AccountInterface | null; 20 | connectedAddress?: string | null; 21 | 22 | error?: Error; 23 | } 24 | 25 | export interface StarknetReactContextInterface 26 | extends StarknetReactManagerFunction { 27 | connector?: AbstractConnector; 28 | library?: T; 29 | chainId?: number; 30 | account?: AccountInterface | null; 31 | connectedAddress?: string | null; 32 | 33 | active: boolean; 34 | error?: Error; 35 | } 36 | -------------------------------------------------------------------------------- /packages/core/test/normalizers.test.ts: -------------------------------------------------------------------------------- 1 | import { normalizeAccount } from '../src/normalizers'; 2 | 3 | describe('normalizers test', () => { 4 | it('checks if normalizeAcccount works with 64bit address string', () => { 5 | let account = 6 | '0x6eff1d71068df8e6677f59a556151c56ed13e14ad431a9bef6fcb3fc5e6fa7'; 7 | 8 | const normalizedAccount = normalizeAccount(account); 9 | 10 | expect(normalizedAccount).toBe( 11 | '0x006eff1d71068df8e6677f59a556151c56ed13e14ad431a9bef6fcb3fc5e6fa7' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/core/test/provider.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | 4 | import { StarknetReactProvider } from '../src/provider'; 5 | import { Provider } from 'starknet'; 6 | 7 | function getLibrary(provider?: Provider) { 8 | const library = new Provider(provider); 9 | 10 | return library; 11 | } 12 | 13 | function App() { 14 | return ( 15 | 16 |
test!
17 |
18 | ); 19 | } 20 | 21 | describe('it', () => { 22 | it('renders without crashing', () => { 23 | const div = document.createElement('div'); 24 | ReactDOM.render(, div); 25 | ReactDOM.unmountComponentAtNode(div); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src", "test"], 4 | "compilerOptions": { 5 | "rootDir": "./", 6 | "baseUrl": "./", 7 | "paths": { 8 | "*": ["src/*", "node_modules/*"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/types/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | .rts2_cache_cjs 6 | .rts2_cache_esm 7 | .rts2_cache_umd 8 | .rts2_cache_system 9 | dist 10 | -------------------------------------------------------------------------------- /packages/types/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 dhruvkelawala 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. 22 | -------------------------------------------------------------------------------- /packages/types/README.md: -------------------------------------------------------------------------------- 1 | # @web3-starknet-react/types 2 | 3 | Please visit the [parent `web3-starknet-react` repository](https://github.com/dhruvkelawala/web3-starknet-react/) for documentation and details on this package. 4 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@web3-starknet-react/types", 3 | "publishConfig": { 4 | "access": "public" 5 | }, 6 | "version": "2.1.0", 7 | "author": "Dhruv Kelawala ", 8 | "main": "dist/index.js", 9 | "module": "dist/types.esm.js", 10 | "typings": "dist/index.d.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "start": "tsdx watch", 16 | "build": "tsdx build", 17 | "test": "tsdx test --env=jsdom", 18 | "lint": "tsdx lint" 19 | }, 20 | "peerDependencies": { 21 | "react": ">=16" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git://github.com/dhruvkelawala/web3-starknet-react.git" 26 | }, 27 | "gitHead": "b893495a21b7d761d895aac9e89666875c315e7b" 28 | } 29 | -------------------------------------------------------------------------------- /packages/types/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AccountInterface, Provider } from 'starknet' 2 | 3 | export interface AbstractConnectorArguments { 4 | supportedChainIds?: number[] 5 | } 6 | 7 | export interface ConnectorUpdate { 8 | provider?: Provider 9 | chainId?: T 10 | account?: AccountInterface | null 11 | connectedAddress?: string | null 12 | } 13 | 14 | export enum ConnectorEvent { 15 | Update = 'StarknetReactUpdate', 16 | Error = 'StarknetReactError', 17 | Deactivate = 'StarknetReactDeactivate' 18 | } 19 | -------------------------------------------------------------------------------- /packages/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src", "types", "test"], 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | "declaration": true, 9 | "sourceMap": true, 10 | "rootDir": "./", 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "baseUrl": "./", 24 | "paths": { 25 | "*": ["src/*", "node_modules/*"] 26 | }, 27 | "jsx": "react", 28 | "esModuleInterop": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "lib": ["dom", "esnext"], 6 | "importHelpers": true, 7 | "declaration": true, 8 | "sourceMap": true, 9 | "strict": true, 10 | "noImplicitAny": true, 11 | "noImplicitReturns": true, 12 | "strictNullChecks": true, 13 | "strictFunctionTypes": true, 14 | "strictPropertyInitialization": true, 15 | "noImplicitThis": true, 16 | "alwaysStrict": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "moduleResolution": "node", 21 | "jsx": "react", 22 | "esModuleInterop": true 23 | } 24 | } 25 | --------------------------------------------------------------------------------