diff --git a/components/brave_rewards/browser/rewards_service_browsertest.cc b/components/brave_rewards/browser/rewards_service_browsertest.cc index dc4c537e5be8..3040f267bcb0 100644 --- a/components/brave_rewards/browser/rewards_service_browsertest.cc +++ b/components/brave_rewards/browser/rewards_service_browsertest.cc @@ -3,9 +3,12 @@ * 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 + #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/string_split.h" +#include "base/memory/weak_ptr.h" #include "bat/ledger/internal/bat_helper.h" #include "bat/ledger/internal/static_values.h" #include "bat/ledger/ledger.h" @@ -16,6 +19,8 @@ #include "brave/components/brave_rewards/browser/rewards_service_factory.h" #include "brave/components/brave_rewards/browser/rewards_service_impl.h" #include "brave/components/brave_rewards/browser/rewards_service_observer.h" +#include "brave/components/brave_rewards/browser/rewards_notification_service_impl.h" // NOLINT +#include "brave/components/brave_rewards/browser/rewards_notification_service_observer.h" // NOLINT #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/common/chrome_paths.h" @@ -74,8 +79,11 @@ namespace brave_test_resp { std::string surveyor_voting_credential_; } // namespace brave_test_resp -class BraveRewardsBrowserTest : public InProcessBrowserTest, - public brave_rewards::RewardsServiceObserver { +class BraveRewardsBrowserTest : + public InProcessBrowserTest, + public brave_rewards::RewardsServiceObserver, + public brave_rewards::RewardsNotificationServiceObserver, + public base::SupportsWeakPtr { public: void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); @@ -174,7 +182,8 @@ class BraveRewardsBrowserTest : public InProcessBrowserTest, *response = brave_test_resp::surveyor_voting_; } else if (URLMatches(url, GET_PUBLISHERS_LIST_V1, "", SERVER_TYPES::PUBLISHER_DISTRO)) { - *response = "[[\"duckduckgo.com\",true,false]]"; + *response = + "[[\"bumpsmack.com\",true,false],[\"duckduckgo.com\",true,false]]"; } } @@ -220,6 +229,14 @@ class BraveRewardsBrowserTest : public InProcessBrowserTest, wait_for_reconcile_completed_loop_->Run(); } + void WaitForInsufficientFundsNotification() { + if (insufficient_notification_would_have_already_shown_) { + return; + } + wait_for_insufficient_notification_loop_.reset(new base::RunLoop); + wait_for_insufficient_notification_loop_->Run(); + } + void GetReconcileTime() { rewards_service()->GetReconcileTime( base::Bind(&BraveRewardsBrowserTest::OnGetReconcileTime, @@ -454,7 +471,9 @@ class BraveRewardsBrowserTest : public InProcessBrowserTest, EXPECT_NE(js_result.ExtractString().find("30.0 BAT"), std::string::npos); } - void VisitPublisher(const std::string& publisher, bool verified) { + void VisitPublisher(const std::string& publisher, + bool verified, + int32_t last_add = false) { GURL url = embedded_test_server()->GetURL(publisher, "/index.html"); ui_test_utils::NavigateToURLWithDisposition( browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB, @@ -477,8 +496,8 @@ class BraveRewardsBrowserTest : public InProcessBrowserTest, contents(), "const delay = t => new Promise(resolve => setTimeout(resolve, t));" "delay(1000).then(() => " - " document.querySelector(\"[data-test-id='autoContribute']\")." - " getElementsByTagName('a')[0].innerText);", + " document.querySelector(\"[data-test-id='ac_link_" + publisher + "']" + "\").innerText);", content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, content::ISOLATED_WORLD_ID_CONTENT_END); EXPECT_STREQ(js_result.ExtractString().c_str(), publisher.c_str()); @@ -488,22 +507,26 @@ class BraveRewardsBrowserTest : public InProcessBrowserTest, // favicon and the verified icon content::EvalJsResult js_result = EvalJs(contents(), - "document.querySelector(\"[data-test-id='autoContribute']\")." - " getElementsByTagName('svg').length === 2;", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); + "document.querySelector(\"[data-test-id='ac_link_" + + publisher + "']\").getElementsByTagName('svg').length === 1;", + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); EXPECT_TRUE(js_result.ExtractBool()); } else { // An unverified site has one image associated with it, the site's // favicon content::EvalJsResult js_result = EvalJs(contents(), - "document.querySelector(\"[data-test-id='autoContribute']\")." - " getElementsByTagName('svg').length === 1;", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); + "document.querySelector(\"[data-test-id='ac_link_" + + publisher + "']\").getElementsByTagName('svg').length === 0;", + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); EXPECT_TRUE(js_result.ExtractBool()); } + + if (last_add) { + last_publisher_added_ = true; + } } void TipPublisher(const std::string& publisher, bool verified, bool monthly) { @@ -791,6 +814,46 @@ class BraveRewardsBrowserTest : public InProcessBrowserTest, ac_low_amount_ = true; } + void OnNotificationAdded( + brave_rewards::RewardsNotificationService* rewards_notification_service, + const brave_rewards::RewardsNotificationService::RewardsNotification& + notification) { + const brave_rewards::RewardsNotificationService::RewardsNotificationsMap& + notifications = rewards_notification_service->GetAllNotifications(); + for (const auto& notification : notifications) { + if (notification.second.type_ == + brave_rewards::RewardsNotificationService::RewardsNotificationType + ::REWARDS_NOTIFICATION_INSUFFICIENT_FUNDS) { + insufficient_notification_would_have_already_shown_ = true; + if (wait_for_insufficient_notification_loop_) { + wait_for_insufficient_notification_loop_->Quit(); + } + } + } + } + + /** + * When using notification observer for insufficient funds, tests will fail + * for sufficient funds because observer will never be called for + * notification. Use this as callback to know when we come back with + * sufficient funds to prevent inf loop + * */ + void ShowNotificationAddFundsForTesting(bool sufficient) { + if (sufficient) { + insufficient_notification_would_have_already_shown_ = true; + if (wait_for_insufficient_notification_loop_) { + wait_for_insufficient_notification_loop_->Quit(); + } + } + } + + void CheckInsufficientFundsForTesting() { + rewards_service_->MaybeShowNotificationAddFundsForTesting( + base::BindOnce( + &BraveRewardsBrowserTest::ShowNotificationAddFundsForTesting, + AsWeakPtr())); + } + MOCK_METHOD1(OnGetProduction, void(bool)); MOCK_METHOD1(OnGetDebug, void(bool)); MOCK_METHOD1(OnGetReconcileTime, void(int32_t)); @@ -819,9 +882,13 @@ class BraveRewardsBrowserTest : public InProcessBrowserTest, bool reconcile_completed_ = false; unsigned int reconcile_status_ = ledger::LEDGER_ERROR; + std::unique_ptr wait_for_insufficient_notification_loop_; + bool insufficient_notification_would_have_already_shown_ = false; + bool contribution_made_ = false; bool tip_made = false; bool ac_low_amount_ = false; + bool last_publisher_added_ = false; }; IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, RenderWelcome) { @@ -1409,3 +1476,138 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, // Stop observing the Rewards service rewards_service_->RemoveObserver(this); } + +IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsZeroAmountZeroPublishers) { + rewards_service_->GetNotificationService()->AddObserver(this); + EnableRewards(); + CheckInsufficientFundsForTesting(); + WaitForInsufficientFundsNotification(); + const brave_rewards::RewardsNotificationService::RewardsNotificationsMap& + notifications = rewards_service_->GetAllNotifications(); + + if (notifications.empty()) { + SUCCEED(); + } + bool notification_shown = false; + for (const auto& notification : notifications) { + if (notification.second.type_ == + brave_rewards::RewardsNotificationService::RewardsNotificationType + ::REWARDS_NOTIFICATION_INSUFFICIENT_FUNDS) { + notification_shown = true; + } + } + EXPECT_FALSE(notification_shown); +} + +IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsDefaultAmount) { + rewards_service_->AddObserver(this); + rewards_service_->GetNotificationService()->AddObserver(this); + EnableRewards(); + // Claim grant using panel + const bool use_panel = true; + ClaimGrant(use_panel); + + // Visit publishers + while (!last_publisher_added_) { + const bool verified = true; + VisitPublisher("duckduckgo.com", verified); + VisitPublisher("bumpsmack.com", verified); + VisitPublisher("google.com", !verified, true); + } + + CheckInsufficientFundsForTesting(); + WaitForInsufficientFundsNotification(); + const brave_rewards::RewardsNotificationService::RewardsNotificationsMap& + notifications = rewards_service_->GetAllNotifications(); + + if (notifications.empty()) { + SUCCEED(); + } + bool notification_shown = false; + for (const auto& notification : notifications) { + if (notification.second.type_ == + brave_rewards::RewardsNotificationService::RewardsNotificationType + ::REWARDS_NOTIFICATION_INSUFFICIENT_FUNDS) { + notification_shown = true; + } + } + EXPECT_FALSE(notification_shown); +} + +IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsSufficientAmount) { + rewards_service_->AddObserver(this); + rewards_service_->GetNotificationService()->AddObserver(this); + + EnableRewards(); + // Claim grant using panel + const bool use_panel = true; + ClaimGrant(use_panel); + + // Visit publishers + while (!last_publisher_added_) { + const bool verified = true; + VisitPublisher("duckduckgo.com", verified); + VisitPublisher("bumpsmack.com", verified); + VisitPublisher("google.com", !verified, true); + } + + rewards_service_->SetContributionAmount(40.0); + + CheckInsufficientFundsForTesting(); + WaitForInsufficientFundsNotification(); + const brave_rewards::RewardsNotificationService::RewardsNotificationsMap& + notifications = rewards_service_->GetAllNotifications(); + if (notifications.empty()) { + SUCCEED(); + } + bool notification_shown = false; + for (const auto& notification : notifications) { + if (notification.second.type_ == + brave_rewards::RewardsNotificationService::RewardsNotificationType + ::REWARDS_NOTIFICATION_INSUFFICIENT_FUNDS) { + notification_shown = true; + } + } + EXPECT_FALSE(notification_shown); +} + +IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsInsufficientAmount) { + rewards_service_->AddObserver(this); + rewards_service_->GetNotificationService()->AddObserver(this); + EnableRewards(); + // Claim grant using panel + const bool use_panel = true; + ClaimGrant(use_panel); + + // Visit publishers + while (!last_publisher_added_) { + const bool verified = true; + VisitPublisher("duckduckgo.com", verified); + VisitPublisher("bumpsmack.com", verified); + VisitPublisher("google.com", !verified, true); + } + rewards_service_->SetContributionAmount(100.0); + + rewards_service_->CheckInsufficientFundsForTesting(); + WaitForInsufficientFundsNotification(); + const brave_rewards::RewardsNotificationService::RewardsNotificationsMap& + notifications = rewards_service_->GetAllNotifications(); + + if (notifications.empty()) { + FAIL() << "Should see Insufficient Funds notification"; + } + bool notification_shown = false; + for (const auto& notification : notifications) { + if (notification.second.type_ == + brave_rewards::RewardsNotificationService::RewardsNotificationType + ::REWARDS_NOTIFICATION_INSUFFICIENT_FUNDS) { + notification_shown = true; + } + } + EXPECT_TRUE(notification_shown); +} + diff --git a/components/brave_rewards/browser/rewards_service_impl.cc b/components/brave_rewards/browser/rewards_service_impl.cc index 2355b8dd35ca..a3e74c417b4f 100644 --- a/components/brave_rewards/browser/rewards_service_impl.cc +++ b/components/brave_rewards/browser/rewards_service_impl.cc @@ -2470,6 +2470,11 @@ void RewardsServiceImpl::MaybeShowNotificationAddFunds() { AsWeakPtr())); } +void RewardsServiceImpl::MaybeShowNotificationAddFundsForTesting( + base::OnceCallback callback) { + bat_ledger_->HasSufficientBalanceToReconcile(std::move(callback)); +} + bool RewardsServiceImpl::ShouldShowNotificationAddFunds() const { base::Time next_time = profile_->GetPrefs()->GetTime(prefs::kRewardsAddFundsNotification); @@ -2667,6 +2672,10 @@ void RewardsServiceImpl::StartAutoContributeForTest() { bat_ledger_->StartAutoContribute(); } +void RewardsServiceImpl::CheckInsufficientFundsForTesting() { + MaybeShowNotificationAddFunds(); +} + void RewardsServiceImpl::GetProduction(const GetProductionCallback& callback) { bat_ledger_service_->GetProduction(callback); } diff --git a/components/brave_rewards/browser/rewards_service_impl.h b/components/brave_rewards/browser/rewards_service_impl.h index 3c4990522bbb..594052de96c7 100644 --- a/components/brave_rewards/browser/rewards_service_impl.h +++ b/components/brave_rewards/browser/rewards_service_impl.h @@ -38,6 +38,30 @@ #include "brave/components/brave_rewards/browser/extension_rewards_service_observer.h" #endif +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsInsufficientAmount); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsSufficientAmount); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, ActivateSettingsModal); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, HandleFlagsSingleArg); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, HandleFlagsMultipleFlags); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, HandleFlagsWrongInput); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, ClaimGrantViaSettingsPage); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, ClaimGrantViaPanel); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, PanelShowsCorrectPublisherData); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, VisitVerifiedPublisher); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, VisitUnverifiedPublisher); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, AutoContribution); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, TipVerifiedPublisher); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, TipUnverifiedPublisher); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, RecurringTipForVerifiedPublisher); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, + RecurringTipForUnverifiedPublisher); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsZeroAmountZeroPublishers); +FORWARD_DECLARE_TEST(BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsDefaultAmount); + namespace base { class OneShotTimer; class RepeatingTimer; @@ -66,6 +90,7 @@ namespace brave_rewards { class PublisherInfoDatabase; class RewardsNotificationServiceImpl; +class BraveRewardsBrowserTest; using GetProductionCallback = base::Callback; using GetDebugCallback = base::Callback; @@ -221,9 +246,38 @@ class RewardsServiceImpl : public RewardsService, // Testing methods void SetLedgerEnvForTesting(); void StartAutoContributeForTest(); + void CheckInsufficientFundsForTesting(); + void MaybeShowNotificationAddFundsForTesting( + base::OnceCallback callback); private: FRIEND_TEST_ALL_PREFIXES(RewardsServiceTest, OnWalletProperties); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsInsufficientAmount); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsSufficientAmount); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, ActivateSettingsModal); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, HandleFlagsSingleArg); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, HandleFlagsMultipleFlags); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, HandleFlagsWrongInput); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + ClaimGrantViaSettingsPage); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, ClaimGrantViaPanel); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + PanelShowsCorrectPublisherData); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, VisitVerifiedPublisher); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, VisitUnverifiedPublisher); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, AutoContribution); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, TipVerifiedPublisher); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, TipUnverifiedPublisher); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + RecurringTipForVerifiedPublisher); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + RecurringTipForUnverifiedPublisher); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsZeroAmountZeroPublishers); + FRIEND_TEST_ALL_PREFIXES(::BraveRewardsBrowserTest, + InsufficientNotificationForVerifiedsDefaultAmount); friend class ::BraveRewardsBrowserTest; const base::OneShotEvent& ready() const { return ready_; } diff --git a/components/services/bat_ledger/bat_ledger_impl.cc b/components/services/bat_ledger/bat_ledger_impl.cc index eef82fd04a5e..a3fedeefd5df 100644 --- a/components/services/bat_ledger/bat_ledger_impl.cc +++ b/components/services/bat_ledger/bat_ledger_impl.cc @@ -364,9 +364,21 @@ void BatLedgerImpl::GetRewardsMainEnabled( std::move(callback).Run(ledger_->GetRewardsMainEnabled()); } +void BatLedgerImpl::OnHasSufficientBalanceToReconcile( + CallbackHolder* holder, + bool sufficient) { + if (holder->is_valid()) { + std::move(holder->get()).Run(sufficient); + } + delete holder; +} + void BatLedgerImpl::HasSufficientBalanceToReconcile( HasSufficientBalanceToReconcileCallback callback) { - std::move(callback).Run(ledger_->HasSufficientBalanceToReconcile()); + auto* holder = new CallbackHolder( + AsWeakPtr(), std::move(callback)); + ledger_->HasSufficientBalanceToReconcile( + std::bind(BatLedgerImpl::OnHasSufficientBalanceToReconcile, holder, _1)); } // static diff --git a/components/services/bat_ledger/bat_ledger_impl.h b/components/services/bat_ledger/bat_ledger_impl.h index f29f3a1b091d..cc7ed7c050ae 100644 --- a/components/services/bat_ledger/bat_ledger_impl.h +++ b/components/services/bat_ledger/bat_ledger_impl.h @@ -218,6 +218,10 @@ class BatLedgerImpl : public mojom::BatLedger, ledger::Result result, ledger::PublisherInfoPtr info); + static void OnHasSufficientBalanceToReconcile( + CallbackHolder* holder, + bool sufficient); + std::unique_ptr bat_ledger_client_mojo_proxy_; std::unique_ptr ledger_; diff --git a/package-lock.json b/package-lock.json index 35b7cbd3d49d..96dc2724d0af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -226,9 +226,9 @@ } }, "@ctrl/tinycolor": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-2.4.0.tgz", - "integrity": "sha512-ZLjdsst8/ENM6spDmh3qPQSM+iDSerTGjA05KhAXog7o/aOa9tn7qzWMeOtJzGaDMmsBLxh4IuZ5GH7nfda9gg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-2.5.1.tgz", + "integrity": "sha512-I5SD9ii2gh/4/LNyg+dXG6S5B41bZyQyXCldSZxNHMlNnFtDgo1h7Tn/PiCZ8qlRkAFmv+kx1ay/gtTyCVrGcw==", "dev": true }, "@jest/console": { @@ -562,7 +562,7 @@ }, "@types/filewriter": { "version": "0.0.28", - "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.28.tgz", + "resolved": "http://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.28.tgz", "integrity": "sha1-wFTor02d11205jq8dviFFocU1LM=", "dev": true }, @@ -1065,7 +1065,7 @@ }, "array-equal": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, @@ -1147,7 +1147,7 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -1259,7 +1259,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -1597,8 +1597,8 @@ } }, "brave-ui": { - "version": "github:brave/brave-ui#079dbadba9c270b975eac1962355914a43935b34", - "from": "github:brave/brave-ui#079dbadba9c270b975eac1962355914a43935b34", + "version": "github:brave/brave-ui#c44109b7241aaaac5cbee82d5f8a49aa16b9a40f", + "from": "github:brave/brave-ui#c44109b7241aaaac5cbee82d5f8a49aa16b9a40f", "dev": true, "requires": { "@ctrl/tinycolor": "^2.2.1", @@ -1637,7 +1637,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -1679,7 +1679,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -1755,7 +1755,7 @@ }, "buffer-equals": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", + "resolved": "http://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", "integrity": "sha1-A1O1T9B/2VZBcGca5vZrnPENJ/U=" }, "buffer-fill": { @@ -2206,7 +2206,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -2219,7 +2219,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -2347,7 +2347,7 @@ }, "css-select": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dev": true, "requires": { @@ -2409,7 +2409,7 @@ }, "d": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { @@ -2606,7 +2606,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -2635,7 +2635,7 @@ }, "doctrine": { "version": "0.7.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", "dev": true, "requires": { @@ -3257,7 +3257,7 @@ }, "file-loader": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { @@ -3470,8 +3470,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -3492,14 +3491,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3514,20 +3511,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -3644,8 +3638,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -3657,7 +3650,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3672,7 +3664,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3680,14 +3671,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3706,7 +3695,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3787,8 +3775,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3800,7 +3787,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3886,8 +3872,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -3923,7 +3908,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3943,7 +3927,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3987,14 +3970,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -4509,7 +4490,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { @@ -4576,7 +4557,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { @@ -6041,7 +6022,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mississippi": { @@ -6085,7 +6066,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -6093,7 +6074,7 @@ "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } @@ -6130,7 +6111,7 @@ }, "mp4-stream": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mp4-stream/-/mp4-stream-2.0.3.tgz", + "resolved": "http://registry.npmjs.org/mp4-stream/-/mp4-stream-2.0.3.tgz", "integrity": "sha512-5NzgI0+bGakoZEwnIYINXqB3mnewkt3Y7jcvkXsTubnCNUSdM8cpP0Vemxf6FLg0qUN8fydTgNMVAc3QU8B92g==", "requires": { "buffer-alloc": "^1.1.0", @@ -6228,7 +6209,7 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, @@ -6314,7 +6295,7 @@ "dependencies": { "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { @@ -6558,7 +6539,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true } @@ -6751,7 +6732,7 @@ }, "path-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -6769,7 +6750,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { @@ -7364,7 +7345,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -7678,7 +7659,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -7783,7 +7764,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -8135,7 +8116,7 @@ }, "sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, @@ -8337,7 +8318,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" @@ -8345,7 +8326,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -8360,7 +8341,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -8388,7 +8369,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -8589,7 +8570,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { @@ -8875,7 +8856,7 @@ }, "tty-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, @@ -9148,7 +9129,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -9286,7 +9267,7 @@ }, "vm-browserify": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { @@ -9621,7 +9602,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { @@ -9640,7 +9621,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { diff --git a/package.json b/package.json index ee674bada5dc..5ab057b0f0a4 100644 --- a/package.json +++ b/package.json @@ -277,7 +277,7 @@ "@types/react-redux": "6.0.4", "@types/redux-logger": "^3.0.7", "awesome-typescript-loader": "^5.2.1", - "brave-ui": "github:brave/brave-ui#079dbadba9c270b975eac1962355914a43935b34", + "brave-ui": "github:brave/brave-ui#c44109b7241aaaac5cbee82d5f8a49aa16b9a40f", "css-loader": "^2.1.1", "csstype": "^2.5.5", "deep-freeze-node": "^1.1.3", diff --git a/test/BUILD.gn b/test/BUILD.gn index 89cacaa9202c..2c98c7f8cef7 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -117,6 +117,7 @@ test("brave_unit_tests") { "//brave/vendor/bat-native-ledger/src/bat/ledger/internal/media/helper_unittest.cc", "//brave/vendor/bat-native-ledger/src/bat/ledger/internal/media/twitch_unittest.cc", "//brave/vendor/bat-native-ledger/src/bat/ledger/internal/media/youtube_unittest.cc", + "//brave/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution_unittest.cc", "//brave/vendor/bat-native-ledger/src/bat/ledger/internal/bat_helper_unittest.cc", "//brave/vendor/bat-native-ledger/src/bat/ledger/internal/bat_helper_unittest.h", "//brave/vendor/bat-native-ledger/src/bat/ledger/internal/bat_publishers_unittest.cc", diff --git a/vendor/bat-native-ledger/include/bat/ledger/ledger.h b/vendor/bat-native-ledger/include/bat/ledger/ledger.h index 799f15afac62..93a383375c08 100644 --- a/vendor/bat-native-ledger/include/bat/ledger/ledger.h +++ b/vendor/bat-native-ledger/include/bat/ledger/ledger.h @@ -64,6 +64,7 @@ using OnWalletPropertiesCallback = std::function)>; using OnRefreshPublisherCallback = std::function; +using HasSufficientBalanceToReconcileCallback = std::function; class LEDGER_EXPORT Ledger { public: @@ -267,7 +268,8 @@ class LEDGER_EXPORT Ledger { virtual uint64_t GetBootStamp() const = 0; - virtual bool HasSufficientBalanceToReconcile() = 0; + virtual void HasSufficientBalanceToReconcile( + HasSufficientBalanceToReconcileCallback callback) = 0; virtual void GetAddressesForPaymentId( ledger::WalletAddressesCallback callback) = 0; diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.cc index b3536d94189d..a8d10211b781 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.cc @@ -92,6 +92,100 @@ std::string BatContribution::GetAnonizeProof( return proof; } +void BatContribution::HasSufficientBalance( + ledger::HasSufficientBalanceToReconcileCallback callback) { + ledger::ActivityInfoFilter filter = ledger_->CreateActivityFilter( + std::string(), + ledger::EXCLUDE_FILTER::FILTER_ALL_EXCEPT_EXCLUDED, + true, + ledger_->GetReconcileStamp(), + ledger_->GetPublisherAllowNonVerified(), + ledger_->GetPublisherMinVisits()); + ledger_->GetActivityInfoList( + 0, + 0, + filter, + std::bind(&BatContribution::GetVerifiedAutoAmount, + this, + _1, + _2, + callback)); +} + +void BatContribution::GetVerifiedAutoAmount( + const ledger::PublisherInfoList& publisher_list, + uint32_t record, + ledger::HasSufficientBalanceToReconcileCallback callback) { + double ac_amount = ledger_->GetContributionAmount(); + double total_reconcile_amount(GetAmountFromVerifiedAuto( + publisher_list, ac_amount)); + ledger_->GetRecurringTips( + std::bind(&BatContribution::GetVerifiedRecurringAmount, + this, + _1, + _2, + total_reconcile_amount, + publisher_list.empty(), + callback)); +} + +// static +double BatContribution::GetAmountFromVerifiedAuto( + const ledger::PublisherInfoList& publisher_list, + double ac_amount) { + double non_verified_bat = 0.0; + for (const auto& publisher : publisher_list) { + if (!publisher->verified) { + non_verified_bat += (publisher->percent / 100.0) * ac_amount; + } + } + return ac_amount - non_verified_bat; +} + +void BatContribution::GetVerifiedRecurringAmount( + const ledger::PublisherInfoList& publisher_list, + uint32_t record, + double total_reconcile_amount, + bool ac_list_empty, + ledger::HasSufficientBalanceToReconcileCallback callback) { + if (!publisher_list.empty()) { + total_reconcile_amount += GetAmountFromVerifiedRecurring(publisher_list); + } + if (publisher_list.empty() && ac_list_empty) { + callback(true); + return; + } + ledger_->FetchWalletProperties( + std::bind(&BatContribution::OnFetchWalletProperties, + this, _1, _2, total_reconcile_amount, callback)); +} + +void BatContribution::OnFetchWalletProperties( + ledger::Result result, + std::unique_ptr info, + double total_reconcile_amount, + ledger::HasSufficientBalanceToReconcileCallback callback) { + if (result == ledger::Result::LEDGER_OK && info) { + bool sufficient(info->balance_ >= total_reconcile_amount); + callback(sufficient); + } +} + +// static +double BatContribution::GetAmountFromVerifiedRecurring( + const ledger::PublisherInfoList& publisher_list) { + double total_recurring_amount(0.0); + for (const auto& publisher : publisher_list) { + if (publisher->id.empty()) { + continue; + } + if (publisher->verified) { + total_recurring_amount += publisher->weight; + } + } + return total_recurring_amount; +} + ledger::PublisherInfoList BatContribution::GetVerifiedListAuto( const std::string& viewing_id, const ledger::PublisherInfoList* list, diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.h b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.h index 40eb0204a6f6..289b816b2c70 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.h +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution.h @@ -11,6 +11,7 @@ #include #include +#include "base/gtest_prod_util.h" #include "bat/ledger/ledger.h" #include "bat/ledger/internal/bat_helper.h" @@ -146,6 +147,8 @@ class BatContribution { ledger::ACTIVITY_MONTH month, int year, uint32_t date); + void HasSufficientBalance( + ledger::HasSufficientBalanceToReconcileCallback callback); // Triggers contribution process for auto contribute table void StartAutoContribute(); @@ -298,11 +301,41 @@ class BatContribution { void DoRetry(const std::string& viewing_id); + void GetVerifiedAutoAmount( + const ledger::PublisherInfoList& publisher_list, + uint32_t record, + ledger::HasSufficientBalanceToReconcileCallback callback); + + void GetVerifiedRecurringAmount( + const ledger::PublisherInfoList& publisher_list, + uint32_t record, + double budget, + bool ac_list_empty, + ledger::HasSufficientBalanceToReconcileCallback callback); + + static double GetAmountFromVerifiedAuto( + const ledger::PublisherInfoList& publisher_list, + double ac_amount); + + static double GetAmountFromVerifiedRecurring( + const ledger::PublisherInfoList& publisher_list); + + void OnFetchWalletProperties( + ledger::Result result, + std::unique_ptr info, + double total_reconcile_amount, + ledger::HasSufficientBalanceToReconcileCallback callback); + bat_ledger::LedgerImpl* ledger_; // NOT OWNED uint32_t last_reconcile_timer_id_; uint32_t last_prepare_vote_batch_timer_id_; uint32_t last_vote_batch_timer_id_; std::map retry_timers_; + + // For testing purposes + friend class BatContributionTest; + FRIEND_TEST_ALL_PREFIXES(BatContributionTest, GetAmountFromVerifiedAuto); + FRIEND_TEST_ALL_PREFIXES(BatContributionTest, GetAmountFromVerifiedRecurring); }; } // namespace braveledger_bat_contribution diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution_unittest.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution_unittest.cc new file mode 100644 index 000000000000..1d3efdbc1a05 --- /dev/null +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/bat_contribution_unittest.cc @@ -0,0 +1,174 @@ +/* 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 +#include + +#include "bat/ledger/internal/logging.h" +#include "bat/ledger/internal/bat_contribution.h" +#include "bat/ledger/ledger.h" +#include "testing/gtest/include/gtest/gtest.h" + +// npm run test -- brave_unit_tests --filter=BatContributionTest.* + +namespace braveledger_bat_contribution { + +class BatContributionTest : public testing::Test { + protected: + void GetPublishersForAuto( + ledger::PublisherInfoList* publisher_info_list, + uint32_t iterations, /* total count of publishers */ + uint32_t variation /* total count of verifieds */) { + // Can't have more verified publishers than total publishers + DCHECK(variation <= iterations); + for (uint32_t ix = 0; ix < iterations; ix++) { + ledger::PublisherInfoPtr publisher_info = ledger::PublisherInfo::New(); + publisher_info->id = "example" + std::to_string(ix) + ".com"; + publisher_info->verified = ix < variation; + publisher_info->percent = (1.0 / iterations) * 100.0; + publisher_info_list->push_back(std::move(publisher_info)); + } + } + + void GetPublishersForRecurring( + ledger::PublisherInfoList* publisher_info_list, + uint32_t iterations, + std::vector amounts, + uint32_t variation) { + for (uint32_t ix = 0; ix < iterations; ix++) { + ledger::PublisherInfoPtr publisher_info = ledger::PublisherInfo::New(); + publisher_info->id = "recurringexample" + std::to_string(ix) + ".com"; + publisher_info->weight = amounts[ix % amounts.size()]; + publisher_info->verified = ix < variation; + publisher_info_list->push_back(std::move(publisher_info)); + } + } + + bool WillTriggerNotification( + uint32_t auto_iterations, + uint32_t auto_variations, + double auto_amount_selected, + uint32_t recurring_iterations, + std::vector recurring_amounts_selected, + uint32_t recurring_variation, + double wallet_balance) { + ledger::PublisherInfoList publisher_info_list_auto; + ledger::PublisherInfoList publisher_info_list_recurring; + GetPublishersForAuto( + &publisher_info_list_auto, auto_iterations, auto_variations); + double total_reconcile_amount = + BatContribution::GetAmountFromVerifiedAuto( + publisher_info_list_auto, auto_amount_selected); + GetPublishersForRecurring( + &publisher_info_list_recurring, + recurring_iterations, + recurring_amounts_selected, + recurring_variation); + total_reconcile_amount += + BatContribution::GetAmountFromVerifiedRecurring( + publisher_info_list_recurring); + return wallet_balance < total_reconcile_amount && + !publisher_info_list_auto.empty() && + !publisher_info_list_recurring.empty(); + } +}; + +TEST_F(BatContributionTest, GetAmountFromVerifiedAuto) { + ledger::PublisherInfoList publisher_info_list; + + // 0 publishers and budget of 0 BAT + GetPublishersForAuto(&publisher_info_list, 0, 0); + double amount = + BatContribution::GetAmountFromVerifiedAuto(publisher_info_list, 0); + EXPECT_EQ(amount, 0); + + // 10 publishers total with 5 verified and budget of 30 BAT + GetPublishersForAuto(&publisher_info_list, 10, 5); + amount = + BatContribution::GetAmountFromVerifiedAuto(publisher_info_list, 30); + EXPECT_EQ(amount, 15); + + // 20 publishers total with 10 verified and budget of 30 BAT + publisher_info_list.clear(); + GetPublishersForAuto(&publisher_info_list, 20, 10); + amount = + BatContribution::GetAmountFromVerifiedAuto(publisher_info_list, 30); + EXPECT_EQ(amount, 15); + + // 50 publishers total with 5 verified and budget of 100 BAT + publisher_info_list.clear(); + GetPublishersForAuto(&publisher_info_list, 50, 5); + amount = + BatContribution::GetAmountFromVerifiedAuto(publisher_info_list, 100); + EXPECT_EQ(amount, 10); + + // 100 publishers total with 80 verified and budget of 1478 BAT + publisher_info_list.clear(); + GetPublishersForAuto(&publisher_info_list, 100, 80); + amount = + BatContribution::GetAmountFromVerifiedAuto(publisher_info_list, 1478); + EXPECT_EQ(amount, 1182.40); + + // 100 publishers total with 4 verified and budget of 100 BAT + publisher_info_list.clear(); + GetPublishersForAuto(&publisher_info_list, 100, 4); + amount = + BatContribution::GetAmountFromVerifiedAuto(publisher_info_list, 100); + EXPECT_EQ(amount, 4); +} + +TEST_F(BatContributionTest, GetAmountFromVerifiedRecurring) { + ledger::PublisherInfoList publisher_info_list; + GetPublishersForRecurring(&publisher_info_list, 5, {1, 5, 10}, 2); + double amount = + BatContribution::GetAmountFromVerifiedRecurring(publisher_info_list); + EXPECT_EQ(amount, 6); + + publisher_info_list.clear(); + GetPublishersForRecurring(&publisher_info_list, 7, {1, 5, 10}, 5); + amount = + BatContribution::GetAmountFromVerifiedRecurring(publisher_info_list); + EXPECT_EQ(amount, 22); + + publisher_info_list.clear(); + GetPublishersForRecurring(&publisher_info_list, 10, {5, 10, 20}, 7); + amount = + BatContribution::GetAmountFromVerifiedRecurring(publisher_info_list); + EXPECT_EQ(amount, 75); + + publisher_info_list.clear(); + GetPublishersForRecurring(&publisher_info_list, 10, {10, 20, 50}, 9); + amount = + BatContribution::GetAmountFromVerifiedRecurring(publisher_info_list); + EXPECT_EQ(amount, 240); + + publisher_info_list.clear(); + GetPublishersForRecurring(&publisher_info_list, 5, {1, 5, 10, 20, 50}, 5); + amount = + BatContribution::GetAmountFromVerifiedRecurring(publisher_info_list); + EXPECT_EQ(amount, 86); +} + +TEST_F(BatContributionTest, WillTriggerNotification) { + // 0 auto, 0 tips, 0 balance + EXPECT_FALSE(WillTriggerNotification(0, 0, 20, 0, {1, 5, 10}, 0, 0.0)); + + EXPECT_TRUE(WillTriggerNotification(10, 5, 30, 5, {1, 5, 10}, 2, 20.9)); + EXPECT_FALSE(WillTriggerNotification(10, 5, 30, 5, {1, 5, 10}, 2, 21)); + EXPECT_TRUE(WillTriggerNotification(20, 10, 30, 7, {1, 5, 10}, 5, 36.9)); + EXPECT_FALSE(WillTriggerNotification(20, 10, 30, 7, {1, 5, 10}, 5, 37)); + EXPECT_TRUE(WillTriggerNotification(50, 5, 100, 10, {5, 10, 20}, 7, 84.9)); + EXPECT_FALSE(WillTriggerNotification(50, 5, 100, 10, {5, 10, 20}, 7, 85)); + EXPECT_TRUE(WillTriggerNotification( + 100, 80, 1478, 10, {10, 20, 50}, 9, 1422.39)); + EXPECT_FALSE(WillTriggerNotification( + 100, 80, 1478, 10, {10, 20, 50}, 9, 1422.40)); + EXPECT_TRUE(WillTriggerNotification( + 100, 4, 100, 5, {1, 5, 10, 20, 50}, 5, 89.9)); + EXPECT_FALSE(WillTriggerNotification( + 100, 4, 100, 5, {1, 5, 10, 20, 50}, 5, 90)); +} + +} // namespace braveledger_bat_contribution diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc index 82e9d4743780..c4026b9904c3 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.cc @@ -1392,8 +1392,9 @@ double LedgerImpl::GetDefaultContributionAmount() { return bat_state_->GetDefaultContributionAmount(); } -bool LedgerImpl::HasSufficientBalanceToReconcile() { - return GetBalance() >= GetContributionAmount(); +void LedgerImpl::HasSufficientBalanceToReconcile( + ledger::HasSufficientBalanceToReconcileCallback callback) { + bat_contribution_->HasSufficientBalance(callback); } void LedgerImpl::SaveNormalizedPublisherList( diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.h b/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.h index 351ce3a79274..500c187ab7b0 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.h +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/ledger_impl.h @@ -412,7 +412,8 @@ class LedgerImpl : public ledger::Ledger, double GetDefaultContributionAmount() override; - bool HasSufficientBalanceToReconcile() override; + void HasSufficientBalanceToReconcile( + ledger::HasSufficientBalanceToReconcileCallback callback) override; void SaveNormalizedPublisherList( ledger::PublisherInfoList normalized_list);