{"id":263,"date":"2026-09-05T20:25:05","date_gmt":"2026-09-05T19:25:05","guid":{"rendered":"https:\/\/thebasicmaterialsproject.com\/?page_id=263"},"modified":"2026-09-18T18:25:26","modified_gmt":"2026-09-18T17:25:26","slug":"metamask-login-connect","status":"publish","type":"page","link":"https:\/\/thebasicmaterialsproject.com\/?page_id=263","title":{"rendered":"metamask login connect"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>&lt;!doctype html&gt;\n&lt;html lang=\"en\"&gt;\n\t&lt;head&gt;\n\t\t&lt;meta charset=\"utf-8\" \/&gt;\n\t\t&lt;meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" \/&gt;\n\t\t&lt;title&gt;Web3 Contract Example&lt;\/title&gt;\n\n\t\t&lt;!-- Pin web3 to a specific version --&gt;\n\t\t&lt;script src=\"https:\/\/cdn.jsdelivr.net\/npm\/web3@1.8.1\/dist\/web3.min.js\"&gt;&lt;\/script&gt;\n\n\t\t&lt;style&gt;\n\t\t\tbody { font-family: Arial, sans-serif; padding: 1rem; max-width: 720px; margin: auto; }\n\t\t\tbutton { margin-top: 0.5rem; }\n\t\t\t.row { margin: 0.5rem 0; }\n\t\t\t.warn { color: #a00; font-weight: bold; }\n\t\t&lt;\/style&gt;\n\t&lt;\/head&gt;\n\t&lt;body&gt;\n\n\t\t&lt;h2&gt;Web3 Contract Demo&lt;\/h2&gt;\n\n\t\t&lt;div id=\"status\" class=\"row\"&gt;\n\t\t\tStatus: &lt;span id=\"statusText\"&gt;idle&lt;\/span&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"row\"&gt;\n\t\t\t&lt;button id=\"connectBtn\"&gt;Connect Wallet&lt;\/button&gt;\n\t\t\t&lt;span id=\"account\" style=\"margin-left:1rem\"&gt;&lt;\/span&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"row\"&gt;\n\t\t\t&lt;strong&gt;Network:&lt;\/strong&gt;\n\t\t\t&lt;span id=\"network\"&gt;\u2014&lt;\/span&gt;\n\t\t\t&lt;span id=\"networkWarn\" class=\"warn\" style=\"margin-left:1rem; display:none\"&gt;Wrong network&lt;\/span&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"row\"&gt;\n\t\t\t&lt;strong&gt;Current value:&lt;\/strong&gt;\n\t\t\t&lt;span id=\"currentValue\"&gt;\u2014&lt;\/span&gt;\n\t\t\t&lt;button id=\"refreshBtn\"&gt;Refresh&lt;\/button&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"row\"&gt;\n\t\t\t&lt;input id=\"newValue\" type=\"number\" placeholder=\"New value\" \/&gt;\n\t\t\t&lt;button id=\"setBtn\"&gt;Set Value&lt;\/button&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"row\"&gt;\n\t\t\t&lt;small&gt;Tip: Place a `contractABI.json` file in the same folder (optional). Otherwise replace the `ABI` and `contractAddress` constants in the source.&lt;\/small&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;script&gt;\n\t\t\t\/\/ === Configuration ===\n\t\t\t\/\/ Replace with your deployed address if you know it.\n\t\t\tconst contractAddress = \"0xYourContractAddressHere\";\n\n\t\t\t\/\/ Optionally set the expected chainId (Hex string like '0x1' for mainnet or '0x5' for Goerli).\n\t\t\t\/\/ Set to null to skip network mismatch warnings.\n\t\t\tconst expectedChainId = null; \/\/ e.g. '0x5'\n\n\t\t\t\/\/ Default ABI placeholder; we will try to load .\/contractABI.json if present.\n\t\t\tlet ABI = &#91; \/* ... ABI array ... *\/ ];\n\n\t\t\tlet web3;\n\t\t\tlet contract;\n\t\t\tlet currentAccount;\n\t\t\tlet currentChainId;\n\n\t\t\tfunction setStatus(text) { document.getElementById('statusText').textContent = text; }\n\n\t\t\t\/\/ Try to load an ABI file from the same directory (contractABI.json)\n\t\t\tasync function tryLoadLocalAbi() {\n\t\t\ttry {\n\t\t\tconst resp = await fetch('.\/contractABI.json', { cache: 'no-store' });\n\t\t\tif (!resp.ok) return;\n\t\t\tconst parsed = await resp.json();\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\tABI = parsed;\n\t\t\tconsole.info('Loaded ABI from contractABI.json');\n\t\t\t} else if (parsed.abi &amp;&amp; Array.isArray(parsed.abi)) {\n\t\t\tABI = parsed.abi;\n\t\t\tconsole.info('Loaded ABI from contractABI.json (wrapped format)');\n\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\/\/ ignore - local ABI optional\n\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Decode revert reason from error.data (if present)\n\t\t\tfunction decodeRevertReason(data) {\n\t\t\ttry {\n\t\t\tif (!data) return null;\n\t\t\t\/\/ standard Error(string) selector: 0x08c379a0\n\t\t\tif (data.startsWith('0x08c379a0')) {\n\t\t\t\/\/ drop selector and length prefix: solidity ABI encode =&gt; 4 + offset(32) + strLen(32) + strBytes\n\t\t\tconst hex = data.slice(10); \/\/ remove 0x08c379a0\n\t\t\t\/\/ Derive the string hex from the remaining payload\n\t\t\t\/\/ Skip first 64 chars (offset + strLen) -&gt; start at char 128 (0-based)\n\t\t\tconst strHex = hex.slice(128);\n\t\t\tconst strBytes = strHex.slice(0, strHex.length - (strHex.length % 2));\n\t\t\tconst str = decodeURIComponent(strBytes.match(\/.{1,2}\/g).map(byte =&gt; '%' + byte).join(''));\n\t\t\treturn str;\n\t\t\t}\n\t\t\treturn null;\n\t\t\t} catch (e) {\n\t\t\treturn null;\n\t\t\t}\n\t\t\t}\n\n\t\t\tasync function connectWallet() {\n\t\t\tif (!window.ethereum) {\n\t\t\tsetStatus('No Ethereum provider (install MetaMask).');\n\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\tsetStatus('Initializing...');\n\t\t\tawait tryLoadLocalAbi();\n\t\t\tweb3 = new Web3(window.ethereum);\n\n\t\t\t\/\/ Request accounts (user will be prompted if not previously allowed)\n\t\t\tconst accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });\n\t\t\tcurrentAccount = accounts &amp;&amp; accounts&#91;0];\n\t\t\tdocument.getElementById('account').textContent = currentAccount || '';\n\n\t\t\t\/\/ Read chainId\n\t\t\tcurrentChainId = await window.ethereum.request({ method: 'eth_chainId' });\n\t\t\tdocument.getElementById('network').textContent = currentChainId || 'unknown';\n\t\t\tif (expectedChainId &amp;&amp; currentChainId !== expectedChainId) {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'inline';\n\t\t\t} else {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'none';\n\t\t\t}\n\n\t\t\tcontract = new web3.eth.Contract(ABI, contractAddress);\n\t\t\tsetStatus('Connected');\n\t\t\tawait readValue();\n\t\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\tsetStatus('Connection failed');\n\t\t\t}\n\t\t\t}\n\n\t\t\tasync function readValue() {\n\t\t\tif (!contract) { setStatus('Not connected'); return; }\n\t\t\ttry {\n\t\t\tsetStatus('Reading value...');\n\t\t\tconst value = await contract.methods.getValue().call();\n\t\t\tdocument.getElementById('currentValue').textContent = value;\n\t\t\tsetStatus('Read complete');\n\t\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\tconst reason = decodeRevertReason(err?.data?.original || err?.data || err?.error?.data);\n\t\t\tsetStatus('Read failed' + (reason ? `: ${reason}` : ''));\n\t\t\t}\n\t\t\t}\n\n\t\t\tfunction validateInput(v) {\n\t\t\tif (v === '') return { ok: false, msg: 'Value required' };\n\t\t\t\/\/ numeric check\n\t\t\tconst n = Number(v);\n\t\t\tif (!Number.isFinite(n)) return { ok: false, msg: 'Not a valid number' };\n\t\t\t\/\/ check safe integer range if integer expected\n\t\t\tif (!Number.isSafeInteger(n)) {\n\t\t\t\/\/ allow decimals if the contract expects them, else warn\n\t\t\treturn { ok: true, value: n, warn: 'Value is outside safe integer range; consider using a string\/BN' };\n\t\t\t}\n\t\t\treturn { ok: true, value: n };\n\t\t\t}\n\n\t\t\tasync function setValue() {\n\t\t\tif (!contract || !currentAccount) { setStatus('Not connected'); return; }\n\t\t\tconst input = document.getElementById('newValue');\n\t\t\tconst v = input.value;\n\t\t\tconst check = validateInput(v);\n\t\t\tif (!check.ok) {\n\t\t\tsetStatus(check.msg);\n\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\tsetStatus('Estimating gas...');\n\t\t\t\/\/ Use BN\/string if necessary - here we pass the value as-is; adapt if the contract expects specific types\n\t\t\tconst method = contract.methods.setValue(check.value);\n\t\t\t\/\/ estimate gas\n\t\t\tconst gasEstimate = await method.estimateGas({ from: currentAccount });\n\t\t\tsetStatus('Sending transaction...');\n\t\t\tconst receipt = await method.send({ from: currentAccount, gas: Math.floor(gasEstimate * 1.2) });\n\t\t\tconsole.log('Tx receipt', receipt);\n\t\t\tsetStatus('Transaction confirmed');\n\t\t\tawait readValue();\n\t\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\t\/\/ Try to show revert reason\n\t\t\tlet reason = null;\n\t\t\t\/\/ common places providers put data\n\t\t\treason = decodeRevertReason(err?.data?.original || err?.data || err?.error?.data || err?.receipt?.revertReason);\n\t\t\tif (!reason &amp;&amp; err?.message) reason = err.message;\n\t\t\tsetStatus('Tx failed or rejected' + (reason ? `: ${reason}` : ''));\n\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ React to account \/ chain changes\n\t\t\tif (window.ethereum) {\n\t\t\twindow.ethereum.on('accountsChanged', (accounts) =&gt; {\n\t\t\tcurrentAccount = accounts&#91;0] || null;\n\t\t\tdocument.getElementById('account').textContent = currentAccount || '';\n\t\t\tif (!currentAccount) setStatus('Disconnected');\n\t\t\t});\n\t\t\twindow.ethereum.on('chainChanged', (chainId) =&gt; {\n\t\t\t\/\/ update UI and optionally warn about mismatch\n\t\t\tcurrentChainId = chainId;\n\t\t\tdocument.getElementById('network').textContent = currentChainId || 'unknown';\n\t\t\tif (expectedChainId &amp;&amp; currentChainId !== expectedChainId) {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'inline';\n\t\t\t} else {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'none';\n\t\t\t}\n\t\t\t\/\/ Recommend reload to reinitialize provider state (keeps things simple).\n\t\t\t\/\/ Some apps handle chain re-init without reload.\n\t\t\twindow.location.reload();\n\t\t\t});\n\t\t\t}\n\n\t\t\tdocument.getElementById('connectBtn').addEventListener('click', connectWallet);\n\t\t\tdocument.getElementById('refreshBtn').addEventListener('click', readValue);\n\t\t\tdocument.getElementById('setBtn').addEventListener('click', setValue);\n\n\t\t\t\/\/ Optionally auto-connect if user already approved - prefer eth_accounts\n\t\t\twindow.addEventListener('DOMContentLoaded', async () =&gt; {\n\t\t\tif (!window.ethereum) return;\n\t\t\ttry {\n\t\t\tawait tryLoadLocalAbi();\n\t\t\tconst accounts = await window.ethereum.request({ method: 'eth_accounts' });\n\t\t\tif (accounts &amp;&amp; accounts.length &gt; 0) {\n\t\t\tawait connectWallet();\n\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\/\/ ignore\n\t\t\t}\n\t\t\t});\n\t\t&lt;\/script&gt;\n\t&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" \/>\n\t\t<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" \/>\n\t\t<title>Web3 Contract Example<\/title>\n\n\t\t<!-- Pin web3 to a specific version -->\n\t\t<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/web3@1.8.1\/dist\/web3.min.js\"><\/script>\n\n\t\t<style>\n\t\t\tbody { font-family: Arial, sans-serif; padding: 1rem; max-width: 720px; margin: auto; }\n\t\t\tbutton { margin-top: 0.5rem; }\n\t\t\t.row { margin: 0.5rem 0; }\n\t\t\t.warn { color: #a00; font-weight: bold; }\n\t\t<\/style>\n\t<\/head>\n\t<body>\n\n\t\t<h2>Web3 Contract Demo<\/h2>\n\n\t\t<div id=\"status\" class=\"row\">\n\t\t\tStatus: <span id=\"statusText\">idle<\/span>\n\t\t<\/div>\n\n\t\t<div class=\"row\">\n\t\t\t<button id=\"connectBtn\">Connect Wallet<\/button>\n\t\t\t<span id=\"account\" style=\"margin-left:1rem\"><\/span>\n\t\t<\/div>\n\n\t\t<div class=\"row\">\n\t\t\t<strong>Network:<\/strong>\n\t\t\t<span id=\"network\">\u2014<\/span>\n\t\t\t<span id=\"networkWarn\" class=\"warn\" style=\"margin-left:1rem; display:none\">Wrong network<\/span>\n\t\t<\/div>\n\n\t\t<div class=\"row\">\n\t\t\t<strong>Current value:<\/strong>\n\t\t\t<span id=\"currentValue\">\u2014<\/span>\n\t\t\t<button id=\"refreshBtn\">Refresh<\/button>\n\t\t<\/div>\n\n\t\t<div class=\"row\">\n\t\t\t<input id=\"newValue\" type=\"number\" placeholder=\"New value\" \/>\n\t\t\t<button id=\"setBtn\">Set Value<\/button>\n\t\t<\/div>\n\n\t\t<div class=\"row\">\n\t\t\t<small>Tip: Place a `contractABI.json` file in the same folder (optional). Otherwise replace the `ABI` and `contractAddress` constants in the source.<\/small>\n\t\t<\/div>\n\n\t\t<script>\n\t\t\t\/\/ === Configuration ===\n\t\t\t\/\/ Replace with your deployed address if you know it.\n\t\t\tconst contractAddress = \"0xYourContractAddressHere\";\n\n\t\t\t\/\/ Optionally set the expected chainId (Hex string like '0x1' for mainnet or '0x5' for Goerli).\n\t\t\t\/\/ Set to null to skip network mismatch warnings.\n\t\t\tconst expectedChainId = null; \/\/ e.g. '0x5'\n\n\t\t\t\/\/ Default ABI placeholder; we will try to load .\/contractABI.json if present.\n\t\t\tlet ABI = [ \/* ... ABI array ... *\/ ];\n\n\t\t\tlet web3;\n\t\t\tlet contract;\n\t\t\tlet currentAccount;\n\t\t\tlet currentChainId;\n\n\t\t\tfunction setStatus(text) { document.getElementById('statusText').textContent = text; }\n\n\t\t\t\/\/ Try to load an ABI file from the same directory (contractABI.json)\n\t\t\tasync function tryLoadLocalAbi() {\n\t\t\ttry {\n\t\t\tconst resp = await fetch('.\/contractABI.json', { cache: 'no-store' });\n\t\t\tif (!resp.ok) return;\n\t\t\tconst parsed = await resp.json();\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\tABI = parsed;\n\t\t\tconsole.info('Loaded ABI from contractABI.json');\n\t\t\t} else if (parsed.abi && Array.isArray(parsed.abi)) {\n\t\t\tABI = parsed.abi;\n\t\t\tconsole.info('Loaded ABI from contractABI.json (wrapped format)');\n\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\/\/ ignore - local ABI optional\n\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Decode revert reason from error.data (if present)\n\t\t\tfunction decodeRevertReason(data) {\n\t\t\ttry {\n\t\t\tif (!data) return null;\n\t\t\t\/\/ standard Error(string) selector: 0x08c379a0\n\t\t\tif (data.startsWith('0x08c379a0')) {\n\t\t\t\/\/ drop selector and length prefix: solidity ABI encode => 4 + offset(32) + strLen(32) + strBytes\n\t\t\tconst hex = data.slice(10); \/\/ remove 0x08c379a0\n\t\t\t\/\/ Derive the string hex from the remaining payload\n\t\t\t\/\/ Skip first 64 chars (offset + strLen) -> start at char 128 (0-based)\n\t\t\tconst strHex = hex.slice(128);\n\t\t\tconst strBytes = strHex.slice(0, strHex.length - (strHex.length % 2));\n\t\t\tconst str = decodeURIComponent(strBytes.match(\/.{1,2}\/g).map(byte => '%' + byte).join(''));\n\t\t\treturn str;\n\t\t\t}\n\t\t\treturn null;\n\t\t\t} catch (e) {\n\t\t\treturn null;\n\t\t\t}\n\t\t\t}\n\n\t\t\tasync function connectWallet() {\n\t\t\tif (!window.ethereum) {\n\t\t\tsetStatus('No Ethereum provider (install MetaMask).');\n\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\tsetStatus('Initializing...');\n\t\t\tawait tryLoadLocalAbi();\n\t\t\tweb3 = new Web3(window.ethereum);\n\n\t\t\t\/\/ Request accounts (user will be prompted if not previously allowed)\n\t\t\tconst accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });\n\t\t\tcurrentAccount = accounts && accounts[0];\n\t\t\tdocument.getElementById('account').textContent = currentAccount || '';\n\n\t\t\t\/\/ Read chainId\n\t\t\tcurrentChainId = await window.ethereum.request({ method: 'eth_chainId' });\n\t\t\tdocument.getElementById('network').textContent = currentChainId || 'unknown';\n\t\t\tif (expectedChainId && currentChainId !== expectedChainId) {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'inline';\n\t\t\t} else {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'none';\n\t\t\t}\n\n\t\t\tcontract = new web3.eth.Contract(ABI, contractAddress);\n\t\t\tsetStatus('Connected');\n\t\t\tawait readValue();\n\t\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\tsetStatus('Connection failed');\n\t\t\t}\n\t\t\t}\n\n\t\t\tasync function readValue() {\n\t\t\tif (!contract) { setStatus('Not connected'); return; }\n\t\t\ttry {\n\t\t\tsetStatus('Reading value...');\n\t\t\tconst value = await contract.methods.getValue().call();\n\t\t\tdocument.getElementById('currentValue').textContent = value;\n\t\t\tsetStatus('Read complete');\n\t\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\tconst reason = decodeRevertReason(err?.data?.original || err?.data || err?.error?.data);\n\t\t\tsetStatus('Read failed' + (reason ? `: ${reason}` : ''));\n\t\t\t}\n\t\t\t}\n\n\t\t\tfunction validateInput(v) {\n\t\t\tif (v === '') return { ok: false, msg: 'Value required' };\n\t\t\t\/\/ numeric check\n\t\t\tconst n = Number(v);\n\t\t\tif (!Number.isFinite(n)) return { ok: false, msg: 'Not a valid number' };\n\t\t\t\/\/ check safe integer range if integer expected\n\t\t\tif (!Number.isSafeInteger(n)) {\n\t\t\t\/\/ allow decimals if the contract expects them, else warn\n\t\t\treturn { ok: true, value: n, warn: 'Value is outside safe integer range; consider using a string\/BN' };\n\t\t\t}\n\t\t\treturn { ok: true, value: n };\n\t\t\t}\n\n\t\t\tasync function setValue() {\n\t\t\tif (!contract || !currentAccount) { setStatus('Not connected'); return; }\n\t\t\tconst input = document.getElementById('newValue');\n\t\t\tconst v = input.value;\n\t\t\tconst check = validateInput(v);\n\t\t\tif (!check.ok) {\n\t\t\tsetStatus(check.msg);\n\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\tsetStatus('Estimating gas...');\n\t\t\t\/\/ Use BN\/string if necessary - here we pass the value as-is; adapt if the contract expects specific types\n\t\t\tconst method = contract.methods.setValue(check.value);\n\t\t\t\/\/ estimate gas\n\t\t\tconst gasEstimate = await method.estimateGas({ from: currentAccount });\n\t\t\tsetStatus('Sending transaction...');\n\t\t\tconst receipt = await method.send({ from: currentAccount, gas: Math.floor(gasEstimate * 1.2) });\n\t\t\tconsole.log('Tx receipt', receipt);\n\t\t\tsetStatus('Transaction confirmed');\n\t\t\tawait readValue();\n\t\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\t\/\/ Try to show revert reason\n\t\t\tlet reason = null;\n\t\t\t\/\/ common places providers put data\n\t\t\treason = decodeRevertReason(err?.data?.original || err?.data || err?.error?.data || err?.receipt?.revertReason);\n\t\t\tif (!reason && err?.message) reason = err.message;\n\t\t\tsetStatus('Tx failed or rejected' + (reason ? `: ${reason}` : ''));\n\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ React to account \/ chain changes\n\t\t\tif (window.ethereum) {\n\t\t\twindow.ethereum.on('accountsChanged', (accounts) => {\n\t\t\tcurrentAccount = accounts[0] || null;\n\t\t\tdocument.getElementById('account').textContent = currentAccount || '';\n\t\t\tif (!currentAccount) setStatus('Disconnected');\n\t\t\t});\n\t\t\twindow.ethereum.on('chainChanged', (chainId) => {\n\t\t\t\/\/ update UI and optionally warn about mismatch\n\t\t\tcurrentChainId = chainId;\n\t\t\tdocument.getElementById('network').textContent = currentChainId || 'unknown';\n\t\t\tif (expectedChainId && currentChainId !== expectedChainId) {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'inline';\n\t\t\t} else {\n\t\t\tdocument.getElementById('networkWarn').style.display = 'none';\n\t\t\t}\n\t\t\t\/\/ Recommend reload to reinitialize provider state (keeps things simple).\n\t\t\t\/\/ Some apps handle chain re-init without reload.\n\t\t\twindow.location.reload();\n\t\t\t});\n\t\t\t}\n\n\t\t\tdocument.getElementById('connectBtn').addEventListener('click', connectWallet);\n\t\t\tdocument.getElementById('refreshBtn').addEventListener('click', readValue);\n\t\t\tdocument.getElementById('setBtn').addEventListener('click', setValue);\n\n\t\t\t\/\/ Optionally auto-connect if user already approved - prefer eth_accounts\n\t\t\twindow.addEventListener('DOMContentLoaded', async () => {\n\t\t\tif (!window.ethereum) return;\n\t\t\ttry {\n\t\t\tawait tryLoadLocalAbi();\n\t\t\tconst accounts = await window.ethereum.request({ method: 'eth_accounts' });\n\t\t\tif (accounts && accounts.length > 0) {\n\t\t\tawait connectWallet();\n\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\/\/ ignore\n\t\t\t}\n\t\t\t});\n\t\t<\/script>\n\t<\/body>\n<\/html>\n\n\n\n<h1 class=\"wp-block-heading\">Note: this is a work in progress and part of practicing a meta mask course currently undergoing. <\/h1>\n","protected":false},"excerpt":{"rendered":"<p>Web3 Contract Example Web3 Contract Demo Status: idle Connect Wallet Network: \u2014 Wrong network Current value: \u2014 Refresh Set Value Tip: Place a `contractABI.json` file in the same folder (optional). Otherwise replace the `ABI` and `contractAddress` constants in the source. Note: this is a work in progress and part of practicing a meta mask course [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-263","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/pages\/263","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=263"}],"version-history":[{"count":3,"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/pages\/263\/revisions"}],"predecessor-version":[{"id":280,"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/pages\/263\/revisions\/280"}],"wp:attachment":[{"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=263"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}