Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This page describes how to programmatically interact with Harmony wallets like Metamask, OneWallet, and MathWallet.
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 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)
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
]
})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/
- Harmony Defi Wallet
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);
}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

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;
}
}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.
Setup your contract object. Ininit.js:
You just completed the tutorial to interact with smart contract using metamask and web3 on Harmony Network!
Interacting With MetaMask
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' --saveFirst 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 */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);
}