Harmony-React

A web3-react toolkit for Harmony wallets

Harmony-React adds support for using OneWallet and MathWallet together with web3-react.

Harmony-React is not a fork of web3-react, but rather built on top of web3-react to ensure that the library can be upgraded whenever web3-react gets updated.

Using Harmony-React

Installation

Add web3-react/core and the wallets you want to use (OneWallet, MathWallet or both) to package.json:

"@web3-react/core": "latest",
"@harmony-react/mathwallet-connector": "latest",
"@harmony-react/onewallet-connector": "latest",

Install using yarn install or npm install.

Usage

Import packages:

import { OneWalletConnector } from '@harmony-react/onewallet-connector'
import { MathWalletConnector } from '@harmony-react/mathwallet-connector'

Instantiate wallets:

const onewallet = new OneWalletConnector({ chainId: 1 }) // 1 = Mainnet, 2 = Testnet
const mathwallet = new MathWalletConnector({ chainId: 1 })  // 1 = Mainnet, 2 = Testnet

Store the wallet references in a store or a suitable structure, e.g:

    this.store = {
      ...
      web3context: null,
      connectorsByName: {
        OneWallet: onewallet,
        MathWallet: mathwallet,
      }
      ...
    }

For a more in-depth implementation example check here.

Create a wallet connection/unlock modal (or other suitable UI element):

import React from "react";
import {
  DialogContent,
  Dialog,
  Slide
} from '@material-ui/core';

import Unlock from './index.jsx';

export default function UnlockModal(props) {
  const { closeModal, modalOpen } = props
  const fullScreen = window.innerWidth < 450
  const Transition = React.forwardRef((props, ref) => <Slide direction="up" {...props} ref={ref} />)

  return (
    <Dialog open={ modalOpen } onClose={ closeModal } fullWidth={ true } maxWidth={ 'sm' } TransitionComponent={ Transition } fullScreen={ fullScreen }>
      <DialogContent>
        <Unlock closeModal={ closeModal } />
      </DialogContent>
    </Dialog>
  )
}

Implement the Unlock component:

...
import { Web3ReactProvider, useWeb3React } from '@web3-react/core'
...

export default function Unlock({ closeModal }) {
  ...
  
  return (
    <div className={ classes.root }>
      <div className={ classes.closeIcon } onClick={ closeModal }><CloseIcon /></div>
      <div className={ classes.contentContainer }>
        <Web3ReactProvider getLibrary={ getLibrary }>
          <WalletComponent closeModal={ closeModal } />
        </Web3ReactProvider>
      </div>
    </div>
  )
}

And finally, implement the WalletComponent:

export default function WalletComponent({ closeModal }) {
  const context = useWeb3React()
  const localContext = store.getStore('web3context')
  var localConnector = null;
  if (localContext) {
    localConnector = localContext.connector
  }
  
  const {
    connector,
    library,
    account,
    activate,
    deactivate,
    active,
    error
  } = context;

  var connectorsByName = store.getStore('connectorsByName')

  const [activatingConnector, setActivatingConnector] = React.useState()
  useEffect(() => {
    if (activatingConnector && activatingConnector === connector) {
      setActivatingConnector(undefined);
    }
  }, [activatingConnector, connector]);

  useEffect(() => {
    if (account && active && library) {
      store.setStore({ account: { address: account }, web3context: context })
      emitter.emit(CONNECTION_CONNECTED)
    }
  }, [account, active, closeModal, context, library]);

  const [hoveredConnectorButtons, setHoveredConnectorButtons] = React.useState(new Map());
  const updateHoveredConnectorButtons = (k,v) => {
    setHoveredConnectorButtons(new Map(hoveredConnectorButtons.set(k,v)));
  }

  // useEffect(() => {
  //   if (storeContext && storeContext.active && !active) {
  //     console.log("we are deactive: "+storeContext.account)
  //     store.setStore({ account: {}, web3context: null })
  //   }
  // }, [active, storeContext]);

  // handle logic to eagerly connect to the injected ethereum provider, if it exists and has granted access already
  // const triedEager = useEagerConnect();

  // handle logic to connect in reaction to certain events on the injected ethereum provider, if it exists
  // useInactiveListener(!triedEager || !!activatingConnector);
  const width = window.innerWidth

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: (width > 650 ? 'space-between' : 'center'), alignItems: 'center' }}>
      {Object.keys(connectorsByName).map(name => {
        const currentConnector = connectorsByName[name];
        const activating = currentConnector === activatingConnector;
        const connected = (currentConnector === connector||currentConnector === localConnector);
        const disabled =
           !!activatingConnector || !!error;

        var url;
        var display = (hovered && connected) ? 'Disconnect' : name;
        if (name === 'OneWallet') {
          url = HarmonyLogo
        } else if (name === 'MathWallet') {
          url = MathWalletLogo
        }

        return (
          // UI to generate list of wallets
        )
      }) }

      // UI to disconnect active wallet
  )
}

For full reference implementations of Store, UnlockModal, Unlock, and WalletComponent:

Last updated