diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml
index 2d0bb2d87b..3125ad1ee6 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 couponID: "";
+ 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.couponID = result.data.coupon_id;
+ couponIDText.text = root.couponID
+ if (couponIDTextField.text !== root.couponID) {
+ console.log("SendAsset: Returned coupon ID doesn't match client-generated coupon ID!");
+ }
+ root.nextActiveView = 'paymentSuccess';
+ } else {
+ root.nextActiveView = 'paymentFailure';
+ }
+ }
+
onCertificateInfoResult: {
if (result.status !== 'success') {
console.log("Failed to get certificate info", result.data.message);
@@ -269,7 +292,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 +393,51 @@ Item {
}
}
+ Item {
+ id: createCouponButton;
+ // 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/coupon.svg";
+ height: 70;
+ width: parent.width;
+ fillMode: Image.PreserveAspectFit;
+ horizontalAlignment: Image.AlignHCenter;
+ verticalAlignment: Image.AlignTop;
+ mipmap: true;
+ }
+
+ RalewaySemiBold {
+ text: "Create Coupon";
+ // 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 = "createCoupon";
+ sendAssetStep.selectedRecipientNodeID = "";
+ couponIDTextField.text = generateRandomCouponID();
+
+ root.nextActiveView = "sendAssetStep";
+ }
+ }
+ }
+
HifiControlsUit.Button {
id: backButton_sendAssetHome;
visible: parentAppNavBarHeight === 0;
@@ -860,7 +928,7 @@ Item {
id: sendAssetStep;
z: 996;
- property string referrer; // either "connections", "nearby", or "payIn"
+ property string referrer; // either "connections", "nearby", "payIn", or "createCoupon"
property string selectedRecipientNodeID;
property string selectedRecipientDisplayName;
property string selectedRecipientUserName;
@@ -872,7 +940,8 @@ Item {
RalewaySemiBold {
id: sendAssetText_sendAssetStep;
- text: sendAssetStep.referrer === "payIn" && root.assetCertID !== "" ? "Send \"" + root.assetName + "\":" :
+ text: ((sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "createCoupon") &&
+ root.assetCertID !== "") ? "Send \"" + root.assetName + "\":" :
(root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:");
// Anchors
anchors.top: parent.top;
@@ -901,12 +970,13 @@ Item {
RalewaySemiBold {
id: sendToText_sendAssetStep;
- text: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:";
+ text: sendAssetStep.referrer === "createCoupon" ? "Coupon ID:" :
+ (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 +985,10 @@ Item {
}
RecipientDisplay {
+ visible: sendAssetStep.referrer !== "createCoupon";
anchors.top: parent.top;
anchors.left: sendToText_sendAssetStep.right;
+ anchors.leftMargin: 16;
anchors.right: changeButton.left;
anchors.rightMargin: 12;
height: parent.height;
@@ -929,6 +1001,68 @@ Item {
multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn";
}
+ Item {
+ id: couponIDContainer;
+ visible: sendAssetStep.referrer === "createCoupon";
+ anchors.top: parent.top;
+ anchors.left: sendToText_sendAssetStep.right;
+ anchors.right: parent.right;
+ height: parent.height;
+
+ RalewaySemiBold {
+ id: couponIDHelp;
+ 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 = "Coupon ID";
+ lightboxPopup.bodyText = "This alphanumeric text string will be used to ensure " +
+ "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;
+ }
+ lightboxPopup.visible = true;
+ }
+ }
+ }
+
+ HifiControlsUit.TextField {
+ id: couponIDTextField;
+ colorScheme: root.assetCertID === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light;
+ // Anchors
+ anchors.verticalCenter: parent.verticalCenter;
+ anchors.left: couponIDHelp.right;
+ anchors.leftMargin: 16;
+ anchors.right: parent.right;
+ height: 50;
+ // Style
+ activeFocusOnPress: true;
+ activeFocusOnTab: true;
+
+ onAccepted: {
+ optionalMessage.focus = true;
+ }
+ }
+ }
+
// "CHANGE" button
HifiControlsUit.Button {
id: changeButton;
@@ -939,7 +1073,7 @@ Item {
height: 35;
width: 100;
text: "CHANGE";
- visible: sendAssetStep.referrer !== "payIn";
+ visible: sendAssetStep.referrer !== "payIn" && sendAssetStep.referrer !== "createCoupon";
onClicked: {
if (sendAssetStep.referrer === "connections") {
root.nextActiveView = "chooseRecipientConnection";
@@ -1263,6 +1397,11 @@ Item {
root.assetCertID,
parseInt(amountTextField.text),
optionalMessage.text);
+ } else if (sendAssetStep.referrer === "createCoupon") {
+ Commerce.authorizeAssetTransfer(couponIDTextField.text || "",
+ root.assetCertID,
+ parseInt(amountTextField.text) || 1,
+ optionalMessage.text)
}
}
}
@@ -1334,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 === "createCoupon" ? 15 : 125;
anchors.left: parent.left;
- anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50;
+ anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ||
+ sendAssetStep.referrer === "createCoupon" ? 15 : 50;
anchors.right: parent.right;
- anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50;
+ anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ||
+ sendAssetStep.referrer === "createCoupon" ? 15 : 50;
anchors.bottom: parent.bottom;
- anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125;
+ anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ||
+ sendAssetStep.referrer === "createCoupon" ? 15 : 125;
color: "#FFFFFF";
RalewaySemiBold {
id: paymentSentText;
- text: root.assetCertID === "" ? "Payment Sent" : (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent");
+ 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;
anchors.topMargin: 26;
@@ -1383,6 +1528,8 @@ Item {
onClicked: {
if (sendAssetStep.referrer === "payIn") {
sendToScript({method: "closeSendAsset"});
+ } else if (sendAssetStep.referrer === "createCoupon") {
+ showDidYouCopyLightbox();
} else {
root.nextActiveView = "sendAssetHome";
resetSendAssetData();
@@ -1402,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 === "createCoupon";
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: couponIDLabel;
+ text: "Coupon ID:";
+ // Anchors
+ anchors.left: parent.left;
+ anchors.top: couponIDText.top;
+ width: authorizationIDLabel.width;
+ // Text size
+ size: 18;
+ // Style
+ color: hifi.colors.baseGray;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+ RalewayRegular {
+ id: couponIDText;
+ text: root.couponID;
+ anchors.top: authorizationIDText.bottom;
+ anchors.topMargin: 16;
+ anchors.left: couponIDLabel.right;
+ anchors.leftMargin: 16;
+ anchors.right: couponIDClipboardButton.left;
+ anchors.rightMargin: 16;
+ // Text size
+ size: 18;
+ // Style
+ color: hifi.colors.baseGray;
+ horizontalAlignment: Text.AlignHCenter;
+ verticalAlignment: Text.AlignVCenter;
+ wrapMode: Text.WrapAnywhere;
+ }
+
+ Image {
+ id: couponIDClipboardButton;
+ source: "images/clipboard.svg"; // clipboard by Bieutuong Bon from the Noun Project
+ fillMode: Image.PreserveAspectFit;
+ // Anchors
+ anchors.right: parent.right;
+ anchors.top: couponIDText.top;
+ height: 40;
+ width: height;
+
+ MouseArea {
+ anchors.fill: parent;
+ onClicked: {
+ Window.copyToClipboard(root.couponID);
+ couponIDText.text = "Copied to Clipboard!\n";
+ couponIDClipboardTimer.start();
+ }
+ }
+ }
+
+ Timer {
+ id: couponIDClipboardTimer;
+ interval: 2000;
+ repeat: false;
+ onTriggered: {
+ couponIDText.text = root.couponID;
+ }
+ }
}
- }
-
+
+ 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;
@@ -1448,7 +1733,8 @@ Item {
RalewaySemiBold {
id: gift_paymentSuccess;
- text: sendAssetStep.referrer === "payIn" ? "Item:" : "Gift:";
+ text: sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "createCoupon" ?
+ "Item:" : "Gift:";
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
@@ -1566,6 +1852,8 @@ Item {
onClicked: {
if (sendAssetStep.referrer === "payIn") {
sendToScript({method: "closeSendAsset"});
+ } else if (sendAssetStep.referrer === "createCoupon") {
+ showDidYouCopyLightbox();
} else {
root.nextActiveView = "sendAssetHome";
resetSendAssetData();
@@ -1599,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 === "createCoupon" ? 15 : 150;
anchors.left: parent.left;
- anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50;
+ anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ||
+ sendAssetStep.referrer === "createCoupon" ? 15 : 50;
anchors.right: parent.right;
- anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50;
+ anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ||
+ sendAssetStep.referrer === "createCoupon" ? 15 : 50;
anchors.bottom: parent.bottom;
- anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 300;
+ anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ||
+ sendAssetStep.referrer === "createCoupon" ? 15 : 300;
color: "#FFFFFF";
RalewaySemiBold {
@@ -1657,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 === "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;
anchors.topMargin: 20;
anchors.left: parent.left;
@@ -1676,7 +1969,8 @@ Item {
Item {
id: sendToContainer_paymentFailure;
- visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn";
+ visible: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") &&
+ sendAssetStep.referrer !== "createCoupon";
anchors.top: paymentFailureDetailText.bottom;
anchors.topMargin: 8;
anchors.left: parent.left;
@@ -1718,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;
@@ -1839,6 +2134,11 @@ Item {
root.assetCertID,
parseInt(amountTextField.text),
optionalMessage.text);
+ } else if (sendAssetStep.referrer === "createCoupon") {
+ Commerce.authorizeAssetTransfer(couponIDTextField.text || "",
+ root.assetCertID,
+ parseInt(amountTextField.text) || 1,
+ optionalMessage.text)
}
}
}
@@ -1867,6 +2167,39 @@ Item {
sendAssetStep.referrer = "";
}
+ function generateRandomCouponID() {
+ var RANDOM_COUPON_ID_LENGTH = 25;
+ var randomCouponID = "";
+ var possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+ for (var i = 0; i < RANDOM_COUPON_ID_LENGTH; i++) {
+ randomCouponID += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length));
+ }
+
+ return randomCouponID;
+ }
+
+ function showDidYouCopyLightbox() {
+ lightboxPopup.titleText = "Close Confirmation";
+ 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() {
+ 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()
//
@@ -1908,9 +2241,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':
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 @@
+
\ No newline at end of file
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 @@
+
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 b10c9647a0..d72d896638 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)
@@ -203,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;
@@ -210,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);
@@ -226,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);
@@ -428,6 +438,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 +451,20 @@ void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& user
}
}
+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["coupon_id"] = couponID;
+ 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..2e18f34c8d 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& 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);
@@ -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..00acd40e70 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& couponID,
+ 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, couponID, 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..ad21899ebf 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& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage);
Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID);