Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace GetWalletToken endpoint with FetchOrGetCachedWalletBalances #21625

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

vkjr
Copy link
Contributor

@vkjr vkjr commented Nov 14, 2024

fixes #20473

Summary

GetWalletToken endpoint in status-go was replaced by FetchOrGetCachedWalletBalances
Visible impact - when user drags down wallet screen and triggers refresh, it happens much quicker - fraction of second instead of few seconds.

Review notes

Deprecated GetWalletToken function was packing a big chunk of information together - not only token balances but also their prices and market values. That resulted in data duplication - inside tokens we had the same information about prices and market values as we already have in re-frame db under [:wallet :tokens :prices-per-token] and [:wallet :tokens :market-values-per-token]. Moreover, in time that information became out of sync, because data under [:wallet :tokens ...] never updated after wallet initialisation while data inside token structure updated regularly.

This PR replaces the endpoint and removes the data duplication.

Token structures fetched with FetchOrGetCachedWalletBalances do not have information about prices and market values. But this information can be found under [:wallet :tokens :prices-per-token] and [:wallet :tokens :market-values-per-token], so big amount of small changes is a result of necessity to pass another structures with prices and market values apart from token itself.

When FetchOrGetCachedWalletBalances finishes successfully we now additionally request prices and market values for those tokens that exist in wallet to have an up-to-date data after user triggered refresh.

Testing notes

From user perspective this PR should't change anything except the speed of wallet refresh when user drags screen down. It is faster now.

Platforms

  • Android
  • iOS

Areas that maybe impacted

Functional
  • wallet / transactions

Steps to test

  • Open Status
  • Check all screens where prices
  • Make sure prices are displayed and displayed correctly

status: ready

@status-im-auto
Copy link
Member

status-im-auto commented Nov 14, 2024

Jenkins Builds

Click to see older builds (38)
Commit #️⃣ Finished (UTC) Duration Platform Result
c35437b #1 2024-11-14 13:12:21 ~3 min tests 📄log
✔️ c35437b #1 2024-11-14 13:18:10 ~9 min ios 📱ipa 📲
✔️ c35437b #1 2024-11-14 13:18:17 ~9 min android-e2e 🤖apk 📲
✔️ c35437b #1 2024-11-14 13:18:43 ~9 min android 🤖apk 📲
f445964 #3 2024-11-14 13:30:35 ~2 min tests 📄log
✔️ f445964 #3 2024-11-14 13:36:15 ~8 min android-e2e 🤖apk 📲
✔️ f445964 #3 2024-11-14 13:36:50 ~8 min android 🤖apk 📲
✔️ f445964 #3 2024-11-14 13:37:25 ~9 min ios 📱ipa 📲
c44b9bd #4 2024-11-14 14:27:29 ~2 min tests 📄log
✔️ c44b9bd #4 2024-11-14 14:31:33 ~6 min android-e2e 🤖apk 📲
✔️ c44b9bd #4 2024-11-14 14:32:49 ~8 min android 🤖apk 📲
✔️ c44b9bd #4 2024-11-14 14:33:32 ~8 min ios 📱ipa 📲
✔️ 97794c9 #5 2024-11-14 15:03:24 ~4 min tests 📄log
✔️ 97794c9 #5 2024-11-14 15:07:08 ~8 min android-e2e 🤖apk 📲
✔️ 97794c9 #5 2024-11-14 15:07:45 ~9 min android 🤖apk 📲
✔️ 97794c9 #5 2024-11-14 15:08:12 ~9 min ios 📱ipa 📲
✔️ ff364b3 #6 2024-11-14 16:22:25 ~4 min tests 📄log
✔️ ff364b3 #6 2024-11-14 16:26:18 ~8 min ios 📱ipa 📲
✔️ ff364b3 #6 2024-11-14 16:26:22 ~8 min android-e2e 🤖apk 📲
✔️ ff364b3 #6 2024-11-14 16:26:53 ~9 min android 🤖apk 📲
cf8da96 #7 2024-11-18 12:23:51 ~3 min tests 📄log
✔️ cf8da96 #7 2024-11-18 12:28:01 ~7 min android 🤖apk 📲
✔️ cf8da96 #7 2024-11-18 12:28:19 ~7 min android-e2e 🤖apk 📲
✔️ cf8da96 #7 2024-11-18 12:29:55 ~9 min ios 📱ipa 📲
0f3cfeb #8 2024-11-18 12:44:23 ~2 min tests 📄log
✔️ 0f3cfeb #8 2024-11-18 12:49:34 ~7 min android-e2e 🤖apk 📲
✔️ 0f3cfeb #8 2024-11-18 12:50:06 ~8 min android 🤖apk 📲
✔️ 0f3cfeb #8 2024-11-18 12:51:00 ~9 min ios 📱ipa 📲
c708313 #10 2024-11-19 12:31:47 ~2 min tests 📄log
✔️ c708313 #10 2024-11-19 12:36:54 ~7 min android-e2e 🤖apk 📲
✔️ be811d9 #11 2024-11-19 12:42:26 ~4 min tests 📄log
✔️ be811d9 #11 2024-11-19 12:45:40 ~7 min android-e2e 🤖apk 📲
✔️ be811d9 #11 2024-11-19 12:46:16 ~8 min android 🤖apk 📲
✔️ be811d9 #11 2024-11-19 12:47:34 ~9 min ios 📱ipa 📲
✔️ 0721455 #12 2024-11-21 13:02:04 ~12 min tests 📄log
✔️ 0721455 #12 2024-11-21 13:02:39 ~13 min android 🤖apk 📲
✔️ 0721455 #12 2024-11-21 13:03:30 ~14 min android-e2e 🤖apk 📲
✔️ 0721455 #12 2024-11-21 13:03:51 ~14 min ios 📱ipa 📲
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ 041e48c #13 2024-11-21 14:30:21 ~6 min tests 📄log
✔️ 041e48c #13 2024-11-21 14:31:52 ~8 min android-e2e 🤖apk 📲
✔️ 041e48c #13 2024-11-21 14:32:37 ~9 min android 🤖apk 📲
✔️ 041e48c #13 2024-11-21 14:35:00 ~11 min ios 📱ipa 📲
✔️ 1538fb4 #14 2024-11-21 15:07:36 ~4 min tests 📄log
✔️ 1538fb4 #14 2024-11-21 15:11:38 ~8 min android-e2e 🤖apk 📲
✔️ 1538fb4 #14 2024-11-21 15:11:45 ~8 min ios 📱ipa 📲
✔️ 1538fb4 #14 2024-11-21 15:12:12 ~9 min android 🤖apk 📲

@vkjr vkjr force-pushed the get-wallet-token-balances branch 2 times, most recently from f445964 to c44b9bd Compare November 14, 2024 14:24
@vkjr vkjr changed the title [WIP] ⚠️ Replace GetWalletToken endpoint with FetchOrGetCachedWalletBalances Replace GetWalletToken endpoint with FetchOrGetCachedWalletBalances Nov 14, 2024
@vkjr vkjr self-assigned this Nov 14, 2024
(str formatted-symbol (cut-fiat-balance-to-two-decimals balance))))
(str formatted-symbol fiat-balance)))

(defn prettify-balance
Copy link
Contributor Author

@vkjr vkjr Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a small refactoring to use more idiomatic ->

(str (cut-crypto-decimals-to-fit-usd-cents crypto-balance conversion-rate)
" "
(string/upper-case token-symbol)))
(-> crypto-balance
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also small refactoring

@@ -80,165 +80,6 @@
(rf/dispatch [:wallet/update-receiver-networks
chain-ids]))}]))}]))

#_(defn- edit-amount
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will never need this since send screen is going to be simplified

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we simply remove it then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is removed in this PR

@@ -116,7 +116,7 @@
{}
raw-data)]
{:db (-> db
(assoc-in [:wallet :tokens :market-values-per-token] market-values)
(update-in [:wallet :tokens :market-values-per-token] merge market-values)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we requested market values just one time so assoc-in was used, but now we do this more often with smaller subset of tokens, so need an update-in

@@ -146,7 +146,7 @@
:wallet.tokens/store-prices
(fn [{:keys [db]} [prices]]
{:db (-> db
(assoc-in [:wallet :tokens :prices-per-token] prices)
(update-in [:wallet :tokens :prices-per-token] merge prices)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor

@alwx alwx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked it at several times and didn't find anything bad or weird :) Thanks!

Copy link
Member

@clauxx clauxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just left one question 👍

Comment on lines +22 to +29
prices-per-token (rf/sub [:wallet/prices-per-token])
balance (utils/calculate-total-token-balance token [chain-id])
crypto-value (utils/get-standard-crypto-format token balance)
crypto-value (utils/get-standard-crypto-format token balance prices-per-token)
fiat-value (utils/calculate-token-fiat-value
{:currency currency
:balance balance
:token token})
{:currency currency
:balance balance
:token token
:prices-per-token prices-per-token})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have subs for utils/get-standard-crypto-format and utils/calculate-token-fiat-value, since in a few places it seems to be directly using values from other subs?

Copy link
Contributor Author

@vkjr vkjr Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are utility functions and they receive different parameters in different contexts (except for prices-per-token), so I believe they aren't very suitable for being a subscription.

But I understand what is the problem that becomes more obvious. We have a piece of information (prices-per-token) that is not needed by UI itself, but have to be passed to utility functions. So the UI here is just a middleman that operates unknown data for no reason. And we have more cases like this. For example passing :profile/currency from ui to utility functions to conversion functions.

I believe that subscription is not a best way to solve this. That data belongs to lower layer (we can think of it as of business-logic), so it should be accessed on lower layer. For example we can create a money/conversion api for ui that contains same functions but they receive less arguments. And calls then redirected to utils functions but that additional arguments like currency, prices-per-token, etc.. taken from database and UI don't know about them.

This is probably something we can discuss on DevX meeting.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, best would be to figure it out during the devx meeting

@VolodLytvynenko
Copy link
Contributor

hi @vkjr could you please rebase and resolve existing conflicts? thanx

@status-im-auto
Copy link
Member

62% of end-end tests have passed

Total executed tests: 8
Failed tests: 2
Expected to fail tests: 1
Passed tests: 5
IDs of failed tests: 727231,740490 
IDs of expected to fail tests: 702843 

Failed tests (2)

Click to expand
  • Rerun failed tests

  • Class TestWalletOneDevice:

    1. test_wallet_add_remove_regular_account, id: 727231

    # STEP: Adding new regular account
    Device 1: Find `Button` by `accessibility id`: `add-account`

    critical/test_wallet.py:255: in test_wallet_add_remove_regular_account
        self.wallet_view.add_regular_account(account_name=new_account_name)
    ../views/wallet_view.py:161: in add_regular_account
        self.add_account_button.click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by accessibility id: `add-account` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    2. test_wallet_balance_mainnet, id: 740490

    ## Signed in successfully!
    Device 1: Find WalletTab by accessibility id: wallet-stack-tab

    critical/test_wallet.py:220: in test_wallet_balance_mainnet
        self.sign_in_view.wallet_tab.click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: WalletTab by accessibility id: `wallet-stack-tab` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Expected to fail tests (1)

    Click to expand

    Class TestCommunityMultipleDeviceMerged:

    1. test_community_message_edit, id: 702843

    Test is not run, e2e blocker  
    

    [[reason: [NOTRUN] Skipped due to waku issue on staging fleet]]

    Passed tests (5)

    Click to expand

    Class TestWalletMultipleDevice:

    1. test_wallet_send_asset_from_drawer, id: 727230
    2. test_wallet_send_eth, id: 727229

    Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_non_latin_messages_stack_update_profile_photo, id: 702745
    Device sessions

    Class TestCommunityOneDeviceMerged:

    1. test_community_copy_and_paste_message_in_chat_input, id: 702742
    Device sessions

    2. test_restore_multiaccount_with_waku_backup_remove_profile_switch, id: 703133
    Device sessions

    @vkjr vkjr force-pushed the get-wallet-token-balances branch 2 times, most recently from a17528a to c708313 Compare November 19, 2024 12:29
    @vkjr
    Copy link
    Contributor Author

    vkjr commented Nov 19, 2024

    @VolodLytvynenko, conflicts resolved

    token-decimals (rf/sub [:wallet/send-display-token-decimals])

    Copy link
    Member

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Remove empty line

    Copy link
    Member

    @briansztamfater briansztamfater left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    LGTM!

    @VolodLytvynenko
    Copy link
    Contributor

    Hi @vkjr thank you for PR. Take a look at found issue

    PR_ISSUE 1: The balances are not refreshed after the fiat change

    Steps:

    1. Go to profile -> select Language and currency -> select any currency

    Actual result:

    The balances are not updated. (see on screen. 26 USDT estimated as 26 RUB)
    image

    Expected result:

    Fiat is converted to the selected one

    OS:

    IOS, Android

    Devices:

    • Pixel 7a, Android 13
    • iPhone 11 Pro Max, IOS 17

    Copy link
    Member

    @smohamedjavid smohamedjavid left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Nice work 🚀

    @smohamedjavid
    Copy link
    Member

    @vkjr - we need to update the following event as well. Fetch only the prices and market values on currency change.

    (rf/reg-event-fx :profile.settings/update-currency
    (fn [_ [currency]]
    {:fx [[:dispatch [:profile.settings/profile-update :currency currency]]
    [:dispatch [:wallet/get-wallet-token-for-all-accounts]]]}))

    @vkjr
    Copy link
    Contributor Author

    vkjr commented Nov 19, 2024

    @VolodLytvynenko, thanks for finding, will fix it.

    @vkjr
    Copy link
    Contributor Author

    vkjr commented Nov 19, 2024

    @smohamedjavid, thanks! I believe this should already work because :wallet/get-wallet-token-for-all-accounts will trigger :wallet/get-wallet-token-for-account and when that calls succeeded fetching of prices and market values will be triggered. Or do you mean something else?

    @smohamedjavid
    Copy link
    Member

    @smohamedjavid, thanks! I believe this should already work because :wallet/get-wallet-token-for-all-accounts will trigger :wallet/get-wallet-token-for-account and when that calls succeeded fetching of prices and market values will be triggered. Or do you mean something else?

    @vkjr - I meant we call the wallet/get-wallet-token-for-all-accounts event in the profile.settings/update-currency event because the currency prices have been nested inside the token data, and we had to fetch again for any other selected currency (including USD - handled by status-go).

    With these PR changes, we can fetch only token prices and market values for the selected currency and USD instead of the whole token data because if the user casually changes the currency multiple times, it will request the whole token data for all those times (pretty heavy for mobile).

    @vkjr
    Copy link
    Contributor Author

    vkjr commented Nov 19, 2024

    @smohamedjavid, ah, now I see your point, thanks!

    @vkjr
    Copy link
    Contributor Author

    vkjr commented Nov 21, 2024

    @VolodLytvynenko, fixed the issue, could you please check? Thanks!

    @status-im-auto
    Copy link
    Member

    75% of end-end tests have passed

    Total executed tests: 8
    Failed tests: 1
    Expected to fail tests: 1
    Passed tests: 6
    
    IDs of failed tests: 727230 
    
    IDs of expected to fail tests: 702843 
    

    Failed tests (1)

    Click to expand
  • Rerun failed tests

  • Class TestWalletMultipleDevice:

    1. test_wallet_send_asset_from_drawer, id: 727230

    Device 2: Find `Text` by `xpath`: `//android.view.ViewGroup[@content-desc='container']/android.widget.TextView[@text='Ether']/../android.widget.TextView[3]`
    Device 2: `Text` is `0.11999 ETH`

    critical/test_wallet.py:189: in test_wallet_send_asset_from_drawer
        self.errors.verify_no_errors()
    base_test_case.py:192: in verify_no_errors
        pytest.fail('\n '.join([self.errors.pop(0) for _ in range(len(self.errors))]))
     Sender balance is not updated on Etherscan, it is 0.3601 but expected to be 0.3602
    



    Expected to fail tests (1)

    Click to expand

    Class TestCommunityMultipleDeviceMerged:

    1. test_community_message_edit, id: 702843

    Test is not run, e2e blocker  
    

    [[reason: [NOTRUN] Skipped due to waku issue on staging fleet]]

    Passed tests (6)

    Click to expand

    Class TestWalletOneDevice:

    1. test_wallet_add_remove_regular_account, id: 727231
    2. test_wallet_balance_mainnet, id: 740490

    Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_non_latin_messages_stack_update_profile_photo, id: 702745
    Device sessions

    Class TestCommunityOneDeviceMerged:

    1. test_community_copy_and_paste_message_in_chat_input, id: 702742
    Device sessions

    2. test_restore_multiaccount_with_waku_backup_remove_profile_switch, id: 703133
    Device sessions

    Class TestWalletMultipleDevice:

    1. test_wallet_send_eth, id: 727229

    @VolodLytvynenko VolodLytvynenko self-assigned this Nov 21, 2024
    (reduce concat)
    (map :symbol)
    set
    vec)]
    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Since there's no guarantee of order in keys from tokens, the resulting vector order of symbols is also unknown. In this case, can't we skip the final vec conversion and persist a set? Seems more correct to me since we don't want duplicates, so why use the vector type?

    This implementation is considerably faster if what I said is correct and we can store a set:

    (reduce-kv (fn [acc _ v]
                 (into acc (map :symbol v)))
               #{}
               tokens)

    :tokens (:tokens %)
    :chain-ids chain-ids})
    (map #(utils/calculate-balance-from-tokens {:currency currency
    :tokens (:tokens %)
    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    (Personal take) Multiline functions with % tend to give poor readability. The characters savings don't compensate in most multiline functions.

    (map #(utils/calculate-balance-from-tokens {:currency currency
    :tokens (:tokens %)
    :chain-ids chain-ids})
    (map #(utils/calculate-balance-from-tokens {:currency currency
    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    [Not a suggestion for change in this PR] This is a good example where we are pulling too much in subs and the code is inefficient.

    To compute this sub we only need the addresses and tokens of accounts. The result of :wallet/accounts sub contains lots of unrelated data, including timestamp and clock, things that can change more often and which would invalidate the cache. The better thing to do is to make the inputs be 2 subs, the accounts addresses and accounts tokens, not the whole :wallet/accounts.

    This :wallet/accounts sub reminds me of the :communities/community sub, which if we subscribe to it will be guaranteed inefficient because it can change for too many reasons (thus changes more frequently and invalidates caches and causes re-processing by Reagent more easily/frequently).

    ;; Do not use this subscription directly in views. There is a significant risk
    ;; of re-rendering views too frequently because an active community can change
    ;; for numerous reasons.
    (re-frame/reg-sub
    :communities/community
    :<- [:communities]
    (fn [communities [_ id]]
    (get communities id)))

    (map :symbol)
    (into acc)))
    #{})
    vec))
    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Is there a reason the unordered sequence of unique symbols must be a vector and not a set?

    Copy link
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Thank you for spotting!
    Not some well-thought reason. I replicated the type of parameter that was passed to :effects.wallet.tokens/fetch-market-values before. But that probably is not necessary. Will check and fix it.

    @VolodLytvynenko
    Copy link
    Contributor

    Hi @vkjr Hi @vkjr, unfortunately, the issue is still reproducible. However, it only occurs after re-login or when the app returns from the background.

    PR_ISSUE 1: Balances shown in USD after fiat currency change and relogin or background

    Steps:

    1. Go to profile -> select Language and currency -> select any other fiat
    2. Relogin or send the app to the background.
    3. Return to the app.

    Actual result:

    Balances are displayed in USD instead of the selected fiat currency.
    Correct fiat conversion occurs only after a manual wallet refresh.

    usd.mp4

    Expected result:

    Fiat is converted to the selected one

    OS:

    IOS, Android

    Devices:

    • Pixel 7a, Android 13
    • iPhone 11 Pro Max, IOS 17

    Logs:

    logs (2).zip

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    Status: CONTRIBUTOR
    Development

    Successfully merging this pull request may close these issues.

    Wallet: update use of GetWalletToken endpoint to GetWalletTokenBalances
    8 participants