Compare commits

..

No commits in common. "fbc06a407b5bb3a31edc6122834c536cd4a3792c" and "28c4c3a1d9a4399e72d267d9222a4e59f4fd43e8" have entirely different histories.

9 changed files with 110 additions and 247 deletions

View file

@ -1,6 +1,6 @@
{
"name": "oxen-electron-wallet",
"version": "1.8.0",
"version": "1.7.2",
"description": "Modern GUI interface for Oxen Currency",
"productName": "Oxen Electron Wallet",
"repository": {

View file

@ -122,19 +122,19 @@ export class Backend {
this.remotes = [
{
host: "public-na.optf.ngo",
host: "imaginary.stream",
port: "22023"
},
{
host: "explorer.oxen.aussie-pools.com",
host: "nodes.hashvault.pro",
port: "22023"
},
{
host: "explorer.loki.aussie-pools.com",
port: "18081"
},
{
host: "public-eu.optf.ngo",
port: "22023"
},
{
host: "oxen-rpc.caliban.org",
host: "public.loki.foundation",
port: "22023"
}
];

View file

@ -272,12 +272,7 @@ export class WalletRPC {
break;
case "create_wallet":
this.createWallet(
params.name,
params.password,
params.language,
params.hardware_wallet
);
this.createWallet(params.name, params.password, params.language);
break;
case "restore_wallet":
@ -514,20 +509,13 @@ export class WalletRPC {
});
}
isHardwareWallet(filename) {
let hwfile = path.join(this.wallet_dir, filename + ".hwdev.txt");
return fs.existsSync(hwfile);
}
createWallet(filename, password, language, hardware_wallet) {
createWallet(filename, password, language) {
// Reset the status error
this.sendGateway("reset_wallet_error");
this.sendRPC("create_wallet", {
filename,
password,
language,
hardware_wallet: !!hardware_wallet,
device_label: hardware_wallet ? "hardware_wallet" : undefined
language
}).then(data => {
if (data.hasOwnProperty("error")) {
this.sendGateway("set_wallet_error", { status: data.error });
@ -714,14 +702,6 @@ export class WalletRPC {
errorOnExist: true
});
}
if (fs.existsSync(import_path + ".hwdev.txt")) {
fs.copySync(
import_path + ".hwdev.txt",
destination + ".hwdev.txt",
fs.constants.COPYFILE_EXCL
);
}
} catch (e) {
this.sendGateway("set_wallet_error", {
status: {
@ -814,10 +794,6 @@ export class WalletRPC {
}
}
if (this.isHardwareWallet(filename)) {
wallet.info.hardware_wallet = true;
}
this.saveWallet().then(() => {
let address_txt_path = path.join(
this.wallet_dir,
@ -834,11 +810,7 @@ export class WalletRPC {
this.sendGateway("set_wallet_data", wallet);
if (this.isHardwareWallet(filename)) {
this.startHeartbeat(10);
} else {
this.startHeartbeat();
}
this.startHeartbeat();
});
}
@ -868,12 +840,6 @@ export class WalletRPC {
});
}
const hardware_wallet_file = path.join(
this.wallet_dir,
filename + ".hwdev.txt"
);
const hardware_wallet = fs.existsSync(hardware_wallet_file);
// store hash of the password so we can check against it later when requesting private keys, or for sending txs
this.wallet_state.password_hash = crypto
.pbkdf2Sync(password, this.auth[2], 1000, 64, "sha512")
@ -881,20 +847,10 @@ export class WalletRPC {
this.wallet_state.name = filename;
this.wallet_state.open = true;
if (hardware_wallet) {
this.startHeartbeat(10);
} else {
this.startHeartbeat();
}
this.startHeartbeat();
this.purchasedNames = {};
this.sendGateway("set_wallet_data", {
info: {
hardware_wallet
}
});
// Check if we have a view only wallet by querying the spend key
this.sendRPC("query_key", { key_type: "spend_key" }).then(data => {
if (data.hasOwnProperty("error") || !data.hasOwnProperty("result")) {
@ -911,17 +867,17 @@ export class WalletRPC {
});
}
startHeartbeat(multiplier = 1) {
startHeartbeat() {
clearInterval(this.heartbeat);
this.heartbeat = setInterval(() => {
this.heartbeatAction();
}, 5000 * multiplier);
}, 5000);
this.heartbeatAction(true);
clearInterval(this.onsHeartbeat);
this.onsHeartbeat = setInterval(() => {
this.updateLocalONSRecords();
}, 30 * 1000 * multiplier); // Every 30 seconds
}, 30 * 1000); // Every 30 seconds
this.updateLocalONSRecords();
}
@ -1745,9 +1701,6 @@ export class WalletRPC {
// send address and tx fees before sending
// isSweepAll refers to if it's the sweep from service nodes page
transfer(password, amount, address, priority, isSweepAll) {
console.log(
"TODO sean remove this - wallet: " + JSON.stringify(this.wallet)
);
const cryptoCallback = (err, password_hash) => {
if (err) {
this.sendGateway("set_tx_status", {
@ -2729,7 +2682,7 @@ export class WalletRPC {
return;
}
// Exclude all files without keys
// Exclude all files without a keys extension
if (path.extname(filename) !== ".keys") return;
const wallet_name = path.parse(filename).name;
@ -2738,8 +2691,7 @@ export class WalletRPC {
let wallet_data = {
name: wallet_name,
address: null,
password_protected: null,
hardware_wallet: false
password_protected: null
};
if (
@ -2768,12 +2720,6 @@ export class WalletRPC {
}
}
if (
fs.existsSync(path.join(this.wallet_dir, wallet_name + ".hwdev.txt"))
) {
wallet_data.hardware_wallet = true;
}
wallets.list.push(wallet_data);
} catch (e) {
// Something went wrong

View file

@ -72,20 +72,13 @@ export default {
node.contributors.find(
c => c.address === this.our_address && c.amount > 0
);
return nodes
.filter(getOurContribution)
.sort((a, b) => {
if (a.service_node_pubkey < b.service_node_pubkey) return -1;
if (a.service_node_pubkey > b.service_node_pubkey) return 1;
return 0;
})
.map(n => {
const ourContribution = getOurContribution(n);
return {
...n,
ourContributionAmount: ourContribution.amount
};
});
return nodes.filter(getOurContribution).map(n => {
const ourContribution = getOurContribution(n);
return {
...n,
ourContributionAmount: ourContribution.amount
};
});
},
fetching: state => state.gateway.daemon.service_nodes.fetching
}),

View file

@ -1,86 +0,0 @@
<template>
<q-item @click.native="openWallet(wallet)">
<q-item-section avatar>
<q-icon class="wallet-icon">
<svg
width="48"
viewBox="0 0 17 16"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="si-glyph si-glyph-wallet"
>
<defs class="si-glyph-fill"></defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(1.000000, 0.000000)" fill="#434343">
<path
d="M7.988,10.635 L7.988,8.327 C7.988,7.578 8.561,6.969 9.267,6.969 L13.964,6.969 L13.964,5.531 C13.964,4.849 13.56,4.279 13.007,4.093 L13.007,4.094 L11.356,4.08 L11.336,4.022 L3.925,4.022 L3.784,4.07 L1.17,4.068 L1.165,4.047 C0.529,4.167 0.017,4.743 0.017,5.484 L0.017,13.437 C0.017,14.269 0.665,14.992 1.408,14.992 L12.622,14.992 C13.365,14.992 13.965,14.316 13.965,13.484 L13.965,12.031 L9.268,12.031 C8.562,12.031 7.988,11.384 7.988,10.635 L7.988,10.635 Z"
class="si-glyph-fill"
></path>
<path
d="M14.996,8.061 L14.947,8.061 L9.989,8.061 C9.46,8.061 9.031,8.529 9.031,9.106 L9.031,9.922 C9.031,10.498 9.46,10.966 9.989,10.966 L14.947,10.966 L14.996,10.966 C15.525,10.966 15.955,10.498 15.955,9.922 L15.955,9.106 C15.955,8.528 15.525,8.061 14.996,8.061 L14.996,8.061 Z M12.031,10.016 L9.969,10.016 L9.969,9 L12.031,9 L12.031,10.016 L12.031,10.016 Z"
class="si-glyph-fill"
></path>
<path
d="M3.926,4.022 L10.557,1.753 L11.337,4.022 L12.622,4.022 C12.757,4.022 12.885,4.051 13.008,4.092 L11.619,0.051 L1.049,3.572 L1.166,4.048 C1.245,4.033 1.326,4.023 1.408,4.023 L3.926,4.023 L3.926,4.022 Z"
class="si-glyph-fill"
></path>
</g>
</g>
</svg>
</q-icon>
</q-item-section>
<q-item-section>
<q-item-label class="wallet-name" caption>{{ wallet.name }}</q-item-label>
<q-item-label class="monospace ellipsis" caption>{{
wallet.address
}}</q-item-label>
</q-item-section>
<ContextMenu
:menu-items="menuItems"
@openWallet="openWallet(wallet)"
@copyAddress="copyAddress(wallet.address)"
/>
</q-item>
</template>
<script>
const { clipboard } = require("electron");
import { mapState } from "vuex";
export default {
name: "WalletListItem",
props: {
wallet: {
type: Object,
required: true
},
openWallet: {
type: Function,
required: true
}
},
computed: mapState({
theme: state => state.gateway.app.config.appearance.theme,
info: state => state.gateway.wallet.info
}),
methods: {
copyAddress() {
event.stopPropagation();
for (let i = 0; i < event.path.length; i++) {
if (event.path[i].tagName == "BUTTON") {
event.path[i].blur();
break;
}
}
clipboard.writeText(this.wallet.address);
this.$q.notify({
type: "positive",
timeout: 1000,
message: this.$t("notification.positive.addressCopied")
});
}
}
};
</script>
<style lang="scss"></style>

View file

@ -516,8 +516,6 @@ export default {
"Purchase or update an ONS record. If you purchase a name, it may take a minute or two for it to show up in the list.",
onsDescription:
"Here you can find all the ONS names owned by this wallet. Decrypting a record you own will return the name and value of that ONS record.",
hardwareWallet: "Hardware wallet",
hardwareWallets: "Hardware wallets",
loadingSettings: "Loading settings",
oxenBalance: "Balance",
lokinetNameDescription:
@ -547,7 +545,6 @@ export default {
recentIncomingTransactionsToAddress:
"Recent incoming transactions to this address",
recentTransactionsWithAddress: "Recent transactions with this address",
regularWallets: "Regular wallets",
rescanModalDescription:
"Select full rescan or rescan of spent outputs only.",
saveSeedWarning: "Please copy and save these in a secure location!",

View file

@ -50,32 +50,12 @@
/>
</OxenField>
<q-field class="q-pb-sm">
<q-checkbox
v-model="wallet.hardware_wallet"
:label="$t('strings.hardwareWallet')"
/>
</q-field>
<OxenField
v-if="!wallet.hardware_wallet"
:label="$t('fieldLabels.seedLanguage')"
>
<q-select
v-model="wallet.language"
:options="languageOptions"
:dark="theme == 'dark'"
hide-underline
/>
</OxenField>
<q-field>
<q-btn
color="primary"
:label="$t('buttons.createWallet')"
@click="create"
/>
</q-field>
<q-btn
class="submit-button"
color="primary"
:label="$t('buttons.createWallet')"
@click="create"
/>
</div>
</q-page>
</template>
@ -108,8 +88,7 @@ export default {
name: "",
language: languageOptions[0].value,
password: "",
password_confirm: "",
hardware_wallet: false
password_confirm: ""
},
languageOptions
};

View file

@ -1,7 +1,7 @@
<template>
<q-page>
<q-list class="wallet-list" link no-border :dark="theme == 'dark'">
<template v-if="wallet_list.length">
<q-list class="wallet-list" no-border :dark="theme == 'dark'">
<template v-if="wallets.list.length">
<div class="header row justify-between items-center">
<div class="header-title">
{{ $t("titles.yourWallets") }}
@ -30,36 +30,61 @@
</q-btn>
</div>
<div class="hr-separator" />
<!-- Hardware wallets -->
<q-list-header v-if="hardware_wallets.length">
<div class="header row justify-between items-center">
<div class="header-title">
{{ $t("strings.hardwareWallets") }}
</div>
</div>
</q-list-header>
<WalletListItem
v-for="wallet in hardware_wallets"
<q-item
v-for="wallet in wallets.list"
:key="`${wallet.address}-${wallet.name}`"
:wallet="wallet"
:open-wallet="openWallet"
/>
<!-- Regular wallets -->
<q-list-header v-if="hardware_wallets.length">
<div class="header row justify-between items-center">
<div class="header-title">
{{ $t("strings.regularWallets") }}
</div>
</div>
</q-list-header>
<WalletListItem
v-for="wallet in regular_wallets"
:key="`${wallet.address}-${wallet.name}`"
:wallet="wallet"
:open-wallet="openWallet"
/>
<q-item-separator />
@click.native="openWallet(wallet)"
>
<q-item-section avatar>
<q-icon class="wallet-icon">
<svg
width="48"
viewBox="0 0 17 16"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="si-glyph si-glyph-wallet"
>
<defs class="si-glyph-fill"></defs>
<g
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
>
<g transform="translate(1.000000, 0.000000)" fill="#434343">
<path
d="M7.988,10.635 L7.988,8.327 C7.988,7.578 8.561,6.969 9.267,6.969 L13.964,6.969 L13.964,5.531 C13.964,4.849 13.56,4.279 13.007,4.093 L13.007,4.094 L11.356,4.08 L11.336,4.022 L3.925,4.022 L3.784,4.07 L1.17,4.068 L1.165,4.047 C0.529,4.167 0.017,4.743 0.017,5.484 L0.017,13.437 C0.017,14.269 0.665,14.992 1.408,14.992 L12.622,14.992 C13.365,14.992 13.965,14.316 13.965,13.484 L13.965,12.031 L9.268,12.031 C8.562,12.031 7.988,11.384 7.988,10.635 L7.988,10.635 Z"
class="si-glyph-fill"
></path>
<path
d="M14.996,8.061 L14.947,8.061 L9.989,8.061 C9.46,8.061 9.031,8.529 9.031,9.106 L9.031,9.922 C9.031,10.498 9.46,10.966 9.989,10.966 L14.947,10.966 L14.996,10.966 C15.525,10.966 15.955,10.498 15.955,9.922 L15.955,9.106 C15.955,8.528 15.525,8.061 14.996,8.061 L14.996,8.061 Z M12.031,10.016 L9.969,10.016 L9.969,9 L12.031,9 L12.031,10.016 L12.031,10.016 Z"
class="si-glyph-fill"
></path>
<path
d="M3.926,4.022 L10.557,1.753 L11.337,4.022 L12.622,4.022 C12.757,4.022 12.885,4.051 13.008,4.092 L11.619,0.051 L1.049,3.572 L1.166,4.048 C1.245,4.033 1.326,4.023 1.408,4.023 L3.926,4.023 L3.926,4.022 Z"
class="si-glyph-fill"
></path>
</g>
</g>
</svg>
</q-icon>
</q-item-section>
<q-item-section>
<q-item-label class="wallet-name" caption>{{
wallet.name
}}</q-item-label>
<q-item-label class="monospace ellipsis" caption>{{
wallet.address
}}</q-item-label>
</q-item-section>
<ContextMenu
:menu-items="menuItems"
@openWallet="openWallet(wallet)"
@copyAddress="copyAddress(wallet.address)"
/>
</q-item>
<q-separator />
</template>
<template v-else>
<q-item
@ -77,24 +102,27 @@
</template>
<script>
const { clipboard } = require("electron");
import { mapState } from "vuex";
import WalletListItem from "components/wallet_list_item";
import ContextMenu from "components/menus/contextmenu";
export default {
components: {
WalletListItem
ContextMenu
},
data() {
const menuItems = [
{ action: "openWallet", i18n: "menuItems.openWallet" },
{ action: "copyAddress", i18n: "menuItems.copyAddress" }
];
return {
menuItems
};
},
computed: mapState({
theme: state => state.gateway.app.config.appearance.theme,
wallets: state => state.gateway.wallets,
wallet_list: state => state.gateway.wallets.list,
status: state => state.gateway.wallet.status,
hardware_wallets() {
return this.wallet_list.filter(w => w.hardware_wallet);
},
regular_wallets() {
return this.wallet_list.filter(w => !w.hardware_wallet);
},
actions() {
// TODO: Add this in once LOKI has the functionality
// <q-item @click.native="restoreViewWallet()">
@ -217,6 +245,14 @@ export default {
},
importLegacyWallet() {
this.$router.replace({ path: "wallet-select/import-legacy" });
},
copyAddress(address) {
clipboard.writeText(address);
this.$q.notify({
type: "positive",
timeout: 1000,
message: this.$t("notification.positive.addressCopied")
});
}
}
};

View file

@ -33,11 +33,9 @@ export default {
height: 0,
balance: 0,
unlocked_balance: 0,
view_only: false,
hardware_wallet: false,
accrued_balance: 0,
accrued_balance_next_payout: 0
accrued_balance_next_payout: 0,
view_only: false
},
secret: {
mnemonic: "",