+ beautifier
* version info
This commit is contained in:
7
.unibeautifyrc.json
Normal file
7
.unibeautifyrc.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"LANGUAGE_NAME": {
|
||||
"beautifiers": [
|
||||
"JS-Beautify"
|
||||
]
|
||||
}
|
||||
}
|
||||
62
index.html
62
index.html
@@ -1,5 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Ether-1 Desktop Wallet</title>
|
||||
@@ -17,7 +18,12 @@
|
||||
<link rel="stylesheet" href="./assets/styles/style.css">
|
||||
<link rel="stylesheet" href="./assets/styles/forms.css">
|
||||
<!-- Insert this line above script imports -->
|
||||
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
|
||||
<script>
|
||||
if (typeof module === 'object') {
|
||||
window.module = module;
|
||||
module = undefined;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- normal script imports etc -->
|
||||
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.36/dist/web3.min.js" integrity="sha256-nWBTbvxhJgjslRyuAKJHK+XcZPlCnmIAAMixz6EefVk=" crossorigin="anonymous"></script>
|
||||
@@ -39,15 +45,15 @@
|
||||
<script src="./assets/scripts/Chart.js"></script>
|
||||
|
||||
<!-- Insert this line after script imports -->
|
||||
<script>if (window.module) module = window.module;</script>
|
||||
<script>
|
||||
if (window.module)
|
||||
module = window.module;
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
var loading_screen = pleaseWait({
|
||||
logo: "assets/images/logo.png",
|
||||
backgroundColor: '#000000',
|
||||
loadingHtml: "<div class='spinner'><div class='bounce bounce1'></div><div class='bounce bounce2'></div><div class='bounce bounce3'></div></div><div class='loadingText'>Starting the node and loading app, please wait...</div>"
|
||||
});
|
||||
var loading_screen = pleaseWait({logo: "assets/images/logo.png", backgroundColor: '#000000', loadingHtml: "<div class='spinner'><div class='bounce bounce1'></div><div class='bounce bounce2'></div><div class='bounce bounce3'></div></div><div class='loadingText'>Starting the node and loading app, please wait...</div>"});
|
||||
|
||||
$(document).on("onGethReady", function () {
|
||||
loading_screen.finish();
|
||||
@@ -61,22 +67,34 @@
|
||||
<!-- The sidebar -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebarIconWrapper iconSelected" id="mainNavBtnWalletsWrapper" data-tippy="Wallets" data-tippy-delay="500">
|
||||
<a class="sidebarIcon" id="mainNavBtnWallets" href="#"><i class="fas fa-wallet fa-2x"></i></a>
|
||||
<a class="sidebarIcon" id="mainNavBtnWallets" href="#">
|
||||
<i class="fas fa-wallet fa-2x"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebarIconWrapper iconSelected" id="mainNavBtnAddressBoookWrapper" data-tippy="Address Book" data-tippy-delay="500">
|
||||
<a class="sidebarIcon" id="mainNavBtnAddressBoook" href="#"><i class="far fa-address-book fa-2x"></i></a>
|
||||
<a class="sidebarIcon" id="mainNavBtnAddressBoook" href="#">
|
||||
<i class="far fa-address-book fa-2x"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebarIconWrapper" id="mainNavBtnSendWrapper" data-tippy="Send Funds" data-tippy-delay="500">
|
||||
<a class="sidebarIcon" id="mainNavBtnSend" href="#"><i class="fas fas fa-share-square fa-2x"></i></a>
|
||||
<a class="sidebarIcon" id="mainNavBtnSend" href="#">
|
||||
<i class="fas fas fa-share-square fa-2x"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebarIconWrapper" id="mainNavBtnTransactionsWrapper" data-tippy="Transactions" data-tippy-delay="500">
|
||||
<a class="sidebarIcon" id="mainNavBtnTransactions" href="#"><i class="fas fa-exchange-alt fa-2x"></i></a>
|
||||
<a class="sidebarIcon" id="mainNavBtnTransactions" href="#">
|
||||
<i class="fas fa-exchange-alt fa-2x"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebarIconWrapper" id="mainNavBtnMarketsWrapper" data-tippy="Markets" data-tippy-delay="500">
|
||||
<a class="sidebarIcon" id="mainNavBtnMarkets" href="#"><i class="fas fa-poll fa-2x"></i></a>
|
||||
<a class="sidebarIcon" id="mainNavBtnMarkets" href="#">
|
||||
<i class="fas fa-poll fa-2x"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebarIconWrapper" id="mainNavBtnSettingsWrapper" data-tippy="Settings" data-tippy-delay="500">
|
||||
<a class="sidebarIcon" id="mainNavBtnSettings" href="#"><i class="fas fa-cog fa-2x"></i></a>
|
||||
<a class="sidebarIcon" id="mainNavBtnSettings" href="#">
|
||||
<i class="fas fa-cog fa-2x"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div id="peerCount">
|
||||
Peer Count: 0
|
||||
@@ -102,7 +120,7 @@
|
||||
</div>
|
||||
|
||||
<!-- The modal for general error -->
|
||||
<div id="dlgGeneralError" class="modalDialog" data-iziModal-title="Application Error" data-iziModal-subtitle="Something went wrong, don't kill the fish..." data-iziModal-icon="icon-home">
|
||||
<div id="dlgGeneralError" class="modalDialog" data-izimodal-title="Application Error" data-izimodal-subtitle="Something went wrong, don't kill the fish..." data-izimodal-icon="icon-home">
|
||||
<div class="modalBody">
|
||||
<div class="form-group">
|
||||
<span id="txtGeneralError"></span>
|
||||
@@ -112,7 +130,7 @@
|
||||
</div>
|
||||
|
||||
<!-- The modal for general confirmation -->
|
||||
<div id="dlgGeneralConfirm" class="modalDialog" data-iziModal-title="Confirmation" data-iziModal-subtitle="" data-iziModal-icon="icon-home">
|
||||
<div id="dlgGeneralConfirm" class="modalDialog" data-izimodal-title="Confirmation" data-izimodal-subtitle="" data-izimodal-icon="icon-home">
|
||||
<div class="modalBody">
|
||||
<div class="form-group">
|
||||
<span id="txtGeneralConfirm"></span>
|
||||
@@ -123,16 +141,22 @@
|
||||
</div>
|
||||
|
||||
<!-- The modal for about info -->
|
||||
<div id="dlgAboutInfo" class="modalDialog" data-iziModal-title="About Ether1 Wallet" data-iziModal-icon="icon-home">
|
||||
<div id="dlgAboutInfo" class="modalDialog" data-izimodal-title="About Ether1 Wallet" data-izimodal-icon="icon-home">
|
||||
<div class="modalBody">
|
||||
<div class="aboutInfo">
|
||||
<div class="infoText" id="aboutInfoWallet">Ether1 Wallet</div>
|
||||
<div class="infoText" id="aboutInfoGitHub">GitHub: <a id="urlOpenGitHub" href="https://github.com/taeguscromis/Ether1DesktopWallet">https://github.com/taeguscromis/Ether1DesktopWallet</a></div>
|
||||
<div class="infoText" id="aboutInfoLicence">Made under <a id="urlOpenLicence" href="https://choosealicense.com/licenses/gpl-3.0">GPL v3.0</a> licence</div>
|
||||
<div class="infoText" id="aboutInfoVersion">Version: <span id="versionNumber"></span></div>
|
||||
<div class="infoText" id="aboutInfoGitHub">GitHub:
|
||||
<a id="urlOpenGitHub" href="https://github.com/taeguscromis/Ether1DesktopWallet">https://github.com/taeguscromis/Ether1DesktopWallet</a>
|
||||
</div>
|
||||
<div class="infoText" id="aboutInfoLicence">Made under
|
||||
<a id="urlOpenLicence" href="https://choosealicense.com/licenses/gpl-3.0">GPL v3.0</a>
|
||||
licence</div>
|
||||
<div class="infoText" id="aboutInfoVersion">Version:
|
||||
<span id="versionNumber"></span></div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-etho btn-dialog-confirm" id="btnAboutInfoClose">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
54
main.js
54
main.js
@@ -1,10 +1,10 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const {app, Menu, ipcMain, BrowserWindow} = require('electron');
|
||||
const singleInstance = require('single-instance');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const {app, Menu, ipcMain, BrowserWindow} = require("electron");
|
||||
const singleInstance = require("single-instance");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
var locker = new singleInstance('Ether1DesktopWallet');
|
||||
var locker = new singleInstance("Ether1DesktopWallet");
|
||||
|
||||
locker.lock().then(function () {
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
@@ -19,69 +19,67 @@ locker.lock().then(function() {
|
||||
minWidth: 1100,
|
||||
minHeight: 700,
|
||||
backgroundColor: "#000000",
|
||||
icon: 'assets/images/icon.png'
|
||||
icon: "assets/images/icon.png"
|
||||
});
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html');
|
||||
mainWindow.loadFile("index.html");
|
||||
EthoGeth.startGeth();
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
mainWindow.on("closed", function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
mainWindow = null;
|
||||
});
|
||||
|
||||
require('./modules/menu.js');
|
||||
require("./modules/menu.js");
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.on('ready', createWindow)
|
||||
app.on("ready", createWindow);
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
app.on("window-all-closed", function () {
|
||||
// On OS X it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
if (process.platform !== "darwin") {
|
||||
EthoGeth.stopGeth();
|
||||
app.quit();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
app.on('activate', function () {
|
||||
app.on("activate", function () {
|
||||
// On OS X it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
createWindow();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
// listen for request to get template
|
||||
|
||||
// get the template content from file
|
||||
ipcMain.on('getTemplateContent', (event, arg) => {
|
||||
event.returnValue = fs.readFileSync(path.join(app.getAppPath(), "assets/templates/") + arg, 'utf8');
|
||||
ipcMain.on("getTemplateContent", (event, arg) => {
|
||||
event.returnValue = fs.readFileSync(path.join(app.getAppPath(), "assets/templates/") + arg, "utf8");
|
||||
});
|
||||
|
||||
// quit the app on coomand
|
||||
ipcMain.on('appQuit', (event, arg) => {
|
||||
ipcMain.on("appQuit", (event, arg) => {
|
||||
app.quit();
|
||||
});
|
||||
}).catch(function (err) {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
})
|
||||
.catch(function(err) {
|
||||
app.quit();
|
||||
})
|
||||
|
||||
require('./modules/geth.js');
|
||||
require('./modules/accounts.js');
|
||||
require('./modules/database.js');
|
||||
require("./modules/geth.js");
|
||||
require("./modules/accounts.js");
|
||||
require("./modules/database.js");
|
||||
@@ -1,26 +1,25 @@
|
||||
const {app, dialog, ipcMain} = require('electron');
|
||||
const admZip = require('adm-zip');
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const os = require('os');
|
||||
const {app, dialog, ipcMain} = require("electron");
|
||||
const admZip = require("adm-zip");
|
||||
const path = require("path");
|
||||
const fs = require("fs-extra");
|
||||
const os = require("os");
|
||||
|
||||
class Accounts {
|
||||
constructor() {
|
||||
}
|
||||
constructor() {}
|
||||
|
||||
getKeyStoreLocation() {
|
||||
switch (os.type()) {
|
||||
case "Darwin":
|
||||
return path.join(os.homedir(), 'Library', 'Ether1', 'keystore');
|
||||
return path.join(os.homedir(), "Library", "Ether1", "keystore");
|
||||
break;
|
||||
default:
|
||||
return path.join(process.env.APPDATA, 'Ether1', 'keystore');
|
||||
return path.join(process.env.APPDATA, "Ether1", "keystore");
|
||||
}
|
||||
}
|
||||
|
||||
exportAccounts() {
|
||||
var savePath = dialog.showSaveDialog({
|
||||
defaultPath: path.join(app.getPath('documents'), 'accounts.zip')
|
||||
defaultPath: path.join(app.getPath("documents"), "accounts.zip")
|
||||
});
|
||||
|
||||
if (savePath) {
|
||||
@@ -43,7 +42,7 @@ class Accounts {
|
||||
var extName = path.extname(accountsFile).toUpperCase();
|
||||
const accPath = EthoAccounts.getKeyStoreLocation();
|
||||
|
||||
if (extName == '.ZIP') {
|
||||
if (extName == ".ZIP") {
|
||||
var zip = new admZip(accountsFile);
|
||||
zip.extractAllTo(accPath, true);
|
||||
return {success: true, text: "Accounts ware successfully imported."};
|
||||
@@ -58,32 +57,29 @@ class Accounts {
|
||||
}
|
||||
|
||||
saveAccount(account) {
|
||||
fs.writeFile(path.join(tEthoAccountshis.getKeyStoreLocation(), '0x' + account.address), JSON.stringify(account), 'utf8', function() {
|
||||
fs.writeFile(path.join(tEthoAccountshis.getKeyStoreLocation(), "0x" + account.address), JSON.stringify(account), "utf8", function () {
|
||||
// file was written
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('exportAccounts', (event, arg) => {
|
||||
ipcMain.on("exportAccounts", (event, arg) => {
|
||||
EthoAccounts.exportAccounts();
|
||||
});
|
||||
|
||||
ipcMain.on('importAccounts', (event, arg) => {
|
||||
ipcMain.on("importAccounts", (event, arg) => {
|
||||
var openPath = dialog.showOpenDialog({
|
||||
defaultPath: app.getPath('documents'),
|
||||
"filters":
|
||||
[
|
||||
defaultPath: app.getPath("documents"),
|
||||
filters: [
|
||||
{
|
||||
"name": "archive",
|
||||
"extensions": ["zip"]
|
||||
},
|
||||
{
|
||||
"name": "json",
|
||||
"extensions": ["json"]
|
||||
},
|
||||
{
|
||||
"name": "All",
|
||||
"extensions": ["*.*"]
|
||||
name: "archive",
|
||||
extensions: ["zip"]
|
||||
}, {
|
||||
name: "json",
|
||||
extensions: ["json"]
|
||||
}, {
|
||||
name: "All",
|
||||
extensions: ["*.*"]
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -95,7 +91,7 @@ ipcMain.on('importAccounts', (event, arg) => {
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('saveAccount', (event, arg) => {
|
||||
ipcMain.on("saveAccount", (event, arg) => {
|
||||
EthoAccounts.saveAccount(arg);
|
||||
event.returnValue = true;
|
||||
});
|
||||
|
||||
@@ -1,45 +1,54 @@
|
||||
const {app, dialog, ipcMain} = require('electron');
|
||||
const storage = require('electron-storage');
|
||||
const datastore = require('nedb');
|
||||
const moment = require('moment');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const {app, dialog, ipcMain} = require("electron");
|
||||
const storage = require("electron-storage");
|
||||
const datastore = require("nedb");
|
||||
const moment = require("moment");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
|
||||
const dbPath = path.join(app.getPath('userData'), 'storage.db');
|
||||
const dbPath = path.join(app.getPath("userData"), "storage.db");
|
||||
const db = new datastore({filename: dbPath});
|
||||
db.loadDatabase(function (err) {
|
||||
// Now commands will be executed
|
||||
});
|
||||
|
||||
// index the block field
|
||||
db.ensureIndex({ fieldName: 'block' }, function (err) {
|
||||
db.ensureIndex({
|
||||
fieldName: "block"
|
||||
}, function (err) {
|
||||
// If there was an error, err is not null
|
||||
});
|
||||
|
||||
// index the txhash field
|
||||
db.ensureIndex({ fieldName: 'txhash', unique: true }, function (err) {
|
||||
db.ensureIndex({
|
||||
fieldName: "txhash",
|
||||
unique: true
|
||||
}, function (err) {
|
||||
// If there was an error, err is not null
|
||||
});
|
||||
|
||||
ipcMain.on('storeTransaction', (event, arg) => {
|
||||
db.update({ txhash: arg.txhash }, arg, { upsert: true }, function (err, numReplaced, upsert) {
|
||||
ipcMain.on("storeTransaction", (event, arg) => {
|
||||
db.update({
|
||||
txhash: arg.txhash
|
||||
}, arg, {
|
||||
upsert: true
|
||||
}, function (err, numReplaced, upsert) {
|
||||
// do nothing for now
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('getTransactions', (event, arg) => {
|
||||
ipcMain.on("getTransactions", (event, arg) => {
|
||||
db.find({}).exec(function (err, docs) {
|
||||
ResultData = [];
|
||||
|
||||
// sort the data
|
||||
docs.sort((a, b) => {
|
||||
if ((!b.block) && (a.block)) {
|
||||
if (!b.block && a.block) {
|
||||
return 1;
|
||||
} else if ((b.block) && (!a.block)) {
|
||||
} else if (b.block && !a.block) {
|
||||
return -1;
|
||||
} else if ((!b.block) && (!a.block)) {
|
||||
return moment(b.timestamp, "YYYY-MM-DD HH:mm:ss").toDate() - moment(a.timestamp, "YYYY-MM-DD HH:mm:ss").toDate();
|
||||
} else if (!b.block && !a.block) {
|
||||
return (moment(b.timestamp, "YYYY-MM-DD HH:mm:ss").toDate() - moment(a.timestamp, "YYYY-MM-DD HH:mm:ss").toDate());
|
||||
} else {
|
||||
return b.block - a.block;
|
||||
}
|
||||
@@ -60,7 +69,7 @@ ipcMain.on('getTransactions', (event, arg) => {
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('getJSONFile', (event, arg) => {
|
||||
ipcMain.on("getJSONFile", (event, arg) => {
|
||||
storage.get(arg, (err, data) => {
|
||||
if (err) {
|
||||
event.returnValue = null;
|
||||
@@ -70,44 +79,64 @@ ipcMain.on('getJSONFile', (event, arg) => {
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('setJSONFile', (event, arg) => {
|
||||
storage.set(arg.file, arg.data, (err) => {
|
||||
ipcMain.on("setJSONFile", (event, arg) => {
|
||||
storage.set(arg.file, arg.data, err => {
|
||||
if (err) {
|
||||
event.returnValue = { success: false, error: err };
|
||||
event.returnValue = {
|
||||
success: false,
|
||||
error: err
|
||||
};
|
||||
} else {
|
||||
event.returnValue = { success: true, error: null };
|
||||
event.returnValue = {
|
||||
success: true,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('deleteTransactions', (event, arg) => {
|
||||
fs.unlink(dbPath, (err) => {
|
||||
ipcMain.on("deleteTransactions", (event, arg) => {
|
||||
fs.unlink(dbPath, err => {
|
||||
if (err) {
|
||||
event.returnValue = { success: false, error: err };
|
||||
event.returnValue = {
|
||||
success: false,
|
||||
error: err
|
||||
};
|
||||
} else {
|
||||
event.returnValue = { success: true, error: null };
|
||||
event.returnValue = {
|
||||
success: true,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('deleteWalletData', (event, arg) => {
|
||||
fs.unlink(path.join(app.getPath('userData'), 'wallets.json'), (err) => {
|
||||
ipcMain.on("deleteWalletData", (event, arg) => {
|
||||
fs.unlink(path.join(app.getPath("userData"), "wallets.json"), err => {
|
||||
if (err) {
|
||||
event.returnValue = { success: false, error: err };
|
||||
event.returnValue = {
|
||||
success: false,
|
||||
error: err
|
||||
};
|
||||
} else {
|
||||
event.returnValue = { success: true, error: null };
|
||||
event.returnValue = {
|
||||
success: true,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('deleteBlockchainData', (event, arg) => {
|
||||
ipcMain.on("deleteBlockchainData", (event, arg) => {
|
||||
var deleteFolderRecursive = function (path) {
|
||||
if (fs.existsSync(path)) {
|
||||
fs.readdirSync(path).forEach(function (file, index) {
|
||||
var curPath = path + "/" + file;
|
||||
if(fs.lstatSync(curPath).isDirectory()) { // recurse
|
||||
if (fs.lstatSync(curPath).isDirectory()) {
|
||||
// recurse
|
||||
deleteFolderRecursive(curPath);
|
||||
} else { // delete file
|
||||
} else {
|
||||
// delete file
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
});
|
||||
@@ -118,10 +147,10 @@ ipcMain.on('deleteBlockchainData', (event, arg) => {
|
||||
function getBlockchainDataLocation() {
|
||||
switch (os.type()) {
|
||||
case "Darwin":
|
||||
return path.join(os.homedir(), 'Library', 'Ether1', 'geth');
|
||||
return path.join(os.homedir(), "Library", "Ether1", "geth");
|
||||
break;
|
||||
default:
|
||||
return path.join(process.env.APPDATA, 'Ether1', 'geth');
|
||||
return path.join(process.env.APPDATA, "Ether1", "geth");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
const {app, dialog, ipcMain} = require('electron');
|
||||
const child_process = require('child_process');
|
||||
const appRoot = require('app-root-path');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
|
||||
const {app, dialog, ipcMain} = require("electron");
|
||||
const child_process = require("child_process");
|
||||
const appRoot = require("app-root-path");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
|
||||
class Geth {
|
||||
constructor() {
|
||||
this.gethProcess = null;
|
||||
this.logGethEvents = false;
|
||||
// create the user data dir (needed for MacOS)
|
||||
if (!fs.existsSync(app.getPath('userData'))) {
|
||||
fs.mkdirSync(app.getPath('userData'));
|
||||
if (!fs.existsSync(app.getPath("userData"))) {
|
||||
fs.mkdirSync(app.getPath("userData"));
|
||||
}
|
||||
|
||||
if (this.logGethEvents) {
|
||||
this.logStream = fs.createWriteStream(path.join(app.getPath('userData'), 'gethlog.txt'), { flags: 'a' });
|
||||
this.logStream = fs.createWriteStream(path.join(app.getPath("userData"), "gethlog.txt"), {flags: "a"});
|
||||
}
|
||||
|
||||
if (appRoot.path.indexOf('app.asar') > -1) {
|
||||
if (appRoot.path.indexOf("app.asar") > -1) {
|
||||
this.rootPath = path.dirname(appRoot.path);
|
||||
} else {
|
||||
this.rootPath = appRoot.path;
|
||||
@@ -27,19 +26,17 @@ class Geth {
|
||||
|
||||
switch (os.type()) {
|
||||
case "Linux":
|
||||
this.binaries = path.join(this.rootPath, 'bin', 'linux');
|
||||
this.binaries = path.join(this.rootPath, "bin", "linux");
|
||||
break;
|
||||
case "Darwin":
|
||||
this.binaries = path.join(this.rootPath, 'bin', 'macos');
|
||||
this.binaries = path.join(this.rootPath, "bin", "macos");
|
||||
break;
|
||||
case "Windows_NT":
|
||||
this.binaries = path.join(this.rootPath, 'bin', 'win');
|
||||
this.binaries = path.join(this.rootPath, "bin", "win");
|
||||
break;
|
||||
default:
|
||||
this.binaries = path.join(this.rootPath, 'bin', 'win');
|
||||
this.binaries = path.join(this.rootPath, "bin", "win");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
_writeLog(text) {
|
||||
@@ -51,22 +48,32 @@ class Geth {
|
||||
startGeth() {
|
||||
// get the path of get and execute the child process
|
||||
try {
|
||||
const gethPath = path.join(this.binaries, 'geth');
|
||||
this.gethProcess = child_process.spawn(gethPath, ['--ws', '--wsorigins', '*', '--wsaddr', '127.0.0.1', '--wsport', '8546', '--wsapi', 'admin,db,eth,net,miner,personal,web3']);
|
||||
const gethPath = path.join(this.binaries, "geth");
|
||||
this.gethProcess = child_process.spawn(gethPath, [
|
||||
"--ws",
|
||||
"--wsorigins",
|
||||
"*",
|
||||
"--wsaddr",
|
||||
"127.0.0.1",
|
||||
"--wsport",
|
||||
"8546",
|
||||
"--wsapi",
|
||||
"admin,db,eth,net,miner,personal,web3"
|
||||
]);
|
||||
|
||||
if (!this.gethProcess) {
|
||||
dialog.showErrorBox("Error starting application", "Geth failed to start!");
|
||||
app.quit();
|
||||
} else {
|
||||
this.gethProcess.on('error', function(err) {
|
||||
this.gethProcess.on("error", function (err) {
|
||||
dialog.showErrorBox("Error starting application", "Geth failed to start!");
|
||||
app.quit();
|
||||
});
|
||||
this.gethProcess.stderr.on('data', function(data) {
|
||||
EthoGeth._writeLog(data.toString() + '\n');
|
||||
this.gethProcess.stderr.on("data", function (data) {
|
||||
EthoGeth._writeLog(data.toString() + "\n");
|
||||
});
|
||||
this.gethProcess.stdout.on('data', function(data) {
|
||||
EthoGeth._writeLog(data.toString() + '\n');
|
||||
this.gethProcess.stdout.on("data", function (data) {
|
||||
EthoGeth._writeLog(data.toString() + "\n");
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -77,15 +84,15 @@ class Geth {
|
||||
|
||||
stopGeth() {
|
||||
if (os.type() == "Windows_NT") {
|
||||
const gethWrapePath = path.join(this.binaries, 'WrapGeth.exe');
|
||||
const gethWrapePath = path.join(this.binaries, "WrapGeth.exe");
|
||||
child_process.spawnSync(gethWrapePath, [this.gethProcess.pid]);
|
||||
} else {
|
||||
this.gethProcess.kill('SIGTERM');
|
||||
this.gethProcess.kill("SIGTERM");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('stopGeth', (event, arg) => {
|
||||
ipcMain.on("stopGeth", (event, arg) => {
|
||||
EthoGeth.stopGeth();
|
||||
});
|
||||
|
||||
|
||||
256
modules/menu.js
256
modules/menu.js
@@ -1,202 +1,170 @@
|
||||
const {app, Menu, ipcMain} = require('electron');
|
||||
const {app, Menu, ipcMain} = require("electron");
|
||||
const open = require("open");
|
||||
|
||||
const template = [
|
||||
{
|
||||
label: 'File',
|
||||
label: "File",
|
||||
submenu: [
|
||||
{
|
||||
label:'Exit',
|
||||
label: "Exit",
|
||||
click() {
|
||||
app.quit()
|
||||
} }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
role: 'undo'
|
||||
},
|
||||
{
|
||||
role: 'redo'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'cut'
|
||||
},
|
||||
{
|
||||
role: 'copy'
|
||||
},
|
||||
{
|
||||
role: 'paste'
|
||||
},
|
||||
{
|
||||
role: 'delete'
|
||||
},
|
||||
{
|
||||
role: 'selectall'
|
||||
app.quit();
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
}, {
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
role: "undo"
|
||||
}, {
|
||||
role: "redo"
|
||||
}, {
|
||||
type: "separator"
|
||||
}, {
|
||||
role: "cut"
|
||||
}, {
|
||||
role: "copy"
|
||||
}, {
|
||||
role: "paste"
|
||||
}, {
|
||||
role: "delete"
|
||||
}, {
|
||||
role: "selectall"
|
||||
}
|
||||
]
|
||||
}, {
|
||||
label: "View",
|
||||
submenu: [
|
||||
{
|
||||
label: "Reload",
|
||||
accelerator: "CmdOrCtrl+R",
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) focusedWindow.reload()
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
|
||||
}, {
|
||||
label: "Toggle Developer Tools",
|
||||
accelerator: process.platform === "darwin"
|
||||
? "Alt+Command+I"
|
||||
: "Ctrl+Shift+I",
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) focusedWindow.webContents.toggleDevTools()
|
||||
if (focusedWindow)
|
||||
focusedWindow.webContents.toggleDevTools();
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'resetzoom'
|
||||
},
|
||||
{
|
||||
role: 'zoomin'
|
||||
},
|
||||
{
|
||||
role: 'zoomout'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'togglefullscreen'
|
||||
}, {
|
||||
type: "separator"
|
||||
}, {
|
||||
role: "resetzoom"
|
||||
}, {
|
||||
role: "zoomin"
|
||||
}, {
|
||||
role: "zoomout"
|
||||
}, {
|
||||
type: "separator"
|
||||
}, {
|
||||
role: "togglefullscreen"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'window',
|
||||
}, {
|
||||
role: "window",
|
||||
submenu: [
|
||||
{
|
||||
role: 'minimize'
|
||||
},
|
||||
{
|
||||
role: 'close'
|
||||
role: "minimize"
|
||||
}, {
|
||||
role: "close"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
}, {
|
||||
role: "help",
|
||||
submenu: [
|
||||
{
|
||||
label: 'About Ether1 wallet',
|
||||
label: "About Ether1 wallet",
|
||||
click() {
|
||||
var infoData = {};
|
||||
infoData.version = app.getVersion();
|
||||
mainWindow.webContents.send('showAboutDialog', infoData);
|
||||
mainWindow.webContents.send("showAboutDialog", infoData);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Ether1 documentation',
|
||||
}, {
|
||||
label: "Ether1 documentation",
|
||||
click() {
|
||||
open("https://docs.ether1.org");
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Report issue on GitHub',
|
||||
}, {
|
||||
label: "Report issue on GitHub",
|
||||
click() {
|
||||
open("https://github.com/taeguscromis/Ether1DesktopWallet/issues");
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
const name = app.getName()
|
||||
if (process.platform === "darwin") {
|
||||
const name = app.getName();
|
||||
template.unshift({
|
||||
label: name,
|
||||
submenu: [
|
||||
{
|
||||
role: 'about'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'services',
|
||||
role: "about"
|
||||
}, {
|
||||
type: "separator"
|
||||
}, {
|
||||
role: "services",
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'hide'
|
||||
},
|
||||
{
|
||||
role: 'hideothers'
|
||||
},
|
||||
{
|
||||
role: 'unhide'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'quit'
|
||||
}, {
|
||||
type: "separator"
|
||||
}, {
|
||||
role: "hide"
|
||||
}, {
|
||||
role: "hideothers"
|
||||
}, {
|
||||
role: "unhide"
|
||||
}, {
|
||||
type: "separator"
|
||||
}, {
|
||||
role: "quit"
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
// Edit menu.
|
||||
template[1].submenu.push(
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Speech',
|
||||
template[1].submenu.push({
|
||||
type: "separator"
|
||||
}, {
|
||||
label: "Speech",
|
||||
submenu: [
|
||||
{
|
||||
role: 'startspeaking'
|
||||
},
|
||||
{
|
||||
role: 'stopspeaking'
|
||||
role: "startspeaking"
|
||||
}, {
|
||||
role: "stopspeaking"
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
});
|
||||
// Window menu.
|
||||
template[3].submenu = [
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'CmdOrCtrl+W',
|
||||
role: 'close'
|
||||
},
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'CmdOrCtrl+M',
|
||||
role: 'minimize'
|
||||
},
|
||||
{
|
||||
label: 'Zoom',
|
||||
role: 'zoom'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
role: 'front'
|
||||
label: "Close",
|
||||
accelerator: "CmdOrCtrl+W",
|
||||
role: "close"
|
||||
}, {
|
||||
label: "Minimize",
|
||||
accelerator: "CmdOrCtrl+M",
|
||||
role: "minimize"
|
||||
}, {
|
||||
label: "Zoom",
|
||||
role: "zoom"
|
||||
}, {
|
||||
type: "separator"
|
||||
}, {
|
||||
label: "Bring All to Front",
|
||||
role: "front"
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
ipcMain.on('openURL', (event, arg) => {
|
||||
ipcMain.on("openURL", (event, arg) => {
|
||||
open(arg);
|
||||
});
|
||||
|
||||
const menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(menu)
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
|
||||
26
package.json
26
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Ether1Wallet",
|
||||
"version": "0.2.6",
|
||||
"version": "0.2.7",
|
||||
"description": "Desktop wallet for Ether1 currency",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@@ -22,41 +22,34 @@
|
||||
"target": "7z",
|
||||
"icon": "build/icon.png",
|
||||
"artifactName": "Windows-${productName}-${version}.${ext}",
|
||||
"extraResources": [
|
||||
"bin/win/*"
|
||||
]
|
||||
"extraResources": ["bin/win/*"]
|
||||
},
|
||||
"linux": {
|
||||
"target": "tar.gz",
|
||||
"icon": "build/icon.icns",
|
||||
"artifactName": "Linux-${productName}-${version}.${ext}",
|
||||
"extraResources": [
|
||||
"bin/linux/*"
|
||||
]
|
||||
"extraResources": ["bin/linux/*"]
|
||||
},
|
||||
"mac": {
|
||||
"target": "pkg",
|
||||
"icon": "build/icon.icns",
|
||||
"artifactName": "MacOS-${productName}-${version}.${ext}",
|
||||
"extraResources": [
|
||||
"bin/macos/*"
|
||||
]
|
||||
"extraResources": ["bin/macos/*"]
|
||||
}
|
||||
},
|
||||
"repository": "https://github.com/taeguscromis/Ether1DesktopWallet",
|
||||
"keywords": [
|
||||
"Ether1",
|
||||
"Desktop",
|
||||
"Wallet"
|
||||
"Ether1", "Desktop", "Wallet"
|
||||
],
|
||||
"author": "Ether1",
|
||||
"license": "CC0-1.0",
|
||||
"dependencies": {
|
||||
"@unibeautify/beautifier-js-beautify": "^0.4.0",
|
||||
"adm-zip": "^0.4.13",
|
||||
"app-root-path": "^2.1.0",
|
||||
"electron-storage": "^1.0.7",
|
||||
"fs-extra": "^7.0.1",
|
||||
"handlebars": "^4.0.12",
|
||||
"handlebars": "^4.1.0",
|
||||
"moment": "^2.23.0",
|
||||
"nedb": "^1.8.0",
|
||||
"open": "0.0.5",
|
||||
@@ -64,6 +57,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^3.0.12",
|
||||
"electron-builder": "^20.38.3"
|
||||
"electron-builder": "^20.38.3",
|
||||
"js-beautify": "^1.9.0",
|
||||
"unibeautify": "^0.17.0",
|
||||
"unibeautify-cli": "^0.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// In renderer process (web page).
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class Blockchain {
|
||||
constructor() {
|
||||
@@ -76,9 +76,8 @@ class Blockchain {
|
||||
web3Local.eth.personal.unlockAccount(fromAddress, password, function (error, result) {
|
||||
if (error) {
|
||||
clbError("Wrong password for the selected address!");
|
||||
} else
|
||||
{
|
||||
web3Local.eth.getTransactionCount(fromAddress, 'pending', function( error, result ) {
|
||||
} else {
|
||||
web3Local.eth.getTransactionCount(fromAddress, "pending", function (error, result) {
|
||||
if (error) {
|
||||
clbError(error);
|
||||
} else {
|
||||
@@ -160,11 +159,10 @@ class Blockchain {
|
||||
}
|
||||
});
|
||||
|
||||
function updateBalance(index)
|
||||
{
|
||||
function updateBalance(index) {
|
||||
web3Local.eth.getBalance(rendererData.addressData[index].address, function (error, balance) {
|
||||
rendererData.addressData[index].balance = parseFloat(web3Local.utils.fromWei(balance, 'ether')).toFixed(2);
|
||||
rendererData.sumBalance = rendererData.sumBalance + parseFloat(web3Local.utils.fromWei(balance, 'ether'));
|
||||
rendererData.addressData[index].balance = parseFloat(web3Local.utils.fromWei(balance, "ether")).toFixed(2);
|
||||
rendererData.sumBalance = rendererData.sumBalance + parseFloat(web3Local.utils.fromWei(balance, "ether"));
|
||||
|
||||
if (counter < rendererData.addressData.length - 1) {
|
||||
counter++;
|
||||
@@ -218,11 +216,11 @@ class Blockchain {
|
||||
importFromPrivateKey(privateKey, password) {
|
||||
web3Local.eth.accounts.wallet.clear();
|
||||
web3Local.eth.accounts.wallet.add(privateKey);
|
||||
return web3Local.eth.accounts.wallet.encrypt('123456789');
|
||||
return web3Local.eth.accounts.wallet.encrypt("123456789");
|
||||
}
|
||||
|
||||
subsribePendingTransactions(clbError, clbSuccess, clbData) {
|
||||
this.txSubscribe = web3Local.eth.subscribe('pendingTransactions', function(error, result){
|
||||
this.txSubscribe = web3Local.eth.subscribe("pendingTransactions", function (error, result) {
|
||||
if (error) {
|
||||
clbError(error);
|
||||
} else {
|
||||
@@ -248,7 +246,7 @@ class Blockchain {
|
||||
}
|
||||
|
||||
subsribeNewBlockHeaders(clbError, clbSuccess, clbData) {
|
||||
this.bhSubscribe = web3Local.eth.subscribe('newBlockHeaders', function(error, result){
|
||||
this.bhSubscribe = web3Local.eth.subscribe("newBlockHeaders", function (error, result) {
|
||||
if (error) {
|
||||
clbError(error);
|
||||
} else {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// In renderer process (web page).
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class Datatabse {
|
||||
constructor() {}
|
||||
|
||||
getCounters() {
|
||||
var counters = ipcRenderer.sendSync('getJSONFile', 'counters.json');
|
||||
var counters = ipcRenderer.sendSync("getJSONFile", "counters.json");
|
||||
|
||||
if (counters == null) {
|
||||
counters = {};
|
||||
@@ -15,45 +15,46 @@ class Datatabse {
|
||||
}
|
||||
|
||||
setCounters(counters) {
|
||||
ipcRenderer.sendSync('setJSONFile',
|
||||
{
|
||||
file: 'counters.json',
|
||||
ipcRenderer.sendSync("setJSONFile", {
|
||||
file: "counters.json",
|
||||
data: counters
|
||||
});
|
||||
}
|
||||
|
||||
getWallets() {
|
||||
var wallets = ipcRenderer.sendSync('getJSONFile', 'wallets.json');
|
||||
var wallets = ipcRenderer.sendSync("getJSONFile", "wallets.json");
|
||||
|
||||
if (!wallets) {
|
||||
wallets = { names: {} };
|
||||
wallets = {
|
||||
names: {}
|
||||
};
|
||||
}
|
||||
|
||||
return wallets;
|
||||
}
|
||||
|
||||
setWallets(wallets) {
|
||||
ipcRenderer.sendSync('setJSONFile',
|
||||
{
|
||||
file: 'wallets.json',
|
||||
ipcRenderer.sendSync("setJSONFile", {
|
||||
file: "wallets.json",
|
||||
data: wallets
|
||||
});
|
||||
}
|
||||
|
||||
getAddresses() {
|
||||
var addressBook = ipcRenderer.sendSync('getJSONFile', 'addresses.json');
|
||||
var addressBook = ipcRenderer.sendSync("getJSONFile", "addresses.json");
|
||||
|
||||
if (!addressBook) {
|
||||
addressBook = { names: {} };
|
||||
addressBook = {
|
||||
names: {}
|
||||
};
|
||||
}
|
||||
|
||||
return addressBook;
|
||||
}
|
||||
|
||||
setAddresses(addresses) {
|
||||
ipcRenderer.sendSync('setJSONFile',
|
||||
{
|
||||
file: 'addresses.json',
|
||||
ipcRenderer.sendSync("setJSONFile", {
|
||||
file: "addresses.json",
|
||||
data: addresses
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// In renderer process (web page).
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class MainGUI {
|
||||
constructor() {
|
||||
@@ -42,10 +42,10 @@ class MainGUI {
|
||||
|
||||
// create and open the dialog
|
||||
$("#dlgGeneralError").iziModal();
|
||||
$('#dlgGeneralError').iziModal('open');
|
||||
$("#dlgGeneralError").iziModal("open");
|
||||
|
||||
$("#btnGeneralErrorOK").click(function () {
|
||||
$('#dlgGeneralError').iziModal('close');
|
||||
$("#dlgGeneralError").iziModal("close");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -54,15 +54,15 @@ class MainGUI {
|
||||
|
||||
// create and open the dialog
|
||||
$("#dlgGeneralConfirm").iziModal();
|
||||
$('#dlgGeneralConfirm').iziModal('open');
|
||||
$("#dlgGeneralConfirm").iziModal("open");
|
||||
|
||||
$("#btnGeneralConfirmYes").click(function () {
|
||||
$('#dlgGeneralConfirm').iziModal('close');
|
||||
$("#dlgGeneralConfirm").iziModal("close");
|
||||
callback(true);
|
||||
});
|
||||
|
||||
$("#btnGeneralConfirmNo").click(function () {
|
||||
$('#dlgGeneralConfirm').iziModal('close');
|
||||
$("#dlgGeneralConfirm").iziModal("close");
|
||||
callback(false);
|
||||
});
|
||||
}
|
||||
@@ -72,23 +72,23 @@ class MainGUI {
|
||||
|
||||
// create and open the dialog
|
||||
$("#dlgAboutInfo").iziModal();
|
||||
$('#dlgAboutInfo').iziModal('open');
|
||||
$("#dlgAboutInfo").iziModal("open");
|
||||
|
||||
$("#urlOpenLicence, #urlOpenGitHub").off("click").on("click", function (even) {
|
||||
event.preventDefault();
|
||||
ipcRenderer.send('openURL', $(this).attr("href"));
|
||||
ipcRenderer.send("openURL", $(this).attr("href"));
|
||||
});
|
||||
|
||||
$("#btnAboutInfoClose").off("click").on("click", function (even) {
|
||||
$('#dlgAboutInfo').iziModal('close');
|
||||
$("#dlgAboutInfo").iziModal("close");
|
||||
});
|
||||
}
|
||||
|
||||
renderTemplate(template, data, container) {
|
||||
var template = Handlebars.compile(ipcRenderer.sendSync('getTemplateContent', template));
|
||||
var template = Handlebars.compile(ipcRenderer.sendSync("getTemplateContent", template));
|
||||
|
||||
if (!container) {
|
||||
container = $("#mainContent")
|
||||
container = $("#mainContent");
|
||||
}
|
||||
|
||||
container.empty();
|
||||
@@ -104,7 +104,7 @@ class MainGUI {
|
||||
}
|
||||
}
|
||||
|
||||
ipcRenderer.on('showAboutDialog', function(event, message) {
|
||||
ipcRenderer.on("showAboutDialog", function (event, message) {
|
||||
EthoMainGUI.showAboutDialog(message);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class Markets {
|
||||
constructor() {}
|
||||
@@ -18,18 +18,20 @@ class Markets {
|
||||
$("#changeMarketcap").html("high 24h: " + data.market_data.high_24h.usd.toFixed(5) + " $");
|
||||
$("#changeVolume").html("all time high: " + data.market_data.ath.usd.toFixed(5) + " $");
|
||||
|
||||
new Chart(document.getElementById('chartMarketPriceCanvas'), {
|
||||
type: 'line',
|
||||
new Chart(document.getElementById("chartMarketPriceCanvas"), {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: data.market_data.sparkline_7d.price,
|
||||
datasets: [{
|
||||
datasets: [
|
||||
{
|
||||
data: data.market_data.sparkline_7d.price,
|
||||
backgroundColor: 'rgb(122,19,54,0.1)',
|
||||
backgroundColor: "rgb(122,19,54,0.1)",
|
||||
fill: true,
|
||||
borderWidth: 3,
|
||||
pointRadius: 0,
|
||||
borderColor: '#7A1336'
|
||||
}]
|
||||
borderColor: "#7A1336"
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
animation: false,
|
||||
@@ -42,22 +44,26 @@ class Markets {
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
yAxes: [
|
||||
{
|
||||
ticks: {
|
||||
maxTicksLimit: 5,
|
||||
beginAtZero: true,
|
||||
fontSize: 10,
|
||||
callback: function (value, index, values) {
|
||||
return value.toFixed(2) + ' $';
|
||||
return value.toFixed(2) + " $";
|
||||
}
|
||||
},
|
||||
gridLines: {
|
||||
color: 'rgba(255,255,255,.08)'
|
||||
color: "rgba(255,255,255,.08)"
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
display: false
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
134
renderer/send.js
134
renderer/send.js
@@ -1,20 +1,16 @@
|
||||
// In renderer process (web page).
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class SendTransaction {
|
||||
constructor() {}
|
||||
|
||||
renderSendState() {
|
||||
EthoBlockchain.getAccountsData(
|
||||
function(error) {
|
||||
EthoBlockchain.getAccountsData(function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
}, function (data) {
|
||||
EthoMainGUI.renderTemplate("send.html", data);
|
||||
$(document).trigger("render_send");
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
validateSendForm() {
|
||||
@@ -60,26 +56,26 @@ class SendTransaction {
|
||||
}
|
||||
|
||||
$(document).on("render_send", function () {
|
||||
$('select').formSelect( {classes: "fromAddressSelect"});
|
||||
$("select").formSelect({classes: "fromAddressSelect"});
|
||||
|
||||
$("#sendFromAddress").on("change", function () {
|
||||
var optionText = $(this).find("option:selected").text();
|
||||
var addrName = optionText.substr(0, optionText.indexOf('-'));
|
||||
var addrName = optionText.substr(0, optionText.indexOf("-"));
|
||||
var addrValue = optionText.substr(optionText.indexOf("-") + 1);
|
||||
$(".fromAddressSelect input").val(addrValue.trim());
|
||||
$("#sendFromAddressName").html(addrName.trim());
|
||||
|
||||
web3Local.eth.getBalance(this.value, function (error, balance) {
|
||||
$("#sendMaxAmmount").html(parseFloat(web3Local.utils.fromWei(balance, 'ether')));
|
||||
$("#sendMaxAmmount").html(parseFloat(web3Local.utils.fromWei(balance, "ether")));
|
||||
});
|
||||
});
|
||||
|
||||
$("#btnSendAll").off('click').on('click', function() {
|
||||
$("#btnSendAll").off("click").on("click", function () {
|
||||
$("#sendAmmount").focus();
|
||||
$("#sendAmmount").val($("#sendMaxAmmount").html());
|
||||
});
|
||||
|
||||
$("#sendToAddress").off('input').on('input', function() {
|
||||
$("#sendToAddress").off("input").on("input", function () {
|
||||
var addressName = null;
|
||||
$("#sendToAddressName").html("");
|
||||
addressName = EthoAddressBook.getAddressName($("#sendToAddress").val());
|
||||
@@ -91,18 +87,16 @@ $(document).on("render_send", function() {
|
||||
$("#sendToAddressName").html(addressName);
|
||||
});
|
||||
|
||||
$("#btnLookForToAddress").off('click').on('click', function() {
|
||||
EthoBlockchain.getAddressListData(
|
||||
function(error) {
|
||||
$("#btnLookForToAddress").off("click").on("click", function () {
|
||||
EthoBlockchain.getAddressListData(function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(addressList) {
|
||||
}, function (addressList) {
|
||||
var addressBook = EthoAddressBook.getAddressList();
|
||||
|
||||
for (var key in addressBook) {
|
||||
if (addressBook.hasOwnProperty(key)) {
|
||||
var adddressObject = {};
|
||||
adddressObject.address = key
|
||||
adddressObject.address = key;
|
||||
adddressObject.name = addressBook[key];
|
||||
addressList.addressData.push(adddressObject);
|
||||
}
|
||||
@@ -110,132 +104,104 @@ $(document).on("render_send", function() {
|
||||
|
||||
$("#dlgAddressList").iziModal({width: "800px"});
|
||||
EthoMainGUI.renderTemplate("addresslist.html", addressList, $("#dlgAddressListBody"));
|
||||
$('#dlgAddressList').iziModal('open');
|
||||
$("#dlgAddressList").iziModal("open");
|
||||
|
||||
$(".btnSelectToAddress").off('click').on('click', function() {
|
||||
$("#sendToAddressName").html($(this).attr('data-name'));
|
||||
$("#sendToAddress").val($(this).attr('data-wallet'));
|
||||
$('#dlgAddressList').iziModal('close');
|
||||
$(".btnSelectToAddress").off("click").on("click", function () {
|
||||
$("#sendToAddressName").html($(this).attr("data-name"));
|
||||
$("#sendToAddress").val($(this).attr("data-wallet"));
|
||||
$("#dlgAddressList").iziModal("close");
|
||||
});
|
||||
|
||||
$('#addressListFilter').off('input').on('input',function(e){
|
||||
EthoUtils.filterTable($("#addressTable"), $('#addressListFilter').val());
|
||||
$("#addressListFilter").off("input").on("input", function (e) {
|
||||
EthoUtils.filterTable($("#addressTable"), $("#addressListFilter").val());
|
||||
});
|
||||
|
||||
$("#btnClearSearchField").off('click').on('click', function() {
|
||||
$("#btnClearSearchField").off("click").on("click", function () {
|
||||
EthoUtils.filterTable($("#addressTable"), "");
|
||||
$('#addressListFilter').val("")
|
||||
$("#addressListFilter").val("");
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$("#btnAddToAddressBook").off('click').on('click', function() {
|
||||
$("#btnAddToAddressBook").off("click").on("click", function () {
|
||||
if (EthoBlockchain.isAddress($("#sendToAddress").val())) {
|
||||
$("#dlgAddAddressToBook").iziModal();
|
||||
$("#inputAddressName").val("");
|
||||
$('#dlgAddAddressToBook').iziModal('open');
|
||||
$("#dlgAddAddressToBook").iziModal("open");
|
||||
|
||||
function doAddAddressToAddressBook() {
|
||||
EthoAddressBook.setAddressName($("#sendToAddress").val(), $("#inputAddressName").val());
|
||||
$('#dlgAddAddressToBook').iziModal('close');
|
||||
$("#dlgAddAddressToBook").iziModal("close");
|
||||
|
||||
iziToast.success({
|
||||
title: 'Success',
|
||||
message: 'Address was added to address book',
|
||||
position: 'topRight',
|
||||
timeout: 2000
|
||||
});
|
||||
iziToast.success({title: "Success", message: "Address was added to address book", position: "topRight", timeout: 2000});
|
||||
}
|
||||
} else {
|
||||
EthoMainGUI.showGeneralError("Recipient address is not valid!");
|
||||
}
|
||||
|
||||
$("#btnAddAddressToBookConfirm").off('click').on('click', function() {
|
||||
$("#btnAddAddressToBookConfirm").off("click").on("click", function () {
|
||||
doAddAddressToAddressBook();
|
||||
});
|
||||
|
||||
$("#dlgAddAddressToBook").off('keypress').on('keypress', function(e) {
|
||||
$("#dlgAddAddressToBook").off("keypress").on("keypress", function (e) {
|
||||
if (e.which == 13) {
|
||||
doAddAddressToAddressBook();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$("#btnSendTransaction").off('click').on('click', function() {
|
||||
$("#btnSendTransaction").off("click").on("click", function () {
|
||||
if (EthoSend.validateSendForm()) {
|
||||
EthoBlockchain.getTranasctionFee($("#sendFromAddress").val(), $("#sendToAddress").val(), $("#sendAmmount").val(),
|
||||
function(error) {
|
||||
EthoBlockchain.getTranasctionFee($("#sendFromAddress").val(), $("#sendToAddress").val(), $("#sendAmmount").val(), function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
}, function (data) {
|
||||
$("#dlgSendWalletPassword").iziModal();
|
||||
$("#walletPassword").val("");
|
||||
$("#fromAddressInfo").html($("#sendFromAddress").val());
|
||||
$("#toAddressInfo").html($("#sendToAddress").val());
|
||||
$("#valueToSendInfo").html($("#sendAmmount").val());
|
||||
$("#feeToPayInfo").html(parseFloat(web3Local.utils.fromWei(data.toString(), 'ether')));
|
||||
$('#dlgSendWalletPassword').iziModal('open');
|
||||
$("#feeToPayInfo").html(parseFloat(web3Local.utils.fromWei(data.toString(), "ether")));
|
||||
$("#dlgSendWalletPassword").iziModal("open");
|
||||
|
||||
function doSendTransaction() {
|
||||
$('#dlgSendWalletPassword').iziModal('close');
|
||||
$("#dlgSendWalletPassword").iziModal("close");
|
||||
|
||||
EthoBlockchain.prepareTransaction(
|
||||
$("#walletPassword").val(),
|
||||
$("#sendFromAddress").val(),
|
||||
$("#sendToAddress").val(),
|
||||
$("#sendAmmount").val(),
|
||||
function(error) {
|
||||
EthoBlockchain.prepareTransaction($("#walletPassword").val(), $("#sendFromAddress").val(), $("#sendToAddress").val(), $("#sendAmmount").val(), function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
EthoBlockchain.sendTransaction(data.raw,
|
||||
function(error) {
|
||||
}, function (data) {
|
||||
EthoBlockchain.sendTransaction(data.raw, function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
}, function (data) {
|
||||
EthoSend.resetSendForm();
|
||||
|
||||
iziToast.success({
|
||||
title: 'Sent',
|
||||
message: 'Transaction was successfully sent to the chain',
|
||||
position: 'topRight',
|
||||
timeout: 5000
|
||||
});
|
||||
iziToast.success({title: "Sent", message: "Transaction was successfully sent to the chain", position: "topRight", timeout: 5000});
|
||||
|
||||
EthoBlockchain.getTransaction(data,
|
||||
function(error) {
|
||||
EthoBlockchain.getTransaction(data, function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(transaction) {
|
||||
ipcRenderer.send('storeTransaction', {
|
||||
}, function (transaction) {
|
||||
ipcRenderer.send("storeTransaction", {
|
||||
block: transaction.blockNumber,
|
||||
txhash: transaction.hash.toLowerCase(),
|
||||
fromaddr: transaction.from.toLowerCase(),
|
||||
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||
timestamp: moment().format("YYYY-MM-DD HH:mm:ss"),
|
||||
toaddr: transaction.to.toLowerCase(),
|
||||
value: transaction.value
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$("#btnSendWalletPasswordConfirm").off('click').on('click', function() {
|
||||
$("#btnSendWalletPasswordConfirm").off("click").on("click", function () {
|
||||
doSendTransaction();
|
||||
});
|
||||
|
||||
$("#dlgSendWalletPassword").off('keypress').on('keypress', function(e) {
|
||||
$("#dlgSendWalletPassword").off("keypress").on("keypress", function (e) {
|
||||
if (e.which == 13) {
|
||||
doSendTransaction();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// In renderer process (web page).
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class Settings {
|
||||
constructor() {}
|
||||
@@ -11,7 +11,7 @@ class Settings {
|
||||
}
|
||||
|
||||
$(document).on("render_settings", function () {
|
||||
$("#btnSettingsCleanTransactions").off('click').on('click', function() {
|
||||
$("#btnSettingsCleanTransactions").off("click").on("click", function () {
|
||||
if (isFullySynced) {
|
||||
EthoMainGUI.showGeneralConfirmation("Do you really want to resync transactions?", function (result) {
|
||||
if (result) {
|
||||
@@ -24,7 +24,7 @@ $(document).on("render_settings", function() {
|
||||
var counters = EthoDatatabse.getCounters();
|
||||
counters.transactions = 0;
|
||||
EthoDatatabse.setCounters(counters);
|
||||
ipcResult = ipcRenderer.sendSync('deleteTransactions', null);
|
||||
ipcResult = ipcRenderer.sendSync("deleteTransactions", null);
|
||||
|
||||
if (ipcResult.success) {
|
||||
// sync all the transactions to the current block
|
||||
@@ -35,12 +35,7 @@ $(document).on("render_settings", function() {
|
||||
EthoTransactions.enableKeepInSync();
|
||||
EthoTransactions.syncTransactionsForAllAddresses(localBlock.number);
|
||||
|
||||
iziToast.success({
|
||||
title: 'Success',
|
||||
message: 'Transactions are being resynced',
|
||||
position: 'topRight',
|
||||
timeout: 5000
|
||||
});
|
||||
iziToast.success({title: "Success", message: "Transactions are being resynced", position: "topRight", timeout: 5000});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -50,27 +45,17 @@ $(document).on("render_settings", function() {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
iziToast.info({
|
||||
title: 'Wait...',
|
||||
message: 'You need to be fully sync before cleaning transactions',
|
||||
position: 'topRight',
|
||||
timeout: 5000
|
||||
});
|
||||
iziToast.info({title: "Wait...", message: "You need to be fully sync before cleaning transactions", position: "topRight", timeout: 5000});
|
||||
}
|
||||
});
|
||||
|
||||
$("#btnSettingsCleanWallets").off('click').on('click', function() {
|
||||
$("#btnSettingsCleanWallets").off("click").on("click", function () {
|
||||
EthoMainGUI.showGeneralConfirmation("Do you really want to delete wallets data?", function (result) {
|
||||
if (result) {
|
||||
ipcResult = ipcRenderer.sendSync('deleteWalletData', null);
|
||||
ipcResult = ipcRenderer.sendSync("deleteWalletData", null);
|
||||
|
||||
if (ipcResult.success) {
|
||||
iziToast.success({
|
||||
title: 'Success',
|
||||
message: 'Wallet names were succesfully cleaned',
|
||||
position: 'topRight',
|
||||
timeout: 5000
|
||||
});
|
||||
iziToast.success({title: "Success", message: "Wallet names were succesfully cleaned", position: "topRight", timeout: 5000});
|
||||
} else {
|
||||
EthoMainGUI.showGeneralError("Error clearing wallet names: " + ipcResult.error);
|
||||
}
|
||||
@@ -78,24 +63,20 @@ $(document).on("render_settings", function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#btnSettingsCleanBlockchain").off('click').on('click', function() {
|
||||
$("#btnSettingsCleanBlockchain").off("click").on("click", function () {
|
||||
EthoMainGUI.showGeneralConfirmation("Do you really want to delete the blockchain data? Wallet will close and you will need to restart it!", function (result) {
|
||||
if (result) {
|
||||
var loading_screen = pleaseWait({
|
||||
logo: "assets/images/logo.png",
|
||||
backgroundColor: '#000000',
|
||||
loadingHtml: "<div class='spinner'><div class='bounce bounce1'></div><div class='bounce bounce2'></div><div class='bounce bounce3'></div></div><div class='loadingText'>Deleting blockchain data, wallet will automatically close, please wait...</div>"
|
||||
});
|
||||
var loading_screen = pleaseWait({logo: "assets/images/logo.png", backgroundColor: "#000000", loadingHtml: "<div class='spinner'><div class='bounce bounce1'></div><div class='bounce bounce2'></div><div class='bounce bounce3'></div></div><div class='loadingText'>Deleting blockchain data, wallet will automatically close, please wait...</div>"});
|
||||
|
||||
setTimeout(() => {
|
||||
// first stop the geth process
|
||||
ipcResult = ipcRenderer.send('stopGeth', null);
|
||||
ipcResult = ipcRenderer.send("stopGeth", null);
|
||||
|
||||
setTimeout(() => {
|
||||
// delete the blockchain date async and wait for 5 seconds
|
||||
ipcResult = ipcRenderer.sendSync('deleteBlockchainData', null);
|
||||
ipcResult = ipcRenderer.sendSync("deleteBlockchainData", null);
|
||||
// finally quit the application
|
||||
ipcResult = ipcRenderer.send('appQuit', null);
|
||||
ipcResult = ipcRenderer.send("appQuit", null);
|
||||
}, 5000);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
// In renderer process (web page).
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
// Set the provider you want from Web3.providers
|
||||
SyncProgress = new ProgressBar.Line('#syncProgress',
|
||||
{
|
||||
SyncProgress = new ProgressBar.Line("#syncProgress", {
|
||||
strokeWidth: 6,
|
||||
easing: 'easeInOut',
|
||||
easing: "easeInOut",
|
||||
duration: 1400,
|
||||
color: "#7A1336",
|
||||
trailColor: '#eee',
|
||||
trailColor: "#eee",
|
||||
trailWidth: 1,
|
||||
text: {
|
||||
style: {
|
||||
color: '#bbb',
|
||||
color: "#bbb",
|
||||
position: "absolute",
|
||||
left: "50%",
|
||||
top: "-1px",
|
||||
@@ -23,16 +22,19 @@ SyncProgress = new ProgressBar.Line('#syncProgress',
|
||||
},
|
||||
autoStyleContainer: false
|
||||
},
|
||||
from: {color: '#FFEA82'},
|
||||
to: {color: '#ED6A5A'}
|
||||
from: {
|
||||
color: "#FFEA82"
|
||||
},
|
||||
to: {
|
||||
color: "#ED6A5A"
|
||||
}
|
||||
});
|
||||
|
||||
// set initial value for the progress text
|
||||
SyncProgress.setText("Waiting for blockchain, please wait...");
|
||||
isFullySynced = false;
|
||||
|
||||
var peerCountInterval = setInterval(function()
|
||||
{
|
||||
var peerCountInterval = setInterval(function () {
|
||||
web3Local.eth.net.getPeerCount(function (error, count) {
|
||||
$("#peerCount").html(vsprintf("Peer Count: %d", [count]));
|
||||
});
|
||||
@@ -42,25 +44,23 @@ function StartSyncProcess() {
|
||||
var alreadyCatchedUp = false;
|
||||
var nodeSyncInterval = null;
|
||||
|
||||
var subscription = web3Local.eth.subscribe('syncing', function(error, sync){
|
||||
var subscription = web3Local.eth.subscribe("syncing", function (error, sync) {
|
||||
if (!error) {
|
||||
if (!sync) {
|
||||
if (nodeSyncInterval) {
|
||||
clearInterval(nodeSyncInterval);
|
||||
}
|
||||
|
||||
nodeSyncInterval = setInterval(function()
|
||||
{
|
||||
nodeSyncInterval = setInterval(function () {
|
||||
web3Local.eth.getBlock("latest", function (error, localBlock) {
|
||||
if (!error) {
|
||||
if (localBlock.number > 0) {
|
||||
if (!EthoTransactions.getIsSyncing()) {
|
||||
SyncProgress.animate(1);
|
||||
SyncProgress.setText(vsprintf('%d/%d (100%%)', [localBlock.number, localBlock.number]));
|
||||
SyncProgress.setText(vsprintf("%d/%d (100%%)", [localBlock.number, localBlock.number]));
|
||||
}
|
||||
|
||||
if (alreadyCatchedUp == false)
|
||||
{
|
||||
if (alreadyCatchedUp == false) {
|
||||
// clear the repeat interval and render wallets
|
||||
$(document).trigger("onNewAccountTransaction");
|
||||
alreadyCatchedUp = true;
|
||||
@@ -85,18 +85,25 @@ function StartSyncProcess() {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
}
|
||||
}).on("data", function (sync) {
|
||||
if ((sync) && (sync.HighestBlock > 0)) {
|
||||
if (sync && sync.HighestBlock > 0) {
|
||||
SyncProgress.animate(sync.CurrentBlock / sync.HighestBlock);
|
||||
SyncProgress.setText(vsprintf('%d/%d (%d%%)', [sync.CurrentBlock, sync.HighestBlock, Math.floor(sync.CurrentBlock / sync.HighestBlock * 100)]));
|
||||
SyncProgress.setText(vsprintf("%d/%d (%d%%)", [
|
||||
sync.CurrentBlock,
|
||||
sync.HighestBlock,
|
||||
Math.floor(sync.CurrentBlock / sync.HighestBlock * 100)
|
||||
]));
|
||||
}
|
||||
}).on("changed", function (isSyncing) {
|
||||
if (isSyncing) {
|
||||
nodeSyncInterval = setInterval(function()
|
||||
{
|
||||
nodeSyncInterval = setInterval(function () {
|
||||
web3Local.eth.isSyncing(function (error, sync) {
|
||||
if ((!error) && (sync)) {
|
||||
if (!error && sync) {
|
||||
SyncProgress.animate(sync.currentBlock / sync.highestBlock);
|
||||
SyncProgress.setText(vsprintf('%d/%d (%d%%)', [sync.currentBlock, sync.highestBlock, Math.floor(sync.currentBlock / sync.highestBlock * 100)]));
|
||||
SyncProgress.setText(vsprintf("%d/%d (%d%%)", [
|
||||
sync.currentBlock,
|
||||
sync.highestBlock,
|
||||
Math.floor(sync.currentBlock / sync.highestBlock * 100)
|
||||
]));
|
||||
} else if (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
}
|
||||
@@ -110,10 +117,9 @@ function StartSyncProcess() {
|
||||
});
|
||||
}
|
||||
|
||||
var InitWeb3 = setInterval(function()
|
||||
{
|
||||
var InitWeb3 = setInterval(function () {
|
||||
try {
|
||||
web3Local = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
|
||||
web3Local = new Web3(new Web3.providers.WebsocketProvider("ws://localhost:8546"));
|
||||
|
||||
web3Local.eth.net.isListening(function (error, success) {
|
||||
if (!error) {
|
||||
@@ -122,8 +128,7 @@ var InitWeb3 = setInterval(function()
|
||||
StartSyncProcess();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
} catch (err) {
|
||||
EthoMainGUI.showGeneralError(err);
|
||||
}
|
||||
}, 2000);
|
||||
@@ -5,24 +5,29 @@ class tableTransactions {
|
||||
|
||||
initialize(id, data) {
|
||||
// register the sort datetime format
|
||||
$.fn.dataTable.moment('MMM Do YYYY HH:mm:ss');
|
||||
$.fn.dataTable.moment("MMM Do YYYY HH:mm:ss");
|
||||
|
||||
var namesType = $.fn.dataTable.absoluteOrderNumber(
|
||||
[
|
||||
{ value: null, position: 'top' }
|
||||
var namesType = $.fn.dataTable.absoluteOrderNumber([
|
||||
{
|
||||
value: null,
|
||||
position: "top"
|
||||
}
|
||||
]);
|
||||
// render the transactions
|
||||
$(id).DataTable({
|
||||
"dom": 'Bfrtip',
|
||||
"paging": false,
|
||||
"scrollY": "calc(100vh - 115px)",
|
||||
"responsive": true,
|
||||
"processing": true,
|
||||
"order": [[ 1, "desc" ]],
|
||||
"data": data,
|
||||
"oSearch": {"sSearch": EthoTransactions.getFilter() },
|
||||
"buttons":
|
||||
[
|
||||
dom: "Bfrtip",
|
||||
paging: false,
|
||||
scrollY: "calc(100vh - 115px)",
|
||||
responsive: true,
|
||||
processing: true,
|
||||
order: [
|
||||
[1, "desc"]
|
||||
],
|
||||
data: data,
|
||||
oSearch: {
|
||||
sSearch: EthoTransactions.getFilter()
|
||||
},
|
||||
buttons: [
|
||||
{
|
||||
text: '<i class="fas fa-sync-alt"></i>',
|
||||
action: function (e, dt, node, config) {
|
||||
@@ -30,10 +35,10 @@ class tableTransactions {
|
||||
}
|
||||
}
|
||||
],
|
||||
"columnDefs": [
|
||||
columnDefs: [
|
||||
{
|
||||
"targets": 0,
|
||||
"render": function ( data, type, row ) {
|
||||
targets: 0,
|
||||
render: function (data, type, row) {
|
||||
if (data == 0) {
|
||||
return '<i class="fas fa-arrow-left"></i>';
|
||||
} else if (data == 1) {
|
||||
@@ -42,28 +47,24 @@ class tableTransactions {
|
||||
return '<i class="fas fa-arrows-alt-h"></i>';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"className": "transactionsBlockNum",
|
||||
"type": namesType,
|
||||
"targets": 1
|
||||
},
|
||||
{
|
||||
"targets": 2,
|
||||
"render": function ( data, type, row ) {
|
||||
}, {
|
||||
className: "transactionsBlockNum",
|
||||
type: namesType,
|
||||
targets: 1
|
||||
}, {
|
||||
targets: 2,
|
||||
render: function (data, type, row) {
|
||||
return moment(data, "YYYY-MM-DD HH:mm:ss").format("MMM Do YYYY HH:mm:ss");
|
||||
}
|
||||
},
|
||||
{
|
||||
"targets": 5,
|
||||
"render": function ( data, type, row ) {
|
||||
return parseFloat(web3Local.utils.fromWei(EthoUtils.toFixed(parseFloat(data)).toString(), 'ether')).toFixed(2);
|
||||
}, {
|
||||
targets: 5,
|
||||
render: function (data, type, row) {
|
||||
return parseFloat(web3Local.utils.fromWei(EthoUtils.toFixed(parseFloat(data)).toString(), "ether")).toFixed(2);
|
||||
}
|
||||
},
|
||||
{
|
||||
"targets": 6,
|
||||
"defaultContent": "",
|
||||
"render": function ( data, type, row ) {
|
||||
}, {
|
||||
targets: 6,
|
||||
defaultContent: "",
|
||||
render: function (data, type, row) {
|
||||
if (row[1]) {
|
||||
return '<i class="fas fa-check"></i>';
|
||||
} else {
|
||||
@@ -72,7 +73,7 @@ class tableTransactions {
|
||||
}
|
||||
}
|
||||
],
|
||||
"drawCallback": function( settings ) {
|
||||
drawCallback: function (settings) {
|
||||
$("#loadingTransactionsOverlay").css("display", "none");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class Transactions {
|
||||
constructor() {
|
||||
@@ -40,12 +40,16 @@ class Transactions {
|
||||
SyncProgress.setText(vsprintf("Syncing address transactions %d/%d, please wait...", [counter, addressList.length]));
|
||||
|
||||
var startBlock = parseInt(counters.transactions) || 0;
|
||||
var params = vsprintf('?address=%s&fromBlock=%d&toBlock=%d', [addressList[counter].toLowerCase(), startBlock, lastBlock]);
|
||||
var params = vsprintf("?address=%s&fromBlock=%d&toBlock=%d", [
|
||||
addressList[counter].toLowerCase(),
|
||||
startBlock,
|
||||
lastBlock
|
||||
]);
|
||||
|
||||
$.getJSON("https://richlist.ether1.org/transactions_list.php" + params, function (result) {
|
||||
result.data.forEach(element => {
|
||||
if (element.fromaddr && element.toaddr) {
|
||||
ipcRenderer.send('storeTransaction', {
|
||||
ipcRenderer.send("storeTransaction", {
|
||||
block: element.block.toString(),
|
||||
txhash: element.txhash.toLowerCase(),
|
||||
fromaddr: element.fromaddr.toLowerCase(),
|
||||
@@ -73,15 +77,12 @@ class Transactions {
|
||||
var counters = EthoDatatabse.getCounters();
|
||||
var counter = 0;
|
||||
|
||||
EthoBlockchain.getAccounts(
|
||||
function(error) {
|
||||
EthoBlockchain.getAccounts(function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
}, function (data) {
|
||||
EthoTransactions.setIsSyncing(true);
|
||||
EthoTransactions.syncTransactionsForSingleAddress(data, counters, lastBlock, counter);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
renderTransactions() {
|
||||
@@ -94,61 +95,56 @@ class Transactions {
|
||||
$("#loadingTransactionsOverlay").css("display", "block");
|
||||
|
||||
setTimeout(() => {
|
||||
var dataTransactions = ipcRenderer.sendSync('getTransactions');
|
||||
var dataTransactions = ipcRenderer.sendSync("getTransactions");
|
||||
var addressList = EthoWallets.getAddressList();
|
||||
|
||||
dataTransactions.forEach(function (element) {
|
||||
var isFromValid = (addressList.indexOf(element[2].toLowerCase()) > -1);
|
||||
var isToValid = (addressList.indexOf(element[3].toLowerCase()) > -1);
|
||||
var isFromValid = addressList.indexOf(element[2].toLowerCase()) > -1;
|
||||
var isToValid = addressList.indexOf(element[3].toLowerCase()) > -1;
|
||||
|
||||
if ((isToValid) && (!isFromValid)) {
|
||||
if (isToValid && !isFromValid) {
|
||||
element.unshift(0);
|
||||
} else if ((!isToValid) && (isFromValid)) {
|
||||
} else if (!isToValid && isFromValid) {
|
||||
element.unshift(1);
|
||||
} else {
|
||||
element.unshift(2);
|
||||
}
|
||||
});
|
||||
|
||||
EthoTableTransactions.initialize('#tableTransactionsForAll', dataTransactions);
|
||||
EthoTableTransactions.initialize("#tableTransactionsForAll", dataTransactions);
|
||||
EthoTransactions.setIsLoading(false);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
enableKeepInSync() {
|
||||
EthoBlockchain.subsribeNewBlockHeaders(
|
||||
function(error) {
|
||||
EthoBlockchain.subsribeNewBlockHeaders(function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data)
|
||||
{
|
||||
EthoBlockchain.getBlock(data.number, true,
|
||||
function(error) {
|
||||
}, function (data) {
|
||||
EthoBlockchain.getBlock(data.number, true, function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
}, function (data) {
|
||||
if (data.transactions) {
|
||||
data.transactions.forEach(element => {
|
||||
if (element.from && element.to) {
|
||||
if ((EthoWallets.getAddressExists(element.from)) || (EthoWallets.getAddressExists(element.to))) {
|
||||
if (EthoWallets.getAddressExists(element.from) || EthoWallets.getAddressExists(element.to)) {
|
||||
var Transaction = {
|
||||
block: element.blockNumber.toString(),
|
||||
txhash: element.hash.toLowerCase(),
|
||||
fromaddr: element.from.toLowerCase(),
|
||||
timestamp: moment.unix(data.timestamp).format('YYYY-MM-DD HH:mm:ss'),
|
||||
timestamp: moment.unix(data.timestamp).format("YYYY-MM-DD HH:mm:ss"),
|
||||
toaddr: element.to.toLowerCase(),
|
||||
value: Number(element.value).toExponential(5).toString().replace('+','')
|
||||
}
|
||||
value: Number(element.value).toExponential(5).toString().replace("+", "")
|
||||
};
|
||||
|
||||
// store transaction and notify about new transactions
|
||||
ipcRenderer.send('storeTransaction', Transaction);
|
||||
ipcRenderer.send("storeTransaction", Transaction);
|
||||
$(document).trigger("onNewAccountTransaction");
|
||||
|
||||
iziToast.info({
|
||||
title: 'New Transaction',
|
||||
message: vsprintf('Transaction from address %s to address %s was just processed', [Transaction.fromaddr, Transaction.toaddr]),
|
||||
position: 'topRight',
|
||||
title: "New Transaction",
|
||||
message: vsprintf("Transaction from address %s to address %s was just processed", [Transaction.fromaddr, Transaction.toaddr]),
|
||||
position: "topRight",
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
@@ -161,21 +157,16 @@ class Transactions {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
disableKeepInSync() {
|
||||
EthoBlockchain.unsubsribeNewBlockHeaders(
|
||||
function(error) {
|
||||
EthoBlockchain.unsubsribeNewBlockHeaders(function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
}, function (data) {
|
||||
// success
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@ class Utils {
|
||||
|
||||
toFixed(x) {
|
||||
if (Math.abs(x) < 1.0) {
|
||||
var e = parseInt(x.toString().split('e-')[1]);
|
||||
var e = parseInt(x.toString().split("e-")[1]);
|
||||
if (e) {
|
||||
x *= Math.pow(10, e - 1);
|
||||
x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
|
||||
x = "0." + new Array(e).join("0") + x.toString().substring(2);
|
||||
}
|
||||
} else {
|
||||
var e = parseInt(x.toString().split('+')[1]);
|
||||
var e = parseInt(x.toString().split("+")[1]);
|
||||
if (e > 20) {
|
||||
e -= 20;
|
||||
x /= Math.pow(10, e);
|
||||
x += (new Array(e+1)).join('0');
|
||||
x += new Array(e + 1).join("0");
|
||||
}
|
||||
}
|
||||
return x;
|
||||
@@ -21,7 +21,11 @@ class Utils {
|
||||
|
||||
filterTable(table, text) {
|
||||
// Declare variables
|
||||
var filter, tr, td, i, txtValue;
|
||||
var filter,
|
||||
tr,
|
||||
td,
|
||||
i,
|
||||
txtValue;
|
||||
filter = text.toUpperCase();
|
||||
tr = $(table).find("tr");
|
||||
|
||||
@@ -45,13 +49,12 @@ class Utils {
|
||||
content: text,
|
||||
delay: 500,
|
||||
arrow: true,
|
||||
arrowType: 'round',
|
||||
size: 'large',
|
||||
arrowType: "round",
|
||||
size: "large",
|
||||
duration: 500,
|
||||
animation: 'scale'
|
||||
animation: "scale"
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EthoUtils = new Utils();
|
||||
@@ -1,11 +1,10 @@
|
||||
const {ipcRenderer} = require('electron');
|
||||
const {ipcRenderer} = require("electron");
|
||||
|
||||
class Wallets {
|
||||
constructor() {
|
||||
this.addressList = [];
|
||||
|
||||
$.getJSON("https://min-api.cryptocompare.com/data/price?fsym=ETHO&tsyms=USD", function( price )
|
||||
{
|
||||
$.getJSON("https://min-api.cryptocompare.com/data/price?fsym=ETHO&tsyms=USD", function (price) {
|
||||
EthoWallets._setPrice(price.USD);
|
||||
});
|
||||
}
|
||||
@@ -75,11 +74,9 @@ renderWalletsState() {
|
||||
// clear the list of addresses
|
||||
EthoWallets.clearAddressList();
|
||||
|
||||
EthoBlockchain.getAccountsData(
|
||||
function(error) {
|
||||
EthoBlockchain.getAccountsData(function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(data) {
|
||||
}, function (data) {
|
||||
data.addressData.forEach(element => {
|
||||
EthoWallets.addAddressToList(element.address);
|
||||
});
|
||||
@@ -89,69 +86,63 @@ renderWalletsState() {
|
||||
$(document).trigger("render_wallets");
|
||||
EthoWallets.enableButtonTooltips();
|
||||
|
||||
$("#labelSumDollars").html(vsprintf("/ %.2f $ / %.4f $ per ETHO", [data.sumBalance * EthoWallets._getPrice(), EthoWallets._getPrice()]));
|
||||
}
|
||||
);
|
||||
$("#labelSumDollars").html(vsprintf("/ %.2f $ / %.4f $ per ETHO", [
|
||||
data.sumBalance * EthoWallets._getPrice(),
|
||||
EthoWallets._getPrice()
|
||||
]));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// the event to tell us that the wallets are rendered
|
||||
$(document).on("render_wallets", function () {
|
||||
$('#addressTable').floatThead();
|
||||
$("#addressTable").floatThead();
|
||||
|
||||
$("#btnNewAddress").off('click').on('click', function() {
|
||||
$("#btnNewAddress").off("click").on("click", function () {
|
||||
$("#dlgCreateWalletPassword").iziModal();
|
||||
$("#walletPasswordFirst").val("");
|
||||
$("#walletPasswordSecond").val("");
|
||||
$('#dlgCreateWalletPassword').iziModal('open');
|
||||
$("#dlgCreateWalletPassword").iziModal("open");
|
||||
|
||||
function doCreateNewWallet() {
|
||||
$('#dlgCreateWalletPassword').iziModal('close');
|
||||
$("#dlgCreateWalletPassword").iziModal("close");
|
||||
|
||||
if (EthoWallets.validateNewAccountForm()) {
|
||||
EthoBlockchain.createNewAccount($("#walletPasswordFirst").val(),
|
||||
function(error) {
|
||||
EthoBlockchain.createNewAccount($("#walletPasswordFirst").val(), function (error) {
|
||||
EthoMainGUI.showGeneralError(error);
|
||||
},
|
||||
function(account) {
|
||||
}, function (account) {
|
||||
EthoWallets.addAddressToList(account);
|
||||
EthoWallets.renderWalletsState();
|
||||
|
||||
iziToast.success({
|
||||
title: 'Created',
|
||||
message: 'New wallet was successfully created',
|
||||
position: 'topRight',
|
||||
timeout: 5000
|
||||
iziToast.success({title: "Created", message: "New wallet was successfully created", position: "topRight", timeout: 5000});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$("#btnCreateWalletConfirm").off('click').on('click', function() {
|
||||
$("#btnCreateWalletConfirm").off("click").on("click", function () {
|
||||
doCreateNewWallet();
|
||||
});
|
||||
|
||||
$("#dlgCreateWalletPassword").off('keypress').on('keypress', function(e) {
|
||||
$("#dlgCreateWalletPassword").off("keypress").on("keypress", function (e) {
|
||||
if (e.which == 13) {
|
||||
doCreateNewWallet();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(".btnShowAddressTransactions").off('click').on('click', function() {
|
||||
EthoTransactions.setFilter($(this).attr('data-wallet'));
|
||||
$(".btnShowAddressTransactions").off("click").on("click", function () {
|
||||
EthoTransactions.setFilter($(this).attr("data-wallet"));
|
||||
EthoMainGUI.changeAppState("transactions");
|
||||
EthoTransactions.renderTransactions();
|
||||
});
|
||||
|
||||
$(".btnChangWalletName").off('click').on('click', function() {
|
||||
var walletAddress = $(this).attr('data-wallet');
|
||||
var walletName = $(this).attr('data-name');
|
||||
$(".btnChangWalletName").off("click").on("click", function () {
|
||||
var walletAddress = $(this).attr("data-wallet");
|
||||
var walletName = $(this).attr("data-name");
|
||||
|
||||
$("#dlgChangeWalletName").iziModal();
|
||||
$("#inputWalletName").val(walletName);
|
||||
$('#dlgChangeWalletName').iziModal('open');
|
||||
$("#dlgChangeWalletName").iziModal("open");
|
||||
|
||||
function doChangeWalletName() {
|
||||
var wallets = EthoDatatabse.getWallets();
|
||||
@@ -160,90 +151,73 @@ $(document).on("render_wallets", function() {
|
||||
wallets.names[walletAddress] = $("#inputWalletName").val();
|
||||
EthoDatatabse.setWallets(wallets);
|
||||
|
||||
$('#dlgChangeWalletName').iziModal('close');
|
||||
$("#dlgChangeWalletName").iziModal("close");
|
||||
EthoWallets.renderWalletsState();
|
||||
}
|
||||
|
||||
$("#btnChangeWalletNameConfirm").off('click').on('click', function() {
|
||||
$("#btnChangeWalletNameConfirm").off("click").on("click", function () {
|
||||
doChangeWalletName();
|
||||
});
|
||||
|
||||
$("#dlgChangeWalletName").off('keypress').on('keypress', function(e) {
|
||||
$("#dlgChangeWalletName").off("keypress").on("keypress", function (e) {
|
||||
if (e.which == 13) {
|
||||
doChangeWalletName();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#btnRefreshAddress").off('click').on('click', function() {
|
||||
$("#btnRefreshAddress").off("click").on("click", function () {
|
||||
EthoWallets.renderWalletsState();
|
||||
});
|
||||
|
||||
$("#btnExportAccounts").off('click').on('click', function() {
|
||||
ipcRenderer.send('exportAccounts', {});
|
||||
$("#btnExportAccounts").off("click").on("click", function () {
|
||||
ipcRenderer.send("exportAccounts", {});
|
||||
});
|
||||
|
||||
$("#btnImportAccounts").off('click').on('click', function() {
|
||||
var ImportResult = ipcRenderer.sendSync('importAccounts', {});
|
||||
$("#btnImportAccounts").off("click").on("click", function () {
|
||||
var ImportResult = ipcRenderer.sendSync("importAccounts", {});
|
||||
|
||||
if (ImportResult.success) {
|
||||
iziToast.success({
|
||||
title: 'Imported',
|
||||
message: ImportResult.text,
|
||||
position: 'topRight',
|
||||
timeout: 2000
|
||||
});
|
||||
iziToast.success({title: "Imported", message: ImportResult.text, position: "topRight", timeout: 2000});
|
||||
} else if (ImportResult.success == false) {
|
||||
EthoMainGUI.showGeneralError(ImportResult.text);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$("#btnImportFromPrivateKey").off('click').on('click', function() {
|
||||
$("#btnImportFromPrivateKey").off("click").on("click", function () {
|
||||
$("#dlgImportFromPrivateKey").iziModal();
|
||||
$("#inputPrivateKey").val("");
|
||||
$('#dlgImportFromPrivateKey').iziModal('open');
|
||||
$("#dlgImportFromPrivateKey").iziModal("open");
|
||||
|
||||
function doImportFromPrivateKeys() {
|
||||
var account = EthoBlockchain.importFromPrivateKey($("#inputPrivateKey").val());
|
||||
$('#dlgImportFromPrivateKey').iziModal('close');
|
||||
$("#dlgImportFromPrivateKey").iziModal("close");
|
||||
|
||||
if (account) {
|
||||
ipcRenderer.sendSync('saveAccount', account[0]);
|
||||
ipcRenderer.sendSync("saveAccount", account[0]);
|
||||
EthoWallets.renderWalletsState();
|
||||
|
||||
iziToast.success({
|
||||
title: 'Imported',
|
||||
message: "Account was succesfully imported",
|
||||
position: 'topRight',
|
||||
timeout: 2000
|
||||
});
|
||||
|
||||
iziToast.success({title: "Imported", message: "Account was succesfully imported", position: "topRight", timeout: 2000});
|
||||
} else {
|
||||
EthoMainGUI.showGeneralError("Error importing account from private key!");
|
||||
}
|
||||
}
|
||||
|
||||
$("#btnImportFromPrivateKeyConfirm").off('click').on('click', function() {
|
||||
$("#btnImportFromPrivateKeyConfirm").off("click").on("click", function () {
|
||||
doImportFromPrivateKeys();
|
||||
});
|
||||
|
||||
$("#dlgImportFromPrivateKey").off('keypress').on('keypress', function(e) {
|
||||
$("#dlgImportFromPrivateKey").off("keypress").on("keypress", function (e) {
|
||||
if (e.which == 13) {
|
||||
doImportFromPrivateKeys();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(".textAddress").off('click').on('click', function() {
|
||||
$(".textAddress").off("click").on("click", function () {
|
||||
EthoMainGUI.copyToClipboard($(this).html());
|
||||
|
||||
iziToast.success({
|
||||
title: 'Copied',
|
||||
message: 'Address was copied to clipboard',
|
||||
position: 'topRight',
|
||||
timeout: 2000
|
||||
});
|
||||
iziToast.success({title: "Copied", message: "Address was copied to clipboard", position: "topRight", timeout: 2000});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user