UNPKG

hang-sdk

Version:

Hang SDK is on a mission to help developers create DAPPs with ease and interact with Hang deployed smart contracts.

158 lines (131 loc) 4.47 kB
import Web3 from 'web3'; import WalletConnectProvider from '@walletconnect/web3-provider'; import Web3Modal, { ICoreOptions, IProviderOptions } from 'web3modal'; import { networkMap } from './utils'; import { HangCore, IHangCoreProps } from './HangCore'; import { INFURA_ID } from './utils'; const SKIPPED = 'skipped'; const providerOptions: IProviderOptions = { walletconnect: { package: WalletConnectProvider, options: { infuraId: INFURA_ID, }, }, }; const CONNECT_KEY = 'HANG_CONNECT_CACHE'; const LATEST_CONNECT_VERSION = '3'; export interface IHangWalletPluginOptions extends IHangCoreProps { web3ModalOptions?: Partial<ICoreOptions>; } export class HangWalletPlugin extends HangCore { accounts?: string[]; provider?: any; web3Modal: Web3Modal; constructor({ slug, web3ModalOptions, ...args }: IHangWalletPluginOptions) { super({ slug, ...args }); this.fetchProjectMetadata(); this.web3Modal = new Web3Modal({ cacheProvider: true, providerOptions, ...web3ModalOptions, }); } autoconnect = async () => { if (this.web3Modal.cachedProvider) { this.provider = this.provider || (await this.connectToWeb3Modal()); this.web3(new Web3(this.provider)); await this.onConnectComplete(); return Promise.resolve(); } else { return Promise.reject(SKIPPED); } }; connect = async (): Promise<void> => { try { this.provider = await this.connectToWeb3Modal(); this.web3(new Web3(this.provider)); await this.onConnectComplete(); } catch (e) { Promise.reject(e); } }; connectToWeb3Modal = async () => { const hangConnectVersion = localStorage.getItem(CONNECT_KEY); if (!hangConnectVersion || hangConnectVersion != LATEST_CONNECT_VERSION) { this.clearWalletConnectKeys(); localStorage.setItem(CONNECT_KEY, LATEST_CONNECT_VERSION); } return await this.web3Modal.connect(); }; clearWalletConnectKeys = () => { Object.entries(localStorage).map((entry) => { const key = entry[0]; if (key.startsWith('-walletlink')) localStorage.removeItem(key); }); }; onConnectComplete = async () => { if (!this.web3Instance.eth) return; await this.requestChainSwitchIfNeeded(); await this.syncAccountAndContract(); this.events.emit('WALLET_CONNECTED', { address: this.getCurrentWallet() }); this.addProviderEvents(); }; syncAccountAndContract = async () => { await this.fetchAccountData(); }; fetchAccountData = async () => { // Get list of accounts of the connected wallet const accounts = await this.web3Instance.eth.getAccounts(); // MetaMask does not give you all accounts, only the selected account this.accounts = accounts; }; addProviderEvents = () => { this.provider!.on('accountsChanged', async () => { await this.syncAccountAndContract(); this.events.emit('WALLET_CHANGED', null); }); }; getCurrentWallet = () => { return this.accounts?.[0] || ''; }; requestChainSwitchIfNeeded = async () => { if (!this.projectData) return; const currentChain = await this.web3Instance.eth.getChainId(); if (this.projectData.contract.chain_id != currentChain) { try { // @ts-ignore await this.web3Instance?.currentProvider?.request({ method: 'wallet_switchEthereumChain', params: [ { chainId: Web3.utils.toHex(this.projectData.contract.chain_id) }, ], }); } catch (e) { console.log('Error thrown while switching ', e); const networkParams = networkMap[this.projectData.contract.chain_id]; if (!networkParams) return; // @ts-ignore: check later await this.web3Instance.currentProvider.request({ method: 'wallet_addEthereumChain', params: [networkMap[this.projectData.contract.chain_id]], }); // @ts-ignore: check later await this.web3Instance.currentProvider.request({ method: 'wallet_switchEthereumChain', params: [ { chainId: Web3.utils.toHex(this.projectData.contract.chain_id) }, ], }); } } }; async mint(quantity: number = 1) { if (!this.projectData) return; await this.connect(); await this.mintTo(quantity, this.getCurrentWallet()); } async balanceOfCurrentWallet() { return this.balanceOfAddress(this.getCurrentWallet()); } }