├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── codeql-analysis.yml │ ├── docusaurus.yml │ ├── lint-workflow.yml │ └── pr-workflow.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierrc ├── .vscode └── settings.json ├── .yarn ├── plugins │ └── @yarnpkg │ │ └── plugin-interactive-tools.cjs └── releases │ └── yarn-3.2.2.cjs ├── .yarnrc.yml ├── README.md ├── package.json ├── packages ├── docusaurus │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── _config.yml │ ├── babel.config.js │ ├── blog │ │ ├── 2022-05-03 React 18 & a Better web3 Login Experience [v4.2.x updates].md │ │ └── authors.yml │ ├── docs │ │ ├── README.md │ │ ├── api │ │ │ ├── _category_.yml │ │ │ ├── classes │ │ │ │ ├── EthersAppContext.CouldNotActivateError.md │ │ │ │ ├── EthersAppContext.EthersModalConnector.md │ │ │ │ ├── EthersAppContext.NoEthereumProviderFoundError.md │ │ │ │ ├── EthersAppContext.NoStaticJsonRPCProviderFoundError.md │ │ │ │ ├── EthersAppContext.UserClosedModalError.md │ │ │ │ ├── TestUtils.MockConnector.md │ │ │ │ └── _category_.yml │ │ │ ├── index.md │ │ │ ├── interfaces │ │ │ │ ├── EthersAppContext.ICommonModalConnector.md │ │ │ │ ├── EthersAppContext.IStaticJsonRpcProviderConnectorOptions.md │ │ │ │ ├── Models.IEthersContext.md │ │ │ │ └── _category_.yml │ │ │ └── modules │ │ │ │ ├── ContractAppContext.md │ │ │ │ ├── EthersAppContext.md │ │ │ │ ├── Helpers-1.md │ │ │ │ ├── Helpers.md │ │ │ │ ├── Hooks.md │ │ │ │ ├── Models.md │ │ │ │ ├── TestUtils.md │ │ │ │ └── _category_.yml │ │ ├── main │ │ │ ├── authors.mdx │ │ │ ├── context │ │ │ │ ├── ContractAppContext.mdx │ │ │ │ ├── EthersAppContext.mdx │ │ │ │ └── _category_.json │ │ │ ├── deep-dive.mdx │ │ │ ├── dependencies.mdx │ │ │ ├── guides │ │ │ │ ├── _category_.json │ │ │ │ ├── intro.md │ │ │ │ ├── tutorial-advanced │ │ │ │ │ ├── _category_.json │ │ │ │ │ └── advanced.mdx │ │ │ │ └── tutorial-basics │ │ │ │ │ ├── _category_.json │ │ │ │ │ └── basic.mdx │ │ │ ├── hooks │ │ │ │ ├── _category_.json │ │ │ │ ├── useBalance.mdx │ │ │ │ ├── useBlockNumber.mdx │ │ │ │ ├── useBlockNumberContext.mdx │ │ │ │ ├── useBurnerSigner.mdx │ │ │ │ ├── useContractExistsAtAddress.mdx │ │ │ │ ├── useContractLoader.mdx │ │ │ │ ├── useContractReader.mdx │ │ │ │ ├── useContractReaderUntyped.mdx │ │ │ │ ├── useDexEthPrice.mdx │ │ │ │ ├── useDexTokenList.mdx │ │ │ │ ├── useEventListener.mdx │ │ │ │ ├── useGasPrice.mdx │ │ │ │ ├── useNonce.mdx │ │ │ │ ├── useResolveEnsAddress.mdx │ │ │ │ ├── useResolveEnsName.mdx │ │ │ │ ├── useSignerAddress.mdx │ │ │ │ └── useTokenBalance.mdx │ │ │ └── license.mdx │ │ └── overview.md │ ├── docusaurus.config.js │ ├── eth-hooks.typedoc.js │ ├── package.json │ ├── sidebars.js │ ├── src │ │ ├── components │ │ │ ├── HomepageEcosystemItems.tsx │ │ │ └── HomepageFeatures.tsx │ │ ├── css │ │ │ └── custom.css │ │ ├── hooks │ │ │ └── themeColorHooks.tsx │ │ └── pages │ │ │ ├── index.module.css │ │ │ ├── index.tsx │ │ │ └── markdown-page.md │ ├── static │ │ ├── .nojekyll │ │ ├── googlefd38dd56cfc4fa75.html │ │ ├── home │ │ │ ├── features1.png │ │ │ ├── features2.png │ │ │ └── features3.png │ │ └── img │ │ │ ├── favicon.ico │ │ │ └── logo.svg │ ├── tailwind.config.js │ └── tsconfig.json ├── eth-hooks │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .mocharc.js │ ├── .npmignore │ ├── .prettierrc │ ├── README.md │ ├── esbuild.shim.js │ ├── hardhat.config.ts │ ├── package.json │ ├── src │ │ ├── context │ │ │ ├── EthersAppState.tsx │ │ │ ├── EthersAppStore.ts │ │ │ ├── contracts-app │ │ │ │ ├── contractConnectors.ts │ │ │ │ ├── contractsContextFactory.tsx │ │ │ │ └── index.ts │ │ │ ├── ethers-app │ │ │ │ ├── EthersAppContext.tsx │ │ │ │ ├── connectors │ │ │ │ │ ├── EthersModalConnector.ts │ │ │ │ │ ├── StaticJsonRpcProviderConnector.ts │ │ │ │ │ ├── connectorErrors.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── queryClient.ts │ │ │ │ └── useBlockNumberContext.tsx │ │ │ └── index.ts │ │ ├── dapps.ts │ │ ├── erc.ts │ │ ├── functions │ │ │ ├── asyncHelpers.ts │ │ │ ├── ethersHelpers.ts │ │ │ ├── hookHelpers.ts │ │ │ ├── index.ts │ │ │ ├── keyHelpers.ts │ │ │ └── parseProviderOrSigner.ts │ │ ├── helpers │ │ │ ├── __global.ts │ │ │ ├── esm-fixtures │ │ │ │ └── web3modal.ts │ │ │ ├── index.ts │ │ │ ├── lazier.ts │ │ │ ├── test-utils │ │ │ │ ├── constants │ │ │ │ │ ├── index.ts │ │ │ │ │ └── testConstants.ts │ │ │ │ ├── eth │ │ │ │ │ ├── hardhatActions.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── functions │ │ │ │ │ ├── conversions.ts │ │ │ │ │ ├── expect.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── mochaHelpers.ts │ │ │ │ │ └── shouldFailWithMessage.ts │ │ │ │ ├── index.ts │ │ │ │ └── wrapper │ │ │ │ │ ├── MockConnector.ts │ │ │ │ │ ├── TestAppWrapper.tsx │ │ │ │ │ ├── getMockProvider.ts │ │ │ │ │ ├── hardhatTestHelpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── testWrapper.tsx │ │ │ │ │ └── wrapperHelpers.ts │ │ │ └── typedoc │ │ │ │ ├── README.md │ │ │ │ ├── contractAppContext.docs.ts │ │ │ │ ├── ethersAppContext.docs.ts │ │ │ │ ├── functions.docs.ts │ │ │ │ ├── helpers.docs.ts │ │ │ │ ├── hooks.docs.ts │ │ │ │ ├── models.docs.ts │ │ │ │ └── test-utils.docs.ts │ │ ├── hooks │ │ │ ├── dapps │ │ │ │ ├── index.ts │ │ │ │ ├── useDexEthPrice.ts │ │ │ │ ├── useDexTokenList.ts │ │ │ │ ├── useResolveEnsAddress.ts │ │ │ │ └── useResolveEnsName.ts │ │ │ ├── erc │ │ │ │ ├── index.ts │ │ │ │ └── useTokenBalance.ts │ │ │ ├── index.ts │ │ │ ├── useAreSignerEqual.ts │ │ │ ├── useBalance.ts │ │ │ ├── useBlockNumber.ts │ │ │ ├── useBurnerSigner.ts │ │ │ ├── useCheckIsMounted.ts │ │ │ ├── useContractExistsAtAddress.ts │ │ │ ├── useContractReader.ts │ │ │ ├── useEthersAdaptorFromProviderOrSigners.ts │ │ │ ├── useEthersUpdater.ts │ │ │ ├── useEventListener.ts │ │ │ ├── useGasPrice.ts │ │ │ ├── useNonce.ts │ │ │ ├── useSignerAddress.ts │ │ │ ├── useSignerChainId.ts │ │ │ └── useTimestamp.ts │ │ ├── index.ts │ │ └── models │ │ │ ├── constants │ │ │ ├── common.ts │ │ │ ├── index.ts │ │ │ └── keyNamespace.ts │ │ │ ├── contractAppContextTypes.ts │ │ │ ├── contractTypes.ts │ │ │ ├── contractTypesDeprecated.ts │ │ │ ├── contractTypesForge.ts │ │ │ ├── contractTypesHardhat.ts │ │ │ ├── ethersAppContextTypes.ts │ │ │ ├── hookTypes.ts │ │ │ ├── index.ts │ │ │ ├── networkTypes.ts │ │ │ ├── providerTypes.ts │ │ │ └── utilityTypes.ts │ ├── test-files │ │ ├── __mocks__ │ │ │ ├── external-contracts │ │ │ │ ├── README.md │ │ │ │ ├── cjs │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── index.js │ │ │ │ │ └── types │ │ │ │ │ │ ├── DAI.d.ts │ │ │ │ │ │ ├── DAI.js │ │ │ │ │ │ ├── UNI.d.ts │ │ │ │ │ │ ├── UNI.js │ │ │ │ │ │ ├── common.d.ts │ │ │ │ │ │ ├── common.js │ │ │ │ │ │ ├── factories │ │ │ │ │ │ ├── DAI__factory.d.ts │ │ │ │ │ │ ├── DAI__factory.js │ │ │ │ │ │ ├── UNI__factory.d.ts │ │ │ │ │ │ └── UNI__factory.js │ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ │ └── index.js │ │ │ │ ├── esm │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── index.js │ │ │ │ │ └── types │ │ │ │ │ │ ├── DAI.d.ts │ │ │ │ │ │ ├── DAI.js │ │ │ │ │ │ ├── UNI.d.ts │ │ │ │ │ │ ├── UNI.js │ │ │ │ │ │ ├── common.d.ts │ │ │ │ │ │ ├── common.js │ │ │ │ │ │ ├── factories │ │ │ │ │ │ ├── DAI__factory.d.ts │ │ │ │ │ │ ├── DAI__factory.js │ │ │ │ │ │ ├── UNI__factory.d.ts │ │ │ │ │ │ └── UNI__factory.js │ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ │ └── index.js │ │ │ │ ├── index.cjs │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.mjs │ │ │ │ ├── package.json │ │ │ │ └── types.d.ts │ │ │ ├── externalContractsForUseContractLoader.ts │ │ │ ├── hardhat_contracts.basic1.json │ │ │ ├── index.ts │ │ │ └── setupMockContracts.ts │ │ ├── contracts │ │ │ ├── BasicERC20Contract.sol │ │ │ └── YourContract.sol │ │ └── deploy │ │ │ └── 00_deploy_your_contract.ts │ ├── test │ │ ├── context │ │ │ ├── BlockNumberContext.test.ts │ │ │ └── EthersAppContext.test.ts │ │ ├── helpers │ │ │ ├── chai-imports.ts │ │ │ ├── hardhat-imports.ts │ │ │ └── mochaRootHooks.ts │ │ ├── useAreSignerEqual.test.ts │ │ ├── useBalance.test.ts │ │ ├── useBlockNumber.test.ts │ │ ├── useContractReader.test.ts │ │ ├── useEventListener.test.ts │ │ ├── useNonce.test.ts │ │ ├── useTimestamp.test.ts │ │ ├── useTokenBalance.test.ts │ │ └── useUserAddress.test.ts │ ├── tsconfig.build.json │ ├── tsconfig.docs.json │ ├── tsconfig.json │ ├── tsconfig.testing.json │ ├── tsconfig.yalc.json │ └── tsup.config.ts ├── wagmi-headless │ ├── .eslintignore │ ├── .eslintrc │ ├── .gitignore │ ├── .mocharc.js │ ├── .npmignore │ ├── .prettierrc │ ├── .vscode │ │ └── settings.json │ ├── README.md │ ├── esbuild.shim.js │ ├── package.json │ ├── src │ │ ├── hooks │ │ │ └── useEthBalance.tsx │ │ └── index.ts │ ├── test │ │ ├── eth-balance.test.ts │ │ └── helpers │ │ │ └── chai-imports.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsconfig.testing.json │ ├── tsconfig.yalc.json │ └── tsup.config.ts └── wagmi-tailwind │ ├── .eslintignore │ ├── .eslintrc │ ├── .gitignore │ ├── .mocharc.js │ ├── .npmignore │ ├── .prettierrc │ ├── .vscode │ └── settings.json │ ├── README.md │ ├── esbuild.shim.js │ ├── package.json │ ├── src │ ├── components │ │ └── Balance.tsx │ └── index.ts │ ├── test │ ├── eth-balance.test.ts │ └── helpers │ │ └── chai-imports.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsconfig.testing.json │ ├── tsconfig.yalc.json │ └── tsup.config.ts ├── tsconfig.build.json ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [packages/**.{j,t}s{,x}] 4 | indent_style = space 5 | indent_size = 2 6 | 7 | [*.{sol,yul}] 8 | indent_style = space 9 | indent_size = 4 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # folders 2 | lib/ 3 | node_modules/ 4 | # files 5 | **/*.less 6 | **/*.css 7 | **/*.scss 8 | **/*.json 9 | **/*.png 10 | **/*.svg 11 | **/generated/**/* 12 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: 'CodeQL checks' 13 | 14 | on: 15 | workflow_dispatch: 16 | push: 17 | branches: [next, release] 18 | pull_request: 19 | # The branches below must be a subset of the branches above 20 | schedule: 21 | - cron: '0 4 */7 * *' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: ['javascript'] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.github/workflows/docusaurus.yml: -------------------------------------------------------------------------------- 1 | name: deploy-docusaurus 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [next] 7 | pull_request: 8 | branches: [next] 9 | types: [opened, reopened, ready_for_review, synchronize] 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | publish: 14 | runs-on: ubuntu-latest 15 | steps: 16 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 17 | - name: Check out repo 18 | uses: actions/checkout@v2 19 | # Node is required for npm 20 | - name: Set up Node 21 | uses: actions/setup-node@v2 22 | with: 23 | node-version: '16' 24 | 25 | - name: 'cache' 26 | uses: actions/cache@v2 27 | with: 28 | path: | 29 | ~/.yarn 30 | ~/node_modules 31 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 32 | restore-keys: | 33 | ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 34 | 35 | - name: Build eth-hooks 36 | run: | 37 | yarn install 38 | - name: Build test artifacts 39 | run: | 40 | yarn install 41 | yarn eth-hooks hardhat:compile 42 | 43 | - name: Build Docusaurus website 44 | run: | 45 | yarn docs build 46 | 47 | - name: Deploy to GitHub Pages 48 | if: success() && contains('refs/heads/next', github.ref) 49 | uses: crazy-max/ghaction-github-pages@v2 50 | with: 51 | target_branch: docusaurus 52 | build_dir: packages/docusaurus/build 53 | env: 54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 55 | -------------------------------------------------------------------------------- /.github/workflows/lint-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Code check workflows 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [release, next] 7 | pull_request: 8 | types: [opened, reopened, ready_for_review, synchronize] 9 | 10 | # Down scope as necessary via https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token 11 | permissions: 12 | checks: write 13 | contents: write 14 | 15 | jobs: 16 | run-linters: 17 | name: Run linters 18 | runs-on: ubuntu-latest 19 | 20 | strategy: 21 | matrix: 22 | node-version: [16.x] 23 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 24 | 25 | steps: 26 | - uses: actions/checkout@v2 27 | 28 | - name: Use Node.js ${{ matrix.node-version }} 29 | uses: actions/setup-node@v2 30 | with: 31 | node-version: ${{ matrix.node-version }} 32 | 33 | - name: 'cache' 34 | uses: actions/cache@v2 35 | with: 36 | path: | 37 | ~/.yarn 38 | ~/node_modules 39 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 40 | restore-keys: | 41 | ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 42 | 43 | - run: yarn install --immutable 44 | 45 | # Install your linters here 46 | 47 | - name: Save Code Linting Report JSON 48 | # npm script for ESLint 49 | # eslint --output-file eslint_report.json --format json src 50 | # See https://eslint.org/docs/user-guide/command-line-interface#options 51 | run: yarn lint:report --quiet 52 | # Continue to the next step even if this fails 53 | continue-on-error: true 54 | - name: Annotate Code Linting Results 55 | uses: ataylorme/eslint-annotate-action@1.2.0 56 | with: 57 | repo-token: '${{ secrets.GITHUB_TOKEN }}' 58 | report-json: 'eslint_report.json' 59 | - name: Upload ESLint report 60 | uses: actions/upload-artifact@v2 61 | with: 62 | name: eslint_report.json 63 | path: eslint_report.json 64 | -------------------------------------------------------------------------------- /.github/workflows/pr-workflow.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: PR workflow checks 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | branches: [release, next] 10 | pull_request: 11 | types: [opened, reopened, ready_for_review, synchronize] 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [14.x, 16.x] 20 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v2 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | - name: 'cache' 29 | uses: actions/cache@v2 30 | with: 31 | path: | 32 | ~/.yarn 33 | ~/node_modules 34 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 35 | restore-keys: | 36 | ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 37 | 38 | - run: yarn install --immutable 39 | - run: yarn eth-hooks run build 40 | 41 | - run: yarn eth-hooks test 42 | - name: Publish Unit Test Results 43 | uses: EnricoMi/publish-unit-test-result-action@v1 44 | if: always() 45 | with: 46 | files: ./packages/eth-hooks/testresult.xml 47 | comment_mode: update last 48 | hide_comments: all but latest 49 | compare_to_earlier_commit: true 50 | check_run_annotations: all tests, skipped tests 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # common 2 | lib/ 3 | node_modules/ 4 | 5 | 6 | #eth-hooks 7 | **/*.log 8 | *.tgz 9 | *.tsbuildinfo 10 | **/cache 11 | **/test/testresult.xml 12 | **/testresult.xml 13 | .yarn/install-state.gz 14 | **/generated 15 | .idea 16 | .DS_store 17 | eslint_report.json 18 | 19 | 20 | # Dependencies 21 | /node_modules 22 | 23 | # Production 24 | /build 25 | 26 | # Generated files 27 | .docusaurus 28 | .cache-loader 29 | 30 | # Misc 31 | .DS_Store 32 | .env.local 33 | .env.development.local 34 | .env.test.local 35 | .env.production.local 36 | 37 | npm-debug.log* 38 | yarn-debug.log* 39 | yarn-error.log* 40 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged -v -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "bracketSpacing": true, 4 | "trailingComma": "es5", 5 | "requirePragma": false, 6 | "arrowParens": "always", 7 | "bracketSameLine": true, 8 | "tabWidth": 2, 9 | "printWidth": 120, 10 | "endOfLine": "lf" 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mochaExplorer.files": "test/**/*.{j,t}s", 3 | "mochaExplorer.parallel": true, 4 | "mochaExplorer.timeout": 20000, 5 | "mochaExplorer.configFile": "./mocharc.json", 6 | "mochaExplorer.esmLoader": false, 7 | "terminal.integrated.fontSize": 12, 8 | "editor.tabSize": 2, 9 | "mochaExplorer.optsFile": "", 10 | "search.useIgnoreFiles": true, 11 | "files.exclude": { 12 | "**/.git": true, 13 | "**/.svn": true, 14 | "**/.hg": true, 15 | "**/CVS": true, 16 | "**/.DS_Store": true, 17 | "**/Thumbs.db": true, 18 | "**/.cache": true, 19 | "**/.vs/": true, 20 | "**/*.cs": true, 21 | "**/*.orig": true, 22 | "**/bin/": true, 23 | "**/build/": true, 24 | "**/build/**/*": true, 25 | "**/debug/": true, 26 | "**/dist/": true, 27 | "**/obj": true, 28 | "lib": true 29 | }, 30 | "explorerExclude.backup": null, 31 | "eslint.debug": true, 32 | "eslint.enable": true, 33 | "eslint.workingDirectories": [ 34 | { "directory": "packages/*", "changeProcessCWD": true }, 35 | { "directory": "packages/eth-hooks", "changeProcessCWD": true }, 36 | { "directory": "packages/docusaurus", "changeProcessCWD": true }, 37 | { "directory": "packages/wagmi-headless", "changeProcessCWD": true } 38 | { "directory": "packages/wagmi-tailwind", "changeProcessCWD": true } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | cacheFolder: ./.yarn/cache 2 | 3 | nmHoistingLimits: workspaces 4 | 5 | nodeLinker: node-modules 6 | 7 | 8 | plugins: 9 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 10 | spec: "@yarnpkg/plugin-interactive-tools" 11 | 12 | 13 | yarnPath: .yarn/releases/yarn-3.2.2.cjs 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eth-ui Monorepo 2 | 3 | ### Note: Archived! 4 | #### Please use wagmi as a modern alternative! Please see [scaffold-eth-2](https://github.com/scaffold-eth/scaffold-eth-2) for details on how to use it with scaffold eth 5 | 6 | 7 | ---- 8 | 9 | A monorep for eth ui related packages including [eth-hooks](packages/eth-hooks/README.md) 10 | 11 | --- 12 | 13 | ## 🖇 Eth-hooks Overview 14 | 15 | Commonly used Ethereum hooks to supercharge your web3 dev! 16 | 17 | Used by 🏭 [scaffold-eth-typescript](https://github.com/scaffold-eth/scaffold-eth-typescript), 🏗 [scaffold-eth](https://github.com/scaffold-eth/scaffold-eth) 18 | , [eth-components](https://github.com/scaffold-eth/eth-components) and many other web3 projects! 19 | 20 | Created by 🏰 [BuidlGuidl.eth](https://BuidlGuidl.com) 21 | 22 | > See the [eth-hooks readme](packages/eth-hooks/README.md) for more details. 23 | 24 | ## Author 25 | 26 | [@shravansunder](https://github.com/ShravanSunder) 27 | [@stevenpslade](https://github.com/stevenpslade) 28 | [@grothem](https://github.com/grothem) 29 | 30 | ## Documentation 31 | 32 | ### 📚 Check out the documentation at [Eth-ui-documentation](https://scaffold-eth.github.io/eth-ui/) 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eth-ui", 3 | "version": "0.0.0", 4 | "keywords": [ 5 | "ethereum", 6 | "react", 7 | "uniswap", 8 | "workspaces", 9 | "yarn" 10 | ], 11 | "scripts": { 12 | "eth-hooks": "yarn workspace eth-hooks", 13 | "wagmi-headless": "yarn workspace wagmi-headless", 14 | "wagmi-tailwind": "yarn workspace wagmi-tailwind", 15 | "docs": "yarn workspace documentation", 16 | "postinstall": "husky install", 17 | "lint": "yarn eth-hooks lint && yarn docs lint", 18 | "lint:fix": "yarn eth-hooks lint --fix && yarn docs lint --fix", 19 | "lint:report": "yarn eth-hooks lint:report", 20 | "format": "yarn eth-hooks format && yarn docs format", 21 | "format:check": "yarn eth-hooks format:check && yarn docs format:check" 22 | }, 23 | "private": true, 24 | "workspaces": { 25 | "packages": [ 26 | "packages/*" 27 | ] 28 | }, 29 | "packageManager": "yarn@3.2.2", 30 | "devDependencies": { 31 | "chalk": "4.1.2", 32 | "commander": "^9.4.0", 33 | "cross-env": "^7.0.3", 34 | "eslint": "^8.22.0", 35 | "husky": "^8.0.1", 36 | "lint-staged": "^13.0.3", 37 | "pinst": "^3.0.0", 38 | "prettier": "^2.7.1", 39 | "prettier-plugin-solidity": "^1.0.0-dev.23", 40 | "shx": "^0.3.4", 41 | "syncpack": "^8.2.4", 42 | "ts-node": "^10.9.1" 43 | }, 44 | "lint-staged": { 45 | "packages/eth-hooks/**/*.{ts,tsx}": [ 46 | "yarn workspace eth-hooks lint --fix", 47 | "yarn workspace eth-hooks format" 48 | ], 49 | "packages/wagmi-headless/**/*.{ts,tsx}": [ 50 | "yarn wagmi-headless lint --fix", 51 | "yarn wagmi-headless format" 52 | ], 53 | "packages/wagmi-tailwind/**/*.{ts,tsx}": [ 54 | "yarn wagmi-tailwind lint --fix", 55 | "yarn wagmi-tailwind format" 56 | ], 57 | "packages/docusaurus/src/**/*.{ts,tsx,js,jsx}": [ 58 | "npm run lint --fix", 59 | "npm run format" 60 | ], 61 | "packages/docusaurus/**/*.{json}": [ 62 | "npm run format" 63 | ], 64 | "packages/docusaurus/src/**/*.{md,mdx}": [ 65 | "npm run format" 66 | ] 67 | }, 68 | "volta": { 69 | "node": "16.15.0" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/docusaurus/.eslintignore: -------------------------------------------------------------------------------- 1 | # folders 2 | lib/ 3 | node_modules/**/* 4 | website/**/* 5 | build/**/* 6 | **/*.js* -------------------------------------------------------------------------------- /packages/docusaurus/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /packages/docusaurus/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "printWidth": 120, 5 | "requirePragma": false, 6 | "singleQuote": true, 7 | "tabWidth": 2, 8 | "trailingComma": "es5", 9 | "endOfLine": "lf", 10 | "bracketSameLine": true, 11 | "tailwindConfig": "./tailwind.config.js" 12 | } 13 | -------------------------------------------------------------------------------- /packages/docusaurus/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using Docusaurus 2, a modern static website generator. 4 | 5 | ### Installation 6 | 7 | NOTE: don't use yarn, use npm for docusarus! 8 | 9 | ``` 10 | $ npm 11 | ``` 12 | 13 | ### Local Development 14 | 15 | ``` 16 | $ npm start 17 | ``` 18 | 19 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 20 | 21 | ### Build 22 | 23 | ``` 24 | $ npm build 25 | ``` 26 | 27 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 28 | 29 | ### Deployment 30 | 31 | ``` 32 | $ GIT_USER= USE_SSH=1 yarn deploy 33 | ``` 34 | 35 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 36 | -------------------------------------------------------------------------------- /packages/docusaurus/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /packages/docusaurus/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /packages/docusaurus/blog/2022-05-03 React 18 & a Better web3 Login Experience [v4.2.x updates].md: -------------------------------------------------------------------------------- 1 | ## React 18 Updates 2 | 3 | Eth-hooks, Eth-components and Scaffold-eth-typescript have been updated to React 18. 4 | 5 | React 18 removes `{children: ReactNode}` from `React.FC` and so the library had typescript errors when used with react 18, and all of this should be solved. 6 | 7 | ## Better login / logout error handling 8 | 9 | ### EthersModalConnector 10 | 11 | EthersModalConnectors now throws typed errors that an app could use to show notifications when login and logout fails. 12 | 13 | - Login now has `onError` callback that passes back the typed error 14 | - Logout now also invoke a callback `onSuccess` incase certain actions needed to be taken on logout 15 | 16 | ### How does EthersAppContext tie in? 17 | 18 | Both these can be used via by ethersAppContext as the `modal` uses `EthersModalConnector` to invoke web3-modal. 19 | 20 | ```ts 21 | const ethersAppContext = useEthersAppContext(); 22 | 23 | // loginOnError is the callback that would be called with the error 24 | ethersContext.openModal(connector, loginOnError); 25 | 26 | // logoutOnSuccess is the callback that woudl be called when the app successfully logs out of the users wallet 27 | ethersAppContext.disconnectModal(props.logoutOnSuccess); 28 | ``` 29 | -------------------------------------------------------------------------------- /packages/docusaurus/blog/authors.yml: -------------------------------------------------------------------------------- 1 | endi: 2 | name: Shravan Sunder 3 | title: Developer for Eth-hooks & Scaffold-eth-typescript 4 | url: https://github.com/shravansunder 5 | image_url: https://github.com/shravansunder.png 6 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/README.md: -------------------------------------------------------------------------------- 1 | # 🖇 Eth-hooks 2 | 3 | Commonly used react hooks to improve Ethereum Dapp development. 4 | 5 | - Used by 🏗 [scaffold-eth](https://github.com/scaffold-eth/scaffold-eth) 6 | 7 | - Used by ⚙ [eth-components](https://github.com/scaffold-eth/eth-components) 8 | 9 | Created by the 🏰 [BuidlGuidl.eth](https://BuidlGuidl.com) 10 | 11 | ## Overview 12 | 13 | [Eth-hooks Overview](./overview.md) 14 | 15 | ## API 16 | 17 | [Eth-hooks API](./api/index.md) 18 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "API" -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/classes/EthersAppContext.CouldNotActivateError.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "EthersAppContext.CouldNotActivateError" 3 | title: "Class: CouldNotActivateError" 4 | sidebar_label: "CouldNotActivateError" 5 | custom_edit_url: null 6 | --- 7 | 8 | [EthersAppContext](../modules/EthersAppContext.md).CouldNotActivateError 9 | 10 | ## Hierarchy 11 | 12 | - `Error` 13 | 14 | ↳ **`CouldNotActivateError`** 15 | 16 | ## Constructors 17 | 18 | ### constructor 19 | 20 | • **new CouldNotActivateError**(`error`) 21 | 22 | #### Parameters 23 | 24 | | Name | Type | 25 | | :------ | :------ | 26 | | `error` | `unknown` | 27 | 28 | #### Overrides 29 | 30 | Error.constructor 31 | 32 | #### Defined in 33 | 34 | [src/context/ethers-app/connectors/connectorErrors.ts:23](https://github.com/scaffold-eth/eth-hooks/blob/951f765/packages/eth-hooks/src/context/ethers-app/connectors/connectorErrors.ts#L23) 35 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/classes/EthersAppContext.NoEthereumProviderFoundError.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "EthersAppContext.NoEthereumProviderFoundError" 3 | title: "Class: NoEthereumProviderFoundError" 4 | sidebar_label: "NoEthereumProviderFoundError" 5 | custom_edit_url: null 6 | --- 7 | 8 | [EthersAppContext](../modules/EthersAppContext.md).NoEthereumProviderFoundError 9 | 10 | ## Hierarchy 11 | 12 | - `Error` 13 | 14 | ↳ **`NoEthereumProviderFoundError`** 15 | 16 | ## Constructors 17 | 18 | ### constructor 19 | 20 | • **new NoEthereumProviderFoundError**() 21 | 22 | #### Overrides 23 | 24 | Error.constructor 25 | 26 | #### Defined in 27 | 28 | [src/context/ethers-app/connectors/connectorErrors.ts:34](https://github.com/scaffold-eth/eth-hooks/blob/951f765/packages/eth-hooks/src/context/ethers-app/connectors/connectorErrors.ts#L34) 29 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/classes/EthersAppContext.NoStaticJsonRPCProviderFoundError.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "EthersAppContext.NoStaticJsonRPCProviderFoundError" 3 | title: "Class: NoStaticJsonRPCProviderFoundError" 4 | sidebar_label: "NoStaticJsonRPCProviderFoundError" 5 | custom_edit_url: null 6 | --- 7 | 8 | [EthersAppContext](../modules/EthersAppContext.md).NoStaticJsonRPCProviderFoundError 9 | 10 | ## Hierarchy 11 | 12 | - `Error` 13 | 14 | ↳ **`NoStaticJsonRPCProviderFoundError`** 15 | 16 | ## Constructors 17 | 18 | ### constructor 19 | 20 | • **new NoStaticJsonRPCProviderFoundError**(`error`) 21 | 22 | #### Parameters 23 | 24 | | Name | Type | 25 | | :------ | :------ | 26 | | `error` | `unknown` | 27 | 28 | #### Overrides 29 | 30 | Error.constructor 31 | 32 | #### Defined in 33 | 34 | [src/context/ethers-app/connectors/connectorErrors.ts:45](https://github.com/scaffold-eth/eth-hooks/blob/951f765/packages/eth-hooks/src/context/ethers-app/connectors/connectorErrors.ts#L45) 35 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/classes/EthersAppContext.UserClosedModalError.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "EthersAppContext.UserClosedModalError" 3 | title: "Class: UserClosedModalError" 4 | sidebar_label: "UserClosedModalError" 5 | custom_edit_url: null 6 | --- 7 | 8 | [EthersAppContext](../modules/EthersAppContext.md).UserClosedModalError 9 | 10 | ## Hierarchy 11 | 12 | - `Error` 13 | 14 | ↳ **`UserClosedModalError`** 15 | 16 | ## Constructors 17 | 18 | ### constructor 19 | 20 | • **new UserClosedModalError**() 21 | 22 | #### Overrides 23 | 24 | Error.constructor 25 | 26 | #### Defined in 27 | 28 | [src/context/ethers-app/connectors/connectorErrors.ts:12](https://github.com/scaffold-eth/eth-hooks/blob/951f765/packages/eth-hooks/src/context/ethers-app/connectors/connectorErrors.ts#L12) 29 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/classes/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Classes" 2 | position: 3 -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "index" 3 | title: "eth-hooks - v4.6.2" 4 | sidebar_label: "Table of contents" 5 | sidebar_position: 0.5 6 | hide_table_of_contents: true 7 | custom_edit_url: null 8 | --- 9 | 10 | ## Modules 11 | 12 | - [ContractAppContext](modules/ContractAppContext.md) 13 | - [EthersAppContext](modules/EthersAppContext.md) 14 | - [Helpers](modules/Helpers.md) 15 | - [Helpers](modules/Helpers-1.md) 16 | - [Hooks](modules/Hooks.md) 17 | - [Models](modules/Models.md) 18 | - [TestUtils](modules/TestUtils.md) 19 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/interfaces/EthersAppContext.IStaticJsonRpcProviderConnectorOptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "EthersAppContext.IStaticJsonRpcProviderConnectorOptions" 3 | title: "Interface: IStaticJsonRpcProviderConnectorOptions" 4 | sidebar_label: "IStaticJsonRpcProviderConnectorOptions" 5 | custom_edit_url: null 6 | --- 7 | 8 | [EthersAppContext](../modules/EthersAppContext.md).IStaticJsonRpcProviderConnectorOptions 9 | 10 | #### Summary 11 | A web3modal CustomProvider Options 12 | - Options for web3modal that allows you to connect to a StaticJsonRpcProvider such as localhost 13 | 14 | ## Hierarchy 15 | 16 | - `IAbstractConnectorOptions` 17 | 18 | ↳ **`IStaticJsonRpcProviderConnectorOptions`** 19 | 20 | ## Properties 21 | 22 | ### rpc 23 | 24 | • **rpc**: `Object` 25 | 26 | #### Index signature 27 | 28 | ▪ [chainId: `number`]: `string` 29 | 30 | #### Defined in 31 | 32 | [src/context/ethers-app/connectors/StaticJsonRpcProviderConnector.ts:14](https://github.com/scaffold-eth/eth-hooks/blob/951f765/packages/eth-hooks/src/context/ethers-app/connectors/StaticJsonRpcProviderConnector.ts#L14) 33 | 34 | ___ 35 | 36 | ### currentChainId 37 | 38 | • **currentChainId**: `number` 39 | 40 | #### Defined in 41 | 42 | [src/context/ethers-app/connectors/StaticJsonRpcProviderConnector.ts:15](https://github.com/scaffold-eth/eth-hooks/blob/951f765/packages/eth-hooks/src/context/ethers-app/connectors/StaticJsonRpcProviderConnector.ts#L15) 43 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/interfaces/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Interfaces" 2 | position: 4 -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/modules/Helpers-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "Helpers-1" 3 | title: "Module: Helpers" 4 | sidebar_label: "Helpers" 5 | sidebar_position: 0 6 | custom_edit_url: null 7 | --- 8 | 9 | Pure functions and helpers with useful functionality 10 | 11 | ## Helpers 12 | 13 | ### lazier 14 | 15 | ▸ **lazier**<`T`\>(`importFactory`, `importName`): `LazyExoticComponent`<`T`\> 16 | 17 | ### Summary 18 | A function that modifies react lazy to allow for named exports 19 | 20 | ### Example 21 | ```typescript 22 | const ExampleUI = lazier(() => import('./exampleui/ExampleUI'), 'ExampleUI'); 23 | ``` 24 | 25 | #### Type parameters 26 | 27 | | Name | Type | 28 | | :------ | :------ | 29 | | `T` | extends `ComponentType`<`any`\> | 30 | 31 | #### Parameters 32 | 33 | | Name | Type | Description | 34 | | :------ | :------ | :------ | 35 | | `importFactory` | () => `Promise`<{ `[name: string]`: `T`; }\> | a callback that imports e.g. () => import('./exampleui/ExampleUI') | 36 | | `importName` | `string` | the named export you want to import. | 37 | 38 | #### Returns 39 | 40 | `LazyExoticComponent`<`T`\> 41 | 42 | #### Defined in 43 | 44 | [src/helpers/lazier.ts:18](https://github.com/scaffold-eth/eth-hooks/blob/951f765/packages/eth-hooks/src/helpers/lazier.ts#L18) 45 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/api/modules/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Modules" 2 | position: 1 -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/authors.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # ✍️ Authors 6 | 7 | - 🏰 [BuidlGuidl.eth](https://BuidlGuidl.com) 8 | - [@shravansunder](https://github.com/ShravanSunder) 9 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/context/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "📃 Context", 3 | "position": 3 4 | } 5 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/deep-dive.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # 🤿 Design Deep Dive 6 | 7 | Learn about how Eth-hooks was built and why. 8 | 9 | :::tip 10 | 11 | If you prefer videos, check out Shravan's [video presentation](https://www.youtube.com/watch?v=STxAdE8wQwY) on Eth-hooks V4 advanced features! 12 | 13 | ::: 14 | 15 | ## Design principles 16 | 17 | - Allow flexibility in how often a hook receives updates from the network. You can choose your update method, for example, polling or every block number. 18 | - Easily use context 19 | - **ethersAppContext** 20 | - **contractAppContext** (new in V4): Access your contract easily anywhere in your app. 21 | - Compatibility with different ways to pass in ethers provider 22 | - Reducing RPC calls with easy caching. Uses React Query under the hood to cache any RPC calls. This lets you use Eth-hooks anywhere in the app and you don't have to worry about optimization. You will automatically get data from the cached layer without extra network calls. 23 | - Typed contracts that make it easier to understand the contract interface, reducing mistakes. 24 | 25 | ### Providers 26 | 27 | - EthersAppContext: The context in Eth-hooks uses ethers under-the-hood. Wrap your main app in context and that allows you to use context anywhere in your app (the provider, signer, account). 28 | - App wide providers with context 29 | - Override 30 | - Alternate context for web3-react 31 | - Pass in provider if you need 32 | 33 | :::tip 34 | Get an example of _providers_ in Scaffold-eth-typescript [App.tsx](https://github.com/scaffold-eth/scaffold-eth-typescript/blob/next/packages/vite-app-ts/src/App.tsx) 35 | ::: 36 | 37 | ### Cache 38 | 39 | Built with React-Query and EthersAppContext. Get a cache when you wrap your app in context. 40 | 41 | - All hook results are cached by EthersAppContext 42 | - Prevents repeated calls to the network because the hooks hit the cache first. 43 | - No need to pass variables. If you use a hook anywhere in the app it will automatically hit the cache. 44 | - When the network or signer changes the cache is automatically invalidated so you don't get the wrong values. 45 | 46 | ### Data updates 47 | 48 | There are several different options for updating hook data. Simply pass in your preferred method. 49 | 50 | - **Default** is the hook updates every block 51 | - You can set it to update every n/blocks 52 | - Polling can be used (minimum time is 10 seconds to prevent spamming the network) 53 | - Refresh on window focus or on mount 54 | - Set stale time for data. Default is 30 seconds 55 | 56 | ### Hook return 57 | 58 | The signature of the hook is returned. 59 | 60 | - This is similar to useState. You get a tuple of [result, update] 61 | - Gives you the result or... 62 | - You can manually update the hook 63 | 64 | ### Contract context 65 | 66 | You can call any contract with a simple hook. 67 | 68 | - Automatically get external contracts that are verified 69 | - Automatically typed by context 70 | - Hardhat contracts 71 | - Automatically typed by context 72 | - Load unverified contracts from an ABI 73 | - BaseContract 74 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/dependencies.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | # 📂 Dependencies 6 | 7 | ## Main package dependencies 8 | 9 | - ethers.js 10 | - @uniswap/token-lists 11 | - @web3-react: core, abstractconnector, types 12 | - web3modal 13 | - react-query 14 | 15 | ## Peer dependencies 16 | 17 | - react, react/dom 18 | - uniswap/sdk 19 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/guides/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "🔧 Guides", 3 | "position": 4 4 | } 5 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/guides/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Quick start 6 | 7 | ## (in 5 minutes or less 😉) 8 | 9 | 1. Create a React app 10 | 2. Connect your app to your smart contracts. 11 | 3. Install Eth-hooks in your React app root folder by entering the following in your terminal 12 | 13 | ```sh 14 | yarn add eth-hooks 15 | ``` 16 | 17 | 4. Setup context in your React app `index.tsx` file 18 | 19 | ```tsx title="src/index.tsx" 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | ``` 28 | 29 | 5. If you're using providers, here's an example of how they sould look in your `App.tsx` file 30 | 31 | ```tsx title="src/App.tsx" 32 | export default function App() { 33 | return ( 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ); 42 | } 43 | ``` 44 | 45 | Now you can use any Eth-hook you need anywhere in your application. 46 | 47 | :::note **Need an out-of-the-box fullstack application?** 48 | Try [Scaffold-eth](https://github.com/scaffold-eth/) (Solidity, Hardhat, Ethers, and React. 49 | ::: 50 | :::note **_Did someone say Typescript?_** 51 | Check out [Scaffold-eth-typescript](https://github.com/scaffold-eth/scaffold-eth-typescript). 52 | ::: 53 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/guides/tutorial-advanced/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Advanced tutorials", 3 | "position": 4 4 | } 5 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/guides/tutorial-advanced/advanced.mdx: -------------------------------------------------------------------------------- 1 | # Advanced tutorial 2 | 3 | **Coming soon** 4 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/guides/tutorial-basics/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Basic tutorials", 3 | "position": 3 4 | } 5 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "🪝 The Hooks!", 3 | "position": 2 4 | } 5 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useBalance.mdx: -------------------------------------------------------------------------------- 1 | # useBalance 2 | 3 | Get account balance information from the Ethereum blockchain. 4 | 5 | > Returns the current balance. 6 | 7 | ## How to import 8 | 9 | ```typescript 10 | import { useBalance } from 'eth-hooks'; 11 | ``` 12 | 13 | ## How to use 14 | 15 | To get started: 16 | 17 | ```typescript 18 | const [yourLocalBalance] = useBalance(ethersContext.account); 19 | ``` 20 | 21 | To get your balance on different changes, just plug in a different provider: 22 | 23 | ```typescript 24 | const [mainnetAdaptor] = useEthersAdaptorFromProviderOrSigners(exampleMainnetProvider); 25 | const [yourMainnetBalance, yUpdate, yStatus] = useBalance(ethersContext.account, mergeDefaultUpdateOptions(), { 26 | adaptorEnabled: true, 27 | adaptor: mainnetAdaptor, 28 | }); 29 | ``` 30 | 31 | You can change the update schedule to every 10 blocks, the default is every 1 block: 32 | 33 | ```typescript 34 | const [secondbalance] = useBalance(ethersContext.account, { blockNumberInterval: 10 }); 35 | ``` 36 | 37 | Or change the update schedule to every polling, min is 10000ms: 38 | 39 | ```typescript 40 | const [thirdbalance] = useBalance(ethersContext.account, { refetchInterval: 100000, blockNumberInterval: undefined }); 41 | ``` 42 | 43 | You can also use advanced react-query update options, like so: 44 | 45 | ```typescript 46 | const [fourthbalance] = useBalance(ethersContext.account, { 47 | blockNumberInterval: 1, 48 | query: { refetchOnWindowFocus: true }, 49 | }); 50 | ``` 51 | 52 | ## To learn more 53 | 54 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usebalance). 55 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useBlockNumber.mdx: -------------------------------------------------------------------------------- 1 | # useBlockNumber 2 | 3 | Invoke a callback on every block or with a polling time. On block is the prefered method. 4 | 5 | > Returns the block number. 6 | 7 | ## How to import 8 | 9 | ```typescript 10 | import { useBlockNumber } from 'eth-hooks'; 11 | ``` 12 | 13 | ## How to use 14 | 15 | ```typescript 16 | useBlockNumber(scaffoldAppProviders.mainnetAdaptor?.provider, (blockNumber) => 17 | console.log(`⛓ A new mainnet block is here: ${blockNumber}`) 18 | ); 19 | ``` 20 | 21 | or 22 | 23 | ```typescript 24 | useBlockNumber(scaffoldAppProviders.localAdaptor?.provider, (blockNumber) => 25 | console.log(`⛓ A new local block is here: ${blockNumber}`) 26 | ); 27 | ``` 28 | 29 | ## To learn more 30 | 31 | [Go here for this hooks full API documentation](../../api/modules/Hooks#useblocknumber). 32 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useBlockNumberContext.mdx: -------------------------------------------------------------------------------- 1 | Get your current block number via react context. 2 | 3 | > Returns the current block number. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useBlockNumberContext } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const blockNumber = useBlockNumberContext(): number 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [See here for this hooks full API documentation](../../api/modules/EthersAppContext#useblocknumbercontext) 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useBurnerSigner.mdx: -------------------------------------------------------------------------------- 1 | Creates a burner signer/address, and provides ways of interacting with and updating the signer. 2 | 3 | > Returns the burner signer/address. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useBurnerSigner } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const burnerSigner = useBurnerSigner(localProvider): TBurnerSigner; 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#useburnersigner). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useContractExistsAtAddress.mdx: -------------------------------------------------------------------------------- 1 | Find out if a contract exists already on the blockchain. 2 | 3 | > Returns a boolean. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useContractExistsAtAddress } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const contractExists = useContractExistsAtAddress(contract, options?): THookResult 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usecontractexistsataddress). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useContractLoader.mdx: -------------------------------------------------------------------------------- 1 | Load your contracts and return them. 2 | 3 | > Returns a record of the contract name. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useContractLoader } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const loadContract = useContractLoader(config?, providerOrSigner): Record; 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usecontractloader). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useContractReader.mdx: -------------------------------------------------------------------------------- 1 | # useContractReader 2 | 3 | Call external functions. 4 | 5 | > Returns `THookResult>>` 6 | 7 | ## How to import 8 | 9 | ```typescript 10 | import { useContractReader } from 'eth-hooks'; 11 | ``` 12 | 13 | ## How to use 14 | 15 | ```typescript 16 | const myMainnetDAIBalance = useContractReader(mainnetDai, mainnetDai?.balanceOf, [myAddress ?? '']); 17 | ``` 18 | 19 | Use with the `useSignerAddress` hook to read your DAI balance from the blockchain: 20 | 21 | ```typescript 22 | const [myAddress] = useSignerAddress(ethersContext.signer); 23 | const myMainnetDAIBalance = useContractReader(mainnetDai, mainnetDai?.balanceOf, [myAddress ?? '']); 24 | ``` 25 | 26 | ## To learn more 27 | 28 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usecontractreader). 29 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useContractReaderUntyped.mdx: -------------------------------------------------------------------------------- 1 | Call a contract function with arguments and receive the output. 2 | 3 | You can use this to easily keep track of contract outputs in react states. 4 | 5 | > Returns undefined or output. 6 | 7 | ## How to import 8 | 9 | ```typescript 10 | import { useContractReaderUntyped } from 'eth-hooks'; 11 | ``` 12 | 13 | ## How to use 14 | 15 | To get started: 16 | 17 | ```typescript 18 | const readContract = useContractReaderUntyped(contract, contractFunctionInfo, formatter?, onChange?, override?): undefined | GOutput 19 | ``` 20 | 21 | ## To learn more 22 | 23 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usecontractreaderuntyped). 24 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useDexEthPrice.mdx: -------------------------------------------------------------------------------- 1 | Get the Uniswap exchange price of ETH/USD (extrapolated from WETH/DAI). 2 | 3 | > Returns the price in USD. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useDexEthPrice } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const price = useDexEthPrice(mainnetProvider, targetNetworkInfo?, options?): THookResult; 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usedexethprice). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useDexTokenList.mdx: -------------------------------------------------------------------------------- 1 | Get a token list from Uniswap's IPFS token list. 2 | 3 | > Returns a token list 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useDexTokenList } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const tokenList = useDexTokenList(tokenListUri?, chainId?, options?): THookResult 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usedextokenlist). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useEventListener.mdx: -------------------------------------------------------------------------------- 1 | Tracks the events associated with a contract. 2 | 3 | > Returns contract events. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useEventListener } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const events = useEventListener(contract, eventFilter, startBlock, toBlock?, options?): THookResult 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#useeventlistener). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useGasPrice.mdx: -------------------------------------------------------------------------------- 1 | Get the price of Gas from EtherGasStation ⛽️ 2 | 3 | > Returns gas in Gwei. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useGasPrice } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const [gasPrice] = useGasPrice(ethersContext.chainId, 'fast', getNetworkInfo(ethersContext.chainId)); 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usegasprice). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useNonce.mdx: -------------------------------------------------------------------------------- 1 | Get the current nonce for the address provided. 2 | 3 | > Returns nonce number. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useNonce } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const getNonce = useNonce(address, options?, override?): THookResult 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usenonce). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useResolveEnsAddress.mdx: -------------------------------------------------------------------------------- 1 | Gets the wallet address from an ENS name. 2 | 3 | > Returns undefined or the address. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useResolveEnsAddress } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const [addressFromENS] = useResolveEnsName(scaffoldAppProviders.mainnetAdaptor?.provider, 'austingriffith.eth'); 17 | console.log('🏷 Resolved austingriffith.eth as:', addressFromENS); 18 | ``` 19 | 20 | ## To learn more 21 | 22 | [Go here for this hooks full API documentation](../../api/modules/Hooks#useresolveensaddress). 23 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useResolveEnsName.mdx: -------------------------------------------------------------------------------- 1 | Gets ENS name form a given wallet address. 2 | 3 | > Returns undefined or the ENS. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useResolveEnsName } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const ensName = useResolveEnsName(mainnetProvider, address): THookResult 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#useresolveensname). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useSignerAddress.mdx: -------------------------------------------------------------------------------- 1 | Call external functions. 2 | 3 | > Returns undefined or the address of the signer. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useSignerAddress } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | ```typescript 14 | const [myAddress] = useSignerAddress(ethersContext.signer); 15 | ``` 16 | 17 | Use with the `useContractReader` hook to read your DAI balance from the blockchain: 18 | 19 | ```typescript 20 | const [myAddress] = useSignerAddress(ethersContext.signer); 21 | const myMainnetDAIBalance = useContractReader(mainnetDai, mainnetDai?.balanceOf, [myAddress ?? '']); 22 | ``` 23 | 24 | ## To learn more 25 | 26 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usesigneraddress). 27 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/hooks/useTokenBalance.mdx: -------------------------------------------------------------------------------- 1 | Get the balance of an ERC20 token at an address. 2 | 3 | > Returns undefined or the balance. 4 | 5 | ## How to import 6 | 7 | ```typescript 8 | import { useTokenBalance } from 'eth-hooks'; 9 | ``` 10 | 11 | ## How to use 12 | 13 | To get started: 14 | 15 | ```typescript 16 | const balance = useTokenBalance(contract, address, options?): THookResult 17 | ``` 18 | 19 | ## To learn more 20 | 21 | [Go here for this hooks full API documentation](../../api/modules/Hooks#usetokenbalance). 22 | -------------------------------------------------------------------------------- /packages/docusaurus/docs/main/license.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 8 3 | --- 4 | 5 | # 📃 MIT License 6 | 7 | MIT License 8 | 9 | Copyright (c) Shravan Sunder 2022 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | -------------------------------------------------------------------------------- /packages/docusaurus/eth-hooks.typedoc.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** @type {Partial} */ 4 | const options = { 5 | defaultCategory: 'Misc', 6 | categoryOrder: ['Hooks', 'EthersAppContext', 'ContractAppContext', 'Models', 'Helpers', 'TestUtils', '*'], 7 | categorizeByGroup: false, 8 | cleanOutputDir: true, 9 | readme: 'none', 10 | entryPoints: [ 11 | '../eth-hooks/src/helpers/typedoc/hooks.docs.ts', 12 | '../eth-hooks/src/helpers/typedoc/ethersAppContext.docs.ts', 13 | '../eth-hooks/src/helpers/typedoc/contractAppContext.docs.ts', 14 | '../eth-hooks/src/helpers/typedoc/models.docs.ts', 15 | '../eth-hooks/src/helpers/typedoc/functions.docs.ts', 16 | '../eth-hooks/src/helpers/typedoc/helpers.docs.ts', 17 | '../eth-hooks/src/helpers/typedoc/test-utils.docs.ts', 18 | ], 19 | entryPointStrategy: 'expand', 20 | hideGenerator: true, 21 | hideLegend: false, 22 | includeVersion: true, 23 | sort: ['source-order'], 24 | excludePrivate: true, 25 | excludeInternal: true, 26 | listInvalidSymbolLinks: true, 27 | logLevel: 'Verbose', 28 | excludeExternals: true, 29 | exclude: ['**/test/**', '**/test-files/**', '**/*.test.ts', '**/*.test.tsx'], 30 | externalPattern: ['**/node_modules/**', '**/test/**', '**/test-files/**'], 31 | tsconfig: '../eth-hooks/tsconfig.docs.json', 32 | treatWarningsAsErrors: true, 33 | }; 34 | 35 | module.exports = options; 36 | -------------------------------------------------------------------------------- /packages/docusaurus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "documentation", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "cross-env TYPEDOC_WATCH=true docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc --noEmit", 16 | "lint": "eslint --config ./.eslintrc.js --ignore-path ./.eslintignore ./src/**/*.ts* ", 17 | "format": "prettier -w ./src", 18 | "format:check": "yarn prettier -c ./src " 19 | }, 20 | "dependencies": { 21 | "@docusaurus/core": "^2.0.1", 22 | "@docusaurus/module-type-aliases": "^2.0.1", 23 | "@docusaurus/preset-classic": "^2.0.1", 24 | "@docusaurus/theme-common": "^2.0.1", 25 | "@easyops-cn/docusaurus-search-local": "^0.31.0", 26 | "@mdx-js/react": "^1.6.22", 27 | "clsx": "^1.2.1", 28 | "prism-react-renderer": "^1.3.5", 29 | "react": "^17.0.2", 30 | "react-dom": "^17.0.2" 31 | }, 32 | "devDependencies": { 33 | "@saucelabs/theme-github-codeblock": "^0.1.1", 34 | "@tsconfig/docusaurus": "^1.0.6", 35 | "@types/tailwindcss": "^3.1.0", 36 | "@typescript-eslint/eslint-plugin": "^5.33.0", 37 | "@typescript-eslint/parser": "^5.33.0", 38 | "autoprefixer": "^10.4.8", 39 | "cross-env": "^7.0.3", 40 | "daisyui": "^2.24.0", 41 | "docusaurus-plugin-typedoc": "^0.17.5", 42 | "eslint": "^8.22.0", 43 | "eslint-config-airbnb": "^19.0.4", 44 | "eslint-config-airbnb-typescript": "^17.0.0", 45 | "eslint-config-developit": "^1.2.0", 46 | "eslint-config-prettier": "^8.5.0", 47 | "eslint-plugin-import": "^2.26.0", 48 | "eslint-plugin-markdown": "^3.0.0", 49 | "eslint-plugin-prettier": "^4.2.1", 50 | "eslint-plugin-react": "^7.30.1", 51 | "eslint-plugin-react-hooks": "^4.6.0", 52 | "eslint-plugin-tailwind": "^0.2.1", 53 | "eslint-plugin-tailwindcss": "^3.6.0", 54 | "mdx-mermaid": "^1.2.3", 55 | "mermaid": "^8.14.0", 56 | "postcss": "^8.4.16", 57 | "prettier": "^2.7.1", 58 | "prettier-eslint": "^15.0.1", 59 | "prettier-markdown": "^0.1.8", 60 | "tailwindcss": "^3.1.8", 61 | "typedoc": "^0.23.10", 62 | "typedoc-plugin-markdown": "^3.13.4", 63 | "typedoc-plugin-merge-modules": "^4.0.1", 64 | "typedoc-plugin-mermaid": "^1.9.0", 65 | "typescript": "^4.7.4", 66 | "url": "^0.11.0" 67 | }, 68 | "resolutions": { 69 | "react": "^17.*", 70 | "react-dom": "^17.*" 71 | }, 72 | "browserslist": { 73 | "production": [ 74 | ">0.95%", 75 | "not dead", 76 | "not op_mini all" 77 | ], 78 | "development": [ 79 | "last 1 chrome version", 80 | "last 1 firefox version", 81 | "last 1 safari version" 82 | ] 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /packages/docusaurus/sidebars.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** @type {import('@docusaurus/plugin-content-docs/src/sidebars/types').SidebarItemConfig[]} */ 4 | const apiMenu = [ 5 | { 6 | type: 'autogenerated', 7 | dirName: 'api', 8 | }, 9 | ]; 10 | 11 | /** @type {import('@docusaurus/plugin-content-docs/src/sidebars/types').SidebarItemConfig[]} */ 12 | const overviewMenu = [ 13 | { 14 | type: 'doc', 15 | id: 'overview', 16 | }, 17 | { 18 | type: 'autogenerated', 19 | dirName: 'main', 20 | }, 21 | ]; 22 | 23 | /** 24 | * Creating a sidebar enables you to: 25 | - create an ordered group of docs 26 | - render a sidebar for each doc of that group 27 | - provide next/previous navigation 28 | 29 | The sidebars can be generated from the filesystem, or explicitly defined here. 30 | 31 | Create as many sidebars as you want. 32 | */ 33 | 34 | // @ts-check 35 | 36 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 37 | const sidebars = { 38 | // But you can create a sidebar manually 39 | overview: overviewMenu, 40 | api: apiMenu, 41 | }; 42 | 43 | module.exports = sidebars; 44 | -------------------------------------------------------------------------------- /packages/docusaurus/src/components/HomepageFeatures.tsx: -------------------------------------------------------------------------------- 1 | import useBaseUrl from '@docusaurus/useBaseUrl'; 2 | import React, { FC } from 'react'; 3 | 4 | type FeatureItem = { 5 | title: string; 6 | image: string; 7 | description: JSX.Element; 8 | }; 9 | 10 | const FeatureList: FeatureItem[] = [ 11 | { 12 | title: 'Fast & Easy Web3 React Hooks', 13 | image: '/home/features1.png', 14 | description: ( 15 | <> 16 | Speed up your frontend development with pre-built hooks for use with EthersAppContext, allowing 17 | easy use throughout your application. Additionally, works out of the box with{' '} 18 | 19 | scaffold-eth-typescript 20 | {' '} 21 | template! 22 | 23 | ), 24 | }, 25 | { 26 | title: 'Optimized Web3 Development', 27 | image: '/home/features2.png', 28 | description: ( 29 | <> 30 | Dedicated caching reduces RPC calls. Use a variety of web3 network update options. Typed contracts increase the 31 | clarity of the contract interface. These are just a few of the benefits you get with eth-hooks. 32 | 33 | ), 34 | }, 35 | { 36 | title: 'Seemless Smart Contract Interaction', 37 | image: '/home/features3.png', 38 | description: ( 39 | <> 40 | Use the ContractAppContext and{' '} 41 | 42 | ethers.js 43 | {' '} 44 | to have typed access to your smart contracts. This gives you reliable read and write controls to smart contracts 45 | and even lets you pass different ethers providers. 46 | 47 | ), 48 | }, 49 | ]; 50 | 51 | const Feature: FC = ({ title, image, description }) => { 52 | return ( 53 |
54 |
55 | {title} 56 |
57 |
58 |
59 |

{title}

60 |

{description}

61 |
62 |
63 | ); 64 | }; 65 | 66 | export const HomepageFeatures: FC = () => { 67 | return ( 68 |
69 |
70 | {FeatureList.map((props, idx) => ( 71 | 72 | ))} 73 |
74 |
75 | ); 76 | }; 77 | -------------------------------------------------------------------------------- /packages/docusaurus/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | @tailwind base; 8 | @tailwind components; 9 | @tailwind utilities; 10 | 11 | /* @layer base { 12 | html { 13 | font-family: system-ui, '-apple-system', 'Segoe UI', Roboto, Ubuntu, Cantarell, 'Noto Sans', sans-serif, 'system-ui', 14 | 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; 15 | } 16 | } */ 17 | 18 | /* ******************************************************************************** 19 | see tailwind.config.js for daisy theme as well 20 | ******************************************************************************** */ 21 | 22 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 23 | :root { 24 | --ifm-color-primary-lightest: #7ce1e8; 25 | --ifm-color-primary-lighter: #59d9e2; 26 | --ifm-color-primary-light: #4dd6e0; 27 | --ifm-color-primary: #36d1dc; 28 | --ifm-color-primary-dark: #25c7d2; 29 | --ifm-color-primary-darker: #23bcc6; 30 | --ifm-color-primary-darkest: #1c9aa3; 31 | } 32 | 33 | /* You can override the default Infima variables here. */ 34 | html[data-theme='light'] { 35 | --ifm-color-primary-lightest: #92afee; 36 | --ifm-color-primary-lighter: #84a5ec; 37 | --ifm-color-primary-light: #779ae9; 38 | --ifm-color-primary: #5b86e5; 39 | --ifm-color-primary-dark: #3f72e1; 40 | --ifm-color-primary-darker: #245ddc; 41 | --ifm-color-primary-darkest: #2157cf; 42 | } 43 | 44 | .docusaurus-highlight-code-line { 45 | background-color: rgba(0, 0, 0, 0.1); 46 | display: block; 47 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 48 | padding: 0 var(--ifm-pre-padding); 49 | } 50 | 51 | html[data-theme='dark'] .docusaurus-highlight-code-line { 52 | background-color: rgba(0, 0, 0, 0.3); 53 | } 54 | -------------------------------------------------------------------------------- /packages/docusaurus/src/hooks/themeColorHooks.tsx: -------------------------------------------------------------------------------- 1 | import { useColorMode } from '@docusaurus/theme-common'; 2 | 3 | export const useBgPrimary = (): string => { 4 | const { colorMode } = useColorMode(); 5 | return colorMode === 'dark' ? 'bg-secondary' : 'bg-primary'; 6 | }; 7 | 8 | export const useHeroTextColor = (): string => { 9 | const { colorMode } = useColorMode(); 10 | return colorMode === 'dark' ? 'text-white' : 'text-black'; 11 | }; 12 | 13 | export const useTextColor = (): string => { 14 | const { colorMode } = useColorMode(); 15 | return colorMode === 'dark' ? 'text-primary' : 'text-black'; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/docusaurus/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 966px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /packages/docusaurus/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Link from '@docusaurus/Link'; 2 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 3 | import Layout from '@theme/Layout'; 4 | import clsx from 'clsx'; 5 | import React, { FC } from 'react'; 6 | 7 | import { HomepageEcosystemItems } from '../components/HomepageEcosystemItems'; 8 | import { HomepageFeatures } from '../components/HomepageFeatures'; 9 | 10 | import styles from './index.module.css'; 11 | 12 | const HomepageHeader: FC = () => { 13 | const { siteConfig } = useDocusaurusContext(); 14 | return ( 15 |
16 |
17 |

{siteConfig.title}

18 |

{siteConfig.tagline}

19 |
20 |
21 | 22 | Quick Start Guide - 5min ⏱️ 23 | 24 |
25 |
26 |
27 | ); 28 | }; 29 | 30 | const Home: FC = () => { 31 | const { siteConfig } = useDocusaurusContext(); 32 | return ( 33 | 34 | 35 |
36 | 37 | 38 |
39 |
40 | ); 41 | }; 42 | export default Home; 43 | -------------------------------------------------------------------------------- /packages/docusaurus/src/pages/markdown-page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown page example 3 | --- 4 | 5 | # Markdown page example 6 | 7 | You don't need React to write simple standalone pages. 8 | -------------------------------------------------------------------------------- /packages/docusaurus/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scaffold-eth/eth-ui/940e0962137047699fecde63ea682617411d6f89/packages/docusaurus/static/.nojekyll -------------------------------------------------------------------------------- /packages/docusaurus/static/googlefd38dd56cfc4fa75.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlefd38dd56cfc4fa75.html -------------------------------------------------------------------------------- /packages/docusaurus/static/home/features1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scaffold-eth/eth-ui/940e0962137047699fecde63ea682617411d6f89/packages/docusaurus/static/home/features1.png -------------------------------------------------------------------------------- /packages/docusaurus/static/home/features2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scaffold-eth/eth-ui/940e0962137047699fecde63ea682617411d6f89/packages/docusaurus/static/home/features2.png -------------------------------------------------------------------------------- /packages/docusaurus/static/home/features3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scaffold-eth/eth-ui/940e0962137047699fecde63ea682617411d6f89/packages/docusaurus/static/home/features3.png -------------------------------------------------------------------------------- /packages/docusaurus/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scaffold-eth/eth-ui/940e0962137047699fecde63ea682617411d6f89/packages/docusaurus/static/img/favicon.ico -------------------------------------------------------------------------------- /packages/docusaurus/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /packages/docusaurus/tailwind.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | const prismDark = require('prism-react-renderer/themes/nightOwl'); 3 | 4 | /** @type {import('tailwindcss/tailwind-config').TailwindConfig} */ 5 | const config = { 6 | content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], 7 | darkMode: 'class', // or 'media' or 'class' 8 | important: false, 9 | corePlugins: { 10 | preflight: false, 11 | }, 12 | theme: { 13 | extend: { 14 | colors: { 15 | 'text-primary': '#C2D0EA', 16 | }, 17 | /** 18 | * added the default spacing values to max width 19 | * @param theme 20 | */ 21 | maxWidth: (theme) => ({ 22 | // @ts-ignore 23 | ...theme('spacing'), 24 | }), 25 | minWidth: (theme) => ({ 26 | // @ts-ignore 27 | ...theme('spacing'), 28 | }), 29 | // @ts-ignore 30 | backgroundColor: ['group-focus'], 31 | borderWidth: { 32 | 1: '1px', 33 | }, 34 | }, 35 | }, 36 | variants: { 37 | extend: { 38 | // ... 39 | borderWidth: ['hover', 'focus'], 40 | }, 41 | }, 42 | // @ts-ignore 43 | plugins: [require('daisyui')], 44 | daisyui: { 45 | themes: [ 46 | { 47 | darkDocs: { 48 | primary: '#36d1dc', 49 | secondary: '#5b86e5', 50 | accent: '#111827', 51 | neutral: '#191D24', 52 | 'base-100': '#2A303C', 53 | info: '#84a5ec', 54 | success: '#0d9488', 55 | warning: '#e67919', 56 | error: '#b91c1c', 57 | }, 58 | }, 59 | ], 60 | }, 61 | }; 62 | 63 | module.exports = config; 64 | -------------------------------------------------------------------------------- /packages/docusaurus/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@tsconfig/docusaurus/tsconfig.json", 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "forceConsistentCasingInFileNames": true, 7 | "allowSyntheticDefaultImports": true, 8 | "downlevelIteration": true, 9 | "esModuleInterop": true, 10 | "isolatedModules": true, 11 | "noImplicitAny": true, 12 | "skipLibCheck": true, 13 | "skipDefaultLibCheck": true, 14 | "strict": true 15 | }, 16 | "include": ["src/**/*.tsx"] 17 | } 18 | -------------------------------------------------------------------------------- /packages/eth-hooks/.eslintignore: -------------------------------------------------------------------------------- 1 | # folders 2 | lib/ 3 | node_modules/**/* 4 | **/*.md 5 | docs/**/* 6 | website/**/* 7 | build/**/* -------------------------------------------------------------------------------- /packages/eth-hooks/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser 3 | extends: ['../../.eslintrc.js'], 4 | parserOptions: { 5 | ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features 6 | sourceType: 'module', // Allows for the use of imports, 7 | ecmaFeatures: { 8 | jsx: true, // Allows for the parsing of JSX, 9 | }, 10 | project: 'tsconfig.json', 11 | tsconfigRootDir: '.', 12 | projectFolderIgnoreList: [ 13 | 'node_modules/*', 14 | 'node_modules', 15 | 'dist', 16 | 'build', 17 | '.yarn', 18 | 'build-utils', 19 | 'docs', 20 | './src/generated/*', 21 | 'generated/*', 22 | ], 23 | }, 24 | env: { 25 | browser: true, 26 | es6: true, 27 | node: true, 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /packages/eth-hooks/.mocharc.js: -------------------------------------------------------------------------------- 1 | console.log('load .mocharc.js config'); 2 | 3 | module.exports = { 4 | require: ['hardhat/register', 'ts-node/register', 'ts-node/register/files'], 5 | timeout: 30000, 6 | bail: false, 7 | allowUncaught: false, 8 | reporter: process.env.GITHUB_ACTIONS === 'true' ? 'mocha-junit-reporter' : 'spec', 9 | reporterOptions: { 10 | mochaFile: 'testresult.xml', 11 | }, 12 | extension: ['js', 'ts', 'tsx', 'jsx'], 13 | spec: ['test/**/*'], 14 | parallel: false, 15 | recursive: true, 16 | jobs: 1, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/eth-hooks/.npmignore: -------------------------------------------------------------------------------- 1 | #folders 2 | src 3 | 4 | #files 5 | .commitlintrc.js 6 | .eslintignore 7 | .eslintrc.js 8 | .gitignore 9 | .huskyrc.js 10 | .lintstagedrc.js 11 | .prettierrc 12 | tsconfig.json 13 | yarn.lock 14 | 15 | *.log 16 | *.tgz -------------------------------------------------------------------------------- /packages/eth-hooks/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "printWidth": 120, 5 | "requirePragma": false, 6 | "singleQuote": true, 7 | "tabWidth": 2, 8 | "trailingComma": "es5", 9 | "endOfLine": "lf", 10 | "bracketSameLine": true 11 | } 12 | -------------------------------------------------------------------------------- /packages/eth-hooks/esbuild.shim.js: -------------------------------------------------------------------------------- 1 | // shim.js 2 | import * as React from 'react'; 3 | export { React }; 4 | export { jsx as _jsx } from 'react/jsx-runtime'; 5 | -------------------------------------------------------------------------------- /packages/eth-hooks/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | // This adds support for typescript paths mappings 2 | import './test/helpers/hardhat-imports'; 3 | 4 | import { HardhatUserConfig } from 'hardhat/types'; 5 | import { mochaRootHook_disableReact18Warnings } from 'test/helpers/mochaRootHooks'; 6 | 7 | /** 8 | * this is used for hook tests 9 | */ 10 | const config: HardhatUserConfig = { 11 | solidity: '0.8.6', 12 | defaultNetwork: 'hardhat', 13 | networks: { 14 | hardhat: { 15 | mining: { 16 | auto: true, 17 | interval: 0, 18 | }, 19 | }, 20 | }, 21 | mocha: { 22 | bail: false, 23 | allowUncaught: false, 24 | require: ['ts-node/register'], 25 | timeout: 30000, 26 | slow: 9900, 27 | reporter: process.env.GITHUB_ACTIONS === 'true' ? 'mocha-junit-reporter' : 'spec', 28 | reporterOptions: { 29 | mochaFile: 'testresult.xml', 30 | toConsole: true, 31 | }, 32 | rootHooks: mochaRootHook_disableReact18Warnings, 33 | }, 34 | paths: { 35 | root: './test-files', 36 | cache: './generated/cache', 37 | artifacts: './generated/artifacts', 38 | deployments: './generated/deployments', 39 | deploy: './deploy', 40 | tests: '../test', 41 | }, 42 | typechain: { 43 | outDir: './generated/contract-types', 44 | discriminateTypes: true, 45 | }, 46 | }; 47 | 48 | export default config; 49 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/EthersAppState.tsx: -------------------------------------------------------------------------------- 1 | /** * 2 | * @internal 3 | */ 4 | 5 | export interface IBlockNumberState { 6 | [chainId: number]: number | undefined; 7 | } 8 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/EthersAppStore.ts: -------------------------------------------------------------------------------- 1 | import { default as create, StoreApi, UseBoundStore } from 'zustand'; 2 | 3 | import { IBlockNumberState } from '~~/context/EthersAppState'; 4 | 5 | interface IStore { 6 | blockNumberState: IBlockNumberState; 7 | setBlockNumber: (blocknumber: number, chainId: number) => void; 8 | } 9 | 10 | // type TSetStoreFunc = IStore | Partial | ((state: IStore) => IStore | Partial); 11 | export type TEthersAppStore = UseBoundStore>; 12 | export type { create, StoreApi, UseBoundStore }; 13 | 14 | export const useEthersAppStore = create()((set) => ({ 15 | blockNumberState: {}, 16 | setBlockNumber: (blocknumber: number, chainId: number): void => 17 | set((state): IStore => { 18 | state.blockNumberState[chainId] = blocknumber; 19 | return state; 20 | }), 21 | })); 22 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/contracts-app/index.ts: -------------------------------------------------------------------------------- 1 | export * from './contractConnectors'; 2 | export * from './contractsContextFactory'; 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/ethers-app/connectors/StaticJsonRpcProviderConnector.ts: -------------------------------------------------------------------------------- 1 | import { StaticJsonRpcProvider } from '@ethersproject/providers'; 2 | import { IAbstractConnectorOptions } from 'web3modal'; 3 | 4 | import { NoStaticJsonRPCProviderFoundError } from '~~/context/ethers-app/connectors/connectorErrors'; 5 | 6 | /** 7 | * #### Summary 8 | * A web3modal CustomProvider Options 9 | * - Options for web3modal that allows you to connect to a StaticJsonRpcProvider such as localhost 10 | * 11 | * @category EthersAppContext 12 | */ 13 | export interface IStaticJsonRpcProviderConnectorOptions extends IAbstractConnectorOptions { 14 | rpc: { [chainId: number]: string }; 15 | currentChainId: number; 16 | } 17 | 18 | /** 19 | * #### Summary 20 | * A connector that can be used by apps to connect to a StaticJsonRpcProvider 21 | * - For example you can use this to connect to a localhost provider 22 | * 23 | * ##### ✏️ Notes 24 | * See scaffold-eth-typescript for an example that uses it to connect to a localhost burner wallet. 25 | * - [scaffold-eth-typescript example](https://github.com/scaffold-eth/scaffold-eth-typescript/blob/next/packages/vite-app-ts/src/config/web3ModalConfig.ts#L86) 26 | * 27 | * @category EthersAppContext 28 | * 29 | * @param _package not used 30 | * @param opts 31 | * @returns 32 | */ 33 | export const ConnectToStaticJsonRpcProvider = async ( 34 | _package: unknown, 35 | opts: IStaticJsonRpcProviderConnectorOptions 36 | ): Promise => { 37 | const url = opts.rpc[opts.currentChainId]; 38 | try { 39 | const provider = new StaticJsonRpcProvider(url, opts.currentChainId); 40 | await provider.getNetwork(); 41 | await provider.getBlockNumber(); 42 | if (!provider?.anyNetwork) { 43 | console.warn(`ConnectToStaticJsonRpcProvider: could not connect to chain: ${opts.currentChainId} url: ${url}`); 44 | } 45 | return provider; 46 | } catch (e) { 47 | throw new NoStaticJsonRPCProviderFoundError(e); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/ethers-app/connectors/connectorErrors.ts: -------------------------------------------------------------------------------- 1 | export const connectorErrorText = { 2 | NoStaticJsonRPCProviderFoundError: 'Could not find a static json-rpc provider. Is it running?', 3 | NoEthereumProviderFoundError: 'No web3 provider found', 4 | CouldNotActivateError: 'Could not activate the web3 provider', 5 | UserClosedModalError: 'Did not log in, the user did not select a web3 provider', 6 | } as const; 7 | 8 | /** 9 | * @category EthersAppContext 10 | */ 11 | export class UserClosedModalError extends Error { 12 | public constructor() { 13 | super(); 14 | this.name = this.constructor.name; 15 | this.message = `EthersModalConnector: ${connectorErrorText.UserClosedModalError}.`; 16 | } 17 | } 18 | 19 | /** 20 | * @category EthersAppContext 21 | */ 22 | export class CouldNotActivateError extends Error { 23 | public constructor(error: unknown) { 24 | super(); 25 | this.name = this.constructor.name; 26 | this.message = `EthersModalConnector: ${connectorErrorText.CouldNotActivateError}. ${(error as string) ?? ''}`; 27 | } 28 | } 29 | 30 | /** 31 | * @category EthersAppContext 32 | */ 33 | export class NoEthereumProviderFoundError extends Error { 34 | public constructor() { 35 | super(); 36 | this.name = this.constructor.name; 37 | this.message = `EthersModalConnector: ${connectorErrorText.NoEthereumProviderFoundError}.`; 38 | } 39 | } 40 | 41 | /** 42 | * @category EthersAppContext 43 | */ 44 | export class NoStaticJsonRPCProviderFoundError extends Error { 45 | public constructor(error: unknown) { 46 | super(); 47 | this.name = this.constructor.name; 48 | this.message = `EthersModalConnector: ${connectorErrorText.NoStaticJsonRPCProviderFoundError}. ${ 49 | (error as string) ?? '' 50 | }`; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/ethers-app/connectors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './EthersModalConnector'; 2 | export * from './StaticJsonRpcProviderConnector'; 3 | export * from './connectorErrors'; 4 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/ethers-app/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useBlockNumberContext'; 2 | export * from './EthersAppContext'; 3 | export * from './connectors'; 4 | export * from './queryClient'; 5 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/ethers-app/queryClient.ts: -------------------------------------------------------------------------------- 1 | import { QueryClient } from 'react-query'; 2 | 3 | export const defaultQueryClient = new QueryClient(); 4 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/ethers-app/useBlockNumberContext.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { invariant } from 'ts-invariant'; 3 | 4 | import { useEthersAppContext } from '~~/context'; 5 | import { useEthersAppStore } from '~~/context/EthersAppStore'; 6 | import { useBlockNumber } from '~~/hooks'; 7 | import { TOverride } from '~~/models'; 8 | 9 | /** 10 | * #### Summary 11 | * A hook that gets you the current blocknumber and saves it to the store 12 | * - can be shared by your whole app. 13 | * 14 | * ##### ❔Use 15 | * Make sure to wrap your main app with the {@link EthersAppContext}. 16 | * - See [scaffold-eth-typescript example](https://github.com/scaffold-eth/scaffold-eth-typescript/blob/next/packages/vite-app-ts/src/components/routes/App.tsx#L38) 17 | * 18 | * 19 | * ##### ✏️ Notes 20 | * - this extensively used by eth-hooks to trigger hooks when a new block arrives 21 | * - uses the current provider {@link ethersProvider} from {@link useEthersContext} 22 | * 23 | * @category EthersAppContext 24 | * 25 | * @returns current block number 26 | */ 27 | export const useBlockNumberContext = (chainId?: number, override?: TOverride): number => { 28 | const ethersContext = useEthersAppContext(override?.alternateContextKey); 29 | const blockNumberState = useEthersAppStore((state) => state.blockNumberState); 30 | const setBlockNumber = useEthersAppStore((state) => state.setBlockNumber); 31 | let result: number | undefined = undefined; 32 | 33 | [result] = useBlockNumber(ethersContext.provider); 34 | 35 | useEffect(() => { 36 | if (ethersContext.chainId && result != null && result !== blockNumberState[ethersContext.chainId]) { 37 | setBlockNumber(result, ethersContext.chainId); 38 | } 39 | }, [blockNumberState, ethersContext.chainId, result, setBlockNumber]); 40 | 41 | if (chainId && chainId !== ethersContext.chainId) { 42 | if (blockNumberState[chainId] == null) 43 | invariant.log( 44 | 'blockNumberState[chainId] in the store is null, make sure to have a provider for this chain', 45 | chainId 46 | ); 47 | result = blockNumberState[chainId] ?? 0; 48 | } 49 | 50 | return result; 51 | }; 52 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/context/index.ts: -------------------------------------------------------------------------------- 1 | export * from './contracts-app'; 2 | export * from './ethers-app'; 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/dapps.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module Hooks 3 | */ 4 | 5 | export * from './hooks/dapps'; 6 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/erc.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module Hooks 3 | */ 4 | 5 | export * from './hooks/erc'; 6 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/functions/asyncHelpers.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * #### Summary 3 | * js .some function that can be used with async predicates 4 | * 5 | * @category Helpers 6 | * 7 | * @param arr 8 | * @param predicate 9 | * @returns 10 | */ 11 | export const asyncSome = async (arr: Array, predicate: (item: T) => Promise): Promise => { 12 | for (const e of arr) { 13 | if (await predicate(e)) return e; 14 | } 15 | return undefined; 16 | }; 17 | 18 | export const asyncForEach = async ( 19 | array: Array, 20 | callback: (item: T, index: number) => Promise 21 | ): Promise => { 22 | for (let index = 0; index < array.length; index++) { 23 | await callback(array[index], index); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/functions/ethersHelpers.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Web3Provider, 3 | StaticJsonRpcProvider, 4 | JsonRpcProvider, 5 | JsonRpcBatchProvider, 6 | UrlJsonRpcProvider, 7 | WebSocketProvider, 8 | } from '@ethersproject/providers'; 9 | import { Signer } from 'ethers'; 10 | 11 | import { providerKey } from '~~/functions'; 12 | import { TEthersProvider, IEthersContext, TEthersAdaptor } from '~~/models'; 13 | 14 | /** 15 | * #### Summary 16 | * Is it a ethers compatable provider, used by {@link EthersModalConnector} and {@link useEthersProvider} 17 | * 18 | * @category Helpers 19 | * 20 | * @param providerBase 21 | * @returns 22 | */ 23 | export const isEthersProvider = (providerBase: unknown): boolean => { 24 | if (providerBase == null) return false; 25 | return ( 26 | providerBase instanceof Web3Provider || 27 | providerBase instanceof StaticJsonRpcProvider || 28 | providerBase instanceof JsonRpcProvider || 29 | providerBase instanceof UrlJsonRpcProvider || 30 | providerBase instanceof JsonRpcBatchProvider || 31 | providerBase instanceof WebSocketProvider 32 | ); 33 | }; 34 | 35 | export const signerHasNetwork = (signer: Signer | undefined): boolean => { 36 | const provider = signer?.provider as TEthersProvider; 37 | if (provider?.network?.chainId > 0 && signer?._isSigner) return true; 38 | 39 | return false; 40 | }; 41 | 42 | export const asEthersAdaptor = (ethersContext: IEthersContext): Readonly => { 43 | return { 44 | provider: ethersContext.provider, 45 | signer: ethersContext.signer, 46 | chainId: ethersContext.chainId, 47 | account: ethersContext.account, 48 | } as const; 49 | }; 50 | 51 | export const isValidEthersContext = (ethersContext: IEthersContext | undefined): boolean => { 52 | if ( 53 | ethersContext != null && 54 | ethersContext.chainId != null && 55 | ethersContext.provider != null && 56 | ethersContext.signer != null && 57 | !!ethersContext.account 58 | ) 59 | return true; 60 | return false; 61 | }; 62 | 63 | export const isValidEthersAdaptor = (ethersAdaptor: TEthersAdaptor | undefined): boolean => { 64 | if (ethersAdaptor != null && ethersAdaptor.chainId != null) { 65 | if (ethersAdaptor.provider != null && ethersAdaptor.provider?.network?.chainId === ethersAdaptor.chainId) { 66 | return true; 67 | } else if ( 68 | ethersAdaptor.signer != null && 69 | !!ethersAdaptor.account && 70 | (ethersAdaptor?.signer?.provider as TEthersProvider)?.network?.chainId === ethersAdaptor.chainId 71 | ) { 72 | return true; 73 | } 74 | } 75 | 76 | // console.log('isValidEthersAdaptorπ', false, ethersAdaptor); 77 | return false; 78 | }; 79 | 80 | export const isAdaptorEqual = (adaptor1: TEthersAdaptor | undefined, adaptor2: TEthersAdaptor | undefined): boolean => { 81 | if (isValidEthersAdaptor(adaptor1) && isValidEthersAdaptor(adaptor2)) { 82 | return ( 83 | adaptor1?.chainId === adaptor2?.chainId && 84 | adaptor1?.account === adaptor2?.account && 85 | providerKey(adaptor1?.provider) === providerKey(adaptor2?.provider) 86 | ); 87 | } 88 | return false; 89 | }; 90 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/functions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './asyncHelpers'; 2 | export * from './ethersHelpers'; 3 | export * from './hookHelpers'; 4 | export * from './keyHelpers'; 5 | export * from './parseProviderOrSigner'; 6 | // export * from './sortContracts'; 7 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/__global.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable unused-imports/no-unused-vars-ts */ 2 | /* eslint-disable @typescript-eslint/no-unsafe-member-access */ 3 | 4 | import { ExternalProvider } from '@ethersproject/providers'; 5 | 6 | interface Ethereum { 7 | send: unknown; 8 | enable: () => Promise; 9 | on?: (method: string, listener: (...args: any[]) => void) => void; 10 | removeListener?: (method: string, listener: (...args: any[]) => void) => void; 11 | } 12 | 13 | declare interface Window { 14 | ethereum: ExternalProvider & Ethereum; 15 | } 16 | 17 | (window as any).global = window; 18 | const global = window; 19 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/esm-fixtures/web3modal.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unsafe-member-access */ 2 | /* eslint-disable @typescript-eslint/no-unsafe-assignment */ 3 | import * as cts from 'web3modal'; 4 | 5 | export const Web3Modal: cts.default = (cts.default as any)?.default ?? cts.default; 6 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lazier'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/lazier.ts: -------------------------------------------------------------------------------- 1 | import { lazy, ComponentType, LazyExoticComponent } from 'react'; 2 | 3 | /** 4 | * ### Summary 5 | * A function that modifies react lazy to allow for named exports 6 | * 7 | * ### Example 8 | * ```typescript 9 | * const ExampleUI = lazier(() => import('./exampleui/ExampleUI'), 'ExampleUI'); 10 | * ``` 11 | * 12 | * @category Helpers 13 | * 14 | * @param importFactory a callback that imports e.g. () => import('./exampleui/ExampleUI') 15 | * @param importName the named export you want to import. 16 | * @returns 17 | */ 18 | export const lazier = >( 19 | importFactory: () => Promise<{ 20 | [name: string]: T; 21 | }>, 22 | importName: string 23 | ): LazyExoticComponent => { 24 | return lazy(() => { 25 | return importFactory().then((module) => ({ default: module[importName] })); 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './testConstants'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/constants/testConstants.ts: -------------------------------------------------------------------------------- 1 | export const const_basicGasPrice = 875000000; 2 | 3 | export const const_DefaultTestChainId = 31337; 4 | 5 | /** 6 | * 7 | * This is a const based on WaitOptions from react testing lib 8 | */ 9 | export const defaultBlockWaitOptions: { timeout: number; interval: number } = { 10 | timeout: 11_000, 11 | interval: 300, 12 | } as const; 13 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/eth/hardhatActions.ts: -------------------------------------------------------------------------------- 1 | import { MockProvider } from 'ethereum-waffle'; 2 | 3 | export const mineBlock = async (mockProvider: MockProvider): Promise => { 4 | const blockNumber1 = await mockProvider.getBlockNumber(); 5 | await mockProvider.send('evm_increaseTime', [3600]); 6 | await mockProvider.send('evm_mine', []); 7 | const blockNumber2 = await mockProvider.getBlockNumber(); 8 | if (!(blockNumber1 + 1 === blockNumber2)) { 9 | console.error('blocknumber was not mined as expected', blockNumber1, blockNumber2); 10 | } 11 | }; 12 | 13 | export const setAutoMine = async (mockProvider: MockProvider, enabled: boolean): Promise => { 14 | await mockProvider.send('evm_setAutomine', [enabled]); 15 | }; 16 | 17 | /** 18 | * #### Summary 19 | * mine block until the a condition is met or a maximumNumberOfBlocks is reached 20 | * @param mockProvider 21 | * @param untilCondition 22 | * @param maxNumberOfBlocks 23 | * @returns [success, currentBlockNumber] 24 | */ 25 | export const mineBlockUntil = async ( 26 | mockProvider: MockProvider, 27 | maxNumberOfBlocks: number, 28 | untilCondition: 29 | | ((currentBlockNumber: number) => Promise) 30 | | ((currentBlockNumber: number) => boolean) 31 | | ((currentBlockNumber: number) => Promise) 32 | ): Promise<[success: boolean, currentBlockNumber: number]> => { 33 | let currentBlockNumber = await mockProvider.getBlockNumber(); 34 | const initialBlockNumber = currentBlockNumber; 35 | while (!(await untilCondition(currentBlockNumber)) && maxNumberOfBlocks >= currentBlockNumber - initialBlockNumber) { 36 | await mineBlock(mockProvider); 37 | currentBlockNumber = await mockProvider.getBlockNumber(); 38 | } 39 | const success = await untilCondition(currentBlockNumber); 40 | return [success ?? true, currentBlockNumber]; 41 | }; 42 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/eth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hardhatActions'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/functions/conversions.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber, utils } from 'ethers'; 2 | 3 | export const fromGwei = (value: string | number): BigNumber => { 4 | return utils.parseUnits(value.toString(), 'gwei'); 5 | }; 6 | 7 | export const fromEther = (value: string | number): BigNumber => { 8 | return utils.parseEther(value.toString()); 9 | }; 10 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/functions/expect.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { Wallet } from 'ethers'; 3 | 4 | export const expectValidWallets = (...wallets: Wallet[]): void => { 5 | wallets.forEach((w) => expect(w.address).to.be.properAddress); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/functions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './conversions'; 2 | export * from './expect'; 3 | export * from './shouldFailWithMessage'; 4 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/functions/mochaHelpers.ts: -------------------------------------------------------------------------------- 1 | import { AssertionError, expect } from 'chai'; 2 | 3 | export type TExpectExpression = (() => Promise) | (() => void); 4 | 5 | const returnExpectAsBool = async (expectExpression: TExpectExpression): Promise => { 6 | try { 7 | await expectExpression(); 8 | } catch (e) { 9 | if (e instanceof AssertionError) { 10 | return false; 11 | } else { 12 | throw e; 13 | } 14 | } 15 | return true; 16 | }; 17 | 18 | export const sleep = (ms: number): Promise => { 19 | return new Promise((resolve) => { 20 | setTimeout(resolve, ms); 21 | }); 22 | }; 23 | export const waitForCondition = async ( 24 | untilCondition: (() => Promise) | (() => boolean), 25 | { timeout, interval }: { timeout?: number; interval?: number } 26 | ): Promise => { 27 | let hasTimedOut = false; 28 | setTimeout(() => { 29 | hasTimedOut = true; 30 | }, timeout); 31 | 32 | while (!(await untilCondition()) && !hasTimedOut) { 33 | await sleep(interval ?? 250); 34 | } 35 | 36 | expect(hasTimedOut, `waitForCondition: timed out ${untilCondition.toString()}`).to.be.false; 37 | }; 38 | 39 | export const waitForExpect = async ( 40 | expectExpression: TExpectExpression, 41 | { timeout, interval }: { timeout?: number; interval?: number } 42 | ): Promise => { 43 | let hasTimedOut = false; 44 | setTimeout(() => { 45 | hasTimedOut = true; 46 | }, timeout); 47 | 48 | while (!(await returnExpectAsBool(expectExpression)) && !hasTimedOut) { 49 | await sleep(interval ?? 250); 50 | } 51 | 52 | expect(hasTimedOut, `returnExpectAsBool: timed out ${expectExpression.toString()}`).to.be.false; 53 | }; 54 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/functions/shouldFailWithMessage.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | /** 4 | * Wrapped around a function to ensure that it fails with the correct message 5 | * and doesn't pass successfully 6 | * 7 | * @param failingFunction Function expect to fail 8 | * @param errorMessage Error message expect to fail with 9 | */ 10 | export const shouldFailWithMessage = async ( 11 | failingFunction: () => Promise, 12 | errorMessage: string 13 | ): Promise => { 14 | try { 15 | await failingFunction(); 16 | } catch (e: any) { 17 | expect(e.message).to.contain(errorMessage); 18 | return; 19 | } 20 | expect.fail(); // Fail test if it doesn't fail 21 | }; 22 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './wrapper/testWrapper'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/wrapper/TestAppWrapper.tsx: -------------------------------------------------------------------------------- 1 | import React, { createElement, FC, useEffect } from 'react'; 2 | 3 | import { EthersAppContext, useEthersAppContext } from '~~/context'; 4 | import { TCreateEthersModalConnector } from '~~/models/ethersAppContextTypes'; 5 | 6 | interface IMockProps { 7 | children?: React.ReactNode; 8 | createMockConnector: TCreateEthersModalConnector; 9 | contractContext?: FC; 10 | } 11 | 12 | const TestConnectorWrapper: FC = (props) => { 13 | const ethersContext = useEthersAppContext(); 14 | 15 | useEffect(() => { 16 | const connector = props.createMockConnector(); 17 | if (connector != null) { 18 | ethersContext.openModal(connector); 19 | } 20 | // eslint-disable-next-line react-hooks/exhaustive-deps 21 | }, []); 22 | 23 | useEffect(() => { 24 | return (): void => { 25 | ethersContext.deactivate(); 26 | }; 27 | // eslint-disable-next-line react-hooks/exhaustive-deps 28 | }, []); 29 | 30 | return <>{props.children}; 31 | }; 32 | 33 | /** 34 | * This is a wrapper for tests 35 | * @param props 36 | * @returns 37 | */ 38 | export const TestAppWrapper: FC = (props) => { 39 | const element = ( 40 | 41 | {props.children} 42 | 43 | ); 44 | 45 | // wrap in contract context if provided 46 | if (props.contractContext != null) { 47 | const wrappedElement = createElement(props.contractContext, {}, element); 48 | return wrappedElement; 49 | } 50 | 51 | return element; 52 | }; 53 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/wrapper/getMockProvider.ts: -------------------------------------------------------------------------------- 1 | import '@nomiclabs/hardhat-waffle'; 2 | 3 | import { MockProvider } from 'ethereum-waffle'; 4 | import { waffle } from 'hardhat'; 5 | 6 | export const getMockProvider = (): MockProvider => { 7 | return waffle.provider; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/wrapper/hardhatTestHelpers.ts: -------------------------------------------------------------------------------- 1 | import { useBlockNumberContext } from '~~/context'; 2 | import { hookTestWrapper, TTestHookResult } from '~~/helpers/test-utils'; 3 | 4 | export const wrapperTestSetupHelper = async (): Promise> => { 5 | const useBeforeTestHook = (): number => { 6 | return useBlockNumberContext(); 7 | }; 8 | 9 | return await hookTestWrapper(() => useBeforeTestHook()); 10 | }; 11 | 12 | export const currentTestBlockNumber = async (): Promise => { 13 | const wrapper = await wrapperTestSetupHelper(); 14 | return await wrapper.mockProvider.getBlockNumber(); 15 | }; 16 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/wrapper/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MockConnector'; 2 | export * from './TestAppWrapper'; 3 | export * from './getMockProvider'; 4 | export * from './hardhatTestHelpers'; 5 | export * from './testWrapper'; 6 | export * from './wrapperHelpers'; 7 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/wrapper/testWrapper.tsx: -------------------------------------------------------------------------------- 1 | import { renderHook, RenderHookResult } from '@testing-library/react-hooks'; 2 | import { MockProvider } from 'ethereum-waffle'; 3 | import { FC } from 'react'; 4 | 5 | import { waitForActivation, isActive } from './wrapperHelpers'; 6 | 7 | import { getMockProvider } from '~~/helpers/test-utils/wrapper/getMockProvider'; 8 | import { MockConnector } from '~~/helpers/test-utils/wrapper/MockConnector'; 9 | import { TestAppWrapper } from '~~/helpers/test-utils/wrapper/TestAppWrapper'; 10 | import { TCreateEthersModalConnector } from '~~/models/ethersAppContextTypes'; 11 | const mockProvider = getMockProvider(); 12 | const mockConnector = new MockConnector(mockProvider); 13 | 14 | export type TTestHookResult any> = Omit< 15 | RenderHookResult, ReturnType>, 16 | 'rerender' 17 | > & { 18 | mockProvider: MockProvider; 19 | rerender: (input: Parameters[0]) => void; 20 | }; 21 | 22 | /** 23 | * Created a test hook with a Web3Wrapper 24 | * @param callbackToHook callback to init hook 25 | * @see renderHook from @link testing-library/react-hooks 26 | * @returns (TTestHookResult) 27 | */ 28 | export const hookTestWrapper = async any>( 29 | callbackToHook: TCallbackToHook 30 | ): Promise> => { 31 | const createMockConnector: TCreateEthersModalConnector = () => { 32 | return mockConnector; 33 | }; 34 | 35 | const wrapper: FC< 36 | Parameters & { 37 | children?: React.ReactNode; 38 | } 39 | > = (props) => {props.children}; 40 | 41 | const result = renderHook(callbackToHook, { wrapper }); 42 | await waitForActivation(() => isActive(mockConnector)); 43 | 44 | return { 45 | ...result, 46 | rerender: result.rerender as (input: Parameters[0]) => void, 47 | mockProvider: mockProvider, 48 | }; 49 | }; 50 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/test-utils/wrapper/wrapperHelpers.ts: -------------------------------------------------------------------------------- 1 | import { JsonRpcSigner } from '@ethersproject/providers'; 2 | import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; 3 | import { MockProvider } from 'ethereum-waffle'; 4 | import { Signer } from 'ethers'; 5 | 6 | import { MockConnector } from '~~/helpers/test-utils/wrapper/MockConnector'; 7 | 8 | export const isActive = async (connector: MockConnector): Promise => { 9 | const active = 10 | connector != null && 11 | (await connector.getChainId()) != null && 12 | (await connector.getProvider()) != null && 13 | (await connector.getAccount()) != null; 14 | return active; 15 | }; 16 | 17 | export const waitForActivation = async (callback: () => Promise): Promise => { 18 | let timeout = false; 19 | void setTimeout(() => { 20 | timeout = true; 21 | }, 2000); 22 | while (!(await callback()) && !timeout) { 23 | // sleep for 100ms 24 | await (async (): Promise => await new Promise((resolve) => setTimeout(resolve, 100)))(); 25 | } 26 | }; 27 | 28 | export type THardhatAccountsNames = 'deployer' | 'user1' | 'user2' | 'user3' | 'user4' | 'user5' | 'governance'; 29 | 30 | export type THardhatAccounts = Record; 31 | export const getTestAccounts = async ( 32 | provider: MockProvider 33 | ): Promise<{ [names in THardhatAccountsNames]: string }> => { 34 | const accounts = await provider.listAccounts(); 35 | 36 | return { 37 | deployer: accounts[0], 38 | user1: accounts[1], 39 | user2: accounts[2], 40 | user3: accounts[3], 41 | user4: accounts[4], 42 | user5: accounts[5], 43 | governance: accounts[10], 44 | }; 45 | }; 46 | 47 | export const getTestSigners = async ( 48 | provider: MockProvider 49 | ): Promise<{ [names in THardhatAccountsNames]: JsonRpcSigner }> => { 50 | const accounts = await provider.listAccounts(); 51 | 52 | return { 53 | deployer: provider.getSigner(accounts[0]), 54 | user1: provider.getSigner(accounts[1]), 55 | user2: provider.getSigner(accounts[2]), 56 | user3: provider.getSigner(accounts[3]), 57 | user4: provider.getSigner(accounts[4]), 58 | user5: provider.getSigner(accounts[5]), 59 | governance: provider.getSigner(accounts[10]), 60 | }; 61 | }; 62 | 63 | export const getHardhatAccount = async (provider: MockProvider, hardhatAccountIndex: number): Promise => { 64 | const accounts = await provider.listAccounts(); 65 | if (accounts?.[hardhatAccountIndex] == null) { 66 | const error = new Error('MockConnector: unknown mock hardhat account'); 67 | console.error(error); 68 | throw error; 69 | } 70 | return accounts[hardhatAccountIndex]; 71 | }; 72 | 73 | export const getHardhatSigner = async (provider: MockProvider, hardhatAccountIndex: number): Promise => { 74 | const accounts = await provider.listAccounts(); 75 | if (accounts?.[hardhatAccountIndex] == null) { 76 | const error = new Error('MockConnector: unknown mock hardhat account'); 77 | console.error(error); 78 | throw error; 79 | } 80 | return provider.getSigner(accounts[hardhatAccountIndex]); 81 | }; 82 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/README.md: -------------------------------------------------------------------------------- 1 | # Generated Docs 2 | 3 | ## Summary 4 | 5 | This folder is used to export modules with comments for docs. 6 | 7 | - do **not** add this to the barrel `index.ts file in helper 8 | 9 | run `yarn docs` 10 | 11 | ## Results 12 | 13 | - this will generate /docs/api-typedocs 14 | 15 | ### Github docs 16 | 17 | - autmatically published from gitbook folder 18 | 19 | ### Gitbook 20 | 21 | - You will have to add new markdown files to SUMMARY.md for each markdown file to show up in gitbook 22 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/contractAppContext.docs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A context for your react app with {@link contractsContextFactory} that provides you access to load, connect and use typed contracts throught your app. 3 | * 4 | * See [the ContractAppContext docs](../../main/context/ContractAppContext) for detailed explanation and examples. 5 | * 6 | * @category ContractAppContext 7 | * @module ContractAppContext 8 | * 9 | */ 10 | 11 | // ------------------------------- 12 | 13 | export * from '../../context/contracts-app'; 14 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/ethersAppContext.docs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A context for your react app with {@link useEthersContext} that provides you access to {@link IEthersContext}. It gives you access to consistent interface to get the current provider {@link EthersModalConnector}. Additionally integration with web3Modal gives you an easy way to guide your user with their web3 journey. 3 | * 4 | * See [the EthersAppContext docs](../../main/context/EthersAppContext) for detailed explanation and examples. 5 | * 6 | * @category EthersAppContext 7 | * @module EthersAppContext 8 | * 9 | */ 10 | 11 | // ------------------------------- 12 | 13 | export * from '../../context/ethers-app'; 14 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/functions.docs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Pure functions in eth-hooks 3 | * 4 | * @module Helpers 5 | */ 6 | 7 | // ------------------------------- 8 | 9 | export * from '../../functions'; 10 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/helpers.docs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Pure functions and helpers with useful functionality 3 | * 4 | * @module Helpers 5 | */ 6 | 7 | // ------------------------------- 8 | 9 | export * from '..'; 10 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/hooks.docs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Commonly used ethereum hooks to turbocharge your development! Works with {@link useEthersContext}. 3 | * 4 | * @module Hooks 5 | */ 6 | 7 | // ------------------------------- 8 | 9 | export * from '../../hooks'; 10 | export * from '../../hooks/dapps'; 11 | export * from '../../hooks/erc'; 12 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/models.docs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Types and constants to make it easier to interact with ethers. 3 | * 4 | * @module Models 5 | */ 6 | 7 | // ------------------------------- 8 | 9 | export * from '../../models'; 10 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/helpers/typedoc/test-utils.docs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Utilities to write tests with ethers, waffle and react hooks 3 | * 4 | * @module TestUtils 5 | */ 6 | 7 | // ------------------------------- 8 | 9 | export * from '../test-utils/constants'; 10 | export * from '../test-utils/eth'; 11 | export * from '../test-utils/functions'; 12 | export * from '../test-utils/wrapper'; 13 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/dapps/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useDexEthPrice'; 2 | export * from './useDexTokenList'; 3 | export * from './useResolveEnsName'; 4 | export * from './useResolveEnsAddress'; 5 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/dapps/useDexEthPrice.ts: -------------------------------------------------------------------------------- 1 | import { Token, WETH, Fetcher, Route } from '@uniswap/sdk'; 2 | import { useQuery } from 'react-query'; 3 | 4 | import { useBlockNumberContext } from '~~/context'; 5 | import { mergeDefaultUpdateOptions, processQueryOptions, providerKey, TRequiredKeys } from '~~/functions'; 6 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 7 | import { THookResult, TNetworkInfo, TUpdateOptions } from '~~/models'; 8 | import { keyNamespace } from '~~/models/constants'; 9 | import { TEthersProvider } from '~~/models/providerTypes'; 10 | 11 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useDexEthPrice' } as const; 12 | 13 | /** 14 | * #### Summary 15 | * Get the Exchange price of ETH/USD (extrapolated from WETH/DAI) from uniswap 16 | * 17 | * ##### ✏️ Notes 18 | * - uses useOnRepetition, does not use context 19 | * 20 | * @category Hooks 21 | * 22 | * @param mainnetProvider 23 | * @param targetNetworkInfo 24 | * @param pollTime if >0 use polling, else use instead of onBlock event 25 | * @returns price in USD 26 | */ 27 | export const useDexEthPrice = ( 28 | mainnetProvider: TEthersProvider | undefined, 29 | targetNetworkInfo?: TNetworkInfo, 30 | options: TUpdateOptions = mergeDefaultUpdateOptions() 31 | ): THookResult => { 32 | const keys = [{ ...queryKey, ...providerKey(mainnetProvider) }, { networkPrice: targetNetworkInfo?.price }] as const; 33 | type TAsyncResult = number | undefined; 34 | 35 | const { data, refetch, status } = useQuery( 36 | keys, 37 | async (keys): Promise => { 38 | const { networkPrice } = keys.queryKey[1]; 39 | if (networkPrice) { 40 | return networkPrice; 41 | } else if (mainnetProvider) { 42 | const network = await mainnetProvider.getNetwork(); 43 | 44 | const DAI = new Token(network ? network.chainId : 1, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18); 45 | const pair = await Fetcher.fetchPairData(DAI, WETH[DAI.chainId], mainnetProvider); 46 | const route = new Route([pair], WETH[DAI.chainId]); 47 | const price = parseFloat(route.midPrice.toSignificant(6)); 48 | return price; 49 | } 50 | }, 51 | { 52 | ...processQueryOptions(options), 53 | } 54 | ); 55 | 56 | const blockNumber = useBlockNumberContext(); 57 | useEthersUpdater(refetch, blockNumber, options); 58 | 59 | return [data ?? 0, refetch, status]; 60 | }; 61 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/dapps/useDexTokenList.ts: -------------------------------------------------------------------------------- 1 | import { TokenInfo, TokenList } from '@uniswap/token-lists'; 2 | import isEqual from 'lodash.isequal'; 3 | import { useQuery } from 'react-query'; 4 | 5 | import { useBlockNumberContext } from '~~/context'; 6 | import { mergeDefaultUpdateOptions, processQueryOptions, TRequiredKeys } from '~~/functions'; 7 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 8 | import { THookResult, TUpdateOptions } from '~~/models'; 9 | import { keyNamespace } from '~~/models/constants'; 10 | 11 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useDexTokenList' } as const; 12 | 13 | /** 14 | * #### Summary 15 | * Gets a tokenlist from uniswap ipfs tokenlist 16 | * 17 | * ##### ✏️ Notes 18 | * - you can also point it to another URI 19 | * 20 | * @category Hooks 21 | * 22 | * @param tokenListUri 23 | * @param chainId optional, you can filter by a particular chainId 24 | * @returns (TokenInfo[]) from '@uniswap/token-lists' 25 | */ 26 | export const useDexTokenList = ( 27 | tokenListUri: string = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org', 28 | chainId?: number, 29 | options: TUpdateOptions = mergeDefaultUpdateOptions() 30 | ): THookResult => { 31 | const keys = [{ ...queryKey }, { tokenListUri, chainId }] as const; 32 | const { data, refetch, status } = useQuery( 33 | keys, 34 | async (keys): Promise => { 35 | const { tokenListUri, chainId } = keys.queryKey[1]; 36 | let tokenInfo: TokenInfo[] = []; 37 | const response = await fetch(tokenListUri); 38 | const tokenList: TokenList = (await response.json()) as TokenList; 39 | if (tokenList != null) { 40 | if (chainId) { 41 | tokenInfo = tokenList.tokens.filter((t: TokenInfo) => { 42 | return t.chainId === chainId; 43 | }); 44 | } else { 45 | tokenInfo = tokenList.tokens; 46 | } 47 | } 48 | return tokenInfo; 49 | }, 50 | { 51 | ...processQueryOptions(options), 52 | isDataEqual: (oldResult, newResult) => isEqual(oldResult, newResult), 53 | } 54 | ); 55 | 56 | const blockNumber = useBlockNumberContext(); 57 | useEthersUpdater(refetch, blockNumber, options); 58 | 59 | return [data ?? [], refetch, status]; 60 | }; 61 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/dapps/useResolveEnsAddress.ts: -------------------------------------------------------------------------------- 1 | import { constants } from 'ethers'; 2 | import { useQuery } from 'react-query'; 3 | 4 | import { providerKey, TRequiredKeys } from '~~/functions'; 5 | import { keyNamespace, TEthersProvider, THookResult } from '~~/models'; 6 | 7 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useResolveEnsAddress' } as const; 8 | 9 | /** 10 | * #### Summary 11 | * Gets the address from an ENS name 12 | * 13 | * @category Hooks 14 | * 15 | * @param mainnetProvider mainnet provider 16 | * @param ensName 17 | * @returns 18 | */ 19 | export const useResolveEnsAddress = ( 20 | mainnetProvider: TEthersProvider | undefined, 21 | ensName: string | undefined 22 | ): THookResult => { 23 | const keys = [{ ...queryKey, ...providerKey(mainnetProvider) }, { ensName }] as const; 24 | const { data, refetch, status } = useQuery(keys, async (keys): Promise => { 25 | const { ensName } = keys.queryKey[1]; 26 | if (mainnetProvider && ensName) { 27 | const resolved = await mainnetProvider.resolveName(ensName); 28 | return resolved ?? constants.AddressZero; 29 | } 30 | return constants.AddressZero; 31 | }); 32 | 33 | return [data, refetch, status]; 34 | }; 35 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/dapps/useResolveEnsName.ts: -------------------------------------------------------------------------------- 1 | import { utils, constants } from 'ethers'; 2 | import { useQuery } from 'react-query'; 3 | 4 | import { providerKey, TRequiredKeys } from '~~/functions'; 5 | import { keyNamespace, TEthersProvider, THookResult } from '~~/models'; 6 | 7 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useResolveEnsName' } as const; 8 | 9 | /** 10 | * @internal 11 | * 12 | * @param provider 13 | * @param address 14 | * @returns 15 | */ 16 | const lookupAddress = async (provider: TEthersProvider, address: string): Promise => { 17 | if (utils.isAddress(address)) { 18 | try { 19 | // Accuracy of reverse resolution is not enforced. 20 | // We then manually ensure that the reported ens name resolves to address 21 | const reportedName = await provider.lookupAddress(address); 22 | const resolvedAddress = await provider.resolveName(reportedName ?? constants.AddressZero); 23 | if (address && utils.getAddress(address) === utils.getAddress(resolvedAddress ?? '')) { 24 | return reportedName ?? ''; 25 | } else { 26 | return utils.getAddress(address); 27 | } 28 | } catch (e) { 29 | return utils.getAddress(address); 30 | } 31 | } 32 | return ''; 33 | }; 34 | 35 | /** 36 | * #### Summary 37 | * Gets ENS name for given address 38 | * 39 | * @category Hooks 40 | * 41 | * @param mainnetProvider mainnet provider 42 | * @param address 43 | * @returns 44 | */ 45 | export const useResolveEnsName = ( 46 | mainnetProvider: TEthersProvider | undefined, 47 | address: string 48 | ): THookResult => { 49 | const keys = [{ ...queryKey, ...providerKey(mainnetProvider) }, { address }] as const; 50 | const { data, refetch, status } = useQuery(keys, async (keys): Promise => { 51 | const { address } = keys.queryKey[1]; 52 | 53 | const storedData: string = window.localStorage.getItem('ethhooks_ensCache_' + address) as string; 54 | const cache = JSON.parse(storedData ?? '{}') as Record; 55 | if (cache && cache?.name && cache?.timestamp > Date.now() && typeof cache?.name === 'string') { 56 | return cache?.name; 57 | } else if (mainnetProvider) { 58 | const ensName = await lookupAddress(mainnetProvider, address); 59 | if (ensName) { 60 | try { 61 | window.localStorage.setItem( 62 | 'ensCache_' + address, 63 | JSON.stringify({ 64 | timestamp: Date.now() + 360000, 65 | name: ensName, 66 | }) 67 | ); 68 | } catch { 69 | /* do nothing */ 70 | } 71 | return ensName; 72 | } 73 | } 74 | }); 75 | 76 | return [data, refetch, status]; 77 | }; 78 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/erc/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useTokenBalance'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/erc/useTokenBalance.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@ethersproject/bignumber'; 2 | import { BaseContract } from '@ethersproject/contracts'; 3 | import { useQuery } from 'react-query'; 4 | 5 | import { useBlockNumberContext } from '~~/context'; 6 | import { contractKey, mergeDefaultUpdateOptions, processQueryOptions, TRequiredKeys } from '~~/functions'; 7 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 8 | import { THookResult, TUpdateOptions } from '~~/models'; 9 | import { keyNamespace } from '~~/models/constants'; 10 | 11 | const zero = BigNumber.from(0); 12 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useTokenBalance' } as const; 13 | 14 | type ERC20 = { 15 | balanceOf: (address: string) => Promise; 16 | }; 17 | 18 | /** 19 | * #### Summary 20 | * Get the balance of an ERC20 token in an address 21 | * 22 | * ##### ✏️ Notes 23 | * - uses the ethers.Contract object's provider to access the network 24 | * 25 | * @category Hooks 26 | * 27 | * @param contract ERC20 token to get the balance of 28 | * @param address Address of wallet that holds the tokens 29 | * @param options Options for how often and when to update 30 | * @returns 31 | */ 32 | export const useTokenBalance = ( 33 | contract: GContract, 34 | address: string, 35 | options: TUpdateOptions = mergeDefaultUpdateOptions() 36 | ): THookResult => { 37 | const keys = [{ ...queryKey, ...contractKey(contract) }, { address }] as const; 38 | const { data, refetch, status } = useQuery( 39 | keys, 40 | async (keys): Promise => { 41 | const { address } = keys.queryKey[1]; 42 | 43 | if (contract?.provider && address) { 44 | const newBalance: BigNumber = (await contract?.balanceOf?.(address)) ?? zero; 45 | return newBalance; 46 | } else { 47 | return zero; 48 | } 49 | }, 50 | { 51 | ...processQueryOptions(options), 52 | isDataEqual: (oldResult, newResult) => oldResult?._hex === newResult?._hex, 53 | } 54 | ); 55 | 56 | const blockNumber = useBlockNumberContext(); 57 | useEthersUpdater(refetch, blockNumber, options); 58 | 59 | return [data ?? zero, refetch, status]; 60 | }; 61 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useAreSignerEqual'; 2 | export * from './useBalance'; 3 | export * from './useBlockNumber'; 4 | export * from './useBurnerSigner'; 5 | export * from './useContractExistsAtAddress'; 6 | export * from './useContractReader'; 7 | export * from './useEthersAdaptorFromProviderOrSigners'; 8 | export * from './useEthersUpdater'; 9 | export * from './useEventListener'; 10 | export * from './useGasPrice'; 11 | export * from './useNonce'; 12 | export * from './useSignerAddress'; 13 | export * from './useSignerChainId'; 14 | export * from './useTimestamp'; 15 | export * from './useCheckIsMounted'; 16 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useAreSignerEqual.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from 'react-query'; 2 | 3 | import { useBlockNumberContext } from '~~/context'; 4 | import { mergeDefaultUpdateOptions, processQueryOptions, providerKey, signerHasNetwork } from '~~/functions'; 5 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 6 | import { keyNamespace, TEthersSigner, THookResult, TUpdateOptions } from '~~/models'; 7 | 8 | const queryKey = { namespace: keyNamespace.signer, key: 'useAreSignerEqual' } as const; 9 | 10 | /** 11 | * #### Summary 12 | * Are the signers equal and valid 13 | * 14 | * @category Hooks 15 | * 16 | * @param signer1 Object for first signer to compare 17 | * @param signer2 Object for second signer to compare 18 | * @param options Options for how often and when to update 19 | * @returns 20 | */ 21 | export const useAreSignerEqual = ( 22 | signer1: TEthersSigner | undefined, 23 | signer2: TEthersSigner | undefined, 24 | options: TUpdateOptions = mergeDefaultUpdateOptions() 25 | ): THookResult => { 26 | const keys = [{ ...queryKey }, { singer1Key: providerKey(signer1), signer2Key: providerKey(signer2) }] as const; 27 | const { data, refetch, status } = useQuery( 28 | keys, 29 | async (_keys): Promise => { 30 | if (signerHasNetwork(signer1)) { 31 | const chainId1 = await signer1?.getChainId(); 32 | const chainId2 = await signer2?.getChainId(); 33 | 34 | const address1 = await signer1?.getAddress(); 35 | const address2 = await signer2?.getAddress(); 36 | const isEqual = 37 | address1 === address2 && chainId1 === chainId2 && address1 !== undefined && chainId1 !== undefined; 38 | return isEqual; 39 | } 40 | return undefined; 41 | }, 42 | { 43 | ...processQueryOptions(options), 44 | } 45 | ); 46 | 47 | const blockNumber = useBlockNumberContext(); 48 | useEthersUpdater(refetch, blockNumber, options); 49 | 50 | return [data, refetch, status]; 51 | }; 52 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useBlockNumber.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useQuery } from 'react-query'; 3 | 4 | import { mergeDefaultUpdateOptions, processQueryOptions, providerKey, TRequiredKeys } from '~~/functions'; 5 | import { keyNamespace, TEthersProvider, THookResult, TUpdateOptions } from '~~/models'; 6 | 7 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useBlockNumber' }; 8 | 9 | /** 10 | * #### Summary 11 | * Get the current block number of the network. ✋🏽 @deprecated 12 | * 13 | * ##### ✏️ Notes 14 | * - ✋🏽 For app wide block number access use {@link useBlockNumberContext} instead. See {@link BlockNumberContext} for more details, you get this as part of {@link EthersAppContext} 15 | * - uses the current provided block number 16 | * 17 | * @category Hooks 18 | * 19 | * @param provider 20 | * @returns block number 21 | */ 22 | export const useBlockNumber = ( 23 | provider: TEthersProvider | undefined, 24 | callback?: ((blockNumber?: number) => void) | ((blockNumber?: number) => Promise), 25 | options: TUpdateOptions = mergeDefaultUpdateOptions() 26 | ): THookResult => { 27 | type TAsyncResult = number | undefined; 28 | const keys = [ 29 | { 30 | ...queryKey, 31 | ...providerKey(provider), 32 | }, 33 | ] as const; 34 | 35 | const { data, refetch, status } = useQuery( 36 | keys, 37 | async (_keys): Promise => { 38 | if (provider) { 39 | const nextBlockNumber = await provider?.getBlockNumber(); 40 | return nextBlockNumber; 41 | } 42 | 43 | return undefined; 44 | }, 45 | { 46 | ...processQueryOptions(options), 47 | } 48 | ); 49 | 50 | useEffect(() => { 51 | if (provider) { 52 | const listener = (blockNumberLocal: number): void => { 53 | void refetch(); 54 | 55 | if (callback != null) { 56 | try { 57 | void callback(blockNumberLocal); 58 | } catch (e) { 59 | console.warn('useBlockNumber callback failed', e); 60 | } 61 | } 62 | }; 63 | provider?.addListener?.('block', listener); 64 | 65 | if (data == null) { 66 | void refetch(); 67 | } 68 | 69 | return (): void => { 70 | provider?.removeListener?.('block', listener); 71 | }; 72 | } 73 | // eslint-disable-next-line react-hooks/exhaustive-deps 74 | }, [callback, provider, refetch]); 75 | 76 | return [data ?? 0, refetch, status]; 77 | }; 78 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useCheckIsMounted.ts: -------------------------------------------------------------------------------- 1 | import { useIsMounted } from 'usehooks-ts'; 2 | 3 | export const useCheckIsMounted = (): void => { 4 | const data = useIsMounted(); 5 | if (data()) { 6 | console.log('is mounted'); 7 | } else { 8 | console.log('not mounted'); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useContractExistsAtAddress.ts: -------------------------------------------------------------------------------- 1 | import { BaseContract, utils } from 'ethers'; 2 | import { useQuery } from 'react-query'; 3 | 4 | import { useBlockNumberContext } from '~~/context'; 5 | import { contractKey, mergeDefaultUpdateOptions, processQueryOptions, TRequiredKeys } from '~~/functions'; 6 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 7 | import { THookResult, TUpdateOptions } from '~~/models'; 8 | import { keyNamespace } from '~~/models/constants'; 9 | 10 | const queryKey: TRequiredKeys = { namespace: keyNamespace.contracts, key: 'useContractExistsAtAddress' } as const; 11 | 12 | /** 13 | * #### Summary 14 | * Checks whether a contract exists on the blockchain 15 | * 16 | * ##### ✏️ Notes 17 | * - uses the ethers.Contract object's provider to access the network 18 | * - checks the contract address to see if the contract is deployed 19 | * 20 | * @category Hooks 21 | * 22 | * @param contract ethers.BaseContract class 23 | * @returns 24 | */ 25 | export const useContractExistsAtAddress = ( 26 | contract: GContract | undefined, 27 | options: TUpdateOptions = mergeDefaultUpdateOptions() 28 | ): THookResult => { 29 | const keys = [{ ...queryKey, ...contractKey(contract) }, { contractAddress: contract?.address }] as const; 30 | const { data, refetch, status } = useQuery( 31 | keys, 32 | async (keys): Promise => { 33 | const { contractAddress } = keys.queryKey[1]; 34 | /** 35 | * We can look at the blockchain and see what's stored at `contractAddress` 36 | * If we find code then we know that a contract exists there. 37 | * If we find nothing (0x0) then there is no contract deployed to that address 38 | */ 39 | if (contractAddress != null && utils.isAddress(contractAddress) && contract?.provider != null) { 40 | const bytecode = await contract.provider.getCode(contractAddress); 41 | return bytecode !== '0x'; 42 | } 43 | return false; 44 | }, 45 | { 46 | ...processQueryOptions(options), 47 | } 48 | ); 49 | 50 | const blockNumber = useBlockNumberContext(); 51 | useEthersUpdater(refetch, blockNumber, options); 52 | 53 | return [data ?? false, refetch, status]; 54 | }; 55 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useEthersAdaptorFromProviderOrSigners.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useQuery } from 'react-query'; 3 | 4 | import { 5 | isAdaptorEqual, 6 | isValidEthersAdaptor, 7 | mergeDefaultUpdateOptions, 8 | parseProviderOrSigner, 9 | processQueryOptions, 10 | providerKey, 11 | TRequiredKeys, 12 | } from '~~/functions'; 13 | import { TEthersProviderOrSigner, THookResult, TUpdateOptions } from '~~/models'; 14 | import { keyNamespace } from '~~/models/constants'; 15 | import { TEthersAdaptor } from '~~/models/ethersAppContextTypes'; 16 | 17 | const queryKey: TRequiredKeys = { 18 | namespace: keyNamespace.network, 19 | key: 'useGetEthersAdaptorFromProviderOrSigners', 20 | } as const; 21 | 22 | /** 23 | * #### Summary 24 | * Gets the user {@link TEthersUser} for a signer or wallet 25 | * 26 | * @category Hooks 27 | * 28 | * @param providerOrSigner input signer 29 | * @returns 30 | */ 31 | export const useEthersAdaptorFromProviderOrSigners = ( 32 | providerOrSigner: TEthersProviderOrSigner | undefined, 33 | options: TUpdateOptions = mergeDefaultUpdateOptions() 34 | ): THookResult => { 35 | const keys = [{ ...queryKey, ...providerKey(providerOrSigner) }] as const; 36 | const { data, refetch, status } = useQuery( 37 | keys, 38 | async (_keys): Promise => { 39 | const result = await parseProviderOrSigner(providerOrSigner); 40 | return result; 41 | }, 42 | { 43 | ...processQueryOptions(options), 44 | isDataEqual: (oldData, newData) => isAdaptorEqual(oldData, newData), 45 | } 46 | ); 47 | 48 | const validAdaptorState = isValidEthersAdaptor(data); 49 | 50 | // if the adaptor is not valid, refetch when the network is obtained 51 | useEffect(() => { 52 | if (data != null && !validAdaptorState) { 53 | console.log('not valid'); 54 | if (data.provider) { 55 | void data.provider 56 | .getNetwork() 57 | .then(() => refetch()) 58 | .catch(); 59 | } else if (data.signer && data.account) { 60 | void data.signer.provider 61 | ?.getNetwork() 62 | .then(() => refetch()) 63 | .catch(); 64 | } 65 | } 66 | }, [data, refetch, validAdaptorState]); 67 | 68 | return [data, refetch, status]; 69 | }; 70 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useEthersUpdater.ts: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react'; 2 | 3 | import { checkUpdateOptions } from '~~/functions'; 4 | import { TUpdateOptions } from '~~/models'; 5 | 6 | /** 7 | * #### Summary 8 | * A hook that invokes an update callback function based on update options and ethers network state (i.e. block number) 9 | * 10 | * @param update Function to call when update 11 | * @param blockNumber Current block number 12 | * @param options Options for how often and when to update 13 | * @param allowBlockNumberUpdate Boolean of if updating using this hook is allowed 14 | */ 15 | export const useEthersUpdater = ( 16 | update: (() => void) | (() => Promise), 17 | blockNumber: number | undefined, 18 | options: TUpdateOptions, 19 | allowBlockNumberUpdate: boolean = true 20 | ): void => { 21 | checkUpdateOptions(options); 22 | const updateNumberRef = useRef(undefined); 23 | 24 | // number that only increases every (X * options.blockNumberInterval) blocks 25 | const blockNumberFilter = blockNumber ? Math.floor(blockNumber / (options.blockNumberInterval ?? 1)) : undefined; 26 | 27 | if (allowBlockNumberUpdate) { 28 | // update if blocknumber or if polling 29 | if (!options.refetchInterval && blockNumberFilter !== updateNumberRef.current) { 30 | updateNumberRef.current = blockNumberFilter; 31 | void update(); 32 | } 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useEventListener.ts: -------------------------------------------------------------------------------- 1 | import { EventFilter, BaseContract } from 'ethers'; 2 | import { Result } from 'ethers/lib/utils'; 3 | import { useEffect } from 'react'; 4 | import { useQuery } from 'react-query'; 5 | 6 | import { contractKey, mergeDefaultUpdateOptions, processQueryOptions, TRequiredKeys } from '~~/functions'; 7 | import { const_blockNumberIntervalMedium, THookResult, TUpdateOptions, TypedEvent } from '~~/models'; 8 | import { keyNamespace } from '~~/models/constants'; 9 | 10 | const queryKey: TRequiredKeys = { namespace: keyNamespace.contracts, key: 'useEventListener' } as const; 11 | /** 12 | * #### Summary 13 | * Tracks the events of associated with a contract 14 | * 15 | * ##### ✏️ Notes 16 | * - updates triggered through ethers event listener 17 | * - uses the current provider {@link ethersProvider} from {@link useEthersContext} 18 | * 19 | * @category Hooks 20 | * 21 | * @param contract ethers.Contract 22 | * @param eventName 23 | * @param startBlock 24 | * @returns 25 | */ 26 | export const useEventListener = >( 27 | contract: BaseContract | undefined, 28 | eventFilter: string | EventFilter | undefined, 29 | startBlock: number, 30 | toBlock: number | undefined = undefined, 31 | options: TUpdateOptions = mergeDefaultUpdateOptions(const_blockNumberIntervalMedium) 32 | ): THookResult => { 33 | const keys = [ 34 | { 35 | ...queryKey, 36 | ...contractKey(contract), 37 | }, 38 | { 39 | eventFilter, 40 | startBlock, 41 | toBlock, 42 | }, 43 | ] as const; 44 | const { data, refetch, status } = useQuery( 45 | keys, 46 | async (keys): Promise => { 47 | { 48 | const { eventFilter: eventFilter_, startBlock: startBlock_, toBlock: toBlock_ } = keys.queryKey[1]; 49 | const result = await contract?.queryFilter(eventFilter_ as EventFilter, startBlock_, toBlock_); 50 | return (result as GTypedEvent[]) ?? []; 51 | } 52 | }, 53 | { 54 | ...processQueryOptions(options), 55 | } 56 | ); 57 | 58 | // update the result when ethers calls the event listner 59 | useEffect(() => { 60 | if (eventFilter != null) { 61 | const listener = (): void => { 62 | void refetch(); 63 | }; 64 | try { 65 | contract?.on(eventFilter, listener); 66 | return (): void => { 67 | contract?.off(eventFilter, listener); 68 | }; 69 | } catch (e) { 70 | console.log(e); 71 | } 72 | } 73 | }, [contract, eventFilter, refetch]); 74 | 75 | // const blockNumber = useBlockNumberContext(); 76 | // useEthersUpdater(refetch, blockNumber, options); 77 | 78 | return [data ?? [], refetch, status]; 79 | }; 80 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useNonce.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from 'react-query'; 2 | 3 | import { useBlockNumberContext, useEthersAppContext } from '~~/context'; 4 | import { 5 | ethersOverride, 6 | mergeDefaultOverride, 7 | mergeDefaultUpdateOptions, 8 | processQueryOptions, 9 | providerKey, 10 | TRequiredKeys, 11 | } from '~~/functions'; 12 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 13 | import { THookResult, TOverride, TUpdateOptions } from '~~/models'; 14 | import { keyNamespace } from '~~/models/constants'; 15 | 16 | const queryKey: TRequiredKeys = { 17 | namespace: keyNamespace.signer, 18 | key: 'useNonce', 19 | } as const; 20 | 21 | /** 22 | * #### Summary 23 | * Get the current nonce for the address provided 24 | * 25 | * ##### ✏️ Notes 26 | * - updates triggered by {@link BlockNumberContext} 27 | * - uses the current provider {@link ethersProvider} from {@link useEthersContext} 28 | * 29 | * @category Hooks 30 | * 31 | * @param address 32 | * @returns 33 | */ 34 | export const useNonce = ( 35 | address: string | undefined, 36 | options: TUpdateOptions = mergeDefaultUpdateOptions(), 37 | override: TOverride = mergeDefaultOverride() 38 | ): THookResult => { 39 | const ethersContext = useEthersAppContext(override.alternateContextKey); 40 | const { provider } = ethersOverride(ethersContext, override); 41 | 42 | const keys = [{ ...queryKey, ...providerKey(provider) }, { address }] as const; 43 | const { data, refetch, status } = useQuery( 44 | keys, 45 | async (keys): Promise => { 46 | const { address } = keys.queryKey[1]; 47 | if (address) { 48 | const nextNonce = await provider?.getTransactionCount(address); 49 | return nextNonce ?? 0; 50 | } 51 | return undefined; 52 | }, 53 | { 54 | ...processQueryOptions(options), 55 | } 56 | ); 57 | 58 | const blockNumber = useBlockNumberContext(); 59 | useEthersUpdater(refetch, blockNumber, options); 60 | 61 | return [data ?? 0, refetch, status]; 62 | }; 63 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useSignerAddress.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from 'react-query'; 2 | 3 | import { useBlockNumberContext } from '~~/context'; 4 | import { mergeDefaultUpdateOptions, processQueryOptions, providerKey } from '~~/functions'; 5 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 6 | import { keyNamespace, TEthersSigner, THookResult, TUpdateOptions } from '~~/models'; 7 | 8 | const queryKey = { namespace: keyNamespace.signer, key: 'useSignerAddress' } as const; 9 | 10 | /** 11 | * #### Summary 12 | * Get the address from the signer 13 | * 14 | * @category Hooks 15 | * 16 | * @param signer 17 | * @returns 18 | */ 19 | export const useSignerAddress = ( 20 | signer: TEthersSigner | undefined, 21 | options: TUpdateOptions = mergeDefaultUpdateOptions() 22 | ): THookResult => { 23 | const keys = [{ ...queryKey, ...providerKey(signer) }] as const; 24 | const { data, refetch, status } = useQuery( 25 | keys, 26 | async (_keys): Promise => { 27 | if (signer) { 28 | const result = await signer.getAddress(); 29 | return result; 30 | } 31 | return undefined; 32 | }, 33 | { 34 | ...processQueryOptions(options), 35 | } 36 | ); 37 | 38 | const blockNumber = useBlockNumberContext(); 39 | useEthersUpdater(refetch, blockNumber, options); 40 | 41 | return [data, refetch, status]; 42 | }; 43 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useSignerChainId.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from 'react-query'; 2 | 3 | import { useBlockNumberContext } from '~~/context'; 4 | import { mergeDefaultUpdateOptions, processQueryOptions, providerKey, TRequiredKeys } from '~~/functions'; 5 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 6 | import { const_blockNumberIntervalMedium, TEthersSigner, THookResult, TUpdateOptions } from '~~/models'; 7 | import { keyNamespace } from '~~/models/constants'; 8 | 9 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useSignerChainId' } as const; 10 | 11 | /** 12 | * #### Summary 13 | * Get the address from the signer 14 | * 15 | * @category Hooks 16 | * 17 | * @param signer 18 | * @returns 19 | */ 20 | export const useSignerChainId = ( 21 | signer: TEthersSigner | undefined, 22 | options: TUpdateOptions = mergeDefaultUpdateOptions({ ...const_blockNumberIntervalMedium }) 23 | ): THookResult => { 24 | type TAsyncResult = number | undefined; 25 | const keys = [{ ...queryKey, ...providerKey(signer) }] as const; 26 | 27 | const { data, refetch, status } = useQuery( 28 | keys, 29 | async (_keys): Promise => { 30 | // const { signer } = keys.queryKey[1]; 31 | const chainId = await signer?.getChainId(); 32 | return chainId; 33 | }, 34 | { 35 | ...processQueryOptions(options), 36 | } 37 | ); 38 | 39 | const blockNumber = useBlockNumberContext(); 40 | useEthersUpdater(refetch, blockNumber, options); 41 | 42 | return [data, refetch, status]; 43 | }; 44 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/hooks/useTimestamp.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from 'react-query'; 2 | 3 | import { useBlockNumberContext, useEthersAppContext } from '~~/context'; 4 | import { 5 | ethersOverride, 6 | mergeDefaultOverride, 7 | mergeDefaultUpdateOptions, 8 | processQueryOptions, 9 | providerKey, 10 | TRequiredKeys, 11 | } from '~~/functions'; 12 | import { useEthersUpdater } from '~~/hooks/useEthersUpdater'; 13 | import { THookResult, TOverride, TUpdateOptions } from '~~/models'; 14 | import { keyNamespace } from '~~/models/constants'; 15 | 16 | const queryKey: TRequiredKeys = { namespace: keyNamespace.signer, key: 'useTimestamp' } as const; 17 | 18 | /** 19 | * #### Summary 20 | * Get the current timestamp from the latest block 21 | * 22 | * ##### ✏️ Notes 23 | * - updates triggered by {@link BlockNumberContext} 24 | * - uses the current provider {@link ethersProvider} from {@link useEthersContext} 25 | * 26 | * @category Hooks 27 | * 28 | * @param pollTime 29 | * @returns 30 | */ 31 | export const useTimestamp = ( 32 | options: TUpdateOptions = mergeDefaultUpdateOptions(), 33 | override: TOverride = mergeDefaultOverride() 34 | ): THookResult => { 35 | const blockNumber = useBlockNumberContext(); 36 | const ethersContext = useEthersAppContext(override.alternateContextKey); 37 | const { provider } = ethersOverride(ethersContext, override); 38 | 39 | const keys = [{ ...queryKey, ...providerKey(provider) }] as const; 40 | const { data, refetch, status } = useQuery( 41 | keys, 42 | async (_keys): Promise => { 43 | const blockNumber = await provider?.getBlockNumber(); 44 | 45 | if (blockNumber != null) { 46 | const block = await provider?.getBlock(blockNumber); 47 | if (block?.timestamp != null) { 48 | return block.timestamp; 49 | } 50 | } 51 | return 0; 52 | }, 53 | { 54 | ...processQueryOptions(options), 55 | } 56 | ); 57 | 58 | useEthersUpdater(refetch, blockNumber, options); 59 | return [data ?? 0, refetch, status]; 60 | }; 61 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module Hooks 3 | */ 4 | 5 | export * from './hooks'; 6 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/constants/common.ts: -------------------------------------------------------------------------------- 1 | export const const_web3DialogClosedByUser = 'Modal closed by user'; 2 | export const const_web3DialogUserRejected = 'Error: User Rejected'; 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './common'; 2 | export * from './keyNamespace'; 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/constants/keyNamespace.ts: -------------------------------------------------------------------------------- 1 | export const keyNamespace = { 2 | network: 'network', 3 | signer: 'signer', 4 | contracts: 'contracts', 5 | state: 'state', 6 | } as const; 7 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/contractTypesDeprecated.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * #### Summary 3 | * @depcrated 4 | * Contract function information: 5 | * - contractName 6 | * - functionname 7 | * - functionArgs: functionArguments, an array 8 | * 9 | * @category Models 10 | */ 11 | 12 | export type TContractFunctionInfoUntyped = { 13 | contractName: string; 14 | functionName: string; 15 | functionArgs?: any[]; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/contractTypesForge.ts: -------------------------------------------------------------------------------- 1 | import { z, ZodType } from 'zod'; 2 | 3 | export type TForgeTransactionData = z.infer; 4 | export const forgeTransactionDataSchema = z.object({ 5 | type: z.string(), 6 | from: z.string(), 7 | gas: z.string(), 8 | value: z.string(), 9 | data: z.string(), 10 | nonce: z.string(), 11 | accessList: z.array(z.string()), 12 | }); 13 | 14 | export type TForgeTransaction = { 15 | hash: string | null; 16 | transactionType: 'CREATE' | Omit; 17 | contractName: string; 18 | contractAddress: string; 19 | function: string | null; 20 | arguments: string | null; 21 | transaction: TForgeTransactionData; 22 | }; 23 | 24 | export const forgeTransactionSchema: ZodType = z.object({ 25 | hash: z.string().nullable(), 26 | transactionType: z.string(), 27 | contractName: z.string(), 28 | contractAddress: z.string(), 29 | function: z.string().nullable(), 30 | arguments: z.string().nullable(), 31 | transaction: forgeTransactionDataSchema, 32 | }); 33 | 34 | export type TForgeBroadcastJson = { 35 | transactions: TForgeTransaction[]; 36 | }; 37 | 38 | export type TForgeDeploymentBroadcastCollection = { 39 | [chainId: number]: TForgeBroadcastJson; 40 | }; 41 | 42 | export const forgeDeploymentBroadcastCollectionSchema: ZodType = z.record( 43 | z.union([z.number(), z.string()], { description: 'chainId' }).transform((t) => parseInt(t as string)), 44 | z.object({ 45 | transactions: z.array(forgeTransactionSchema), 46 | }) 47 | ); 48 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/contractTypesHardhat.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | 3 | /** 4 | * #### Summary 5 | * Describes the structure of hardhat_contracts.json 6 | * - {chainIds: { networkNames: {contracts} }}, contains an record of contracts 7 | * - Used by {@link useContractLoader} 8 | * 9 | * @category Models 10 | */ 11 | export type TDeployedHardhatContractsJson = z.infer; 12 | 13 | /** 14 | * #### Summary 15 | * Zod Schema for {@link TBasicContractMap} 16 | */ 17 | export const deployedHardhatContractsJsonSchema = z.record( 18 | z.union([z.string(), z.number()], { description: 'chainId' }).transform((s) => parseInt(s.toString())), 19 | z 20 | .object({ 21 | name: z.string({ description: 'contractName' }), 22 | chainId: z.string({ description: 'chainId' }), 23 | contracts: z.record( 24 | z.string({ description: 'contractName' }), 25 | z.object({ 26 | address: z.string(), 27 | abi: z.array(z.any()).optional(), 28 | }) 29 | ), 30 | }) 31 | .array() 32 | ); 33 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/ethersAppContextTypes.ts: -------------------------------------------------------------------------------- 1 | import { Web3ReactContextInterface } from '@web3-react/core/dist/types'; 2 | import { Signer } from 'ethers'; 3 | 4 | import { TEthersModalConnector } from '~~/context/ethers-app/connectors/EthersModalConnector'; 5 | import { TEthersProvider, TEthersSigner } from '~~/models'; 6 | 7 | /** 8 | * #### Summary 9 | * A callback type that returns a EthersModalConnector 10 | * 11 | * ##### ✏️ Notes 12 | * - can be used by components that need to give a connector to {@link IEthersContext.openModal} 13 | * - id is the identifier of the provider: [See docs](https://github.com/Web3Modal/web3modal#connect-to-specific-provider) 14 | * 15 | * @category EthersAppContext 16 | */ 17 | export type TCreateEthersModalConnector = (id?: string) => TEthersModalConnector | undefined; 18 | 19 | /** 20 | * #### Summary 21 | * The return type of {@link TCreateEthersModalConnector} 22 | * - ethers compatable provider {@link TEthersProvider} 23 | * - a callback to change the current signer 24 | * - the current account, chainId and signer 25 | * - callbacks to open the web3Modal, logout or change theme 26 | * 27 | * @category EthersAppContext 28 | */ 29 | export interface IEthersContext extends Web3ReactContextInterface { 30 | connector: TEthersModalConnector | undefined; 31 | provider: TEthersProvider | undefined; 32 | active: boolean; 33 | signer: TEthersSigner | undefined; 34 | account: string | undefined; 35 | chainId: number | undefined; 36 | changeSigner: ((signer: Signer) => Promise) | undefined; 37 | /** 38 | * Open web3 modal for login 39 | */ 40 | openModal: (ethersModalConnector: TEthersModalConnector, onError?: (error: Error) => void) => void; 41 | disconnectModal: (onSuccess?: () => void) => void; 42 | setModalTheme: ((theme: 'light' | 'dark') => void) | undefined; 43 | } 44 | 45 | /** 46 | * #### Summary 47 | * Essentially a object that allows interaction with the network: 48 | * - provider signer, 49 | * 50 | * @category Type Definition 51 | */ 52 | export type TEthersAdaptor = { 53 | signer?: TEthersSigner; 54 | provider?: TEthersProvider; 55 | chainId?: number; 56 | account?: string; 57 | }; 58 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './constants'; 2 | export * from './contractAppContextTypes'; 3 | export * from './contractTypes'; 4 | export * from './ethersAppContextTypes'; 5 | export * from './hookTypes'; 6 | export * from './networkTypes'; 7 | export * from './providerTypes'; 8 | export * from './utilityTypes'; 9 | export * from './contractTypesForge'; 10 | export * from './contractTypesHardhat'; 11 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/networkTypes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * #### Summary 3 | * A type that describes the basics of a network for applications. e.g. mainnet, ropsten, rinkeby, etc. 4 | * 5 | * @category Models 6 | */ 7 | export type TNetworkInfo = { 8 | name: string; 9 | chainId: number; 10 | rpcUrl: string; 11 | faucet?: string; 12 | blockExplorer: string; 13 | price?: number; 14 | gasPrice?: number; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/providerTypes.ts: -------------------------------------------------------------------------------- 1 | import { 2 | JsonRpcProvider, 3 | StaticJsonRpcProvider, 4 | Web3Provider, 5 | Provider, 6 | JsonRpcSigner, 7 | } from '@ethersproject/providers'; 8 | import { Signer, VoidSigner, Wallet, Event, EventFilter } from 'ethers'; 9 | import { Result } from 'ethers/lib/utils'; 10 | /** 11 | * #### Summary 12 | * A union of various ethers providers for ease of use and maximum flexiblity 13 | * 14 | * ##### ✏️ Notes 15 | * Used by eth-hooks, eth-components and scaffold-eth-typescript 16 | * 17 | * @category Models 18 | */ 19 | export type TEthersProvider = JsonRpcProvider | Web3Provider | StaticJsonRpcProvider; 20 | 21 | /** 22 | * #### Summary 23 | * A union of various providers and signers in ethers to give maximum flexibility 24 | * 25 | * @category Models 26 | */ 27 | export type TEthersProviderOrSigner = 28 | | JsonRpcProvider 29 | | Web3Provider 30 | | StaticJsonRpcProvider 31 | | Signer 32 | | JsonRpcSigner 33 | | Wallet 34 | | VoidSigner; 35 | 36 | /** 37 | * #### Summary 38 | * A union of various providers in ethers to give maximum flexibility 39 | * 40 | * @category Models 41 | */ 42 | export type TEthersSigner = Signer | JsonRpcSigner | Wallet | VoidSigner; 43 | 44 | /** 45 | * #### Summary 46 | * A union of abstract, non initalizable providers, used by some functions 47 | * 48 | * @category Models 49 | */ 50 | export type TAbstractProvider = Provider; 51 | 52 | /** 53 | * #### Summary 54 | * An generic extension of EventFilter that is used by TypedEvent. It allows for typed events to be returned 55 | * 56 | * @category Models 57 | */ 58 | export type TypedEventFilter< 59 | _EventArgsArray extends Array, 60 | _EventArgsObject extends Record 61 | > = EventFilter; 62 | 63 | /** 64 | * #### Summary 65 | * An generic extension of Event. It types the the arguments and return values of the contract event to be used in typescript. 66 | * 67 | * @category Models 68 | */ 69 | export type TypedEvent = Event & { 70 | args: EventArgs; 71 | }; 72 | -------------------------------------------------------------------------------- /packages/eth-hooks/src/models/utilityTypes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * #### Summary 3 | * Similar to [partial](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) int typescript but allows deep partial types. 4 | * 5 | * @category Models 6 | */ 7 | export type DeepPartial = { 8 | [P in keyof T]?: DeepPartial; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/README.md: -------------------------------------------------------------------------------- 1 | This package was automatically generated by eth-sdk. Don't edit its source code, it will be rewritten when you run 2 | eth-sdk next time. 3 | 4 | --- 5 | 6 | `index.cjs`, `index.d.ts`, `index.mjs`, `types.d.ts` and `package.json` here are static files copied from 7 | `eth-sdk/static` to the generated package. 8 | 9 | You can find your generated files in `./esm` and `./cjs` directories. 10 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Signer } from 'ethers'; 2 | import * as types from './types'; 3 | export declare function getContract(address: string, abi: object, defaultSigner: Signer): any; 4 | export declare type MainnetSdk = ReturnType; 5 | export declare function getMainnetSdk(defaultSigner: Signer): { 6 | DAI: types.DAI; 7 | UNI: types.UNI; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var __importDefault = 3 | (this && this.__importDefault) || 4 | function (mod) { 5 | return mod && mod.__esModule ? mod : { default: mod }; 6 | }; 7 | Object.defineProperty(exports, '__esModule', { value: true }); 8 | exports.getMainnetSdk = exports.getContract = void 0; 9 | const ethers_1 = require('ethers'); 10 | const DAI_json_1 = __importDefault(require('../../abis/mainnet/DAI.json')); 11 | const UNI_json_1 = __importDefault(require('../../abis/mainnet/UNI.json')); 12 | function getContract(address, abi, defaultSigner) { 13 | return new ethers_1.Contract(address, abi, defaultSigner); 14 | } 15 | exports.getContract = getContract; 16 | function getMainnetSdk(defaultSigner) { 17 | return { 18 | DAI: getContract('0x6b175474e89094c44da98b954eedeac495271d0f', DAI_json_1.default, defaultSigner), 19 | UNI: getContract('0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', UNI_json_1.default, defaultSigner), 20 | }; 21 | } 22 | exports.getMainnetSdk = getMainnetSdk; 23 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/DAI.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/UNI.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/common.d.ts: -------------------------------------------------------------------------------- 1 | import type { Listener } from '@ethersproject/providers'; 2 | import type { Event, EventFilter } from 'ethers'; 3 | export interface TypedEvent = any, TArgsObject = any> extends Event { 4 | args: TArgsArray & TArgsObject; 5 | } 6 | export interface TypedEventFilter<_TEvent extends TypedEvent> extends EventFilter {} 7 | export interface TypedListener { 8 | (...listenerArg: [...__TypechainArgsArray, TEvent]): void; 9 | } 10 | declare type __TypechainArgsArray = T extends TypedEvent ? U : never; 11 | export interface OnEvent { 12 | (eventFilter: TypedEventFilter, listener: TypedListener): TRes; 13 | (eventName: string, listener: Listener): TRes; 14 | } 15 | export declare type MinEthersFactory = { 16 | deploy(...a: ARGS[]): Promise; 17 | }; 18 | export declare type GetContractTypeFromFactory = F extends MinEthersFactory ? C : never; 19 | export declare type GetARGsTypeFromFactory = F extends MinEthersFactory ? Parameters : never; 20 | export {}; 21 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/common.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/factories/DAI__factory.d.ts: -------------------------------------------------------------------------------- 1 | import { Signer } from 'ethers'; 2 | import { Provider } from '@ethersproject/providers'; 3 | import type { DAI, DAIInterface } from '../DAI'; 4 | export declare class DAI__factory { 5 | static readonly abi: ( 6 | | { 7 | inputs: { 8 | internalType: string; 9 | name: string; 10 | type: string; 11 | }[]; 12 | payable: boolean; 13 | stateMutability: string; 14 | type: string; 15 | anonymous?: undefined; 16 | name?: undefined; 17 | constant?: undefined; 18 | outputs?: undefined; 19 | } 20 | | { 21 | anonymous: boolean; 22 | inputs: { 23 | indexed: boolean; 24 | internalType: string; 25 | name: string; 26 | type: string; 27 | }[]; 28 | name: string; 29 | type: string; 30 | payable?: undefined; 31 | stateMutability?: undefined; 32 | constant?: undefined; 33 | outputs?: undefined; 34 | } 35 | | { 36 | constant: boolean; 37 | inputs: { 38 | internalType: string; 39 | name: string; 40 | type: string; 41 | }[]; 42 | name: string; 43 | outputs: { 44 | internalType: string; 45 | name: string; 46 | type: string; 47 | }[]; 48 | payable: boolean; 49 | stateMutability: string; 50 | type: string; 51 | anonymous?: undefined; 52 | } 53 | )[]; 54 | static createInterface(): DAIInterface; 55 | static connect(address: string, signerOrProvider: Signer | Provider): DAI; 56 | } 57 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/factories/UNI__factory.d.ts: -------------------------------------------------------------------------------- 1 | import { Signer } from 'ethers'; 2 | import { Provider } from '@ethersproject/providers'; 3 | import type { UNI, UNIInterface } from '../UNI'; 4 | export declare class UNI__factory { 5 | static readonly abi: ( 6 | | { 7 | inputs: { 8 | internalType: string; 9 | name: string; 10 | type: string; 11 | }[]; 12 | payable: boolean; 13 | stateMutability: string; 14 | type: string; 15 | anonymous?: undefined; 16 | name?: undefined; 17 | constant?: undefined; 18 | outputs?: undefined; 19 | } 20 | | { 21 | anonymous: boolean; 22 | inputs: { 23 | indexed: boolean; 24 | internalType: string; 25 | name: string; 26 | type: string; 27 | }[]; 28 | name: string; 29 | type: string; 30 | payable?: undefined; 31 | stateMutability?: undefined; 32 | constant?: undefined; 33 | outputs?: undefined; 34 | } 35 | | { 36 | constant: boolean; 37 | inputs: { 38 | internalType: string; 39 | name: string; 40 | type: string; 41 | }[]; 42 | name: string; 43 | outputs: { 44 | internalType: string; 45 | name: string; 46 | type: string; 47 | }[]; 48 | payable: boolean; 49 | stateMutability: string; 50 | type: string; 51 | anonymous?: undefined; 52 | } 53 | )[]; 54 | static createInterface(): UNIInterface; 55 | static connect(address: string, signerOrProvider: Signer | Provider): UNI; 56 | } 57 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export type { DAI } from './DAI'; 2 | export type { UNI } from './UNI'; 3 | export { DAI__factory } from './factories/DAI__factory'; 4 | export { UNI__factory } from './factories/UNI__factory'; 5 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/cjs/types/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | exports.UNI__factory = exports.DAI__factory = void 0; 4 | var DAI__factory_1 = require('./factories/DAI__factory'); 5 | Object.defineProperty(exports, 'DAI__factory', { 6 | enumerable: true, 7 | get: function () { 8 | return DAI__factory_1.DAI__factory; 9 | }, 10 | }); 11 | var UNI__factory_1 = require('./factories/UNI__factory'); 12 | Object.defineProperty(exports, 'UNI__factory', { 13 | enumerable: true, 14 | get: function () { 15 | return UNI__factory_1.UNI__factory; 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Signer } from 'ethers'; 2 | import * as types from './types'; 3 | export declare function getContract(address: string, abi: object, defaultSigner: Signer): any; 4 | export declare type MainnetSdk = ReturnType; 5 | export declare function getMainnetSdk(defaultSigner: Signer): { 6 | DAI: types.DAI; 7 | UNI: types.UNI; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/index.js: -------------------------------------------------------------------------------- 1 | import { Contract } from 'ethers'; 2 | import mainnetDAIAbi from '../../abis/mainnet/DAI.json'; 3 | import mainnetUNIAbi from '../../abis/mainnet/UNI.json'; 4 | export function getContract(address, abi, defaultSigner) { 5 | return new Contract(address, abi, defaultSigner); 6 | } 7 | export function getMainnetSdk(defaultSigner) { 8 | return { 9 | DAI: getContract('0x6b175474e89094c44da98b954eedeac495271d0f', mainnetDAIAbi, defaultSigner), 10 | UNI: getContract('0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', mainnetUNIAbi, defaultSigner), 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/DAI.js: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/UNI.js: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/common.d.ts: -------------------------------------------------------------------------------- 1 | import type { Listener } from '@ethersproject/providers'; 2 | import type { Event, EventFilter } from 'ethers'; 3 | export interface TypedEvent = any, TArgsObject = any> extends Event { 4 | args: TArgsArray & TArgsObject; 5 | } 6 | export interface TypedEventFilter<_TEvent extends TypedEvent> extends EventFilter {} 7 | export interface TypedListener { 8 | (...listenerArg: [...__TypechainArgsArray, TEvent]): void; 9 | } 10 | declare type __TypechainArgsArray = T extends TypedEvent ? U : never; 11 | export interface OnEvent { 12 | (eventFilter: TypedEventFilter, listener: TypedListener): TRes; 13 | (eventName: string, listener: Listener): TRes; 14 | } 15 | export declare type MinEthersFactory = { 16 | deploy(...a: ARGS[]): Promise; 17 | }; 18 | export declare type GetContractTypeFromFactory = F extends MinEthersFactory ? C : never; 19 | export declare type GetARGsTypeFromFactory = F extends MinEthersFactory ? Parameters : never; 20 | export {}; 21 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/common.js: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/factories/DAI__factory.d.ts: -------------------------------------------------------------------------------- 1 | import { Signer } from 'ethers'; 2 | import { Provider } from '@ethersproject/providers'; 3 | import type { DAI, DAIInterface } from '../DAI'; 4 | export declare class DAI__factory { 5 | static readonly abi: ( 6 | | { 7 | inputs: { 8 | internalType: string; 9 | name: string; 10 | type: string; 11 | }[]; 12 | payable: boolean; 13 | stateMutability: string; 14 | type: string; 15 | anonymous?: undefined; 16 | name?: undefined; 17 | constant?: undefined; 18 | outputs?: undefined; 19 | } 20 | | { 21 | anonymous: boolean; 22 | inputs: { 23 | indexed: boolean; 24 | internalType: string; 25 | name: string; 26 | type: string; 27 | }[]; 28 | name: string; 29 | type: string; 30 | payable?: undefined; 31 | stateMutability?: undefined; 32 | constant?: undefined; 33 | outputs?: undefined; 34 | } 35 | | { 36 | constant: boolean; 37 | inputs: { 38 | internalType: string; 39 | name: string; 40 | type: string; 41 | }[]; 42 | name: string; 43 | outputs: { 44 | internalType: string; 45 | name: string; 46 | type: string; 47 | }[]; 48 | payable: boolean; 49 | stateMutability: string; 50 | type: string; 51 | anonymous?: undefined; 52 | } 53 | )[]; 54 | static createInterface(): DAIInterface; 55 | static connect(address: string, signerOrProvider: Signer | Provider): DAI; 56 | } 57 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/factories/UNI__factory.d.ts: -------------------------------------------------------------------------------- 1 | import { Signer } from 'ethers'; 2 | import { Provider } from '@ethersproject/providers'; 3 | import type { UNI, UNIInterface } from '../UNI'; 4 | export declare class UNI__factory { 5 | static readonly abi: ( 6 | | { 7 | inputs: { 8 | internalType: string; 9 | name: string; 10 | type: string; 11 | }[]; 12 | payable: boolean; 13 | stateMutability: string; 14 | type: string; 15 | anonymous?: undefined; 16 | name?: undefined; 17 | constant?: undefined; 18 | outputs?: undefined; 19 | } 20 | | { 21 | anonymous: boolean; 22 | inputs: { 23 | indexed: boolean; 24 | internalType: string; 25 | name: string; 26 | type: string; 27 | }[]; 28 | name: string; 29 | type: string; 30 | payable?: undefined; 31 | stateMutability?: undefined; 32 | constant?: undefined; 33 | outputs?: undefined; 34 | } 35 | | { 36 | constant: boolean; 37 | inputs: { 38 | internalType: string; 39 | name: string; 40 | type: string; 41 | }[]; 42 | name: string; 43 | outputs: { 44 | internalType: string; 45 | name: string; 46 | type: string; 47 | }[]; 48 | payable: boolean; 49 | stateMutability: string; 50 | type: string; 51 | anonymous?: undefined; 52 | } 53 | )[]; 54 | static createInterface(): UNIInterface; 55 | static connect(address: string, signerOrProvider: Signer | Provider): UNI; 56 | } 57 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export type { DAI } from './DAI'; 2 | export type { UNI } from './UNI'; 3 | export { DAI__factory } from './factories/DAI__factory'; 4 | export { UNI__factory } from './factories/UNI__factory'; 5 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/esm/types/index.js: -------------------------------------------------------------------------------- 1 | export { DAI__factory } from './factories/DAI__factory'; 2 | export { UNI__factory } from './factories/UNI__factory'; 3 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/index.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require('./cjs'); 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './esm'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/index.mjs: -------------------------------------------------------------------------------- 1 | export * from './esm'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": ".dethcrypto/eth-sdk-client", 3 | "main": "index.cjs", 4 | "module": "index.mjs", 5 | "types": "index.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/external-contracts/types.d.ts: -------------------------------------------------------------------------------- 1 | export * from './esm/types'; 2 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/hardhat_contracts.basic1.json: -------------------------------------------------------------------------------- 1 | { 2 | "31337": [ 3 | { 4 | "name": "localhost", 5 | "chainId": "31337", 6 | "contracts": { 7 | "YourContract": { 8 | "address": "0x8464135c8F25Da09e49BC8782676a84730C318bC", 9 | "abi": [ 10 | { 11 | "inputs": [], 12 | "stateMutability": "nonpayable", 13 | "type": "constructor" 14 | }, 15 | { 16 | "anonymous": false, 17 | "inputs": [ 18 | { 19 | "indexed": false, 20 | "internalType": "address", 21 | "name": "sender", 22 | "type": "address" 23 | }, 24 | { 25 | "indexed": false, 26 | "internalType": "string", 27 | "name": "purpose", 28 | "type": "string" 29 | } 30 | ], 31 | "name": "SetPurpose", 32 | "type": "event" 33 | }, 34 | { 35 | "inputs": [], 36 | "name": "purpose", 37 | "outputs": [ 38 | { 39 | "internalType": "string", 40 | "name": "", 41 | "type": "string" 42 | } 43 | ], 44 | "stateMutability": "view", 45 | "type": "function" 46 | }, 47 | { 48 | "inputs": [ 49 | { 50 | "internalType": "string", 51 | "name": "newPurpose", 52 | "type": "string" 53 | } 54 | ], 55 | "name": "setPurpose", 56 | "outputs": [], 57 | "stateMutability": "nonpayable", 58 | "type": "function" 59 | } 60 | ] 61 | } 62 | } 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/index.ts: -------------------------------------------------------------------------------- 1 | import { ContractJSON } from 'ethereum-waffle/dist/esm/ContractJSON'; 2 | 3 | import * as basicERC20ContractJson from '../generated/artifacts/contracts/BasicERC20Contract.sol/BasicERC20Contract.json'; 4 | import * as yourContractJson from '../generated/artifacts/contracts/YourContract.sol/YourContract.json'; 5 | 6 | import * as hardhatJson from './hardhat_contracts.basic1.json'; 7 | 8 | import { TDeployedHardhatContractsJson } from '~~/models'; 9 | 10 | export const mockHardhatBasicJson: TDeployedHardhatContractsJson = hardhatJson; 11 | export const mockYourContractJson: ContractJSON = yourContractJson; 12 | export const mockBasicERC20ContractJson: ContractJSON = basicERC20ContractJson; 13 | 14 | export * as mockExternalContracts from './external-contracts/cjs/types'; 15 | export * from './externalContractsForUseContractLoader'; 16 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/__mocks__/setupMockContracts.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { deployContract } from 'ethereum-waffle'; 3 | import { Signer } from 'ethers'; 4 | import { mockYourContractJson, mockBasicERC20ContractJson } from 'test-files/__mocks__'; 5 | 6 | import { YourContract, BasicERC20Contract } from '../generated/contract-types'; 7 | 8 | import { TContractFunctionInfoUntyped } from '~~/models'; 9 | 10 | export const setupMockYourContract = async ( 11 | contractSigner: Signer 12 | ): Promise<[YourContract, TContractFunctionInfoUntyped]> => { 13 | const yourContract = (await deployContract(contractSigner, mockYourContractJson)) as YourContract; 14 | const yourContractFunctionInfo: TContractFunctionInfoUntyped = { 15 | contractName: 'YourContract', 16 | functionName: 'purpose', 17 | }; 18 | expect(yourContract).to.exist; 19 | expect(await yourContract.purpose()).to.equal('Building Unstoppable Apps!!!'); 20 | return [yourContract, yourContractFunctionInfo]; 21 | }; 22 | 23 | export const setupMockBasicERC20Contract = async ( 24 | contractSigner: Signer, 25 | initialNumberOfTokens?: number 26 | ): Promise => { 27 | const initialTotalSupply = initialNumberOfTokens || 1000; 28 | const basicERC20Contract = (await deployContract(contractSigner, mockBasicERC20ContractJson, [ 29 | initialTotalSupply, 30 | ])) as BasicERC20Contract; 31 | expect(basicERC20Contract).to.exist; 32 | expect(await basicERC20Contract.totalSupply()).to.equal(initialTotalSupply); 33 | return basicERC20Contract; 34 | }; 35 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/contracts/BasicERC20Contract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.8.0 <0.9.0; 2 | //SPDX-License-Identifier: MIT 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | // Example class - a mock class using delivering from ERC20 7 | contract BasicERC20Contract is ERC20 { 8 | constructor(uint256 initialBalance) ERC20("Basic", "BSC") { 9 | _mint(msg.sender, initialBalance); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/contracts/YourContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.8.0 <0.9.0; 2 | //SPDX-License-Identifier: MIT 3 | 4 | import 'hardhat/console.sol'; 5 | 6 | //import "@openzeppelin/contracts/access/Ownable.sol"; //https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol 7 | 8 | contract YourContract { 9 | string public purpose = 'Building Unstoppable Apps!!!'; 10 | 11 | // this is an error handler 12 | //error EmptyPurposeError(uint code, string message); 13 | 14 | constructor() { 15 | // what should we do on deploy? 16 | } 17 | 18 | // this is an event for the function below 19 | event SetPurpose(address sender, string purpose); 20 | 21 | function setPurpose(string memory newPurpose) public payable { 22 | // you can add error handling! 23 | 24 | // if(bytes(newPurpose).length == 0){ 25 | // revert EmptyPurposeError({ 26 | // code: 1, 27 | // message: "Purpose can not be empty" 28 | // }); 29 | // } 30 | 31 | purpose = newPurpose; 32 | console.log(msg.sender, 'set purpose to', purpose); 33 | emit SetPurpose(msg.sender, purpose); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/eth-hooks/test-files/deploy/00_deploy_your_contract.ts: -------------------------------------------------------------------------------- 1 | import { DeployFunction } from 'hardhat-deploy/types'; 2 | import { HardhatRuntimeEnvironment } from 'hardhat/types'; 3 | 4 | const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { 5 | const { getNamedAccounts, deployments } = hre; 6 | const { deploy } = deployments; 7 | const { deployer } = await getNamedAccounts(); 8 | await deploy('YourContract', { 9 | // Learn more about args here: https://www.npmjs.com/package/hardhat-deploy#deploymentsdeploy 10 | from: deployer, 11 | // args: ["Hello"], 12 | log: true, 13 | }); 14 | 15 | /* 16 | // Getting a previously deployed contract 17 | const YourContract = await ethers.getContract("YourContract", deployer); 18 | await YourContract.setPurpose("Hello"); 19 | 20 | //const yourContract = await ethers.getContractAt('YourContract', "0xaAC799eC2d00C013f1F11c37E654e59B0429DF6A") //<-- if you want to instantiate a version of a contract at a specific address! 21 | */ 22 | }; 23 | export default func; 24 | func.tags = ['YourContract']; 25 | 26 | /* 27 | Tenderly verification 28 | let verification = await tenderly.verify({ 29 | name: contractName, 30 | address: contractAddress, 31 | network: targetNetwork, 32 | }); 33 | */ 34 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/context/BlockNumberContext.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { useBlockNumberContext } from '~~/context'; 4 | import { hookTestWrapper } from '~~/helpers/test-utils'; 5 | import { defaultBlockWaitOptions } from '~~/helpers/test-utils/constants'; 6 | import { mineBlock } from '~~/helpers/test-utils/eth'; 7 | 8 | import 'test/helpers/chai-imports'; 9 | 10 | describe('BlockNumberContext', function () { 11 | describe('Give that context is initalized', function () { 12 | let initialBlockNumber = 0; 13 | 14 | before(async () => { 15 | const wrapper = await hookTestWrapper(() => useBlockNumberContext()); 16 | initialBlockNumber = await wrapper.mockProvider.getBlockNumber(); 17 | console.log('initial block number', initialBlockNumber); 18 | }); 19 | 20 | it('When the hook called without a new block arriving; then useBlockNumberContext gets the current blockNumber', async () => { 21 | const wrapper = await hookTestWrapper(() => useBlockNumberContext()); 22 | expect(initialBlockNumber).to.exist; 23 | expect(wrapper.result.current).to.equal(initialBlockNumber); 24 | }); 25 | 26 | it('When the a new block arrives; then useBlockNumberContext updates to the latest value', async () => { 27 | const wrapper = await hookTestWrapper(() => useBlockNumberContext()); 28 | expect(wrapper.result.all.length).equals(2); 29 | 30 | // mine a block 31 | await mineBlock(wrapper.mockProvider); 32 | await wrapper.waitForValueToChange(() => wrapper.result.current, defaultBlockWaitOptions); 33 | expect(wrapper.result.current).equal(initialBlockNumber + 1); 34 | expect(wrapper.result.all.length).equals(4); 35 | 36 | // mine another block 37 | await mineBlock(wrapper.mockProvider); 38 | await wrapper.waitForValueToChange(() => wrapper.result.current, defaultBlockWaitOptions); 39 | expect(wrapper.result.current).equal(initialBlockNumber + 2); 40 | 41 | expect(wrapper.result.all.length).equals(6); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/helpers/chai-imports.ts: -------------------------------------------------------------------------------- 1 | // import { smock } from '@defi-wonderland/smock'; 2 | import { should, use } from 'chai'; 3 | import { solidity } from 'ethereum-waffle'; 4 | import sinonChai from 'sinon-chai'; 5 | 6 | use(sinonChai); 7 | use(solidity); 8 | 9 | should(); // if you like should syntax 10 | // use(smock.matchers); 11 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/helpers/hardhat-imports.ts: -------------------------------------------------------------------------------- 1 | import 'tsconfig-paths/register'; 2 | import 'global-jsdom/register'; 3 | 4 | import '@typechain/hardhat'; 5 | import '@nomiclabs/hardhat-ethers'; 6 | import '@nomiclabs/hardhat-waffle'; 7 | import 'hardhat-deploy-ethers'; 8 | import 'hardhat-deploy'; 9 | 10 | // import 'solidity-coverage'; 11 | 12 | // import '@tenderly/hardhat-tenderly'; 13 | // import 'hardhat-watcher'; 14 | // import '@primitivefi/hardhat-dodoc'; 15 | // import 'hardhat-tracer'; 16 | // import 'hardhat-gas-reporter'; 17 | // import 'hardhat-contract-sizer'; 18 | // import '@openzeppelin/hardhat-upgrades'; 19 | // import '@nomiclabs/hardhat-solhint'; 20 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/helpers/mochaRootHooks.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * disable react 18 warnings until react testing hook library and react testing library are fixed 3 | */ 4 | export const mochaRootHook_disableReact18Warnings = { 5 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type 6 | beforeAll() { 7 | //* **Add This*** 8 | const error = console.error; 9 | console.error = (...args: any[]): void => { 10 | if (/Warning: ReactDOM.render is no longer supported in React 18./.test(args[0] as string)) { 11 | return; 12 | } else { 13 | error(args); 14 | } 15 | }; 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/useAreSignerEqual.test.ts: -------------------------------------------------------------------------------- 1 | import 'test/helpers/chai-imports'; 2 | import { expect } from 'chai'; 3 | 4 | import { useAreSignerEqual } from '~~'; 5 | import { defaultBlockWaitOptions } from '~~/helpers/test-utils/constants'; 6 | import { getTestSigners, hookTestWrapper } from '~~/helpers/test-utils/wrapper'; 7 | import { TEthersSigner } from '~~/models'; 8 | 9 | type InputType = { 10 | signer1: TEthersSigner | undefined; 11 | signer2: TEthersSigner | undefined; 12 | }; 13 | 14 | describe('useAreSignerEqual', () => { 15 | it('When signers are the same; then returns true', async () => { 16 | // ::Given:: 17 | const wrapper = await hookTestWrapper(({ signer1, signer2 }: InputType) => useAreSignerEqual(signer1, signer2)); 18 | const signer1 = (await getTestSigners(wrapper.mockProvider)).user1; 19 | 20 | // ::When:: 21 | wrapper.rerender({ signer1, signer2: signer1 }); 22 | await wrapper.waitForValueToChange(() => wrapper.result.current[0], defaultBlockWaitOptions); 23 | 24 | // ::Then:: 25 | expect(wrapper.result.current[0]).be.equal(true); 26 | }); 27 | 28 | it('When signers have different address; then returns false', async () => { 29 | // ::Given:: 30 | const wrapper = await hookTestWrapper(({ signer1, signer2 }: InputType) => useAreSignerEqual(signer1, signer2)); 31 | const signer1 = (await getTestSigners(wrapper.mockProvider)).user1; 32 | const signer2 = (await getTestSigners(wrapper.mockProvider)).user2; 33 | 34 | // ::When:: 35 | wrapper.rerender({ signer1, signer2 }); 36 | await wrapper.waitForValueToChange(() => wrapper.result.current[0], defaultBlockWaitOptions); 37 | 38 | // ::Then:: 39 | expect(wrapper.result.current[0]).be.equal(false); 40 | }); 41 | 42 | it('When signer1 is undefined (has no network); then returns undefined', async () => { 43 | // ::Given:: 44 | const wrapper = await hookTestWrapper(({ signer1, signer2 }: InputType) => useAreSignerEqual(signer1, signer2)); 45 | const signer1 = undefined; 46 | const signer2 = (await getTestSigners(wrapper.mockProvider)).user2; 47 | 48 | // ::When:: 49 | wrapper.rerender({ signer1, signer2 }); 50 | await wrapper.waitFor(() => wrapper.result.current[0], defaultBlockWaitOptions); 51 | 52 | // ::Then:: 53 | expect(wrapper.result.current[0]).be.equal(undefined); 54 | }); 55 | 56 | it('When signer2 is undefined; then returns false', async () => { 57 | // ::Given:: 58 | const wrapper = await hookTestWrapper(({ signer1, signer2 }: InputType) => useAreSignerEqual(signer1, signer2)); 59 | const signer1 = (await getTestSigners(wrapper.mockProvider)).user1; 60 | const signer2 = undefined; 61 | 62 | // ::When:: 63 | wrapper.rerender({ signer1, signer2 }); 64 | await wrapper.waitForValueToChange(() => wrapper.result.current[0], defaultBlockWaitOptions); 65 | 66 | // ::Then:: 67 | expect(wrapper.result.current[0]).be.equal(false); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/useBalance.test.ts: -------------------------------------------------------------------------------- 1 | import 'test/helpers/chai-imports'; 2 | import { expect } from 'chai'; 3 | 4 | import { hookTestWrapper } from '~~/helpers/test-utils'; 5 | import { defaultBlockWaitOptions } from '~~/helpers/test-utils/constants/testConstants'; 6 | import { expectValidWallets } from '~~/helpers/test-utils/functions'; 7 | import { fromEther } from '~~/helpers/test-utils/functions/conversions'; 8 | import { waitForExpect } from '~~/helpers/test-utils/functions/mochaHelpers'; 9 | import { useBalance } from '~~/hooks'; 10 | 11 | describe('useBalance', function () { 12 | it('When the hook is called; then it returns the initial balance', async () => { 13 | const wrapper = await hookTestWrapper((address: string | undefined) => useBalance(address ?? '')); 14 | const [wallet, secondWallet] = wrapper.mockProvider.getWallets(); 15 | wrapper.rerender(wallet.address); 16 | 17 | expectValidWallets(wallet, secondWallet); 18 | 19 | await wrapper.waitForNextUpdate(defaultBlockWaitOptions); 20 | const balance = await wallet.getBalance(); 21 | const [result] = wrapper.result.current; 22 | expect(result).be.equal(balance); 23 | }); 24 | 25 | it('When wallet balances changes; then the hook returns the new balance', async () => { 26 | const wrapper = await hookTestWrapper((address: string | undefined) => useBalance(address)); 27 | const [wallet, secondWallet] = wrapper.mockProvider.getWallets(); 28 | wrapper.rerender(wallet.address); 29 | 30 | expectValidWallets(wallet, secondWallet); 31 | 32 | const oldBalance = await wallet.getBalance(); 33 | const valueToSend = fromEther(1); 34 | // await expect( 35 | await wallet.sendTransaction({ 36 | to: secondWallet.address, 37 | value: valueToSend, 38 | }); 39 | // commented out since the waffle chai matcher doesn't work with london hardform. Merged PR to waffle, but they didn't release it 40 | 41 | // ).to.changeEtherBalances([wallet], [fromEther(-1)]); 42 | 43 | await waitForExpect(async () => { 44 | const newBalance = await wallet.getBalance(); 45 | const [result] = wrapper.result.current; 46 | expect(result).to.equal(newBalance); 47 | expect(result).not.to.equal(oldBalance); 48 | }, defaultBlockWaitOptions); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/useBlockNumber.test.ts: -------------------------------------------------------------------------------- 1 | import 'test/helpers/chai-imports'; 2 | import { expect } from 'chai'; 3 | 4 | import { hookTestWrapper } from '~~/helpers/test-utils'; 5 | import { defaultBlockWaitOptions } from '~~/helpers/test-utils/constants'; 6 | import { mineBlock } from '~~/helpers/test-utils/eth'; 7 | import { waitForExpect } from '~~/helpers/test-utils/functions/mochaHelpers'; 8 | import { currentTestBlockNumber, wrapperTestSetupHelper } from '~~/helpers/test-utils/wrapper/hardhatTestHelpers'; 9 | import { useBlockNumber } from '~~/hooks'; 10 | import { TEthersProvider } from '~~/models'; 11 | 12 | describe('useBlockNumber', function () { 13 | let provider: TEthersProvider; 14 | before(async () => { 15 | const wrapper = await wrapperTestSetupHelper(); 16 | provider = wrapper.mockProvider; 17 | }); 18 | 19 | let testStartBockNumber = 0; 20 | beforeEach(async () => { 21 | testStartBockNumber = await currentTestBlockNumber(); 22 | }); 23 | 24 | it('When the a new block arrives, useBlockNumberContext updates to the latest value', async () => { 25 | const wrapper = await hookTestWrapper(() => useBlockNumber(provider)); 26 | 27 | // mine a block 28 | await mineBlock(wrapper.mockProvider); 29 | await wrapper.waitForValueToChange(() => wrapper.result.current[0], defaultBlockWaitOptions); 30 | expect(await wrapper.mockProvider.getBlockNumber()).to.equal(testStartBockNumber + 1); 31 | const [result1] = wrapper.result.current; 32 | expect(result1).equal(testStartBockNumber + 1); 33 | 34 | // mine another block 35 | await mineBlock(wrapper.mockProvider); 36 | await waitForExpect(async () => { 37 | const [result2] = wrapper.result.current; 38 | expect(result2).equal(testStartBockNumber + 2); 39 | expect(await wrapper.mockProvider.getBlockNumber()).to.equal(testStartBockNumber + 2); 40 | }, defaultBlockWaitOptions); 41 | }); 42 | 43 | it('When the hook called without a new block arriving, useBlockNumber gets the current blockNumber', async () => { 44 | const wrapper = await hookTestWrapper(() => useBlockNumber(provider)); 45 | 46 | const blockNumber = await wrapper.mockProvider.getBlockNumber(); 47 | await wrapper.waitFor(() => wrapper.result.current[0] === blockNumber, defaultBlockWaitOptions); 48 | 49 | const [result] = wrapper.result.current; 50 | expect(result).to.equal(testStartBockNumber); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/useNonce.test.ts: -------------------------------------------------------------------------------- 1 | import 'test/helpers/chai-imports'; 2 | import { expect } from 'chai'; 3 | 4 | import { hookTestWrapper } from '~~/helpers/test-utils'; 5 | import { defaultBlockWaitOptions } from '~~/helpers/test-utils/constants'; 6 | import { expectValidWallets, fromEther } from '~~/helpers/test-utils/functions'; 7 | import { waitForExpect } from '~~/helpers/test-utils/functions/mochaHelpers'; 8 | import { useNonce } from '~~/hooks'; 9 | 10 | describe('useNonce', function () { 11 | it('When an wallet performs an action; then it increments the nonce of the address', async () => { 12 | const wrapper = await hookTestWrapper((address: string) => useNonce(address ?? '')); 13 | const [wallet, secondWallet] = wrapper.mockProvider.getWallets(); 14 | wrapper.rerender(wallet.address); 15 | 16 | let [oldNonce] = wrapper.result.current; 17 | await waitForExpect(() => { 18 | [oldNonce] = wrapper.result.current; 19 | expect(oldNonce).be.greaterThanOrEqual(0); 20 | }, defaultBlockWaitOptions); 21 | 22 | expectValidWallets(wallet, secondWallet); 23 | await wallet.sendTransaction({ 24 | to: secondWallet.address, 25 | from: wallet.address, 26 | value: fromEther(0.1), 27 | }); 28 | 29 | await waitForExpect(() => { 30 | const [newNonce] = wrapper.result.current; 31 | expect(newNonce).be.equal(oldNonce + 1); 32 | }, defaultBlockWaitOptions); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/useTimestamp.test.ts: -------------------------------------------------------------------------------- 1 | import 'test/helpers/chai-imports'; 2 | import { expect } from 'chai'; 3 | import { QueryStatus } from 'react-query'; 4 | 5 | import { hookTestWrapper, TTestHookResult } from '~~/helpers/test-utils'; 6 | import { defaultBlockWaitOptions } from '~~/helpers/test-utils/constants'; 7 | import { mineBlock } from '~~/helpers/test-utils/eth'; 8 | import { useTimestamp } from '~~/hooks'; 9 | 10 | const expectTimestamp = async ( 11 | wrapper: TTestHookResult<() => [timestamp: number, update: () => void, status: QueryStatus]> 12 | ): Promise => { 13 | const blockNumber = await wrapper.mockProvider.getBlockNumber(); 14 | expect(blockNumber).to.exist; 15 | const timestamp = (await wrapper.mockProvider.getBlock(blockNumber)).timestamp; 16 | expect(timestamp).be.greaterThan(0); 17 | return timestamp; 18 | }; 19 | 20 | describe('useTimestamp', function () { 21 | it('When the hook is called; then it returns the current block timestamp', async () => { 22 | const wrapper = await hookTestWrapper(() => useTimestamp()); 23 | console.log(wrapper.result.current[0]); 24 | await wrapper.waitFor( 25 | () => wrapper.result.current[0] !== undefined && wrapper.result.current[0] !== 0, 26 | defaultBlockWaitOptions 27 | ); 28 | 29 | const timestamp1 = await expectTimestamp(wrapper); 30 | const [result1] = wrapper.result.current; 31 | expect(result1).be.equal(timestamp1); 32 | 33 | // mine another block 34 | await mineBlock(wrapper.mockProvider); 35 | 36 | await wrapper.waitFor(() => { 37 | return wrapper.result.current[0] !== result1; 38 | }, defaultBlockWaitOptions); 39 | 40 | const timestamp2 = await expectTimestamp(wrapper); 41 | const [result2] = wrapper.result.current; 42 | expect(result2).be.equal(timestamp2); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /packages/eth-hooks/test/useUserAddress.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { Signer } from 'ethers'; 3 | 4 | import { hookTestWrapper } from '~~/helpers/test-utils'; 5 | import { defaultBlockWaitOptions } from '~~/helpers/test-utils/constants'; 6 | import { useSignerAddress } from '~~/hooks'; 7 | 8 | import 'test/helpers/chai-imports'; 9 | describe('useUserAddress', function () { 10 | it('When an signer is provider; the hook returns the correct address', async () => { 11 | const wrapper = await hookTestWrapper((signer: Signer) => useSignerAddress(signer)); 12 | const [wallet, secondWallet] = wrapper.mockProvider.getWallets(); 13 | 14 | wrapper.rerender(wallet); 15 | await wrapper.waitForValueToChange(() => wrapper.result.current[0], defaultBlockWaitOptions); 16 | const [result1] = wrapper.result.current; 17 | expect(wallet.address).be.equal(result1); 18 | expect(result1).to.be.properAddress; 19 | 20 | wrapper.rerender(secondWallet); 21 | await wrapper.waitForValueToChange(() => wrapper.result.current[0], defaultBlockWaitOptions); 22 | const [result2] = wrapper.result.current; 23 | expect(secondWallet.address).be.equal(result2); 24 | expect(result2).to.be.properAddress; 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/eth-hooks/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "module": "esNext", 6 | "outDir": "lib", 7 | "emitDeclarationOnly": true, 8 | "declaration": true, 9 | "declarationMap": true, 10 | "sourceMap": true, 11 | "inlineSources": true, 12 | "plugins": [ 13 | { "transform": "typescript-transform-paths" }, 14 | { "transform": "typescript-transform-paths", "afterDeclarations": true } 15 | ], 16 | "paths": { 17 | "~~": ["./src"], 18 | "~~/*": ["./src/*"] 19 | } 20 | }, 21 | "files": [], 22 | "include": ["./src/**/*"], 23 | "exclude": [ 24 | "docs/**/*", 25 | "**/typedoc/**", 26 | "test/**/*", 27 | "test-files/**/*", 28 | "node_modules", 29 | "**/node_modules", 30 | "**/node_modules/**", 31 | "./.yalc/**/*", 32 | "docusaurus/**/*" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /packages/eth-hooks/tsconfig.docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "rootDir": "./", 5 | "paths": { 6 | "~~": ["./src"], 7 | "~~/*": ["./src/*"] 8 | } 9 | }, 10 | "files": [], 11 | "include": ["./src/**/*"], 12 | "exclude": ["docs/**/*", "test/**/*", "node_modules", "**/node_modules/**", "./.yalc/**/*", "docusaurus/**/*"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/eth-hooks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esNext", 5 | "outDir": "lib", 6 | "lib": ["dom", "ESNext", "ES2017"], 7 | "sourceMap": true, 8 | "inlineSources": true, 9 | "jsx": "react-jsxdev", 10 | "allowJs": false, 11 | "declaration": true, 12 | "declarationDir": "lib", 13 | "declarationMap": true, 14 | "resolveJsonModule": true, 15 | "moduleResolution": "node", 16 | "forceConsistentCasingInFileNames": true, 17 | "allowSyntheticDefaultImports": true, 18 | "downlevelIteration": true, 19 | "esModuleInterop": true, 20 | "isolatedModules": true, 21 | "noImplicitAny": true, 22 | "skipLibCheck": true, 23 | "skipDefaultLibCheck": true, 24 | "strict": true, 25 | "rootDir": ".", 26 | "baseUrl": ".", 27 | "typeRoots": ["node_modules/@types"], 28 | "paths": { 29 | "~~": ["./src/"], 30 | "~~/*": ["./src/*"] 31 | } 32 | }, 33 | "exclude": [ 34 | "lib/**/*", 35 | "node_modules", 36 | "**/node_modules", 37 | "**/node_modules/**", 38 | ".husky", 39 | "./.yalc/**/*", 40 | "**/*.md", 41 | "docs/**/*", 42 | "website/**/*", 43 | "**/*.json" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /packages/eth-hooks/tsconfig.testing.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "esModuleInterop": true 6 | }, 7 | "files": ["hardhat.config.ts"], 8 | "ts-node": { 9 | "swc": true, 10 | 11 | "compilerOptions": { 12 | "module": "CommonJS" 13 | }, 14 | "moduleTypes": { 15 | "**/*": "cjs" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/eth-hooks/tsconfig.yalc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "emitDeclarationOnly": false, 5 | "declarationMap": false, 6 | "sourceMap": false, 7 | "inlineSources": false, 8 | "inlineSourceMap": false 9 | }, 10 | "files": [] 11 | } 12 | -------------------------------------------------------------------------------- /packages/eth-hooks/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entryPoints: [ 5 | './src/index.ts', 6 | './src/index.ts', 7 | './src/dapps.ts', 8 | './src/erc.ts', 9 | './src/context/index.ts', 10 | './src/functions/index.ts', 11 | './src/helpers/index.ts', 12 | './src/models/index.ts', 13 | './src/helpers/__global.ts', 14 | ], 15 | splitting: true, 16 | sourcemap: true, 17 | clean: true, 18 | outDir: 'lib', 19 | bundle: true, 20 | minifyWhitespace: false, 21 | minifySyntax: false, 22 | minifyIdentifiers: false, 23 | legacyOutput: false, 24 | platform: 'browser', 25 | target: ['node16', 'esnext'], 26 | format: ['cjs', 'esm'], 27 | inject: ['esbuild.shim.js'], 28 | skipNodeModulesBundle: true, 29 | tsconfig: 'tsconfig.build.json', 30 | treeshake: true, 31 | }); 32 | -------------------------------------------------------------------------------- /packages/wagmi-headless/.eslintignore: -------------------------------------------------------------------------------- 1 | # folders 2 | lib/ 3 | node_modules/**/* 4 | **/*.md 5 | docs/**/* 6 | website/**/* 7 | build/**/* -------------------------------------------------------------------------------- /packages/wagmi-headless/.gitignore: -------------------------------------------------------------------------------- 1 | # folders 2 | lib/ 3 | node_modules/ 4 | 5 | *.log 6 | *.tgz 7 | *.tsbuildinfo 8 | cache 9 | test/testresult.xml 10 | testresult.xml 11 | .yarn/install-state.gz 12 | test-files/__mocks__/generated 13 | .idea 14 | .DS_store 15 | eslint_report.json -------------------------------------------------------------------------------- /packages/wagmi-headless/.mocharc.js: -------------------------------------------------------------------------------- 1 | console.log('load .mocharc.js config'); 2 | 3 | module.exports = { 4 | require: ['ts-node/register', 'ts-node/register/files', 'tsconfig-paths/register', 'global-jsdom/register'], 5 | timeout: 30000, 6 | bail: false, 7 | allowUncaught: false, 8 | reporter: process.env.GITHUB_ACTIONS === 'true' ? 'mocha-junit-reporter' : 'spec', 9 | reporterOptions: { 10 | mochaFile: 'testresult.xml', 11 | }, 12 | extension: ['js', 'ts', 'tsx', 'jsx'], 13 | spec: ['test/**/*'], 14 | parallel: false, 15 | recursive: true, 16 | jobs: 1, 17 | }; -------------------------------------------------------------------------------- /packages/wagmi-headless/.npmignore: -------------------------------------------------------------------------------- 1 | #folders 2 | src 3 | 4 | #files 5 | .commitlintrc.js 6 | .eslintignore 7 | .eslintrc.js 8 | .gitignore 9 | .huskyrc.js 10 | .lintstagedrc.js 11 | .prettierrc 12 | tsconfig.json 13 | yarn.lock 14 | 15 | *.log 16 | *.tgz -------------------------------------------------------------------------------- /packages/wagmi-headless/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "printWidth": 120, 5 | "requirePragma": false, 6 | "singleQuote": true, 7 | "tabWidth": 2, 8 | "trailingComma": "es5", 9 | "endOfLine": "lf", 10 | "bracketSameLine": true 11 | } 12 | -------------------------------------------------------------------------------- /packages/wagmi-headless/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mochaExplorer.files": "test/**/*.{j,t}s", 3 | "mochaExplorer.parallel": true, 4 | "mochaExplorer.timeout": 20000, 5 | "mochaExplorer.configFile": "./mocharc.json", 6 | "mochaExplorer.esmLoader": false, 7 | "terminal.integrated.fontSize": 12, 8 | "editor.tabSize": 2, 9 | "mochaExplorer.optsFile": "", 10 | "search.useIgnoreFiles": true, 11 | "files.exclude": { 12 | "**/.git": true, 13 | "**/.svn": true, 14 | "**/.hg": true, 15 | "**/CVS": true, 16 | "**/.DS_Store": true, 17 | "**/Thumbs.db": true, 18 | "**/.cache": true, 19 | "**/.vs/": true, 20 | "**/*.cs": true, 21 | "**/*.orig": true, 22 | "**/bin/": true, 23 | "**/build/": true, 24 | "**/build/**/*": true, 25 | "**/debug/": true, 26 | "**/dist/": true, 27 | "**/obj": true, 28 | "lib": true 29 | }, 30 | "explorerExclude.backup": null, 31 | "exportall.config.relExclusion": ["/src/helpers/test-utils", "/src/helpers/typedoc", "/src/helpers/__global.ts"] 32 | } 33 | -------------------------------------------------------------------------------- /packages/wagmi-headless/README.md: -------------------------------------------------------------------------------- 1 | # 🖇 wagmi-headless Overview 2 | 3 | Commonly used Ethereum hooks to supercharge your web3 dev! 4 | 5 | Used by 🏭 [scaffold-eth-typescript](https://github.com/scaffold-eth/scaffold-eth-typescript), 🏗 [scaffold-eth](https://github.com/scaffold-eth/scaffold-eth) 6 | , [eth-components](https://github.com/scaffold-eth/eth-components) and many other web3 projects! 7 | 8 | Created by 🏰 [BuidlGuidl.eth](https://BuidlGuidl.com) 9 | 10 | ## Author 11 | 12 | # Documentation 13 | 14 | ## 📚 Check out the documentation at [Eth-hooks-documentation](https://scaffold-eth.github.io/eth-ui/) 15 | 16 | # Features 17 | 18 | ## Hooks! 19 | -------------------------------------------------------------------------------- /packages/wagmi-headless/esbuild.shim.js: -------------------------------------------------------------------------------- 1 | // shim.js 2 | import * as React from 'react'; 3 | export { React }; 4 | export { jsx as _jsx } from 'react/jsx-runtime'; -------------------------------------------------------------------------------- /packages/wagmi-headless/src/hooks/useEthBalance.tsx: -------------------------------------------------------------------------------- 1 | // import { useBalance } from 'eth-hooks'; 2 | import { BigNumber, utils } from 'ethers'; 3 | import { useState } from 'react'; 4 | 5 | export interface EthBalanceProps { 6 | address: string; 7 | price?: number; 8 | balance?: BigNumber; 9 | dollarMultiplier?: number; 10 | } 11 | 12 | export interface EthBalanceResult { 13 | balance: string; 14 | toggleMode: () => void; 15 | } 16 | 17 | export const useEthBalance = (props: EthBalanceProps): EthBalanceResult => { 18 | const [dollarMode, setDollarMode] = useState(true); 19 | // const [userBalance] = useBalance(props.address); 20 | // hack to get monorepo done 21 | const userBalance = [3]; 22 | 23 | let resolvedBalance = BigNumber.from(userBalance ?? 0); 24 | if (userBalance != null) { 25 | resolvedBalance = BigNumber.from(userBalance); 26 | } 27 | 28 | let floatBalance = parseFloat('0.00'); 29 | if (resolvedBalance) { 30 | const etherBalance = utils.formatEther(resolvedBalance); 31 | floatBalance = parseFloat(etherBalance); 32 | } 33 | 34 | let balance = floatBalance.toFixed(4); 35 | const price = props.price ?? props.dollarMultiplier; 36 | if (price && dollarMode) { 37 | balance = `$${(floatBalance * price).toFixed(2)}`; 38 | } 39 | 40 | const toggleMode = (): void => { 41 | setDollarMode(!dollarMode); 42 | }; 43 | 44 | return { 45 | balance, 46 | toggleMode, 47 | }; 48 | }; 49 | -------------------------------------------------------------------------------- /packages/wagmi-headless/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hooks/useEthBalance'; 2 | -------------------------------------------------------------------------------- /packages/wagmi-headless/test/eth-balance.test.ts: -------------------------------------------------------------------------------- 1 | import 'test/helpers/chai-imports'; 2 | import { expect } from 'chai'; 3 | 4 | describe('useEthBalance', function () { 5 | it('When a test is run mocha and chai work', () => { 6 | expect(true).be.equal(true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/wagmi-headless/test/helpers/chai-imports.ts: -------------------------------------------------------------------------------- 1 | import { should, use } from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | use(sinonChai); 5 | 6 | should(); // if you like should syntax 7 | -------------------------------------------------------------------------------- /packages/wagmi-headless/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "module": "esNext", 6 | "outDir": "lib", 7 | "esModuleInterop": true, 8 | "emitDeclarationOnly": true, 9 | "declaration": true, 10 | "declarationMap": true, 11 | "sourceMap": true, 12 | "inlineSources": true, 13 | "plugins": [ 14 | { "transform": "typescript-transform-paths" }, 15 | { "transform": "typescript-transform-paths", "afterDeclarations": true } 16 | ], 17 | "paths": { 18 | "~~": ["./src"], 19 | "~~/*": ["./src/*"] 20 | } 21 | }, 22 | "files": [], 23 | "include": ["./src/**/*"], 24 | "exclude": [ 25 | "docs/**/*", 26 | "**/typedoc/**", 27 | "test/**/*", 28 | "test-files/**/*", 29 | "node_modules", 30 | "**/node_modules", 31 | "**/node_modules/**", 32 | "./.yalc/**/*", 33 | "docusaurus/**/*" 34 | ] 35 | } -------------------------------------------------------------------------------- /packages/wagmi-headless/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esNext", 5 | "outDir": "lib", 6 | "lib": ["dom", "ESNext", "ES2017"], 7 | "sourceMap": true, 8 | "inlineSources": true, 9 | "jsx": "react-jsxdev", 10 | "allowJs": false, 11 | "declaration": true, 12 | "declarationDir": "lib", 13 | "declarationMap": true, 14 | "resolveJsonModule": true, 15 | "moduleResolution": "node", 16 | "forceConsistentCasingInFileNames": true, 17 | "allowSyntheticDefaultImports": true, 18 | "downlevelIteration": true, 19 | "esModuleInterop": true, 20 | "isolatedModules": true, 21 | "noImplicitAny": true, 22 | "skipLibCheck": true, 23 | "skipDefaultLibCheck": true, 24 | "strict": true, 25 | "rootDir": ".", 26 | "baseUrl": ".", 27 | "typeRoots": ["node_modules/@types"], 28 | "paths": { 29 | "~~": ["./src/"], 30 | "~~/*": ["./src/*"] 31 | } 32 | }, 33 | "include": ["src", "test", "tsup.config.ts"], 34 | "exclude": [ 35 | "lib/**/*", 36 | "node_modules", 37 | "**/node_modules", 38 | "**/node_modules/**", 39 | ".husky", 40 | "./.yalc/**/*", 41 | "**/*.md", 42 | "docs/**/*", 43 | "website/**/*", 44 | "**/*.json" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /packages/wagmi-headless/tsconfig.testing.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "types": ["mocha"] 7 | }, 8 | "files": ["hardhat.config.ts"], 9 | "ts-node": { 10 | "compilerOptions": { 11 | "module": "CommonJS" 12 | }, 13 | "moduleTypes": { 14 | "**/*": "cjs" 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /packages/wagmi-headless/tsconfig.yalc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "emitDeclarationOnly": false, 5 | "declarationMap": false, 6 | "sourceMap": false, 7 | "inlineSources": false, 8 | "inlineSourceMap": false 9 | }, 10 | "files": [] 11 | } -------------------------------------------------------------------------------- /packages/wagmi-headless/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entryPoints: [ 5 | './src/index.ts', 6 | './src/dapps.ts', 7 | './src/erc.ts', 8 | './src/context/index.ts', 9 | './src/functions/index.ts', 10 | './src/helpers/index.ts', 11 | './src/models/index.ts', 12 | './src/helpers/__global.ts', 13 | ], 14 | splitting: true, 15 | sourcemap: true, 16 | clean: true, 17 | outDir: 'lib', 18 | bundle: true, 19 | minifyWhitespace: false, 20 | minifySyntax: false, 21 | minifyIdentifiers: false, 22 | legacyOutput: false, 23 | platform: 'browser', 24 | target: ['node16', 'esnext'], 25 | format: ['cjs', 'esm'], 26 | inject: ['esbuild.shim.js'], 27 | skipNodeModulesBundle: true, 28 | tsconfig: 'tsconfig.build.json', 29 | treeshake: true, 30 | }); 31 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/.eslintignore: -------------------------------------------------------------------------------- 1 | # folders 2 | lib/ 3 | node_modules/**/* 4 | **/*.md 5 | docs/**/* 6 | website/**/* 7 | build/**/* -------------------------------------------------------------------------------- /packages/wagmi-tailwind/.gitignore: -------------------------------------------------------------------------------- 1 | # folders 2 | lib/ 3 | node_modules/ 4 | 5 | *.log 6 | *.tgz 7 | *.tsbuildinfo 8 | cache 9 | test/testresult.xml 10 | testresult.xml 11 | .yarn/install-state.gz 12 | test-files/__mocks__/generated 13 | .idea 14 | .DS_store 15 | eslint_report.json -------------------------------------------------------------------------------- /packages/wagmi-tailwind/.mocharc.js: -------------------------------------------------------------------------------- 1 | console.log('load .mocharc.js config'); 2 | 3 | module.exports = { 4 | require: ['ts-node/register', 'ts-node/register/files', 'tsconfig-paths/register', 'global-jsdom/register'], 5 | timeout: 30000, 6 | bail: false, 7 | allowUncaught: false, 8 | reporter: process.env.GITHUB_ACTIONS === 'true' ? 'mocha-junit-reporter' : 'spec', 9 | reporterOptions: { 10 | mochaFile: 'testresult.xml', 11 | }, 12 | extension: ['js', 'ts', 'tsx', 'jsx'], 13 | spec: ['test/**/*'], 14 | parallel: false, 15 | recursive: true, 16 | jobs: 1, 17 | }; -------------------------------------------------------------------------------- /packages/wagmi-tailwind/.npmignore: -------------------------------------------------------------------------------- 1 | #folders 2 | src 3 | 4 | #files 5 | .commitlintrc.js 6 | .eslintignore 7 | .eslintrc.js 8 | .gitignore 9 | .huskyrc.js 10 | .lintstagedrc.js 11 | .prettierrc 12 | tsconfig.json 13 | yarn.lock 14 | 15 | *.log 16 | *.tgz -------------------------------------------------------------------------------- /packages/wagmi-tailwind/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "printWidth": 120, 5 | "requirePragma": false, 6 | "singleQuote": true, 7 | "tabWidth": 2, 8 | "trailingComma": "es5", 9 | "endOfLine": "lf", 10 | "bracketSameLine": true 11 | } 12 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mochaExplorer.files": "test/**/*.{j,t}s", 3 | "mochaExplorer.parallel": true, 4 | "mochaExplorer.timeout": 20000, 5 | "mochaExplorer.configFile": "./mocharc.json", 6 | "mochaExplorer.esmLoader": false, 7 | "terminal.integrated.fontSize": 12, 8 | "editor.tabSize": 2, 9 | "mochaExplorer.optsFile": "", 10 | "search.useIgnoreFiles": true, 11 | "files.exclude": { 12 | "**/.git": true, 13 | "**/.svn": true, 14 | "**/.hg": true, 15 | "**/CVS": true, 16 | "**/.DS_Store": true, 17 | "**/Thumbs.db": true, 18 | "**/.cache": true, 19 | "**/.vs/": true, 20 | "**/*.cs": true, 21 | "**/*.orig": true, 22 | "**/bin/": true, 23 | "**/build/": true, 24 | "**/build/**/*": true, 25 | "**/debug/": true, 26 | "**/dist/": true, 27 | "**/obj": true, 28 | "lib": true 29 | }, 30 | "explorerExclude.backup": null, 31 | "exportall.config.relExclusion": ["/src/helpers/test-utils", "/src/helpers/typedoc", "/src/helpers/__global.ts"] 32 | } 33 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/README.md: -------------------------------------------------------------------------------- 1 | # 🖇 Eth-headless Overview 2 | 3 | Commonly used Ethereum hooks to supercharge your web3 dev! 4 | 5 | Used by 🏭 [scaffold-eth-typescript](https://github.com/scaffold-eth/scaffold-eth-typescript), 🏗 [scaffold-eth](https://github.com/scaffold-eth/scaffold-eth) 6 | , [eth-components](https://github.com/scaffold-eth/eth-components) and many other web3 projects! 7 | 8 | Created by 🏰 [BuidlGuidl.eth](https://BuidlGuidl.com) 9 | 10 | ## Author 11 | 12 | # Documentation 13 | 14 | ## 📚 Check out the documentation at [Eth-hooks-documentation](https://scaffold-eth.github.io/eth-ui/) 15 | 16 | # Features 17 | 18 | ## Hooks! 19 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/esbuild.shim.js: -------------------------------------------------------------------------------- 1 | // shim.js 2 | import * as React from 'react'; 3 | export { React }; 4 | export { jsx as _jsx } from 'react/jsx-runtime'; -------------------------------------------------------------------------------- /packages/wagmi-tailwind/src/components/Balance.tsx: -------------------------------------------------------------------------------- 1 | // import { useBalance } from 'eth-hooks'; 2 | import { FC } from 'react'; 3 | export const Balance: FC = () => { 4 | return <>; 5 | }; 6 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components/Balance'; 2 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/test/eth-balance.test.ts: -------------------------------------------------------------------------------- 1 | import 'test/helpers/chai-imports'; 2 | import { expect } from 'chai'; 3 | 4 | describe('useEthBalance', function () { 5 | it('When a test is run mocha and chai work', () => { 6 | expect(true).be.equal(true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/test/helpers/chai-imports.ts: -------------------------------------------------------------------------------- 1 | import { should, use } from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | use(sinonChai); 5 | 6 | should(); // if you like should syntax 7 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "module": "esNext", 6 | "outDir": "lib", 7 | "esModuleInterop": true, 8 | "emitDeclarationOnly": true, 9 | "declaration": true, 10 | "declarationMap": true, 11 | "sourceMap": true, 12 | "inlineSources": true, 13 | "plugins": [ 14 | { "transform": "typescript-transform-paths" }, 15 | { "transform": "typescript-transform-paths", "afterDeclarations": true } 16 | ], 17 | "paths": { 18 | "~~": ["./src"], 19 | "~~/*": ["./src/*"] 20 | } 21 | }, 22 | "files": [], 23 | "include": ["./src/**/*"], 24 | "exclude": [ 25 | "docs/**/*", 26 | "**/typedoc/**", 27 | "test/**/*", 28 | "test-files/**/*", 29 | "node_modules", 30 | "**/node_modules", 31 | "**/node_modules/**", 32 | "./.yalc/**/*", 33 | "docusaurus/**/*" 34 | ] 35 | } -------------------------------------------------------------------------------- /packages/wagmi-tailwind/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esNext", 5 | "outDir": "lib", 6 | "lib": ["dom", "ESNext", "ES2017"], 7 | "sourceMap": true, 8 | "inlineSources": true, 9 | "jsx": "react-jsxdev", 10 | "allowJs": false, 11 | "declaration": true, 12 | "declarationDir": "lib", 13 | "declarationMap": true, 14 | "resolveJsonModule": true, 15 | "moduleResolution": "node", 16 | "forceConsistentCasingInFileNames": true, 17 | "allowSyntheticDefaultImports": true, 18 | "downlevelIteration": true, 19 | "esModuleInterop": true, 20 | "isolatedModules": true, 21 | "noImplicitAny": true, 22 | "skipLibCheck": true, 23 | "skipDefaultLibCheck": true, 24 | "strict": true, 25 | "rootDir": ".", 26 | "baseUrl": ".", 27 | "typeRoots": ["node_modules/@types"], 28 | "paths": { 29 | "~~": ["./src/"], 30 | "~~/*": ["./src/*"] 31 | } 32 | }, 33 | "include": ["src", "test", "tsup.config.ts"], 34 | "exclude": [ 35 | "lib/**/*", 36 | "node_modules", 37 | "**/node_modules", 38 | "**/node_modules/**", 39 | ".husky", 40 | "./.yalc/**/*", 41 | "**/*.md", 42 | "docs/**/*", 43 | "website/**/*", 44 | "**/*.json" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /packages/wagmi-tailwind/tsconfig.testing.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "types": ["mocha"] 7 | }, 8 | "files": ["hardhat.config.ts"], 9 | "ts-node": { 10 | "compilerOptions": { 11 | "module": "CommonJS" 12 | }, 13 | "moduleTypes": { 14 | "**/*": "cjs" 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /packages/wagmi-tailwind/tsconfig.yalc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "emitDeclarationOnly": false, 5 | "declarationMap": false, 6 | "sourceMap": false, 7 | "inlineSources": false, 8 | "inlineSourceMap": false 9 | }, 10 | "files": [] 11 | } -------------------------------------------------------------------------------- /packages/wagmi-tailwind/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entryPoints: [ 5 | './src/index.ts', 6 | './src/dapps.ts', 7 | './src/erc.ts', 8 | './src/context/index.ts', 9 | './src/functions/index.ts', 10 | './src/helpers/index.ts', 11 | './src/models/index.ts', 12 | './src/helpers/__global.ts', 13 | ], 14 | splitting: true, 15 | sourcemap: true, 16 | clean: true, 17 | outDir: 'lib', 18 | bundle: true, 19 | minifyWhitespace: false, 20 | minifySyntax: false, 21 | minifyIdentifiers: false, 22 | legacyOutput: false, 23 | platform: 'browser', 24 | target: ['node16', 'esnext'], 25 | format: ['cjs', 'esm'], 26 | inject: ['esbuild.shim.js'], 27 | skipNodeModulesBundle: true, 28 | tsconfig: 'tsconfig.build.json', 29 | treeshake: true, 30 | }); 31 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "module": "esNext", 6 | "outDir": "lib", 7 | "emitDeclarationOnly": true, 8 | "declaration": true, 9 | "declarationMap": true, 10 | "sourceMap": true, 11 | "inlineSources": true, 12 | "plugins": [ 13 | { "transform": "typescript-transform-paths" }, 14 | { "transform": "typescript-transform-paths", "afterDeclarations": true } 15 | ], 16 | "paths": { 17 | "~~": ["./src"], 18 | "~~/*": ["./src/*"] 19 | } 20 | }, 21 | "files": [], 22 | "include": ["./src/**/*"], 23 | "exclude": [ 24 | "docs/**/*", 25 | "**/typedoc/**", 26 | "test/**/*", 27 | "test-files/**/*", 28 | "node_modules", 29 | "**/node_modules", 30 | "**/node_modules/**", 31 | "./.yalc/**/*", 32 | "docusaurus/**/*" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | // "inlineSources": true, 5 | "allowJs": false, 6 | "declarationMap": true, 7 | "declaration": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "module": "es2020", 11 | "moduleResolution": "Node", 12 | "incremental": true, 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true 16 | }, 17 | "include": ["packages/**/*.ts", "packages/**/*.tsx"], 18 | "exclude": [ 19 | "**/node_modules", 20 | "node_modules", 21 | ".husky", 22 | "**/*.css", 23 | "./tailwind.config.js", 24 | "**/.yalc/", 25 | "**/.yalc/**/*", 26 | ".yalc/**/*" 27 | ] 28 | } 29 | --------------------------------------------------------------------------------