diff --git a/CMakeLists.txt b/CMakeLists.txt index c7ca4065..4d5fc332 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required( VERSION 3.1 ) #set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "Minimum OS X deployment version") if(UNIX AND APPLE) - project(Nunchuk VERSION 1.9.38) + project(Nunchuk VERSION 1.9.39) else() - project(nunchuk-qt VERSION 1.9.38) + project(nunchuk-qt VERSION 1.9.39) endif() set( CMAKE_CXX_STANDARD 20 ) diff --git a/Images/wallet-dark-disabled.svg b/Images/wallet-dark-disabled.svg new file mode 100644 index 00000000..029a20c1 --- /dev/null +++ b/Images/wallet-dark-disabled.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Models/Commons/Slugs.cpp b/Models/Commons/Slugs.cpp index 5d170501..f1fe2889 100644 --- a/Models/Commons/Slugs.cpp +++ b/Models/Commons/Slugs.cpp @@ -74,3 +74,8 @@ bool Slugs::isHoneyBadgerPlus() const { return slugs().contains("honey_badger_plus_testnet") || slugs().contains("honey_badger_plus"); } + +bool Slugs::isDraftWallet() const +{ + return false; +} diff --git a/Models/Commons/Slugs.h b/Models/Commons/Slugs.h index 553b83eb..a6269cf3 100644 --- a/Models/Commons/Slugs.h +++ b/Models/Commons/Slugs.h @@ -22,6 +22,8 @@ class Slugs virtual bool isPremierGroup() const; virtual bool isGroupWallet() const; virtual bool isUserWallet() const; + + virtual bool isDraftWallet() const; }; #endif // SLUGS_H diff --git a/Models/Premiums/QAssistedDraftWallets.cpp b/Models/Premiums/QAssistedDraftWallets.cpp index 5052516d..e7b97001 100644 --- a/Models/Premiums/QAssistedDraftWallets.cpp +++ b/Models/Premiums/QAssistedDraftWallets.cpp @@ -160,8 +160,13 @@ bool QAssistedDraftWallets::RequestAddOrUpdateAKeyToDraftWallet(StructAddHardwar ret = Draco::instance()->assistedWalletAddKey(hardware.mRequestId, data, isDuplicateKey, error_msg); DBG_INFO << data << ret << isDuplicateKey; } else { - ret = Byzantine::instance()->DraftWalletAddKey(hardware.mGroupId, hardware.mRequestId, data, isDuplicateKey, error_msg); - DBG_INFO << data << ret << error_msg << isDuplicateKey; + auto dash = QGroupWallets::instance()->GetDashboard(hardware.mGroupId); + if (dash && dash->isDraftWallet()) { + ret = Draco::instance()->assistedWalletAddKey(hardware.mRequestId, data, isDuplicateKey, error_msg); + } else { + ret = Byzantine::instance()->DraftWalletAddKey(hardware.mGroupId, hardware.mRequestId, data, isDuplicateKey, error_msg); + DBG_INFO << data << ret << error_msg << isDuplicateKey; + } if (ret) { if (auto dashboard = QGroupWallets::instance()->dashboardInfoPtr()) { dashboard->GetAlertsInfo(); @@ -222,8 +227,13 @@ bool QAssistedDraftWallets::RequestAddOrUpdateReuseKeyToDraftWallet(StructAddHar DBG_INFO << data << ret << isDuplicateKey; } else { - ret = Byzantine::instance()->DraftWalletAddKey(hardware.mGroupId, hardware.mRequestId, data, isDuplicateKey, error_msg); - DBG_INFO << data << ret << error_msg << isDuplicateKey; + auto dash = QGroupWallets::instance()->GetDashboard(hardware.mGroupId); + if (dash && dash->isDraftWallet()) { + ret = Draco::instance()->assistedWalletAddKey(hardware.mRequestId, data, isDuplicateKey, error_msg); + } else { + ret = Byzantine::instance()->DraftWalletAddKey(hardware.mGroupId, hardware.mRequestId, data, isDuplicateKey, error_msg); + DBG_INFO << data << ret << error_msg << isDuplicateKey; + } if (ret) { if (auto dashboard = QGroupWallets::instance()->dashboardInfoPtr()) { dashboard->GetAlertsInfo(); @@ -329,7 +339,7 @@ int QAssistedDraftWallets::reuseKeyGetCurrentIndex(const QString &xfp) ENUNCHUCK::AddressType::NATIVE_SEGWIT, msg); if((int)EWARNING::WarningType::NONE_MSG != msg.type()){ - AppModel::instance()->showToast(msg.code(), msg.what(), EWARNING::WarningType::EXCEPTION_MSG); + DBG_INFO << msg.code() << msg.what(); } return ret; } diff --git a/Models/Premiums/QBasePremium.cpp b/Models/Premiums/QBasePremium.cpp index ccceec97..56b3caf3 100644 --- a/Models/Premiums/QBasePremium.cpp +++ b/Models/Premiums/QBasePremium.cpp @@ -11,6 +11,7 @@ #include "Premiums/QInheritancePlan.h" #include "Premiums/QRecurringPayment.h" #include "Premiums/QWalletServicesTag.h" +#include "Premiums/QUserWallets.h" QBasePremium::QBasePremium(WalletId wallet_id) :m_wallet_id(wallet_id) @@ -79,3 +80,14 @@ QStringList QBasePremium::slugs() const { return walletInfoPtr() ? walletInfoPtr()->slugs() : QStringList(); } + +bool QBasePremium::isDraftWallet() const +{ + auto dash = dynamic_cast(this); + if (dash) { + if (auto draft = QUserWallets::instance()->dashboardInfoPtr()) { + return qUtils::strCompare(dash->groupId(), draft->groupId()); + } + } + return false; +} diff --git a/Models/Premiums/QBasePremium.h b/Models/Premiums/QBasePremium.h index dfc037d1..8956efb8 100644 --- a/Models/Premiums/QBasePremium.h +++ b/Models/Premiums/QBasePremium.h @@ -27,6 +27,7 @@ class QBasePremium : public QObject, public Slugs virtual QRecurringPaymentPtr recurringPaymentPtr() const; virtual QWalletServicesTagPtr servicesTagPtr() const; QStringList slugs() const final; + bool isDraftWallet() const final; private: WalletId m_wallet_id; }; diff --git a/Models/Premiums/QGroupDashboard.cpp b/Models/Premiums/QGroupDashboard.cpp index 09717fee..bd02d3c6 100644 --- a/Models/Premiums/QGroupDashboard.cpp +++ b/Models/Premiums/QGroupDashboard.cpp @@ -128,6 +128,9 @@ QString QGroupDashboard::userEmail() const QVariantList QGroupDashboard::members() const { + if (isDraftWallet()) { + return {}; + } return groupInfo()["members"].toArray().toVariantList(); } @@ -165,7 +168,7 @@ QJsonObject QGroupDashboard::walletJson() const void QGroupDashboard::GetMemberInfo() { - if (isUserWallet() || isReplaced()) return; + if (isUserWallet() || isReplaced() || isDraftWallet()) return; QJsonObject output; QString error_msg = ""; bool ret = Byzantine::instance()->GetOneGroupWallets(groupId(), output, error_msg); @@ -180,7 +183,10 @@ void QGroupDashboard::GetAlertsInfo() QJsonObject output; QString error_msg = ""; bool ret {false}; - if (isUserWallet()) { + if (isDraftWallet()) { + ret = Draco::instance()->DraftWalletGetAlerts(output, error_msg); + } + else if (isUserWallet()) { ret = Draco::instance()->GetAlerts(wallet_id(), output, error_msg); } else { @@ -216,7 +222,10 @@ bool QGroupDashboard::MarkAlertAsRead(const QString &alert_id) QJsonObject output; QString error_msg = ""; bool ret {false}; - if (isUserWallet()) { + if (isDraftWallet()) { + ret = Draco::instance()->DraftWalletMarkAnAlertAsRead(alert_id, output, error_msg); + } + else if (isUserWallet()) { ret = Draco::instance()->MarkAlertAsRead(wallet_id(), alert_id, output, error_msg); } else { @@ -237,7 +246,10 @@ bool QGroupDashboard::DismissAlert(const QString &alert_id) QJsonObject output; QString error_msg = ""; bool ret {false}; - if (isUserWallet()) { + if (isDraftWallet()) { + ret = Draco::instance()->DraftWalletDismissAnAlert(alert_id, output, error_msg); + } + else if (isUserWallet()) { ret = Draco::instance()->DismissAlert(wallet_id(), alert_id, output, error_msg); } else { @@ -262,7 +274,9 @@ void QGroupDashboard::GetWalletInfo() QJsonObject output; QString error_msg = ""; bool ret {false}; - if (isUserWallet()) { + if (isDraftWallet()) { + + } else if (isUserWallet()) { ret = Draco::instance()->assistedWalletGetInfo(wallet_id(), output, error_msg); } else { ret = Byzantine::instance()->GetCurrentGroupWallet(groupId(), output, error_msg); @@ -301,10 +315,14 @@ void QGroupDashboard::checkInheritanceWallet() void QGroupDashboard::GetDraftWalletInfo() { - if (isUserWallet()) return; QJsonObject output; QString error_msg = ""; - bool ret = Byzantine::instance()->GetCurrentGroupDraftWallet(groupId(), output, error_msg); + bool ret {false}; + if (isDraftWallet()) { + ret = Draco::instance()->DraftWalletGetCurrent(output, error_msg); + } else if (!isUserWallet()){ + ret = Byzantine::instance()->GetCurrentGroupDraftWallet(groupId(), output, error_msg); + } if (ret) { QJsonObject draft_wallet = output["draft_wallet"].toObject(); UpdateKeys(draft_wallet); @@ -560,6 +578,7 @@ bool QGroupDashboard::canEntryClickAlert() return true; } } + case AlertEnum::E_Alert_t::WALLET_PENDING: case AlertEnum::E_Alert_t::GROUP_WALLET_PENDING:{ QtConcurrent::run([this]() { GetDraftWalletInfo(); @@ -856,7 +875,12 @@ void QGroupDashboard::byzantineRoomDeleted(QString room_id, QString group_id) void QGroupDashboard::requestShowLetAddYourKeys() { - setFlow((int)AlertEnum::E_Alert_t::GROUP_WALLET_PENDING); + if (isDraftWallet()) { + setFlow((int)AlertEnum::E_Alert_t::WALLET_PENDING); + } + else { + setFlow((int)AlertEnum::E_Alert_t::GROUP_WALLET_PENDING); + } QEventProcessor::instance()->sendEvent(E::EVT_SHOW_GROUP_WALLET_CONFIG_REQUEST); } diff --git a/Models/Premiums/QGroupWallets.cpp b/Models/Premiums/QGroupWallets.cpp index cb4b9df7..7e192167 100644 --- a/Models/Premiums/QGroupWallets.cpp +++ b/Models/Premiums/QGroupWallets.cpp @@ -2,6 +2,7 @@ #include "Chats/ClientController.h" #include "QEventProcessor.h" #include "ViewsEnums.h" +#include "Premiums/QUserWallets.h" QGroupWallets::QGroupWallets() : QAssistedDraftWallets(GROUP_WALLET) @@ -57,18 +58,25 @@ void QGroupWallets::GetAllGroups() if(!CLIENT_INSTANCE->isNunchukLoggedIn()){ return; } + QUserWallets::instance()->GetDraftWallet(); QtConcurrent::run([=, this]() { QJsonObject output; QString error_msg = ""; bool ret = Byzantine::instance()->GetAllGroupWallets(output, error_msg); + QJsonArray groupList; + auto draft = QUserWallets::instance()->dashboardInfoPtr(); + if (draft) { + groupList.append(draft->groupInfo()); + } if (ret) { QJsonArray groups = output["groups"].toArray(); for (auto v : groups) { QJsonObject group = v.toObject(); + groupList.append(group); DBG_INFO << group["id"].toString() << group["status"].toString(); } GetListAllRequestAddKey(groups); - emit dashboardList(groups); + emit dashboardList(groupList); } else { //Show error DBG_INFO << error_msg; @@ -110,7 +118,12 @@ void QGroupWallets::ResetGroupWallet() if (!mDashboard) return; QJsonObject output; QString error_msg = ""; - bool ret = Byzantine::instance()->ResetGroupWallet(mDashboard->groupId(), output, error_msg); + bool ret {false}; + if (mDashboard->isDraftWallet()) { + ret = Draco::instance()->DraftWalletResetCurrent(output, error_msg); + } else { + ret = Byzantine::instance()->ResetGroupWallet(mDashboard->groupId(), output, error_msg); + } if(ret){ GetAllGroups(); QString msg_name = QString("Wallet has been canceled"); @@ -139,6 +152,10 @@ void QGroupWallets::MakePendingDashboardList(const QJsonArray &groups) else{ // status = "DELETED" continue; } + auto draft = QUserWallets::instance()->dashboardInfoPtr(); + if (draft && draft->groupId() == group_id) { + dashboard = draft; + } if(group_id != ""){ groupids.append(group_id); if (!Contains(group_id)) { diff --git a/Models/Premiums/QUserWallets.cpp b/Models/Premiums/QUserWallets.cpp index a1b4673c..1429fd8f 100644 --- a/Models/Premiums/QUserWallets.cpp +++ b/Models/Premiums/QUserWallets.cpp @@ -7,6 +7,7 @@ #include "ServiceSetting.h" #include "nunchuckiface.h" #include "ViewsEnums.h" +#include "ifaces/Servers/Draco.h" QUserWallets::QUserWallets() : QAssistedDraftWallets(USER_WALLET) @@ -24,3 +25,52 @@ QUserWallets *QUserWallets::instance() static QUserWallets mInstance; return &mInstance; } + +void QUserWallets::GetDraftWallet() +{ + QJsonObject output; + QString error_msg = ""; + bool ret = Draco::instance()->DraftWalletGetCurrent(output, error_msg); + if (ret) { + QJsonObject draft_wallet = output["draft_wallet"].toObject(); + if (draft_wallet.isEmpty()) { + mDashboard.clear(); + } + else { + QJsonObject info; + info["status"] = "PENDING_WALLET"; + info["id"] = draft_wallet["id"]; + QJsonObject user; + DracoUser me = ClientController::instance()->getMe(); + user["id"] = me.id; + user["name"] = me.name; + user["email"] = me.email; + user["avatar"] = me.avatar; + user["chat_id"] = me.chat_id; + QJsonObject member; + member["user"] = user; + member["status"] = "ACTIVE"; + member["role"] = "MASTER"; + QJsonArray members; + members.append(member); + info["members"] = members; + QGroupDashboardPtr dashboard = QGroupDashboardPtr(new QGroupDashboard("")); + dashboard->setGroupInfo(info); + DBG_INFO << info; + mDashboard = dashboard; + } + } +} + +QGroupDashboardPtr QUserWallets::dashboardInfoPtr() +{ + return mDashboard; +} + +bool QUserWallets::hasDraftWallet(const QString& group_id) +{ + if (!mDashboard.isNull() && mDashboard->groupId() == group_id) { + return true; + } + return false; +} diff --git a/Models/Premiums/QUserWallets.h b/Models/Premiums/QUserWallets.h index 6459298c..10d71283 100644 --- a/Models/Premiums/QUserWallets.h +++ b/Models/Premiums/QUserWallets.h @@ -27,6 +27,7 @@ #include "TypeDefine.h" #include "Servers/Draco.h" #include "Premiums/QAssistedDraftWallets.h" +#include "Premiums/QGroupDashboard.h" class QUserWallets : public QAssistedDraftWallets { @@ -35,9 +36,12 @@ class QUserWallets : public QAssistedDraftWallets QUserWallets(); ~QUserWallets(); static QUserWallets *instance(); -private: - + void GetDraftWallet(); + QGroupDashboardPtr dashboardInfoPtr(); + bool hasDraftWallet(const QString& group_id); +private: + QGroupDashboardPtr mDashboard {}; }; #endif // QUSERWALLETS_H diff --git a/Qml/Components/customizes/Buttons/QIconButton.qml b/Qml/Components/customizes/Buttons/QIconButton.qml index 0e83dc81..deb07411 100644 --- a/Qml/Components/customizes/Buttons/QIconButton.qml +++ b/Qml/Components/customizes/Buttons/QIconButton.qml @@ -41,7 +41,7 @@ QBaseButton { id: idIcon width: iconSize height: iconSize - icons: icon !== "" ? [icon, icon, icon, icon] : icons + icons: icon !== "" ? [icon, icon, icon, icon] : idBtn.icons anchors.centerIn: parent scale: btnMouse.pressed ? 0.9 : 1 transformOrigin: Item.Center diff --git a/Qml/Components/customizes/QHomePendingWallet.qml b/Qml/Components/customizes/QHomePendingWallet.qml index 432c4ead..ed1f15ed 100644 --- a/Qml/Components/customizes/QHomePendingWallet.qml +++ b/Qml/Components/customizes/QHomePendingWallet.qml @@ -118,11 +118,13 @@ Rectangle { } } } + QIconButton { width: 48 height: 48 bgColor: "#F5F5F5" - icon: "qrc:/Images/Images/OnlineMode/wallet-dark.png" + enabled: !("PENDING_WALLET" === pendingDashboard.groupStatus) + icons: ["wallet-dark.svg", "wallet-dark.svg", "wallet-dark-disabled.svg", "wallet-dark.svg"] onClicked: { // FIXME GOTO WALLET INFO dashboardInfo.isShowDashBoard = false diff --git a/Qml/Components/customizes/Signers/QAddRequestKey.qml b/Qml/Components/customizes/Signers/QAddRequestKey.qml index 1d27a1e5..46e62fbc 100644 --- a/Qml/Components/customizes/Signers/QAddRequestKey.qml +++ b/Qml/Components/customizes/Signers/QAddRequestKey.qml @@ -411,7 +411,7 @@ Item { anchors.verticalCenter: parent.verticalCenter horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter - font.pixelSize: 12 + font.pixelSize: 16 } } QBadge { diff --git a/Qml/Components/customizes/Wallets/QDashboardAlert.qml b/Qml/Components/customizes/Wallets/QDashboardAlert.qml index 358d26e1..c72e7dee 100644 --- a/Qml/Components/customizes/Wallets/QDashboardAlert.qml +++ b/Qml/Components/customizes/Wallets/QDashboardAlert.qml @@ -93,6 +93,7 @@ Rectangle { verticalCenter: parent.verticalCenter } enabled: modelData.type === AlertType.GROUP_WALLET_PENDING || + modelData.type === AlertType.WALLET_PENDING || modelData.type === AlertType.GROUP_WALLET_SETUP || modelData.type === AlertType.HEALTH_CHECK_REQUEST || modelData.type === AlertType.HEALTH_CHECK_PENDING || diff --git a/Qml/Screens/OnlineMode/SCR_DASHBOARD_ALERT_INFO.qml b/Qml/Screens/OnlineMode/SCR_DASHBOARD_ALERT_INFO.qml index dcebc757..75a3e618 100644 --- a/Qml/Screens/OnlineMode/SCR_DASHBOARD_ALERT_INFO.qml +++ b/Qml/Screens/OnlineMode/SCR_DASHBOARD_ALERT_INFO.qml @@ -44,6 +44,7 @@ QScreen { property string config_flow: GroupWallet.dashboardInfo.configFlow readonly property var map_flow: [ {flow_action: AlertType.GROUP_WALLET_PENDING, screen_component: _wallet_creation_pending}, + {flow_action: AlertType.WALLET_PENDING, screen_component: _wallet_creation_pending}, {flow_action: AlertType.GROUP_WALLET_SETUP, screen_component: _wallet_setup}, {flow_action: AlertType.UPDATE_SERVER_KEY, screen_component: _platform_key_policy_change}, {flow_action: AlertType.HEALTH_CHECK_PENDING, screen_component: _health_check_pending}, diff --git a/Qml/Screens/OnlineMode/SetupWallets/QWalletCreationPending.qml b/Qml/Screens/OnlineMode/SetupWallets/QWalletCreationPending.qml index 1320d6e8..e5182d16 100644 --- a/Qml/Screens/OnlineMode/SetupWallets/QWalletCreationPending.qml +++ b/Qml/Screens/OnlineMode/SetupWallets/QWalletCreationPending.qml @@ -47,7 +47,7 @@ Item { width: popupWidth height: popupHeight anchors.centerIn: parent - label.text: STR.STR_QML_936 + label.text: alert.title extraHeader: Item {} onCloseClicked: closeTo(NUNCHUCKTYPE.WALLET_TAB) content: Item { diff --git a/ifaces/Servers/Draco.cpp b/ifaces/Servers/Draco.cpp index 65eae63f..9565e172 100644 --- a/ifaces/Servers/Draco.cpp +++ b/ifaces/Servers/Draco.cpp @@ -4144,4 +4144,325 @@ void Draco::setIsSubscribed(bool newIsSubscribed) emit isSubscribedChanged(); } +bool Draco::DraftWalletMarkAnAlertAsRead(const QString alert_id, QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_MARK_ALERT_AS_READ]; + cmd.replace("{alert_id}", alert_id); + + QJsonObject jsonObj = putSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletDismissAnAlert(const QString alert_id, QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_DISMISS_ALERT]; + cmd.replace("{alert_id}", alert_id); + + QJsonObject jsonObj = putSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletGetAlerts(QJsonObject &output, QString &errormsg) +{ + const int size = 20; + auto getAlerts = [&] (int index, QJsonArray &alert) -> bool { + QJsonObject data; + data["offset"] = QString("%1").arg(index); // Adjust offset + data["limit"] = QString("%1").arg(size); // Adjust limit + + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_GET_ALERTS]; + QJsonObject jsonObj = getSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + QJsonObject ret = jsonObj["data"].toObject(); + alert = ret["alerts"].toArray(); + return true; + } + else{ + errormsg = response_msg; + DBG_INFO << response_code << response_msg; + return false; + } + } + errormsg = reply_msg; + return false; + }; + QJsonArray alerts; + int index = 0; + while (true) { + QJsonArray alert {}; + bool ret = getAlerts(index, alert); + if (ret == false) { + return false; + } + if (alert.isEmpty()) { + break; + } + for (const auto &item : alert) { + alerts.append(item); + } + if (alert.size() < size) { + break; + } + index += size; + } + output["alerts"] = alerts; + return true; +} + +bool Draco::DraftWalletGetAlertsCount(QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_GET_TOTAL_ALERTS]; + QJsonObject jsonObj = getSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + AppModel::instance()->showToast(response_code, response_msg, EWARNING::WarningType::EXCEPTION_MSG); + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletSetServerKey(const QString &server_key_id, QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + data["server_key_id"] = server_key_id; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_SET_SERVER_KEY]; + QJsonObject jsonObj = postSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletRequestAddKey(QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + QJsonArray tags; + tags.append("INHERITANCE"); + data["tags"] = tags; + data["key_index"] = 0; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_GET_REQUEST_ADD_KEY]; + QJsonObject jsonObj = postSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + AppModel::instance()->showToast(response_code, response_msg, EWARNING::WarningType::EXCEPTION_MSG); + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletPushRequestAddKey(const QString &request_id, QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + QJsonArray tags; + tags.append("INHERITANCE"); + data["tags"] = tags; + data["key_index"] = 0; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_PUSH_REQUEST_ADD_KEY]; + cmd.replace("{request_id}", request_id); + QJsonObject jsonObj = postSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + AppModel::instance()->showToast(response_code, response_msg, EWARNING::WarningType::EXCEPTION_MSG); + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletInit(int m, int n, bool required_server_key, bool allow_inheritance, QJsonObject &output, QString &errormsg) +{ + QJsonObject wallet_config; + wallet_config["m"] = m; + wallet_config["n"] = n; + wallet_config["required_server_key"] = required_server_key; + wallet_config["allow_inheritance"] = allow_inheritance; + QJsonObject data; + data["wallet_config"] = wallet_config; + + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_INIT]; + QJsonObject jsonObj = postSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + AppModel::instance()->showToast(response_code, response_msg, EWARNING::WarningType::EXCEPTION_MSG); + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletGetStatusOfARequestAddKey(const QString &request_id, QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_GET_REQUEST_ADD_KEY]; + cmd.replace("{request_id}", request_id); + QJsonObject jsonObj = getSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + AppModel::instance()->showToast(response_code, response_msg, EWARNING::WarningType::EXCEPTION_MSG); + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletGetCurrent(QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_GET_CURRENT]; + QJsonObject jsonObj = getSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + AppModel::instance()->showToast(response_code, response_msg, EWARNING::WarningType::EXCEPTION_MSG); + return false; + } + } + errormsg = reply_msg; + return false; +} + +bool Draco::DraftWalletResetCurrent(QJsonObject &output, QString &errormsg) +{ + QJsonObject data; + int reply_code = -1; + QString reply_msg = ""; + QString cmd = commands[Premium::CMD_IDX::DRAFT_WALLET_RESET_CURRENT]; + QJsonObject jsonObj = deleteSync(cmd, data, reply_code, reply_msg); + if(reply_code == DRACO_CODE::SUCCESSFULL){ + QJsonObject errorObj = jsonObj["error"].toObject(); + int response_code = errorObj["code"].toInt(); + QString response_msg = errorObj["message"].toString(); + if(response_code == DRACO_CODE::RESPONSE_OK){ + output = jsonObj["data"].toObject(); + return true; + } + else{ + errormsg = response_msg; + AppModel::instance()->showToast(response_code, response_msg, EWARNING::WarningType::EXCEPTION_MSG); + return false; + } + } + errormsg = reply_msg; + return false; +} diff --git a/ifaces/Servers/Draco.h b/ifaces/Servers/Draco.h index 379c9a92..bad0e67a 100644 --- a/ifaces/Servers/Draco.h +++ b/ifaces/Servers/Draco.h @@ -416,6 +416,18 @@ class Draco : public QRest bool isSubscribed() const; void setIsSubscribed(bool newIsSubscribed); + // Draft Wallet + bool DraftWalletMarkAnAlertAsRead(const QString alert_id, QJsonObject &output, QString &errormsg); + bool DraftWalletDismissAnAlert(const QString alert_id, QJsonObject &output, QString &errormsg); + bool DraftWalletGetAlerts(QJsonObject &output, QString &errormsg); + bool DraftWalletGetAlertsCount(QJsonObject &output, QString &errormsg); + bool DraftWalletSetServerKey(const QString &server_key_id, QJsonObject &output, QString &errormsg); + bool DraftWalletRequestAddKey(QJsonObject &output, QString &errormsg); + bool DraftWalletPushRequestAddKey(const QString &request_id, QJsonObject &output, QString &errormsg); + bool DraftWalletInit(int m, int n, bool required_server_key, bool allow_inheritance, QJsonObject &output, QString &errormsg); + bool DraftWalletGetStatusOfARequestAddKey(const QString &request_id, QJsonObject &output, QString &errormsg); + bool DraftWalletGetCurrent(QJsonObject &output, QString &errormsg); + bool DraftWalletResetCurrent(QJsonObject &output, QString &errormsg); private: Draco(); ~Draco(); diff --git a/ifaces/Servers/DracoDefines.h b/ifaces/Servers/DracoDefines.h index af676533..4c8860be 100644 --- a/ifaces/Servers/DracoDefines.h +++ b/ifaces/Servers/DracoDefines.h @@ -271,6 +271,19 @@ enum CMD_IDX { SIGN_DUMMY_TRANSACTION_TO_SIGN_IN, SIGN_IN_USING_XPUB_WALLET, + // Draft Wallet + DRAFT_WALLET_MARK_ALERT_AS_READ, + DRAFT_WALLET_DISMISS_ALERT, + DRAFT_WALLET_GET_ALERTS, + DRAFT_WALLET_GET_TOTAL_ALERTS, + DRAFT_WALLET_SET_SERVER_KEY, + DRAFT_WALLET_REQUEST_ADD_KEY, + DRAFT_WALLET_PUSH_REQUEST_ADD_KEY, + DRAFT_WALLET_INIT, + DRAFT_WALLET_GET_REQUEST_ADD_KEY, + DRAFT_WALLET_GET_CURRENT, + DRAFT_WALLET_RESET_CURRENT, + CMD_MAX }; } @@ -604,6 +617,18 @@ const QMap commands { { Premium::CMD_IDX::ASSISTED_WALLET_GET_STATUS_KEY_REPLACEMENT , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("wallets/{wallet_id_or_local_id}/replacement/status") }, { Premium::CMD_IDX::ASSISTED_WALLET_RESET_KEY_REPLACEMENT , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("wallets/{wallet_id_or_local_id}/replacement/reset") }, + // Draft Wallet + { Premium::CMD_IDX::DRAFT_WALLET_MARK_ALERT_AS_READ , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/current/alerts/{alert_id}/mark-as-read") }, + { Premium::CMD_IDX::DRAFT_WALLET_DISMISS_ALERT , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/current/alerts/{alert_id}/dismiss") }, + { Premium::CMD_IDX::DRAFT_WALLET_GET_ALERTS , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/current/alerts") }, + { Premium::CMD_IDX::DRAFT_WALLET_GET_TOTAL_ALERTS , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/current/alerts/total") }, + { Premium::CMD_IDX::DRAFT_WALLET_SET_SERVER_KEY , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/set-server-key") }, + { Premium::CMD_IDX::DRAFT_WALLET_REQUEST_ADD_KEY , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/request-add-key") }, + { Premium::CMD_IDX::DRAFT_WALLET_PUSH_REQUEST_ADD_KEY , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/request-add-key/{request_id}/push") }, + { Premium::CMD_IDX::DRAFT_WALLET_INIT , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/init") }, + { Premium::CMD_IDX::DRAFT_WALLET_GET_REQUEST_ADD_KEY , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/request-add-key/{request_id}") }, + { Premium::CMD_IDX::DRAFT_WALLET_GET_CURRENT , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/current") }, + { Premium::CMD_IDX::DRAFT_WALLET_RESET_CURRENT , QString("%1/%2").arg(DRAGON_USER_WALLETS_URL).arg("draft-wallets/current") }, //DRAGON_GROUP_WALLETS { Group::CMD_IDX::GROUP_WALLET_LIST_WALLETS , QString("%1/%2").arg(DRAGON_GROUP_WALLETS_URL).arg("wallets") }, diff --git a/localization/STR_QML.js b/localization/STR_QML.js index f1ff3d1f..fdbdc15a 100644 --- a/localization/STR_QML.js +++ b/localization/STR_QML.js @@ -114,7 +114,7 @@ var STR_QML_081 = qsTr("Your wallet is almost ready") var STR_QML_082 = qsTr("Wrapping up...") //SCR_ADD_NEW_SIGNER.qml -var STR_QML_083 = qsTr("Add a key") +var STR_QML_083 = qsTr("Add key") var STR_QML_084 = qsTr("Hardware key") var STR_QML_085 = qsTr("Wired and air-gapped keys supported.") var STR_QML_086 = qsTr("Add hardware key") @@ -1510,7 +1510,7 @@ var STR_QML_1223 = qsTr("I’ll explore on my own") var STR_QML_1224 = qsTr("Freely create hot wallets, watch-only wallets, or state-of-the-art multisig wallets that work with a plethora of hardware signing devices. Choose one that fits your need. \n \ \n \ To quickly create a hot wallet for immediate use, click the button below. You can back it up later.") -var STR_QML_1225 = qsTr("Create a hot wallet now") +var STR_QML_1225 = qsTr("Create hot wallet now") var STR_QML_1226 = qsTr("Hot wallet") var STR_QML_1227 = qsTr("A hot wallet is a wallet that is frequently connected to the Internet. \n \ \n \ @@ -1537,9 +1537,9 @@ var STR_QML_1245 = qsTr("I have an advisor") var STR_QML_1246 = qsTr("Here are some of the things that you can do with an assisted wallet:") var STR_QML_1247 = qsTr("Get more out of Nunchuk with an assisted wallet") var STR_QML_1248 = qsTr("Visit our website") -var STR_QML_1249 = qsTr("Add a wallet") +var STR_QML_1249 = qsTr("Add wallet") var STR_QML_1250 = qsTr("Use a multisig wallet for maximum safety. A multisig wallet has multiple keys—if one is compromised, your fund is still safe.") -var STR_QML_1251 = qsTr("Create a hot wallet") +var STR_QML_1251 = qsTr("Create hot wallet") var STR_QML_1252 = qsTr("Quickly create a hot wallet for immediate use and back it up later. No existing keys required.") var STR_QML_1253 = qsTr("Recover existing wallet") var STR_QML_1254 = qsTr("Recover hot wallet") @@ -1550,7 +1550,7 @@ var STR_QML_1258 = qsTr("Learn more about Nunchuk assisted services") var STR_QML_1259 = qsTr("Send query") var STR_QML_1260 = qsTr("If you are looking for a white-glove, personalized service offered by a Bitcoin Advisor, enter your country and email address below, and we’ll send you the best Bitcoin Advisors in your area. \n \n Alternatively, check out the assisted services offered by our platform.") var STR_QML_1261 = qsTr("Create new assisted wallet (%1 remaining)") -var STR_QML_1262 = qsTr("Create a new wallet") +var STR_QML_1262 = qsTr("Create new wallet") var STR_QML_1263 = qsTr("Your email address") var STR_QML_1264 = qsTr("Your country") diff --git a/main.cpp b/main.cpp index 7f769411..c245045f 100644 --- a/main.cpp +++ b/main.cpp @@ -124,7 +124,7 @@ int main(int argc, char* argv[]) app.setOrganizationName("nunchuk"); app.setOrganizationDomain("nunchuk.io"); app.setApplicationName("NunchukClient"); - app.setApplicationVersion("1.9.38"); + app.setApplicationVersion("1.9.39"); app.setApplicationDisplayName(QString("%1 %2").arg("Nunchuk").arg(app.applicationVersion())); AppModel::instance(); Draco::instance(); diff --git a/qml.qrc b/qml.qrc index 7c57df6c..ad27883a 100644 --- a/qml.qrc +++ b/qml.qrc @@ -776,6 +776,7 @@ Images/groups-dark.svg Images/health-check-light.svg Images/person-add-24px.svg + Images/wallet-dark-disabled.svg Info.plist