UNPKG

@foreverrbum/ethsign

Version:

This package will allow you to electronically sign documents within your application

258 lines (237 loc) 8.52 kB
import { ethers } from 'ethers'; import Fortmatic from 'fortmatic'; import Torus from "@toruslabs/torus-embed"; import {getChain, getFortmaticChainOptions, getTorusChainOptions, getTorusChainSwitchOptions, isTestnet} from '../chains' import Ethsign from '../../artifacts/EthSign.json'; import { Biconomy } from '@biconomy/mexa'; import * as Sentry from '@sentry/react'; const fortmatic_key = 'pk_live_6D2FFF6E41301BF0'; const fortmatic_test_key = 'pk_test_F4BDDED1F885923E'; export const updateNetwork = async (provider, handleNetwork) => { try { await provider.getNetwork().then((network)=>{ const chain = getChain(network.chainId); handleNetwork(chain); }) } catch(err) { handleNetwork(null); return; } } export const initializeProvider = async (handleProvider, handleNetwork, handleWalletName) => { const name = getWallet(); if (name){ window.ethereum.request({ method: 'eth_requestAccounts' }).then(async()=>{ const provider = new ethers.providers.Web3Provider(window.ethereum) handleWalletName(name) handleProvider(provider) await updateNetwork(provider, handleNetwork); }) } } export const getWallet = () => { if (typeof window !== "undefined" && typeof window.ethereum !== "undefined" ) { if (window.ethereum.isMetaMask){ return 'Metamask' } if (window.ethereum.isTorus) { return 'Torus' } if (window.ethereum.isImToken) { return 'imToken' } } return null } export const renderProviderText = (account) => { if(account && account.address) { const providerTextList = { Metamask: 'Add to Metamask', imToken: 'Add to imToken', Wallet: 'Add to Wallet' } return providerTextList[getProvider()] } else { return 'Connect wallet' } } const toHex = (num) => { return '0x'+num.toString(16) } export const connectNetwork = async (chain, provider, handleProvider, handleContract, handleNetwork, walletName, handleFm, torus, handleTorus, finishedCallback) => { let ethAccount = null; try { ethAccount = await provider.getSigner().getAddress(); } catch (err) { console.log(err); return; } if(walletName === 'Fortmatic') { let fm = null; if(chain.chainId == 1) { fm = new Fortmatic(fortmatic_key); } else { fm = new Fortmatic(isTestnet(chain.chainId) ? fortmatic_test_key : fortmatic_key, getFortmaticChainOptions(chain.chainId)) } let provider = new ethers.providers.Web3Provider(fm.getProvider()); const networkId = (await provider.getNetwork()).chainId; const deployedNetwork = Ethsign.networks[networkId]; const contract = new ethers.Contract(deployedNetwork.address, Ethsign.abi, provider); if (handleFm) { handleFm(fm) } if(handleProvider) { handleProvider(provider); } if(handleContract) { handleContract(contract); } if(handleNetwork) { handleNetwork(chain); } if(finishedCallback) { finishedCallback(true); } return chain; } else if(walletName === 'Torus') { if(!torus) { torus = new Torus(); await torus.init(getTorusChainOptions(chain.chainId)); await torus.login(); } else { await torus.setProvider(getTorusChainSwitchOptions(chain.chainId)); } let provider = new ethers.providers.Web3Provider(torus.provider); const networkId = (await provider.getNetwork()).chainId; const deployedNetwork = Ethsign.networks[networkId]; const contract = new ethers.Contract(deployedNetwork.address, Ethsign.abi, provider); if (handleTorus) { handleTorus(torus) } if(handleProvider) { handleProvider(provider); } if(handleNetwork) { handleNetwork(chain); } if(handleContract) { handleContract(contract); } if(finishedCallback) { finishedCallback(true); } return chain; } else { const params = { chainId: toHex(chain.chainId), // A 0x-prefixed hexadecimal string chainName: chain.name, nativeCurrency: { name: chain.nativeCurrency.name, symbol: chain.nativeCurrency.symbol, // 2-6 characters long decimals: chain.nativeCurrency.decimals, }, rpcUrls: chain.rpc, blockExplorerUrls: [ ((chain.explorers && chain.explorers.length > 0 && chain.explorers[0].url) ? chain.explorers[0].url : chain.infoURL) ] } try { let res = await window.ethereum.request({ method: 'wallet_switchEthereumChain', params: [{chainId: params.chainId}], }); connectNetworkRequestResult(chain, handleProvider, handleContract, handleNetwork, finishedCallback); } catch (err) { // This error code indicates that the chain has not been added to MetaMask. if(err.code === 4902) { try { let res = window.ethereum.request({ method: 'wallet_addEthereumChain', params: [params, ethAccount], }); connectNetworkRequestResult(chain, handleProvider, handleContract, handleNetwork, finishedCallback); } catch(error) { console.log(error) if(finishedCallback) { finishedCallback(true); } Sentry.captureException(error); return error; } } else { // this is some other network switch error console.log(err) if(finishedCallback) { finishedCallback(true); } Sentry.captureException(err); return err; } } return chain; } } export const connectNetworkRequestResult = async (chain, handleProvider, handleContract, handleNetwork, finishedCallback) => { let provider = new ethers.providers.Web3Provider(window.ethereum); handleProvider(provider) if (handleContract){ const deployedNetwork = Ethsign.networks[chain.chainId]; const contract = new ethers.Contract(deployedNetwork.address, Ethsign.abi, provider); handleContract(contract); } if(finishedCallback) { finishedCallback(true); } if (handleNetwork){ handleNetwork(chain) } } // This function supports only torus, imtoken and metamask wallets because we currently don't support network switch for fortmatic export const resetContractAndProvider = async (chainId, handleProvider, handleContract, torus) => { let biconomy = null; let provider = null; if(torus) { if(getChain(await torus.ethereum.request({ method: 'eth_chainId' }))?.biconomySupport) { let originalProvider = new ethers.providers.Web3Provider(torus.ethereum); biconomy = new Biconomy(originalProvider, { apiKey: getChain(await torus.ethereum.request({ method: 'eth_chainId' })).biconomyKey }); provider = new ethers.providers.Web3Provider(biconomy); } else { provider = new ethers.providers.Web3Provider(torus.ethereum); } handleProvider(provider) } else if(window.ethereum != null && window.ethereum != undefined) { if(getChain(await window.ethereum.request({ method: 'eth_chainId' }))?.biconomySupport) { let originalProvider = new ethers.providers.Web3Provider(window.ethereum); biconomy = new Biconomy(originalProvider, { apiKey: getChain(await window.ethereum.request({ method: 'eth_chainId' })).biconomyKey }); provider = new ethers.providers.Web3Provider(biconomy); } else { provider = new ethers.providers.Web3Provider(window.ethereum); } handleProvider(provider) } // Handle the contract const deployedNetwork = Ethsign.networks[chainId]; const signer = await provider.getSigner(); // signer == current logged in user const account = await signer.getAddress(); let contract = null; if (biconomy == null) { contract = new ethers.Contract(deployedNetwork.address, Ethsign.abi, provider); console.log("EthSign: Initialized normally.") } else { await new Promise((resolve, reject) => { biconomy.onEvent(biconomy.READY, async () => { contract = new ethers.Contract( deployedNetwork.address, Ethsign.abi, biconomy.getSignerByAddress(account) ); console.log("EthSign: Initialized with Mexa.") resolve(); }).onEvent(biconomy.ERROR, (error, message) => { console.log("EthSign: Failed to initialize with Mexa.") console.log(message); console.log(error); reject(); }); }); } handleContract(contract); }