craft-nft

A standalone NFT implementation for real-world arts and crafts assets
Log | Files | Refs | README

commit 1c0b460267919bd18c4e575ea11143878d17c959
parent defaa2d0f79265e9edbfe11dd04a0cac379b6079
Author: lash <dev@holbrook.no>
Date:   Mon, 20 Feb 2023 23:50:21 +0000

Skip sparse tokens in qr scan, recipient address display

Diffstat:
Mjs/qrread.html | 18+++++-------------
Mjs/qrread.js | 19+++++++++++++------
Mjs/qrread_ui.js | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
3 files changed, 80 insertions(+), 37 deletions(-)

diff --git a/js/qrread.html b/js/qrread.html @@ -10,14 +10,6 @@ const MAX_MINT = 4; -//const privateKey = "5087503f0a9cc35b38665955eb830c63f778453dd11b8fa5bd04bc41fd2cc6d6"; -//const tokenId = "49d2711d67894feeb8fa449530aff40ee969cc09eebfc521c397432ef56cf33d"; -//const batchNumber = "0000000000000000000000000000000000000000000000000000000000000000"; -//const addressPrePad = "000000000000000000000000"; -//const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545"); -//const wallet_offline = new ethers.Wallet(privateKey); -//const wallet = wallet_offline.connect(provider); -// window.addEventListener('load', () => { for (let i = 1; i <= MAX_MINT; i<<=1) { const opt = document.createElement('option'); @@ -90,7 +82,7 @@ window.addEventListener('load', () => { </div> <div class="pane" id="contract"> <label for="contractAddress">Contract address</label> - <input type="text" id="contractAddress" /> + <input type="text" id="contractAddress" size="42" /> <button id="contractSubmit">connect to contract</button> </div> <div class="pane" id="product"> @@ -110,12 +102,12 @@ window.addEventListener('load', () => { <dt>Amount</dt> <dd id="scanTokenAmount"></dd> </dl> - <!--<div class="video-wrap"> - <video id="video" playsinline autoplay></video> - </div>--> <div class="out"> - <canvas id="qr-canvas" width="800" height="800"></canvas> + <canvas id="qr-canvas" width="400" height="400"></canvas> </div> + <label for="scanAddress">Recipient address</label> + <input type="text" id="scanAddress" size="42" /> + <ol id="txList"></ol> <button id="scanAbort">abort</button> </div> </html> diff --git a/js/qrread.js b/js/qrread.js @@ -5,10 +5,11 @@ const STATE = { CONTRACT_SETTINGS: 4, MINT: 8, SCAN_START: 16, - SCAN_STOP: 32, - SCAN_DONE: 64, - TX_FLIGHT: 128, - TX_RESULT: 256, + SCAN_RESULT: 32, + SCAN_STOP: 64, + SCAN_DONE: 128, + TX_FLIGHT: 256, + TX_RESULT: 512, }; var settings = { @@ -21,6 +22,7 @@ var settings = { chainId: undefined, dataPost: undefined, mintAmount: 1, + recipient: undefined, }; const txBase = { @@ -112,6 +114,10 @@ async function contractHandler(contractAddress) { if (batch.count == 0) { console.debug('skipping unique token', tokenId); break; + } else if (batch.sparse) { + console.debug('skip sparse token', tokenId); + j++; + continue; } const e = new CustomEvent('token', { detail: { @@ -151,8 +157,9 @@ function requestHandler(tokenBatch, amount) { const v = tokenBatch.split('.'); let batchNumberHex = "0000000000000000000000000000000000000000000000000000000000000000" + v[1].toString(16); batchNumberHex = batchNumberHex.slice(-64); - settings.dataPost = v[0] + batchNumberHex; - settings.tokenId = v[0]; + let tokenId = v[0].substring(2); + settings.dataPost = tokenId + batchNumberHex; + settings.tokenId = tokenId; settings.batchNumber = v[1]; settings.mintAmount = amount; const e = new CustomEvent('uistate', { diff --git a/js/qrread_ui.js b/js/qrread_ui.js @@ -40,6 +40,9 @@ window.addEventListener('uistate', (e) => { document.getElementById("read").style.display = "block"; live(); break; + case STATE.SCAN_RESULT: + document.getElementById('scanAddress').value = e.detail.settings.recipient; + break; case STATE.SCAN_STOP: window.stream.getTracks().forEach(track => track.stop()); break; @@ -72,6 +75,19 @@ window.addEventListener('token', (e) => { ls.appendChild(label); }); +window.addEventListener('tx', (e) => { + const ls = document.getElementById('txList'); + const li = document.createElement('li'); + const l = document.createElement('span'); + l.innerHTML = e.detail.tx.hash; + const r = document.createElement('span'); + r.setAttribute('id', 'status.' + e.detail.tx.hash); + r.innerHTML = 'status: pending'; + li.appendChild(l); + li.appendChild(r); + ls.appendChild(li); +}); + function updateSettingsView(k, v) { const dl = document.getElementById("settingsView"); const dt = document.createElement("dt"); @@ -124,23 +140,36 @@ function scan() { const code = jsQR(imageData, 400, 400); if (code) { console.log("Found QR code", code); - signAndSend(code.data); + let addr = code.data; + if (addr.length < 40) { + console.error('invalid ethereum address (too short)', addr); + return; + } + if (addr.substring(0, 9) == "ethereum:") { // metamask qr + addr = addr.substring(9); + } + if (addr.substring(0, 2) == "0x") { + addr = addr.substring(2); + } + settings.recipient = addr; + const e = new CustomEvent('uistate', { + detail: { + delta: STATE.SCAN_RESULT, + settings: settings, + }, + bubbles: true, + cancelable: true, + composed: false, + }); + window.dispatchEvent(e); + signAndSend(addr); return; } setTimeout(scan, 10); } async function signAndSend(addr) { - if (addr.length < 40) { - console.error('invalid ethereum address (too short)', addr); - return; - } - if (addr.substring(0, 9) == "ethereum:") { // metamask qr - addr = addr.substring(9); - } - if (addr.substring(0, 2) == "0x") { - addr = addr.substring(2); - } + const re = new RegExp("^[0-9a-fA-F]{40}$"); const m = addr.match(re); if (m === null) { @@ -149,14 +178,29 @@ async function signAndSend(addr) { } console.info('found recipient address', addr); let tx = txBase; - const nonce = await settings.wallet.getTransactionCount(); + let nonce = await settings.wallet.getTransactionCount(); addr = addressPrePad + addr; tx.data += addr; tx.data += settings.dataPost; - tx.nonce = nonce; - console.log(tx); - const txSigned = await settings.wallet.signTransaction(tx); - console.log(txSigned); - const r = await settings.wallet.sendTransaction(tx); - console.log(r); + + for (let i = 0; i < settings.mintAmount; i++) { + let txCopy = tx; + txCopy.nonce = nonce; + const txSigned = await settings.wallet.signTransaction(tx); + console.log(txSigned); + const txr = await settings.wallet.sendTransaction(txCopy); + const e = new CustomEvent('tx', { + detail: { + settings: settings, + tx: txr, + mintAmount: settings.mintAmount, + }, + bubbles: true, + cancelable: true, + composed: false, + }); + window.dispatchEvent(e); + console.debug(txr); + nonce++; + } }