Merge branch 'master' into pirate-chain

# Conflicts:
#	qortal-ui-core/src/plugins/routes.js
This commit is contained in:
CalDescent 2022-08-17 08:41:11 +01:00
commit 59fb31f84d
39 changed files with 12455 additions and 10845 deletions

View File

@ -41,19 +41,7 @@ Clone the main UI repo
Installation and linking Installation and linking
------------------------ ------------------------
In `qortal-ui-core/`, `qortal-ui-plugins/`, `qortal-ui-crypto/` directories, run: In `qortal-ui/` install_link:all
```
yarn install
yarn link
```
Finally, in the `qortal-ui` directory, run:
```
yarn link qortal-ui-core
yarn link qortal-ui-plugins
yarn link qortal-ui-crypto
```
Build UI server and files Build UI server and files

View File

@ -16,6 +16,7 @@
"author": "QORTAL <admin@qortal.org>", "author": "QORTAL <admin@qortal.org>",
"license": "GPL-3.0", "license": "GPL-3.0",
"scripts": { "scripts": {
"install_link:all": "(cd qortal-ui-core && yarn install && yarn link) && (cd qortal-ui-plugins && yarn install && yarn link) && (cd qortal-ui-crypto && yarn install && yarn link) && (yarn link qortal-ui-core && yarn link qortal-ui-plugins && yarn link qortal-ui-crypto)",
"dev": "node server.js", "dev": "node server.js",
"prebuild": "node -p \"'export const UI_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > qortal-ui-core/src/redux/app/version.js", "prebuild": "node -p \"'export const UI_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > qortal-ui-core/src/redux/app/version.js",
"build-dev": "node build.js", "build-dev": "node build.js",
@ -31,12 +32,12 @@
"publish": "electron-builder -p always" "publish": "electron-builder -p always"
}, },
"dependencies": { "dependencies": {
"electron-updater": "5.0.5", "electron-updater": "5.2.1",
"electron-log": "4.4.8" "electron-log": "4.4.8"
}, },
"devDependencies": { "devDependencies": {
"electron": "19.0.9", "electron": "19.0.11",
"electron-builder": "23.1.0", "electron-builder": "23.3.3",
"electron-notarize": "1.2.1", "electron-notarize": "1.2.1",
"electron-packager": "15.5.1", "electron-packager": "15.5.1",
"shelljs": "0.8.5" "shelljs": "0.8.5"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -19,10 +19,10 @@
"dependencies": { "dependencies": {
"@hapi/hapi": "20.2.2", "@hapi/hapi": "20.2.2",
"@hapi/inert": "7.0.0", "@hapi/inert": "7.0.0",
"sass": "1.53.0" "sass": "1.54.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.18.9", "@babel/core": "7.18.10",
"@material/mwc-button": "0.26.1", "@material/mwc-button": "0.26.1",
"@material/mwc-checkbox": "0.26.1", "@material/mwc-checkbox": "0.26.1",
"@material/mwc-dialog": "0.26.1", "@material/mwc-dialog": "0.26.1",
@ -55,24 +55,24 @@
"@polymer/paper-tooltip": "3.0.1", "@polymer/paper-tooltip": "3.0.1",
"@rollup/plugin-alias": "3.1.9", "@rollup/plugin-alias": "3.1.9",
"@rollup/plugin-babel": "5.3.1", "@rollup/plugin-babel": "5.3.1",
"@rollup/plugin-commonjs": "22.0.1", "@rollup/plugin-commonjs": "22.0.2",
"@rollup/plugin-node-resolve": "13.3.0", "@rollup/plugin-node-resolve": "13.3.0",
"@rollup/plugin-replace": "4.0.0", "@rollup/plugin-replace": "4.0.0",
"@vaadin/grid": "23.1.4", "@vaadin/grid": "23.1.5",
"@vaadin/icons": "23.1.4", "@vaadin/icons": "23.1.5",
"@vaadin/password-field": "23.1.4", "@vaadin/password-field": "23.1.5",
"asmcrypto.js": "2.3.2", "asmcrypto.js": "2.3.2",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"epml": "0.3.3", "epml": "0.3.3",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"lit": "2.2.7", "lit": "2.2.8",
"lit-translate": "2.0.1", "lit-translate": "2.0.1",
"postcss": "8.4.14", "postcss": "8.4.16",
"pwa-helpers": "0.9.1", "pwa-helpers": "0.9.1",
"random-sentence-generator": "0.0.8", "random-sentence-generator": "0.0.8",
"redux": "4.2.0", "redux": "4.2.0",
"redux-thunk": "2.4.1", "redux-thunk": "2.4.1",
"rollup": "2.77.0", "rollup": "2.77.2",
"rollup-plugin-node-globals": "1.4.0", "rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-postcss": "4.0.2", "rollup-plugin-postcss": "4.0.2",
"rollup-plugin-progress": "1.1.2", "rollup-plugin-progress": "1.1.2",

View File

@ -5,6 +5,8 @@ import { translate, translateUnsafeHTML } from 'lit-translate'
import '@polymer/paper-icon-button/paper-icon-button.js' import '@polymer/paper-icon-button/paper-icon-button.js'
import '@polymer/iron-icons/iron-icons.js' import '@polymer/iron-icons/iron-icons.js'
import '@polymer/app-layout/app-layout.js'
import '@polymer/paper-ripple'
import './wallet-profile.js' import './wallet-profile.js'
import './app-info.js' import './app-info.js'
@ -12,10 +14,6 @@ import './sidenav-menu.js'
import './show-plugin.js' import './show-plugin.js'
import './qort-theme-toggle.js' import './qort-theme-toggle.js'
import './language-selector.js' import './language-selector.js'
import '@polymer/app-layout/app-layout.js'
import '@polymer/paper-ripple'
import './settings-view/user-settings.js' import './settings-view/user-settings.js'
import './logout-view/logout-view.js' import './logout-view/logout-view.js'

View File

@ -1,159 +1,248 @@
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.js';
import '../functional-components/side-menu-item.js' import '../functional-components/side-menu-item.js';
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()}
</side-menu>
</div>
`;
}
async getNodeType() { firstUpdated() {
const myNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node] this.getNodeType();
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() { async getNodeType() {
if (this.nodeType === 'lite') { const myNode =
return html` store.getState().app.nodeConfig.knownNodes[
<side-menu-item label="${translate("sidemenu.wallets")}" href="/app/wallet" selected> store.getState().app.nodeConfig.node
<vaadin-icon icon="vaadin:wallet" slot="icon"></vaadin-icon> ];
</side-menu-item> const nodeUrl =
<side-menu-item label="${translate("sidemenu.nameregistration")}" href="/app/name-registration"> myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
<vaadin-icon icon="vaadin:user-check" slot="icon"></vaadin-icon> const url = `${nodeUrl}/admin/info`;
</side-menu-item> await fetch(url)
<side-menu-item label="${translate("sidemenu.datamanagement")}" href="/app/data-management"> .then((response) => {
<vaadin-icon icon="vaadin:database" slot="icon"></vaadin-icon> return response.json();
</side-menu-item> })
<side-menu-item label="${translate("sidemenu.qchat")}" href="/app/q-chat"> .then((data) => {
<vaadin-icon icon="vaadin:chat" slot="icon"></vaadin-icon> this.nodeType = data.type;
</side-menu-item> })
` .catch((err) => {
} else { console.error('Request failed', err);
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() { renderNodeTypeMenu() {
const checkNodeManagement = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node] const addressInfo = this.addressInfo;
if (checkNodeManagement.enableManagement = true) { const isMinter = addressInfo?.error !== 124 && +addressInfo?.level > 0;
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) { if (this.nodeType === 'lite') {
this.config = state.config return html`
this.urls = state.app.registeredUrls <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>
${this.renderNodeManagement()}
`;
} else {
return html`
<side-menu-item
label="${translate('sidemenu.minting')}"
expanded
>
<vaadin-icon icon="vaadin:info-circle" slot="icon"></vaadin-icon>
${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:thumbs-up" slot="icon"></vaadin-icon>
</side-menu-item>`}
</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.qchat')}"
href="/app/q-chat"
>
<vaadin-icon icon="vaadin:chat" 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.management')}"
expanded
>
<vaadin-icon icon="vaadin:cogs" slot="icon"></vaadin-icon>
<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.groupmanagement')}"
href="/app/group-management"
>
<vaadin-icon icon="vaadin:group" slot="icon"></vaadin-icon>
</side-menu-item>
${this.renderNodeManagement()}
</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,259 @@
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;
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

@ -6,6 +6,8 @@ import { translate, translateUnsafeHTML } from 'lit-translate'
import '@polymer/paper-toast' import '@polymer/paper-toast'
import '@material/mwc-icon-button' import '@material/mwc-icon-button'
import './start-minting.js'
class WalletProfile extends connect(store)(LitElement) { class WalletProfile extends connect(store)(LitElement) {
static get properties() { static get properties() {
return { return {
@ -88,6 +90,7 @@ class WalletProfile extends connect(store)(LitElement) {
<p id="blocksMinted">${translate("walletprofile.blocksminted")} - ${this.accountInfo.addressInfo.blocksMinted + this.accountInfo.addressInfo.blocksMintedAdjustment}</p> <p id="blocksMinted">${translate("walletprofile.blocksminted")} - ${this.accountInfo.addressInfo.blocksMinted + this.accountInfo.addressInfo.blocksMintedAdjustment}</p>
<p id="address">${this.wallet.addresses[0].address}</p> <p id="address">${this.wallet.addresses[0].address}</p>
</div> </div>
<start-minting></start-minting>
</div> </div>
<paper-toast id="toast" horizontal-align="right" vertical-align="top" vertical-offset="64"></paper-toast> <paper-toast id="toast" horizontal-align="right" vertical-align="top" vertical-offset="64"></paper-toast>
` `

View File

@ -0,0 +1,47 @@
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,84 +1,96 @@
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;
const sendArrr = api.sendArrr const sendArrr = api.sendArrr;
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) => {
@ -86,26 +98,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) => {
@ -116,251 +128,289 @@ 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;
}, },
sendArrr: async (req) => { sendArrr: async (req) => {
@ -375,4 +425,4 @@ export const routes = {
} }
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

@ -22,7 +22,7 @@
"emoji-picker-js": "https://github.com/Qortal/emoji-picker-js" "emoji-picker-js": "https://github.com/Qortal/emoji-picker-js"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.18.9", "@babel/core": "7.18.10",
"@github/time-elements": "3.1.2", "@github/time-elements": "3.1.2",
"@material/mwc-button": "0.26.1", "@material/mwc-button": "0.26.1",
"@material/mwc-checkbox": "0.26.1", "@material/mwc-checkbox": "0.26.1",
@ -43,17 +43,17 @@
"@polymer/paper-tooltip": "3.0.1", "@polymer/paper-tooltip": "3.0.1",
"@rollup/plugin-alias": "3.1.9", "@rollup/plugin-alias": "3.1.9",
"@rollup/plugin-babel": "5.3.1", "@rollup/plugin-babel": "5.3.1",
"@rollup/plugin-commonjs": "22.0.1", "@rollup/plugin-commonjs": "22.0.2",
"@rollup/plugin-node-resolve": "13.3.0", "@rollup/plugin-node-resolve": "13.3.0",
"@rollup/plugin-replace": "4.0.0", "@rollup/plugin-replace": "4.0.0",
"@vaadin/button": "23.1.4", "@vaadin/button": "23.1.5",
"@vaadin/grid": "23.1.4", "@vaadin/grid": "23.1.5",
"@vaadin/icons": "23.1.4", "@vaadin/icons": "23.1.5",
"epml": "0.3.3", "epml": "0.3.3",
"html-escaper": "3.0.3", "html-escaper": "3.0.3",
"lit": "2.2.7", "lit": "2.2.8",
"lit-translate": "2.0.1", "lit-translate": "2.0.1",
"rollup": "2.77.0", "rollup": "2.77.2",
"rollup-plugin-node-globals": "1.4.0", "rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-progress": "1.1.2", "rollup-plugin-progress": "1.1.2",
"rollup-plugin-terser": "7.0.2" "rollup-plugin-terser": "7.0.2"

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,199 @@
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('mintingpage.mchange32')}
</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,141 @@
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 });
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('mintingpage.mchange33')}
</h2>
<p class="description">
${translate('mintingpage.mchange34')}
</p>
<h2 class="level-black">
${translate('mintingpage.mchange35')}
</h2>
<p class="description">
${translate('mintingpage.mchange36')}
</p>
<p class="description">
${translate('mintingpage.mchange37')}
</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(
'puzzlepage.pchange15'
)}`
: 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(
'walletpage.wchange41'
)}</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('mintingpage.mchange26')}
</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

@ -309,6 +309,10 @@ class ChatPage extends LitElement {
this.messageSignature = eachMessage.signature this.messageSignature = eachMessage.signature
let _eachMessage = this.decodeMessage(eachMessage) let _eachMessage = this.decodeMessage(eachMessage)
return _eachMessage return _eachMessage
} else {
this.messageSignature = eachMessage.signature
let _eachMessage = this.decodeMessage(eachMessage)
return _eachMessage
} }
}) })
@ -329,18 +333,22 @@ class ChatPage extends LitElement {
} else { } else {
let _newMessages = messages.map((eachMessage) => { let _newMessages = messages.map((eachMessage) => {
if (eachMessage.isText === true) { if (eachMessage.isText === true) {
let _eachMessage = this.decodeMessage(eachMessage) let _eachMessage = this.decodeMessage(eachMessage)
if (this.messageSignature !== eachMessage.signature) { if (this.messageSignature !== eachMessage.signature) {
this.messageSignature = eachMessage.signature this.messageSignature = eachMessage.signature
// What are we waiting for, send in the message immediately... // What are we waiting for, send in the message immediately...
this.renderNewMessage(_eachMessage) this.renderNewMessage(_eachMessage)
} }
return _eachMessage
} else {
let _eachMessage = this.decodeMessage(eachMessage)
if (this.messageSignature !== eachMessage.signature) {
this.messageSignature = eachMessage.signature
this.renderNewMessage(_eachMessage)
}
return _eachMessage return _eachMessage
} }
}) })

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);
} }
}) });
}) });

View File

@ -545,7 +545,7 @@ class Websites extends LitElement {
const blockedNamesUrl = `${nodeUrl}/lists/blockedNames?apiKey=${this.getApiKey()}` const blockedNamesUrl = `${nodeUrl}/lists/blockedNames?apiKey=${this.getApiKey()}`
const resources = await parentEpml.request('apiCall', { const resources = await parentEpml.request('apiCall', {
url: `/arbitrary/resources?service=${this.service}&default=true&limit=0&reverse=false&includestatus=true&includemetadata=true` url: `/arbitrary/resources?service=${this.service}&default=true&limit=0&reverse=false&includestatus=false&includemetadata=false`
}) })
this.resources = resources this.resources = resources
@ -553,7 +553,7 @@ class Websites extends LitElement {
const followedResponse = await fetch(followedNamesUrl) const followedResponse = await fetch(followedNamesUrl)
const followednames = await followedResponse.json() const followednames = await followedResponse.json()
let followedres = resources.filter((elm) => followednames.includes(elm.name)) let followedres = resources.filter((elm) => followednames.includes(elm.name))
this.followedResources = followedres this.followedResources = followedres
const blockedResponse = await fetch(blockedNamesUrl) const blockedResponse = await fetch(blockedNamesUrl)
const blockednames = await blockedResponse.json() const blockednames = await blockedResponse.json()

View File

@ -0,0 +1,55 @@
<!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>
<trade-bot></trade-bot>
<script src="trade-bot.js"></script>
</body>
</html>

View File

@ -19,6 +19,8 @@ import '@material/mwc-textfield'
import '@polymer/paper-progress/paper-progress.js' import '@polymer/paper-progress/paper-progress.js'
import '@polymer/paper-slider/paper-slider.js' import '@polymer/paper-slider/paper-slider.js'
import '@polymer/paper-spinner/paper-spinner-lite.js' import '@polymer/paper-spinner/paper-spinner-lite.js'
import '@polymer/paper-icon-button/paper-icon-button.js'
import '@polymer/iron-icons/iron-icons.js'
import '@vaadin/button' import '@vaadin/button'
import '@vaadin/grid' import '@vaadin/grid'
import '@vaadin/icon' import '@vaadin/icon'
@ -436,7 +438,7 @@ class MultiWallet extends LitElement {
background-image: url('/img/dgb.png'); background-image: url('/img/dgb.png');
} }
.rvn .currency-image { .rvn .currency-image {
background-image: url('/img/rvn.png'); background-image: url('/img/rvn.png');
} }
@ -776,7 +778,10 @@ class MultiWallet extends LitElement {
<div><span>${this.selectedTransaction.creatorAddress}</span></div> <div><span>${this.selectedTransaction.creatorAddress}</span></div>
<span class="title"> ${translate("walletpage.wchange10")} </span> <span class="title"> ${translate("walletpage.wchange10")} </span>
<br /> <br />
<div><span>${this.selectedTransaction.recipient}</span></div> <div style="display: inline;">
${this.renderSQB()}
</div>
<br />
${!this.selectedTransaction.amount ? '' : html` ${!this.selectedTransaction.amount ? '' : html`
<span class="title"> ${translate("walletpage.wchange11")} </span> <span class="title"> ${translate("walletpage.wchange11")} </span>
<br /> <br />
@ -821,11 +826,12 @@ class MultiWallet extends LitElement {
<div> <div>
<span>${this.selectedTransaction.btcSender}</span> <span>${this.selectedTransaction.btcSender}</span>
</div> </div>
<span class="title"> ${translate("walletpage.wchange10")} </span> <span class="title"> ${translate("walletpage.wchange10")} </span>
<br /> <br />
<div> <div style="display: inline;">
<span>${this.selectedTransaction.btcReceiver}</span> <span>${this.selectedTransaction.btcReceiver}</span>
</div> </div>
<br />
<span class="title"> ${translate("walletpage.wchange12")} </span> <span class="title"> ${translate("walletpage.wchange12")} </span>
<br /> <br />
<div> <div>
@ -873,9 +879,10 @@ class MultiWallet extends LitElement {
</div> </div>
<span class="title"> ${translate("walletpage.wchange10")} </span> <span class="title"> ${translate("walletpage.wchange10")} </span>
<br /> <br />
<div> <div style="display: inline;">
<span> ${this.selectedTransaction.ltcReceiver} </span> <span>${this.selectedTransaction.ltcReceiver}</span> <paper-icon-button icon="icons:send" @click=${() => this.sendToLtcAddress()} title="Send to this address"></paper-icon-button>
</div> </div>
<br />
<span class="title"> ${translate("walletpage.wchange12")} </span> <span class="title"> ${translate("walletpage.wchange12")} </span>
<br /> <br />
<div> <div>
@ -918,10 +925,11 @@ class MultiWallet extends LitElement {
</div> </div>
<span class="title"> ${translate("walletpage.wchange9")} </span> <span class="title"> ${translate("walletpage.wchange9")} </span>
<br /> <br />
<div> <div style="display: inline;">
<span>${this.selectedTransaction.dogeSender}</span> <span>${this.selectedTransaction.dogeSender}</span>
</div> </div>
<span class="title"> ${translate("walletpage.wchange10")} </span> <br />
<span class="title"> ${translate("walletpage.wchange10")} </span>
<br /> <br />
<div> <div>
<span>${this.selectedTransaction.dogeReceiver}</span> <span>${this.selectedTransaction.dogeReceiver}</span>
@ -971,11 +979,12 @@ class MultiWallet extends LitElement {
<div> <div>
<span>${this.selectedTransaction.dgbSender}</span> <span>${this.selectedTransaction.dgbSender}</span>
</div> </div>
<span class="title"> ${translate("walletpage.wchange10")} </span> <span class="title"> ${translate("walletpage.wchange10")} </span>
<br /> <br />
<div> <div> style="display: inline;"
<span>${this.selectedTransaction.dgbReceiver}</span> <span>${this.selectedTransaction.dgbReceiver}</span>
</div> </div>
<br />
<span class="title"> ${translate("walletpage.wchange12")} </span> <span class="title"> ${translate("walletpage.wchange12")} </span>
<br /> <br />
<div> <div>
@ -1004,7 +1013,7 @@ class MultiWallet extends LitElement {
</mwc-button> </mwc-button>
</mwc-dialog> </mwc-dialog>
<mwc-dialog id="showRvnTransactionDetailsDialog" scrimClickAction="${this.showRvnTransactionDetailsLoading ? '' : 'close'}"> <mwc-dialog id="showRvnTransactionDetailsDialog" scrimClickAction="${this.showRvnTransactionDetailsLoading ? '' : 'close'}">
<div style="text-align: center;"> <div style="text-align: center;">
<h1>${translate("walletpage.wchange5")}</h1> <h1>${translate("walletpage.wchange5")}</h1>
<hr /> <hr />
@ -1021,11 +1030,12 @@ class MultiWallet extends LitElement {
<div> <div>
<span>${this.selectedTransaction.rvnSender}</span> <span>${this.selectedTransaction.rvnSender}</span>
</div> </div>
<span class="title"> ${translate("walletpage.wchange10")} </span> <span class="title"> ${translate("walletpage.wchange10")} </span>
<br /> <br />
<div> <div style="display: inline;">
<span>${this.selectedTransaction.rvnReceiver}</span> <span>${this.selectedTransaction.rvnReceiver}</span>
</div> </div>
<br />
<span class="title"> ${translate("walletpage.wchange12")} </span> <span class="title"> ${translate("walletpage.wchange12")} </span>
<br /> <br />
<div> <div>
@ -1117,7 +1127,10 @@ class MultiWallet extends LitElement {
</p> </p>
<p> <p>
<span>${translate("walletpage.wchange19")}:</span><br /> <span>${translate("walletpage.wchange19")}:</span><br />
<span style="font-weight: bold;">${this.balanceString}</span> <span style="float: left; font-weight: bold; display: inline;">${this.balanceString}</span><br />
<span style="float: left; font-weight: bold; display: inline;">
<vaadin-button theme="primary small" style="width: 100%;" @click=${() => this.calculateQortAll()}><vaadin-icon icon="vaadin:coin-piles" slot="prefix"></vaadin-icon> ${translate("walletpage.wchange45")} QORT</vaadin-button>
</span><br /><span>&nbsp;</span>
</p> </p>
<p> <p>
<mwc-textfield <mwc-textfield
@ -1254,7 +1267,10 @@ class MultiWallet extends LitElement {
</p> </p>
<p> <p>
<span>${translate("walletpage.wchange19")}:</span><br /> <span>${translate("walletpage.wchange19")}:</span><br />
<span style="font-weight: bold;">${this.balanceString}</span> <span style="float: left; font-weight: bold; display: inline;">${this.balanceString}</span><br />
<span style="float: left; font-weight: bold; display: inline;">
<vaadin-button theme="primary small" style="width: 100%;" @click=${() => this.calculateLtcAll()}><vaadin-icon icon="vaadin:coin-piles" slot="prefix"></vaadin-icon> ${translate("walletpage.wchange45")} LTC</vaadin-button>
</span><br /><span>&nbsp;</span>
</p> </p>
<p> <p>
<mwc-textfield <mwc-textfield
@ -1467,7 +1483,7 @@ class MultiWallet extends LitElement {
</mwc-button> </mwc-button>
</mwc-dialog> </mwc-dialog>
<mwc-dialog id="sendRvnDialog"> <mwc-dialog id="sendRvnDialog">
<div class="send-coin-dialog"> <div class="send-coin-dialog">
<div style="text-align: center;"> <div style="text-align: center;">
<img src="/img/rvn.png" width="32" height="32"> <img src="/img/rvn.png" width="32" height="32">
@ -1882,7 +1898,7 @@ class MultiWallet extends LitElement {
checkSelectedTextAndShowMenu() checkSelectedTextAndShowMenu()
}) })
this.shadowRoot.getElementById('rvnAmountInput').addEventListener('contextmenu', (event) => { this.shadowRoot.getElementById('rvnAmountInput').addEventListener('contextmenu', (event) => {
const getSelectedText = () => { const getSelectedText = () => {
var text = '' var text = ''
if (typeof window.getSelection != 'undefined') { if (typeof window.getSelection != 'undefined') {
@ -2045,6 +2061,46 @@ class MultiWallet extends LitElement {
this.errorMessage = '' this.errorMessage = ''
} }
sendToQortAddress() {
this.recipient = this.selectedTransaction.recipient
this.openSendQort()
this.shadowRoot.querySelector('#showTransactionDetailsDialog').close()
}
sendToLtcAddress() {
this.ltcRecipient = this.selectedTransaction.ltcReceiver
this.openSendLtc()
this.shadowRoot.querySelector('#showLtcTransactionDetailsDialog').close()
}
calculateQortAll() {
if (this.balance < 0.00100000) {
let not_enough_string = get("walletpage.wchange26")
parentEpml.request('showSnackBar', `${not_enough_string}`)
} else {
this.amount = (this.balance - 0.00100000).toFixed(8)
}
}
calculateLtcAll() {
if (this.balance < 0.00025000) {
let not_enough_string = get("walletpage.wchange26")
parentEpml.request('showSnackBar', `${not_enough_string}`)
} else {
this.ltcAmount = (this.balance - 0.00025000).toFixed(8)
this.ltcFeePerByte = 15
}
}
renderSQB() {
let displaybutton = this.selectedTransaction.recipient
if (displaybutton == null) {
return html`<span>${this.selectedTransaction.recipient}</span>`
} else {
return html`<span>${this.selectedTransaction.recipient}</span> <paper-icon-button icon="icons:send" @click=${() => this.sendToQortAddress()} title="Send to this address"></paper-icon-button>`
}
}
renderFetchText() { renderFetchText() {
return html`${translate("walletpage.wchange1")}` return html`${translate("walletpage.wchange1")}`
} }
@ -2646,7 +2702,6 @@ class MultiWallet extends LitElement {
} }
const sortedTransactions = txs.sort(compareFn) const sortedTransactions = txs.sort(compareFn)
console.log(sortedTransactions)
if (this._selectedWallet == coin) { if (this._selectedWallet == coin) {
this.wallets.get(this._selectedWallet).transactions = sortedTransactions this.wallets.get(this._selectedWallet).transactions = sortedTransactions
} }
@ -2900,7 +2955,7 @@ class MultiWallet extends LitElement {
render(this.renderDogeTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM) render(this.renderDogeTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
} else if (this._selectedWallet === 'dgb') { } else if (this._selectedWallet === 'dgb') {
render(this.renderDgbTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM) render(this.renderDgbTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
} else if (this._selectedWallet === 'rvn') { } else if (this._selectedWallet === 'rvn') {
render(this.renderRvnTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM) render(this.renderRvnTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
} else if (this._selectedWallet === 'arrr') { } else if (this._selectedWallet === 'arrr') {
render(this.renderArrrTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM) render(this.renderArrrTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)

View File

@ -0,0 +1,23 @@
export const blocksNeed = (level) => {
if (level === 0) {
return '7200';
} else if (level === 1) {
return '72000';
} else if (level === 2) {
return '201600';
} else if (level === 3) {
return '374400';
} else if (level === 4) {
return '618400';
} else if (level === 5) {
return '964000';
} else if (level === 6) {
return '1482400';
} else if (level === 7) {
return '2173600';
} else if (level === 8) {
return '3037600';
} else if (level === 9) {
return '4074400';
}
};