From 505f2fe62482f1e33fd6c025b210929b1422297c Mon Sep 17 00:00:00 2001 From: Icaro Motta Date: Thu, 8 Feb 2024 11:17:15 -0300 Subject: [PATCH] Communities: Show relevant tokens (#18636) Show "relevant tokens" in account selection step. Related status-go PR https://github.com/status-im/status-go/pull/4631. - Balances are fetched on the account selection screen. Assuming most users won't care about selecting addresses, this eliminates unnecessary calls to get balances, at the expense of refetching them every time the component is mounted. I think for now this is acceptable. - Relevant tokens is a terminology used in Figma, but more specifically, it means "balances for all assets that have at least one Token Criteria associated, and for a given address". Or, as I tried to give it a more distinct name, "permissioned balances". Areas that may be impacted: None because all affected code is behind a disabled feature flag. Fixes https://github.com/status-im/status-mobile/issues/18126 --- .../account_permissions/component_spec.cljs | 12 +- .../wallet/account_permissions/view.cljs | 16 +- .../wallet/required_tokens/view.cljs | 2 +- src/schema/common.cljs | 2 +- src/status_im/constants.cljs | 3 + .../actions/accounts_selection/view.cljs | 6 +- .../addresses_for_permissions/events.cljs | 58 ++++++ .../events_test.cljs | 15 ++ .../addresses_for_permissions/view.cljs | 170 ++++++++++-------- .../contexts/communities/events.cljs | 1 + src/status_im/subs/communities.cljs | 5 + src/status_im/subs/root.cljs | 1 + status-go-version.json | 6 +- 13 files changed, 203 insertions(+), 94 deletions(-) create mode 100644 src/status_im/contexts/communities/actions/addresses_for_permissions/events.cljs create mode 100644 src/status_im/contexts/communities/actions/addresses_for_permissions/events_test.cljs diff --git a/src/quo/components/wallet/account_permissions/component_spec.cljs b/src/quo/components/wallet/account_permissions/component_spec.cljs index 48f2a2fe29..41eb4ab483 100644 --- a/src/quo/components/wallet/account_permissions/component_spec.cljs +++ b/src/quo/components/wallet/account_permissions/component_spec.cljs @@ -42,18 +42,22 @@ (render [account-permissions/view {:account account :token-details [{:token "SNT" - :amount "100"}]}]) + :amount "100" + :type :token}]}]) (h/is-truthy (h/get-by-text "100 SNT"))) (h/test "render with multiple token details" (render [account-permissions/view {:account account :token-details [{:token "SNT" - :amount "100"} + :amount "100" + :type :token} {:token "ETH" - :amount "18"} + :amount "18" + :type :token} {:token "BTM" - :amount "1000"}]}]) + :amount "1000" + :type :token}]}]) (h/is-truthy (h/get-by-text "100 SNT")) (h/is-truthy (h/get-by-text "18 ETH")) (h/is-truthy (h/get-by-text "1000 BTM"))) diff --git a/src/quo/components/wallet/account_permissions/view.cljs b/src/quo/components/wallet/account_permissions/view.cljs index 9adc035434..8e94e23242 100644 --- a/src/quo/components/wallet/account_permissions/view.cljs +++ b/src/quo/components/wallet/account_permissions/view.cljs @@ -24,7 +24,7 @@ [:address [:maybe :string]] [:emoji [:maybe :string]] [:customization-color [:maybe [:or :string :keyword]]]]] - [:token-details {:optional true} [:maybe [:vector required-tokens/?schema]]] + [:token-details {:optional true} [:maybe [:sequential required-tokens/?schema]]] [:keycard? {:optional true} [:maybe :boolean]] [:checked? {:optional true} [:maybe :boolean]] [:disabled? {:optional true} [:maybe :boolean]] @@ -47,14 +47,16 @@ (i18n/label :t/no-relevant-tokens)] (let [token-length (dec (count tokens))] - (map-indexed (fn [idx {:keys [token amount]}] + (map-indexed (fn [idx {:keys [type token amount collectible-name collectible-img-src]}] ^{:key idx} [required-tokens/view - {:container-style style/token-and-text - :type :token - :amount amount - :token token - :divider? (not= token-length idx)}]) + {:container-style style/token-and-text + :type type + :amount amount + :token token + :collectible-img-src collectible-img-src + :collectible-name collectible-name + :divider? (not= token-length idx)}]) tokens)))]])) (defn- view-internal diff --git a/src/quo/components/wallet/required_tokens/view.cljs b/src/quo/components/wallet/required_tokens/view.cljs index e1a8d6c496..d3a7754e28 100644 --- a/src/quo/components/wallet/required_tokens/view.cljs +++ b/src/quo/components/wallet/required_tokens/view.cljs @@ -15,7 +15,7 @@ [:amount {:optional true} [:maybe [:or :string :int]]] [:token {:optional true} [:maybe :string]] [:token-img-src {:optional true} [:maybe :schema.common/image-source]] - [:collectible-img-src {:optional true} :schema.common/image-source] + [:collectible-img-src {:optional true} [:maybe :schema.common/image-source]] [:collectible-name {:optional true} [:maybe :string]] [:divider? {:optional true} [:maybe :boolean]] [:theme :schema.common/theme] diff --git a/src/schema/common.cljs b/src/schema/common.cljs index 5b5fa57974..3353531162 100644 --- a/src/schema/common.cljs +++ b/src/schema/common.cljs @@ -22,7 +22,7 @@ {:min 1} [:map {:closed true} - [:method :string] + [:method [:or :keyword :string]] [:params [:sequential :any]] [:js-response {:optional true} :any] [:on-success [:or fn? [:cat keyword? [:* :any]]]] diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 09250fe58f..60ffe50183 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -159,6 +159,9 @@ community-token-permission-become-token-master community-token-permission-become-token-owner}) +(def ^:const community-token-type-erc20 1) +(def ^:const community-token-type-erc721 2) + ;; Community rules for joining (def ^:const community-rule-ens-only "ens-only") diff --git a/src/status_im/contexts/communities/actions/accounts_selection/view.cljs b/src/status_im/contexts/communities/actions/accounts_selection/view.cljs index 93ea436b81..8c8100d2a0 100644 --- a/src/status_im/contexts/communities/actions/accounts_selection/view.cljs +++ b/src/status_im/contexts/communities/actions/accounts_selection/view.cljs @@ -18,7 +18,7 @@ {:community-id id :password %}])}]) (rf/dispatch [:navigate-back])) -(defn f-view-internal +(defn view [] (let [{id :community-id} (rf/sub [:get-screen-params]) {:keys [name color images]} (rf/sub [:communities/community id]) @@ -83,7 +83,3 @@ :track-icon :i/face-id :customization-color color :on-complete #(join-community-and-navigate-back id)}]]])) - -(defn view - [] - [:f> f-view-internal]) diff --git a/src/status_im/contexts/communities/actions/addresses_for_permissions/events.cljs b/src/status_im/contexts/communities/actions/addresses_for_permissions/events.cljs new file mode 100644 index 0000000000..b7018aa478 --- /dev/null +++ b/src/status_im/contexts/communities/actions/addresses_for_permissions/events.cljs @@ -0,0 +1,58 @@ +(ns status-im.contexts.communities.actions.addresses-for-permissions.events + (:require + [schema.core :as schema] + [taoensso.timbre :as log] + [utils.re-frame :as rf])) + +(defn get-permissioned-balances + [{[event-id _] :original-event} [community-id]] + {:fx [[:json-rpc/call + [{:method :wakuext_getCommunityPermissionedBalances + :params [{:communityId community-id}] + :on-success [:communities/get-permissioned-balances-success community-id] + :on-error (fn [error] + (log/error "failed to get balances" + {:community-id community-id + :event event-id + :error error}))}]]]}) + +(schema/=> get-permissioned-balances + [:=> + [:catn + [:cofx :schema.re-frame/cofx] + [:args [:schema [:catn [:community-id :string]]]]] + [:map {:closed true} + [:fx + [:tuple + [:tuple [:= :json-rpc/call] :schema.common/rpc-call]]]]]) + +(rf/reg-event-fx :communities/get-permissioned-balances get-permissioned-balances) + +(defn get-permissioned-balances-success + [{:keys [db]} [community-id response]] + {:db (assoc-in db [:communities/permissioned-balances community-id] response)}) + +(def ^:private ?account-address keyword?) + +(def ^:private ?permissioned-balances-response + [:map-of + ?account-address + [:sequential + [:map + [:type int?] + [:symbol string?] + [:decimals int?] + [:amount string?]]]]) + +(schema/=> get-permissioned-balances-success + [:=> + [:catn + [:cofx :schema.re-frame/cofx] + [:args + [:schema + [:catn + [:community-id string?] + [:response ?permissioned-balances-response]]]]] + map?]) + +(rf/reg-event-fx :communities/get-permissioned-balances-success get-permissioned-balances-success) diff --git a/src/status_im/contexts/communities/actions/addresses_for_permissions/events_test.cljs b/src/status_im/contexts/communities/actions/addresses_for_permissions/events_test.cljs new file mode 100644 index 0000000000..cfb3aef237 --- /dev/null +++ b/src/status_im/contexts/communities/actions/addresses_for_permissions/events_test.cljs @@ -0,0 +1,15 @@ +(ns status-im.contexts.communities.actions.addresses-for-permissions.events-test + (:require + [cljs.test :refer [is deftest]] + [status-im.contexts.communities.actions.addresses-for-permissions.events :as sut])) + +(def community-id "0x1") + +(deftest get-permissioned-balances-test + (let [cofx {:db {}}] + (is (match? {:fx [[:json-rpc/call + [{:method :wakuext_getCommunityPermissionedBalances + :params [{:communityId community-id}] + :on-success [:communities/get-permissioned-balances-success community-id] + :on-error fn?}]]]} + (sut/get-permissioned-balances cofx [community-id]))))) diff --git a/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs b/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs index cd92d8deff..8fb3d79b44 100644 --- a/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs +++ b/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs @@ -3,90 +3,114 @@ [quo.foundations.colors :as colors] [react-native.core :as rn] [status-im.common.not-implemented :as not-implemented] + [status-im.common.resources :as resources] + [status-im.constants :as constants] [status-im.contexts.communities.actions.addresses-for-permissions.style :as style] [status-im.contexts.communities.utils :as communities.utils] [utils.i18n :as i18n] + [utils.money :as money] [utils.re-frame :as rf])) +(defn- balances->components-props + [balances] + (for [{:keys [amount decimals type name] :as balance} balances] + (cond-> balance + true + (assoc :type + (condp = type + constants/community-token-type-erc20 :token + constants/community-token-type-erc721 :collectible + :token)) + + (= type constants/community-token-type-erc721) + (assoc :collectible-name name + :collectible-img-src (resources/get-mock-image :collectible)) + + (= type constants/community-token-type-erc20) + (assoc :amount (str (money/with-precision (money/token->unit amount decimals) 3)) + :token (:symbol balance))))) + (defn- account-item - [item _ _ [selected-addresses community-id]] - [quo/account-permissions - {:account {:name (:name item) - :address (:address item) - :emoji (:emoji item) - :customization-color (:customization-color item)} - :token-details [] - :checked? (contains? selected-addresses (:address item)) - :on-change #(rf/dispatch [:communities/toggle-selected-permission-address - (:address item) community-id]) - :container-style {:margin-bottom 8}}]) + [{:keys [customization-color address name emoji]} _ _ [selected-addresses community-id]] + (let [balances (rf/sub [:communities/permissioned-balances-by-address community-id address])] + [quo/account-permissions + {:account {:name name + :address address + :emoji emoji + :customization-color customization-color} + :token-details (balances->components-props balances) + :checked? (contains? selected-addresses address) + :on-change #(rf/dispatch [:communities/toggle-selected-permission-address + address community-id]) + :container-style {:margin-bottom 8}}])) (defn view [] - (let [{id :community-id} (rf/sub [:get-screen-params]) - {:keys [name color images]} (rf/sub [:communities/community id]) - {:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id]) - accounts (rf/sub [:wallet/accounts-with-customization-color]) - selected-addresses (rf/sub [:communities/selected-permission-addresses id]) - highest-role-text - (i18n/label - (communities.utils/role->translation-key highest-permission-role))] - [rn/safe-area-view {:style style/container} - [quo/drawer-top - {:type :context-tag - :title (i18n/label :t/addresses-for-permissions) - :context-tag-type :community - :community-name name - :button-icon :i/info - :on-button-press not-implemented/alert - :community-logo (get-in images [:thumbnail :uri]) - :customization-color color}] + (let [{id :community-id} (rf/sub [:get-screen-params])] + (rf/dispatch [:communities/get-permissioned-balances id]) + (fn [] + (let [{:keys [name color images]} (rf/sub [:communities/community id]) + {:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id]) + accounts (rf/sub [:wallet/accounts-with-customization-color]) + selected-addresses (rf/sub [:communities/selected-permission-addresses id]) + highest-role-text (i18n/label (communities.utils/role->translation-key + highest-permission-role))] + [rn/safe-area-view {:style style/container} + [quo/drawer-top + {:type :context-tag + :title (i18n/label :t/addresses-for-permissions) + :context-tag-type :community + :community-name name + :button-icon :i/info + :on-button-press not-implemented/alert + :community-logo (get-in images [:thumbnail :uri]) + :customization-color color}] - [rn/flat-list - {:render-fn account-item - :render-data [selected-addresses id] - :content-container-style {:padding 20} - :key-fn :address - :data accounts}] + [rn/flat-list + {:render-fn account-item + :render-data [selected-addresses id] + :content-container-style {:padding 20} + :key-fn :address + :data accounts}] - (when (and highest-permission-role (seq selected-addresses)) - [rn/view - {:style style/highest-role} - [quo/text - {:size :paragraph-2 - :style {:color colors/neutral-50}} - (i18n/label :t/eligible-to-join-as)] - [quo/context-tag - {:type :icon - :icon :i/members - :size 24 - :context highest-role-text}]]) + (when (and highest-permission-role (seq selected-addresses)) + [rn/view + {:style style/highest-role} + [quo/text + {:size :paragraph-2 + :style {:color colors/neutral-50}} + (i18n/label :t/eligible-to-join-as)] + [quo/context-tag + {:type :icon + :icon :i/members + :size 24 + :context highest-role-text}]]) - (when (empty? selected-addresses) - [rn/view - {:style style/error-message} - [quo/icon - :i/info - {:color colors/danger-50 - :size 16}] - [quo/text - {:size :paragraph-2 - :style {:color colors/danger-50}} - (i18n/label :t/no-addresses-selected)]]) + (when (empty? selected-addresses) + [rn/view + {:style style/error-message} + [quo/icon + :i/info + {:color colors/danger-50 + :size 16}] + [quo/text + {:size :paragraph-2 + :style {:color colors/danger-50}} + (i18n/label :t/no-addresses-selected)]]) - [rn/view {:style style/buttons} - [quo/button - {:type :grey - :container-style {:flex 1} - :on-press (fn [] - (rf/dispatch [:communities/reset-selected-permission-addresses id]) - (rf/dispatch [:navigate-back]))} - (i18n/label :t/cancel)] - [quo/button - {:container-style {:flex 1} - :customization-color color - :disabled? (empty? selected-addresses) - :on-press (fn [] - (rf/dispatch [:communities/update-previous-permission-addresses id]) + [rn/view {:style style/buttons} + [quo/button + {:type :grey + :container-style {:flex 1} + :on-press (fn [] + (rf/dispatch [:communities/reset-selected-permission-addresses id]) (rf/dispatch [:navigate-back]))} - (i18n/label :t/confirm-changes)]]])) + (i18n/label :t/cancel)] + [quo/button + {:container-style {:flex 1} + :customization-color color + :disabled? (empty? selected-addresses) + :on-press (fn [] + (rf/dispatch [:communities/update-previous-permission-addresses id]) + (rf/dispatch [:navigate-back]))} + (i18n/label :t/confirm-changes)]]])))) diff --git a/src/status_im/contexts/communities/events.cljs b/src/status_im/contexts/communities/events.cljs index bd6632e392..40ad49d70d 100644 --- a/src/status_im/contexts/communities/events.cljs +++ b/src/status_im/contexts/communities/events.cljs @@ -9,6 +9,7 @@ [schema.core :as schema] [status-im.constants :as constants] [status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events] + status-im.contexts.communities.actions.addresses-for-permissions.events status-im.contexts.communities.actions.community-options.events status-im.contexts.communities.actions.leave.events [status-im.navigation.events :as navigation] diff --git a/src/status_im/subs/communities.cljs b/src/status_im/subs/communities.cljs index da7ab63559..67e6bf618e 100644 --- a/src/status_im/subs/communities.cljs +++ b/src/status_im/subs/communities.cljs @@ -363,6 +363,11 @@ (fn [communities [_ community-id]] (get-in communities [community-id :intro-message]))) +(re-frame/reg-sub :communities/permissioned-balances-by-address + :<- [:communities/permissioned-balances] + (fn [balances [_ community-id account-address]] + (get-in balances [community-id (keyword account-address)]))) + (re-frame/reg-sub :communities/selected-permission-addresses (fn [[_ community-id]] diff --git a/src/status_im/subs/root.cljs b/src/status_im/subs/root.cljs index db168fe887..3c9faa4fee 100644 --- a/src/status_im/subs/root.cljs +++ b/src/status_im/subs/root.cljs @@ -145,6 +145,7 @@ (reg-root-key-sub :communities/collapsed-categories :communities/collapsed-categories) (reg-root-key-sub :communities/selected-tab :communities/selected-tab) (reg-root-key-sub :contract-communities :contract-communities) +(reg-root-key-sub :communities/permissioned-balances :communities/permissioned-balances) ;;activity center (reg-root-key-sub :activity-center :activity-center) diff --git a/status-go-version.json b/status-go-version.json index e213dca903..4aea2b0fc8 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -3,7 +3,7 @@ "_comment": "Instead use: scripts/update-status-go.sh ", "owner": "status-im", "repo": "status-go", - "version": "v0.174.2", - "commit-sha1": "cd228d97dde2063352654f426d7fc50df90c3d30", - "src-sha256": "1kpyyrv0kjzlzmm6mwhh6lv3bilza18ngx1vq1drrp8m8wggwmfa" + "version": "v0.174.3", + "commit-sha1": "c15f9e73654ed2f21887af680d7730dec5bec3e3", + "src-sha256": "09jvamavnkii2fikpz2a5d345aspfp5lzlg5lpymz7lyjif4qn1s" }