Finish out the feature

This commit is contained in:
Zach Fox 2018-11-29 12:44:30 -08:00
parent 371c50b2ab
commit bc39dbba8b
6 changed files with 291 additions and 45 deletions

View file

@ -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()
//

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 44 55" enable-background="new 0 0 44 44" xml:space="preserve"><path d="M30.201,10.811h-1.599v-0.076c0-0.754-0.612-1.367-1.366-1.367h-2.063c0.005-0.074,0.023-0.146,0.023-0.225 c0-1.766-1.432-3.197-3.197-3.197s-3.197,1.432-3.197,3.197c0,0.078,0.018,0.15,0.023,0.225h-2.063 c-0.754,0-1.366,0.613-1.366,1.367v0.076h-1.599c-1.38,0-2.502,1.123-2.502,2.502v22.24c0,1.379,1.122,2.502,2.502,2.502h16.402 c1.38,0,2.502-1.123,2.502-2.502v-22.24C32.703,11.934,31.581,10.811,30.201,10.811z M22,7.893c0.691,0,1.251,0.559,1.251,1.25 s-0.56,1.252-1.251,1.252s-1.251-0.561-1.251-1.252S21.309,7.893,22,7.893z M31.035,35.553c0,0.459-0.374,0.834-0.834,0.834H13.799 c-0.46,0-0.834-0.375-0.834-0.834v-22.24c0-0.459,0.374-0.834,0.834-0.834h1.599v1.443h13.205v-1.443h1.599 c0.46,0,0.834,0.375,0.834,0.834V35.553z"/><rect x="15.397" y="16.648" width="13.205" height="0.975"/><rect x="15.397" y="20.402" width="13.205" height="0.973"/><rect x="15.397" y="24.154" width="13.205" height="0.975"/><rect x="15.397" y="27.908" width="13.205" height="0.973"/><rect x="15.397" y="31.66" width="13.205" height="0.975"/><text x="0" y="59" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by Bieutuong Bon</text><text x="0" y="64" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project</text></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -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<AddressManager>()->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<Wallet>();
QString endpoint = "already_owned";

View file

@ -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);

View file

@ -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<Ledger>();
auto wallet = DependencyManager::get<Wallet>();
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<Ledger>();

View file

@ -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);