Skip to content

Commit

Permalink
Added ability to retrieve transaction history
Browse files Browse the repository at this point in the history
  • Loading branch information
tmancey committed Feb 25, 2019
1 parent 9a2126d commit 211e767
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 4 deletions.
1 change: 1 addition & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ source_set("bat-native-confirmations") {
deps = [
"//base",
"//third_party/boringssl",
"//third_party/re2",
rebase_path("bat-native-ledger:headers", dep_base),
rebase_path("bat-native-tweetnacl:tweetnacl", dep_base),
rebase_path("challenge_bypass_ristretto_ffi", dep_base),
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ void SetCatalogIssuers(
std::unique_ptr<IssuersInfo> info)
```

`GetTransactionHistory` should be called to get transaction history
```
void GetTransactionHistory(
const uint64_t from_timestamp_in_seconds,
const uint64_t to_timestamp_in_seconds,
OnGetTransactionHistoryCallback callback)
```

`AdSustained` should be called by Ads to be rewarded for viewing an Ad
```
void AdSustained(
Expand All @@ -36,7 +44,7 @@ void OnTimer(

### Client

`SetConfirmationsIsReady` should notify Brave Ads if Confirmations is ready
`SetConfirmationsIsReady` should notify Ads if Confirmations is ready
```
void SetConfirmationsIsReady(
const bool is_ready)
Expand Down
19 changes: 17 additions & 2 deletions include/bat/confirmations/confirmations.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
#ifndef BAT_CONFIRMATIONS_CONFIRMATIONS_H_
#define BAT_CONFIRMATIONS_CONFIRMATIONS_H_

#include <vector>
#include <memory>

#include "bat/confirmations/confirmations_client.h"
#include "bat/confirmations/export.h"
#include "bat/confirmations/notification_info.h"
#include "bat/confirmations/issuers_info.h"
#include "bat/confirmations/wallet_info.h"
#include "bat/ledger/ledger.h"
#include "bat/ledger/transactions_info.h"

namespace confirmations {

Expand All @@ -21,6 +24,12 @@ extern bool _is_production;

extern const char _confirmations_name[];

using TransactionInfo = ::ledger::TransactionInfo;
using TransactionsInfo = ::ledger::TransactionsInfo;

using OnGetTransactionHistoryCallback =
::ledger::AdsNotificationsHistoryCallback;

class CONFIRMATIONS_EXPORT Confirmations {
public:
Confirmations() = default;
Expand All @@ -32,10 +41,16 @@ class CONFIRMATIONS_EXPORT Confirmations {
// Should be called to set wallet information for payments
virtual void SetWalletInfo(std::unique_ptr<WalletInfo> info) = 0;

// Should be called when a new catalog has been downloaded in Brave Ads
// Should be called when a new catalog has been downloaded in Ads
virtual void SetCatalogIssuers(std::unique_ptr<IssuersInfo> info) = 0;

// Should be called when an ad is sustained in Brave Ads
// Should be called to get transaction history
virtual void GetTransactionHistory(
const uint64_t from_timestamp_in_seconds,
const uint64_t to_timestamp_in_seconds,
OnGetTransactionHistoryCallback callback) = 0;

// Should be called when an ad is sustained in Ads
virtual void AdSustained(std::unique_ptr<NotificationInfo> info) = 0;

// Should be called when a timer is triggered
Expand Down
94 changes: 94 additions & 0 deletions src/bat/confirmations/transactions_info.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* Copyright (c) 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "bat/ledger/transactions_info.h"

#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/values.h"

namespace confirmations {

TransactionsInfo::TransactionsInfo() :
transactions({}) {}

TransactionsInfo::TransactionsInfo(const TransactionsInfo& info) :
transactions(info.transactions) {}

TransactionsInfo::~TransactionsInfo() = default;

const std::string TransactionsInfo::ToJson() const {
base::Value dictionary(base::Value::Type::DICTIONARY);

base::Value list(base::Value::Type::LIST);
for (const auto& transaction : transactions) {
base::Value transaction_dictionary(base::Value::Type::DICTIONARY);

transaction_dictionary.SetKey("timestamp_in_seconds",
base::Value(std::to_string(transaction.timestamp_in_seconds)));

transaction_dictionary.SetKey("estimated_redemption_value",
base::Value(transaction.estimated_redemption_value));

list.GetList().push_back(std::move(transaction_dictionary));
}

dictionary.SetKey("transactions", base::Value(std::move(list)));

// Write to JSON
std::string json;
base::JSONWriter::Write(dictionary, &json);

return json;
}

bool TransactionsInfo::FromJson(
const std::string& json) {
std::unique_ptr<base::DictionaryValue> dictionary =
base::DictionaryValue::From(base::JSONReader::Read(json));

auto* transactions_value = dictionary->FindKey("transactions");
if (!transactions_value) {
return false;
}

std::vector<TransactionInfo> new_transactions;

base::ListValue transactions_list_value(transactions_value->GetList());
for (auto& transaction_value : transactions_list_value) {
base::DictionaryValue* transaction_dictionary;
if (!transaction_value.GetAsDictionary(&transaction_dictionary)) {
return false;
}

TransactionInfo info;

// Timestamp
auto* timestamp_in_seconds_value =
transaction_dictionary->FindKey("timestamp_in_seconds");
if (!timestamp_in_seconds_value) {
return false;
}
info.timestamp_in_seconds =
std::stoull(timestamp_in_seconds_value->GetString());

// Estimated redemption value
auto* estimated_redemption_value_value =
transaction_dictionary->FindKey("estimated_redemption_value");
if (!estimated_redemption_value_value) {
return false;
}
info.estimated_redemption_value =
estimated_redemption_value_value->GetDouble();

new_transactions.push_back(info);
}

transactions = new_transactions;

return true;
}

} // namespace confirmations
147 changes: 147 additions & 0 deletions src/confirmations_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <time>
#include <utility>

#include "confirmations_impl.h"
Expand All @@ -16,6 +17,8 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"

#include "third_party/re2/src/re2/re2.h"

using std::placeholders::_1;
using std::placeholders::_2;

Expand Down Expand Up @@ -76,6 +79,12 @@ std::string ConfirmationsImpl::ToJSON() const {
GetCatalogIssuersAsDictionary(public_key_, catalog_issuers_);
dictionary.SetKey("catalog_issuers", base::Value(std::move(catalog_issuers)));

// Transaction history
auto transaction_history =
GetTransactionHistoryAsDictionary(transaction_history_);
dictionary.SetKey("transaction_history", base::Value(
std::move(transaction_history)));

// Unblinded tokens
auto unblinded_tokens = unblinded_tokens_->GetTokensAsList();
dictionary.SetKey("unblinded_tokens", base::Value(
Expand Down Expand Up @@ -114,6 +123,28 @@ base::Value ConfirmationsImpl::GetCatalogIssuersAsDictionary(
return dictionary;
}

base::Value ConfirmationsImpl::GetTransactionHistoryAsDictionary(
const std::vector<TransactionInfo>& transaction_history) const {
base::Value dictionary(base::Value::Type::DICTIONARY);

base::Value list(base::Value::Type::LIST);
for (const auto& transaction : transaction_history) {
base::Value transaction_dictionary(base::Value::Type::DICTIONARY);

transaction_dictionary.SetKey("timestamp_in_seconds",
base::Value(std::to_string(transaction.timestamp_in_seconds)));

transaction_dictionary.SetKey("estimated_redemption_value",
base::Value(transaction.estimated_redemption_value));

list.GetList().push_back(std::move(transaction_dictionary));
}

dictionary.SetKey("transactions", base::Value(std::move(list)));

return dictionary;
}

bool ConfirmationsImpl::FromJSON(const std::string& json) {
std::unique_ptr<base::DictionaryValue> dictionary =
base::DictionaryValue::From(base::JSONReader::Read(json));
Expand Down Expand Up @@ -141,6 +172,26 @@ bool ConfirmationsImpl::FromJSON(const std::string& json) {
return false;
}

// Transaction history
auto* transaction_history_value = dictionary->FindKey("transaction_history");
if (!transaction_history_value) {
return false;
}

base::DictionaryValue* transaction_history_dictionary;
if (!transaction_history_value->GetAsDictionary(
&transaction_history_dictionary)) {
return false;
}

std::vector<TransactionInfo> transaction_history;
if (!GetTransactionHistoryFromDictionary(transaction_history_dictionary,
&transaction_history)) {
return false;
}

transaction_history_ = transaction_history;

// Unblinded tokens
auto* unblinded_tokens_value = dictionary->FindKey("unblinded_tokens");
if (!unblinded_tokens_value) {
Expand Down Expand Up @@ -217,6 +268,52 @@ bool ConfirmationsImpl::GetCatalogIssuersFromDictionary(
return true;
}

bool ConfirmationsImpl::GetTransactionHistoryFromDictionary(
base::DictionaryValue* dictionary,
std::vector<TransactionInfo>* transaction_history) {
DCHECK(dictionary);
DCHECK(transaction_history);

// Transaction
auto* transactions_value = dictionary->FindKey("transactions");
if (!transactions_value) {
return false;
}

transaction_history->clear();
base::ListValue transactions_list_value(transactions_value->GetList());
for (auto& transaction_value : transactions_list_value) {
base::DictionaryValue* transaction_dictionary;
if (!transaction_value.GetAsDictionary(&transaction_dictionary)) {
return false;
}

TransactionInfo info;

// Timestamp
auto* timestamp_in_seconds_value =
transaction_dictionary->FindKey("timestamp_in_seconds");
if (!timestamp_in_seconds_value) {
return false;
}
info.timestamp_in_seconds =
std::stoull(timestamp_in_seconds_value->GetString());

// Estimated redemption value
auto* estimated_redemption_value_value =
transaction_dictionary->FindKey("estimated_redemption_value");
if (!estimated_redemption_value_value) {
return false;
}
info.estimated_redemption_value =
estimated_redemption_value_value->GetDouble();

transaction_history->push_back(info);
}

return true;
}

void ConfirmationsImpl::SaveState() {
BLOG(INFO) << "Saving confirmations state";

Expand Down Expand Up @@ -336,6 +433,56 @@ bool ConfirmationsImpl::IsValidPublicKeyForCatalogIssuers(
return true;
}

void ConfirmationsImpl::GetTransactionHistory(
const uint64_t from_timestamp_in_seconds,
const uint64_t to_timestamp_in_seconds,
OnGetTransactionHistoryCallback callback) {
std::vector<TransactionInfo> transactions(transaction_history_.size());

auto it = std::copy_if(transaction_history_.begin(),
transaction_history_.end(), transactions.begin(),
[=](TransactionInfo& info) {
return info.timestamp_in_seconds >= from_timestamp_in_seconds &&
info.timestamp_in_seconds <= to_timestamp_in_seconds;
});

transactions.resize(std::distance(transactions.begin(), it));

auto transactions_info = std::make_unique<TransactionsInfo>();
transactions_info->transactions = transactions;

callback(std::move(transactions_info));
}

double ConfirmationsImpl::GetEstimatedRedemptionValue(
const std::string& public_key) const {
double estimated_redemption_value = 0.0;

auto it = catalog_issuers_.find(public_key);
if (it != catalog_issuers_.end()) {
auto name = it->second;
if (!re2::RE2::Replace(&name, "BAT", "")) {
BLOG(ERROR) << "Could not estimate redemption value due to catalog"
<< " issuer name missing BAT";
}

estimated_redemption_value = stod(name);
}

return estimated_redemption_value;
}

void ConfirmationsImpl::AppendEstimatedRedemptionValueToTransactionHistory(
double estimated_redemption_value) {
TransactionInfo info;
info.timestamp_in_seconds = static_cast<uint64_t>(std::time(nullptr));
info.estimated_redemption_value = estimated_redemption_value;

transaction_history_.push_back(info);

SaveState();
}

void ConfirmationsImpl::AdSustained(std::unique_ptr<NotificationInfo> info) {
BLOG(INFO) << "AdSustained:";
BLOG(INFO) << " creativeSetId: " << info->creative_set_id;
Expand Down
Loading

0 comments on commit 211e767

Please sign in to comment.