@@ -17,12 +17,12 @@ tar -xvf zec-qt-wallet-v0.2.7.tar.gz
|
|||||||
Unzip the release binary and double click on zec-qt-wallet to start.
|
Unzip the release binary and double click on zec-qt-wallet to start.
|
||||||
|
|
||||||
## Prerequisites: zcashd
|
## Prerequisites: zcashd
|
||||||
zec-qt-wallet needs a Zcash node running zcashd. Linux users should download the zcash node software
|
zec-qt-wallet needs a Zcash node running zcashd. Linux users should download the Zcash node software
|
||||||
from [https://z.cash/download/](https://z.cash/download/), configure `zcash.conf`, download the parameters and start zcashd according to the [official documentation](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html).
|
from [https://z.cash/download/](https://z.cash/download/), configure `zcash.conf`, download the parameters and start zcashd according to the [official documentation](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html).
|
||||||
|
|
||||||
There is currently no official zcashd build for Windows so Windows users may either [cross-compile from source on Linux](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#installation) to generate the necessary zcashd executables or simply download community hosted pre-compiled executables such as those hosted by WinZEC developer [@radix42](https://github.com/radix42) at https://zcash.dl.mercerweiss.com/zcash-win-v2.0.1b.zip.
|
There is currently no official zcashd build for Windows so Windows users may either [cross-compile from source on Linux](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#installation) to generate the necessary zcashd executables or simply download community hosted pre-compiled executables such as those hosted by WinZEC developer [@radix42](https://github.com/radix42) at https://zcash.dl.mercerweiss.com/zcash-win-v2.0.1b.zip.
|
||||||
|
|
||||||
Alternitavely run zcashd inside [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
|
Alternatively run zcashd inside [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
|
||||||
|
|
||||||
For all installations zcashd needs to run with RPC enabled (`server=1`, which is the default) and with a RPC username/password set. Add the following entries into `~/.zcash/zcash.conf` for Linux or` C:\Users\your-username\AppData\Roaming\Zcash\zcash.conf` on Windows replacing the default values with a strong password. zec-qt-wallet should detect these settings but if that fails you may edit the connection settings manually via the `File->Settings` menu.
|
For all installations zcashd needs to run with RPC enabled (`server=1`, which is the default) and with a RPC username/password set. Add the following entries into `~/.zcash/zcash.conf` for Linux or` C:\Users\your-username\AppData\Roaming\Zcash\zcash.conf` on Windows replacing the default values with a strong password. zec-qt-wallet should detect these settings but if that fails you may edit the connection settings manually via the `File->Settings` menu.
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ rpcuser=username
|
|||||||
rpcpassword=password
|
rpcpassword=password
|
||||||
```
|
```
|
||||||
|
|
||||||
Additionaly for Windows users the Zcash parameters must be manually downloaded and placed in `C:\Users\your-username\AppData\Roaming\ZcashParams`. The following files are required (and are around ~1.7GB in total).
|
Additionally for Windows users the Zcash parameters must be manually downloaded and placed in `C:\Users\your-username\AppData\Roaming\ZcashParams`. The following files are required (and are around ~1.7GB in total).
|
||||||
|
|
||||||
```
|
```
|
||||||
https://z.cash/downloads/sapling-spend.params
|
https://z.cash/downloads/sapling-spend.params
|
||||||
@@ -87,7 +87,7 @@ The easiest way to connect to a remote node is probably to ssh to it with port f
|
|||||||
ssh -L8232:127.0.0.1:8232 user@remotehost
|
ssh -L8232:127.0.0.1:8232 user@remotehost
|
||||||
```
|
```
|
||||||
### 2. "Not enough balance" when sending transactions
|
### 2. "Not enough balance" when sending transactions
|
||||||
The most likely cause for this is that you are trying to spend unconfirmed funds. Unlike bitcoin, the zcash protocol doesn't let you spent unconfirmed funds yet. Please wait for
|
The most likely cause for this is that you are trying to spend unconfirmed funds. Unlike Bitcoin, the Zcash protocol doesn't let you spent unconfirmed funds yet. Please wait for
|
||||||
1-2 blocks for the funds to confirm and retry the transaction.
|
1-2 blocks for the funds to confirm and retry the transaction.
|
||||||
|
|
||||||
### Support or other questions
|
### Support or other questions
|
||||||
|
|||||||
@@ -640,10 +640,10 @@ void MainWindow::setupTransactionsTab() {
|
|||||||
void MainWindow::addNewZaddr(bool sapling) {
|
void MainWindow::addNewZaddr(bool sapling) {
|
||||||
rpc->newZaddr(sapling, [=] (json reply) {
|
rpc->newZaddr(sapling, [=] (json reply) {
|
||||||
QString addr = QString::fromStdString(reply.get<json::string_t>());
|
QString addr = QString::fromStdString(reply.get<json::string_t>());
|
||||||
// Make sure the RPC class reloads the Z-addrs for future use
|
// Make sure the RPC class reloads the z-addrs for future use
|
||||||
rpc->refreshAddresses();
|
rpc->refreshAddresses();
|
||||||
|
|
||||||
// Just double make sure the Z-address is still checked
|
// Just double make sure the z-address is still checked
|
||||||
if (( sapling && ui->rdioZSAddr->isChecked()) ||
|
if (( sapling && ui->rdioZSAddr->isChecked()) ||
|
||||||
(!sapling && ui->rdioZAddr->isChecked())) {
|
(!sapling && ui->rdioZAddr->isChecked())) {
|
||||||
ui->listRecieveAddresses->insertItem(0, addr);
|
ui->listRecieveAddresses->insertItem(0, addr);
|
||||||
@@ -684,7 +684,7 @@ void MainWindow::setupRecieveTab() {
|
|||||||
rpc->newTaddr([=] (json reply) {
|
rpc->newTaddr([=] (json reply) {
|
||||||
QString addr = QString::fromStdString(reply.get<json::string_t>());
|
QString addr = QString::fromStdString(reply.get<json::string_t>());
|
||||||
|
|
||||||
// Just double make sure the T-address is still checked
|
// Just double make sure the t-address is still checked
|
||||||
if (ui->rdioTAddr->isChecked()) {
|
if (ui->rdioTAddr->isChecked()) {
|
||||||
ui->listRecieveAddresses->insertItem(0, addr);
|
ui->listRecieveAddresses->insertItem(0, addr);
|
||||||
ui->listRecieveAddresses->setCurrentIndex(0);
|
ui->listRecieveAddresses->setCurrentIndex(0);
|
||||||
@@ -696,8 +696,8 @@ void MainWindow::setupRecieveTab() {
|
|||||||
|
|
||||||
// Connect t-addr radio button
|
// Connect t-addr radio button
|
||||||
QObject::connect(ui->rdioTAddr, &QRadioButton::toggled, [=] (bool checked) {
|
QObject::connect(ui->rdioTAddr, &QRadioButton::toggled, [=] (bool checked) {
|
||||||
// Whenever the T-address is selected, we generate a new address, because we don't
|
// Whenever the t-address is selected, we generate a new address, because we don't
|
||||||
// want to reuse T-addrs
|
// want to reuse t-addrs
|
||||||
if (checked && this->rpc->getUTXOs() != nullptr) {
|
if (checked && this->rpc->getUTXOs() != nullptr) {
|
||||||
auto utxos = this->rpc->getUTXOs();
|
auto utxos = this->rpc->getUTXOs();
|
||||||
ui->listRecieveAddresses->clear();
|
ui->listRecieveAddresses->clear();
|
||||||
@@ -729,12 +729,12 @@ void MainWindow::setupRecieveTab() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Focus enter for the Recieve Tab
|
// Focus enter for the Receive Tab
|
||||||
QObject::connect(ui->tabWidget, &QTabWidget::currentChanged, [=] (int tab) {
|
QObject::connect(ui->tabWidget, &QTabWidget::currentChanged, [=] (int tab) {
|
||||||
if (tab == 2) {
|
if (tab == 2) {
|
||||||
// Switched to recieve tab, so update everything.
|
// Switched to receive tab, so update everything.
|
||||||
|
|
||||||
// Hide Sapling radio button if sapling is not active
|
// Hide Sapling radio button if Sapling is not active
|
||||||
if (Settings::getInstance()->isSaplingActive()) {
|
if (Settings::getInstance()->isSaplingActive()) {
|
||||||
ui->rdioZSAddr->setVisible(true);
|
ui->rdioZSAddr->setVisible(true);
|
||||||
ui->rdioZSAddr->setChecked(true);
|
ui->rdioZSAddr->setChecked(true);
|
||||||
@@ -742,7 +742,7 @@ void MainWindow::setupRecieveTab() {
|
|||||||
} else {
|
} else {
|
||||||
ui->rdioZSAddr->setVisible(false);
|
ui->rdioZSAddr->setVisible(false);
|
||||||
ui->rdioZAddr->setChecked(true);
|
ui->rdioZAddr->setChecked(true);
|
||||||
ui->rdioZAddr->setText("z-Addr"); // Don't use the "Sprout" label if there's no sapling
|
ui->rdioZAddr->setText("z-Addr"); // Don't use the "Sprout" label if there's no Sapling
|
||||||
}
|
}
|
||||||
|
|
||||||
// And then select the first one
|
// And then select the first one
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
|
|||||||
|
|
||||||
// A special function that will call the callback when two lists have been added
|
// A special function that will call the callback when two lists have been added
|
||||||
auto holder = new QPair<int, QList<QPair<QString, QString>>>();
|
auto holder = new QPair<int, QList<QPair<QString, QString>>>();
|
||||||
holder->first = 0; // This is the number of times the callback has been called, initalized to 0
|
holder->first = 0; // This is the number of times the callback has been called, initialized to 0
|
||||||
auto fnCombineTwoLists = [=] (QList<QPair<QString, QString>> list) {
|
auto fnCombineTwoLists = [=] (QList<QPair<QString, QString>> list) {
|
||||||
// Increment the callback counter
|
// Increment the callback counter
|
||||||
holder->first++;
|
holder->first++;
|
||||||
@@ -269,7 +269,7 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// First get all the T and Z addresses.
|
// First get all the t and z addresses.
|
||||||
json payloadT = {
|
json payloadT = {
|
||||||
{"jsonrpc", "1.0"},
|
{"jsonrpc", "1.0"},
|
||||||
{"id", "someid"},
|
{"id", "someid"},
|
||||||
@@ -699,7 +699,7 @@ void RPC::watchTxStatus() {
|
|||||||
conn->doRPCWithDefaultErrorHandling(payload, [=] (const json& reply) {
|
conn->doRPCWithDefaultErrorHandling(payload, [=] (const json& reply) {
|
||||||
// There's an array for each item in the status
|
// There's an array for each item in the status
|
||||||
for (auto& it : reply.get<json::array_t>()) {
|
for (auto& it : reply.get<json::array_t>()) {
|
||||||
// If we were watching this Tx and it's status became "success", then we'll show a status bar alert
|
// If we were watching this Tx and its status became "success", then we'll show a status bar alert
|
||||||
QString id = QString::fromStdString(it["id"]);
|
QString id = QString::fromStdString(it["id"]);
|
||||||
if (watchingOps.contains(id)) {
|
if (watchingOps.contains(id)) {
|
||||||
// And if it ended up successful
|
// And if it ended up successful
|
||||||
@@ -755,7 +755,7 @@ void RPC::watchTxStatus() {
|
|||||||
|
|
||||||
// Get the ZEC->USD price from coinmarketcap using their API
|
// Get the ZEC->USD price from coinmarketcap using their API
|
||||||
void RPC::refreshZECPrice() {
|
void RPC::refreshZECPrice() {
|
||||||
qDebug() << QString::fromStdString("Getting zec price");
|
qDebug() << QString::fromStdString("Getting ZEC price");
|
||||||
if (conn == nullptr)
|
if (conn == nullptr)
|
||||||
return noConnection();
|
return noConnection();
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ echo "Linux"
|
|||||||
|
|
||||||
echo -n "Configuring..."
|
echo -n "Configuring..."
|
||||||
$QT_STATIC/bin/qmake zec-qt-wallet.pro -spec linux-clang CONFIG+=release > /dev/null
|
$QT_STATIC/bin/qmake zec-qt-wallet.pro -spec linux-clang CONFIG+=release > /dev/null
|
||||||
#Mingw seems to have trouble with precompiled heades, so strip that option from the .pro file
|
#Mingw seems to have trouble with precompiled headers, so strip that option from the .pro file
|
||||||
echo "[OK]"
|
echo "[OK]"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ void MainWindow::setMemoEnabled(int number, bool enabled) {
|
|||||||
memoBtn->setToolTip("");
|
memoBtn->setToolTip("");
|
||||||
} else {
|
} else {
|
||||||
memoBtn->setEnabled(false);
|
memoBtn->setEnabled(false);
|
||||||
memoBtn->setToolTip("Only Z addresses can have memos");
|
memoBtn->setToolTip("Only z-addresses can have memos");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,8 +225,8 @@ void MainWindow::memoButtonClicked(int number) {
|
|||||||
// Memos can only be used with zAddrs. So check that first
|
// Memos can only be used with zAddrs. So check that first
|
||||||
auto addr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Address") + QString::number(number));
|
auto addr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Address") + QString::number(number));
|
||||||
if (!addr->text().trimmed().startsWith("z")) {
|
if (!addr->text().trimmed().startsWith("z")) {
|
||||||
QMessageBox msg(QMessageBox::Critical, "Memos can only be used with z Addresses",
|
QMessageBox msg(QMessageBox::Critical, "Memos can only be used with z-addresses",
|
||||||
"The Memo field can only be used with a z Address.\n" + addr->text() + "\ndoesn't look like a z Address",
|
"The memo field can only be used with a z-address.\n" + addr->text() + "\ndoesn't look like a z-address",
|
||||||
QMessageBox::Ok, this);
|
QMessageBox::Ok, this);
|
||||||
|
|
||||||
msg.exec();
|
msg.exec();
|
||||||
@@ -261,7 +261,7 @@ void MainWindow::removeExtraAddresses() {
|
|||||||
// The last one is a spacer, so ignore that
|
// The last one is a spacer, so ignore that
|
||||||
int totalItems = ui->sendToWidgets->children().size() - 2;
|
int totalItems = ui->sendToWidgets->children().size() - 2;
|
||||||
|
|
||||||
// Clear the first recepient fields
|
// Clear the first recipient fields
|
||||||
auto addr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Address1"));
|
auto addr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Address1"));
|
||||||
addr->clear();
|
addr->clear();
|
||||||
auto amt = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount1"));
|
auto amt = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount1"));
|
||||||
@@ -511,7 +511,7 @@ void MainWindow::sendButton() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindow::doSendTxValidations(Tx tx) {
|
QString MainWindow::doSendTxValidations(Tx tx) {
|
||||||
// 1. Addresses are valid format.
|
// 1. Addresses have valid format.
|
||||||
QRegExp zcexp("^z[a-z0-9]{94}$", Qt::CaseInsensitive);
|
QRegExp zcexp("^z[a-z0-9]{94}$", Qt::CaseInsensitive);
|
||||||
QRegExp zsexp("^z[a-z0-9]{77}$", Qt::CaseInsensitive);
|
QRegExp zsexp("^z[a-z0-9]{77}$", Qt::CaseInsensitive);
|
||||||
QRegExp ztsexp("^ztestsapling[a-z0-9]{76}", Qt::CaseInsensitive);
|
QRegExp ztsexp("^ztestsapling[a-z0-9]{76}", Qt::CaseInsensitive);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ void SentTxStore::addToSentTx(Tx tx, QString txid) {
|
|||||||
if (!Settings::getInstance()->getSaveZtxs())
|
if (!Settings::getInstance()->getSaveZtxs())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Also, only store outgoing Txs where the from address is a z-Addr. Else, regular zcashd
|
// Also, only store outgoing txs where the from address is a z-Addr. Else, regular zcashd
|
||||||
// stores it just fine
|
// stores it just fine
|
||||||
if (!tx.fromAddr.startsWith("z"))
|
if (!tx.fromAddr.startsWith("z"))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ void Turnstile::planMigration(QString zaddr, QString destAddr, int numsplits, in
|
|||||||
auto bal = rpc->getAllBalances()->value(zaddr);
|
auto bal = rpc->getAllBalances()->value(zaddr);
|
||||||
auto splits = splitAmount(bal, numsplits);
|
auto splits = splitAmount(bal, numsplits);
|
||||||
|
|
||||||
// Then, generate an intermediate t-Address for each part using getBatchRPC
|
// Then, generate an intermediate t-address for each part using getBatchRPC
|
||||||
rpc->getConnection()->doBatchRPC<double>(splits,
|
rpc->getConnection()->doBatchRPC<double>(splits,
|
||||||
[=] (double /*unused*/) {
|
[=] (double /*unused*/) {
|
||||||
json payload = {
|
json payload = {
|
||||||
@@ -186,7 +186,7 @@ void Turnstile::fillAmounts(QList<double>& amounts, double amount, int count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get a random amount off the amount (between half and full) and call recursively.
|
// Get a random amount off the amount (between half and full) and call recursively.
|
||||||
// Multiply by hundered, because we'll operate on 0.01 ZEC minimum. We'll divide by 100 later
|
// Multiply by hundred, because we'll operate on 0.01 ZEC minimum. We'll divide by 100 later
|
||||||
double curAmount = std::rand() % (int)std::floor(amount * 100);
|
double curAmount = std::rand() % (int)std::floor(amount * 100);
|
||||||
|
|
||||||
// Try to round it off
|
// Try to round it off
|
||||||
@@ -319,14 +319,14 @@ void Turnstile::executeMigrationStep() {
|
|||||||
|
|
||||||
} else if (nextStep->status == TurnstileMigrationItemStatus::SentToT) {
|
} else if (nextStep->status == TurnstileMigrationItemStatus::SentToT) {
|
||||||
// First thing to do is check to see if the funds are confirmed.
|
// First thing to do is check to see if the funds are confirmed.
|
||||||
// We'll check both the original sprout address and the intermediate T addr for safety.
|
// We'll check both the original sprout address and the intermediate t-addr for safety.
|
||||||
if (fnHasUnconfirmed(nextStep->intTAddr) || fnHasUnconfirmed(nextStep->fromAddr)) {
|
if (fnHasUnconfirmed(nextStep->intTAddr) || fnHasUnconfirmed(nextStep->fromAddr)) {
|
||||||
//qDebug() << QString("unconfirmed, waiting");
|
//qDebug() << QString("unconfirmed, waiting");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rpc->getAllBalances()->keys().contains(nextStep->intTAddr)) {
|
if (!rpc->getAllBalances()->keys().contains(nextStep->intTAddr)) {
|
||||||
qDebug() << QString("The intermediate Taddress doesn't have balance, even though it is confirmed");
|
qDebug() << QString("The intermediate t-address doesn't have balance, even though it is confirmed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const QString Utils::getDevAddr(Tx tx) {
|
|||||||
return devAddr;
|
return devAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// t-Addr, find if it is going to a sprout or sapling address
|
// t-Addr, find if it is going to a Sprout or Sapling address
|
||||||
for (const ToFields& to : tx.toAddrs) {
|
for (const ToFields& to : tx.toAddrs) {
|
||||||
devAddr = testnetAddrLookup(to.addr);
|
devAddr = testnetAddrLookup(to.addr);
|
||||||
if (!devAddr.isEmpty()) {
|
if (!devAddr.isEmpty()) {
|
||||||
@@ -55,7 +55,7 @@ const QString Utils::getDevAddr(Tx tx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a t-Addr -> t-Addr transaction, use the sapling address by default
|
// If this is a t-Addr -> t-Addr transaction, use the Sapling address by default
|
||||||
return testnetAddrLookup("ztestsapling");
|
return testnetAddrLookup("ztestsapling");
|
||||||
} else {
|
} else {
|
||||||
// Mainnet doesn't have a fee yet!
|
// Mainnet doesn't have a fee yet!
|
||||||
|
|||||||
Reference in New Issue
Block a user