-
Notifications
You must be signed in to change notification settings - Fork 985
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
Communities: Show relevant tokens #18636
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: this is a nice way to grab the current event ID. Often the case when we want to log a descriptive error. |
||
{: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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @yqrashawn There's a strong pattern in the way we write schemas for event handlers. We could go just a small step further to help alleviate the verbosity for 95% of our use cases. Something to be discussed, but sharing here to give some visibility of the idea. In the example below, the first argument to (schema/event=> get-permissioned-balances-success
[:=>
[:catn
[:community-id string?]
[:response ?permissioned-balances-response]]
[:map {:closed true}
[:db map?]]]) cc @clauxx There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be great to get rid of the boilerplate, I agree. Not as verbose as events, but for quo components we could do the same and just pass a prop map schema. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we definitely need this. I'm thinking about something like ring's middleware and I checked Malli's schema transformation the other day. There are these If that's what we are using. It would be great. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@yqrashawn Last week I wrote a malli transformer similar to OTOH, transformers may be a bazooka to solve a simple problem of just eliminating the most essential boilerplate to define event handler schemas. For that, we just need a vanilla Clojure function and no need to use specific Malli APIs.
I only know what lenses are and why they exist in functional languages, but I have zero knowledge about this part of Malli. Looks like something to be explored!
I've never used specter outside playground stuff, but it's surely one of a kind Clojure library. A bit too alien if you ask me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Totally agree |
||
[:=> | ||
[: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) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]))))) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI: I'll create a follow-up issue to use the real collectible image. It just didn't seem important for this PR since there's a bunch of things going on in the status-go side. |
||
|
||
(= 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)]]])))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note:
:vector
is rarely the schema we want to use because it will fail when lazy sequences are passed.