Coder Social home page Coder Social logo

kesne / ethereal-react Goto Github PK

View Code? Open in Web Editor NEW
129.0 5.0 4.0 1.68 MB

A suspense-compatible React library for Ethereum development

Home Page: https://kesne.github.io/ethereal-react/

License: MIT License

TypeScript 91.84% JavaScript 1.94% CSS 0.44% Solidity 5.78%
react hooks react-hooks reactjs ethereum eth dapps

ethereal-react's Introduction

ethereal-react

A collection of React hooks and components, making it easy to develop frontends for Ethereum dApps.

Features:

  • Powered by ethers.
  • Works with React 17+, and compatible with upcoming React 18 features. Powered by Suspense, Error Boundaries, and concurrent rendering.
  • Built-in support for connecting to wallets with Web3Modal.
  • Supports TypeScript out of the box, including fully-typed contracts with TypeChain.
  • Small bundle size, and tree-shakable module. Currently ~2.5 kB gzipped for all features.

Getting Started

Read the documentation site for details about how to integrate ethereal-react in your project.

ethereal-react's People

Contributors

github-actions[bot] avatar holic avatar kesne avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ethereal-react's Issues

Add NFT utilities

It's common to work with ERC721 tokens and want to do things with them, like display them! Right now, this isn't super easy, because you need to do something roughly as follows:

  • Get the token ID (could involve knowing it ahead of time, or having to iterate through tokenOfOwnerByIndex)
  • Call tokenURI for the token ID.
  • Given the URI, determine how to load it (data: urls, IPFS, network request).
  • Parse response as JSON.

It would be way more ideal to have hooks that could do some of this for us:

  • Automatic token ID retrieval.
  • Automatic tokenURI resource loading.

Figure out value nullability

Right now, most APIs don't ever return null, and instead throw when they're not able to load data. I think this is not super ideal in all cases, and in some cases we want to be able to return null values from this instead of depending on an error boundary.

Look into multi-provider setups

We don't always want just one provider, we often will have a read-only provider (some JSON-RPC provider), and then a wallet-connected write provider (which can be optional).

I think we have a couple options here:

  1. Accept a provider as an argument in most hooks.
  2. Make users create a context sub-tree that hooks pull context from.
  3. Add a app-level provider with named providers, and hooks can define the name of the provider they'd like to use.

Simplify wallet connection flow

Right now, managing the wallet connection flow requires a decent amount of user code. I think we can simplify this with a simple component:

import { ConnectedToWallet, useConnectToWallet } from 'ethical-react';

function ConnectButton() {
  const connect = useConnectToWallet();
  return <button onClick={connect}>Connect</button>;
}

function App() {
  return <ConnectedToWallet fallback={<ConnectButton />}>
    <div>You are connected, the provider is safe to use here.</div>
  </ConnectedToWallet>;
}

Cache rework

Right now the cache is global, which works well, and even works for when providers change. However, this doesn't make a lot of sense long-term, because it causes unbounded cache growth, and resetting the provider doesn't actually free any memory.

I think there's a couple ways to solve this:

  • Cache object is provided by the provider itself. This should help clean up memory when providers are reset / removed.
  • Cache is a user-configurable LRU cache, with the ability to explicitly retain data that is actively being used.
  • Hooks cause data being used to be explicitly retained (need to figure out how this works with suspense and concurrent).

Use WalletProvider without fallback

Hey!! Awesome library. I was thinking of doing something like this but looks like I will be using this library.

I wanted to display my webpage without needed to connect to wallet and it seems that I am unable to use WalletProvider without a fallback.

I tried to use my webpage router as a fallback but then I cannot find a hook that tells me if the wallet is connected or not which I could use to render the connect wallet button.

Remove useOnBlock

This hook doesn't really accomplish anything that you can't already accomplish with other hooks, and has some weird side effects like logistics of cleanup that don't have great patterns. Replacement:

function Component() {
  const block = useBlock();
  useEffect(() => {
    // block update logic here
 }, [block]);
}

Migrate to use-asset

Right now we use jotai because it had built-in suspense support. This works, but it means we'll need to do a decent amount of work when the actual native suspense cache is introduced.

Instead, we should migrate to use-asset, which has a much clearer path forward with the built-in suspense cache.

https://github.com/pmndrs/use-asset

Docs Restructure

  • Introduction
  • Installation
  • Getting Started
  • Guides (Today's Getting Started)
  • Hooks & Components
  • Advanced

Add useTransaction hook

This is required to implement #46. Should take in an ID and then load up a transaction based on that. Should be composable with useWaitForTransaction.

Example should use hardhat

Right now the example runs on the test net, and depends on known deployed contract addresses. Instead, we should just run a hardhat node and point it to that by default.

Handle Wait for transaction when user gets disconnected

I was looking at ways to handle situations where we want to display a loader to the user if their transactions is currently ongoing.
we can use useWaitForTransaction for that. However, how do we handle the case, if the user refreshes the page?

Ideally, I want to be able to fetch user's pending transactions and display a UI suitable to my needs.

What's your thought on this?

Potential Future API design

The current API design is heavily hook-based, which makes sense given some of our current constraints and design inspiration. However, as we continue to evolve the API and lean more and more into the suspense- and concurrent- based API patterns, we can simplify the API design so that it does not depend as heavily on hooks.

One of the benefits of this API design is that all of the non-hook APIs can be called conditionally, instead of needing to be called unconditionally to follow the rules of hooks.

A note on providers

The core of providers shouldn't need any work, as they are the most foundational piece of the library, and must exist in react context.

  • useLogout - This API is probably fine, as it just returns a method that uses a value read out of the context.
  • useWeb3Modal - This is only for advanced use-cases, and just reads a value out of context.
  • WalletProvider - This initializes some values into a context, and renders a Provider.
  • Provider - This just provides values into context.
  • useProvider - This just reads values out of the context.

Thick Providers

I still need to write about this in more depth, but the TL;DR is that we'll have a new provider class, which has the following:

  • Built-in cache response.
  • Methods on the provider that trigger suspsense.
const provider = useProvider();
const address = provider.getUserAddress();
const balance = provider.getBalance(address);

We probably should figure out a new name for provider with this though.

Downsides:

  • Always requires a call to get the provider.
  • Lack of hooks means we can't effectively retain + LRU cache responses, potentially infinite cache growth.

Use built-in suspense cache

Once it is released, I'll refactor this to use the built-in suspense cache: reactwg/react-18#25

For the cache, I'll probably do some sort of nested cache structure, where the top-level cache key is the provider itself, and then under that we can construct whatever cache keys we want. I think it'd make sense to eventually do some sort of cache eviction when an item is no longer retained (similar to how Relay does it), as otherwise we'll have infinite cache growth.

The Provider component will also likely be wrapped in a Cache, as all components underneath should share a unique cache. One implication is that nested providers may have slightly odd caching behavior, but I think the toplevel cache key being the provider will (mostly) solve that.

Ship native ESM

We can't until React 18 adds the export field, but once it does, we should ship native ESM by adding this to the package.json:

"type": "module",
"exports": "./dist/index.modern.js",

Add useBlockOnce

This is a variant of useBlock that only fetches it once, and does not subscribe to new blocks.

Figure out how to reload data.

Eventually, it's feasable that people would want to refetch previously-cached data. I think there's a few ways that would be good to tackle this:

  • Use the upcoming useCacheRefresh to invalidate the cache. This depends on #8, and potentially requires over-fetching, but it probably would solve our use-cases. We can also integrate it to contract writes so that we also initiate contract reads after writing.
  • Move all async reads to a tuple, with a refetch function. The refetch function would effectively do what the realtime block updates do today. Has implications for transactions, and also API ergonomics

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.