Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a8f4c7e
feat: macos daemons
alex-sandrk May 17, 2023
b8460cb
feat: restart proxy at initial run
alex-sandrk May 17, 2023
f43d02c
use standart name for daemons
alex-sandrk May 17, 2023
182cc23
test Windows service
alex-sandrk May 24, 2023
b6bfba3
fix command
alex-sandrk May 24, 2023
35ca74e
add new resource
alex-sandrk May 24, 2023
b89bb91
add new resource
alex-sandrk May 24, 2023
dcfab08
add new resource
alex-sandrk May 24, 2023
f2a8327
fix: command
alex-sandrk May 24, 2023
4b5b998
fix: wallet uninstall
alex-sandrk May 24, 2023
966a1ff
fix: wallet uninstall
alex-sandrk May 24, 2023
a7f8315
fix: wallet uninstall
alex-sandrk May 24, 2023
02ede0f
fix: wallet uninstall
alex-sandrk May 24, 2023
9e3ca08
fix: wallet uninstall
alex-sandrk May 24, 2023
78ca091
fix: wallet uninstall
alex-sandrk May 24, 2023
4f58cf6
cleanup code
alex-sandrk May 24, 2023
1513c54
fix: wallet uninstall
alex-sandrk May 24, 2023
e23de74
feat: linux system service
alex-sandrk May 26, 2023
05cc47a
fix: linux service installation
alex-sandrk May 26, 2023
3ba955b
fix: linux service installation
alex-sandrk May 26, 2023
28de31a
fix: escape space
alex-sandrk May 30, 2023
737c166
fix: install script
alex-sandrk May 30, 2023
02f9b6d
fix: install script
alex-sandrk May 30, 2023
f36a060
fix: install script
alex-sandrk May 30, 2023
fe08375
refactor daemons code
alex-sandrk May 30, 2023
a492cf5
small refactor
alex-sandrk May 30, 2023
4dbef7e
Merge branch 'dev' of github.com:Lumerin-protocol/WalletDesktop into …
alex-sandrk Jul 28, 2023
ee43519
feat: prefix variables; fix bug
alex-sandrk Jul 28, 2023
b6ca96d
fix: edit contract
alex-sandrk Jul 28, 2023
801ddbd
Merge branch 'dev' of github.com:Lumerin-protocol/WalletDesktop into …
alex-sandrk Aug 7, 2023
112d6af
remove test artifacts
alex-sandrk Aug 7, 2023
5e39086
fix: not defined fn
alex-sandrk Aug 8, 2023
265e3de
feature release
alex-sandrk Aug 8, 2023
f33496f
Revert "fix: not defined fn"
alex-sandrk Aug 8, 2023
f840cc2
revert artifacts
alex-sandrk Aug 8, 2023
5ba7e4a
fix: llinux start command
alex-sandrk Aug 8, 2023
6bec705
fix
alex-sandrk Aug 9, 2023
50112a1
fix env setting
alex-sandrk Aug 9, 2023
3727c33
fix env setting
alex-sandrk Aug 9, 2023
0ca7b03
feat: use launchagents for macos
alex-sandrk Aug 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion assets/installer.nsh
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
!macro customHeader
RequestExecutionLevel admin
!macroend

!macro customUnInstall
ExecWait "TaskKill /IM proxy-router.exe /F"
${ifNot} ${isUpdated}
ExecWait "TaskKill /IM proxy-router.exe /F"
ExecWait "sc stop proxySeller"
ExecWait "sc stop proxyBuyer"
ExecWait "sc delete proxySeller"
ExecWait "sc delete proxyBuyer"
${endIf}
!macroend
Binary file added executables/nssm.zip
Binary file not shown.
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lumerin-wallet-desktop",
"version": "1.1.31",
"version": "1.1.32",
"engines": {
"node": ">=14"
},
Expand Down Expand Up @@ -45,6 +45,7 @@
"@lumerin/wallet-core": "git+ssh://git@github.com:Lumerin-protocol/WalletCore.git#1.0.62",
"@reach/menu-button": "0.17.0",
"@tabler/icons": "1.119.0",
"@vscode/sudo-prompt": "9.3.1",
"axios": "0.27.2",
"babel-preset-env": "1.7.0",
"babel-preset-es2015": "6.24.1",
Expand Down Expand Up @@ -128,7 +129,8 @@
"executables/**/*"
],
"nsis": {
"include": "assets/installer.nsh"
"include": "assets/installer.nsh",
"allowElevation": true
},
"mac": {
"artifactName": "${name}.${ext}",
Expand All @@ -155,6 +157,7 @@
"artifactName": "${name}.${ext}",
"target": "nsis",
"icon": "./assets/lumerin.png",
"requestedExecutionLevel": "requireAdministrator",
"legalTrademarks": ""
}
},
Expand Down
30 changes: 20 additions & 10 deletions public/main/client/handlers/single-core.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@


const os = require("os");

const pTimeout = require("p-timeout");
const logger = require("../../../logger");
const auth = require("../auth");
Expand Down Expand Up @@ -154,12 +156,15 @@ function createWallet(data, core, isOpen = true) {
const restartProxyRouter = async (data, { emitter, api }) => {
const password = await auth.getSessionPassword();

api["proxy-router"].kill(config.chain.buyerProxyPort).catch(logger.error);
await api["proxy-router"]
.kill(config.chain.sellerProxyPort)
.catch(logger.error);

emitter.emit("open-proxy-router", { password });
if (['darwin', 'win32', 'linux'].includes(os.platform()) ) {
emitter.emit("open-proxy-router", { password, restartDaemon: true });
} else {
api["proxy-router"].kill(config.chain.buyerProxyPort).catch(logger.error);
await api["proxy-router"]
.kill(config.chain.sellerProxyPort)
.catch(logger.error);
emitter.emit("open-proxy-router", { password });
}
};

async function openWallet({ emitter }, password) {
Expand Down Expand Up @@ -310,7 +315,6 @@ const getLmrTransferGasLimit = (data, { api }) =>
api.lumerin.estimateGasTransfer(data);

const getAddressAndPrivateKey = async (data, { api }) => {

const isValid = await auth.isValidPassword(data.password);
if (!isValid) {
return { error: new WalletError("Invalid password") };
Expand Down Expand Up @@ -343,14 +347,20 @@ const revealSecretPhrase = async (password) => {
if (!isValid) {
return { error: new WalletError("Invalid password") };
}

const entropy = wallet.getEntropy(password);
const mnemonic = keys.entropyToMnemonic(entropy);
return mnemonic;
}
};

function getPastTransactions({ address, page, pageSize }, { api }) {
return api.explorer.getPastCoinTransactions(0, undefined, address, page, pageSize);
return api.explorer.getPastCoinTransactions(
0,
undefined,
address,
page,
pageSize
);
}

module.exports = {
Expand Down
92 changes: 76 additions & 16 deletions public/main/client/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use strict";

const { ipcMain } = require("electron");
const { ipcMain, app, dialog } = require("electron");
const createCore = require("@lumerin/wallet-core");
const stringify = require("json-stringify-safe");
const os = require("os");

const logger = require("../../logger");
const subscriptions = require("./subscriptions");
Expand All @@ -18,7 +19,11 @@ const {
runProxyRouter,
PROXY_ROUTER_MODE,
isProxyRouterHealthy,
getResourcesPath,
} = require("./proxyRouter");
const { runMacosDaemons } = require("./proxyRouter/macos/daemon");
const { runWindowsServices } = require("./proxyRouter/windows/service");
const { runLinuxDaemons } = require("./proxyRouter/linux/daemon");

function startCore({ chain, core, config: coreConfig }, webContent) {
logger.verbose(`Starting core ${chain}`);
Expand Down Expand Up @@ -61,9 +66,13 @@ function startCore({ chain, core, config: coreConfig }, webContent) {
send("transactions-scan-started", {});

return api.explorer
.syncTransactions(0, address, (number) =>
storage.setSyncBlock(number, chain)
, page, pageSize)
.syncTransactions(
0,
address,
(number) => storage.setSyncBlock(number, chain),
page,
pageSize
)
.then(function() {
send("transactions-scan-finished", { success: true });

Expand All @@ -81,7 +90,9 @@ function startCore({ chain, core, config: coreConfig }, webContent) {
success: false,
});

emitter.once("coin-block", () => syncTransactions({ address }, page, pageSize));
emitter.once("coin-block", () =>
syncTransactions({ address }, page, pageSize)
);
});
}

Expand All @@ -93,7 +104,29 @@ function startCore({ chain, core, config: coreConfig }, webContent) {
);
});

emitter.on("open-proxy-router", async ({ password }) => {
const shouldRestartProxyRouterAfterWalletUpdate = () => {
const prevAppVersion = settings.getAppVersion();
const isAppVersionChanged = prevAppVersion !== app.getVersion();

if (!isAppVersionChanged) {
return false;
}

settings.setAppVersion(app.getVersion());
const choice = dialog.showMessageBoxSync(null, {
type: "question",
buttons: ["Restart", "Later"],
title: "Confirm",
message:
"The wallet was updated and requires the restart of background service. Would you like to do it right now or restart manually later? The currently running contracts will be affected.",
});
if (choice === 0) {
return true;
}
return false;
};

emitter.on("open-proxy-router", async ({ password, restartDaemon }) => {
const proxyRouterUserConfig = settings.getProxyRouterConfig();
if (!proxyRouterUserConfig.useHostedProxyRouter) {
const { address, privateKey } = await getAddressAndPrivateKey(
Expand All @@ -106,26 +139,53 @@ function startCore({ chain, core, config: coreConfig }, webContent) {
...coreConfig.chain,
...proxyRouterUserConfig,
};
const shouldRestartProxy = shouldRestartProxyRouterAfterWalletUpdate();

const isSellerHealthy = await isProxyRouterHealthy(
api,
config.localSellerProxyRouterUrl
);
if (!isSellerHealthy) {
logger.debug("Seller is not healhy, restart...");
await proxyRouterApi.kill(config.sellerProxyPort).catch(logger.error);
runProxyRouter(config, PROXY_ROUTER_MODE.Seller);
}

const isBuyerHealthy = await isProxyRouterHealthy(
api,
config.localBuyerProxyRouterUrl
);
if (!isBuyerHealthy) {
logger.debug("Buyer is not healhy, restart...");
await proxyRouterApi.kill(config.buyerProxyPort).catch(logger.error);
runProxyRouter(config, PROXY_ROUTER_MODE.Buyer);

if (
!isSellerHealthy ||
!isBuyerHealthy ||
restartDaemon ||
shouldRestartProxy
) {
logger.debug("Proxy is not healhy, restart...");
if (os.platform() === "darwin") {
await proxyRouterApi.kill(config.sellerProxyPort).catch(logger.error);
await proxyRouterApi.kill(config.buyerProxyPort).catch(logger.error);
await runMacosDaemons(getResourcesPath(), config);
} else if (os.platform() === "win32") {
await proxyRouterApi.kill(config.sellerProxyPort).catch(logger.error);
await proxyRouterApi.kill(config.buyerProxyPort).catch(logger.error);
await runWindowsServices(getResourcesPath(), config);
} else if (os.platform() === "linux") {
await proxyRouterApi.kill(config.sellerProxyPort).catch(logger.error);
await proxyRouterApi.kill(config.buyerProxyPort).catch(logger.error);
await runLinuxDaemons(getResourcesPath(), config);
} else {
if (!isSellerHealthy) {
await proxyRouterApi
.kill(config.sellerProxyPort)
.catch(logger.error);
runProxyRouter(config, PROXY_ROUTER_MODE.Seller);
}

if (!isBuyerHealthy) {
await proxyRouterApi
.kill(config.buyerProxyPort)
.catch(logger.error);
runProxyRouter(config, PROXY_ROUTER_MODE.Buyer);
}
}
}

send("proxy-router-type-changed", {
isLocal: true,
});
Expand Down
16 changes: 9 additions & 7 deletions public/main/client/proxyRouter.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
const { app } = require("electron");
const fs = require("fs");
const { spawn } = require("child_process");

const logger = require("../../logger.js");
const { spawn } = require("child_process");

const PROXY_ROUTER_MODE = {
Buyer: "buyer",
Seller: "seller",
};

const getResourcesPath = () => {
return process.env.NODE_ENV === "production"
? process.resourcesPath // Prod Mode
: `${__dirname}/../../..`; // Dev Mode
};

const openLogFile = (name, retry = true) => {
try {
const path = `${app.getPath("logs")}/${name}.log`;
Expand Down Expand Up @@ -61,10 +66,7 @@ const runProxyRouter = (config, mode = PROXY_ROUTER_MODE.Seller) => {
};

try {
const resourcePath =
process.env.NODE_ENV === "production"
? process.resourcesPath // Prod Mode
: `${__dirname}/../../..`; // Dev Mode
const resourcePath = getResourcesPath()

const out = openLogFile(`${mode}-out`);
const err = openLogFile(`${mode}-err`);
Expand Down Expand Up @@ -101,4 +103,4 @@ const runProxyRouter = (config, mode = PROXY_ROUTER_MODE.Seller) => {
}
};

module.exports = { runProxyRouter, PROXY_ROUTER_MODE, isProxyRouterHealthy };
module.exports = { runProxyRouter, PROXY_ROUTER_MODE, isProxyRouterHealthy, getResourcesPath };
40 changes: 40 additions & 0 deletions public/main/client/proxyRouter/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const PROXY_ROUTER_MODE = {
Buyer: "buyer",
Seller: "seller",
};

const getProxyRouterEnvs = (config, mode) => {
const modes = {
[PROXY_ROUTER_MODE.Buyer]: [
["PROXY_ADDRESS", `0.0.0.0:${config.buyerProxyPort}`],
["WEB_ADDRESS", `0.0.0.0:${config.buyerWebPort}`],
["IS_BUYER", true],
["POOL_ADDRESS", `"${config.buyerDefaultPool}"`],
["HASHRATE_DIFF_THRESHOLD", 0.1],
],
[PROXY_ROUTER_MODE.Seller]: [
["PROXY_ADDRESS", `0.0.0.0:${config.sellerProxyPort}`],
["WEB_ADDRESS", `0.0.0.0:${config.sellerWebPort}`],
["IS_BUYER", false],
["POOL_ADDRESS", `"${config.sellerDefaultPool}"`],
["HASHRATE_DIFF_THRESHOLD", 0.03],
],
};
return [
["CLONE_FACTORY_ADDRESS", `"${config.cloneFactoryAddress}"`],
["ETH_NODE_ADDRESS", `"${config.wsApiUrl}"`],
["MINER_VETTING_DURATION", "1m"],
["POOL_CONN_TIMEOUT", "15m"],
["POOL_MAX_DURATION", "7m"],
["POOL_MIN_DURATION", "2m"],
["STRATUM_SOCKET_BUFFER_SIZE", 4],
["VALIDATION_BUFFER_PERIOD", "10m"],
["WALLET_ADDRESS", `"${config.walletAddress}"`],
["WALLET_PRIVATE_KEY", `"${config.privateKey}"`],
["LOG_LEVEL", "debug"],
["MINER_SUBMIT_ERR_LIMIT", 0],
...(modes[mode] || []),
];
};

module.exports = { getProxyRouterEnvs, PROXY_ROUTER_MODE };
54 changes: 54 additions & 0 deletions public/main/client/proxyRouter/linux/daemon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const { getProxyRouterEnvs, PROXY_ROUTER_MODE } = require("../config");
const { linuxInstallScript } = require("./installScript");
const { sudo } = require("../sudoPrompt");

const getInstallLinuxServiceCommand = async (daemonName, pathToExecutable) => {
const config = linuxInstallScript
.replaceAll("{serviceName}", daemonName)
.replaceAll("{pathToExecutable}", `${pathToExecutable}/proxy-router`)

const path = `/etc/systemd/system/${daemonName}.service`;
return `touch ${path} && echo '${config}' > ${path}`;
};

const getCommandToRunDaemon = async (serviceName, envs) => {
const setEnvsCommand = envs
.map((e) => `sudo systemctl set-environment ${e[0]}=${e[1]}`)
.join(";");
return `sudo systemctl daemon-reload; ${setEnvsCommand}; sudo service ${serviceName} restart`;
};

const runLinuxDaemons = async (resourcePath, config) => {
const sellerServiceName = "proxyRouterSeller";
const buyerServiceName = "proxyRouterBuyer";
const installSellerCommand = await getInstallLinuxServiceCommand(
sellerServiceName,
`${resourcePath}/executables`
);
const installBuyerCommand = await getInstallLinuxServiceCommand(
buyerServiceName,
`${resourcePath}/executables`
);

const sellerRunCommand = await getCommandToRunDaemon(
sellerServiceName,
getProxyRouterEnvs(config, PROXY_ROUTER_MODE.Seller)
);
const buyerRunCommand = await getCommandToRunDaemon(
buyerServiceName,
getProxyRouterEnvs(config, PROXY_ROUTER_MODE.Buyer)
);

const commands = [
installSellerCommand,
installBuyerCommand,
sellerRunCommand,
buyerRunCommand,
];

await sudo(commands.join(";"));
};

module.exports = {
runLinuxDaemons,
};
Loading