{"version":3,"sources":["App.tsx","index.tsx"],"names":["reloadContractValue","contract","callback","get","then","value","catch","error","console","PleaseChangeNetworkMessage","CannotAccessBlockChainMessage","App","useState","isMetaMaskActive","setIsMetaMaskActive","isRopstenNetwork","setIsRopstenNetwork","isChainConnectionHealthy","setIsChainConnectionHealthy","providerRef","useRef","contractRef","signerRef","userInput","setUserInput","signedUserInput","setSignedUserInput","contractValue","setContractValue","isSigningUserInput","setIsSigningUserInput","isSendingTransaction","setIsSendingTransaction","useEffect","timeout","window","ethereum","request","method","chainId","Promise","resolve","connected","undefined","setTimeoutId","setTimeout","params","blockNumber","clearTimeout","on","location","reload","account","current","toast","slice","removeAllListeners","ethers","providers","Web3Provider","Contract","debugEnvironment","useCallback","duration","connect","provider","send","accounts","getSigner","code","signUserInput","signer","signMessage","signed","finally","updateContractValue","set","result","transactionHash","hash","once","transaction","isSignButtonDisabled","isSendButtonDisabled","className","type","onClick","onChange","event","target","placeholder","disabled","ReactDOM","render","StrictMode","document","getElementById"],"mappings":"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","file":"static/js/main.0f746d15.chunk.js","sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { ethers } from 'ethers';\nimport toast, { Toaster } from 'react-hot-toast';\nimport './App.css';\n\nconst CONTRACT_ADDRESS = '0xA0875db1562e16Ca9a15420464ac82947F424FFa';\n\nconst canGetBlockNumber = (timeout: number): Promise =>\n new Promise((resolve) => {\n if (!window.ethereum) {\n resolve(false);\n\n return;\n }\n\n let connected = undefined as boolean | undefined;\n\n const setTimeoutId = setTimeout(() => {\n if (connected === undefined) {\n connected = false;\n\n resolve(false);\n }\n }, timeout);\n\n window.ethereum.request({ method: 'eth_blockNumber', params: [] }).then(\n (blockNumber: number) => {\n if (connected === undefined) {\n clearTimeout(setTimeoutId);\n connected = true;\n\n resolve(true);\n }\n },\n () => {\n if (connected === undefined) {\n clearTimeout(setTimeoutId);\n connected = false;\n\n resolve(false);\n }\n },\n );\n });\n\nconst reloadContractValue = (contract: ethers.Contract, callback: (value: string) => void) => {\n contract\n .get()\n .then((value: string) => callback(value))\n .catch((error: any) => {\n console.error('MetaMask cannot get contract value. Error:', error);\n });\n};\n\nconst PleaseChangeNetworkMessage =\n 'Please change the network to Ropsten Test Network in order to interact with the contract.';\n\nconst CannotAccessBlockChainMessage = `MetaMask cannot access blockchain data.\nThis may be caused by limited site access. Please allow MetaMask to access on all sites and reload page as a workaround.`;\n\nfunction App() {\n const [isMetaMaskActive, setIsMetaMaskActive] = useState();\n const [isRopstenNetwork, setIsRopstenNetwork] = useState();\n const [isChainConnectionHealthy, setIsChainConnectionHealthy] = useState();\n\n const providerRef = useRef();\n const contractRef = useRef();\n const signerRef = useRef();\n\n const [userInput, setUserInput] = useState('');\n const [signedUserInput, setSignedUserInput] = useState('');\n const [contractValue, setContractValue] = useState('');\n\n const [isSigningUserInput, setIsSigningUserInput] = useState(false);\n const [isSendingTransaction, setIsSendingTransaction] = useState(false);\n\n useEffect(() => {\n // detect MetaMask environment\n if (!window.ethereum) {\n setIsMetaMaskActive(false);\n\n return;\n }\n\n setIsMetaMaskActive(true);\n\n window.ethereum\n .request({ method: 'eth_chainId' })\n .then((chainId: string) => setIsRopstenNetwork(chainId === '0x3'));\n\n canGetBlockNumber(2000).then(setIsChainConnectionHealthy);\n\n // setup MetaMask listeners\n window.ethereum.on('chainChanged', () => window.location.reload()); // reload page on chain changed\n\n window.ethereum.on('accountsChanged', ([account]: string[]) => {\n if (!account) {\n signerRef.current = undefined;\n\n toast('Disconnected.');\n\n return;\n }\n\n if (signerRef.current) {\n setSignedUserInput('');\n\n toast(`Account changed to ${account.slice(0, 30)}...`);\n }\n });\n\n return () => window.ethereum.removeAllListeners();\n }, []);\n\n // setup provider if MetaMask is active\n useEffect(() => {\n if (isMetaMaskActive && !providerRef.current) {\n providerRef.current = new ethers.providers.Web3Provider(window.ethereum);\n }\n }, [isMetaMaskActive]);\n\n // setup contract if network is ropsten\n useEffect(() => {\n if (isRopstenNetwork && !contractRef.current) {\n const contract = new ethers.Contract(\n CONTRACT_ADDRESS,\n ['function get() view returns (string)', 'function set(string)'],\n providerRef.current,\n );\n\n contractRef.current = contract;\n\n reloadContractValue(contract, setContractValue);\n } else if (isRopstenNetwork === false) {\n toast(PleaseChangeNetworkMessage);\n }\n }, [isRopstenNetwork]);\n\n // remind user if MetaMask cannot access blockchain data\n useEffect(() => {\n if (isChainConnectionHealthy === false) {\n toast(CannotAccessBlockChainMessage);\n }\n }, [isChainConnectionHealthy]);\n\n // show error messages when action is not allowed\n const debugEnvironment = useCallback(() => {\n if (isMetaMaskActive === undefined) return;\n\n if (isMetaMaskActive === false) {\n toast('MetaMask not enabled.');\n\n return;\n }\n\n if (!signerRef.current) {\n toast('Please connect to MetaMask first.');\n }\n\n if (isRopstenNetwork === false) {\n setTimeout(() => toast(PleaseChangeNetworkMessage), 400);\n }\n\n if (isChainConnectionHealthy === false) {\n setTimeout(() => toast(CannotAccessBlockChainMessage, { duration: 8000 }), 800);\n }\n\n return;\n }, [isMetaMaskActive, isChainConnectionHealthy, isRopstenNetwork]);\n\n // connect to wallet handler\n const connect = useCallback(() => {\n const provider = providerRef.current;\n\n if (!provider) {\n debugEnvironment();\n\n return;\n }\n\n provider\n .send('eth_requestAccounts', [])\n .then((accounts) => {\n const [account] = accounts;\n\n // setup signer\n signerRef.current = provider.getSigner();\n\n toast(`Connected. Current account: ${account.slice(0, 30)}...`);\n\n if (!isRopstenNetwork || !isChainConnectionHealthy) {\n debugEnvironment();\n }\n })\n .catch((error) => {\n if (error.code === 4001) {\n toast('Denied.');\n }\n\n if (error.code === -32002) {\n toast('Already requesting accounts. Reload this page if necessary.');\n }\n });\n }, [debugEnvironment, isRopstenNetwork, isChainConnectionHealthy]);\n\n // sign message handler\n const signUserInput = useCallback(() => {\n const signer = signerRef.current;\n\n if (!signer) {\n debugEnvironment();\n\n return;\n }\n\n setIsSigningUserInput(true);\n\n signer\n .signMessage(userInput)\n .then((signed) => {\n setSignedUserInput(signed);\n })\n .catch((error: any) => {\n if (error.code === 4001) {\n toast('Denied.');\n } else {\n toast('Error');\n }\n })\n .finally(() => {\n setIsSigningUserInput(false);\n });\n }, [debugEnvironment, userInput]);\n\n // set contract value handler\n const updateContractValue = useCallback(() => {\n const provider = providerRef.current;\n const contract = contractRef.current;\n const signer = signerRef.current;\n\n if (!provider || !contract || !signer || !isChainConnectionHealthy) {\n debugEnvironment();\n\n return;\n }\n\n setIsSendingTransaction(true);\n\n contract\n .connect(signer)\n .set(signedUserInput)\n .then((result: any) => {\n const transactionHash = result.hash as string;\n\n toast(`Transaction ${transactionHash.slice(0, 30)}... has been sent.`);\n\n provider.once(transactionHash, (transaction) => {\n toast(`Transaction ${transaction.transactionHash.slice(0, 30)}... has been mined.`);\n\n reloadContractValue(contract, setContractValue);\n });\n })\n .catch((error: any) => {\n if (error.code === 4001) {\n toast('Denied.');\n } else {\n toast('Error.');\n }\n })\n .finally(() => {\n setIsSendingTransaction(false);\n });\n }, [isChainConnectionHealthy, debugEnvironment, signedUserInput]);\n\n const isSignButtonDisabled = isSigningUserInput || isSendingTransaction;\n const isSendButtonDisabled = isSigningUserInput || isSendingTransaction || !signedUserInput;\n\n return (\n <>\n
\n TEST\n \n
\n
\n
\n setUserInput(event.target.value)}\n placeholder=\"input\"\n />\n \n sign\n \n
\n
\n Hashed Value:\n {signedUserInput}\n \n send\n \n
\n
\n Variable Value:\n {contractValue}\n
\n \n
\n \n );\n}\n\nexport default App;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root'),\n);\n"],"sourceRoot":""}