commit e122f1e40c89bf8a5887b1dd5f7f8849f44d99f1
parent 2d68d177b264a321919a0e8992b2317857999751
Author: lash <dev@holbrook.no>
Date: Sat, 17 Dec 2022 19:45:57 +0000
Add token details view, minting view
Diffstat:
4 files changed, 166 insertions(+), 7 deletions(-)
diff --git a/js/index.html b/js/index.html
@@ -10,6 +10,9 @@
#detail {
visibility: hidden;
}
+#mint {
+ visibility: hidden;
+}
a {
text-decoration: underline;
color: #0000ff;
@@ -39,7 +42,7 @@ a:hover {
</form>
</div>
<div id="detail">
- <a id="back_link" onClick="listTokens();">back</a>
+ <a id="back_link" onClick="uiCreateToken();">back</a>
<dl>
<dt>token id</dt>
<dd id="token_id"></dd>
@@ -47,8 +50,25 @@ a:hover {
<dd id="token_name"></dd>
<dt>description</dt>
<dd id="token_description"></dd>
+ <dt class="token_batch_list">batches</dt>
+ <dd class="token_batch_list">
+ <ol id="token_batches"></ol>
+ </dd>
</dl>
</div>
+ <div id="mint">
+ <a id="back_link" onClick="uiCreateToken();">back</a>
+ <dl>
+ <dt>token id</dt>
+ <dd id="token_mint_id"></dd>
+ <dt>batch</dt>
+ <dd id="token_mint_batch"></dd>
+ </dl>
+ <form>
+ <input type="text" id="token_mint_recipient" />
+ <button id="mint_submit">mint</button>
+ </form>
+ </div>
<h2>Tokens</h2>
<ul id="token_list"></ul>
diff --git a/js/manual_test_browser.js b/js/manual_test_browser.js
@@ -1,13 +1,36 @@
window.addEventListener('token', (e) => {
const li = document.createElement('li');
const a = document.createElement('a');
- a.setAttribute('onClick', 'viewToken("' + e.detail.tokenId + '")');
+ a.setAttribute('onClick', 'uiViewToken("' + e.detail.tokenId + '")');
li.id = 'token_' + e.detail.tokenId;
a.textContent = e.detail.tokenId;
li.appendChild(a);
document.getElementById('token_list').appendChild(li);
});
+window.addEventListener('tokenBatch', (e) => {
+ let currentTokenId = document.getElementById('token_id').innerHTML;
+ if (currentTokenId.substring(0, 2) == '0x') {
+ currentTokenId = currentTokenId.substring(2);
+ }
+ if (e.detail.tokenId != currentTokenId) {
+ throw 'batch event without matching token ' + tokenId + ' in view';
+ }
+ const li = document.createElement('li');
+ const span = document.createElement('span');
+ li.setAttribute('id', 'token_' + e.detail.tokenId + ' _batch_' + e.detail.batch);
+ span.innerHTML = 'used ' + e.detail.cursor + ' of ' + e.detail.count;
+ li.appendChild(span);
+ if (window.craftnft.isMintAvailable(e.detail.tokenId, e.detail.batch)) {
+ const a = document.createElement('a');
+ a.setAttribute('onClick', 'uiMintToken("' + e.detail.tokenId + '", ' + e.detail.batch + ')');
+ a.innerHTML = 'mint';
+ li.appendChild(a);
+ }
+ const batchList = document.getElementById('token_batches')
+ batchList.appendChild(li);
+});
+
async function generatePayload() {
let tokenData = {
@@ -47,20 +70,81 @@ async function generatePayload() {
window.dispatchEvent(tokenRequestEvent);
}
-async function viewToken(tokenId) {
+async function generateMint() {
+ const tokenId = document.getElementById('token_mint_id').innerHTML;
+ let batch = document.getElementById('token_mint_batch').innerHTML;
+ batch = parseInt(batch, 10);
+ const recipient = document.getElementById('token_mint_recipient').value;
+ window.craftnft.mintToken(session, tokenId, batch, recipient);
+ uiViewToken(tokenId);
+}
+
+async function uiMintToken(tokenId, batch) {
+ document.getElementById('token_mint_id').innerHTML = tokenId;
+ document.getElementById('token_mint_batch').innerHTML = batch;
+
+ document.getElementById('interactive').style.visibility = 'hidden';
+ document.getElementById('detail').style.visibility = 'hidden';
+ document.getElementById('mint').style.visibility = 'visible'
+}
+
+async function uiViewTokenSingle(tokenId) {
+ if (!await window.craftnft.isMintAvailable(session, tokenId, 0)) {
+ console.debug('token ' + tokenId + ' is already minted');
+ return;
+ }
+ const li = document.createElement('li');
+ li.setAttribute('id', 'token_' + tokenId + '_single');
+
+ let a = document.createElement('a');
+ a.setAttribute('onClick', 'uiMintToken("' + tokenId + '", ' + 0 + ')');
+ a.innerHTML = 'mint';
+ li.appendChild(a);
+
+ const batch = document.getElementById('token_batches');
+ batch.appendChild(li);
+
+}
+
+async function uiViewToken(tokenId) {
const r = await session.contentGateway.get(tokenId);
const tokenData = JSON.parse(r);
+ const batch_shit = document.getElementById('token_batches');
+ while (batch_shit.lastChild) {
+ batch_shit.removeChild(batch_shit.lastChild);
+ }
+
document.getElementById('token_id').innerHTML = tokenId;
document.getElementById('token_name').innerHTML = tokenData.name;
document.getElementById('token_description').innerHTML = tokenData.description;
+ window.craftnft.getBatches(session, tokenId, (batch, count, cursor) => {
+ if (batch == -1) {
+ uiViewTokenSingle(tokenId);
+ return;
+ }
+ const e = new CustomEvent('tokenBatch', {
+ detail: {
+ tokenId: tokenId,
+ batch: batch,
+ count: count,
+ cursor: cursor,
+ },
+ bubbles: true,
+ cancelable: true,
+ composed: false,
+ });
+ window.dispatchEvent(e);
+ });
document.getElementById('interactive').style.visibility = 'hidden';
document.getElementById('detail').style.visibility = 'visible';
+ document.getElementById('mint').style.visibility = 'hidden';
}
-async function listTokens() {
+async function uiCreateToken() {
document.getElementById('interactive').style.visibility = 'visible';
document.getElementById('detail').style.visibility = 'hidden';
+ document.getElementById('mint').style.visibility = 'hidden';
}
function run(w3, generated_session) {
@@ -69,11 +153,12 @@ function run(w3, generated_session) {
document.getElementById('data_account').innerHTML = session.account;
document.getElementById('data_contract').innerHTML = session.contractAddress;
document.getElementById('panel_submit').addEventListener('click', generatePayload);
+ document.getElementById('mint_submit').addEventListener('click', generateMint);
window.craftnft.getTokens(w3, session, (tokenId) => {
if (tokenId.substring(0, 2) == '0x') {
tokenId = tokenId.substring(2);
}
- const tokenEvent = new CustomEvent('token', {
+ const e = new CustomEvent('token', {
detail: {
tokenId: tokenId,
},
@@ -81,6 +166,6 @@ function run(w3, generated_session) {
cancelable: true,
composed: false,
});
- window.dispatchEvent(tokenEvent);
+ window.dispatchEvent(e);
});
}
diff --git a/js/src/common.js b/js/src/common.js
@@ -10,6 +10,13 @@ var session = {
window.addEventListener('load', async () => {
const provider = window.craftnft.loadProvider();
const conn = window.craftnft.loadConn(provider);
+ // none of the suggestions tried so far worked (accountsChanged on provider, update on conn.provider publicconfigstore ...
+// window.addEventListener('update', async (e) => {
+// const oldAccount = session.account;
+// const newAccount = await conn.eth.getAccounts();
+// session.account = newAccount[0];
+// console.log('account changed from ' + oldACcount + ' to ' + session.account);
+// });
let config = undefined;
let rs = await fetch('settings.json');
@@ -34,5 +41,6 @@ window.addEventListener('load', async () => {
});
window.addEventListener('tokenRequest', async(e) => {
- window.craftnft.allocateToken(session, e.detail.digest, e.detail.amount);
+ window.craftnft.allocateToken(session, e.detail.digest, e.detail.tokenData.amount);
});
+
diff --git a/js/src/engine.js b/js/src/engine.js
@@ -51,10 +51,56 @@ async function allocateToken(session, tokenId, amount) {
});
}
+async function mintToken(session, tokenId, batch, recipient) {
+ const w3 = new Web3();
+ const address = await w3.utils.toChecksumAddress(recipient);
+ console.log('address', address, recipient);
+ session.contract.methods.mintFromBatchTo(address, '0x' + tokenId, batch).send({
+ from: session.account,
+ value: 0,
+ });
+}
+
+async function isMintAvailable(session, tokenId, batch) {
+ let token = await session.contract.methods.token('0x' + tokenId, batch).call({from: session.account});
+ if (batch == 0) {
+ if (token.count == 0) {
+ return token.cursor == 0;
+ }
+ }
+ if (token.cursor < token.count) {
+ return true;
+ }
+ return false;
+}
+
+async function getBatches(session, tokenId, callback) {
+ let token = await session.contract.methods.token('0x' + tokenId, 0).call({from: session.account});
+ if (token.count == 0) {
+ callback(-1);
+ return;
+ }
+
+ callback(0, token.count, token.cursor);
+ let i = 1;
+ while (true) {
+ try {
+ token = await session.contract.methods.token('0x' + tokenId, 1).call({from: session.account});
+ } catch(e) {
+ break;
+ }
+ callback(i, token.count, token.cursor);
+ i++;
+ }
+}
+
module.exports = {
loadProvider: loadProvider,
loadConn: loadConn,
startSession: startSession,
getTokens: getTokens,
+ getBatches: getBatches,
allocateToken: allocateToken,
+ mintToken: mintToken,
+ isMintAvailable: isMintAvailable,
};