{"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-05T20:25:05","modified_gmt":"2026-09-05T19:25:05","slug":"metamask-login-connect","status":"publish","type":"page","link":"https:\/\/thebasicmaterialsproject.com\/?page_id=263","title":{"rendered":"metamask login connect"},"content":{"rendered":"\n<div class=\"wp-block-group alignfull has-global-padding is-layout-constrained wp-container-core-group-is-layout-75f56b9d wp-block-group-is-layout-constrained\" style=\"min-height:0vh;margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--70);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--70);padding-left:var(--wp--preset--spacing--40)\">\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-container-core-group-is-layout-f15145cb wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading has-text-align-center has-xx-large-font-size\" style=\"margin-right:0;margin-left:0;padding-right:0;padding-left:0\">Tell your story<\/h2>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">Like flowers that bloom in unexpected places, every story unfolds with beauty and resilience, revealing hidden wonders.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-35f06ea7 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\">Learn more<\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-group alignfull is-style-section-1 has-global-padding is-layout-constrained wp-block-group-is-layout-constrained is-style-section-1--1\" style=\"margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--80);padding-bottom:var(--wp--preset--spacing--80)\">\n<div class=\"wp-block-columns alignwide is-layout-flex wp-container-core-columns-is-layout-f911b2ec wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"padding-right:var(--wp--preset--spacing--50);flex-basis:45%\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/thebasicmaterialsproject.com\/wp-content\/themes\/twentytwentyfive\/assets\/images\/red-hibiscus-closeup.webp\" alt=\"Photography close up of a red flower.\"\/><\/figure>\n\n\n\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\" style=\"margin-top:-12vw\">\n<figure class=\"wp-block-image alignright size-full is-resized\" style=\"margin-right:-5vw;margin-left:-5vw\"><img decoding=\"async\" src=\"https:\/\/thebasicmaterialsproject.com\/wp-content\/themes\/twentytwentyfive\/assets\/images\/grid-flower-2.webp\" alt=\"Black and white photography close up of a flower.\" style=\"width:202px;height:auto\"\/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow\" style=\"padding-right:0;padding-left:0;flex-basis:50%\">\n<div class=\"wp-block-group is-vertical is-layout-flex wp-container-core-group-is-layout-831b2db5 wp-block-group-is-layout-flex\">\n<h2 class=\"wp-block-heading is-style-text-annotation is-style-text-annotation--2\">About Us<\/h2>\n<\/div>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--3 wp-block-paragraph\">\n\t\t\t<strong>Fleurs<\/strong> is a flower delivery and subscription business. Based in the EU, our mission is not only to deliver stunning flower arrangements across but also foster knowledge and enthusiasm on the beautiful gift of nature: flowers.\t\t\t<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-group alignfull has-global-padding is-layout-constrained wp-container-core-group-is-layout-4bb49aaa wp-block-group-is-layout-constrained\" style=\"margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--50);padding-bottom:var(--wp--preset--spacing--50)\">\n<h2 class=\"wp-block-heading alignwide\">Our services<\/h2>\n\n\n\n<div class=\"wp-block-columns alignwide is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\" style=\"margin-bottom:24px\"><img decoding=\"async\" src=\"https:\/\/thebasicmaterialsproject.com\/wp-content\/themes\/twentytwentyfive\/assets\/images\/campanula-alliariifolia-flower.webp\" alt=\"Image for service\" style=\"aspect-ratio:4\/3;object-fit:cover\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Collect<\/h3>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Like flowers that bloom in unexpected places, every story unfolds with beauty and resilience<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\" style=\"margin-bottom:24px\"><img decoding=\"async\" src=\"https:\/\/thebasicmaterialsproject.com\/wp-content\/themes\/twentytwentyfive\/assets\/images\/delphinium-flowers.webp\" alt=\"Image for service\" style=\"aspect-ratio:4\/3;object-fit:cover\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Assemble<\/h3>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Like flowers that bloom in unexpected places, every story unfolds with beauty and resilience<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\" style=\"margin-bottom:24px\"><img decoding=\"async\" src=\"https:\/\/thebasicmaterialsproject.com\/wp-content\/themes\/twentytwentyfive\/assets\/images\/star-thristle-flower.webp\" alt=\"Image for service\" style=\"aspect-ratio:4\/3;object-fit:cover\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Deliver<\/h3>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Like flowers that bloom in unexpected places, every story unfolds with beauty and resilience<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\" style=\"margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)\">\n<div class=\"wp-block-columns alignwide is-layout-flex wp-container-core-columns-is-layout-6108e6a5 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-group is-vertical is-content-justification-left is-layout-flex wp-container-core-group-is-layout-1e881699 wp-block-group-is-layout-flex\" style=\"min-height:100%\">\n<h2 class=\"wp-block-heading is-style-text-annotation has-x-small-font-size is-style-text-annotation--4\">What people are saying<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-style-plain has-x-large-font-size is-layout-flow wp-container-core-quote-is-layout-a54b8880 wp-block-quote-is-layout-flow is-style-plain--5\" style=\"font-style:normal;font-weight:400\">\n<div class=\"wp-block-group has-global-padding is-content-justification-left is-layout-constrained wp-container-core-group-is-layout-c61b7426 wp-block-group-is-layout-constrained\" style=\"margin-top:0;margin-bottom:0;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0\">\n<p class=\"has-xx-large-font-size wp-block-paragraph\">\u201cSuperb product and customer service!\u201d<\/p>\n<\/div>\n<cite>Jo Mulligan <br><sub>Atlanta, GA<\/sub><\/cite><\/blockquote>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"padding-top:0;padding-right:0;padding-bottom:0;padding-left:0\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/thebasicmaterialsproject.com\/wp-content\/themes\/twentytwentyfive\/assets\/images\/typewriter.webp\" alt=\"Picture of a person typing on a typewriter.\" style=\"aspect-ratio:1;object-fit:cover\"\/><\/figure>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\" style=\"margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)\">\n<h2 class=\"wp-block-heading has-text-align-center alignwide\">Pricing<\/h2>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">Cancel or pause anytime.<\/p>\n\n\n\n<div style=\"height:var(--wp--preset--spacing--40)\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-columns alignwide is-layout-flex wp-container-core-columns-is-layout-f765c490 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column has-border-color is-layout-flow wp-block-column-is-layout-flow\" style=\"border-color:var(--wp--preset--color--accent-6);border-width:1px;border-radius:10px;padding-top:var(--wp--preset--spacing--50);padding-right:var(--wp--preset--spacing--50);padding-bottom:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<h3 id=\"free\" class=\"wp-block-heading\">Free<\/h3>\n\n\n\n<p class=\"has-large-font-size wp-block-paragraph\">0\u20ac<\/p>\n\n\n\n<ul style=\"padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--20)\" class=\"wp-block-list is-style-checkmark-list has-small-font-size\">\n<li>Get access to our paid articles and weekly newsletter.<\/li>\n\n\n\n<li>Join our IRL events.<\/li>\n\n\n\n<li>Get a free tote bag.<\/li>\n\n\n\n<li>An elegant addition of home decor collection.<\/li>\n\n\n\n<li>Join our forums.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-35f06ea7 wp-block-buttons-is-layout-flex\">\n<div style=\"--wp--block-button--width: 100;\" class=\"wp-block-button has-custom-width wp-block-button__width wp-block-button__width-100\"><a class=\"wp-block-button__link wp-element-button\">Join<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column has-border-color is-layout-flow wp-block-column-is-layout-flow\" style=\"border-color:var(--wp--preset--color--accent-6);border-width:1px;border-radius:10px;padding-top:var(--wp--preset--spacing--50);padding-right:var(--wp--preset--spacing--50);padding-bottom:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<h3 id=\"single\" class=\"wp-block-heading\">Single<\/h3>\n\n\n\n<p class=\"has-large-font-size wp-block-paragraph\">20\u20ac\/month<\/p>\n\n\n\n<ul style=\"padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--20)\" class=\"wp-block-list is-style-checkmark-list has-small-font-size\">\n<li>Get access to our paid articles and weekly newsletter.<\/li>\n\n\n\n<li>Join our IRL events.<\/li>\n\n\n\n<li>Get a free tote bag.<\/li>\n\n\n\n<li>An elegant addition of home decor collection.<\/li>\n\n\n\n<li>Join our forums.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-35f06ea7 wp-block-buttons-is-layout-flex\">\n<div style=\"--wp--block-button--width: 100;\" class=\"wp-block-button has-custom-width wp-block-button__width wp-block-button__width-100\"><a class=\"wp-block-button__link wp-element-button\">Join<\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<aside class=\"wp-block-group alignfull is-style-section-3 has-global-padding is-layout-constrained wp-container-core-group-is-layout-0553457c wp-block-group-is-layout-constrained is-style-section-3--6\" style=\"margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--50);padding-right:var(--wp--preset--spacing--50);padding-bottom:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<div class=\"wp-block-group is-vertical is-content-justification-center is-layout-flex wp-container-core-group-is-layout-65db5ff9 wp-block-group-is-layout-flex\" style=\"min-height:360px;margin-top:0;margin-bottom:0\">\n<h2 class=\"wp-block-heading has-text-align-center has-xx-large-font-size\">Sign up to get daily stories<\/h2>\n\n\n\n<p class=\"has-text-align-center is-style-text-subtitle is-style-text-subtitle--7 wp-block-paragraph\">Get access to a curated collection of moments in time featuring photographs from historical relevance.<\/p>\n\n\n\n<div style=\"height:0px\" aria-hidden=\"true\" class=\"wp-block-spacer wp-container-content-62aae154\"><\/div>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-35f06ea7 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-text-align-center wp-element-button\">Subscribe<\/a><\/div>\n<\/div>\n<\/div>\n<\/aside>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!doctype html>\n&lt;html lang=\"en\">\n\t&lt;head>\n\t\t&lt;meta charset=\"utf-8\" \/>\n\t\t&lt;meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" \/>\n\t\t&lt;title>Web3 Contract Example&lt;\/title>\n\n\t\t&lt;!-- Pin web3 to a specific version -->\n\t\t&lt;script src=\"https:\/\/cdn.jsdelivr.net\/npm\/web3@1.8.1\/dist\/web3.min.js\">&lt;\/script>\n\n\t\t&lt;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&lt;\/style>\n\t&lt;\/head>\n\t&lt;body>\n\n\t\t&lt;h2>Web3 Contract Demo&lt;\/h2>\n\n\t\t&lt;div id=\"status\" class=\"row\">\n\t\t\tStatus: &lt;span id=\"statusText\">idle&lt;\/span>\n\t\t&lt;\/div>\n\n\t\t&lt;div class=\"row\">\n\t\t\t&lt;button id=\"connectBtn\">Connect Wallet&lt;\/button>\n\t\t\t&lt;span id=\"account\" style=\"margin-left:1rem\">&lt;\/span>\n\t\t&lt;\/div>\n\n\t\t&lt;div class=\"row\">\n\t\t\t&lt;strong>Network:&lt;\/strong>\n\t\t\t&lt;span id=\"network\">\u2014&lt;\/span>\n\t\t\t&lt;span id=\"networkWarn\" class=\"warn\" style=\"margin-left:1rem; display:none\">Wrong network&lt;\/span>\n\t\t&lt;\/div>\n\n\t\t&lt;div class=\"row\">\n\t\t\t&lt;strong>Current value:&lt;\/strong>\n\t\t\t&lt;span id=\"currentValue\">\u2014&lt;\/span>\n\t\t\t&lt;button id=\"refreshBtn\">Refresh&lt;\/button>\n\t\t&lt;\/div>\n\n\t\t&lt;div class=\"row\">\n\t\t\t&lt;input id=\"newValue\" type=\"number\" placeholder=\"New value\" \/>\n\t\t\t&lt;button id=\"setBtn\">Set Value&lt;\/button>\n\t\t&lt;\/div>\n\n\t\t&lt;div class=\"row\">\n\t\t\t&lt;small>Tip: Place a `contractABI.json` file in the same folder (optional). Otherwise replace the `ABI` and `contractAddress` constants in the source.&lt;\/small>\n\t\t&lt;\/div>\n\n\t\t&lt;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 = &#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 => 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 &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) => {\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) => {\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 () => {\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 > 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>\n\t&lt;\/body>\n&lt;\/html><\/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","protected":false},"excerpt":{"rendered":"<p>Tell your story Like flowers that bloom in unexpected places, every story unfolds with beauty and resilience, revealing hidden wonders. About Us Fleurs is a flower delivery and subscription business. Based in the EU, our mission is not only to deliver stunning flower arrangements across but also foster knowledge and enthusiasm on the beautiful gift [&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":1,"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/pages\/263\/revisions"}],"predecessor-version":[{"id":264,"href":"https:\/\/thebasicmaterialsproject.com\/index.php?rest_route=\/wp\/v2\/pages\/263\/revisions\/264"}],"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}]}}