Merge pull request #11149 from howard-stearns/buy

Buy
This commit is contained in:
Howard Stearns 2017-08-09 13:24:25 -07:00 committed by GitHub
commit 860934cd59
11 changed files with 252 additions and 1 deletions

View file

@ -27,6 +27,9 @@ Rectangle {
property string itemId;
// Style
color: hifi.colors.baseGray;
Hifi.QmlCommerce {
id: commerce;
}
//
// TITLE BAR START
@ -259,7 +262,7 @@ Rectangle {
width: parent.width/2 - anchors.rightMargin*2;
text: "Buy"
onClicked: {
sendToScript({method: 'checkout_buyClicked', params: itemId});
sendToScript({method: 'checkout_buyClicked', params: {success: commerce.buy(itemId, parseInt(itemPriceText.text))}});
}
}
}

View file

@ -193,6 +193,9 @@
#include <src/scripting/LimitlessVoiceRecognitionScriptingInterface.h>
#include <EntityScriptClient.h>
#include <ModelScriptingInterface.h>
#include "commerce/Ledger.h"
#include "commerce/Wallet.h"
#include "commerce/QmlCommerce.h"
// On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
// FIXME seems to be broken.
@ -598,6 +601,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<CloseEventSender>();
DependencyManager::set<ResourceManager>();
DependencyManager::set<ContextOverlayInterface>();
DependencyManager::set<Ledger>();
DependencyManager::set<Wallet>();
return previousSessionCrashed;
}
@ -2057,6 +2062,7 @@ void Application::initializeUi() {
LoginDialog::registerType();
Tooltip::registerType();
UpdateDialog::registerType();
QmlCommerce::registerType();
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");

View file

@ -0,0 +1,14 @@
//
// CommerceLogging.cpp
// interface/src/commerce
//
// Created by Howard Stearns on 8/9/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "CommerceLogging.h"
Q_LOGGING_CATEGORY(commerce, "hifi.commerce")

View file

@ -0,0 +1,19 @@
//
// CommerceLogging.h
// interface/src/commerce
//
// Created by Howard Stearns on 8/9/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_CommerceLogging_h
#define hifi_CommerceLogging_h
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(commerce)
#endif // hifi_CommerceLogging_h

View file

@ -0,0 +1,48 @@
//
// Ledger.cpp
// interface/src/commerce
//
// Created by Howard Stearns on 8/4/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QJsonObject>
#include <QJsonDocument>
#include "AccountManager.h"
#include "Wallet.h"
#include "Ledger.h"
#include "CommerceLogging.h"
bool Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const QString& buyerUsername) {
QJsonObject transaction;
transaction["hfc_key"] = hfc_key;
transaction["hfc"] = cost;
transaction["asset_id"] = asset_id;
transaction["inventory_key"] = inventory_key;
transaction["inventory_buyer_username"] = buyerUsername;
QJsonDocument transactionDoc{ transaction };
QString transactionString = transactionDoc.toJson(QJsonDocument::Compact);
auto wallet = DependencyManager::get<Wallet>();
QString signature = wallet->signWithKey(transactionString, hfc_key);
QJsonObject request;
request["transaction"] = transactionString;
request["signature"] = signature;
qCInfo(commerce) << "Transaction:" << QJsonDocument(request).toJson(QJsonDocument::Compact);
return true; // FIXME send to server.
}
bool Ledger::receiveAt(const QString& hfc_key) {
auto accountManager = DependencyManager::get<AccountManager>();
if (!accountManager->isLoggedIn()) {
qCWarning(commerce) << "Cannot set receiveAt when not logged in.";
return false;
}
auto username = accountManager->getAccountInfo().getUsername();
qCInfo(commerce) << "Setting default receiving key for" << username;
return true; // FIXME send to server.
}

View file

@ -0,0 +1,28 @@
//
// Ledger.h
// interface/src/commerce
//
// Bottlenecks all interaction with the blockchain or other ledger system.
//
// Created by Howard Stearns on 8/4/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Ledger_h
#define hifi_Ledger_h
#include <DependencyManager.h>
class Ledger : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
bool buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const QString& buyerUsername = "");
bool receiveAt(const QString& hfc_key);
};
#endif // hifi_Ledger_h

View file

@ -0,0 +1,30 @@
//
// Commerce.cpp
// interface/src/commerce
//
// Created by Howard Stearns on 8/4/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "QmlCommerce.h"
#include "Application.h"
#include "DependencyManager.h"
#include "Ledger.h"
#include "Wallet.h"
HIFI_QML_DEF(QmlCommerce)
bool QmlCommerce::buy(const QString& assetId, int cost, const QString& buyerUsername) {
auto ledger = DependencyManager::get<Ledger>();
auto wallet = DependencyManager::get<Wallet>();
QStringList keys = wallet->listPublicKeys();
if (keys.count() == 0) {
return false;
}
QString key = keys[0];
// For now, we receive at the same key that pays for it.
return ledger->buy(key, cost, assetId, key, buyerUsername);
}

View file

@ -0,0 +1,28 @@
//
// Commerce.h
// interface/src/commerce
//
// Guard for safe use of Commerce (Wallet, Ledger) by authorized QML.
//
// Created by Howard Stearns on 8/4/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_QmlCommerce_h
#define hifi_QmlCommerce_h
#include <OffscreenQmlDialog.h>
class QmlCommerce : public OffscreenQmlDialog {
Q_OBJECT
HIFI_QML_DECL
protected:
Q_INVOKABLE bool buy(const QString& assetId, int cost, const QString& buyerUsername = "");
};
#endif // hifi_QmlCommerce_h

View file

@ -0,0 +1,41 @@
//
// Wallet.cpp
// interface/src/commerce
//
// Created by Howard Stearns on 8/4/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <quuid.h>
#include "CommerceLogging.h"
#include "Ledger.h"
#include "Wallet.h"
bool Wallet::createIfNeeded() {
// FIXME: persist in file between sessions.
if (_publicKeys.count() > 0) return false;
qCInfo(commerce) << "Creating wallet.";
return generateKeyPair();
}
bool Wallet::generateKeyPair() {
// FIXME: need private key, too, and persist in file.
qCInfo(commerce) << "Generating keypair.";
QString key = QUuid::createUuid().toString();
_publicKeys.push_back(key);
auto ledger = DependencyManager::get<Ledger>();
return ledger->receiveAt(key);
}
QStringList Wallet::listPublicKeys() {
qCInfo(commerce) << "Enumerating public keys.";
createIfNeeded();
return _publicKeys;
}
QString Wallet::signWithKey(const QString& text, const QString& key) {
qCInfo(commerce) << "Signing text.";
return "fixme signed";
}

View file

@ -0,0 +1,33 @@
//
// Wallet.h
// interface/src/commerce
//
// API for secure keypair management
//
// Created by Howard Stearns on 8/4/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Wallet_h
#define hifi_Wallet_h
#include <DependencyManager.h>
class Wallet : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
bool createIfNeeded();
bool generateKeyPair();
QStringList listPublicKeys();
QString signWithKey(const QString& text, const QString& key);
private:
QStringList _publicKeys{};
};
#endif // hifi_Wallet_h

View file

@ -197,6 +197,7 @@
//tablet.popFromStack();
break;
case 'checkout_buyClicked':
print("fromQml: " + JSON.stringify(message));
//tablet.popFromStack();
break;
default: