* redesigned sync, so no external node is needed
+ allow only once instance of the wallet + store txhash and use it as single ID for transactions
This commit is contained in:
108
main.js
108
main.js
@@ -1,68 +1,76 @@
|
|||||||
// Modules to control application life and create native browser window
|
// Modules to control application life and create native browser window
|
||||||
const {app, ipcMain, BrowserWindow} = require('electron');
|
const {app, ipcMain, BrowserWindow} = require('electron');
|
||||||
|
const singleInstance = require('single-instance');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
// Keep a global reference of the window object, if you don't, the window will
|
var locker = new singleInstance('Ether1DesktopWallet');
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
|
||||||
let mainWindow
|
|
||||||
|
|
||||||
function createWindow () {
|
locker.lock().then(function() {
|
||||||
// Create the browser window.
|
// Keep a global reference of the window object, if you don't, the window will
|
||||||
mainWindow = new BrowserWindow({
|
// be closed automatically when the JavaScript object is garbage collected.
|
||||||
width: 1200,
|
let mainWindow
|
||||||
height: 800,
|
|
||||||
minWidth: 1100,
|
|
||||||
minHeight: 700,
|
|
||||||
backgroundColor: "#000000"
|
|
||||||
});
|
|
||||||
|
|
||||||
// and load the index.html of the app.
|
function createWindow () {
|
||||||
mainWindow.loadFile('index.html');
|
// Create the browser window.
|
||||||
EthoGeth.startGeth();
|
mainWindow = new BrowserWindow({
|
||||||
|
width: 1200,
|
||||||
|
height: 800,
|
||||||
|
minWidth: 1100,
|
||||||
|
minHeight: 700,
|
||||||
|
backgroundColor: "#000000"
|
||||||
|
});
|
||||||
|
|
||||||
// Open the DevTools.
|
// and load the index.html of the app.
|
||||||
// mainWindow.webContents.openDevTools()
|
mainWindow.loadFile('index.html');
|
||||||
|
EthoGeth.startGeth();
|
||||||
|
|
||||||
// Emitted when the window is closed.
|
// Open the DevTools.
|
||||||
mainWindow.on('closed', function () {
|
// mainWindow.webContents.openDevTools()
|
||||||
// Dereference the window object, usually you would store windows
|
|
||||||
// in an array if your app supports multi windows, this is the time
|
// Emitted when the window is closed.
|
||||||
// when you should delete the corresponding element.
|
mainWindow.on('closed', function () {
|
||||||
mainWindow = null
|
// 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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// Quit when all windows are closed.
|
||||||
|
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') {
|
||||||
|
EthoGeth.stopGeth();
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
app.on('activate', function () {
|
||||||
// initialization and is ready to create browser windows.
|
// On OS X it's common to re-create a window in the app when the
|
||||||
// Some APIs can only be used after this event occurs.
|
// dock icon is clicked and there are no other windows open.
|
||||||
app.on('ready', createWindow)
|
if (mainWindow === null) {
|
||||||
|
createWindow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
// In this file you can include the rest of your app's specific main process
|
||||||
app.on('window-all-closed', function () {
|
// code. You can also put them in separate files and require them here.
|
||||||
// On OS X it is common for applications and their menu bar
|
// listen for request to get template
|
||||||
// to stay active until the user quits explicitly with Cmd + Q
|
ipcMain.on('getTemplateContent', (event, arg) => {
|
||||||
if (process.platform !== 'darwin') {
|
event.returnValue = fs.readFileSync(path.join(app.getAppPath(), "assets/templates/") + arg, 'utf8');
|
||||||
EthoGeth.stopGeth();
|
});
|
||||||
app.quit()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.catch(function(err) {
|
||||||
app.on('activate', function () {
|
app.quit();
|
||||||
// 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()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 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
|
|
||||||
ipcMain.on('getTemplateContent', (event, arg) => {
|
|
||||||
event.returnValue = fs.readFileSync(path.join(app.getAppPath(), "assets/templates/") + arg, 'utf8');
|
|
||||||
});
|
|
||||||
|
|
||||||
require('./modules/geth.js');
|
require('./modules/geth.js');
|
||||||
require('./modules/accounts.js');
|
require('./modules/accounts.js');
|
||||||
require('./modules/database.js');
|
require('./modules/database.js');
|
||||||
@@ -14,7 +14,7 @@ db.ensureIndex({ fieldName: 'block' }, function (err) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('storeTransaction', (event, arg) => {
|
ipcMain.on('storeTransaction', (event, arg) => {
|
||||||
db.update({ block: arg.block, fromaddr: arg.fromaddr, toaddr: arg.toaddr }, arg, { upsert: true }, function (err, numReplaced, upsert) {
|
db.update({ txhash: arg.txhash }, arg, { upsert: true }, function (err, numReplaced, upsert) {
|
||||||
// do nothing for now
|
// do nothing for now
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -29,8 +29,7 @@ ipcMain.on('getTransactions', (event, arg) => {
|
|||||||
docs[i].timestamp,
|
docs[i].timestamp,
|
||||||
docs[i].fromaddr,
|
docs[i].fromaddr,
|
||||||
docs[i].toaddr,
|
docs[i].toaddr,
|
||||||
docs[i].value,
|
docs[i].value
|
||||||
docs[i].confirmed || 1
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ class Geth {
|
|||||||
this.gethProcess.stdout.on('data', function(data) {
|
this.gethProcess.stdout.on('data', function(data) {
|
||||||
EthoGeth._writeLog(data.toString() + '\n');
|
EthoGeth._writeLog(data.toString() + '\n');
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (err) {
|
||||||
dialog.showErrorBox("Error starting application", e);
|
dialog.showErrorBox("Error starting application", err.message);
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,14 +21,14 @@
|
|||||||
"win": {
|
"win": {
|
||||||
"icon": "build/icon.png",
|
"icon": "build/icon.png",
|
||||||
"target": "7z",
|
"target": "7z",
|
||||||
"artifactName": "Windows-${productName}-${version}.${ext}",
|
"artifactName": "Windows-${productName}-${version}.${ext}",
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
"bin/win/*"
|
"bin/win/*"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": "tar.gz",
|
"target": "tar.gz",
|
||||||
"artifactName": "Linux-${productName}-${version}.${ext}",
|
"artifactName": "Linux-${productName}-${version}.${ext}",
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
"bin/linux/*"
|
"bin/linux/*"
|
||||||
]
|
]
|
||||||
@@ -47,7 +47,8 @@
|
|||||||
"app-root-path": "^2.1.0",
|
"app-root-path": "^2.1.0",
|
||||||
"electron-storage": "^1.0.7",
|
"electron-storage": "^1.0.7",
|
||||||
"handlebars": "^4.0.12",
|
"handlebars": "^4.0.12",
|
||||||
"nedb": "^1.8.0"
|
"nedb": "^1.8.0",
|
||||||
|
"single-instance": "0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^3.0.12",
|
"electron": "^3.0.12",
|
||||||
|
|||||||
@@ -145,16 +145,14 @@ $(document).on("render_send", function() {
|
|||||||
EthoMainGUI.showGeneralError(error);
|
EthoMainGUI.showGeneralError(error);
|
||||||
},
|
},
|
||||||
function(transaction) {
|
function(transaction) {
|
||||||
/*
|
|
||||||
ipcRenderer.send('storeTransaction', {
|
ipcRenderer.send('storeTransaction', {
|
||||||
block: element.block,
|
block: element.block.toString(),
|
||||||
fromaddr: element.fromaddr,
|
txhash: element.hash.toLowerCase(),
|
||||||
|
fromaddr: element.fromaddr.toLowerCase(),
|
||||||
timestamp: element.timestamp,
|
timestamp: element.timestamp,
|
||||||
toaddr: element.toaddr,
|
toaddr: element.toaddr.toLowerCase(),
|
||||||
value: element.value,
|
value: element.value
|
||||||
confirmed: "1",
|
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ SyncProgress = new ProgressBar.Line('#syncProgress',
|
|||||||
});
|
});
|
||||||
|
|
||||||
// set initial value for the progress text
|
// set initial value for the progress text
|
||||||
SyncProgress.setText("initializing, please wait...");
|
SyncProgress.setText("Waiting for blockchain, please wait...");
|
||||||
|
|
||||||
var peerCountInterval = setInterval(function()
|
var peerCountInterval = setInterval(function()
|
||||||
{
|
{
|
||||||
@@ -39,61 +39,67 @@ var peerCountInterval = setInterval(function()
|
|||||||
|
|
||||||
function StartSyncProcess() {
|
function StartSyncProcess() {
|
||||||
var alreadyCatchedUp = false;
|
var alreadyCatchedUp = false;
|
||||||
|
var nodeSyncInterval = null;
|
||||||
|
|
||||||
function keepTheNodeInSync(interval) {
|
var subscription = web3Local.eth.subscribe('syncing', function(error, sync){
|
||||||
var nodeSyncInterval = setInterval(function()
|
if (!error) {
|
||||||
{
|
if (!sync) {
|
||||||
web3Local.eth.isSyncing(function(error, sync)
|
if (nodeSyncInterval) {
|
||||||
|
clearInterval(nodeSyncInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeSyncInterval = setInterval(function()
|
||||||
|
{
|
||||||
|
web3Local.eth.getBlock("latest", function(error, localBlock) {
|
||||||
|
if (localBlock.number > 0) {
|
||||||
|
if (!EthoTransactions.getIsSyncing()) {
|
||||||
|
SyncProgress.animate(1);
|
||||||
|
SyncProgress.setText(vsprintf('%d/%d (100%%)', [localBlock.number, localBlock.number]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alreadyCatchedUp == false)
|
||||||
|
{
|
||||||
|
// clear the repeat interval and render wallets
|
||||||
|
$(document).trigger("onNewAccountTransaction");
|
||||||
|
alreadyCatchedUp = true;
|
||||||
|
|
||||||
|
// sync all the transactions to the current block
|
||||||
|
EthoTransactions.syncTransactionsForAllAddresses(localBlock.number);
|
||||||
|
$(document).trigger("onSyncInterval");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).on("data", function(sync){
|
||||||
|
if ((sync) && (sync.HighestBlock > 0)) {
|
||||||
|
SyncProgress.animate(sync.CurrentBlock / sync.HighestBlock);
|
||||||
|
SyncProgress.setText(vsprintf('%d/%d (%d%%)', [sync.CurrentBlock, sync.HighestBlock, Math.round(sync.CurrentBlock / sync.HighestBlock * 100)]));
|
||||||
|
}
|
||||||
|
}).on("changed", function(isSyncing){
|
||||||
|
if(isSyncing) {
|
||||||
|
nodeSyncInterval = setInterval(function()
|
||||||
{
|
{
|
||||||
if(!error) {
|
web3Local.eth.isSyncing(function(error, sync){
|
||||||
if(sync == true) {
|
if ((!error) && (sync)) {
|
||||||
console.log("start the sync");
|
|
||||||
} else if(sync) {
|
|
||||||
SyncProgress.animate(sync.currentBlock / sync.highestBlock);
|
SyncProgress.animate(sync.currentBlock / sync.highestBlock);
|
||||||
SyncProgress.setText(vsprintf('%d/%d (%d%%)', [sync.currentBlock, sync.highestBlock, Math.round(sync.currentBlock / sync.highestBlock * 100)]));
|
SyncProgress.setText(vsprintf('%d/%d (%d%%)', [sync.currentBlock, sync.highestBlock, Math.round(sync.currentBlock / sync.highestBlock * 100)]));
|
||||||
} else {
|
|
||||||
web3Local.eth.getBlock("latest", function(error, localBlock) {
|
|
||||||
if (localBlock.number > 0) {
|
|
||||||
web3Remote.eth.getBlock("latest", function(error, remoteBlock) {
|
|
||||||
if (!EthoTransactions.getIsSyncing()) {
|
|
||||||
SyncProgress.animate(localBlock.number / remoteBlock.number);
|
|
||||||
SyncProgress.setText(vsprintf('%d/%d (%d%%)', [localBlock.number, remoteBlock.number, Math.round(localBlock.number / remoteBlock.number * 100)]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remoteBlock.number == localBlock.number) {
|
|
||||||
if (alreadyCatchedUp == false)
|
|
||||||
{
|
|
||||||
// clear the repeat interval and render wallets
|
|
||||||
$(document).trigger("onNewAccountTransaction");
|
|
||||||
clearInterval(nodeSyncInterval);
|
|
||||||
alreadyCatchedUp = true;
|
|
||||||
|
|
||||||
// sync all the transactions to the current block
|
|
||||||
EthoTransactions.syncTransactionsForAllAddresses(localBlock.number);
|
|
||||||
$(document).trigger("onSyncInterval");
|
|
||||||
|
|
||||||
// restart with less intensity
|
|
||||||
keepTheNodeInSync(10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}, 2000);
|
||||||
}, interval);
|
} else {
|
||||||
}
|
if (nodeSyncInterval) {
|
||||||
|
clearInterval(nodeSyncInterval);
|
||||||
// initial fast syncing
|
}
|
||||||
keepTheNodeInSync(2000);
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var InitWeb3 = setInterval(function()
|
var InitWeb3 = setInterval(function()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
web3Local = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
|
web3Local = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
|
||||||
web3Remote = new Web3(new Web3.providers.HttpProvider("https://rpc.ether1.org"));
|
|
||||||
|
|
||||||
web3Local.eth.net.isListening(function(error, success) {
|
web3Local.eth.net.isListening(function(error, success) {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
|||||||
@@ -36,13 +36,12 @@ class Transactions {
|
|||||||
$.getJSON("https://richlist.ether1.org/transactions_list.php" + params, function( result ) {
|
$.getJSON("https://richlist.ether1.org/transactions_list.php" + params, function( result ) {
|
||||||
result.data.forEach(element => {
|
result.data.forEach(element => {
|
||||||
ipcRenderer.send('storeTransaction', {
|
ipcRenderer.send('storeTransaction', {
|
||||||
block: element.block,
|
block: element.block.toString(),
|
||||||
txhash: element.hash,
|
txhash: element.txhash.toLowerCase(),
|
||||||
fromaddr: element.fromaddr,
|
fromaddr: element.fromaddr.toLowerCase(),
|
||||||
timestamp: element.timestamp,
|
timestamp: element.timestamp,
|
||||||
toaddr: element.toaddr,
|
toaddr: element.toaddr.toLowerCase(),
|
||||||
value: element.value,
|
value: element.value
|
||||||
confirmed: "1"
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -149,11 +148,12 @@ class Transactions {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"targets": 6,
|
"targets": 6,
|
||||||
|
"defaultContent": "",
|
||||||
"render": function ( data, type, row ) {
|
"render": function ( data, type, row ) {
|
||||||
if (data == 0) {
|
if (row[1]) {
|
||||||
return '<i class="fas fa-question"></i>';
|
|
||||||
} else if (data == 1) {
|
|
||||||
return '<i class="fas fa-check"></i>';
|
return '<i class="fas fa-check"></i>';
|
||||||
|
} else if (data == 1) {
|
||||||
|
return '<i class="fas fa-question"></i>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,11 +196,11 @@ $(document).on("onSyncInterval", function() {
|
|||||||
if ((EthoWallets.getAddressExists(element.from)) || (EthoWallets.getAddressExists(element.to))) {
|
if ((EthoWallets.getAddressExists(element.from)) || (EthoWallets.getAddressExists(element.to))) {
|
||||||
var Transaction = {
|
var Transaction = {
|
||||||
block: element.blockNumber.toString(),
|
block: element.blockNumber.toString(),
|
||||||
|
txhash: element.hash.toLowerCase(),
|
||||||
fromaddr: element.from.toLowerCase(),
|
fromaddr: element.from.toLowerCase(),
|
||||||
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
|
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
toaddr: element.to.toLowerCase(),
|
toaddr: element.to.toLowerCase(),
|
||||||
value: Number(element.value).toExponential(5).toString().replace('+',''),
|
value: Number(element.value).toExponential(5).toString().replace('+','')
|
||||||
confirmed: "0",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// store transaction and notify about new transactions
|
// store transaction and notify about new transactions
|
||||||
|
|||||||
Reference in New Issue
Block a user