DevPost: How to Integrate HashPack & HashConnect on a React/Recoil dApp
About HashPack & HashConnect
Here at hashport, we have added HashPack and HashConnect to our collection of wallets (alongside MetaMask and Venly). During this process, we ran into some challenges while integrating HashPack on hashport mainly deriving from our previous acclimation to the Ethereum ecosystem. Despite its robust community and documentation, as developers, we believe having many educational resources is good for everyone– especially for early, exciting, and unique technologies like HashPack and hashport!
To this end, we assembled this guide and developer post-mortem to help you along with your own integrations and hope we can provide some value to the ever-growing web3 developer community.
HashPack, under development since 2021, is one of the most exciting projects in the Hedera space. An analogue to MetaMask and, similarly, a browser extension, HashPack represents a new capability for Hedera application developers to develop client-side decentralised applications while effectively abstracting some of the complexities around Hedera accounts.
A companion technology, HashConnect is a middleware module that facilitates communication and connection objects between your application and HashPack. Rather than being injected from the wallet itself, it allows HashPack to eject into a popup window allowing for some more streamlined interactions as well as avoiding some of the irksome loss-of-work accidental window closings from more traditional browser extensions. This, of course, leads to some idiosyncrasies in implementation which we are addressing today.
Going forward, we will try to add updates and any version changes we run into as we improve our own integration on hashport.
Since HashConnect is the provider library that our components will implement, we will be focusing on this aspect of the stack. In order to test, talk to, and interact with these components, you will indeed need to install the HashPack application or extension. More info on that can be found here.
A Quick Note on React/Recoil
In order to keep the scope of this article focused (despite our love of chattering into the abyss about React and state managers and just how cool useEffect is) we will be skipping any installation and set up steps for both React and Recoil. In order to get the most out of this post, we highly recommend having the following skills:
- A strong understanding of React functional components and hooks
- A moderate understanding of Recoil
- A functional understanding of NPM
Setting Up HashConnect & HashPack
We will be following many of the core steps in the HashConnect tutorial. We highly recommend using this resource for your first steps since we will be plunging into the component and Recoil level of the app Lickety Split. For anyone who wants to jump the line or has already messed with the beginning documentation, we give a quick outline of this process here since some of these objects are used later.
Installing HashConnect through NPM is as easy as:
npm i hashconnect — save
Importing the library and instantiating a HashConnect object is pretty straightforward as well:
import { HashConnect } from ‘hashconnect’;//… More ImportsLet hashconnect = new HashConnect();
If it is the first time you are connecting, you need to set up a metadata object to feed to the HashConnect unit. This metadata allows the app to get basic information to the HashPack application and adds a level of polish for your users (if you are on client side). The url of the app is retrieved by HashPack automatically. Next, you will receive a private key in your dApp from HashPack. This flow can be found below (again, sourced from HashConnect docs).
For the rest of this, we will be showing some basics on how to set up your Recoil atoms to handle HashConnect & HashPack states followed by an example implementation of HashConnect in React. Finally, we will add in some various tips and observations that the hashport team has assembled to help you with your own integration.
Connecting HashPack to Recoil
If you are an AngularJS developer (AngularJS rocks!), HashPack (the company) has provided an excellent example of setting up HashConnect on that framework here.
If you have not used Recoil before, check out the docs and installation details found here. Recoil is a state management library similar to Redux that has out-of-the-box hooks and is built from the ground up to run with React.
- Set up Types.
You can find an assemblage of all the HashConnect types and interfaces here.
- Create HashConnect state handling Atom.
Creating your React Component Context
React Contexts are a handy way to allow data and functionality to pass into child components easily without having to create a long chain of props. We recommend injecting the functions you need at a top-level parent component like so:
<HashConnectProviderdebugnetwork={appConfig.isProdEnv() || appConfig.isTestEnv() ? `mainnet` : `testnet`}hashConnect={hashConnect}><HederaClientContextProvider><App /></HashConnectProvider>
The entire HashConnect context can be found here.
As you can see, this component returns an API object giving access to functions and data that help to legislate the lifecycle and functionality of your HashConnect wallet. This pattern allows you to then implement as you see fit each function inside component hooks. Likewise, if you have further functionality you want to draw out from any additional functions in the HashConnect library, you can implement them in the context while having a single place in the event of library changes or further desired functionality.
Rather than going through every component and hook where we use the Context, we will be just highlighting a few pernickety bits from the larger implementation remarked on above. At the end, we will provide a code snippet of the entire component that we implement on hashport rather than walking through the entire process since every app is a little different. If you have additional questions, please feel free to leave a comment and we will attempt to answer and revise.
On Listeners
Similar to MetaMask, HashConnect includes out-of-the-box, a set of listeners which can be used to call functions upon certain user actions or events coming from the HashPack extension (Remember, HashConnect is the Web3.js to HashPack’s MetaMask). We chose to instantiate these listeners in the useEffect area of the context provider wrapping the App component. By placing them top level we ensure the listeners are only ever engaged once.
Here, you can see as well that we implemented the callback functions for the listeners as methods within the component. These can also be exposed in the context API if desired if you want custom behaviours in other components (not recommended but hey who knows?).
Finally, note that unsetting HashPack connection on disconnectSync HashPack in useEffect will assist with handling rejected transactions. This actually leads us into our next bit: HashConnect’s relationship with the Hashgraph SDK.
On HashConnect and Hashgraph SDK
For much of our Hedera Hashgraph functionality, we utilized the Javascript implementation of the Hashgraph SDK. For Hedera SDK actions we wrote a set of functions for crafting raw transactions from the SDK which can be found here:
We then use the SDK signing logic to craft a raw transaction and sign it with the HashConnect Context API we provided above. In our case, we support multiple wallets so it is nested in a switch/case block:
The main reason for segregating our SDK and HashConnect logic into a handler/component pattern is to ensure that any changes we make to the SDK-level logic have a clean division from its implementation in the signing logic. Likewise, this also allows us to elegantly implement more complex logic later on from the SDK (e.g. Staking and Smart Contract calls) while keeping everything tied together just at the transactionary level (very similar to MetaMask and other extension client-side wallets).
hashport Team Tips
After many hours of experimentation with setup and configuration, we realised we basically needed to follow the tutorial to the “T” and then make adjustments based on our architecture/context/hooks using the events.
There’s a technical limitation around requests requiring a transaction fee on the Hedera/HashPack side that makes it hard to implement smoothly.
The providers and signers work fine, just need to ensure the Hedera SDK and HashConnect versions match up as much as possible.
When token associations have to be done in HashPack, there’s a technical limitation around requests requiring a transaction fee on the Hedera/HashPack side that makes it hard to implement smoothly so we recommend until this is ironed out, associations should be done separately to make dev lives easier; using the public API or using account balances is a better option.
Setting your listeners as an effect in whatever provider you create is extremely useful/important for debugging, since that’s how the app and the HashPack extension communicate with each other.
About hashport
hashport is the enterprise-grade public utility that facilitates the movement of digital assets between distributed networks, extending their functionality in a quick, secure, and cost-effective way. In order to remain platform-neutral, hashport functions without the use of a proprietary token. The network is built on a robust and performant architecture, secured and operated by a group of industry-leading validator partners from around the world. hashport has passed a rigorous security audit and follows industry best practices; regularly performing comprehensive network tests to ensure the integrity of the network.
Website | Twitter | Reddit | Telegram | LinkedIn | YouTube | GitHub
Disclaimer: The information provided on hashport’s website does not constitute investment advice, financial advice, trading advice, or any other sort of advice. You should not treat any site content as advice.