Merge pull request #50 from PhillipLangMartinez/Feature/become-minter

Added new plugin - Become a minter
This commit is contained in:
AlphaX-Projects 2022-08-11 09:00:28 +02:00 committed by GitHub
commit 2840a9dd89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2408 additions and 1156 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,159 +1,270 @@
import { LitElement, html, css } from 'lit' import { LitElement, html, css } from 'lit';
import { connect } from 'pwa-helpers' import { connect } from 'pwa-helpers';
import { store } from '../store.js' import { store } from '../store.js';
import { translate, translateUnsafeHTML } from 'lit-translate' import { translate, translateUnsafeHTML } from 'lit-translate';
import '@polymer/paper-ripple' import '@polymer/paper-ripple';
import '@vaadin/icon' import '@vaadin/icon';
import '@vaadin/icons' import '@vaadin/icons';
import '../functional-components/side-menu.js'
import '../functional-components/side-menu-item.js'
import '../functional-components/side-menu.js';
import '../functional-components/side-menu-item.js';
import '../functional-components/my-button.js';
import './start-minting';
class SidenavMenu extends connect(store)(LitElement) { class SidenavMenu extends connect(store)(LitElement) {
static get properties() { static get properties() {
return { return {
config: { type: Object }, config: { type: Object },
urls: { type: Object }, urls: { type: Object },
nodeType: { type: String, reflect: true }, nodeType: { type: String, reflect: true },
theme: { type: String, reflect: true } theme: { type: String, reflect: true },
} addressInfo: { type: Object },
} };
}
static get styles() { static get styles() {
return [ return [
css` css`
* { * {
--item-selected-color: var(--nav-selected-color); --item-selected-color: var(--nav-selected-color);
--item-selected-color-text: var(--nav-selected-color-text); --item-selected-color-text: var(--nav-selected-color-text);
--item-color-active: var(--nav-color-active); --item-color-active: var(--nav-color-active);
--item-color-hover: var(--nav-color-hover); --item-color-hover: var(--nav-color-hover);
--item-text-color: var(--nav-text-color); --item-text-color: var(--nav-text-color);
--item-icon-color: var(--nav-icon-color); --item-icon-color: var(--nav-icon-color);
--item-border-color: var(--nav-border-color); --item-border-color: var(--nav-border-color);
--item-border-selected-color: var(--nav-border-selected-color); --item-border-selected-color: var(
} --nav-border-selected-color
);
}
.s-menu { .s-menu {
list-style: none; list-style: none;
padding: 0px 0px; padding: 0px 0px;
background: var(--sidetopbar); background: var(--sidetopbar);
border-radius: 2px; border-radius: 2px;
width: 100%; width: 100%;
border-top: 1px solid var(--border); border-top: 1px solid var(--border);
outline: none; outline: none;
} }
`
]
}
constructor() { .start-minting-wrapper {
super() position: absolute;
this.urls = [] bottom: 130px;
this.nodeType = '' left: 50%;
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' transform: translateX(calc(-50% - 10px));
} }
`,
];
}
render() { constructor() {
return html` super();
<div class="s-menu"> this.urls = [];
<side-menu> this.nodeType = '';
${this.renderNodeTypeMenu()} this.theme = localStorage.getItem('qortalTheme')
${this.renderNodeManagement()} ? localStorage.getItem('qortalTheme')
</side-menu> : 'light';
</div> this.addressInfo = {};
` }
}
firstUpdated() { render() {
this.getNodeType() return html`
} <div class="s-menu">
<side-menu>
${this.renderNodeTypeMenu()} ${this.renderNodeManagement()}
</side-menu>
</div>
async getNodeType() { <start-minting></start-minting>
const myNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node] `;
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port }
const url = `${nodeUrl}/admin/info`
await fetch(url)
.then(response => {
return response.json()
})
.then(data => {
this.nodeType = data.type
})
.catch(err => {
console.error('Request failed', err);
})
}
renderNodeTypeMenu() { firstUpdated() {
if (this.nodeType === 'lite') { this.getNodeType();
return html` }
<side-menu-item label="${translate("sidemenu.wallets")}" href="/app/wallet" selected>
<vaadin-icon icon="vaadin:wallet" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.nameregistration")}" href="/app/name-registration">
<vaadin-icon icon="vaadin:user-check" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.datamanagement")}" href="/app/data-management">
<vaadin-icon icon="vaadin:database" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.qchat")}" href="/app/q-chat">
<vaadin-icon icon="vaadin:chat" slot="icon"></vaadin-icon>
</side-menu-item>
`
} else {
return html`
<side-menu-item label="${translate("sidemenu.mintingdetails")}" href="/app/minting">
<vaadin-icon icon="vaadin:info-circle" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.wallets")}" href="/app/wallet" selected>
<vaadin-icon icon="vaadin:wallet" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.tradeportal")}" href="/app/trade-portal">
<vaadin-icon icon="vaadin:bullets" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.rewardshare")}" href="/app/reward-share">
<vaadin-icon icon="vaadin:share-square" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.nameregistration")}" href="/app/name-registration">
<vaadin-icon icon="vaadin:user-check" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.websites")}" href="/app/websites">
<vaadin-icon icon="vaadin:desktop" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.datamanagement")}" href="/app/data-management">
<vaadin-icon icon="vaadin:database" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.qchat")}" href="/app/q-chat">
<vaadin-icon icon="vaadin:chat" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.groupmanagement")}" href="/app/group-management">
<vaadin-icon icon="vaadin:group" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item label="${translate("sidemenu.puzzles")}" href="/app/puzzles">
<vaadin-icon icon="vaadin:puzzle-piece" slot="icon"></vaadin-icon>
</side-menu-item>
`
}
}
renderNodeManagement() { async getNodeType() {
const checkNodeManagement = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node] const myNode =
if (checkNodeManagement.enableManagement = true) { store.getState().app.nodeConfig.knownNodes[
return html` store.getState().app.nodeConfig.node
<side-menu-item label="${translate("sidemenu.nodemanagement")}" href="/app/node-management"> ];
<vaadin-icon icon="vaadin:cloud" slot="icon"></vaadin-icon> const nodeUrl =
</side-menu-item> myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
` const url = `${nodeUrl}/admin/info`;
} else { await fetch(url)
return html`` .then((response) => {
} return response.json();
} })
.then((data) => {
this.nodeType = data.type;
})
.catch((err) => {
console.error('Request failed', err);
});
}
stateChanged(state) { renderNodeTypeMenu() {
this.config = state.config const addressInfo = this.addressInfo;
this.urls = state.app.registeredUrls const isMinter = addressInfo?.error !== 124 && +addressInfo?.level > 0;
}
if (this.nodeType === 'lite') {
return html`
<side-menu-item
label="${translate('sidemenu.wallets')}"
href="/app/wallet"
selected
>
<vaadin-icon icon="vaadin:wallet" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.nameregistration')}"
href="/app/name-registration"
>
<vaadin-icon
icon="vaadin:user-check"
slot="icon"
></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.datamanagement')}"
href="/app/data-management"
>
<vaadin-icon
icon="vaadin:database"
slot="icon"
></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.qchat')}"
href="/app/q-chat"
>
<vaadin-icon icon="vaadin:chat" slot="icon"></vaadin-icon>
</side-menu-item>
`;
} else {
return html`
${isMinter
? html`<side-menu-item
label="${translate('sidemenu.mintingdetails')}"
href="/app/minting"
>
<vaadin-icon
icon="vaadin:info-circle"
slot="icon"
></vaadin-icon>
</side-menu-item>`
: html`<side-menu-item
label="${translate('sidemenu.becomeAMinter')}"
href="/app/become-minter"
>
<vaadin-icon
icon="vaadin:info-circle"
slot="icon"
></vaadin-icon>
</side-menu-item>`}
<side-menu-item
label="${translate('sidemenu.wallets')}"
href="/app/wallet"
selected
>
<vaadin-icon icon="vaadin:wallet" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.tradeportal')}"
href="/app/trade-portal"
>
<vaadin-icon
icon="vaadin:bullets"
slot="icon"
></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.rewardshare')}"
href="/app/reward-share"
>
<vaadin-icon
icon="vaadin:share-square"
slot="icon"
></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.nameregistration')}"
href="/app/name-registration"
>
<vaadin-icon
icon="vaadin:user-check"
slot="icon"
></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.websites')}"
href="/app/websites"
>
<vaadin-icon
icon="vaadin:desktop"
slot="icon"
></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.datamanagement')}"
href="/app/data-management"
>
<vaadin-icon
icon="vaadin:database"
slot="icon"
></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.qchat')}"
href="/app/q-chat"
>
<vaadin-icon icon="vaadin:chat" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.groupmanagement')}"
href="/app/group-management"
>
<vaadin-icon icon="vaadin:group" slot="icon"></vaadin-icon>
</side-menu-item>
<side-menu-item
label="${translate('sidemenu.puzzles')}"
href="/app/puzzles"
>
<vaadin-icon
icon="vaadin:puzzle-piece"
slot="icon"
></vaadin-icon>
</side-menu-item>
`;
}
}
renderNodeManagement() {
const checkNodeManagement =
store.getState().app.nodeConfig.knownNodes[
store.getState().app.nodeConfig.node
];
if ((checkNodeManagement.enableManagement = true)) {
return html`
<side-menu-item
label="${translate('sidemenu.nodemanagement')}"
href="/app/node-management"
>
<vaadin-icon icon="vaadin:cloud" slot="icon"></vaadin-icon>
</side-menu-item>
`;
} else {
return html``;
}
}
stateChanged(state) {
this.config = state.config;
this.urls = state.app.registeredUrls;
this.addressInfo = state.app.accountInfo.addressInfo;
}
} }
window.customElements.define('sidenav-menu', SidenavMenu) window.customElements.define('sidenav-menu', SidenavMenu);

View File

@ -0,0 +1,261 @@
import { LitElement, html, css } from 'lit';
import { connect } from 'pwa-helpers';
import { store } from '../store.js';
import { translate, get } from 'lit-translate';
import '../functional-components/my-button.js';
import { routes } from '../plugins/routes.js';
class StartMinting extends connect(store)(LitElement) {
static get properties() {
return {
addressInfo: { type: Object },
mintingAccountData: { type: Array },
errorMsg: { type: String },
};
}
static get styles() {
return [
css`
.start-minting-wrapper {
position: absolute;
bottom: 130px;
left: 50%;
transform: translateX(calc(-50% - 10px));
}
`,
];
}
constructor() {
super();
this.addressInfo = {};
this.mintingAccountData = [];
this.errorMsg = '';
}
render() {
return html` ${this.renderStartMintingButton()} `;
}
firstUpdated() {
this.getMintingAcccounts();
}
async getMintingAcccounts() {
const myNode =
store.getState().app.nodeConfig.knownNodes[
store.getState().app.nodeConfig.node
];
const nodeUrl =
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
const url = `${nodeUrl}/admin/mintingaccounts`;
try {
const res = await fetch(url);
const mintingAccountData = await res.json();
this.mintingAccountData = mintingAccountData;
} catch (error) {
this.errorMsg = 'Cannot fetch minting accounts';
}
}
renderStartMintingButton() {
const myNode =
store.getState().app.nodeConfig.knownNodes[
store.getState().app.nodeConfig.node
];
const nodeUrl =
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
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 =
window.parent.reduxStore.getState().app?.selectedAddress?.nonce;
const publicAddress =
window.parent.reduxStore.getState().app?.selectedAddress
?.base58PublicKey;
const findMintingAccount = mintingAccountData.find((ma) =>
ma.publicKey.includes(publicAddress)
);
const isMinterButKeyMintingKeyNotAssigned =
addressInfo?.error !== 124 &&
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;
let rewarddialog1 = get('transactions.rewarddialog1');
let rewarddialog2 = get('transactions.rewarddialog2');
let rewarddialog3 = get('transactions.rewarddialog3');
let rewarddialog4 = get('transactions.rewarddialog4');
let myTxnrequest = await routes.transaction({
data: {
type: 38,
nonce: nonce,
params: {
recipientPublicKey: publicAddress,
percentageShare: 0,
lastReference: mylastRef,
rewarddialog1: rewarddialog1,
rewarddialog2: rewarddialog2,
rewarddialog3: rewarddialog3,
rewarddialog4: rewarddialog4,
},
},
disableModal: true,
});
return myTxnrequest;
};
const getTxnRequestResponse = (txnResponse) => {
if (txnResponse.success === false && txnResponse.message) {
throw new Error(txnResponse);
} else if (
txnResponse.success === true &&
!txnResponse.data.error
) {
let err6string = get('rewardsharepage.rchange21');
return err6string;
} else {
throw new Error(txnResponse);
}
};
const createSponsorshipKey = async () => {
let lastRef = await getLastRef();
let myTransaction = await makeTransactionRequest(lastRef);
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}`;
const res = await fetch(url);
const data = await res.text();
return data;
};
const startMinting = async () => {
this.errorMsg = '';
let rewardSharesList;
try {
rewardSharesList = await rewardShares(address);
} 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';
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`
${isMinterButKeyMintingKeyNotAssigned
? html`
<div class="start-minting-wrapper">
<my-button
label="${translate(
'becomeMinterPage.bchange18'
)}"
?isLoading=${false}
.onClick=${async () => {
await startMinting();
if (this.errorMsg) {
routes.showSnackBar({
data: this.errorMsg,
});
}
}}
></my-button>
</div>
`
: ''}
`;
}
stateChanged(state) {
this.addressInfo = state.app.accountInfo.addressInfo;
}
}
window.customElements.define('start-minting', StartMinting);

View File

@ -0,0 +1,48 @@
import { LitElement, html, css } from 'lit';
import '@vaadin/button';
import '@polymer/paper-spinner/paper-spinner-lite.js';
export class MyButton extends LitElement {
static properties = {
onClick: { type: Function },
isLoading: { type: Boolean },
label: { type: String },
};
static styles = css`
vaadin-button {
height: 100%;
margin: 0;
cursor: pointer;
min-width: 80px;
background-color: #03a9f4;
color: white;
}
vaadin-button:hover {
opacity: 0.8;
}
`;
constructor() {
super();
this.onClick = () => {};
this.isLoading = false;
this.label = '';
}
render() {
return html`
<vaadin-button
?disabled="${this.isLoading}"
@click="${this.onClick}"
>
${this.isLoading === false
? html`${this.label}`
: html`<paper-spinner-lite active></paper-spinner-lite>`}
</vaadin-button>
`;
}
}
customElements.define('my-button', MyButton);

View File

@ -1,83 +1,95 @@
import { store } from '../store.js' import { store } from '../store.js';
import { doAddPluginUrl, doUpdateBlockInfo, doUpdateNodeStatus, doUpdateNodeInfo, doSetNode, doPageUrl, doSetChatHeads, doUpdateAccountInfo } from '../redux/app/app-actions.js' import {
import * as api from 'qortal-ui-crypto' doAddPluginUrl,
import { requestTransactionDialog } from '../functional-components/confirm-transaction-dialog.js' doUpdateBlockInfo,
import { doNewMessage } from '../notifications/controller.js' doUpdateNodeStatus,
import snackbar from '../functional-components/snackbar.js' doUpdateNodeInfo,
import { loadStateFromLocalStorage, saveStateToLocalStorage } from '../localStorageHelpers.js' doSetNode,
import copyTextMenu from '../functional-components/copy-text-menu.js' doPageUrl,
import framePasteMenu from '../functional-components/frame-paste-menu.js' doSetChatHeads,
doUpdateAccountInfo,
} from '../redux/app/app-actions.js';
import * as api from 'qortal-ui-crypto';
import { requestTransactionDialog } from '../functional-components/confirm-transaction-dialog.js';
import { doNewMessage } from '../notifications/controller.js';
import snackbar from '../functional-components/snackbar.js';
import {
loadStateFromLocalStorage,
saveStateToLocalStorage,
} from '../localStorageHelpers.js';
import copyTextMenu from '../functional-components/copy-text-menu.js';
import framePasteMenu from '../functional-components/frame-paste-menu.js';
const createTransaction = api.createTransaction const createTransaction = api.createTransaction;
const processTransaction = api.processTransaction const processTransaction = api.processTransaction;
const signChatTransaction = api.signChatTransaction const signChatTransaction = api.signChatTransaction;
const signArbitraryTransaction = api.signArbitraryTransaction const signArbitraryTransaction = api.signArbitraryTransaction;
const tradeBotCreateRequest = api.tradeBotCreateRequest const tradeBotCreateRequest = api.tradeBotCreateRequest;
const tradeBotRespondRequest = api.tradeBotRespondRequest const tradeBotRespondRequest = api.tradeBotRespondRequest;
const signTradeBotTxn = api.signTradeBotTxn const signTradeBotTxn = api.signTradeBotTxn;
const deleteTradeOffer = api.deleteTradeOffer const deleteTradeOffer = api.deleteTradeOffer;
const cancelAllOffers = api.cancelAllOffers const cancelAllOffers = api.cancelAllOffers;
const sendBtc = api.sendBtc const sendBtc = api.sendBtc;
const sendLtc = api.sendLtc const sendLtc = api.sendLtc;
const sendDoge = api.sendDoge const sendDoge = api.sendDoge;
const sendDgb = api.sendDgb const sendDgb = api.sendDgb;
const sendRvn = api.sendRvn const sendRvn = api.sendRvn;
export const routes = { export const routes = {
hello: async (req) => { hello: async (req) => {
return 'Hello from awesomeness' return 'Hello from awesomeness';
}, },
registerUrl: async (req) => { registerUrl: async (req) => {
store.dispatch(doAddPluginUrl(req.data)) store.dispatch(doAddPluginUrl(req.data));
}, },
setAccountInfo: async (req) => { setAccountInfo: async (req) => {
store.dispatch(doUpdateAccountInfo(req.data)) store.dispatch(doUpdateAccountInfo(req.data));
}, },
getAccountInfo: async (req) => { getAccountInfo: async (req) => {
return store.getState().app.accountInfo return store.getState().app.accountInfo;
}, },
setChatHeads: async (req) => { setChatHeads: async (req) => {
return store.dispatch(doSetChatHeads(req.data)) return store.dispatch(doSetChatHeads(req.data));
}, },
getChatHeads: async (req) => { getChatHeads: async (req) => {
return store.getState().app.chatHeads return store.getState().app.chatHeads;
}, },
updateBlockInfo: async (req) => { updateBlockInfo: async (req) => {
store.dispatch(doUpdateBlockInfo(req.data)) store.dispatch(doUpdateBlockInfo(req.data));
}, },
updateNodeStatus: async (req) => { updateNodeStatus: async (req) => {
store.dispatch(doUpdateNodeStatus(req.data)) store.dispatch(doUpdateNodeStatus(req.data));
}, },
updateNodeInfo: async (req) => { updateNodeInfo: async (req) => {
store.dispatch(doUpdateNodeInfo(req.data)) store.dispatch(doUpdateNodeInfo(req.data));
}, },
setNode: async (req) => { setNode: async (req) => {
store.dispatch(doSetNode(req.data)) store.dispatch(doSetNode(req.data));
}, },
getNodeConfig: async (req) => { getNodeConfig: async (req) => {
return store.getState().app.nodeConfig return store.getState().app.nodeConfig;
}, },
setPageUrl: async (req) => { setPageUrl: async (req) => {
return store.dispatch(doPageUrl(req.data)) return store.dispatch(doPageUrl(req.data));
}, },
getLocalStorage: async (req) => { getLocalStorage: async (req) => {
return loadStateFromLocalStorage(req.data) return loadStateFromLocalStorage(req.data);
}, },
setLocalStorage: async (req) => { setLocalStorage: async (req) => {
return saveStateToLocalStorage(req.data.key, req.data.dataObj) return saveStateToLocalStorage(req.data.key, req.data.dataObj);
}, },
openCopyTextMenu: async (req) => { openCopyTextMenu: async (req) => {
@ -85,26 +97,26 @@ export const routes = {
selectedText: req.data.selectedText, selectedText: req.data.selectedText,
eventObject: req.data.eventObject, eventObject: req.data.eventObject,
isFrame: req.data.isFrame, isFrame: req.data.isFrame,
} };
copyTextMenu.open(textMenuObject) copyTextMenu.open(textMenuObject);
}, },
closeCopyTextMenu: async (req) => { closeCopyTextMenu: async (req) => {
copyTextMenu.close() copyTextMenu.close();
}, },
openFramePasteMenu: async (req) => { openFramePasteMenu: async (req) => {
framePasteMenu.open(req.data) framePasteMenu.open(req.data);
}, },
closeFramePasteMenu: async (req) => { closeFramePasteMenu: async (req) => {
framePasteMenu.close() framePasteMenu.close();
}, },
apiCall: async (req) => { apiCall: async (req) => {
const url = req.data.url const url = req.data.url;
delete req.data.url delete req.data.url;
return api.request(url, req.data) return api.request(url, req.data);
}, },
addresses: async (req) => { addresses: async (req) => {
@ -115,250 +127,288 @@ export const routes = {
nonce: address.nonce, nonce: address.nonce,
textColor: address.textColor, textColor: address.textColor,
base58PublicKey: address.base58PublicKey, base58PublicKey: address.base58PublicKey,
} };
}) });
}, },
transaction: async (req) => { transaction: async (req) => {
let response let response;
try { try {
const tx = createTransaction(req.data.type, store.getState().app.wallet._addresses[req.data.nonce].keyPair, req.data.params) const tx = createTransaction(
await requestTransactionDialog.requestTransaction(tx) req.data.type,
const res = await processTransaction(tx.signedBytes) store.getState().app.wallet._addresses[req.data.nonce].keyPair,
req.data.params
);
if (!req.disableModal) {
await requestTransactionDialog.requestTransaction(tx);
}
const res = await processTransaction(tx.signedBytes);
response = { response = {
success: true, success: true,
data: res, data: res,
} };
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = { response = {
success: false, success: false,
message: e.message, message: e.message,
} };
} }
return response return response;
}, },
standaloneTransaction: async (req) => { standaloneTransaction: async (req) => {
const rebuildUint8Array = (obj) => { const rebuildUint8Array = (obj) => {
let _array = new Uint8Array(Object.keys(obj).length) let _array = new Uint8Array(Object.keys(obj).length);
for (let i = 0; i < _array.byteLength; ++i) { for (let i = 0; i < _array.byteLength; ++i) {
_array.set([obj[i]], i) _array.set([obj[i]], i);
} }
return _array return _array;
} };
let response let response;
try { try {
// req.data.keyPair unfortunately "prepared" into horrible object so we need to convert back // req.data.keyPair unfortunately "prepared" into horrible object so we need to convert back
let _keyPair = {}; let _keyPair = {};
for (let _keyName in req.data.keyPair) { for (let _keyName in req.data.keyPair) {
_keyPair[_keyName] = rebuildUint8Array(req.data.keyPair[_keyName]) _keyPair[_keyName] = rebuildUint8Array(
req.data.keyPair[_keyName]
);
} }
const tx = createTransaction(req.data.type, _keyPair, req.data.params) const tx = createTransaction(
const res = await processTransaction(tx.signedBytes) req.data.type,
_keyPair,
req.data.params
);
const res = await processTransaction(tx.signedBytes);
response = { response = {
success: true, success: true,
data: res, data: res,
} };
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = { response = {
success: false, success: false,
message: e.message, message: e.message,
} };
} }
return response return response;
}, },
username: async (req) => { username: async (req) => {
const state = store.getState() const state = store.getState();
const username = state.user.storedWallets[state.app.wallet.addresses[0].address].name const username =
state.user.storedWallets[state.app.wallet.addresses[0].address]
.name;
return username return username;
}, },
chat: async (req) => { chat: async (req) => {
let response let response;
try { try {
const tx = createTransaction(req.data.type, store.getState().app.wallet._addresses[req.data.nonce].keyPair, req.data.params) const tx = createTransaction(
req.data.type,
store.getState().app.wallet._addresses[req.data.nonce].keyPair,
req.data.params
);
response = tx.chatBytes response = tx.chatBytes;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = false response = false;
} }
return response return response;
}, },
sign_chat: async (req) => { sign_chat: async (req) => {
let response let response;
try { try {
const signedChatBytes = await signChatTransaction(req.data.chatBytesArray, req.data.chatNonce, store.getState().app.wallet._addresses[req.data.nonce].keyPair) const signedChatBytes = await signChatTransaction(
req.data.chatBytesArray,
req.data.chatNonce,
store.getState().app.wallet._addresses[req.data.nonce].keyPair
);
const res = await processTransaction(signedChatBytes) const res = await processTransaction(signedChatBytes);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = false response = false;
} }
return response return response;
}, },
sign_arbitrary: async (req) => { sign_arbitrary: async (req) => {
let response let response;
try { try {
const signedArbitraryBytes = await signArbitraryTransaction(req.data.arbitraryBytesBase58, req.data.arbitraryBytesForSigningBase58, req.data.arbitraryNonce, store.getState().app.wallet._addresses[req.data.nonce].keyPair) const signedArbitraryBytes = await signArbitraryTransaction(
req.data.arbitraryBytesBase58,
req.data.arbitraryBytesForSigningBase58,
req.data.arbitraryNonce,
store.getState().app.wallet._addresses[req.data.nonce].keyPair
);
const res = await processTransaction(signedArbitraryBytes) const res = await processTransaction(signedArbitraryBytes);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = false response = false;
} }
return response return response;
}, },
showNotification: async (req) => { showNotification: async (req) => {
doNewMessage(req.data) doNewMessage(req.data);
}, },
showSnackBar: async (req) => { showSnackBar: async (req) => {
snackbar.add({ snackbar.add({
labelText: req.data, labelText: req.data,
dismiss: true, dismiss: true,
}) });
}, },
tradeBotCreateRequest: async (req) => { tradeBotCreateRequest: async (req) => {
let response let response;
try { try {
const unsignedTxn = await tradeBotCreateRequest(req.data) const unsignedTxn = await tradeBotCreateRequest(req.data);
const signedTxnBytes = await signTradeBotTxn(unsignedTxn, store.getState().app.selectedAddress.keyPair) const signedTxnBytes = await signTradeBotTxn(
unsignedTxn,
store.getState().app.selectedAddress.keyPair
);
const res = await processTransaction(signedTxnBytes) const res = await processTransaction(signedTxnBytes);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
tradeBotRespondRequest: async (req) => { tradeBotRespondRequest: async (req) => {
let response let response;
try { try {
const res = await tradeBotRespondRequest(req.data) const res = await tradeBotRespondRequest(req.data);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
deleteTradeOffer: async (req) => { deleteTradeOffer: async (req) => {
let response let response;
try { try {
const unsignedTxn = await deleteTradeOffer(req.data) const unsignedTxn = await deleteTradeOffer(req.data);
const signedTxnBytes = await signTradeBotTxn(unsignedTxn, store.getState().app.selectedAddress.keyPair) const signedTxnBytes = await signTradeBotTxn(
unsignedTxn,
store.getState().app.selectedAddress.keyPair
);
const res = await processTransaction(signedTxnBytes) const res = await processTransaction(signedTxnBytes);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
cancelAllOffers: async (req) => { cancelAllOffers: async (req) => {
let response let response;
try { try {
const res = await cancelAllOffers(store.getState().app.selectedAddress) const res = await cancelAllOffers(
response = res store.getState().app.selectedAddress
);
response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
sendBtc: async (req) => { sendBtc: async (req) => {
let response let response;
try { try {
const res = await sendBtc(req.data) const res = await sendBtc(req.data);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
sendLtc: async (req) => { sendLtc: async (req) => {
let response let response;
try { try {
const res = await sendLtc(req.data) const res = await sendLtc(req.data);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
sendDoge: async (req) => { sendDoge: async (req) => {
let response let response;
try { try {
const res = await sendDoge(req.data) const res = await sendDoge(req.data);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
sendDgb: async (req) => { sendDgb: async (req) => {
let response let response;
try { try {
const res = await sendDgb(req.data) const res = await sendDgb(req.data);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
sendRvn: async (req) => { sendRvn: async (req) => {
let response let response;
try { try {
const res = await sendRvn(req.data) const res = await sendRvn(req.data);
response = res response = res;
} catch (e) { } catch (e) {
console.error(e) console.error(e);
console.error(e.message) console.error(e.message);
response = e.message response = e.message;
} }
return response return response;
}, },
} };

View File

@ -1,137 +1,141 @@
require('events').EventEmitter.defaultMaxListeners = 0 require('events').EventEmitter.defaultMaxListeners = 0;
const path = require("path"); const path = require('path');
const { nodeResolve } = require("@rollup/plugin-node-resolve"); const { nodeResolve } = require('@rollup/plugin-node-resolve');
const progress = require("rollup-plugin-progress"); const progress = require('rollup-plugin-progress');
const replace = require('@rollup/plugin-replace'); const replace = require('@rollup/plugin-replace');
const globals = require("rollup-plugin-node-globals"); const globals = require('rollup-plugin-node-globals');
const commonjs = require("@rollup/plugin-commonjs"); const commonjs = require('@rollup/plugin-commonjs');
const alias = require("@rollup/plugin-alias"); const alias = require('@rollup/plugin-alias');
const { terser } = require('rollup-plugin-terser'); const { terser } = require('rollup-plugin-terser');
const babel = require("@rollup/plugin-babel"); const babel = require('@rollup/plugin-babel');
const aliases = {}; const aliases = {};
const generateRollupConfig = (inputFile, outputFile) => { const generateRollupConfig = (inputFile, outputFile) => {
return { return {
inputOptions: { inputOptions: {
onwarn: (warning, rollupWarn) => { onwarn: (warning, rollupWarn) => {
if (warning.code !== 'CIRCULAR_DEPENDENCY') { if (warning.code !== 'CIRCULAR_DEPENDENCY') {
rollupWarn(warning) rollupWarn(warning);
} }
}, },
input: inputFile, input: inputFile,
plugins: [ plugins: [
alias({ alias({
entries: Object.keys(aliases).map((find) => { entries: Object.keys(aliases).map((find) => {
return { return {
find, find,
replacement: aliases[find], replacement: aliases[find],
}; };
}), }),
}), }),
nodeResolve({ nodeResolve({
preferBuiltins: false, preferBuiltins: false,
mainFields: ['module', 'browser'] mainFields: ['module', 'browser'],
}), }),
replace({ replace({
preventAssignment: true, preventAssignment: true,
"process.env.NODE_ENV": JSON.stringify("production"), 'process.env.NODE_ENV': JSON.stringify('production'),
}), }),
commonjs(), commonjs(),
globals(), globals(),
progress(), progress(),
babel.babel({ babel.babel({
babelHelpers: 'bundled', babelHelpers: 'bundled',
exclude: "node_modules/**", exclude: 'node_modules/**',
}), }),
terser({ terser({
compress: true, compress: true,
output: { output: {
comments: false, comments: false,
}, },
}) }),
], ],
}, },
outputOptions: { outputOptions: {
file: outputFile, file: outputFile,
format: "umd", format: 'umd',
}, },
}; };
}; };
const generateForPlugins = () => { const generateForPlugins = () => {
const configs = [ const configs = [
{ {
in: "plugins/core/main.src.js", in: 'plugins/core/main.src.js',
out: "plugins/core/main.js", out: 'plugins/core/main.js',
}, },
{ {
in: "plugins/core/trade-portal/trade-portal.src.js", in: 'plugins/core/trade-portal/trade-portal.src.js',
out: "plugins/core/trade-portal/trade-portal.js", out: 'plugins/core/trade-portal/trade-portal.js',
}, },
{ {
in: "plugins/core/wallet/wallet-app.src.js", in: 'plugins/core/wallet/wallet-app.src.js',
out: "plugins/core/wallet/wallet-app.js", out: 'plugins/core/wallet/wallet-app.js',
}, },
{ {
in: "plugins/core/reward-share/reward-share.src.js", in: 'plugins/core/reward-share/reward-share.src.js',
out: "plugins/core/reward-share/reward-share.js", out: 'plugins/core/reward-share/reward-share.js',
}, },
{ {
in: "plugins/core/node-management/node-management.src.js", in: 'plugins/core/node-management/node-management.src.js',
out: "plugins/core/node-management/node-management.js", out: 'plugins/core/node-management/node-management.js',
}, },
{ {
in: "plugins/core/group-management/group-management.src.js", in: 'plugins/core/group-management/group-management.src.js',
out: "plugins/core/group-management/group-management.js", out: 'plugins/core/group-management/group-management.js',
}, },
{ {
in: "plugins/core/name-registration/name-registration.src.js", in: 'plugins/core/name-registration/name-registration.src.js',
out: "plugins/core/name-registration/name-registration.js", out: 'plugins/core/name-registration/name-registration.js',
}, },
{ {
in: "plugins/core/qdn/websites.src.js", in: 'plugins/core/qdn/websites.src.js',
out: "plugins/core/qdn/websites.js", out: 'plugins/core/qdn/websites.js',
}, },
{ {
in: "plugins/core/qdn/publish/publish.src.js", in: 'plugins/core/qdn/publish/publish.src.js',
out: "plugins/core/qdn/publish/publish.js", out: 'plugins/core/qdn/publish/publish.js',
}, },
{ {
in: "plugins/core/qdn/browser/browser.src.js", in: 'plugins/core/qdn/browser/browser.src.js',
out: "plugins/core/qdn/browser/browser.js", out: 'plugins/core/qdn/browser/browser.js',
}, },
{ {
in: "plugins/core/qdn/data-management/data-management.src.js", in: 'plugins/core/qdn/data-management/data-management.src.js',
out: "plugins/core/qdn/data-management/data-management.js", out: 'plugins/core/qdn/data-management/data-management.js',
}, },
{ {
in: "plugins/core/messaging/messaging.src.js", in: 'plugins/core/messaging/messaging.src.js',
out: "plugins/core/messaging/messaging.js", out: 'plugins/core/messaging/messaging.js',
}, },
{ {
in: "plugins/core/messaging/chain-messaging/chain-messaging.src.js", in: 'plugins/core/messaging/chain-messaging/chain-messaging.src.js',
out: "plugins/core/messaging/chain-messaging/chain-messaging.js", out: 'plugins/core/messaging/chain-messaging/chain-messaging.js',
}, },
{ {
in: "plugins/core/messaging/q-chat/q-chat.src.js", in: 'plugins/core/messaging/q-chat/q-chat.src.js',
out: "plugins/core/messaging/q-chat/q-chat.js", out: 'plugins/core/messaging/q-chat/q-chat.js',
}, },
{ {
in: "plugins/core/minting/minting-info.src.js", in: 'plugins/core/minting/minting-info.src.js',
out: "plugins/core/minting/minting-info.js", out: 'plugins/core/minting/minting-info.js',
}, },
{ {
in: "plugins/core/puzzles/puzzles.src.js", in: 'plugins/core/become-minter/become-minter.src.js',
out: "plugins/core/puzzles/puzzles.js", out: 'plugins/core/become-minter/become-minter.js',
} },
].map((file) => { {
return generateRollupConfig( in: 'plugins/core/puzzles/puzzles.src.js',
path.join(__dirname, file.in), out: 'plugins/core/puzzles/puzzles.js',
path.join(__dirname, file.out) },
); ].map((file) => {
}); return generateRollupConfig(
return configs; path.join(__dirname, file.in),
path.join(__dirname, file.out)
);
});
return configs;
}; };
module.exports = generateForPlugins; module.exports = generateForPlugins;

View File

@ -0,0 +1,229 @@
import { css } from 'lit';
export const pageStyles = css`
* {
--mdc-theme-surface: var(--white);
--mdc-dialog-content-ink-color: var(--black);
}
.header-title {
font-size: 40px;
color: var(--black);
font-weight: 400;
text-align: center;
}
.divider {
color: #eee;
border-radius: 80%;
margin-bottom: 2rem;
}
.fullWidth {
width: 100%;
}
.page-container {
display: flex;
align-items: center;
flex-direction: column;
margin-bottom: 75px;
width: 100%;
}
.inner-container {
display: flex;
align-items: center;
flex-direction: column;
width: 100%;
}
.description {
color: var(--black);
}
.message {
color: var(--gray);
}
.sub-main {
width: 95%;
display: flex;
flex-direction: column;
max-width: 800px;
}
.level-black {
font-size: 32px;
color: var(--black);
font-weight: 400;
text-align: center;
margin-top: 2rem;
}
.form-wrapper {
display: flex;
align-items: center;
width: 100%;
height: 50px;
}
.row {
display: flex;
width: 100%;
}
.column {
display: flex;
flex-direction: column;
width: 100%;
}
.column-center {
align-items: center;
}
.no-margin {
margin: 0;
}
.no-wrap {
flex-wrap: nowrap !important;
}
.row-center {
justify-content: center;
flex-wrap: wrap;
}
.form-item {
display: flex;
height: 100%;
}
.form-item--button {
flex-grow: 0;
}
.form-item--input {
flex-grow: 1;
margin-right: 25px;
}
.center-box {
position: absolute;
width: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, 0%);
text-align: center;
}
.content-box {
border: 1px solid var(--border);
border-radius: 10px;
padding: 10px 25px;
text-align: center;
display: inline-block;
margin-bottom: 5px;
flex-basis: 250px;
}
.gap {
gap: 10px;
}
.level-black {
font-size: 32px;
color: var(--black);
font-weight: 400;
text-align: center;
margin-top: 2rem;
text-align: center;
}
.title {
font-weight: 600;
font-size: 20px;
line-height: 28px;
opacity: 0.66;
color: var(--switchborder);
}
.address {
overflow-wrap: anywhere;
color: var(--black);
}
h4 {
font-weight: 600;
font-size: 20px;
line-height: 28px;
color: var(--black);
}
mwc-textfield {
width: 100%;
}
vaadin-button {
height: 100%;
margin: 0;
cursor: pointer;
outline: 1px var(--black) solid;
min-width: 80px;
}
.loader,
.loader:after {
border-radius: 50%;
width: 10em;
height: 10em;
}
.loadingContainer {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
}
.backdrop {
height: 100vh;
width: 100vw;
opacity: 0.6;
background-color: var(--border);
z-index: 9;
position: fixed;
}
.loading,
.loading:after {
border-radius: 50%;
width: 5em;
height: 5em;
}
.loading {
margin: 10px auto;
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);
}
}
`;

View File

@ -0,0 +1,200 @@
import { LitElement, html } from 'lit';
import { Epml } from '../../../epml.js';
import '../components/ButtonIconCopy.js';
import { use, translate, registerTranslateConfig } from 'lit-translate';
import { blocksNeed } from './utils/blocks-needed.js';
registerTranslateConfig({
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
});
import '@polymer/paper-spinner/paper-spinner-lite.js';
import '@material/mwc-button';
import '@material/mwc-textfield';
import '@vaadin/button';
import { pageStyles } from './become-minter-css.src.js';
import './components/not-sponsored.src';
import './components/yes-sponsored.src';
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
class BecomeMinter extends LitElement {
static get properties() {
return {
theme: { type: String, reflect: true },
sponsorshipKeyValue: { type: String },
nodeInfo: { type: Object },
isPageLoading: { type: Boolean },
addressInfo: { type: Object },
rewardSharePublicKey: { type: String },
mintingAccountData: { type: Array },
};
}
static styles = [pageStyles];
constructor() {
super();
this.theme = localStorage.getItem('qortalTheme')
? localStorage.getItem('qortalTheme')
: 'light';
this.sponsorshipKeyValue = '';
this.isPageLoading = true;
this.nodeInfo = {};
this.addressInfo = {};
this.rewardSharePublicKey = '';
this.mintingAccountData = null;
}
changeLanguage() {
const checkLanguage = localStorage.getItem('qortalLanguage');
if (checkLanguage === null || checkLanguage.length === 0) {
localStorage.setItem('qortalLanguage', 'us');
use('us');
} else {
use(checkLanguage);
}
}
_handleStorage() {
const checkLanguage = localStorage.getItem('qortalLanguage');
const checkTheme = localStorage.getItem('qortalTheme');
use(checkLanguage);
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
connectedCallback() {
super.connectedCallback();
window.addEventListener('storage', this._handleStorage);
}
disconnectedCallback() {
window.removeEventListener('storage', this._handleStorage);
super.disconnectedCallback();
}
async getNodeInfo() {
const nodeInfo = await parentEpml.request('apiCall', {
url: `/admin/status`,
});
return nodeInfo;
}
async getMintingAcccounts() {
const mintingAccountData = await parentEpml.request('apiCall', {
url: `/admin/mintingaccounts`,
});
return mintingAccountData;
}
async atMount() {
this.changeLanguage();
this.addressInfo =
window.parent.reduxStore.getState().app.accountInfo.addressInfo;
this.isPageLoading = true;
try {
const [nodeInfo, myRewardShareArray, mintingaccounts] =
await Promise.all([
this.getNodeInfo(),
this.getRewardShareRelationship(
window.parent.reduxStore.getState().app?.selectedAddress
?.address
),
this.getMintingAcccounts(),
]);
this.nodeInfo = nodeInfo;
this.rewardSharePublicKey =
myRewardShareArray[0]?.rewardSharePublicKey;
this.isPageLoading = false;
this.mintingAccountData = mintingaccounts;
} catch (error) {
console.error(error);
this.isPageLoading = false;
}
}
async firstUpdated() {
await this.atMount();
}
async getRewardShareRelationship(recipientAddress) {
const myRewardShareArray = await parentEpml.request('apiCall', {
type: 'api',
url: `/addresses/rewardshares?recipients=${recipientAddress}`,
});
return myRewardShareArray;
}
_levelUpBlocks() {
let countBlocksString = (
blocksNeed(0) -
(this.addressInfo?.blocksMinted +
this.addressInfo?.blocksMintedAdjustment)
).toString();
return countBlocksString;
}
render() {
console.log({ mintingAccountData: this.mintingAccountData });
const findMintingAccount = this.mintingAccountData?.find(
(ma) => !!ma.publicKey
);
const isAlreadySponsored =
this.addressInfo?.error !== 124 &&
this.addressInfo?.level === 0 &&
findMintingAccount;
return html`
${this.isPageLoading
? html`
<div class="loadingContainer">
<div class="loading"></div>
</div>
<div class="backdrop"></div>
`
: ''}
<div class="page-container">
<h1 class="header-title">
${translate('becomeMinterPage.bchange1')}
</h1>
<div class="fullWidth">
<hr class="divider" />
</div>
${isAlreadySponsored
? ''
: html`
<not-sponsored
.atMount="${() => this.atMount()}"
></not-sponsored>
`}
${!isAlreadySponsored
? ''
: html`
<yes-sponsored
.rewardSharePublicKey=${this
.rewardSharePublicKey}
.addressInfo=${this.addressInfo}
></yes-sponsored>
`}
</div>
`;
}
}
window.customElements.define('become-minter', BecomeMinter);

View File

@ -0,0 +1,140 @@
import { LitElement, html } from 'lit';
import { Epml } from '../../../../epml.js';
import '../../components/ButtonIconCopy.js';
import { use, translate, registerTranslateConfig } from 'lit-translate';
registerTranslateConfig({
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
});
import '@polymer/paper-spinner/paper-spinner-lite.js';
import '@material/mwc-button';
import '@material/mwc-textfield';
import '@vaadin/button';
import { pageStyles } from '../become-minter-css.src.js';
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
// hello
class NotSponsored extends LitElement {
static properties = {
atMount: { type: Function },
isLoadingSponsorshipKeySubmit: { type: Boolean },
sponsorshipKeyValue: { type: String },
addMintingAccountMessage: { type: String },
};
static styles = [pageStyles];
constructor() {
super();
this.isLoadingSponsorshipKeySubmit = false;
this.sponsorshipKeyValue = '';
this.addMintingAccountMessage = '';
this.atMount = () => {};
}
renderErr1Text() {
return html`${translate('nodepage.nchange27')}`;
}
renderErr2Text() {
return html`${translate('nodepage.nchange28')}`;
}
getApiKey() {
const myNode =
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
window.parent.reduxStore.getState().app.nodeConfig.node
];
let apiKey = myNode.apiKey;
return apiKey;
}
addMintingAccount(e) {
this.isLoadingSponsorshipKeySubmit = true;
this.addMintingAccountMessage = 'Loading...';
parentEpml
.request('apiCall', {
url: `/admin/mintingaccounts?apiKey=${this.getApiKey()}`,
method: 'POST',
body: this.sponsorshipKeyValue,
})
.then((res) => {
if (res === true) {
// refetch data
this.atMount();
this.sponsorshipKeyValue = '';
this.addMintingAccountMessage = this.renderErr1Text();
this.isLoadingSponsorshipKeySubmit = false;
} else {
this.sponsorshipKeyValue = '';
this.addMintingAccountMessage = this.renderErr2Text();
this.isLoadingSponsorshipKeySubmit = false;
}
});
}
inputHandler(e) {
this.sponsorshipKeyValue = e.target.value;
}
render() {
return html`
<div class="inner-container">
<div class="sub-main">
<h2 class="level-black">
${translate('becomeMinterPage.bchange2')}
</h2>
<p class="description">
${translate('becomeMinterPage.bchange3')}
</p>
<h2 class="level-black">
${translate('becomeMinterPage.bchange4')}
</h2>
<p class="description">
${translate('becomeMinterPage.bchange5')}
</p>
<p class="description">
${translate('becomeMinterPage.bchange6')}
</p>
<p class="message">${this.addMintingAccountMessage}</p>
<div class="form-wrapper">
<div class="form-item form-item--input">
<mwc-textfield
?disabled="${this
.isLoadingSponsorshipKeySubmit}"
label="${translate(
'becomeMinterPage.bchange8'
)}"
id="addSponsorshipKey"
@input="${this.inputHandler}"
.value="${this.sponsorshipKeyValue || ''}"
fullWidth
>
</mwc-textfield>
</div>
<div class="form-item form-item--button">
<vaadin-button
?disabled="${this
.isLoadingSponsorshipKeySubmit}"
@click="${this.addMintingAccount}"
>
${this.isLoadingSponsorshipKeySubmit === false
? html`${translate(
'becomeMinterPage.bchange9'
)}`
: html`<paper-spinner-lite
active
></paper-spinner-lite>`}
</vaadin-button>
</div>
</div>
</div>
</div>
`;
}
}
window.customElements.define('not-sponsored', NotSponsored);

View File

@ -0,0 +1,123 @@
import { LitElement, html } from 'lit';
import { Epml } from '../../../../epml.js';
import '../../components/ButtonIconCopy.js';
import { use, translate, registerTranslateConfig } from 'lit-translate';
registerTranslateConfig({
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
});
import '@polymer/paper-spinner/paper-spinner-lite.js';
import '@material/mwc-button';
import '@material/mwc-textfield';
import '@vaadin/button';
import { blocksNeed } from '../utils/blocks-needed.js';
import { pageStyles } from '../become-minter-css.src.js';
class YesSponsored extends LitElement {
static get properties() {
return {
addressInfo: { type: Object },
rewardSharePublicKey: { type: String },
};
}
constructor() {
super();
this.addressInfo = {};
this.rewardSharePublicKey = '';
}
static styles = [pageStyles];
_levelUpBlocks() {
let countBlocksString = (
blocksNeed(0) -
(this.addressInfo?.blocksMinted +
this.addressInfo?.blocksMintedAdjustment)
).toString();
return countBlocksString;
}
render() {
return html`
<div class="inner-container">
<div class="column column-center">
<div class="column column-center">
<span class="level-black"
>${translate('becomeMinterPage.bchange10')}</span
>
<hr
style="width: 50%; color: #eee; border-radius: 80%; margin-bottom: 2rem;"
/>
</div>
<br />
<div class="row row-center gap">
<div class="content-box">
<span class="title"
>${translate(
'becomeMinterPage.bchange11'
)}</span
>
<hr
style="color: #eee; border-radius: 90%; margin-bottom: 1rem;"
/>
<h4>${translate('becomeMinterPage.bchange12')}</h4>
</div>
<div class="content-box">
<span class="title"
>${translate(
'becomeMinterPage.bchange13'
)}</span
>
<hr
style="color: #eee; border-radius: 90%; margin-bottom: 1rem;"
/>
<h4>
${this._levelUpBlocks()}
${translate('becomeMinterPage.bchange14')}
</h4>
</div>
<div class="content-box">
<span class="title"
>${translate(
'becomeMinterPage.bchange15'
)}</span
>
<hr
style="color: #eee; border-radius: 90%; margin-bottom: 1rem;"
/>
<h4 class="no-margin">
${translate('becomeMinterPage.bchange16')}
</h4>
<div class="row row-center column-center no-wrap">
<p class="address">
${this.rewardSharePublicKey}
</p>
<button-icon-copy
title="${translate('walletpage.wchange3')}"
onSuccessMessage="${translate(
'walletpage.wchange4'
)}"
onErrorMessage="${translate(
'walletpage.wchange39'
)}"
textToCopy=${this.rewardSharePublicKey}
buttonSize="28px"
iconSize="16px"
color="var(--copybutton)"
offsetLeft="4px"
>
</button-icon-copy>
</div>
</div>
</div>
<br />
</div>
</div>
`;
}
}
window.customElements.define('yes-sponsored', YesSponsored);

View File

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/font/material-icons.css" />
<link rel="stylesheet" href="/font/switch-theme.css" />
<script>
const checkBack = localStorage.getItem('qortalTheme');
if (checkBack === 'dark') {
newtheme = 'dark';
} else {
newtheme = 'light';
}
document.querySelector('html').setAttribute('theme', newtheme);
</script>
<style>
html {
--scrollbarBG: #a1a1a1;
--thumbBG: #6a6c75;
}
*::-webkit-scrollbar {
width: 11px;
}
* {
scrollbar-width: thin;
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
}
*::-webkit-scrollbar-track {
background: var(--scrollbarBG);
}
*::-webkit-scrollbar-thumb {
background-color: var(--thumbBG);
border-radius: 6px;
border: 3px solid var(--scrollbarBG);
}
html,
body {
margin: 0;
font-family: 'Roboto', sans-serif;
background: var(--plugback);
}
</style>
</head>
<body>
<become-minter></become-minter>
<script src="become-minter.js"></script>
</body>
</html>

View File

@ -1,132 +1,143 @@
import { parentEpml } from './connect.js' import { parentEpml } from './connect.js';
import './streams/streams.js' import './streams/streams.js';
let config = {}
let haveRegisteredNodeManagement = false
let config = {};
let haveRegisteredNodeManagement = false;
parentEpml.ready().then(() => { parentEpml.ready().then(() => {
// pluginUrlsConf // pluginUrlsConf
let pluginUrlsConf = [ let pluginUrlsConf = [
{ {
url: 'minting', url: 'minting',
domain: 'core', domain: 'core',
page: 'minting/index.html', page: 'minting/index.html',
title: 'Minting Details', title: 'Minting Details',
icon: 'vaadin:info-circle', icon: 'vaadin:info-circle',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'wallet', url: 'become-minter',
domain: 'core', domain: 'core',
page: 'wallet/index.html', page: 'become-minter/index.html',
title: 'Wallet', title: 'Become a Minter',
icon: 'vaadin:wallet', icon: 'vaadin:info-circle',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'trade-portal', url: 'wallet',
domain: 'core', domain: 'core',
page: 'trade-portal/index.html', page: 'wallet/index.html',
title: 'Trade Portal', title: 'Wallet',
icon: 'vaadin:bullets', icon: 'vaadin:wallet',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'reward-share', url: 'trade-portal',
domain: 'core', domain: 'core',
page: 'reward-share/index.html', page: 'trade-portal/index.html',
title: 'Reward Share', title: 'Trade Portal',
icon: 'vaadin:share-square', icon: 'vaadin:bullets',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'name-registration', url: 'reward-share',
domain: 'core', domain: 'core',
page: 'name-registration/index.html', page: 'reward-share/index.html',
title: 'Name Registration', title: 'Reward Share',
icon: 'vaadin:user-check', icon: 'vaadin:share-square',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'websites', url: 'name-registration',
domain: 'core', domain: 'core',
page: 'qdn/index.html', page: 'name-registration/index.html',
title: 'Websites', title: 'Name Registration',
icon: 'vaadin:desktop', icon: 'vaadin:user-check',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'data-management', url: 'websites',
domain: 'core', domain: 'core',
page: 'qdn/data-management/index.html', page: 'qdn/index.html',
title: 'Data Management', title: 'Websites',
icon: 'vaadin:database', icon: 'vaadin:desktop',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'q-chat', url: 'data-management',
domain: 'core', domain: 'core',
page: 'messaging/q-chat/index.html', page: 'qdn/data-management/index.html',
title: 'Q-Chat', title: 'Data Management',
icon: 'vaadin:chat', icon: 'vaadin:database',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'group-management', url: 'q-chat',
domain: 'core', domain: 'core',
page: 'group-management/index.html', page: 'messaging/q-chat/index.html',
title: 'Group Management', title: 'Q-Chat',
icon: 'vaadin:group', icon: 'vaadin:chat',
menus: [], menus: [],
parent: false parent: false,
}, },
{ {
url: 'puzzles', url: 'group-management',
domain: 'core', domain: 'core',
page: 'puzzles/index.html', page: 'group-management/index.html',
title: 'Puzzles', title: 'Group Management',
icon: 'vaadin:puzzle-piece', icon: 'vaadin:group',
menus: [], menus: [],
parent: false parent: false,
} },
] {
url: 'puzzles',
domain: 'core',
page: 'puzzles/index.html',
title: 'Puzzles',
icon: 'vaadin:puzzle-piece',
menus: [],
parent: false,
},
];
const registerPlugins = (pluginInfo) => { const registerPlugins = (pluginInfo) => {
parentEpml.request('registerUrl', pluginInfo) parentEpml.request('registerUrl', pluginInfo);
} };
const checkNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] const checkNode =
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
window.parent.reduxStore.getState().app.nodeConfig.node
];
parentEpml.subscribe('config', c => { parentEpml.subscribe('config', (c) => {
config = JSON.parse(c) config = JSON.parse(c);
// Only register node management if node management is enabled and it hasn't already been registered // Only register node management if node management is enabled and it hasn't already been registered
if (!haveRegisteredNodeManagement && checkNode.enableManagement) { if (!haveRegisteredNodeManagement && checkNode.enableManagement) {
haveRegisteredNodeManagement = true haveRegisteredNodeManagement = true;
let nodeManagementConf = { let nodeManagementConf = {
url: 'node-management', url: 'node-management',
domain: 'core', domain: 'core',
page: 'node-management/index.html', page: 'node-management/index.html',
title: 'Node Management', title: 'Node Management',
icon: 'vaadin:cloud', icon: 'vaadin:cloud',
menus: [], menus: [],
parent: false parent: false,
} };
let _pluginUrlsConf = [...pluginUrlsConf, nodeManagementConf] let _pluginUrlsConf = [...pluginUrlsConf, nodeManagementConf];
registerPlugins(_pluginUrlsConf) registerPlugins(_pluginUrlsConf);
} else { } else {
registerPlugins(pluginUrlsConf) registerPlugins(pluginUrlsConf);
} }
}) });
}) });