diff --git a/qortal-ui-core/language/de.json b/qortal-ui-core/language/de.json index f10ddfe7..cedb6452 100644 --- a/qortal-ui-core/language/de.json +++ b/qortal-ui-core/language/de.json @@ -128,7 +128,11 @@ "snack2":"UI mit Knoten verbunden", "snack3":"Benutzerdefinierter Knoten erfolgreich hinzugefügt und gespeichert", "snack4":"Knoten erfolgreich gespeichert als", - "snack5":"Knoten erfolgreich importiert" + "snack5":"Knoten erfolgreich importiert", + "exp1":"Privaten Hauptschlüssel exportieren", + "exp2":"Hauptschlüssel exportieren", + "exp3":"Exportieren", + "exp4":"Bitte wählen Sie eine Brieftasche aus, um den privaten Hauptschlüssel zu sichern." }, "appinfo":{ "blockheight":"Blockhöhe", diff --git a/qortal-ui-core/language/es.json b/qortal-ui-core/language/es.json index 4ae55367..adf6d85c 100644 --- a/qortal-ui-core/language/es.json +++ b/qortal-ui-core/language/es.json @@ -128,7 +128,11 @@ "snack2":"UI conectada al nodo", "snack3":"Nodo personalizado agregado y guardado con éxito", "snack4":"Nodos guardados con éxito como", - "snack5":"Nodos importados con éxito" + "snack5":"Nodos importados con éxito", + "exp1":"Exportar clave maestra privada", + "exp2":"Exportar clave maestra", + "exp3":"Exportar", + "exp4":"Elija una billetera para hacer una copia de seguridad de la clave maestra privada." }, "appinfo":{ "blockheight":"Altura del Bloque", diff --git a/qortal-ui-core/language/fr.json b/qortal-ui-core/language/fr.json index 03b21617..86b02d49 100644 --- a/qortal-ui-core/language/fr.json +++ b/qortal-ui-core/language/fr.json @@ -128,7 +128,11 @@ "snack2":"Interface utilisateur connectée au noeud", "snack3":"Noeud personnalisé ajouté et enregistré avec succès", "snack4":"Les noeuds ont été enregistrés avec succès sous", - "snack5":"Les noeuds ont été importés avec succès" + "snack5":"Les noeuds ont été importés avec succès", + "exp1":"Exporter la clé principale privée", + "exp2":"Exporter la clé principale", + "exp3":"Exporter", + "exp4":"Veuillez choisir un portefeuille pour sauvegarder la clé principale privée." }, "appinfo":{ "blockheight":"Hauteur de bloc", diff --git a/qortal-ui-core/language/hindi.json b/qortal-ui-core/language/hindi.json index 02479e0f..e82ab1b0 100644 --- a/qortal-ui-core/language/hindi.json +++ b/qortal-ui-core/language/hindi.json @@ -129,7 +129,11 @@ "snack2":"यूआई नोड से जुड़ा", "snack3":"कस्टम नोड को सफलतापूर्वक जोड़ा और सहेजा गया", "snack4":"नोड्स सफलतापूर्वक सहेजे गए", - "snack5":"नोड्स सफलतापूर्वक आयात किए गए" + "snack5":"नोड्स सफलतापूर्वक आयात किए गए", + "exp1":"निजी मास्टर कुंजी निर्यात करें", + "exp2":"निर्यात मास्टर कुंजी", + "exp3":"निर्यात", + "exp4":"निजी मास्टर कुंजी का बैकअप लेने के लिए कृपया एक वॉलेट चुनें।" }, "appinfo":{ "blockheight":"ब्लॉक ऊँचाई", diff --git a/qortal-ui-core/language/hr.json b/qortal-ui-core/language/hr.json index dc066af8..40689c8f 100644 --- a/qortal-ui-core/language/hr.json +++ b/qortal-ui-core/language/hr.json @@ -128,7 +128,11 @@ "snack2":"UI spojen na čvor", "snack3":"Uspješno dodan i spremljen prilagođeni čvor", "snack4":"Čvorovi su uspješno spremljeni kao", - "snack5":"Čvorovi su uspješno uvezeni" + "snack5":"Čvorovi su uspješno uvezeni", + "exp1":"Izvezi privatni glavni ključ", + "exp2":"Glavni ključ izvoza", + "exp3":"Izvoz", + "exp4":"Odaberite novčanik za sigurnosnu kopiju privatnog glavnog ključa." }, "appinfo":{ "blockheight":"Visina bloka", diff --git a/qortal-ui-core/language/hu.json b/qortal-ui-core/language/hu.json index 76f9fed4..7b57ad70 100644 --- a/qortal-ui-core/language/hu.json +++ b/qortal-ui-core/language/hu.json @@ -128,7 +128,11 @@ "snack2":"UI csatlakozik a csomóponthoz", "snack3":"Az egyéni csomópont sikeresen hozzáadva és mentve", "snack4":"A csomópontok sikeresen mentve másként", - "snack5":"A csomópontok sikeresen importálva" + "snack5":"A csomópontok sikeresen importálva", + "exp1":"Privát főkulcs exportálása", + "exp2":"Főkulcs exportálása", + "exp3":"Exportálás", + "exp4":"Kérjük, válasszon egy tárcát a privát főkulcs biztonsági mentéséhez." }, "appinfo":{ "blockheight":"Blokk Magassága", diff --git a/qortal-ui-core/language/it.json b/qortal-ui-core/language/it.json index 42e55e2e..e669f6de 100644 --- a/qortal-ui-core/language/it.json +++ b/qortal-ui-core/language/it.json @@ -128,7 +128,11 @@ "snack2":"Interfaccia utente collegata al nodo", "snack3":"Nodo personalizzato aggiunto e salvato con successo", "snack4":"Nodi salvati con successo come", - "snack5":"Nodi importati correttamente" + "snack5":"Nodi importati correttamente", + "exp1":"Esporta chiave master privata", + "exp2":"Esporta chiave master", + "exp3":"Esporta", + "exp4":"Scegli un portafoglio per il backup della chiave master privata." }, "appinfo":{ "blockheight":"Altezza blocco", diff --git a/qortal-ui-core/language/ko.json b/qortal-ui-core/language/ko.json index 2124eec4..4eed1cbc 100644 --- a/qortal-ui-core/language/ko.json +++ b/qortal-ui-core/language/ko.json @@ -128,7 +128,11 @@ "snack2":"노드에 연결된 UI", "snack3":"사용자 정의 노드를 성공적으로 추가하고 저장했습니다.", "snack4":"노드가 다음으로 성공적으로 저장되었습니다", - "snack5":"노드를 성공적으로 가져왔습니다." + "snack5":"노드를 성공적으로 가져왔습니다.", + "exp1":"개인 마스터 키 내보내기", + "exp2":"마스터 키 내보내기", + "exp3":"내보내기", + "exp4":"개인 마스터 키를 백업할 지갑을 선택하세요." }, "appinfo":{ "blockheight":"블록 높이", diff --git a/qortal-ui-core/language/no.json b/qortal-ui-core/language/no.json index a38abbe8..7795fa96 100644 --- a/qortal-ui-core/language/no.json +++ b/qortal-ui-core/language/no.json @@ -128,7 +128,11 @@ "snack2":"UI koblet til node", "snack3":"Egendefinert node er lagt til og lagret", "snack4":"Noder ble lagret som", - "snack5":"Noder ble importert" + "snack5":"Noder ble importert", + "exp1":"Eksporter privat hovednøkkel", + "exp2":"Eksporter hovednøkkel", + "exp3":"Eksporter", + "exp4":"Velg en lommebok for å sikkerhetskopiere den private hovednøkkelen." }, "appinfo":{ "blockheight":"Blokkhøyde", diff --git a/qortal-ui-core/language/pl.json b/qortal-ui-core/language/pl.json index aff8fbd4..5fbd3224 100644 --- a/qortal-ui-core/language/pl.json +++ b/qortal-ui-core/language/pl.json @@ -128,7 +128,11 @@ "snack2":"Interfejs użytkownika połączony z węzłem", "snack3":"Pomyślnie dodano i zapisano niestandardowy węzeł", "snack4":"Węzły pomyślnie zapisane jako", - "snack5":"Węzły pomyślnie zaimportowane" + "snack5":"Węzły pomyślnie zaimportowane", + "exp1":"Eksportuj prywatny klucz główny", + "exp2":"Eksportuj klucz główny", + "exp3":"Eksportuj", + "exp4":"Wybierz portfel do wykonania kopii zapasowej prywatnego klucza głównego." }, "appinfo":{ "blockheight":"Wysokość bloku", diff --git a/qortal-ui-core/language/pt.json b/qortal-ui-core/language/pt.json index 035986c0..c731226f 100644 --- a/qortal-ui-core/language/pt.json +++ b/qortal-ui-core/language/pt.json @@ -128,7 +128,11 @@ "snack2":"UI conectada ao nó", "snack3":"Nó personalizado adicionado e salvo com sucesso", "snack4":"Nós salvos com sucesso como", - "snack5":"Nós importados com sucesso" + "snack5":"Nós importados com sucesso", + "exp1":"Exportar Chave Mestra Privada", + "exp2":"Exportar Chave Mestra", + "exp3":"Exportar", + "exp4":"Por favor, escolha uma carteira para fazer backup da chave mestra privada." }, "appinfo":{ "blockheight":"Altura do Bloco", diff --git a/qortal-ui-core/language/ro.json b/qortal-ui-core/language/ro.json index 891a0be4..60bce846 100644 --- a/qortal-ui-core/language/ro.json +++ b/qortal-ui-core/language/ro.json @@ -128,7 +128,11 @@ "snack2":"Interfata de utilizare conectata la nod", "snack3":"Nod personalizat adaugat si salvat cu succes", "snack4":"Nodurile au fost salvate cu succes ca", - "snack5":"Nodurile au fost importate cu succes" + "snack5":"Nodurile au fost importate cu succes", + "exp1":"Exportați cheia principală privată", + "exp2":"Exportați cheia principală", + "exp3":"Export", + "exp4":"Vă rugăm să alegeți un portofel pentru a face backup cheii master private." }, "appinfo":{ "blockheight":"Dimensiunea blocului", diff --git a/qortal-ui-core/language/rs.json b/qortal-ui-core/language/rs.json index 432280f7..c7ad6d88 100644 --- a/qortal-ui-core/language/rs.json +++ b/qortal-ui-core/language/rs.json @@ -128,7 +128,11 @@ "snack2":"UI je povezan sa čvorom", "snack3":"Uspešno dodat i sačuvan prilagođeni čvor", "snack4":"Čvorovi su uspešno sačuvani kao", - "snack5":"Čvorovi su uspešno uvezeni" + "snack5":"Čvorovi su uspešno uvezeni", + "exp1":"Izvezi privatni glavni ključ", + "exp2":"Izvezi glavni ključ", + "exp3":"Izvoz", + "exp4":"Molimo izaberite novčanik za rezervnu kopiju privatnog glavnog ključa." }, "appinfo":{ "blockheight":"Visina Bloka", diff --git a/qortal-ui-core/language/ru.json b/qortal-ui-core/language/ru.json index e40c5ae3..abad841f 100644 --- a/qortal-ui-core/language/ru.json +++ b/qortal-ui-core/language/ru.json @@ -128,7 +128,11 @@ "snack2":"Пользовательский интерфейс, подключенный к узлу", "snack3":"Пользовательский узел успешно добавлен и сохранен", "snack4":"Узлы успешно сохранены как", - "snack5":"Узлы успешно импортированы" + "snack5":"Узлы успешно импортированы", + "exp1":"Экспорт закрытого мастер-ключа", + "exp2":"Экспорт мастер-ключа", + "exp3":"Экспорт", + "exp4":"Пожалуйста, выберите кошелек для резервного копирования приватного главного ключа." }, "appinfo":{ "blockheight":"Высота блока", diff --git a/qortal-ui-core/language/us.json b/qortal-ui-core/language/us.json index 7da41ef0..580d0549 100644 --- a/qortal-ui-core/language/us.json +++ b/qortal-ui-core/language/us.json @@ -128,7 +128,11 @@ "snack2":"UI conected to node", "snack3":"Successfully added and saved custom node", "snack4":"Nodes successfully saved as", - "snack5":"Nodes successfully imported" + "snack5":"Nodes successfully imported", + "exp1":"Export Private Master Key", + "exp2":"Export Master Key", + "exp3":"Export", + "exp4":"Please choose a wallet to backup the private master key." }, "appinfo":{ "blockheight":"Block Height", diff --git a/qortal-ui-core/language/zhc.json b/qortal-ui-core/language/zhc.json index dfd1d98d..b41114a8 100644 --- a/qortal-ui-core/language/zhc.json +++ b/qortal-ui-core/language/zhc.json @@ -128,7 +128,11 @@ "snack2":"连接到节点的 UI", "snack3":"成功添加并保存自定义节点", "snack4":"节点成功保存为", - "snack5":"节点成功导入" + "snack5":"节点成功导入", + "exp1":"导出主密钥", + "exp2":"导出主密钥", + "exp3":"导出", + "exp4":"请选择一个钱包来备份私钥。" }, "appinfo":{ "blockheight":"区块高度", diff --git a/qortal-ui-core/language/zht.json b/qortal-ui-core/language/zht.json index 7572a9df..52fa5400 100644 --- a/qortal-ui-core/language/zht.json +++ b/qortal-ui-core/language/zht.json @@ -128,7 +128,11 @@ "snack2":"連接到節點的 UI", "snack3":"成功添加並保存自定義節點", "snack4":"節點成功保存為", - "snack5":"節點成功導入" + "snack5":"節點成功導入", + "exp1":"導出主密鑰", + "exp2":"導出主密鑰", + "exp3":"導出", + "exp4":"請選擇一個錢包來備份私鑰。" }, "appinfo":{ "blockheight":"區塊高度", diff --git a/qortal-ui-core/src/components/settings-view/export-keys.js b/qortal-ui-core/src/components/settings-view/export-keys.js new file mode 100644 index 00000000..1456ce3a --- /dev/null +++ b/qortal-ui-core/src/components/settings-view/export-keys.js @@ -0,0 +1,236 @@ +import { LitElement, html, css } from 'lit' +import { connect } from 'pwa-helpers' +import { store } from '../../store.js' +import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate' + +import '@material/mwc-dialog' +import '@material/mwc-button' +import '@material/mwc-icon' +import FileSaver from 'file-saver' + +class ExportKeys extends connect(store)(LitElement) { + static get properties() { + return { + theme: { type: String, reflect: true }, + backupErrorMessage: { type: String }, + btcPMK: { type: String }, + ltcPMK: { type: String }, + dogePMK: { type: String }, + dgbPMK: { type: String }, + rvnPMK: { type: String }, + btcWALLET: { type: String }, + ltcWALLET: { type: String }, + dogeWALLET: { type: String }, + dgbWALLET: { type: String }, + rvnWALLET: { type: String }, + btcName: { type: String }, + ltcName: { type: String }, + dogeName: { type: String }, + dgbName: { type: String }, + rvnName: { type: String }, + btcShort: { type: String }, + ltcShort: { type: String }, + dogeShort: { type: String }, + dgbShort: { type: String }, + rvnShort: { type: String }, + dWalletAddress: { type: String }, + dPrivateKey: { type: String }, + dCoinName: { type: String }, + dCoinShort: { type: String } + } + } + + static get styles() { + return css` + * { + --mdc-theme-primary: rgb(3, 169, 244); + --mdc-theme-surface: var(--white); + --mdc-dialog-content-ink-color: var(--black); + --mdc-dialog-min-width: 500px; + --mdc-dialog-max-width: 500px; + --lumo-primary-text-color: rgb(0, 167, 245); + --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); + --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); + --lumo-primary-color: hsl(199, 100%, 48%); + --lumo-base-color: var(--white); + --lumo-body-text-color: var(--black); + --lumo-secondary-text-color: var(--sectxt); + --lumo-contrast-60pct: var(--vdicon); + } + + .center-box { + position: absolute; + width: 100%; + top: 50%; + left: 50%; + transform: translate(-50%, 0%); + text-align: center; + } + + .sub-main { + position: relative; + text-align: center; + width: 100%; + } + + .content-box { + text-align: center; + display: inline-block; + min-width: 400px; + margin-bottom: 10px; + margin-left: 10px; + margin-top: 20px; + } + + .export-button { + display: inline-flex; + flex-direction: column; + justify-content: center; + align-content: center; + border: none; + border-radius: 20px; + padding-left: 10px; + padding-right: 10px; + color: white; + background: #03a9f4; + width: 75%; + font-size: 16px; + cursor: pointer; + height: 40px; + margin-top: 1rem; + text-transform: uppercase; + text-decoration: none; + transition: all .2s; + position: relative; + } + + .red { + --mdc-theme-primary: red; + } + ` + } + + constructor() { + super() + this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' + this.backupErrorMessage = '' + this.btcPMK = store.getState().app.selectedAddress.btcWallet.derivedMasterPrivateKey + this.btcWALLET = store.getState().app.selectedAddress.btcWallet.address + this.btcName = 'Bitcoin' + this.btcShort = 'btc' + this.ltcPMK = store.getState().app.selectedAddress.ltcWallet.derivedMasterPrivateKey + this.ltcWALLET = store.getState().app.selectedAddress.ltcWallet.address + this.ltcName = 'Litecoin' + this.ltcShort = 'ltc' + this.dogePMK = store.getState().app.selectedAddress.dogeWallet.derivedMasterPrivateKey + this.dogeWALLET = store.getState().app.selectedAddress.dogeWallet.address + this.dogeName = 'Dogecoin' + this.dogeShort = 'doge' + this.dgbPMK = store.getState().app.selectedAddress.dgbWallet.derivedMasterPrivateKey + this.dgbWALLET = store.getState().app.selectedAddress.dgbWallet.address + this.dgbName = 'Digibyte' + this.dgbShort = 'dgb' + this.rvnPMK = store.getState().app.selectedAddress.rvnWallet.derivedMasterPrivateKey + this.rvnWALLET = store.getState().app.selectedAddress.rvnWallet.address + this.rvnName = 'Ravencoin' + this.rvnShort = 'rvn' + this.dWalletAddress = '' + this.dPrivateKey = '' + this.dCoinName = '' + this.dCoinShort = 'btc' + } + + render() { + return html` +
+
+

+ ${translate("settings.exp4")} +

+
+
+
+
+
+   ${this.btcWALLET}
+
+
this.checkForPmkDownload(this.btcWALLET, this.btcPMK, this.btcName, this.btcShort)} class="export-button"> ${translate("settings.exp2")}
+
+
+
+   ${this.ltcWALLET}
+
+
this.checkForPmkDownload(this.ltcWALLET, this.ltcPMK, this.ltcName, this.ltcShort)} class="export-button"> ${translate("settings.exp2")}
+
+
+
+   ${this.dogeWALLET}
+
+
this.checkForPmkDownload(this.dogeWALLET, this.dogePMK, this.dogeName, this.dogeShort)} class="export-button"> ${translate("settings.exp2")}
+
+
+
+   ${this.dgbWALLET}
+
+
this.checkForPmkDownload(this.dgbWALLET, this.dgbPMK, this.dgbName, this.dgbShort)} class="export-button"> ${translate("settings.exp2")}
+
+
+
+   ${this.rvnWALLET}
+
+
this.checkForPmkDownload(this.rvnWALLET, this.rvnPMK, this.rvnName, this.rvnShort)} class="export-button"> ${translate("settings.exp2")}
+
+
+
+ + +

${this.dCoinName} ${translate("settings.exp2")}

+
+

${translate("settings.address")}: ${this.dWalletAddress}

+ + ${translate("general.close")} + + + ${translate("settings.exp3")} + +
+
+ ` + } + + closeSavePkmDialog() { + this.shadowRoot.querySelector('#savePkmDialog').close() + } + + checkForPmkDownload(wAddress, wPkm, wName, wShort) { + this.dWalletAddress = '' + this.dPrivateKey = '' + this.dCoinName = '' + this.dCoinShort = '' + this.dWalletAddress = wAddress + this.dPrivateKey = wPkm + this.dCoinName = wName + this.dCoinShort = wShort + this.shadowRoot.querySelector('#savePkmDialog').show() + } + + async exportKey(cMasterKey, cName, cAddress) { + const myPrivateMasterKey = cMasterKey + const myCoinName = cName + const myCoinAddress = cAddress + const blob = new Blob([`${myPrivateMasterKey}`], { type: 'text/plain;charset=utf-8' }) + FileSaver.saveAs(blob, `Private_Master_Key_${myCoinName}_${myCoinAddress}.txt`) + } + + stateChanged(state) { + } +} + +window.customElements.define('export-keys', ExportKeys) diff --git a/qortal-ui-core/src/components/settings-view/user-settings.js b/qortal-ui-core/src/components/settings-view/user-settings.js index 4d522f17..66a8c887 100644 --- a/qortal-ui-core/src/components/settings-view/user-settings.js +++ b/qortal-ui-core/src/components/settings-view/user-settings.js @@ -10,6 +10,7 @@ import './account-view.js' import './security-view.js' import './notifications-view.js' import './qr-login-view.js' +import './export-keys.js' import { doLogout } from '../../redux/app/app-actions.js' @@ -156,6 +157,7 @@ class UserSettings extends connect(store)(LitElement) { font-size: 16px; text-align: center; min-height: 460px; + height: 60vh; } @media(max-width:700px) { @@ -226,6 +228,7 @@ class UserSettings extends connect(store)(LitElement) { @@ -247,25 +250,29 @@ class UserSettings extends connect(store)(LitElement) { renderSettingViews(selectedView) { if (selectedView.id === 'info') { - return html``; + return html`` } else if (selectedView.id === 'security') { - return html``; + return html`` + } else if (selectedView.id === 'export') { + return html`` } else if (selectedView.id === 'notification') { - return html``; + return html`` } else if (selectedView.id === 'qr-login') { - return html``; + return html`` } } renderHeaderViews() { if (this.selectedView.id === 'info') { - return html`${translate("settings.generalinfo")}`; + return html`${translate("settings.generalinfo")}` } else if (this.selectedView.id === 'security') { - return html`${translate("settings.accountsecurity")}`; + return html`${translate("settings.accountsecurity")}` + } else if (this.selectedView.id === 'export') { + return html`${translate("settings.exp1")}` } else if (this.selectedView.id === 'notification') { - return html`UI ${translate("settings.notifications")}`; + return html`UI ${translate("settings.notifications")}` } else if (this.selectedView.id === 'qr-login') { - return html`${translate("settings.qr_login_menu_item")}`; + return html`${translate("settings.qr_login_menu_item")}` } } @@ -274,6 +281,8 @@ class UserSettings extends connect(store)(LitElement) { return this.selectedView = { id: 'info', name: 'General Account Info' } } else if (pageId === 'security') { return this.selectedView = { id: 'security', name: 'Account Security' } + } else if (pageId === 'export') { + return this.selectedView = { id: 'export', name: 'Export Master Keys' } } else if (pageId === 'notification') { return this.selectedView = { id: 'notification', name: 'UI Notifications' } } else if (pageId === 'qr-login') {