From 371c50b2ab90b51f479e3906656a6a8b4d52c31d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Nov 2018 11:01:15 -0800 Subject: [PATCH 1/5] Start work on Pay Out UI --- .../commerce/common/sendAsset/SendAsset.qml | 146 +++++++++++++++++- 1 file changed, 139 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 2d0bb2d87b..2a2369795e 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -269,7 +269,7 @@ Item { RalewaySemiBold { id: sendAssetText; - text: root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"; + text: root.assetCertID === "" ? "Send Money To:" : "Send \"" + root.assetName + "\" To:"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -370,6 +370,50 @@ Item { } } + Item { + id: authorizedScriptButton; + // Anchors + anchors.top: nearbyButton.bottom; + anchors.topMargin: 32; + anchors.horizontalCenter: parent.horizontalCenter; + height: connectionButton.height; + width: connectionButton.width; + + Image { + anchors.top: parent.top; + source: "./images/nearby.svg"; + height: 70; + width: parent.width; + fillMode: Image.PreserveAspectFit; + horizontalAlignment: Image.AlignHCenter; + verticalAlignment: Image.AlignTop; + mipmap: true; + } + + RalewaySemiBold { + text: "Authorized Script"; + // Anchors + anchors.bottom: parent.bottom; + height: 15; + width: parent.width; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + horizontalAlignment: Text.AlignHCenter; + } + + MouseArea { + anchors.fill: parent; + onClicked: { + sendAssetStep.referrer = "authorizedScript"; + sendAssetStep.selectedRecipientNodeID = ""; + + root.nextActiveView = "sendAssetStep"; + } + } + } + HifiControlsUit.Button { id: backButton_sendAssetHome; visible: parentAppNavBarHeight === 0; @@ -860,7 +904,7 @@ Item { id: sendAssetStep; z: 996; - property string referrer; // either "connections", "nearby", or "payIn" + property string referrer; // either "connections", "nearby", "payIn", or "authorizedScript" property string selectedRecipientNodeID; property string selectedRecipientDisplayName; property string selectedRecipientUserName; @@ -872,7 +916,8 @@ Item { RalewaySemiBold { id: sendAssetText_sendAssetStep; - text: sendAssetStep.referrer === "payIn" && root.assetCertID !== "" ? "Send \"" + root.assetName + "\":" : + text: ((sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript") && + root.assetCertID !== "") ? "Send \"" + root.assetName + "\":" : (root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"); // Anchors anchors.top: parent.top; @@ -901,12 +946,13 @@ Item { RalewaySemiBold { id: sendToText_sendAssetStep; - text: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; + text: sendAssetStep.referrer === "authorizedScript" ? "Script Secret:" : + (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; anchors.bottom: parent.bottom; - width: 90; + width: paintedWidth; // Text size size: 18; // Style @@ -915,8 +961,10 @@ Item { } RecipientDisplay { + visible: sendAssetStep.referrer !== "authorizedScript"; anchors.top: parent.top; anchors.left: sendToText_sendAssetStep.right; + anchors.leftMargin: 16; anchors.right: changeButton.left; anchors.rightMargin: 12; height: parent.height; @@ -929,6 +977,71 @@ Item { multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } + Item { + id: scriptSecretContainer; + visible: sendAssetStep.referrer === "authorizedScript"; + anchors.top: parent.top; + anchors.left: sendToText_sendAssetStep.right; + anchors.right: parent.right; + height: parent.height; + + RalewaySemiBold { + id: scriptSecretHelp; + text: "[?]"; + // Anchors + anchors.left: parent.left; + anchors.leftMargin: 8; + anchors.verticalCenter: parent.verticalCenter; + height: 30; + width: paintedWidth; + // Text size + size: 18; + // Style + color: hifi.colors.blueAccent; + MouseArea { + anchors.fill: parent; + hoverEnabled: true; + onEntered: { + parent.color = hifi.colors.blueHighlight; + } + onExited: { + parent.color = hifi.colors.blueAccent; + } + onClicked: { + lightboxPopup.titleText = "Script Secret"; + lightboxPopup.bodyText = "This alphanumeric text string will be used to ensure " + + "that only your scripts have access to the asset that you are sending. Keep it private!"; + lightboxPopup.button1text = "CLOSE"; + lightboxPopup.button1method = function() { + lightboxPopup.visible = false; + } + lightboxPopup.visible = true; + } + } + } + + HifiControlsUit.TextField { + id: scriptSecretTextField; + text: generateRandomSecret(); + colorScheme: root.assetCertID === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + // Anchors + anchors.verticalCenter: parent.verticalCenter; + anchors.left: scriptSecretHelp.right; + anchors.leftMargin: 16; + anchors.right: parent.right; + height: 50; + // Style + activeFocusOnPress: true; + activeFocusOnTab: true; + + validator: RegExpValidator { regExp: /^[a-zA-Z0-9]+$/ } + + onAccepted: { + optionalMessage.focus = true; + } + } + } + // "CHANGE" button HifiControlsUit.Button { id: changeButton; @@ -939,7 +1052,7 @@ Item { height: 35; width: 100; text: "CHANGE"; - visible: sendAssetStep.referrer !== "payIn"; + visible: sendAssetStep.referrer !== "payIn" && sendAssetStep.referrer !== "authorizedScript"; onClicked: { if (sendAssetStep.referrer === "connections") { root.nextActiveView = "chooseRecipientConnection"; @@ -1263,6 +1376,8 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); + } else if (sendAssetStep.referrer === "authorizedScript") { + console.log("ZRF HERE: SENDING TO AUTHORIZED SCRIPT"); } } } @@ -1867,6 +1982,17 @@ Item { sendAssetStep.referrer = ""; } + function generateRandomSecret() { + var randomSecret = ""; + var possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + for (var i = 0; i < 10; i++) { + randomSecret += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); + } + + return randomSecret; + } + // // Function Name: fromScript() // @@ -1908,9 +2034,15 @@ Item { sendAssetStep.referrer = "payIn"; sendAssetStep.selectedRecipientNodeID = ""; sendAssetStep.selectedRecipientDisplayName = "Determined by script:"; - sendAssetStep.selectedRecipientUserName = message.username; + sendAssetStep.selectedRecipientUserName = message.username || ""; optionalMessage.text = message.message || "No Message Provided"; + if (sendAssetStep.selectedRecipientUserName === "") { + console.log("SendAsset: Script didn't specify a recipient username!"); + sendAssetHome.visible = false; + return; + } + root.nextActiveView = "sendAssetStep"; break; case 'inspectionCertificate_resetCert': From bc39dbba8b38b80f6023f5e47dd75d4248c6cce6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 29 Nov 2018 12:44:30 -0800 Subject: [PATCH 2/5] Finish out the feature --- .../commerce/common/sendAsset/SendAsset.qml | 297 +++++++++++++++--- .../common/sendAsset/images/clipboard.svg | 1 + interface/src/commerce/Ledger.cpp | 16 + interface/src/commerce/Ledger.h | 4 + interface/src/commerce/QmlCommerce.cpp | 16 + interface/src/commerce/QmlCommerce.h | 2 + 6 files changed, 291 insertions(+), 45 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 2a2369795e..36113077f5 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -36,6 +36,8 @@ Item { property bool isCurrentlySendingAsset: false; property string assetName: ""; property string assetCertID: ""; + property string secret: ""; + property string authorizationID: ""; property string sendingPubliclyEffectImage; property var http; property var listModelName; @@ -108,6 +110,27 @@ Item { } } + onAuthorizeAssetTransferResult: { + if (!root.visible) { + return; + } + + root.isCurrentlySendingAsset = false; + + if (result.status === 'success') { + root.authorizationID = result.data.authorization_id; + authorizationIDText.text = root.authorizationID; + root.secret = result.data.secret; + secretText.text = root.secret + if (scriptSecretTextField.text !== root.secret) { + console.log("SendAsset: Returned secret doesn't match client-generated secret!"); + } + root.nextActiveView = 'paymentSuccess'; + } else { + root.nextActiveView = 'paymentFailure'; + } + } + onCertificateInfoResult: { if (result.status !== 'success') { console.log("Failed to get certificate info", result.data.message); @@ -408,6 +431,7 @@ Item { onClicked: { sendAssetStep.referrer = "authorizedScript"; sendAssetStep.selectedRecipientNodeID = ""; + scriptSecretTextField.text = generateRandomSecret(); root.nextActiveView = "sendAssetStep"; } @@ -1022,7 +1046,6 @@ Item { HifiControlsUit.TextField { id: scriptSecretTextField; - text: generateRandomSecret(); colorScheme: root.assetCertID === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; // Anchors anchors.verticalCenter: parent.verticalCenter; @@ -1034,8 +1057,6 @@ Item { activeFocusOnPress: true; activeFocusOnTab: true; - validator: RegExpValidator { regExp: /^[a-zA-Z0-9]+$/ } - onAccepted: { optionalMessage.focus = true; } @@ -1377,7 +1398,10 @@ Item { parseInt(amountTextField.text), optionalMessage.text); } else if (sendAssetStep.referrer === "authorizedScript") { - console.log("ZRF HERE: SENDING TO AUTHORIZED SCRIPT"); + Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + root.assetCertID, + parseInt(amountTextField.text) || 1, + optionalMessage.text) } } } @@ -1449,18 +1473,24 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 125; anchors.left: parent.left; - anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 125; color: "#FFFFFF"; RalewaySemiBold { id: paymentSentText; - text: root.assetCertID === "" ? "Payment Sent" : (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent"); + text: root.assetCertID === "" ? (sendAssetStep.referrer === "authorizedScript" ? "Payment Authorized" : "Payment Sent") : + (sendAssetStep.referrer === "authorizedScript" ? "Item Transfer Authorized" : + (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent")); // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -1498,6 +1528,8 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); + } else if (sendAssetStep.referrer === "authorizedScript") { + showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; resetSendAssetData(); @@ -1517,38 +1549,176 @@ Item { anchors.leftMargin: 20; anchors.right: parent.right; anchors.rightMargin: 20; - height: 80; + height: childrenRect.height; - RalewaySemiBold { - id: sendToText_paymentSuccess; - text: "Sent To:"; - // Anchors + Item { + id: sendToScriptContainer_paymentSuccess; + visible: sendAssetStep.referrer === "authorizedScript"; anchors.top: parent.top; anchors.left: parent.left; - anchors.bottom: parent.bottom; - width: 90; - // Text size - size: 18; - // Style - color: hifi.colors.baseGray; - verticalAlignment: Text.AlignVCenter; - } - - RecipientDisplay { - anchors.top: parent.top; - anchors.left: sendToText_paymentSuccess.right; anchors.right: parent.right; - height: parent.height; - textColor: hifi.colors.blueAccent; + height: childrenRect.height; - displayName: sendAssetStep.selectedRecipientDisplayName; - userName: sendAssetStep.selectedRecipientUserName; - profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? - sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; + RalewaySemiBold { + id: authorizationIDLabel; + text: "Authorization ID:"; + // Anchors + anchors.left: parent.left; + anchors.top: authorizationIDText.top; + width: paintedWidth; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + + RalewayRegular { + id: authorizationIDText; + text: root.authorizationID; + anchors.top: parent.top; + anchors.left: authorizationIDLabel.right; + anchors.leftMargin: 16; + anchors.right: authorizationIDClipboardButton.left; + anchors.rightMargin: 16; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + horizontalAlignment: Text.AlignHCenter; + verticalAlignment: Text.AlignVCenter; + wrapMode: Text.WrapAnywhere; + } + + Image { + id: authorizationIDClipboardButton; + source: "images/clipboard.svg"; // clipboard by Bieutuong Bon from the Noun Project + fillMode: Image.PreserveAspectFit; + // Anchors + anchors.right: parent.right; + anchors.top: authorizationIDText.top; + height: 40; + width: height; + + MouseArea { + anchors.fill: parent; + onClicked: { + Window.copyToClipboard(root.authorizationID); + authorizationIDText.text = "Copied to Clipboard!\n"; + authorizationIDClipboardTimer.start(); + } + } + } + + Timer { + id: authorizationIDClipboardTimer; + interval: 2000; + repeat: false; + onTriggered: { + authorizationIDText.text = root.authorizationID; + } + } + + RalewaySemiBold { + id: secretLabel; + text: "Secret:"; + // Anchors + anchors.left: parent.left; + anchors.top: secretText.top; + width: authorizationIDLabel.width; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + + RalewayRegular { + id: secretText; + text: root.secret; + anchors.top: authorizationIDText.bottom; + anchors.topMargin: 16; + anchors.left: secretLabel.right; + anchors.leftMargin: 16; + anchors.right: secretClipboardButton.left; + anchors.rightMargin: 16; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + horizontalAlignment: Text.AlignHCenter; + verticalAlignment: Text.AlignVCenter; + wrapMode: Text.WrapAnywhere; + } + + Image { + id: secretClipboardButton; + source: "images/clipboard.svg"; // clipboard by Bieutuong Bon from the Noun Project + fillMode: Image.PreserveAspectFit; + // Anchors + anchors.right: parent.right; + anchors.top: secretText.top; + height: 40; + width: height; + + MouseArea { + anchors.fill: parent; + onClicked: { + Window.copyToClipboard(root.secret); + secretText.text = "Copied to Clipboard!\n"; + secretClipboardTimer.start(); + } + } + } + + Timer { + id: secretClipboardTimer; + interval: 2000; + repeat: false; + onTriggered: { + secretText.text = root.secret; + } + } } - } - + + Item { + id: sendToRecipientContainer_paymentSuccess; + visible: !sendToScriptContainer_paymentSuccess.visible; + anchors.top: parent.top; + anchors.left: parent.left; + anchors.right: parent.right; + height: 80; + + RalewaySemiBold { + id: sendToText_paymentSuccess; + text: "Sent To:"; + // Anchors + anchors.top: parent.top; + anchors.left: parent.left; + anchors.bottom: parent.bottom; + width: 90; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + + RecipientDisplay { + anchors.top: parent.top; + anchors.left: sendToText_paymentSuccess.right; + anchors.right: parent.right; + height: parent.height; + textColor: hifi.colors.blueAccent; + + displayName: sendAssetStep.selectedRecipientDisplayName; + userName: sendAssetStep.selectedRecipientUserName; + profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? + sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; + } + } + } Item { id: giftContainer_paymentSuccess; @@ -1563,7 +1733,8 @@ Item { RalewaySemiBold { id: gift_paymentSuccess; - text: sendAssetStep.referrer === "payIn" ? "Item:" : "Gift:"; + text: sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript" ? + "Item:" : "Gift:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; @@ -1681,6 +1852,8 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); + } else if (sendAssetStep.referrer === "authorizedScript") { + showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; resetSendAssetData(); @@ -1714,13 +1887,17 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 150; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 150; anchors.left: parent.left; - anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 300; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 300; color: "#FFFFFF"; RalewaySemiBold { @@ -1772,8 +1949,9 @@ Item { RalewaySemiBold { id: paymentFailureDetailText; - text: "The recipient you specified was unable to receive your " + - (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift.")); + text: sendAssetStep.referrer === "authorizedScript" ? "The server was unable to handle your request. Please try again later." : + ("The recipient you specified was unable to receive your " + + (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift."))); anchors.top: paymentFailureText.bottom; anchors.topMargin: 20; anchors.left: parent.left; @@ -1791,7 +1969,8 @@ Item { Item { id: sendToContainer_paymentFailure; - visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; + visible: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") && + sendAssetStep.referrer !== "authorizedScript"; anchors.top: paymentFailureDetailText.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1833,7 +2012,8 @@ Item { Item { id: amountContainer_paymentFailure; visible: root.assetCertID === ""; - anchors.top: sendToContainer_paymentFailure.bottom; + anchors.top: sendToContainer_paymentFailure.visible ? + sendToContainer_paymentFailure.bottom : paymentFailureDetailText.bottom; anchors.topMargin: 16; anchors.left: parent.left; anchors.leftMargin: 20; @@ -1954,6 +2134,11 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); + } else if (sendAssetStep.referrer === "authorizedScript") { + Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + root.assetCertID, + parseInt(amountTextField.text) || 1, + optionalMessage.text) } } } @@ -1983,16 +2168,38 @@ Item { } function generateRandomSecret() { + var RANDOM_SECRET_LENGTH = 25; var randomSecret = ""; var possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (var i = 0; i < 10; i++) { + for (var i = 0; i < RANDOM_SECRET_LENGTH; i++) { randomSecret += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); } return randomSecret; } + function showDidYouCopyLightbox() { + lightboxPopup.titleText = "Close Confirmation"; + lightboxPopup.bodyText = "Did you copy your Authorization ID and your Script Secret?\n\n" + + "You won't be able to see your Authorization ID or your Script Secret once " + + "you close this window."; + lightboxPopup.button1text = "GO BACK"; + lightboxPopup.button1method = function() { + lightboxPopup.visible = false; + } + lightboxPopup.button2text = "I'M ALL SET"; + lightboxPopup.button2method = function() { + lightboxPopup.visible = false; + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } + } + lightboxPopup.visible = true; + } + // // Function Name: fromScript() // diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg b/interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg new file mode 100644 index 0000000000..798fdaaab1 --- /dev/null +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg @@ -0,0 +1 @@ +Created by Bieutuong Bonfrom the Noun Project \ No newline at end of file diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index b10c9647a0..fb177ddc82 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -63,6 +63,7 @@ Handler(balance) Handler(inventory) Handler(transferAssetToNode) Handler(transferAssetToUsername) +Handler(authorizeAssetTransfer) Handler(alreadyOwned) Handler(availableUpdates) Handler(updateItem) @@ -428,6 +429,7 @@ void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& user transaction["username"] = username; transaction["quantity"] = amount; transaction["message"] = optionalMessage; + transaction["place_name"] = DependencyManager::get()->getPlaceName(); if (!certificateID.isEmpty()) { transaction["certificate_id"] = certificateID; } @@ -440,6 +442,20 @@ void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& user } } +void Ledger::authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage) { + QJsonObject transaction; + transaction["public_key"] = hfc_key; + transaction["secret"] = secret; + transaction["quantity"] = amount; + transaction["message"] = optionalMessage; + if (!certificateID.isEmpty()) { + transaction["certificate_id"] = certificateID; + } + QJsonDocument transactionDoc{ transaction }; + auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); + signedSend("transaction", transactionString, hfc_key, "authorize", "authorizeAssetTransferSuccess", "authorizeAssetTransferFailure"); +} + void Ledger::alreadyOwned(const QString& marketplaceId) { auto wallet = DependencyManager::get(); QString endpoint = "already_owned"; diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 715d6337ad..700cbe2c4b 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -36,6 +36,7 @@ public: void certificateInfo(const QString& certificateId); void transferAssetToNode(const QString& hfc_key, const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); void transferAssetToUsername(const QString& hfc_key, const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); + void authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); void alreadyOwned(const QString& marketplaceId); void getAvailableUpdates(const QString& itemId = "", const int& pageNumber = 1, const int& itemsPerPage = 10); void updateItem(const QString& hfc_key, const QString& certificate_id); @@ -59,6 +60,7 @@ signals: void certificateInfoResult(QJsonObject result); void transferAssetToNodeResult(QJsonObject result); void transferAssetToUsernameResult(QJsonObject result); + void authorizeAssetTransferResult(QJsonObject result); void alreadyOwnedResult(QJsonObject result); void availableUpdatesResult(QJsonObject result); void updateItemResult(QJsonObject result); @@ -86,6 +88,8 @@ public slots: void transferAssetToNodeFailure(QNetworkReply* reply); void transferAssetToUsernameSuccess(QNetworkReply* reply); void transferAssetToUsernameFailure(QNetworkReply* reply); + void authorizeAssetTransferSuccess(QNetworkReply* reply); + void authorizeAssetTransferFailure(QNetworkReply* reply); void alreadyOwnedSuccess(QNetworkReply* reply); void alreadyOwnedFailure(QNetworkReply* reply); void availableUpdatesSuccess(QNetworkReply* reply); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 566f7ba324..aab053484b 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -38,6 +38,7 @@ QmlCommerce::QmlCommerce() { connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); connect(ledger.data(), &Ledger::transferAssetToNodeResult, this, &QmlCommerce::transferAssetToNodeResult); connect(ledger.data(), &Ledger::transferAssetToUsernameResult, this, &QmlCommerce::transferAssetToUsernameResult); + connect(ledger.data(), &Ledger::authorizeAssetTransferResult, this, &QmlCommerce::authorizeAssetTransferResult); connect(ledger.data(), &Ledger::availableUpdatesResult, this, &QmlCommerce::availableUpdatesResult); connect(ledger.data(), &Ledger::updateItemResult, this, &QmlCommerce::updateItemResult); @@ -246,6 +247,21 @@ void QmlCommerce::transferAssetToUsername(const QString& username, ledger->transferAssetToUsername(key, username, certificateID, amount, optionalMessage); } +void QmlCommerce::authorizeAssetTransfer(const QString& secret, + const QString& certificateID, + const int& amount, + const QString& optionalMessage) { + auto ledger = DependencyManager::get(); + auto wallet = DependencyManager::get(); + QStringList keys = wallet->listPublicKeys(); + if (keys.count() == 0) { + QJsonObject result{ { "status", "fail" }, { "message", "Uninitialized Wallet." } }; + return emit authorizeAssetTransferResult(result); + } + QString key = keys[0]; + ledger->authorizeAssetTransfer(key, secret, certificateID, amount, optionalMessage); +} + void QmlCommerce::replaceContentSet(const QString& itemHref, const QString& certificateID) { if (!certificateID.isEmpty()) { auto ledger = DependencyManager::get(); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index c5fbdaf4a4..e22b540624 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -51,6 +51,7 @@ signals: void transferAssetToNodeResult(QJsonObject result); void transferAssetToUsernameResult(QJsonObject result); + void authorizeAssetTransferResult(QJsonObject result); void contentSetChanged(const QString& contentSetHref); @@ -84,6 +85,7 @@ protected: Q_INVOKABLE void transferAssetToNode(const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void transferAssetToUsername(const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); + Q_INVOKABLE void authorizeAssetTransfer(const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID); From ab184c5c2b7adadeb42c4e8c390e8b6cc5e69797 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 3 Dec 2018 15:16:06 -0800 Subject: [PATCH 3/5] Authorized Script to Coupon --- .../commerce/common/sendAsset/SendAsset.qml | 126 +++++++++--------- .../common/sendAsset/images/coupon.svg | 10 ++ 2 files changed, 73 insertions(+), 63 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 36113077f5..7c2116f77b 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -36,7 +36,7 @@ Item { property bool isCurrentlySendingAsset: false; property string assetName: ""; property string assetCertID: ""; - property string secret: ""; + property string couponID: ""; property string authorizationID: ""; property string sendingPubliclyEffectImage; property var http; @@ -120,9 +120,9 @@ Item { if (result.status === 'success') { root.authorizationID = result.data.authorization_id; authorizationIDText.text = root.authorizationID; - root.secret = result.data.secret; - secretText.text = root.secret - if (scriptSecretTextField.text !== root.secret) { + root.couponID = result.data.secret; + couponIDText.text = root.couponID + if (couponIDTextField.text !== root.couponID) { console.log("SendAsset: Returned secret doesn't match client-generated secret!"); } root.nextActiveView = 'paymentSuccess'; @@ -394,7 +394,7 @@ Item { } Item { - id: authorizedScriptButton; + id: createCouponButton; // Anchors anchors.top: nearbyButton.bottom; anchors.topMargin: 32; @@ -404,7 +404,7 @@ Item { Image { anchors.top: parent.top; - source: "./images/nearby.svg"; + source: "./images/coupon.svg"; height: 70; width: parent.width; fillMode: Image.PreserveAspectFit; @@ -414,7 +414,7 @@ Item { } RalewaySemiBold { - text: "Authorized Script"; + text: "Create Coupon"; // Anchors anchors.bottom: parent.bottom; height: 15; @@ -429,9 +429,9 @@ Item { MouseArea { anchors.fill: parent; onClicked: { - sendAssetStep.referrer = "authorizedScript"; + sendAssetStep.referrer = "createCoupon"; sendAssetStep.selectedRecipientNodeID = ""; - scriptSecretTextField.text = generateRandomSecret(); + couponIDTextField.text = generateRandomCouponID(); root.nextActiveView = "sendAssetStep"; } @@ -928,7 +928,7 @@ Item { id: sendAssetStep; z: 996; - property string referrer; // either "connections", "nearby", "payIn", or "authorizedScript" + property string referrer; // either "connections", "nearby", "payIn", or "createCoupon" property string selectedRecipientNodeID; property string selectedRecipientDisplayName; property string selectedRecipientUserName; @@ -940,7 +940,7 @@ Item { RalewaySemiBold { id: sendAssetText_sendAssetStep; - text: ((sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript") && + text: ((sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "createCoupon") && root.assetCertID !== "") ? "Send \"" + root.assetName + "\":" : (root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"); // Anchors @@ -970,7 +970,7 @@ Item { RalewaySemiBold { id: sendToText_sendAssetStep; - text: sendAssetStep.referrer === "authorizedScript" ? "Script Secret:" : + text: sendAssetStep.referrer === "createCoupon" ? "Coupon ID:" : (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; @@ -985,7 +985,7 @@ Item { } RecipientDisplay { - visible: sendAssetStep.referrer !== "authorizedScript"; + visible: sendAssetStep.referrer !== "createCoupon"; anchors.top: parent.top; anchors.left: sendToText_sendAssetStep.right; anchors.leftMargin: 16; @@ -1002,15 +1002,15 @@ Item { } Item { - id: scriptSecretContainer; - visible: sendAssetStep.referrer === "authorizedScript"; + id: couponIDContainer; + visible: sendAssetStep.referrer === "createCoupon"; anchors.top: parent.top; anchors.left: sendToText_sendAssetStep.right; anchors.right: parent.right; height: parent.height; RalewaySemiBold { - id: scriptSecretHelp; + id: couponIDHelp; text: "[?]"; // Anchors anchors.left: parent.left; @@ -1032,9 +1032,9 @@ Item { parent.color = hifi.colors.blueAccent; } onClicked: { - lightboxPopup.titleText = "Script Secret"; + lightboxPopup.titleText = "Coupon ID"; lightboxPopup.bodyText = "This alphanumeric text string will be used to ensure " + - "that only your scripts have access to the asset that you are sending. Keep it private!"; + "that only you can redeem the coupon for the asset that you are sending. Keep it private!"; lightboxPopup.button1text = "CLOSE"; lightboxPopup.button1method = function() { lightboxPopup.visible = false; @@ -1045,11 +1045,11 @@ Item { } HifiControlsUit.TextField { - id: scriptSecretTextField; + id: couponIDTextField; colorScheme: root.assetCertID === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; // Anchors anchors.verticalCenter: parent.verticalCenter; - anchors.left: scriptSecretHelp.right; + anchors.left: couponIDHelp.right; anchors.leftMargin: 16; anchors.right: parent.right; height: 50; @@ -1073,7 +1073,7 @@ Item { height: 35; width: 100; text: "CHANGE"; - visible: sendAssetStep.referrer !== "payIn" && sendAssetStep.referrer !== "authorizedScript"; + visible: sendAssetStep.referrer !== "payIn" && sendAssetStep.referrer !== "createCoupon"; onClicked: { if (sendAssetStep.referrer === "connections") { root.nextActiveView = "chooseRecipientConnection"; @@ -1397,8 +1397,8 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); - } else if (sendAssetStep.referrer === "authorizedScript") { - Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + } else if (sendAssetStep.referrer === "createCoupon") { + Commerce.authorizeAssetTransfer(couponIDTextField.text || "", root.assetCertID, parseInt(amountTextField.text) || 1, optionalMessage.text) @@ -1474,22 +1474,22 @@ Item { Rectangle { anchors.top: parent.top; anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 125; + sendAssetStep.referrer === "createCoupon" ? 15 : 125; anchors.left: parent.left; anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.right: parent.right; anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.bottom: parent.bottom; anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 125; + sendAssetStep.referrer === "createCoupon" ? 15 : 125; color: "#FFFFFF"; RalewaySemiBold { id: paymentSentText; - text: root.assetCertID === "" ? (sendAssetStep.referrer === "authorizedScript" ? "Payment Authorized" : "Payment Sent") : - (sendAssetStep.referrer === "authorizedScript" ? "Item Transfer Authorized" : + text: root.assetCertID === "" ? (sendAssetStep.referrer === "createCoupon" ? "Payment Authorized" : "Payment Sent") : + (sendAssetStep.referrer === "createCoupon" ? "Item Transfer Authorized" : (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent")); // Anchors anchors.top: parent.top; @@ -1528,7 +1528,7 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); - } else if (sendAssetStep.referrer === "authorizedScript") { + } else if (sendAssetStep.referrer === "createCoupon") { showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; @@ -1553,7 +1553,7 @@ Item { Item { id: sendToScriptContainer_paymentSuccess; - visible: sendAssetStep.referrer === "authorizedScript"; + visible: sendAssetStep.referrer === "createCoupon"; anchors.top: parent.top; anchors.left: parent.left; anchors.right: parent.right; @@ -1620,11 +1620,11 @@ Item { } RalewaySemiBold { - id: secretLabel; - text: "Secret:"; + id: couponIDLabel; + text: "Coupon ID:"; // Anchors anchors.left: parent.left; - anchors.top: secretText.top; + anchors.top: couponIDText.top; width: authorizationIDLabel.width; // Text size size: 18; @@ -1634,13 +1634,13 @@ Item { } RalewayRegular { - id: secretText; - text: root.secret; + id: couponIDText; + text: root.couponID; anchors.top: authorizationIDText.bottom; anchors.topMargin: 16; - anchors.left: secretLabel.right; + anchors.left: couponIDLabel.right; anchors.leftMargin: 16; - anchors.right: secretClipboardButton.left; + anchors.right: couponIDClipboardButton.left; anchors.rightMargin: 16; // Text size size: 18; @@ -1652,31 +1652,31 @@ Item { } Image { - id: secretClipboardButton; + id: couponIDClipboardButton; source: "images/clipboard.svg"; // clipboard by Bieutuong Bon from the Noun Project fillMode: Image.PreserveAspectFit; // Anchors anchors.right: parent.right; - anchors.top: secretText.top; + anchors.top: couponIDText.top; height: 40; width: height; MouseArea { anchors.fill: parent; onClicked: { - Window.copyToClipboard(root.secret); - secretText.text = "Copied to Clipboard!\n"; - secretClipboardTimer.start(); + Window.copyToClipboard(root.couponID); + couponIDText.text = "Copied to Clipboard!\n"; + couponIDClipboardTimer.start(); } } } Timer { - id: secretClipboardTimer; + id: couponIDClipboardTimer; interval: 2000; repeat: false; onTriggered: { - secretText.text = root.secret; + couponIDText.text = root.couponID; } } } @@ -1733,7 +1733,7 @@ Item { RalewaySemiBold { id: gift_paymentSuccess; - text: sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript" ? + text: sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "createCoupon" ? "Item:" : "Gift:"; // Anchors anchors.top: parent.top; @@ -1852,7 +1852,7 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); - } else if (sendAssetStep.referrer === "authorizedScript") { + } else if (sendAssetStep.referrer === "createCoupon") { showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; @@ -1888,16 +1888,16 @@ Item { Rectangle { anchors.top: parent.top; anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 150; + sendAssetStep.referrer === "createCoupon" ? 15 : 150; anchors.left: parent.left; anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.right: parent.right; anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.bottom: parent.bottom; anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 300; + sendAssetStep.referrer === "createCoupon" ? 15 : 300; color: "#FFFFFF"; RalewaySemiBold { @@ -1949,7 +1949,7 @@ Item { RalewaySemiBold { id: paymentFailureDetailText; - text: sendAssetStep.referrer === "authorizedScript" ? "The server was unable to handle your request. Please try again later." : + text: sendAssetStep.referrer === "createCoupon" ? "The server was unable to handle your request. Please try again later." : ("The recipient you specified was unable to receive your " + (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift."))); anchors.top: paymentFailureText.bottom; @@ -1970,7 +1970,7 @@ Item { Item { id: sendToContainer_paymentFailure; visible: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") && - sendAssetStep.referrer !== "authorizedScript"; + sendAssetStep.referrer !== "createCoupon"; anchors.top: paymentFailureDetailText.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -2134,8 +2134,8 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); - } else if (sendAssetStep.referrer === "authorizedScript") { - Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + } else if (sendAssetStep.referrer === "createCoupon") { + Commerce.authorizeAssetTransfer(couponIDTextField.text || "", root.assetCertID, parseInt(amountTextField.text) || 1, optionalMessage.text) @@ -2167,22 +2167,22 @@ Item { sendAssetStep.referrer = ""; } - function generateRandomSecret() { - var RANDOM_SECRET_LENGTH = 25; - var randomSecret = ""; + function generateRandomCouponID() { + var RANDOM_COUPON_ID_LENGTH = 25; + var randomCouponID = ""; var possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (var i = 0; i < RANDOM_SECRET_LENGTH; i++) { - randomSecret += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); + for (var i = 0; i < RANDOM_COUPON_ID_LENGTH; i++) { + randomCouponID += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); } - return randomSecret; + return randomCouponID; } function showDidYouCopyLightbox() { lightboxPopup.titleText = "Close Confirmation"; - lightboxPopup.bodyText = "Did you copy your Authorization ID and your Script Secret?\n\n" + - "You won't be able to see your Authorization ID or your Script Secret once " + + lightboxPopup.bodyText = "Did you copy your Authorization ID and your Coupon ID?\n\n" + + "You won't be able to see your Authorization ID or your Coupon ID once " + "you close this window."; lightboxPopup.button1text = "GO BACK"; lightboxPopup.button1method = function() { diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg b/interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg new file mode 100644 index 0000000000..2b7c052589 --- /dev/null +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + From 02307d2308f56f21754d7a121d635d4062d7b6cb Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 5 Dec 2018 16:34:53 -0800 Subject: [PATCH 4/5] Secret to Coupon ID --- .../qml/hifi/commerce/common/sendAsset/SendAsset.qml | 4 ++-- interface/src/commerce/Ledger.cpp | 4 ++-- interface/src/commerce/Ledger.h | 2 +- interface/src/commerce/QmlCommerce.cpp | 4 ++-- interface/src/commerce/QmlCommerce.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 7c2116f77b..3125ad1ee6 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -120,10 +120,10 @@ Item { if (result.status === 'success') { root.authorizationID = result.data.authorization_id; authorizationIDText.text = root.authorizationID; - root.couponID = result.data.secret; + root.couponID = result.data.coupon_id; couponIDText.text = root.couponID if (couponIDTextField.text !== root.couponID) { - console.log("SendAsset: Returned secret doesn't match client-generated secret!"); + console.log("SendAsset: Returned coupon ID doesn't match client-generated coupon ID!"); } root.nextActiveView = 'paymentSuccess'; } else { diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index fb177ddc82..8bb01f6389 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -442,10 +442,10 @@ void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& user } } -void Ledger::authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage) { +void Ledger::authorizeAssetTransfer(const QString& hfc_key, const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage) { QJsonObject transaction; transaction["public_key"] = hfc_key; - transaction["secret"] = secret; + transaction["coupon_id"] = couponID; transaction["quantity"] = amount; transaction["message"] = optionalMessage; if (!certificateID.isEmpty()) { diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 700cbe2c4b..2e18f34c8d 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -36,7 +36,7 @@ public: void certificateInfo(const QString& certificateId); void transferAssetToNode(const QString& hfc_key, const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); void transferAssetToUsername(const QString& hfc_key, const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); - void authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); + void authorizeAssetTransfer(const QString& hfc_key, const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage); void alreadyOwned(const QString& marketplaceId); void getAvailableUpdates(const QString& itemId = "", const int& pageNumber = 1, const int& itemsPerPage = 10); void updateItem(const QString& hfc_key, const QString& certificate_id); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index aab053484b..00acd40e70 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -247,7 +247,7 @@ void QmlCommerce::transferAssetToUsername(const QString& username, ledger->transferAssetToUsername(key, username, certificateID, amount, optionalMessage); } -void QmlCommerce::authorizeAssetTransfer(const QString& secret, +void QmlCommerce::authorizeAssetTransfer(const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage) { @@ -259,7 +259,7 @@ void QmlCommerce::authorizeAssetTransfer(const QString& secret, return emit authorizeAssetTransferResult(result); } QString key = keys[0]; - ledger->authorizeAssetTransfer(key, secret, certificateID, amount, optionalMessage); + ledger->authorizeAssetTransfer(key, couponID, certificateID, amount, optionalMessage); } void QmlCommerce::replaceContentSet(const QString& itemHref, const QString& certificateID) { diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index e22b540624..ad21899ebf 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -85,7 +85,7 @@ protected: Q_INVOKABLE void transferAssetToNode(const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void transferAssetToUsername(const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); - Q_INVOKABLE void authorizeAssetTransfer(const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); + Q_INVOKABLE void authorizeAssetTransfer(const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID); From a2af50a9d0b7a82c7c993d1801b2c5ee0d797afe Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 6 Dec 2018 11:07:26 -0800 Subject: [PATCH 5/5] Show pre-auth'd transactions in Recent Activity before redemption --- .../qml/hifi/commerce/wallet/WalletHome.qml | 8 ++++++-- interface/src/commerce/Ledger.cpp | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 4c8e1e6ca5..cf293a06df 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -270,9 +270,11 @@ Item { model: transactionHistoryModel; delegate: Item { width: parent.width; - height: (model.transaction_type === "pendingCount" && model.count !== 0) ? 40 : ((model.status === "confirmed" || model.status === "invalidated") ? transactionText.height + 30 : 0); + height: (model.transaction_type === "pendingCount" && model.count !== 0) ? 40 : + (transactionContainer.visible ? transactionText.height + 30 : 0); Item { + id: pendingCountContainer; visible: model.transaction_type === "pendingCount" && model.count !== 0; anchors.top: parent.top; anchors.left: parent.left; @@ -291,7 +293,9 @@ Item { } Item { - visible: model.transaction_type !== "pendingCount" && (model.status === "confirmed" || model.status === "invalidated"); + id: transactionContainer; + visible: model.transaction_type !== "pendingCount" && + (model.status === "confirmed" || model.status === "invalidated"); anchors.top: parent.top; anchors.left: parent.left; width: parent.width; diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 8bb01f6389..d72d896638 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -204,6 +204,7 @@ QString transactionString(const QJsonObject& valueObject) { int sentMoney = valueObject["sent_money"].toInt(); int receivedMoney = valueObject["received_money"].toInt(); int dateInteger = valueObject["created_at"].toInt(); + QString transactionType = valueObject["transaction_type"].toString(); QString message = valueObject["message"].toString(); QDateTime createdAt(QDateTime::fromSecsSinceEpoch(dateInteger, Qt::UTC)); QString result; @@ -211,8 +212,12 @@ QString transactionString(const QJsonObject& valueObject) { if (sentCerts <= 0 && receivedCerts <= 0 && !KNOWN_USERS.contains(valueObject["sender_name"].toString())) { // this is an hfc transfer. if (sentMoney > 0) { - QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); - result += QString("Money sent to %1").arg(recipient); + if (transactionType == "escrow") { + result += QString("Money transferred to coupon"); + } else { + QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); + result += QString("Money sent to %1").arg(recipient); + } } else { QString sender = userLink(valueObject["sender_name"].toString(), valueObject["place_name"].toString()); result += QString("Money from %1").arg(sender); @@ -227,8 +232,12 @@ QString transactionString(const QJsonObject& valueObject) { ) { // this is a non-HFC asset transfer. if (sentCerts > 0) { - QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); - result += QString("Gift sent to %1").arg(recipient); + if (transactionType == "escrow") { + result += QString("Item transferred to coupon"); + } else { + QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); + result += QString("Gift sent to %1").arg(recipient); + } } else { QString sender = userLink(valueObject["sender_name"].toString(), valueObject["place_name"].toString()); result += QString("Gift from %1").arg(sender);