forked from Qortal/qortal-ui
Merge pull request #61 from PhillipLangMartinez/release/26-08-22
Release/26 08 22 - bug fixes
This commit is contained in:
commit
ce6ee040f1
@ -30,6 +30,7 @@ html {
|
||||
--nav-icon-color: #080808;
|
||||
--nav-border-color: #eeeeee;
|
||||
--nav-border-selected-color: #03a9f4;
|
||||
--error: #d50000;
|
||||
--background: url("/img/qortal_background_light_.jpg");
|
||||
}
|
||||
|
||||
@ -65,5 +66,6 @@ html[theme="dark"] {
|
||||
--nav-icon-color: #008fd5;
|
||||
--nav-border-color: #0b305e;
|
||||
--nav-border-selected-color: #76c8f5;
|
||||
--error: #d50000;
|
||||
--background: url("/img/qortal_background_dark_.jpg");
|
||||
}
|
||||
|
@ -174,7 +174,7 @@
|
||||
"mchange33":"Introduction",
|
||||
"mchange34":"In Qortal, in order to become a minter and begin earning QORT rewards with your increase in Minter Level, you must first become ‘sponsored’. A sponsor in Qortal is any other minter of level 5 or higher, or a Qortal Founder. You will obtain a sponsorship key from the sponsor, and use that key to get to level 1. Once you have reached level 1, you will be able to create your own minting key and start earning rewards for helping secure the Qortal Blockchain.",
|
||||
"mchange35":"Sponsorship",
|
||||
"mchange36":"Your sponsor will issue you a ‘Sponsorship Key’ which you will use to add to your node, and begin minting (for no rewards until reaching level 1.) Once you reach level 1, you create/assign your own ‘Minting Key’ and begin earning rewards. You have XXXX blocks remaining in your sponsorship period.",
|
||||
"mchange36":"Your sponsor will issue you a ‘Sponsorship Key’ which you will use to add to your node, and begin minting (for no rewards until reaching level 1.) Once you reach level 1, you create/assign your own ‘Minting Key’ and begin earning rewards.",
|
||||
"mchange37":"Simply reach out to a minter in Qortal who is high enough level to issue a sponsorship key, obtain that key, then come back here and input the key to begin your minting journey !",
|
||||
"mchange38":"in"
|
||||
},
|
||||
|
@ -2,27 +2,193 @@ import { LitElement, html, css } from 'lit';
|
||||
import { connect } from 'pwa-helpers';
|
||||
import { store } from '../store.js';
|
||||
import { translate, get } from 'lit-translate';
|
||||
import {asyncReplace} from 'lit/directives/async-replace.js';
|
||||
|
||||
import '../functional-components/my-button.js';
|
||||
import { routes } from '../plugins/routes.js';
|
||||
import "@material/mwc-button"
|
||||
|
||||
import '@material/mwc-dialog'
|
||||
|
||||
|
||||
async function* countDown(count, callback) {
|
||||
|
||||
|
||||
while (count > 0) {
|
||||
yield count--;
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
if(count === 0){
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
class StartMinting extends connect(store)(LitElement) {
|
||||
static get properties() {
|
||||
return {
|
||||
addressInfo: { type: Object },
|
||||
mintingAccountData: { type: Array },
|
||||
errorMsg: { type: String },
|
||||
openDialogRewardShare : {type: Boolean},
|
||||
status: {type: Number},
|
||||
timer: {type: Number},
|
||||
privateRewardShareKey: {type: String}
|
||||
};
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
|
||||
.dialogCustom {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
|
||||
left: 0px;
|
||||
width: 100vw;
|
||||
}
|
||||
.dialogCustomInner {
|
||||
|
||||
width: 300px;
|
||||
min-height: 400px;
|
||||
background-color: var(--white);
|
||||
box-shadow: var(--mdc-dialog-box-shadow, 0px 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12));
|
||||
padding: 20px 24px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.dialogCustomInner ul {
|
||||
padding-left: 0px
|
||||
}
|
||||
.dialogCustomInner li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.start-minting-wrapper {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(calc(-50% - 10px));
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.dialog-header h1 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modalFooter {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.hide {
|
||||
visibility: hidden
|
||||
}
|
||||
|
||||
.inactiveText {
|
||||
opacity: .60
|
||||
}
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.smallLoading,
|
||||
.smallLoading:after {
|
||||
border-radius: 50%;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.smallLoading {
|
||||
border-width: 0.6em;
|
||||
border-style: solid;
|
||||
border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2)
|
||||
rgba(3, 169, 244, 0.2) rgb(3, 169, 244);
|
||||
font-size: 10px;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
transform: translateZ(0px);
|
||||
animation: 1.1s linear 0s infinite normal none running loadingAnimation;
|
||||
}
|
||||
@-webkit-keyframes loadingAnimation {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loadingAnimation {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.word-break {
|
||||
word-break:break-all;
|
||||
}
|
||||
.dialog-container {
|
||||
width: 300px;
|
||||
min-height: 300px;
|
||||
max-height: 75vh;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
.between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.no-width {
|
||||
width: auto
|
||||
}
|
||||
|
||||
.between p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.marginLoader {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.marginRight {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.warning{
|
||||
display: flex;
|
||||
flex-grow: 1
|
||||
}
|
||||
|
||||
.message-error {
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
`,
|
||||
];
|
||||
}
|
||||
@ -32,6 +198,9 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
this.addressInfo = {};
|
||||
this.mintingAccountData = [];
|
||||
this.errorMsg = '';
|
||||
this.openDialogRewardShare = false;
|
||||
this.status = 0;
|
||||
this.privateRewardShareKey = "";
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -40,6 +209,10 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
|
||||
firstUpdated() {
|
||||
this.getMintingAcccounts();
|
||||
|
||||
|
||||
|
||||
this.shadowRoot.querySelector('mdc-dialog--open').setAttribute('style', 'width: 100vw')
|
||||
}
|
||||
|
||||
async getMintingAcccounts() {
|
||||
@ -60,6 +233,118 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
async changeStatus(value){
|
||||
const myNode =
|
||||
store.getState().app.nodeConfig.knownNodes[
|
||||
store.getState().app.nodeConfig.node
|
||||
];
|
||||
|
||||
const nodeUrl =
|
||||
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
this.status = value
|
||||
const publicAddress =
|
||||
window.parent.reduxStore.getState().app?.selectedAddress
|
||||
?.base58PublicKey;
|
||||
// Check to see if a sponsorship key on a newly-level 1 minter exists. If it does, remove it.
|
||||
const findMintingAccountFromOtherUser = this.mintingAccountData.find(
|
||||
(ma) => !ma.publicKey.includes(publicAddress)
|
||||
);
|
||||
const removeMintingAccount = async (publicKey) => {
|
||||
|
||||
const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`;
|
||||
|
||||
return await fetch(url, {
|
||||
method: 'DELETE',
|
||||
body: publicKey,
|
||||
});
|
||||
};
|
||||
|
||||
const addMintingAccount = async (sponsorshipKeyValue) => {
|
||||
const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`;
|
||||
|
||||
return await fetch(url, {
|
||||
method: 'POST',
|
||||
body: sponsorshipKeyValue,
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
if (
|
||||
findMintingAccountFromOtherUser &&
|
||||
findMintingAccountFromOtherUser?.publicKey[0]
|
||||
) {
|
||||
await removeMintingAccount(
|
||||
findMintingAccountFromOtherUser?.publicKey[0]
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
this.errorMsg = 'Failed to remove key';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await addMintingAccount(this.privateRewardShareKey);
|
||||
routes.showSnackBar({
|
||||
data: translate('becomeMinterPage.bchange19'),
|
||||
});
|
||||
this.status = 5;
|
||||
this.getMintingAcccounts();
|
||||
} catch (error) {
|
||||
this.errorMsg = 'Failed to add minting key';
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async confirmRelationship(){
|
||||
const myNode =
|
||||
store.getState().app.nodeConfig.knownNodes[
|
||||
store.getState().app.nodeConfig.node
|
||||
];
|
||||
const nodeUrl =
|
||||
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
|
||||
let interval = null
|
||||
let stop = false
|
||||
this.status = 2
|
||||
const getAnswer = async () => {
|
||||
|
||||
const rewardShares = async (minterAddr) => {
|
||||
const url = `${nodeUrl}/addresses/rewardshares?minters=${minterAddr}&recipients=${minterAddr}`;
|
||||
const res = await fetch(url);
|
||||
const data = await res.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
if (!stop) {
|
||||
stop= true;
|
||||
|
||||
try {
|
||||
|
||||
const address =
|
||||
window.parent.reduxStore.getState().app?.selectedAddress?.address;
|
||||
|
||||
const myRewardShareArray = await rewardShares(address);
|
||||
if(myRewardShareArray.length > 0){
|
||||
clearInterval(interval)
|
||||
this.status = 3
|
||||
|
||||
|
||||
this.timer = countDown(180, ()=> this.changeStatus(4));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
stop = false
|
||||
}
|
||||
};
|
||||
interval = setInterval(getAnswer, 5000);
|
||||
}
|
||||
|
||||
renderStartMintingButton() {
|
||||
const myNode =
|
||||
store.getState().app.nodeConfig.knownNodes[
|
||||
@ -70,12 +355,7 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
const mintingAccountData = this.mintingAccountData;
|
||||
|
||||
const addressInfo = this.addressInfo;
|
||||
const rewardShares = async (minterAddr) => {
|
||||
const url = `${nodeUrl}/addresses/rewardshares?minters=${minterAddr}&recipients=${minterAddr}`;
|
||||
const res = await fetch(url);
|
||||
const data = await res.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
const address =
|
||||
window.parent.reduxStore.getState().app?.selectedAddress?.address;
|
||||
const nonce =
|
||||
@ -89,17 +369,10 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
);
|
||||
const isMinterButKeyMintingKeyNotAssigned =
|
||||
addressInfo?.error !== 124 &&
|
||||
addressInfo?.level === 1 &&
|
||||
addressInfo?.level >= 1 &&
|
||||
!findMintingAccount;
|
||||
|
||||
const removeMintingAccount = async (publicKey) => {
|
||||
const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`;
|
||||
|
||||
return await fetch(url, {
|
||||
method: 'DELETE',
|
||||
body: publicKey,
|
||||
});
|
||||
};
|
||||
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
let mylastRef = lastRef;
|
||||
@ -128,35 +401,33 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
};
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
let err6string = get('rewardsharepage.rchange21');
|
||||
if(txnResponse?.extraData?.rewardSharePrivateKey && (txnResponse?.data?.message.includes('multiple') || txnResponse?.data?.message.includes('SELF_SHARE_EXISTS'))){
|
||||
return err6string
|
||||
}
|
||||
if (txnResponse.success === false && txnResponse.message) {
|
||||
throw new Error(txnResponse);
|
||||
throw(txnResponse);
|
||||
} else if (
|
||||
txnResponse.success === true &&
|
||||
!txnResponse.data.error
|
||||
) {
|
||||
let err6string = get('rewardsharepage.rchange21');
|
||||
|
||||
return err6string;
|
||||
} else {
|
||||
throw new Error(txnResponse);
|
||||
throw(txnResponse);
|
||||
}
|
||||
};
|
||||
|
||||
const createSponsorshipKey = async () => {
|
||||
this.status= 1
|
||||
let lastRef = await getLastRef();
|
||||
|
||||
let myTransaction = await makeTransactionRequest(lastRef);
|
||||
|
||||
getTxnRequestResponse(myTransaction);
|
||||
return myTransaction.data;
|
||||
return myTransaction?.extraData?.rewardSharePrivateKey
|
||||
};
|
||||
const addMintingAccount = async (sponsorshipKeyValue) => {
|
||||
const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`;
|
||||
|
||||
return await fetch(url, {
|
||||
method: 'POST',
|
||||
body: sponsorshipKeyValue,
|
||||
});
|
||||
};
|
||||
|
||||
const getLastRef = async () => {
|
||||
const url = `${nodeUrl}/addresses/lastreference/${address}`;
|
||||
@ -167,64 +438,23 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
const startMinting = async () => {
|
||||
this.openDialogRewardShare = true
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
this.privateRewardShareKey = await createSponsorshipKey();
|
||||
this.confirmRelationship(publicAddress)
|
||||
} catch (error) {
|
||||
this.errorMsg = 'Cannot create sponsorship key';
|
||||
console.log({error})
|
||||
this.errorMsg = error?.data?.message || 'Cannot create sponsorship key';
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if a sponsorship key on a newly-level 1 minter exists. If it does, remove it.
|
||||
const findMintingAccountFromOtherUser = mintingAccountData.find(
|
||||
(ma) => !ma.publicKey.includes(publicAddress)
|
||||
);
|
||||
|
||||
try {
|
||||
if (
|
||||
findMintingAccountFromOtherUser &&
|
||||
findMintingAccountFromOtherUser?.publicKey[0]
|
||||
) {
|
||||
await removeMintingAccount(
|
||||
findMintingAccountFromOtherUser?.publicKey[0]
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
this.errorMsg = 'Failed to remove key';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await addMintingAccount(sponsorshipKeyValue);
|
||||
routes.showSnackBar({
|
||||
data: translate('becomeMinterPage.bchange19'),
|
||||
});
|
||||
this.getMintingAcccounts();
|
||||
} catch (error) {
|
||||
this.errorMsg = 'Failed to add minting key';
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
return html`
|
||||
@ -246,6 +476,93 @@ class StartMinting extends connect(store)(LitElement) {
|
||||
}}
|
||||
></my-button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Dialog for tracking the progress of starting minting -->
|
||||
|
||||
|
||||
${this.openDialogRewardShare ? html`
|
||||
<div class="dialogCustom">
|
||||
<div class="dialogCustomInner">
|
||||
<div class="dialog-header" >
|
||||
<div class="row">
|
||||
<h1>In progress </h1> <div class=${`smallLoading marginLoader ${this.status > 3 && 'hide'}`}></div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
</div>
|
||||
<div class="dialog-container">
|
||||
<ul>
|
||||
|
||||
|
||||
|
||||
<li class="row between">1. Creating relationship <div class=${`smallLoading marginLoader ${this.status !== 1 && 'hide'}`}></div></li>
|
||||
<li class=${`row between ${this.status < 2 && 'inactiveText' }`}>
|
||||
<p>
|
||||
2. Awaiting confirmation on blockchain
|
||||
</p>
|
||||
<div class=${`smallLoading marginLoader ${this.status !== 2 && 'hide'}`}></div>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=${`row between ${this.status < 3 && 'inactiveText' }`}>
|
||||
<p>
|
||||
3. Finishing up relationship
|
||||
</p>
|
||||
|
||||
<div class="row no-width">
|
||||
<div class=${`smallLoading marginLoader marginRight ${this.status !== 3 && 'hide'}`} ></div> ${asyncReplace(this.timer)}
|
||||
</div>
|
||||
|
||||
|
||||
</li>
|
||||
<li class=${`row between ${this.status < 4 && 'inactiveText' }`}>
|
||||
<p>
|
||||
4. Adding minting key to node
|
||||
</p>
|
||||
<div class=${`smallLoading marginLoader ${this.status !== 4 && 'hide'}`}></div>
|
||||
|
||||
</li>
|
||||
<li class=${`row between ${this.status < 5 && 'inactiveText' }`}>
|
||||
<p>
|
||||
5. Complete
|
||||
</p>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="warning column">
|
||||
<p>
|
||||
Warning: do not close the Qortal UI until completion!
|
||||
</p>
|
||||
<p class="message-error">${this.errorMsg}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modalFooter">
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${()=>{
|
||||
this.openDialogRewardShare = false
|
||||
this.errorMsg = ''
|
||||
|
||||
}}
|
||||
class="red"
|
||||
>
|
||||
${translate("general.close")}
|
||||
</mwc-button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- </mwc-dialog> -->
|
||||
</div>
|
||||
|
||||
` : ""}
|
||||
|
||||
`
|
||||
: ''}
|
||||
`;
|
||||
|
@ -141,15 +141,21 @@ export const routes = {
|
||||
req.data.params
|
||||
);
|
||||
|
||||
if (!req.disableModal) {
|
||||
if (!req.disableModal && !req.data.disableModal) {
|
||||
await requestTransactionDialog.requestTransaction(tx);
|
||||
}
|
||||
|
||||
const res = await processTransaction(tx.signedBytes);
|
||||
let extraData = {}
|
||||
if(req.data.type === 38 && tx && tx._rewardShareKeyPair && tx._rewardShareKeyPair.secretKey){
|
||||
extraData.rewardSharePrivateKey = Base58.encode(tx._rewardShareKeyPair.secretKey)
|
||||
}
|
||||
|
||||
|
||||
response = {
|
||||
success: true,
|
||||
data: res,
|
||||
extraData
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -147,9 +147,9 @@ class BecomeMinter extends LitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log({ mintingAccountData: this.mintingAccountData });
|
||||
const findMintingAccount = this.mintingAccountData?.find(
|
||||
(ma) => !!ma.publicKey
|
||||
(ma) => ma.publicKey === window.parent.reduxStore.getState().app?.selectedAddress
|
||||
?.base58PublicKey
|
||||
);
|
||||
|
||||
const isAlreadySponsored =
|
||||
|
@ -37,8 +37,8 @@ export const pageStyles = css`
|
||||
|
||||
|
||||
|
||||
.message {
|
||||
color: var(--gray);
|
||||
.message-error {
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +62,15 @@ export const pageStyles = css`
|
||||
.row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hide {
|
||||
visibility: hidden
|
||||
}
|
||||
|
||||
.inactiveText {
|
||||
opacity: .60
|
||||
}
|
||||
.column {
|
||||
display: flex;
|
||||
@ -156,6 +165,30 @@ export const pageStyles = css`
|
||||
z-index: 9;
|
||||
position: fixed;
|
||||
}
|
||||
.marginLoader {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.marginRight {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.smallLoading,
|
||||
.smallLoading:after {
|
||||
border-radius: 50%;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.smallLoading {
|
||||
border-width: 0.6em;
|
||||
border-style: solid;
|
||||
border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2)
|
||||
rgba(3, 169, 244, 0.2) rgb(3, 169, 244);
|
||||
font-size: 10px;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
transform: translateZ(0px);
|
||||
animation: 1.1s linear 0s infinite normal none running loadingAnimation;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.loading:after {
|
||||
@ -201,9 +234,9 @@ export const pageStyles = css`
|
||||
|
||||
.tableGrid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(
|
||||
grid-template-columns: minmax(0, 3fr) minmax(0, 1fr) minmax(
|
||||
0,
|
||||
1fr
|
||||
2fr
|
||||
) minmax(0, 1fr);
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
@ -214,6 +247,16 @@ export const pageStyles = css`
|
||||
|
||||
}
|
||||
|
||||
.header {
|
||||
align-self: flex-start;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.header p {
|
||||
word-break: break-word ;
|
||||
}
|
||||
|
||||
|
||||
.grid-item {
|
||||
text-align: center;
|
||||
@ -267,7 +310,9 @@ export const pageStyles = css`
|
||||
}
|
||||
|
||||
|
||||
|
||||
.word-break {
|
||||
word-break:break-all;
|
||||
}
|
||||
.dialog-container {
|
||||
width: 300px;
|
||||
min-height: 300px;
|
||||
@ -331,6 +376,7 @@ export const pageStyles = css`
|
||||
text-decoration: none;
|
||||
margin: 0px;
|
||||
margin-right: 10px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
@ -356,4 +402,37 @@ export const pageStyles = css`
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.no-width {
|
||||
width: auto
|
||||
}
|
||||
|
||||
.between p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#showDialogRewardShareCreationStatus .dialog-container {
|
||||
width: 300px;
|
||||
min-height: 250px;
|
||||
max-height: 75vh;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.warning{
|
||||
display: flex;
|
||||
flex-grow: 1
|
||||
}
|
||||
|
||||
#showDialogRewardShareCreationStatus li {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
|
@ -13,14 +13,27 @@ import "@polymer/paper-spinner/paper-spinner-lite.js"
|
||||
import "@material/mwc-button"
|
||||
import "@material/mwc-textfield"
|
||||
import "@vaadin/button"
|
||||
import "@material/mwc-button"
|
||||
import "@polymer/paper-spinner/paper-spinner-lite.js"
|
||||
import '@material/mwc-dialog'
|
||||
import {asyncReplace} from 'lit/directives/async-replace.js';
|
||||
|
||||
import { pageStyles } from "./sponsorship-list-css.src.js"
|
||||
|
||||
const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
|
||||
|
||||
async function* countDown(count, callback) {
|
||||
|
||||
|
||||
while (count > 0) {
|
||||
yield count--;
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
if(count === 0){
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SponsorshipList extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
@ -32,11 +45,14 @@ class SponsorshipList extends LitElement {
|
||||
mintingAccountData: { type: Array },
|
||||
sponsorships: { type: Array },
|
||||
removeRewardShareLoading: { type: Array },
|
||||
createSponsorshipMessage: { type: String },
|
||||
errorMessage: { type: String },
|
||||
isLoadingCreateSponsorship: { type: Array },
|
||||
publicKeyValue: { type: String },
|
||||
error: { type: Boolean },
|
||||
isOpenModal: {type: Boolean}
|
||||
isOpenModal: {type: Boolean},
|
||||
status: {type: Number},
|
||||
privateRewardShareKey: {type: String},
|
||||
timer: {type: Number},
|
||||
openDialogRewardShare: {type: Boolean}
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,11 +70,14 @@ class SponsorshipList extends LitElement {
|
||||
this.mintingAccountData = null
|
||||
this.sponsorships = []
|
||||
this.removeRewardShareLoading = false
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
|
||||
this.errorMessage = ""
|
||||
this.isLoadingCreateSponsorship = false
|
||||
this.publicKeyValue = ""
|
||||
this.isOpenModal = false
|
||||
this.status = 0
|
||||
this.privateRewardShareKey = ""
|
||||
this.openDialogRewardShare = false
|
||||
}
|
||||
|
||||
inputHandler(e) {
|
||||
@ -108,6 +127,24 @@ class SponsorshipList extends LitElement {
|
||||
return nodeInfo
|
||||
}
|
||||
|
||||
async saveToClipboard(text) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text)
|
||||
parentEpml.request('showSnackBar', this.onSuccessMessage)
|
||||
} catch (err) {
|
||||
parentEpml.request('showSnackBar', this.onErrorMessage)
|
||||
console.error('Copy to clipboard error:', err)
|
||||
}
|
||||
}
|
||||
|
||||
changeStatus(value){
|
||||
this.status = value
|
||||
this.saveToClipboard(translate(
|
||||
"walletpage.wchange4"
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
async atMount() {
|
||||
this.changeLanguage()
|
||||
|
||||
@ -119,6 +156,8 @@ class SponsorshipList extends LitElement {
|
||||
const address =
|
||||
window.parent.reduxStore.getState().app?.selectedAddress
|
||||
?.address
|
||||
|
||||
|
||||
let rewardShares = await this.getRewardShareRelationship(
|
||||
address
|
||||
)
|
||||
@ -130,7 +169,6 @@ class SponsorshipList extends LitElement {
|
||||
type: "api",
|
||||
url: `/addresses/${rs.recipient}`,
|
||||
})
|
||||
|
||||
let blocksRemaining = this._levelUpBlocks(addressInfo)
|
||||
blocksRemaining = +blocksRemaining > 0 ? +blocksRemaining : 0
|
||||
return {
|
||||
@ -152,6 +190,7 @@ class SponsorshipList extends LitElement {
|
||||
if(openModal){
|
||||
this.shadowRoot.querySelector('#showDialog').show()
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
|
||||
@ -250,18 +289,23 @@ class SponsorshipList extends LitElement {
|
||||
removeReceiver()
|
||||
}
|
||||
|
||||
async createRewardShare(e) {
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
const recipientPublicKey = this.publicKeyValue
|
||||
async createRewardShare(publicKeyValue) {
|
||||
this.openDialogRewardShare = true
|
||||
if(!publicKeyValue){
|
||||
this.errorMessage = "unable to pull public key from the chain, account has no outgoing transactions"
|
||||
return
|
||||
}
|
||||
this.privateRewardShareKey = ""
|
||||
|
||||
this.errorMessage = ""
|
||||
const recipientPublicKey = publicKeyValue
|
||||
const percentageShare = 0
|
||||
const selectedAddress =
|
||||
window.parent.reduxStore.getState().app?.selectedAddress
|
||||
// Check for valid...
|
||||
this.isLoadingCreateSponsorship = true
|
||||
|
||||
let recipientAddress =
|
||||
window.parent.base58PublicKeyToAddress(recipientPublicKey)
|
||||
|
||||
|
||||
// Get Last Ref
|
||||
const getLastRef = async () => {
|
||||
@ -281,96 +325,39 @@ class SponsorshipList extends LitElement {
|
||||
return myAccountDetails
|
||||
}
|
||||
|
||||
// Get Reward Relationship if it already exists
|
||||
const getRewardShareRelationship = async (minterAddr) => {
|
||||
let isRewardShareExisting = false
|
||||
let myRewardShareArray = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/addresses/rewardshares?minters=${minterAddr}&recipients=${recipientAddress}`,
|
||||
})
|
||||
isRewardShareExisting =
|
||||
myRewardShareArray.length !== 0 ? true : false
|
||||
return isRewardShareExisting
|
||||
}
|
||||
|
||||
|
||||
// Validate Reward Share by Level
|
||||
const validateReceiver = async () => {
|
||||
let accountDetails = await getAccountDetails()
|
||||
let lastRef = await getLastRef()
|
||||
let isExisting = await getRewardShareRelationship(
|
||||
selectedAddress.address
|
||||
)
|
||||
let accountDetails
|
||||
try {
|
||||
accountDetails = await getAccountDetails()
|
||||
} catch (error) {
|
||||
this.errorMessage = "Couldn't fetch account details"
|
||||
}
|
||||
|
||||
// Check for creating self share at different levels (also adding check for flags...)
|
||||
if (accountDetails.flags === 1) {
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
if (isExisting === true) {
|
||||
this.error = true
|
||||
this.createSponsorshipMessage = `Cannot Create Multiple Reward Shares!`
|
||||
} else {
|
||||
// Send the transaction for confirmation by the user
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
getTxnRequestResponse(myTransaction)
|
||||
}
|
||||
} else if (accountDetails.address === recipientAddress) {
|
||||
if (accountDetails.level >= 1 && accountDetails.level <= 4) {
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
if (isExisting === true) {
|
||||
let err1string = get("rewardsharepage.rchange18")
|
||||
this.error = true
|
||||
this.createSponsorshipMessage = `${err1string}`
|
||||
} else {
|
||||
// Send the transaction for confirmation by the user
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
getTxnRequestResponse(myTransaction)
|
||||
}
|
||||
} else if (accountDetails.level >= 5) {
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
if (isExisting === true) {
|
||||
let err2string = get("rewardsharepage.rchange19")
|
||||
this.error = true
|
||||
this.createSponsorshipMessage = `${err2string}`
|
||||
} else {
|
||||
// Send the transaction for confirmation by the user
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
getTxnRequestResponse(myTransaction)
|
||||
}
|
||||
} else {
|
||||
let err3string = get("rewardsharepage.rchange20")
|
||||
this.error = true
|
||||
this.createSponsorshipMessage = `${err3string} ${accountDetails.level}`
|
||||
}
|
||||
} else {
|
||||
//Check for creating reward shares
|
||||
let lastRef = await getLastRef()
|
||||
if (accountDetails.level >= 5) {
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
if (isExisting === true) {
|
||||
let err4string = get("rewardsharepage.rchange18")
|
||||
this.error = true
|
||||
this.createSponsorshipMessage = `${err4string}`
|
||||
} else {
|
||||
// Send the transaction for confirmation by the user
|
||||
this.error = false
|
||||
this.createSponsorshipMessage = ""
|
||||
this.status = 1
|
||||
|
||||
this.errorMessage = ""
|
||||
|
||||
try {
|
||||
const myTransaction = await makeTransactionRequest(lastRef)
|
||||
|
||||
|
||||
getTxnRequestResponse(myTransaction)
|
||||
} catch (error) {
|
||||
this.errorMessage = error
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
this.error = true
|
||||
|
||||
let err5string = get("rewardsharepage.rchange20")
|
||||
this.createSponsorshipMessage = `${err5string} ${accountDetails.level}`
|
||||
}
|
||||
this.errorMessage = `${err5string} ${accountDetails.level}`
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Make Transaction Request
|
||||
@ -392,35 +379,86 @@ class SponsorshipList extends LitElement {
|
||||
rewarddialog3: rewarddialog3,
|
||||
rewarddialog4: rewarddialog4,
|
||||
},
|
||||
disableModal: true
|
||||
})
|
||||
return myTxnrequest
|
||||
}
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
if (txnResponse.success === false && txnResponse.message) {
|
||||
this.error = true
|
||||
this.createSponsorshipMessage = txnResponse.message
|
||||
throw new Error(txnResponse)
|
||||
|
||||
if(txnResponse?.extraData?.rewardSharePrivateKey && (txnResponse?.data?.message.includes('multiple') || txnResponse?.data?.message.includes('SELF_SHARE_EXISTS')) ){
|
||||
|
||||
this.privateRewardShareKey = txnResponse?.extraData?.rewardSharePrivateKey
|
||||
this.confirmRelationship(publicKeyValue)
|
||||
} else if (txnResponse.success === false && txnResponse?.message) {
|
||||
|
||||
this.errorMessage = txnResponse?.message
|
||||
this.isLoadingCreateSponsorship = false
|
||||
throw(txnResponse?.message)
|
||||
} else if (
|
||||
txnResponse.success === true &&
|
||||
!txnResponse.data.error
|
||||
) {
|
||||
let err6string = get("rewardsharepage.rchange21")
|
||||
this.createSponsorshipMessage = err6string
|
||||
this.error = false
|
||||
|
||||
|
||||
this.privateRewardShareKey = txnResponse?.extraData?.rewardSharePrivateKey
|
||||
this.confirmRelationship(publicKeyValue)
|
||||
} else {
|
||||
this.error = true
|
||||
this.createSponsorshipMessage = txnResponse.data.message
|
||||
throw new Error(txnResponse)
|
||||
|
||||
this.errorMessage = txnResponse?.data?.message || txnResponse?.message
|
||||
this.isLoadingCreateSponsorship = false
|
||||
throw(txnResponse?.data?.message || txnResponse?.message)
|
||||
}
|
||||
}
|
||||
validateReceiver()
|
||||
this.isLoadingCreateSponsorship = false
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
async confirmRelationship(recipientPublicKey){
|
||||
this.status = 2
|
||||
let interval = null
|
||||
let stop = false
|
||||
|
||||
const getAnswer = async () => {
|
||||
|
||||
if (!stop) {
|
||||
stop= true;
|
||||
|
||||
try {
|
||||
|
||||
const recipientAddress =
|
||||
window.parent.base58PublicKeyToAddress(recipientPublicKey)
|
||||
|
||||
const minterAddress = window.parent.reduxStore.getState().app?.selectedAddress.address
|
||||
const myRewardShareArray = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/addresses/rewardshares?minters=${minterAddress}&recipients=${recipientAddress}`,
|
||||
})
|
||||
if(myRewardShareArray.length > 0){
|
||||
clearInterval(interval)
|
||||
this.status = 3
|
||||
|
||||
|
||||
this.timer = countDown(180, ()=> this.changeStatus(4));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
}
|
||||
|
||||
stop = false
|
||||
}
|
||||
};
|
||||
interval = setInterval(getAnswer, 5000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${
|
||||
this.isPageLoading
|
||||
@ -452,17 +490,17 @@ class SponsorshipList extends LitElement {
|
||||
<p>${translate("sponsorshipspage.schange1")}</p>
|
||||
</div>
|
||||
<div class="tableGrid table-header">
|
||||
<div class="grid-item">
|
||||
<div class="grid-item header">
|
||||
<p>${translate("sponsorshipspage.schange2")}</p>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<div class="grid-item header">
|
||||
<p>${translate("walletprofile.blocksminted")}</p>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<div class="grid-item header">
|
||||
<p>${translate("becomeMinterPage.bchange17")}</p>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<div class="grid-item header">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -472,33 +510,29 @@ class SponsorshipList extends LitElement {
|
||||
(sponsorship) => html`
|
||||
<ul class="tableGrid">
|
||||
<li class="grid-item">
|
||||
|
||||
<p class="grid-item-text">
|
||||
Account Address
|
||||
</p>
|
||||
${sponsorship.address}
|
||||
</li>
|
||||
<li class="grid-item">
|
||||
|
||||
<p class="grid-item-text">
|
||||
Blocks Minted
|
||||
</p>
|
||||
${+sponsorship.blocksMinted +
|
||||
+sponsorship.blocksMintedAdjustment}
|
||||
</li>
|
||||
|
||||
<li class="grid-item">
|
||||
<p class="grid-item-text">
|
||||
Copy Sponsorship Key
|
||||
</p>
|
||||
|
||||
<button-icon-copy
|
||||
title="${translate(
|
||||
"becomeMinterPage.bchange17"
|
||||
)}"
|
||||
onSuccessMessage="${translate(
|
||||
"walletpage.wchange4"
|
||||
)}"
|
||||
onErrorMessage="${translate(
|
||||
"walletpage.wchange39"
|
||||
)}"
|
||||
textToCopy=${sponsorship.rewardSharePublicKey}
|
||||
buttonSize="28px"
|
||||
iconSize="16px"
|
||||
color="var(--copybutton)"
|
||||
offsetLeft="4px"
|
||||
></button-icon-copy>
|
||||
<mwc-button @click=${()=> {
|
||||
|
||||
|
||||
this.createRewardShare(sponsorship?.publicKey)
|
||||
} }>copy</mwc-button>
|
||||
</li>
|
||||
<li class="grid-item grid-item-button">
|
||||
<mwc-button
|
||||
@ -540,7 +574,7 @@ class SponsorshipList extends LitElement {
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
<p class="message">${this.createSponsorshipMessage}</p>
|
||||
<p class="message-error">${this.errorMessage}</p>
|
||||
<div class="form-wrapper">
|
||||
<div class="sponsor-minter-wrapper">
|
||||
<p class="sponsor-minter-text">${translate("sponsorshipspage.schange5")}</p>
|
||||
@ -559,17 +593,11 @@ class SponsorshipList extends LitElement {
|
||||
<div class="form-item form-item--button">
|
||||
<vaadin-button
|
||||
?disabled="${this.isLoadingCreateSponsorship || !this.publicKeyValue}"
|
||||
@click="${this.createRewardShare}"
|
||||
@click="${()=> this.createRewardShare(this.publicKeyValue)}"
|
||||
>
|
||||
${
|
||||
this.isLoadingCreateSponsorship === false
|
||||
? html`${translate(
|
||||
${translate(
|
||||
"puzzlepage.pchange15"
|
||||
)}`
|
||||
: html`<paper-spinner-lite
|
||||
active
|
||||
></paper-spinner-lite>`
|
||||
}
|
||||
)}
|
||||
</vaadin-button>
|
||||
</div>
|
||||
</div>
|
||||
@ -598,6 +626,85 @@ class SponsorshipList extends LitElement {
|
||||
${translate("general.close")}
|
||||
</mwc-button>
|
||||
|
||||
</mwc-dialog>
|
||||
<mwc-dialog escapeKeyAction="" scrimClickAction="" id="showDialogRewardShareCreationStatus" ?hideActions=${this.errorMessage ? false : this.status < 4 ? true : false} ?open=${this.openDialogRewardShare}>
|
||||
|
||||
<div class="dialog-header" >
|
||||
<div class="row">
|
||||
<h1>In progress </h1> <div class=${`smallLoading marginLoader ${this.status > 3 && 'hide'}`}></div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
</div>
|
||||
<div class="dialog-container">
|
||||
<ul>
|
||||
|
||||
|
||||
|
||||
<li class="row between">1. Creating relationship <div class=${`smallLoading marginLoader ${this.status !== 1 && 'hide'}`}></div></li>
|
||||
<li class=${`row between ${this.status < 2 && 'inactiveText' }`}>
|
||||
<p>
|
||||
2. Awaiting confirmation on blockchain
|
||||
</p>
|
||||
<div class=${`smallLoading marginLoader ${this.status !== 2 && 'hide'}`}></div>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=${`row between ${this.status < 3 && 'inactiveText' }`}>
|
||||
<p>
|
||||
3. Finishing up
|
||||
</p>
|
||||
|
||||
<div class="row no-width">
|
||||
<div class=${`smallLoading marginLoader marginRight ${this.status !== 3 && 'hide'}`} ></div> ${asyncReplace(this.timer)}
|
||||
</div>
|
||||
|
||||
|
||||
</li>
|
||||
<li class=${`row between ${this.status < 4 && 'inactiveText' }`}>
|
||||
<p>
|
||||
4. Complete
|
||||
</p>
|
||||
|
||||
|
||||
</li>
|
||||
${this.privateRewardShareKey && this.status === 4 ? html`
|
||||
<li class=${`column word-break ${this.status < 4 && 'inactiveText' }`}>
|
||||
|
||||
<p>Copy the key below and share it with your sponsored person.</p>
|
||||
<div style="background: #eee; padding: 8px; margin: 8px 0; border-radius: 5px;">
|
||||
<span style="color: #000;">${this.privateRewardShareKey}</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
` : ''}
|
||||
</ul>
|
||||
<div class="warning column">
|
||||
<p>
|
||||
Warning: do not close the Qortal UI until completion!
|
||||
</p>
|
||||
<p class="message-error">${this.errorMessage}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${()=>{
|
||||
this.openDialogRewardShare = false
|
||||
this.errorMessage = ''
|
||||
this.isLoadingCreateSponsorship = false
|
||||
this.privateRewardShareKey = ""
|
||||
this.atMount()
|
||||
}}
|
||||
class="red"
|
||||
>
|
||||
${translate("general.close")}
|
||||
</mwc-button>
|
||||
|
||||
|
||||
</mwc-dialog>
|
||||
</div>
|
||||
`
|
||||
|
Loading…
x
Reference in New Issue
Block a user