diff --git a/qortal-ui-core/src/components/start-minting.js b/qortal-ui-core/src/components/start-minting.js index 5fa35fe7..9d2bfd59 100644 --- a/qortal-ui-core/src/components/start-minting.js +++ b/qortal-ui-core/src/components/start-minting.js @@ -2,27 +2,193 @@ import { LitElement, html, css } from 'lit'; import { connect } from 'pwa-helpers'; import { store } from '../store.js'; import { translate, get } from 'lit-translate'; +import {asyncReplace} from 'lit/directives/async-replace.js'; import '../functional-components/my-button.js'; import { routes } from '../plugins/routes.js'; +import "@material/mwc-button" +import '@material/mwc-dialog' + + +async function* countDown(count, callback) { + + + while (count > 0) { + yield count--; + await new Promise((r) => setTimeout(r, 1000)); + if(count === 0){ + + callback() + } + } + } class StartMinting extends connect(store)(LitElement) { static get properties() { return { addressInfo: { type: Object }, mintingAccountData: { type: Array }, errorMsg: { type: String }, + openDialogRewardShare : {type: Boolean}, + status: {type: Number}, + timer: {type: Number}, + privateRewardShareKey: {type: String} }; } static get styles() { return [ css` + + .dialogCustom { + position: fixed; + z-index: 10000; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + top: 0px; + bottom: 0px; + + left: 0px; + width: 100vw; + } + .dialogCustomInner { + + width: 300px; + min-height: 400px; + background-color: var(--white); + box-shadow: var(--mdc-dialog-box-shadow, 0px 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12)); + padding: 20px 24px; + border-radius: 4px; + } + .dialogCustomInner ul { + padding-left: 0px + } + .dialogCustomInner li { + margin-bottom: 10px; + } .start-minting-wrapper { position: absolute; left: 50%; transform: translateX(calc(-50% - 10px)); + z-index: 10; } + + .dialog-header h1 { + font-size: 18px; + } + + .row { + display: flex; + width: 100%; + align-items: center; + } + + .modalFooter { + width: 100%; + display: flex; + justify-content: flex-end; + } + + + + + .hide { + visibility: hidden + } + + .inactiveText { + opacity: .60 + } + .column { + display: flex; + flex-direction: column; + width: 100%; + } + + .smallLoading, + .smallLoading:after { + border-radius: 50%; + width: 2px; + height: 2px; + } + + .smallLoading { + border-width: 0.6em; + border-style: solid; + border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) + rgba(3, 169, 244, 0.2) rgb(3, 169, 244); + font-size: 10px; + position: relative; + text-indent: -9999em; + transform: translateZ(0px); + animation: 1.1s linear 0s infinite normal none running loadingAnimation; + } + @-webkit-keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + @keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + .word-break { + word-break:break-all; + } + .dialog-container { + width: 300px; + min-height: 300px; + max-height: 75vh; + padding: 5px; + display: flex; + align-items: flex-start; + flex-direction: column; + + + } + + + .between { + justify-content: space-between; + } + .no-width { + width: auto + } + + .between p { + margin: 0; + padding: 0; + } + .marginLoader { + margin-left: 10px; + } + .marginRight { + margin-right: 10px; + } + .warning{ + display: flex; + flex-grow: 1 +} + +.message-error { + color: var(--error); + } + `, ]; } @@ -32,6 +198,9 @@ class StartMinting extends connect(store)(LitElement) { this.addressInfo = {}; this.mintingAccountData = []; this.errorMsg = ''; + this.openDialogRewardShare = false; + this.status = 0; + this.privateRewardShareKey = ""; } render() { @@ -40,6 +209,10 @@ class StartMinting extends connect(store)(LitElement) { firstUpdated() { this.getMintingAcccounts(); + + + + this.shadowRoot.querySelector('mdc-dialog--open').setAttribute('style', 'width: 100vw') } async getMintingAcccounts() { @@ -60,6 +233,103 @@ class StartMinting extends connect(store)(LitElement) { } } + async changeStatus(value){ + this.status = value + const publicAddress = + window.parent.reduxStore.getState().app?.selectedAddress + ?.base58PublicKey; + // Check to see if a sponsorship key on a newly-level 1 minter exists. If it does, remove it. + const findMintingAccountFromOtherUser = mintingAccountData.find( + (ma) => !ma.publicKey.includes(publicAddress) + ); + const removeMintingAccount = async (publicKey) => { + const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`; + + return await fetch(url, { + method: 'DELETE', + body: publicKey, + }); + }; + + const addMintingAccount = async (sponsorshipKeyValue) => { + const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`; + + return await fetch(url, { + method: 'POST', + body: sponsorshipKeyValue, + }); + }; + + try { + if ( + findMintingAccountFromOtherUser && + findMintingAccountFromOtherUser?.publicKey[0] + ) { + await removeMintingAccount( + findMintingAccountFromOtherUser?.publicKey[0] + ); + } + } catch (error) { + this.errorMsg = 'Failed to remove key'; + return; + } + + try { + await addMintingAccount(sponsorshipKeyValue); + routes.showSnackBar({ + data: translate('becomeMinterPage.bchange19'), + }); + this.status = 5; + this.getMintingAcccounts(); + } catch (error) { + this.errorMsg = 'Failed to add minting key'; + return; + } + + } + + + + async confirmRelationship(){ + let interval = null + let stop = false + this.status = 2 + const getAnswer = async () => { + + const rewardShares = async (minterAddr) => { + const url = `${nodeUrl}/addresses/rewardshares?minters=${minterAddr}&recipients=${minterAddr}`; + const res = await fetch(url); + const data = await res.json(); + return data; + }; + + if (!stop) { + stop= true; + + try { + + const address = + window.parent.reduxStore.getState().app?.selectedAddress?.address; + + const myRewardShareArray = await rewardShares(address); + if(myRewardShareArray.length > 0){ + clearInterval(interval) + this.status = 3 + + + this.timer = countDown(180, ()=> this.changeStatus(4)); + } + + } catch (error) { + + } + + stop = false + } + }; + interval = setInterval(getAnswer, 2000); + } + renderStartMintingButton() { const myNode = store.getState().app.nodeConfig.knownNodes[ @@ -70,12 +340,7 @@ class StartMinting extends connect(store)(LitElement) { const mintingAccountData = this.mintingAccountData; const addressInfo = this.addressInfo; - const rewardShares = async (minterAddr) => { - const url = `${nodeUrl}/addresses/rewardshares?minters=${minterAddr}&recipients=${minterAddr}`; - const res = await fetch(url); - const data = await res.json(); - return data; - }; + const address = window.parent.reduxStore.getState().app?.selectedAddress?.address; const nonce = @@ -92,14 +357,7 @@ class StartMinting extends connect(store)(LitElement) { addressInfo?.level === 1 && !findMintingAccount; - const removeMintingAccount = async (publicKey) => { - const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`; - - return await fetch(url, { - method: 'DELETE', - body: publicKey, - }); - }; + const makeTransactionRequest = async (lastRef) => { let mylastRef = lastRef; @@ -128,8 +386,12 @@ class StartMinting extends connect(store)(LitElement) { }; const getTxnRequestResponse = (txnResponse) => { + + if(txnResponse?.message?.includes('multiple')){ + return err6string + } if (txnResponse.success === false && txnResponse.message) { - throw new Error(txnResponse); + throw(txnResponse); } else if ( txnResponse.success === true && !txnResponse.data.error @@ -137,11 +399,12 @@ class StartMinting extends connect(store)(LitElement) { let err6string = get('rewardsharepage.rchange21'); return err6string; } else { - throw new Error(txnResponse); + throw(txnResponse); } }; const createSponsorshipKey = async () => { + this.status= 1 let lastRef = await getLastRef(); let myTransaction = await makeTransactionRequest(lastRef); @@ -149,14 +412,7 @@ class StartMinting extends connect(store)(LitElement) { getTxnRequestResponse(myTransaction); return myTransaction.data; }; - const addMintingAccount = async (sponsorshipKeyValue) => { - const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`; - - return await fetch(url, { - method: 'POST', - body: sponsorshipKeyValue, - }); - }; + const getLastRef = async () => { const url = `${nodeUrl}/addresses/lastreference/${address}`; @@ -167,64 +423,23 @@ class StartMinting extends connect(store)(LitElement) { return data; }; + const startMinting = async () => { + this.openDialogRewardShare = true + this.errorMsg = ''; - let rewardSharesList; + try { - rewardSharesList = await rewardShares(address); + + this.privateRewardShareKey = await createSponsorshipKey(); + this.confirmRelationship() } catch (error) { - this.errorMsg = 'Cannot fetch reward shares'; - return; - } - // check to see if self-share exists - - const findRewardShareData = rewardSharesList.find( - (rs) => - rs?.mintingAccount === address && rs?.recipient === address - ); - let sponsorshipKeyValue = null; - try { - if (!findRewardShareData) { - // if no self-share exits, create one. - sponsorshipKeyValue = await createSponsorshipKey(); - } else { - sponsorshipKeyValue = - findRewardShareData.rewardSharePublicKey; - } - } catch (error) { - this.errorMsg = 'Cannot create sponsorship key'; + console.log({error}) + this.errorMsg = error?.data?.message || 'Cannot create sponsorship key'; return; } - // Check to see if a sponsorship key on a newly-level 1 minter exists. If it does, remove it. - const findMintingAccountFromOtherUser = mintingAccountData.find( - (ma) => !ma.publicKey.includes(publicAddress) - ); - - try { - if ( - findMintingAccountFromOtherUser && - findMintingAccountFromOtherUser?.publicKey[0] - ) { - await removeMintingAccount( - findMintingAccountFromOtherUser?.publicKey[0] - ); - } - } catch (error) { - this.errorMsg = 'Failed to remove key'; - return; - } - - try { - await addMintingAccount(sponsorshipKeyValue); - routes.showSnackBar({ - data: translate('becomeMinterPage.bchange19'), - }); - this.getMintingAcccounts(); - } catch (error) { - this.errorMsg = 'Failed to add minting key'; - return; - } + }; return html` @@ -246,6 +461,93 @@ class StartMinting extends connect(store)(LitElement) { }} > + + + + + + ${this.openDialogRewardShare ? html` +
+ 2. Awaiting confirmation on blockchain +
+ + ++ 3. Finishing up relationship +
+ ++ 4. Adding minting key to node +
+ + ++ 5. Complete +
+ + ++ Warning: do not close the Qortal UI until completion! +
+ +