All pages
Powered by GitBook
1 of 8

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Metamask

Wallets

This page describes how to programmatically interact with Harmony wallets like Metamask, OneWallet, and MathWallet.

Harmony Chrome Extension Wallet

This wallet has been deprecated

Please note this extension is end-of-life, receiving no further updates and is unsupported by Harmony Protocol. Please see our announcement here for more information.

WalletConnect

WalletConnect is standard api widely used by Trustwallet, Binance, Kava, and other apps to connect mobile wallet with Dapps.

Most existing connect works with a minor modification: allow support for Harmony ChainId. (example Viperswap PR)

Adding Harmony chains

export const walletconnect = new WalletConnectConnector({
  rpc: {
    1: NETWORK_URL,
    [ChainId.HARMONY_MAINNET]: 'https://api.s0.t.hmny.io/',
    [ChainId.HARMONY_TESTNET]: 'https://api.s0.b.hmny.io'
  },
  bridge: 'https://bridge.walletconnect.org',
  qrcode: true,
  supportedChainIds: [
    ChainId.HARMONY_MAINNET, // harmony
    ChainId.HARMONY_TESTNET // harmony testnet
  ]
})

Full dApp implementation

Follow the tutorials on https://docs.walletconnect.com for the respective platform.

For web, there is a reference implementation available at https://github.com/hashmesan/sef-walletconnect-example-dapp

Live demo: https://hashmesan.github.io/sef-walletconnect-example-dapp/

Current supported mobile wallets

  • - Harmony Defi Wallet

Add or Switch to Harmony chain on Metamask

This tutorial help developers to interact with Metamask installed on a user's device, to add (or switch to) the Harmony chain's network.

Harmony is a multi-sharded chain, currently with shard 0, 1, 2 and 3 running on Mainnet. To execute the code snippet below successfull, you can test on a device that has Metamask extension / add-on installed and visible to your app.

// Harmony's Shard ID {0..3}
const shardId = 0;

try {
  const walletAddEthereumChainRequest = await ethereum.request({
    method: 'wallet_addEthereumChain',
    params: [
      {
        chainId: '0x' + Number(1666600000 + shardId).toString(16),
        chainName: 'Harmony Mainnet Shard ' + shardId,
        nativeCurrency: { name: 'ONE', symbol: 'ONE', decimals: 18 },
        rpcUrls: ['https://' + (shardId === 0 ? 'api.harmony.one' : 'api.s' + shardId + '.t.hmny.io')],
        blockExplorerUrls: ['https://explorer.harmony.one/'],
      },
    ],
  });
} catch (error) {
  console.error(error);
}

Please note that window.web3 has been deprecated. Use window.ethereum instead. To migrate, use this guide from Metamask.

When this code snippet is executed, users will see message to approve adding or switching to correct Harmony chain.

You can see more information about Metamask documentation related to the Ethereum Provider API at

To see a full list of Chain IDs, please visit and search for Harmony

Sef Wallet
https://docs.metamask.io/guide/ethereum-provider.html
https://chainlist.org/
Metamask pops up asking to Switch Network to Harmony Mainnet Shard 0

Math Wallet

Installation

The completed code can be found here.

Download Math Wallet from here. Follow the instructions and setup your wallet.

For setting up your own project just replace the code in userWallet.js in One Wallet guide with the following:

const { fromBech32 } = require('@harmony-js/crypto');
const defaults = {};

export class MathWallet {

	constructor(network, client) {
		console.log(network, client);
		this.isMathWallet = false;
	}

	 signIn() {
		if (!this.mathwallet) {
			this.initWallet();
		}

		this.mathwallet.getAccount().then((account) => {
			this.sessionType = `mathwallet`;
			this.address = account.address;
			this.isAuthorized = true;
			return Promise.resolve();
		});
	}

	 initWallet() {
		this.isMathWallet = window.harmony && window.harmony.isMathWallet;
		this.mathwallet = window.harmony;
		this.signIn();
	}

	 async signTransaction(txn) {
		console.log(this.isMathWallet);
		if (this.sessionType === 'mathwallet' && this.isMathWallet) {
			console.log(this.mathwallet);
			return this.mathwallet.signTransaction(txn);
		}
	}

	 attachToContract(contract) {
		contract.wallet.createAccount();

		if (contract.wallet.defaultSigner === '') {
			contract.wallet.defaultSigner = this.address;
		}

		contract.wallet.signTransaction = async (tx) => {
			try {
				tx.from = this.address;
				const signTx = await this.signTransaction(tx);
				console.log(signTx);
				return signTx;
			} catch (err) {
				if (err.type === 'locked') {
					alert(
						'Your MathWallet is locked! Please unlock it and try again!'
					);
					return Promise.reject();
				} else if (err.type === 'networkError') {
					await this.signIn();
					this.initWallet();

					try {
						tx.from = this.address;
						const signTx = await this.signTransaction(tx);
						return signTx;
					} catch (error) {
						return Promise.reject(error);
					}
				} else {
					alert(
						'An error occurred - please check that you have MathWallet installed and that it is properly configured!'
					);
					return Promise.reject();
				}
			}
		};

		return contract;
	}
}

Using Metamask with Harmony Smart Contracts

For instructions on how to install and setup Metamask to work with Harmony blockchain please click here.

Project Setup

The completed code can be found here.

For reference, the smart contract code will look as follows:

For setting up your own project just replace the code in userWallet.js in One Wallet guide with the following.

This will connect your metamask.

Making Calls

Setup your contract object. Ininit.js:

Making a Payable Contract Call

Making a Read-Only Call

Congratulations

You just completed the tutorial to interact with smart contract using metamask and web3 on Harmony Network!

Interacting With Metamask

Interacting With MetaMask

For instructions on how to install and setup Metamask to work with Harmony blockchain please click here.

You can connect and sign transactions with Metamask using the Web3 library - which is fully compatible with the Harmony RPC API.

Do not forget that an important difference from One Wallet is that Metamsk sends transactions itself (extension side). While One Wallet only sign transaction, and then sending happens on browser side.

To use next example, you need to include the following libraries:

npm i '@metamask/detect-provider' --save
npm i web3 --save
npm i 'bn.js' --save

First step - you need to detect provider and connect to Metamask:

Next step - you can use connected provider with Web3 to sign and send transactions:

After executing this function, an interactive MetaMask window will open in which you can sign the transaction and change the gasPrice / gasLimit parameters - if it necessary.

Full code example will be here:

Also you can use all Provider API from official MetaMask and Web3 docs:

import detectEthereumProvider from '@metamask/detect-provider';

let ethAddress;
let isAuthorised = false;

const handleAccountsChanged = (accounts) => {
  if (accounts.length === 0) {
    console.error('Not found accounts');
  } else {
    ethAddress = accounts[0];
    
    console.log('Your address: ', ethAddress);
  }
}

export const signInMetamask = async () => {
    const provider = await detectEthereumProvider();

    // @ts-ignore
    if (provider !== window.ethereum) {
      console.error('Do you have multiple wallets installed?');
    }

    if (!provider) {
      console.error('Metamask not found');
      return;
    }

    // MetaMask events
    provider.on('accountsChanged', handleAccountsChanged);

    provider.on('disconnect', () => {
      console.log('disconnect');
      isAuthorised = false;
    });
    
    provider.on('chainIdChanged', chainId => console.log('chainIdChanged', chainId));

    provider
      .request({ method: 'eth_requestAccounts' })
      .then(async params => {
        handleAccountsChanged(params);
        isAuthorised = true;
      })
      .catch(err => {
        isAuthorised = false;
        
        if (err.code === 4001) {
          console.error('Please connect to MetaMask.');
        } else {
          console.error(err);
        }
      });
}
new Web3(window.web3.currentProvider) 

/* provider will use network RPC, wich was selected in MetaMask */
const accounts = await ethereum.enable();
    
/* Now any request to sign a transaction will be redirected to MetaMask */
https://github.com/harmony-one/ethhmy-bridge.frontend/blob/web3_hmy/src/pages/Examples/TransactionExample.tsx
https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents
pragma solidity >=0.4.22 <0.8.0;

contract Counter {
    uint256 private count = 0;
    uint256 moneyStored = 0;

    function incrementCounter() public {
        count += 1;
    }
    function decrementCounter() public {
        count -= 1;
    }

    function addMoney() payable public {
        moneyStored += msg.value;
    }

    function getCount() public view returns (uint256) {
        return count;
    }

    function getMoneyStored() public view returns (uint256){
        return moneyStored;
    }
}
import detectEthereumProvider from "@metamask/detect-provider";

let ethAddress;
let isAuthorised = false;

const handleAccountsChanged = (accounts) => {
  if (accounts.length === 0) {
    console.error("Not found accounts");
  } else {
    ethAddress = accounts[0];

    console.log("Your address: ", ethAddress);
  }
};

export const signInMetamask = async () => {
  const provider = await detectEthereumProvider();

  // @ts-ignore
  if (provider !== window.ethereum) {
    console.error("Do you have multiple wallets installed?");
  }

  if (!provider) {
    console.error("Metamask not found");
    return;
  }

  // MetaMask events
  provider.on("accountsChanged", handleAccountsChanged);

  provider.on("disconnect", () => {
    console.log("disconnect");
    isAuthorised = false;
  });

  provider.on("chainIdChanged", (chainId) =>
    console.log("chainIdChanged", chainId)
  );

  provider
    .request({ method: "eth_requestAccounts" })
    .then(async (params) => {
      handleAccountsChanged(params);
      isAuthorised = true;
    })
    .catch((err) => {
      isAuthorised = false;

      if (err.code === 4001) {
        console.error("Please connect to MetaMask.");
      } else {
        console.error(err);
      }
    });
};
import { signInMetamask } from "./walletStore";
import Web3 from "web3";
import fs from "fs";
let but = document.getElementById("inputtButton");

let web3;
let contract;

async function setupContract() {
  let contractFile = fs.readFileSync("../build/contracts/Counter.json", {
    encoding: "UTF-8",
  });
  contractFile = JSON.parse(contractFile);
  const abi = contractFile.abi;
  const contractAddress = contractFile.networks["2"].address;
  await signInMetamask();
  web3 = new Web3(window.web3.currentProvider);

  const contractInstance = new web3.eth.Contract(abi, contractAddress);
  contract = contractInstance;
}

async function demoInteraction() {
  await setupContract();
  const accounts = await web3.eth.getAccounts();
  console.log(accounts);
  const increment = await contract.methods
    .addMoney()
    .send({ from: accounts[0], value: web3.utils.wei });
  console.log(increment);
}
await setupContract();
const value = await contract.methods.getMoneyStored().call();
import Web3 from 'web3';
const BN = require('bn.js');

const sendTransaction = async () => {
    const web3 = new Web3(window.ethereum);
    
    const receiverAddress = '0x430506383F1Ac31F5FdF5b49ADb77faC604657B2';
    
    const gas = 6721900;
    const gasPrice = new BN(await web3.eth.getGasPrice()).mul(new BN(1));
    
    const result = await web3.eth
      .sendTransaction({
        from: account,
        to: receiverAddress,
        value: 1 * 1e18, // 1ONE
        gasPrice,
        gas,
      })
      .on('error', console.error);

    console.log(`Send tx: ${result.transactionHash} result: `, result.status);
}