Compare commits

...
15 Commits
Author SHA1 Message Date
Ibrkhalil a4568e5f8b Edge case 2023-11-15 11:27:00 +02:00
Ibrkhalil 4fc07bda76 Extract the focusing logic from the data setting logic 2023-11-15 11:21:41 +02:00
Ibrkhalil 17a8824251 refactor variable name 2023-11-15 11:12:33 +02:00
ibrkhalil 3ebf34580a Lintil soup = yummy 2023-11-15 11:12:33 +02:00
ibrkhalil abecc38424 Apply for reply 2023-11-15 11:12:33 +02:00
ibrkhalil 3bbaee2e2f Clauxx comments 2023-11-15 11:12:33 +02:00
Ibrkhalil b9f5f737e6 clean 2023-11-15 11:12:32 +02:00
Ibrkhalil 964b19659d prevent composer when focusing on opening chat with edit/reply 2023-11-15 11:12:32 +02:00
Ibrkhalil bb02d8698d Fix text content when editing and reentering chat 2023-11-15 11:12:32 +02:00
Ulises Manuel 45df308dd0 [#17823] Refactor tokens data app-db (#17880)
* Refactor edit-account view and events:

 - Fix `(fn [])` code style.
 - Avoid overriding clojure.core/type by destructuring the `:type` key.
 - Split the toast callback to a different function.
 - `:wallet/save-account` receives `:on-success` instead of `:callback` to improve readability.

* Refactor app-db for `:wallet/tokens` & `:wallet/tokens-loading?`

- Remove the root sub `:wallet/tokens-loading?`, now it's in app-db in `[:wallet :ui :tokens-loading?]`.
- Remove the root subs `:wallet/tokens`, now the value is returned along with the account data by the sub
  `:wallet/accounts`, it's stored in app-db in `[:wallet :address "0x..." :tokens]`.
- Fix the format of the token data returned by the endpoint `"wallet_getWalletToken"` and the fn `js->clj`,
    - Addresses are no longer keywords (since keywords mustn't start with a number).
    - Keys are now kebab-case.
    - Chain-ids are no longer keywords, now they are integers.
- Update tests.

* Move logic to calculate `:wallet/balances` and change value returned

- Move logic to `status-im2.contexts.wallet.common.utils`
- The `:wallet/balances` value returned by the sub had the following structure:
  [{:address "0x1...", :balance 12345}
   {:address "0x2...", :balance 67890} ...]
  This required a helper function to get the balance for an address (`get-balance-by-address`)
  It has been changed to a map:
  {"0x1..." 12345
   "0x2..." 67890, ...}
  So now we don't need a helper function (just the hashmap itself or `clojure.core/get`).
- Because of the previous change, now the `get-balance-by-address` has been removed.
- The function `get-account-by-address` has zero uses, so it has been removed.
- The test for the sub has been updated.

* Create sub `:wallet/account-cards-data`

This sub returns a vector of maps to render the account cards in the wallet page.
This logic was previously in the `view` namespace, but it was completely calculated from
the subs `:wallet/accounts`, `:wallet/balances` and `:wallet/tokens-loading?`, so it was
clear that's a derived value.
2023-11-14 10:54:26 -06:00
Brian Sztamfater a74c934936 feat: implement summary tag component (#17858)
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-11-14 11:50:58 -03:00
andrey c150070cfe remove empty files 2023-11-13 14:50:45 +01:00
Ibrahem Khalilandbalogunofafrica 1b745857e8 [17634] Start rendering syncing UI ASAP (#17755)
* Start rendering syncing UI ASAP

* Consolidating values

* fix: show syncing ui immediately

* fix: error validation

---------

Co-authored-by: balogunofafrica <balogunakanbi.k@gmail.com>
2023-11-13 12:15:53 +01:00
Omar Basem 87c9946092 Wallet: Keypair Screen (#17775)
* wallet: keypair screen
2023-11-13 14:43:43 +04:00
Omar Basem f3e47ac1a2 Wallet: watch address - select random color (#17859)
Wallet: randomize color picker
2023-11-13 14:25:44 +04:00
48 changed files with 781 additions and 401 deletions
@@ -1,3 +1,3 @@
(ns quo.components.colors.color.constants)
(def ^:const IPHONE_11_PRO_VIEWPORT_WIDTH 375)
(def ^:const color-size 48)
+3 -2
View File
@@ -1,12 +1,13 @@
(ns quo.components.colors.color.style
(:require
[quo.components.colors.color.constants :as constants]
[quo.foundations.colors :as colors]
[utils.responsiveness :as responsiveness]))
(defn color-button-common
[window-width]
{:width 48
:height 48
{:width constants/color-size
:height constants/color-size
:border-width 4
:border-radius 24
:margin-right (-> window-width
@@ -5,10 +5,6 @@
[test-helpers.component :as h]))
(h/describe "color-picker"
(h/test "color picker rendered"
(h/render [color-picker/view])
(-> (h/expect (h/get-all-by-label-text :color-picker-item))
(.toHaveLength 11)))
(h/test "clicks on a color item"
(let [event (h/mock-fn)]
(h/render [color-picker/view {:on-change #(event)}])
@@ -20,11 +16,6 @@
(h/render [color-picker/view {:on-change #(reset! selected %)}])
(h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0))
(-> (h/expect @selected)
(.toStrictEqual :blue))))
(h/test "all of the values of colors-list are rendered"
(h/render [color-picker/view])
(js/Promise.all (map (fn [color]
(h/is-truthy (h/get-all-by-label-text color)))
color-picker/color-list))))
(.toStrictEqual :blue)))))
@@ -1,39 +1,67 @@
(ns quo.components.colors.color-picker.view
(:require
[quo.components.colors.color.constants :as constants]
[quo.components.colors.color.view :as color]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]))
(def color-list
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :flamingo :camel :copper])
(defn- on-change-handler
[selected color-name on-change]
(reset! selected color-name)
(when on-change (on-change color-name)))
(defn view
(defn get-item-layout
[_ index]
#js
{:length constants/color-size
:offset (* (+ constants/color-size 8) index)
:index index})
(defn- view-internal
"Options
- `default-selected` Default selected color name.
- `on-change` Callback called when a color is selected `(fn [color-name])`.
- `blur?` Boolean to enable blur background support.}"
[{:keys [default-selected]}]
[{:keys [default-selected blur? on-change feng-shui? container-style]}]
(let [selected (reagent/atom default-selected)
{window-width :width} (rn/get-window)]
(fn [{:keys [blur? on-change feng-shui? container-style]}]
[rn/scroll-view
{:horizontal true
:shows-horizontal-scroll-indicator false
:content-container-style container-style}
(doall (map-indexed (fn [idx color]
[color/view
{:selected? (= color @selected)
:on-press #(on-change-handler selected % on-change)
:blur? blur?
:key color
:color color
:idx idx
:window-width window-width}])
;; TODO: using :feng-shui? temporarily while b & w is being developed.
;; https://github.com/status-im/status-mobile/discussions/16676
(if feng-shui? (conj color-list :feng-shui) color-list)))])))
{window-width :width} (rn/get-window)
ref (atom nil)]
(rn/use-effect #(js/setTimeout (fn []
(.scrollToIndex ^js @ref
#js
{:animated true
:index (.indexOf colors/account-colors
default-selected)
:viewPosition 0.5}))
50))
[rn/flat-list
{:ref #(reset! ref %)
;; TODO: using :feng-shui? temporarily while b & w is being developed.
;; https://github.com/status-im/status-mobile/discussions/16676
:data (if feng-shui?
(conj colors/account-colors :feng-shui)
colors/account-colors)
:render-fn (fn [color idx]
[color/view
{:selected? (= color @selected)
:on-press (fn [e]
(.scrollToIndex ^js @ref
#js
{:animated true
:index idx
:viewPosition 0.5})
(on-change-handler selected e on-change))
:blur? blur?
:key color
:color color
:idx idx
:window-width window-width}])
:get-item-layout get-item-layout
:horizontal true
:shows-horizontal-scroll-indicator false
:content-container-style container-style}]))
(defn view
[props]
[:f> view-internal props])
@@ -24,9 +24,9 @@
:scroll? - bool (default false) - Whether the iOS Home Indicator should be rendered"
[props]
(let [{:keys [actions description button-one-label button-two-label
button-one-props button-two-props theme scroll? customization-color]}
button-one-props button-two-props theme scroll? customization-color container-style]}
(merge default-props props)]
[:<>
[rn/view {:style container-style}
[rn/view {:style style/buttons-container}
(when (= actions :2-actions)
[button/button
@@ -0,0 +1,53 @@
(ns quo.components.tags.summary-tag.component-spec
(:require
[quo.components.tags.summary-tag.view :as summary-tag]
[test-helpers.component :as h]))
(h/describe "Summary tag component tests"
(h/test "Basic render"
(h/render [summary-tag/view])
(h/is-truthy (h/query-by-label-text :container)))
(h/test "Account view render"
(h/render [summary-tag/view
{:type :account
:label "Alice's Account"
:customization-color "#ff0000"
:emoji "🎉"}])
(h/is-truthy (h/get-by-text "Alice's Account")))
(h/test "Network view render"
(h/render [summary-tag/view
{:type :network
:label "Ethereum Network"
:image-source "path/to/ethereum-logo.png"}])
(h/is-truthy (h/get-by-text "Ethereum Network")))
(h/test "Saved address view render"
(h/render [summary-tag/view
{:type :saved-address
:label "Charlie's Wallet"
:customization-color "#00ff00"}])
(h/is-truthy (h/get-by-text "Charlie's Wallet")))
(h/test "Collectible view render"
(h/render [summary-tag/view
{:type :collectible
:label "Rare Artifact"
:image-source "path/to/artifact-image.png"}])
(h/is-truthy (h/get-by-text "Rare Artifact")))
(h/test "User view render"
(h/render [summary-tag/view
{:type :user
:label "Bob Smith"
:image-source "path/to/profile-pic.png"
:customization-color "#0000ff"}])
(h/is-truthy (h/get-by-text "Bob Smith")))
(h/test "Token view render"
(h/render [summary-tag/view
{:type :token
:label "1,000 SNT"
:image-source "path/to/token-image.png"}])
(h/is-truthy (h/get-by-text "1,000 SNT"))))
@@ -0,0 +1,29 @@
(ns quo.components.tags.summary-tag.style
(:require
[quo.foundations.colors :as colors]))
(defn main
[{:keys [type theme customization-color]}]
{:justify-content :center
:align-items :center
:height 32
:padding-left 4
:padding-right 10
:flex-direction :row
:border-radius (if (#{:account :collectible} type) 10 16)
:background-color (colors/resolve-color customization-color theme 10)})
(defn label
[type theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)
:margin-left (if (= type :address) 6 4)})
(def collectible-image
{:width 24
:height 24
:border-radius 10})
(def token-image
{:width 24
:height 24
:border-radius 12})
@@ -0,0 +1,67 @@
(ns quo.components.tags.summary-tag.view
(:require
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
[quo.components.markdown.text :as text]
[quo.components.tags.summary-tag.style :as style]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]))
(defn- left-view
[{:keys [label type customization-color emoji image-source]}]
(case type
:account
[account-avatar/view
{:customization-color customization-color
:size 24
:emoji emoji
:type :default}]
:network
[rn/image
{:source image-source
:style style/token-image}]
:saved-address
[wallet-user-avatar/wallet-user-avatar
{:full-name label
:size :size-24
:customization-color customization-color}]
:collectible
[rn/image
{:source image-source
:style style/collectible-image}]
:user
[user-avatar/user-avatar
{:full-name label
:size :xs
:profile-picture image-source
:customization-color customization-color}]
:token
[rn/image
{:source image-source
:style style/token-image}]
nil))
(defn- view-internal
"Options:
- :label - string - tag label
- :customization-color - color - It will be passed down to components that
should vary based on a custom color.
- :type - :token / :user / :collectible / :saved-address / :network / :account
- :emoji - string - emoji used for displaying account avatar
- :image-source - resource - image to display on :network, :collectible :user and :token
- :theme - :light / :dark"
[{:keys [label customization-color type theme]
:as props
:or {customization-color colors/neutral-80-opa-5}}]
[rn/view
{:accessibility-label :container
:style (style/main (assoc props :customization-color customization-color))}
[left-view props]
[text/text
{:style (style/label type theme)
:weight :semi-bold
:size :heading-1} label]])
(def view (quo.theme/with-theme view-internal))
+25 -13
View File
@@ -1,5 +1,6 @@
(ns quo.components.text-combinations.view
(:require
[quo.components.buttons.button.view :as button]
[quo.components.markdown.text :as text]
[quo.components.text-combinations.style :as style]
[quo.theme :as theme]
@@ -23,20 +24,31 @@
avatar
title-accessibility-label
description
description-accessibility-label]}]
description-accessibility-label
button-icon
button-on-press
customization-color]}]
[rn/view {:style container-style}
[rn/view {:style style/title-container}
(when avatar
[rn/view {:style style/avatar-container}
[icon avatar 32]])
[text/text
{:accessibility-label title-accessibility-label
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:size :heading-1}
title]]
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[rn/view {:style style/title-container}
(when avatar
[rn/view {:style style/avatar-container}
[icon avatar 32]])
[text/text
{:accessibility-label title-accessibility-label
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:size :heading-1}
title]]
(when button-icon
[button/button
{:icon-only? true
:on-press button-on-press
:customization-color customization-color
:size 32} button-icon])]
(when description
[text/text
{:accessibility-label description-accessibility-label
+2 -4
View File
@@ -4,8 +4,7 @@
(defn container
[{:keys [blur? customization-color theme selected?]}]
{:flex 1
:border-radius 20
{:border-radius 16
:border-width 1
:border-color (if selected?
(if blur?
@@ -28,5 +27,4 @@
(def title-container
{:flex-direction :row
:align-items :center
:justify-content :space-between
:flex 1})
:justify-content :space-between})
+7 -4
View File
@@ -27,13 +27,16 @@
(defn avatar
[{{:keys [full-name]} :details
avatar-type :type
customization-color :customization-color}]
customization-color :customization-color
profile-picture :profile-picture}]
(if (= avatar-type :default-keypair)
[user-avatar/user-avatar
{:full-name full-name
:ring? true
:size :small
:customization-color customization-color}]
:status-indicator? false
:customization-color customization-color
:profile-picture profile-picture}]
[icon-avatar/icon-avatar
{:size :size-32
:icon :i/placeholder
@@ -84,9 +87,9 @@
(defn- view-internal
[]
(let [selected? (reagent/atom true)]
(fn [{:keys [accounts action] :as props}]
(fn [{:keys [accounts action container-style] :as props}]
[rn/pressable
{:style (style/container (merge props {:selected? @selected?}))
{:style (merge (style/container (merge props {:selected? @selected?})) container-style)
:on-press #(when (= action :selector) (reset! selected? (not @selected?)))}
[rn/view {:style style/header-container}
[avatar props]
+2
View File
@@ -131,6 +131,7 @@
quo.components.tags.number-tag.view
quo.components.tags.permission-tag
quo.components.tags.status-tags
quo.components.tags.summary-tag.view
quo.components.tags.tag
quo.components.tags.tags
quo.components.tags.tiny-tag.view
@@ -360,6 +361,7 @@
(def number-tag quo.components.tags.number-tag.view/view)
(def permission-tag quo.components.tags.permission-tag/tag)
(def status-tag quo.components.tags.status-tags/status-tag)
(def summary-tag quo.components.tags.summary-tag.view/view)
(def tag quo.components.tags.tag/tag)
(def tags quo.components.tags.tags/tags)
(def tiny-tag quo.components.tags.tiny-tag.view/view)
+1
View File
@@ -73,6 +73,7 @@
[quo.components.switchers.group-messaging-card.component-spec]
[quo.components.tags.network-tags.component-spec]
[quo.components.tags.status-tags-component-spec]
[quo.components.tags.summary-tag.component-spec]
[quo.components.tags.tiny-tag.component-spec]
[quo.components.wallet.account-card.component-spec]
[quo.components.wallet.account-origin.component-spec]
+3
View File
@@ -4,6 +4,9 @@
[quo.theme :as theme]
[react-native.platform :as platform]))
(def account-colors
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :flamingo :camel :copper])
(defn alpha
[value opacity]
(when value
+3
View File
@@ -29,3 +29,6 @@
(testing
"when using opacity theme is ignored and uses the light suffix resolver"
(is (colors/resolve-color :blue :light 10) (colors/resolve-color :blue :dark 10))))
(deftest test-account-colors-customization
(is (every? #(contains? colors/customization %) colors/account-colors)))
+9 -8
View File
@@ -107,14 +107,15 @@
[{:keys [db] :as cofx} message]
(let [current-chat-id (:current-chat-id db)
text (get-in message [:content :text])]
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))
:dispatch [:mention/to-input-field text current-chat-id]}))
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))
:dispatch-n [[:chat.ui/set-chat-input-text nil current-chat-id]
[:mention/to-input-field text current-chat-id]]}))
(rf/defn show-contact-request-input
"Sets reference to previous chat message and focuses on input"
@@ -106,34 +106,37 @@
(defn use-edit
[{:keys [input-ref]}
{:keys [text-value saved-cursor-position]}
{:keys [edit]}]
{:keys [edit]}
messages-list-on-layout-finished?]
(rn/use-effect
(fn []
(let [edit-text (get-in edit [:content :text])
text-value-count (count @text-value)]
(when (and edit @input-ref)
;; A small setTimeout is necessary to ensure the statement is enqueued and will get executed
;; ASAP.
;; https://github.com/software-mansion/react-native-screens/issues/472
(js/setTimeout #(.focus ^js @input-ref) 250)
(.setNativeProps ^js @input-ref (clj->js {:text edit-text}))
(reset! text-value edit-text)
(reset! saved-cursor-position (if (zero? text-value-count)
(when @messages-list-on-layout-finished?
;; A small setTimeout is necessary to ensure the statement is enqueued and will get
;; executed
;; ASAP. Https://github.com/software-mansion/react-native-screens/issues/472
(reset! saved-cursor-position (if edit-text
(count edit-text)
text-value-count)))))
text-value-count))
(js/setTimeout #(.focus ^js @input-ref) 250))
(when (and edit @input-ref)
(.setNativeProps ^js @input-ref (clj->js {:text edit-text}))
(reset! text-value edit-text))))
[(:message-id edit)]))
(defn use-reply
[{:keys [input-ref]}
{:keys [container-opacity]}
{:keys [reply]}]
{:keys [reply]}
messages-list-on-layout-finished?]
(rn/use-effect
(fn []
(when reply
(reanimated/animate container-opacity 1))
(when (and reply @input-ref)
(js/setTimeout #(.focus ^js @input-ref) 250)))
[(:message-id reply)]))
(when (and reply @input-ref @messages-list-on-layout-finished?)
(js/setTimeout #(.focus ^js @input-ref) 250))))
[(:message-id reply)])
(defn edit-mentions
[{:keys [input-ref]} {:keys [text-value cursor-position]} {:keys [input-with-mentions]}]
@@ -33,7 +33,8 @@
blur-height
opacity
background-y
theme]} props state]
theme
messages-list-on-layout-finished?]} props state]
(let [{:keys [chat-screen-loaded?]
:as subscriptions} (utils/init-subs)
content-height (reagent/atom (or (:input-content-height ; Actual text height
@@ -73,8 +74,8 @@
animations
dimensions
subscriptions)
(effects/use-edit props state subscriptions)
(effects/use-reply props animations subscriptions)
(effects/use-edit props state subscriptions messages-list-on-layout-finished?)
(effects/use-reply props animations subscriptions messages-list-on-layout-finished?)
(effects/update-input-mention props state subscriptions)
(effects/edit-mentions props state subscriptions)
(effects/link-previews props state animations subscriptions)
@@ -147,7 +148,8 @@
subscriptions]]]]]))
(defn composer
[{:keys [insets scroll-to-bottom-fn show-floating-scroll-down-button?]}]
[{:keys [insets scroll-to-bottom-fn show-floating-scroll-down-button?
messages-list-on-layout-finished?]}]
(let [window-height (:height (rn/get-window))
theme (quo.theme/use-theme-value)
opacity (reanimated/use-shared-value 0)
@@ -161,7 +163,8 @@
:blur-height blur-height
:opacity opacity
:background-y background-y
:theme theme}
:theme theme
:messages-list-on-layout-finished? messages-list-on-layout-finished?}
props (utils/init-non-reactive-state)
state (utils/init-reactive-state)]
[rn/view (when platform/ios? {:style {:z-index 1}})
@@ -298,7 +298,7 @@
(defn f-messages-list-content
[{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown? inner-state-atoms
big-name-visible? animate-topbar-opacity? composer-active?
big-name-visible? animate-topbar-opacity? composer-active? messages-list-on-layout-finished?
on-end-reached? animate-topbar-name?]}]
(rn/use-effect (fn []
(if (and (not @on-end-reached?)
@@ -412,6 +412,7 @@
;;TODO(rasom) https://github.com/facebook/react-native/issues/30034
:inverted (when platform/ios? true)
:on-layout (fn [e]
(reset! messages-list-on-layout-finished? true)
(let [layout-height (oops/oget e
"nativeEvent.layout.height")]
(reset! messages-view-height layout-height)))
+18 -15
View File
@@ -15,7 +15,7 @@
(defn f-chat
[{:keys [show-floating-scroll-down-button? animate-topbar-name?
big-name-visible? animate-topbar-opacity? on-end-reached?]
big-name-visible? animate-topbar-opacity? on-end-reached? messages-list-on-layout-finished?]
:as inner-state-atoms}]
(let [insets (safe-area/get-insets)
scroll-y (reanimated/use-shared-value 0)
@@ -53,18 +53,19 @@
:keyboard-vertical-offset (- (:bottom insets))}
[list.view/message-list-content-view
{:chat chat
:insets insets
:scroll-y scroll-y
:content-height content-height
:cover-bg-color :turquoise
:keyboard-shown? keyboard-shown
:inner-state-atoms inner-state-atoms
:animate-topbar-name? animate-topbar-name?
:big-name-visible? big-name-visible?
:animate-topbar-opacity? animate-topbar-opacity?
:composer-active? focused?
:on-end-reached? on-end-reached?}]
{:chat chat
:insets insets
:scroll-y scroll-y
:content-height content-height
:cover-bg-color :turquoise
:keyboard-shown? keyboard-shown
:inner-state-atoms inner-state-atoms
:animate-topbar-name? animate-topbar-name?
:big-name-visible? big-name-visible?
:animate-topbar-opacity? animate-topbar-opacity?
:composer-active? focused?
:on-end-reached? on-end-reached?
:messages-list-on-layout-finished? messages-list-on-layout-finished?}]
[messages.navigation/navigation-view
{:scroll-y scroll-y
@@ -86,7 +87,8 @@
[:f> composer.view/composer
{:insets insets
:scroll-to-bottom-fn list.view/scroll-to-bottom
:show-floating-scroll-down-button? show-floating-scroll-down-button?}]
:show-floating-scroll-down-button? show-floating-scroll-down-button?
:messages-list-on-layout-finished? messages-list-on-layout-finished?}]
[contact-requests.bottom-drawer/view chat-id contact-request-state group-chat]))]))
(defn chat
@@ -99,5 +101,6 @@
:animate-topbar-name? (reagent/atom false)
:big-name-visible? (reagent/atom :initial-render)
:animate-topbar-opacity? (reagent/atom false)
:on-end-reached? (reagent/atom false)}]
:on-end-reached? (reagent/atom false)
:messages-list-on-layout-finished? (reagent/atom false)}]
[:f> f-chat inner-state-atoms]))
@@ -73,12 +73,12 @@
(data-store.settings/rpc->settings settings)
profile-overview (profile.rpc/rpc->profiles-overview account)]
(rf/merge cofx
{:db (assoc db
:chats/loading? true
:networks/current-network current-network
:wallet/tokens-loading? true
:networks/networks (merge networks config/default-networks-by-id)
:profile/profile (merge profile-overview settings))}
{:db (-> db
(assoc :chats/loading? true
:networks/current-network current-network
:networks/networks (merge networks config/default-networks-by-id)
:profile/profile (merge profile-overview settings))
(assoc-in [:wallet :ui :tokens-loading?] true))}
(notifications/load-preferences)
(data-store.chats/fetch-chats-preview
{:on-success
@@ -153,6 +153,7 @@
[status-im2.contexts.quo-preview.tags.number-tag :as number-tag]
[status-im2.contexts.quo-preview.tags.permission-tag :as permission-tag]
[status-im2.contexts.quo-preview.tags.status-tags :as status-tags]
[status-im2.contexts.quo-preview.tags.summary-tag :as summary-tag]
[status-im2.contexts.quo-preview.tags.tag :as tag]
[status-im2.contexts.quo-preview.tags.tags :as tags]
[status-im2.contexts.quo-preview.tags.tiny-tag :as tiny-tag]
@@ -433,6 +434,8 @@
:component permission-tag/view}
{:name :status-tags
:component status-tags/view}
{:name :summary-tag
:component summary-tag/view}
{:name :tag
:component tag/view}
{:name :tags
@@ -0,0 +1,66 @@
(ns status-im2.contexts.quo-preview.tags.summary-tag
(:require
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(defn data
[type]
(case type
:token
{:customization-color "#9999991A"
:label "150 ETH"
:image-source (quo.resources/get-token :eth)}
:address
{:label "0x39c...Bd2"}
:user
{:image-source (resources/mock-images :user-picture-male4)
:customization-color :blue
:label "Mark Libot"}
:collectible
{:label "Isekai #1"
:image-source (resources/mock-images :collectible2)
:customization-color :yellow}
:network
{:image-source (quo.resources/get-network :ethereum)
:label "Mainnet"}
:saved-address
{:customization-color :flamingo
:label "Peter Lambo"}
:account
{:label "Account"
:emoji "🍿"
:customization-color :purple}))
(def descriptor
[{:key :type
:type :select
:options [{:value "Token"
:key :token}
{:value "Address"
:key :address}
{:value "User"
:key :user}
{:value "Collectible"
:key :collectible}
{:value "Network"
:key :network}
{:value "Saved address"
:key :saved-address}
{:value "Account"
:key :account}]}])
(defn view
[]
(let [state (reagent/atom
(merge {:type :token}
(data :token)))]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor}
[rn/view {:style {:align-items :center}}
[quo/summary-tag (merge @state (data (:type @state)))]]])))
@@ -1,6 +1,7 @@
(ns status-im2.contexts.quo-preview.wallet.keypair
(:require
[quo.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
@@ -101,8 +102,9 @@
:component-container-style {:padding-vertical 30
:flex-direction :row
:justify-content :center}}
[quo/keypair
(merge
@state
{:details (if (= (:type @state) :default-keypair) default-details other-details)
:accounts (get-accounts (:blur? @state))})]])))
[rn/view {:style {:flex 1}}
[quo/keypair
(merge
@state
{:details (if (= (:type @state) :default-keypair) default-details other-details)
:accounts (get-accounts (:blur? @state))})]]])))
+29 -9
View File
@@ -2,6 +2,7 @@
(:require
[clojure.string :as string]
[native-module.core :as native-module]
[quo.foundations.colors :as colors]
[re-frame.core :as re-frame]
[react-native.platform :as platform]
[status-im.data-store.settings :as data-store.settings]
@@ -36,6 +37,26 @@
:custom-bootnodes-enabled? false}}]
(node/get-multiaccount-node-config db)))
(defn- extract-error
[json-str]
(-> json-str
transforms/json->clj
(get :error "")
not-empty))
(defn- input-connection-string-callback
[res]
(log/info "[local-pairing] input-connection-string-for-bootstrapping callback"
{:response res
:event :syncing/input-connection-string-for-bootstrapping})
(let [error (when (extract-error res)
(str "generic-error: " res))]
(when (some? error)
(rf/dispatch [:toasts/upsert
{:icon :i/alert
:icon-color colors/danger-50
:text error}]))))
(rf/defn preflight-outbound-check-for-local-pairing
{:events [:syncing/preflight-outbound-check]}
[_ set-checks-passed]
@@ -60,19 +81,18 @@
(fn [final-node-config]
(let [config-map (.stringify js/JSON
(clj->js
{:receiverConfig {:kdfIterations config/default-kdf-iterations
:nodeConfig final-node-config
:settingCurrentNetwork config/default-network
:deviceType platform/os
:deviceName
(native-module/get-installation-name)}}))]
{:receiverConfig
{:kdfIterations config/default-kdf-iterations
:nodeConfig final-node-config
:settingCurrentNetwork config/default-network
:deviceType platform/os
:deviceName
(native-module/get-installation-name)}}))]
(rf/dispatch [:syncing/update-role constants/local-pairing-role-receiver])
(native-module/input-connection-string-for-bootstrapping
connection-string
config-map
#(log/info "Initiated local pairing"
{:response %
:event :syncing/input-connection-string-for-bootstrapping}))))]
input-connection-string-callback)))]
(native-module/prepare-dir-and-update-config "" default-node-config-string callback)))
(rf/defn preparations-for-connection-string
@@ -62,10 +62,11 @@
{:content buy-drawer}])
:bridge-action #(rf/dispatch [:open-modal :wallet-bridge])}]
[quo/tabs
{:style style/tabs
:size 32
:default-active @selected-tab
:data tabs-data
:on-change #(reset! selected-tab %)
:scrollable? true}]
{:style style/tabs
:size 32
:default-active @selected-tab
:data tabs-data
:on-change #(reset! selected-tab %)
:scrollable? true
:scroll-on-press? true}]
[tabs/view {:selected-tab @selected-tab}]]))))
@@ -1,4 +1,4 @@
(ns status-im2.contexts.wallet.add-watch-only-account.style)
(ns status-im2.contexts.wallet.add-address-to-watch.confirm-address.style)
(def container
{:flex 1})
@@ -1,13 +1,14 @@
(ns status-im2.contexts.wallet.add-watch-only-account.views
(ns status-im2.contexts.wallet.add-address-to-watch.confirm-address.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[re-frame.core :as re-frame]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.emoji-picker.utils :as emoji-picker.utils]
[status-im2.contexts.wallet.add-watch-only-account.style :as style]
[status-im2.contexts.wallet.add-address-to-watch.confirm-address.style :as style]
[status-im2.contexts.wallet.common.screen-base.create-or-edit-account.view :as
create-or-edit-account]
[utils.i18n :as i18n]
@@ -20,7 +21,7 @@
account-name (reagent/atom (i18n/label :t/default-account-name
{:number (inc number-of-accounts)}))
address-title (i18n/label :t/watch-address)
account-color (reagent/atom :blue)
account-color (reagent/atom (rand-nth colors/account-colors))
account-emoji (reagent/atom (emoji-picker.utils/random-emoji))
on-change-name #(reset! account-name %)
on-change-color #(reset! account-color %)
@@ -57,4 +58,4 @@
:container-style style/data-item
:on-press #(js/alert "To be implemented")}]]])))
(def address-add-edit (quo.theme/with-theme view-internal))
(def view (quo.theme/with-theme view-internal))
@@ -1,4 +1,4 @@
(ns status-im2.contexts.wallet.select-address-to-watch.style)
(ns status-im2.contexts.wallet.add-address-to-watch.style)
(def header-container
{:margin-horizontal 20
@@ -10,9 +10,8 @@
:padding-horizontal 20
:align-items :flex-end})
(defn button-container
[bottom]
(def button-container
{:position :absolute
:bottom (- bottom 22)
:bottom 22
:left 20
:right 20})
@@ -1,4 +1,4 @@
(ns status-im2.contexts.wallet.select-address-to-watch.view
(ns status-im2.contexts.wallet.add-address-to-watch.view
(:require
[clojure.string :as string]
[quo.core :as quo]
@@ -6,22 +6,18 @@
[re-frame.core :as re-frame]
[react-native.clipboard :as clipboard]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.contexts.wallet.select-address-to-watch.style :as style]
[status-im2.contexts.wallet.add-address-to-watch.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view-internal
[]
(let [top (safe-area/get-top)
bottom (safe-area/get-bottom)
input-value (reagent/atom "")
(let [input-value (reagent/atom "")
customization-color (rf/sub [:profile/customization-color])]
(fn []
[rn/view
{:style {:flex 1
:margin-top top}}
{:style {:flex 1}}
[quo/page-nav
{:type :no-title
:icon-name :i/close
@@ -48,9 +44,9 @@
{:customization-color customization-color
:disabled? (clojure.string/blank? @input-value)
:on-press #(re-frame/dispatch [:navigate-to
:address-to-watch-edit
:confirm-address-to-watch
{:address @input-value}])
:container-style (style/button-container bottom)}
:container-style style/button-container}
(i18n/label :t/continue)]])))
(def view (quo.theme/with-theme view-internal))
@@ -58,7 +58,8 @@
[quo/section-label
{:section (i18n/label :t/colour)
:container-style style/section-container}]
[rn/view {:style style/color-picker-container}
[rn/view
{:style style/color-picker-container}
[quo/color-picker
{:default-selected account-color
:on-change on-change-color
@@ -1,22 +1,12 @@
(ns status-im2.contexts.wallet.common.utils
(:require [clojure.string :as string]
[status-im2.constants :as constants]))
[status-im2.constants :as constants]
[utils.number]))
(defn get-first-name
[full-name]
(first (string/split full-name #" ")))
(defn get-balance-by-address
[balances address]
(->> balances
(filter #(= (:address %) address))
first
:balance))
(defn get-account-by-address
[accounts address]
(some #(when (= (:address %) address) %) accounts))
(defn prettify-balance
[balance]
(str "$" (.toFixed (if (number? balance) balance 0) 2)))
@@ -24,7 +14,6 @@
(defn get-derivation-path
[number-of-accounts]
(str constants/path-wallet-root "/" number-of-accounts))
(defn format-derivation-path
[path]
(string/replace path "/" " / "))
@@ -33,3 +22,24 @@
[number-of-accounts]
(let [path (get-derivation-path number-of-accounts)]
(format-derivation-path path)))
(defn- calculate-raw-balance
[raw-balance decimals]
(if-let [n (utils.number/parse-int raw-balance nil)]
(/ n (Math/pow 10 (utils.number/parse-int decimals)))
0))
(defn- total-token-value-in-all-chains
[{:keys [balances-per-chain decimals]}]
(->> balances-per-chain
(vals)
(map #(calculate-raw-balance (:raw-balance %) decimals))
(reduce +)))
(defn calculate-balance
[tokens-in-account]
(->> tokens-in-account
(map (fn [token]
(* (total-token-value-in-all-chains token)
(-> token :market-values-per-currency :usd :price))))
(reduce +)))
@@ -0,0 +1,12 @@
(ns status-im2.contexts.wallet.create-account.select-keypair.style)
(def header-container
{:margin-horizontal 20
:margin-top 12
:margin-bottom 20})
(def bottom-action-container
{:position :absolute
:bottom 0
:left 0
:right 0})
@@ -0,0 +1,62 @@
(ns status-im2.contexts.wallet.create-account.select-keypair.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im2.contexts.profile.utils :as profile.utils]
[status-im2.contexts.wallet.create-account.select-keypair.style :as style]
[utils.address :as utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def accounts
[{:account-props {:customization-color :turquoise
:size 32
:emoji "\uD83C\uDFB2"
:type :default
:name "Trip to Vegas"
:address "0x0ah...71a"}
:networks [{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "opt"}]
:state :default
:action :none}])
(defn view
[]
(let [{:keys [public-key compressed-key
customization-color]} (rf/sub [:profile/profile])
display-name (first (rf/sub [:contacts/contact-two-names-by-identity
public-key]))
profile-with-image (rf/sub [:profile/profile-with-image])
profile-picture (profile.utils/photo profile-with-image)]
[rn/view {:style {:flex 1}}
[quo/page-nav
{:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])
:accessibility-label :top-bar}]
[quo/text-combinations
{:container-style style/header-container
:title (i18n/label :t/keypairs)
:description (i18n/label :t/keypairs-description)
:button-icon :i/add
:button-on-press #(js/alert "not implemented")
:customization-color customization-color}]
[quo/keypair
(merge
{:customization-color customization-color
:profile-picture profile-picture
:status-indicator false
:type :default-keypair
:stored :on-device
:on-options-press #(js/alert "Options pressed")
:action :selector
:blur? false
:details {:full-name display-name
:address (utils/get-shortened-compressed-key compressed-key)}
:accounts accounts
:container-style {:margin-horizontal 20
:margin-vertical 8}})]
[quo/bottom-actions
{:button-one-label (i18n/label :t/confirm-account-origin)
:button-one-props {:disabled? true
:customization-color customization-color}
:container-style style/bottom-action-container}]]))
@@ -1,6 +1,8 @@
(ns status-im2.contexts.wallet.create-account.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
@@ -12,7 +14,8 @@
[status-im2.contexts.wallet.create-account.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.responsiveness :refer [iphone-11-Pro-20-pixel-from-width]]))
[utils.responsiveness :refer [iphone-11-Pro-20-pixel-from-width]]
[utils.string]))
(defn keypair-string
[full-name]
@@ -20,30 +23,34 @@
(i18n/label :t/keypair-title {:name first-name})))
(defn get-keypair-data
[name derivation-path]
[name derivation-path account-color]
[{:title (keypair-string name)
:left-icon :i/placeholder
:image :avatar
:image-props {:full-name (utils.string/get-initials name 1)
:size :xxs
:customization-color account-color}
:action :button
:action-props {:on-press #(js/alert "Button pressed!")
:action-props {:on-press #(rf/dispatch [:navigate-to :wallet-select-keypair])
:button-text (i18n/label :t/edit)
:alignment :flex-start}
:description :text
:description-props {:text (i18n/label :t/on-device)}}
{:title (i18n/label :t/derivation-path)
:image :icon
:image-props :i/derivated-path
:action :button
:action-props {:on-press #(rf/dispatch [:navigate-to :wallet-edit-derivation-path])
:action-props {:on-press #(js/alert "Button pressed!")
:button-text (i18n/label :t/edit)
:icon-left :i/placeholder
:alignment :flex-start}
:left-icon :i/derivated-path
:description :text
:description-props {:text derivation-path}}])
:description-props {:text (string/replace derivation-path #"/" " / ")}}])
(defn- view-internal
[]
(let [top (safe-area/get-top)
bottom (safe-area/get-bottom)
account-color (reagent/atom :blue)
account-color (reagent/atom (rand-nth colors/account-colors))
emoji (reagent/atom (emoji-picker.utils/random-emoji))
number-of-accounts (count (rf/sub [:wallet/accounts]))
account-name (reagent/atom (i18n/label :t/default-account-name
@@ -106,7 +113,7 @@
[quo/category
{:list-type :settings
:label (i18n/label :t/origin)
:data (get-keypair-data primary-name @derivation-path)}]
:data (get-keypair-data primary-name @derivation-path @account-color)}]
[standard-auth/view
{:size :size-48
:track-text (i18n/label :t/slide-to-create-account)
@@ -4,29 +4,33 @@
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.wallet.common.screen-base.create-or-edit-account.view :as
create-or-edit-account]
[status-im2.contexts.wallet.common.sheets.network-preferences.view :as network-preferences]
[status-im2.contexts.wallet.common.screen-base.create-or-edit-account.view
:as create-or-edit-account]
[status-im2.contexts.wallet.common.sheets.network-preferences.view
:as network-preferences]
[status-im2.contexts.wallet.edit-account.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- show-save-account-toast
[updated-key theme]
(let [message (case updated-key
:name :t/edit-wallet-account-name-updated-message
:color :t/edit-wallet-account-colour-updated-message
:emoji :t/edit-wallet-account-emoji-updated-message
nil)]
(rf/dispatch [:toasts/upsert
{:id :edit-account
:icon :i/correct
:icon-color (colors/resolve-color :success theme)
:text (i18n/label message)}])))
(defn- save-account
[{:keys [theme type value account]}]
(let [edited-account-data (assoc account type value)
message (case type
:name :t/edit-wallet-account-name-updated-message
:color :t/edit-wallet-account-colour-updated-message
:emoji :t/edit-wallet-account-emoji-updated-message
nil)
callback #(rf/dispatch [:toasts/upsert
{:id :edit-account
:icon :i/correct
:icon-color (colors/resolve-color :success theme)
:text (i18n/label message)}])]
[{:keys [account updated-key new-value theme]}]
(let [edited-account-data (assoc account updated-key new-value)]
(rf/dispatch [:wallet/save-account
{:account edited-account-data
:callback callback}])))
{:account edited-account-data
:on-success #(show-save-account-toast updated-key theme)}])))
(defn- view-internal
[{:keys [theme]}]
@@ -34,22 +38,22 @@
show-confirm-button? (reagent/atom false)
on-change-color (fn [edited-color {:keys [color] :as account}]
(when (not= edited-color color)
(save-account {:account account
:type :color
:value edited-color
:theme theme})))
(save-account {:account account
:updated-key :color
:new-value edited-color
:theme theme})))
on-change-emoji (fn [edited-emoji {:keys [emoji] :as account}]
(when (not= edited-emoji emoji)
(save-account {:account account
:type :emoji
:value edited-emoji
:theme theme})))
(save-account {:account account
:updated-key :emoji
:new-value edited-emoji
:theme theme})))
on-confirm-name (fn [account]
(rn/dismiss-keyboard!)
(save-account {:account account
:type :name
:value @edited-account-name
:theme theme}))]
(save-account {:account account
:updated-key :name
:new-value @edited-account-name
:theme theme}))]
(fn []
(let [{:keys [name emoji address color]
:as account} (rf/sub [:wallet/current-viewing-account])
@@ -82,17 +86,18 @@
:right-icon :i/advanced
:card? true
:title (i18n/label :t/address)
:custom-subtitle (fn [] [quo/address-text
{:networks [{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "opt"}
{:network-name :arbitrum :short-name "arb1"}]
:address address
:format :long}])
:custom-subtitle (fn []
[quo/address-text
{:networks [{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "opt"}
{:network-name :arbitrum :short-name "arb1"}]
:address address
:format :long}])
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [network-preferences/view
{:on-save #(js/alert
"calling on save")}])}]))
{:content (fn []
[network-preferences/view
{:on-save #(js/alert "calling on save")}])}]))
:container-style style/data-item}]]))))
(def view (quo.theme/with-theme view-internal))
+43 -18
View File
@@ -11,6 +11,7 @@
[taoensso.timbre :as log]
[utils.ethereum.chain :as chain]
[utils.i18n :as i18n]
[utils.number]
[utils.re-frame :as rf]
[utils.security.core :as security]
[utils.transforms :as types]))
@@ -40,7 +41,8 @@
{:db (update db :wallet dissoc :current-viewing-account-address)
:fx [[:dispatch [:navigate-back]]]}))
(rf/reg-event-fx :wallet/get-accounts-success
(rf/reg-event-fx
:wallet/get-accounts-success
(fn [{:keys [db]} [accounts]]
(let [wallet-db (get db :wallet)
new-account? (:new-account? wallet-db)
@@ -61,7 +63,8 @@
{:dispatch [:wallet/navigate-to-account navigate-to-account]
:ms 300}]])))))
(rf/reg-event-fx :wallet/get-accounts
(rf/reg-event-fx
:wallet/get-accounts
(fn [_]
{:fx [[:json-rpc/call
[{:method "accounts_getAccounts"
@@ -72,35 +75,54 @@
(rf/reg-event-fx
:wallet/save-account
(fn [_ [{:keys [account callback]}]]
(fn [_ [{:keys [account on-success]}]]
{:fx [[:json-rpc/call
[{:method "accounts_saveAccount"
:params [(data-store/<-account account)]
:on-success (fn []
(rf/dispatch [:wallet/get-accounts])
(when (fn? callback)
(callback)))
(when (fn? on-success)
(on-success)))
:on-error #(log/info "failed to save account "
{:error %
:event :wallet/save-account})}]]]}))
(rf/reg-event-fx :wallet/get-wallet-token
(rf/reg-event-fx
:wallet/get-wallet-token
(fn [{:keys [db]}]
(let [addresses (map :address (vals (get-in db [:wallet :accounts])))]
(let [addresses (->> (get-in db [:wallet :accounts])
vals
(map :address))]
{:fx [[:json-rpc/call
[{:method "wallet_getWalletToken"
:params [addresses]
:on-success [:wallet/get-wallet-token-success]
:on-success [:wallet/store-wallet-token]
:on-error #(log/info "failed to get wallet token "
{:error %
:event :wallet/get-wallet-token
:params addresses})}]]]})))
(rf/reg-event-fx :wallet/get-wallet-token-success
(fn [{:keys [db]} [tokens]]
{:db (assoc db
:wallet/tokens tokens
:wallet/tokens-loading? false)}))
(defn- fix-chain-id-keys
[token]
(update token :balances-per-chain update-keys (comp utils.number/parse-int name)))
(rf/reg-event-fx
:wallet/store-wallet-token
(fn [{:keys [db]} [raw-tokens-data]]
(let [tokens (-> raw-tokens-data
(update-keys name)
(update-vals #(cske/transform-keys csk/->kebab-case %))
(update-vals #(mapv fix-chain-id-keys %)))
add-tokens (fn [stored-accounts tokens-per-account]
(reduce-kv (fn [accounts address tokens-data]
(if (accounts address)
(update accounts address assoc :tokens tokens-data)
accounts))
stored-accounts
tokens-per-account))]
{:db (-> db
(update-in [:wallet :accounts] add-tokens tokens)
(assoc-in [:wallet :ui :tokens-loading?] false))})))
(rf/defn scan-address-success
{:events [:wallet/scan-address-success]}
@@ -122,7 +144,8 @@
:on-success on-success
:on-error #(log/info "failed to derive address " %)}]]]})))
(rf/reg-event-fx :wallet/add-account
(rf/reg-event-fx
:wallet/add-account
(fn [{:keys [db]} [password {:keys [emoji account-name color]} {:keys [public-key address path]}]]
(let [key-uid (get-in db [:profile/profile :key-uid])
sha3-pwd (native-module/sha3 (security/safe-unmask-data password))
@@ -146,11 +169,12 @@
:on-success [:wallet/get-accounts]
:on-error #(log/info "failed to create account " %)}]]]})))
(rf/reg-event-fx :wallet/derive-address-and-add-account
(rf/reg-event-fx
:wallet/derive-address-and-add-account
(fn [_ [password account-details]]
(let [on-success (fn [derived-adress-details]
(let [on-success (fn [derived-address-details]
(rf/dispatch [:wallet/add-account password account-details
(first derived-adress-details)]))]
(first derived-address-details)]))]
{:fx [[:dispatch [:wallet/create-derived-addresses password account-details on-success]]]})))
(rf/defn get-ethereum-chains
@@ -199,7 +223,8 @@
(rf/reg-event-fx :wallet/clear-stored-collectibles clear-stored-collectibles)
(rf/reg-event-fx :wallet/request-collectibles
(rf/reg-event-fx
:wallet/request-collectibles
(fn [{:keys [db]} [{:keys [start-at-index new-request?]}]]
(let [request-id 0
collectibles-filter nil
+9 -32
View File
@@ -8,7 +8,6 @@
[status-im2.contexts.wallet.common.activity-tab.view :as activity]
[status-im2.contexts.wallet.common.collectibles-tab.view :as collectibles]
[status-im2.contexts.wallet.common.temp :as temp]
[status-im2.contexts.wallet.common.utils :as utils]
[status-im2.contexts.wallet.home.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -25,12 +24,12 @@
:accessibility-label :add-a-contact
:label (i18n/label :t/add-address)
:sub-label (i18n/label :t/add-address-description)
:on-press #(rf/dispatch [:navigate-to :wallet-address-watch])
:on-press #(rf/dispatch [:navigate-to :add-address-to-watch])
:add-divider? true}]]])
(defn- add-account-placeholder
[color]
{:customization-color color
(defn- new-account-card-data
[]
{:customization-color (rf/sub [:profile/customization-color])
:on-press #(rf/dispatch [:show-bottom-sheet {:content new-account}])
:type :add-account})
@@ -39,21 +38,6 @@
{:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}
{:id :activity :label (i18n/label :t/activity) :accessibility-label :activity-tab}])
(defn account-cards
[{:keys [accounts loading? balances profile-color]}]
(let [accounts-with-balances
(mapv
(fn [{:keys [color address] :as account}]
(assoc account
:customization-color color
:type :empty
:on-press #(rf/dispatch [:wallet/navigate-to-account address])
:loading? loading?
:balance (utils/prettify-balance
(utils/get-balance-by-address balances address))))
accounts)]
(conj accounts-with-balances (add-account-placeholder profile-color))))
(defn view
[]
(rf/dispatch [:wallet/request-collectibles
@@ -62,14 +46,10 @@
(let [top (safe-area/get-top)
selected-tab (reagent/atom (:id (first tabs-data)))]
(fn []
(let [accounts (rf/sub [:wallet/accounts])
loading? (rf/sub [:wallet/tokens-loading?])
balances (rf/sub [:wallet/balances])
profile-color (rf/sub [:profile/customization-color])
networks (rf/sub [:wallet/network-details])]
[rn/view
{:style {:margin-top top
:flex 1}}
(let [networks (rf/sub [:wallet/network-details])
account-cards-data (rf/sub [:wallet/account-cards-data])
cards (conj account-cards-data (new-account-card-data))]
[rn/view {:style {:margin-top top :flex 1}}
[common.top-nav/view]
[rn/view {:style style/overview-container}
[quo/wallet-overview (temp/wallet-overview-state networks)]]
@@ -80,10 +60,7 @@
[rn/flat-list
{:style style/accounts-list
:content-container-style style/accounts-list-container
:data (account-cards {:accounts accounts
:loading? loading?
:balances balances
:profile-color profile-color})
:data cards
:horizontal true
:separator [rn/view {:style {:width 12}}]
:render-fn quo/account-card
+12 -7
View File
@@ -39,14 +39,15 @@
[status-im2.contexts.syncing.syncing-devices-list.view :as settings-syncing]
[status-im2.contexts.wallet.account.bridge.view :as bridge]
[status-im2.contexts.wallet.account.view :as wallet-accounts]
[status-im2.contexts.wallet.add-watch-only-account.views :as address-add-edit]
[status-im2.contexts.wallet.add-address-to-watch.confirm-address.view :as confirm-address-to-watch]
[status-im2.contexts.wallet.add-address-to-watch.view :as add-address-to-watch]
[status-im2.contexts.wallet.collectible.view :as wallet-collectible]
[status-im2.contexts.wallet.create-account.edit-derivation-path.view :as wallet-edit-derivation-path]
[status-im2.contexts.wallet.create-account.select-keypair.view :as wallet-select-keypair]
[status-im2.contexts.wallet.create-account.view :as wallet-create-account]
[status-im2.contexts.wallet.edit-account.view :as wallet-edit-account]
[status-im2.contexts.wallet.saved-address.view :as wallet-saved-address]
[status-im2.contexts.wallet.scan-account.view :as scan-address]
[status-im2.contexts.wallet.select-address-to-watch.view :as wallet-address-watch]
[status-im2.contexts.wallet.send.select-address.view :as wallet-select-address]
[status-im2.navigation.options :as options]
[status-im2.navigation.transitions :as transitions]))
@@ -248,16 +249,16 @@
:options {:insets {:top? true}}
:component wallet-accounts/view}
{:name :address-to-watch-edit
:component address-add-edit/address-add-edit}
{:name :wallet-edit-account
:component wallet-edit-account/view}
{:name :wallet-address-watch
{:name :add-address-to-watch
:options {:insets {:top? true
:bottom? true}}
:component wallet-address-watch/view}
:component add-address-to-watch/view}
{:name :confirm-address-to-watch
:component confirm-address-to-watch/view}
{:name :wallet-bridge
:options {:insets {:top? true}
@@ -270,6 +271,10 @@
{:name :wallet-collectible
:component wallet-collectible/view}
{:name :wallet-select-keypair
:options {:insets {:top? true}}
:component wallet-select-keypair/view}
{:name :wallet-create-account
:options {:insets {:top? true}}
:component wallet-create-account/view}
-4
View File
@@ -145,10 +145,6 @@
(reg-root-key-sub :communities/selected-tab :communities/selected-tab)
(reg-root-key-sub :contract-communities :contract-communities)
;;wallet
(reg-root-key-sub :wallet/tokens :wallet/tokens)
(reg-root-key-sub :wallet/tokens-loading? :wallet/tokens-loading?)
;;activity center
(reg-root-key-sub :activity-center :activity-center)
+31 -35
View File
@@ -1,36 +1,19 @@
(ns status-im2.subs.wallet.wallet
(:require [re-frame.core :as re-frame]
(:require [re-frame.core :as rf]
[status-im2.contexts.wallet.common.utils :as utils]
[utils.number]))
(defn- calculate-raw-balance
[raw-balance decimals]
(if-let [n (utils.number/parse-int raw-balance nil)]
(/ n (Math/pow 10 (utils.number/parse-int decimals)))
0))
(rf/reg-sub
:wallet/ui
:<- [:wallet]
:-> :ui)
(defn- total-per-token
[item]
(reduce (fn [ac balances]
(+ (calculate-raw-balance (:rawBalance balances)
(:decimals item))
ac))
0
(vals (:balancesPerChain item))))
(rf/reg-sub
:wallet/tokens-loading?
:<- [:wallet/ui]
:-> :tokens-loading?)
(defn- calculate-balance
[address tokens]
(let [token (get tokens (keyword address))
result (reduce
(fn [acc item]
(let [total-values (* (total-per-token item)
(get-in item [:marketValuesPerCurrency :USD :price]))]
(+ acc total-values)))
0
token)]
result))
(re-frame/reg-sub
(rf/reg-sub
:wallet/accounts
:<- [:wallet]
:-> #(->> %
@@ -38,20 +21,33 @@
vals
(sort-by :position)))
(re-frame/reg-sub
(rf/reg-sub
:wallet/balances
:<- [:wallet/accounts]
:<- [:wallet/tokens]
(fn [[accounts tokens]]
(for [{:keys [address]} accounts]
{:address address
:balance (calculate-balance address tokens)})))
(fn [accounts]
(zipmap (map :address accounts)
(map #(-> % :tokens utils/calculate-balance) accounts))))
(re-frame/reg-sub
(rf/reg-sub
:wallet/account-cards-data
:<- [:wallet/accounts]
:<- [:wallet/balances]
:<- [:wallet/tokens-loading?]
(fn [[accounts balances tokens-loading?]]
(mapv (fn [{:keys [color address] :as account}]
(assoc account
:customization-color color
:type :empty
:on-press #(rf/dispatch [:wallet/navigate-to-account address])
:loading? tokens-loading?
:balance (utils/prettify-balance (get balances address))))
accounts)))
(rf/reg-sub
:wallet/current-viewing-account
:<- [:wallet]
:<- [:wallet/balances]
(fn [[{:keys [current-viewing-account-address] :as wallet} balances]]
(-> wallet
(get-in [:accounts current-viewing-account-address])
(assoc :balance (utils/get-balance-by-address balances current-viewing-account-address)))))
(assoc :balance (get balances current-viewing-account-address)))))
+83 -92
View File
@@ -8,43 +8,35 @@
(use-fixtures :each
{:before #(reset! rf-db/app-db {})})
(def tokens
{:0x1 [{:decimals 1
:symbol "ETH"
:name "Ether"
:balancesPerChain {:1 {:rawBalance "20"
:hasError false}
:2 {:rawBalance "10"
:hasError false}}
:marketValuesPerCurrency {:USD {:price 1000}}} ;; total should be 3000
{:decimals 2
:symbol "DAI"
:name "Dai Stablecoin"
:balancesPerChain {:1 {:rawBalance "100"
:hasError false}
:2 {:rawBalance "150"
:hasError false}}
:marketValuesPerCurrency {:USD {:price 100}}}] ;; total should be 250
:0x2 [{:decimals 3
:symbol "ETH"
:name "Ether"
:balancesPerChain {:1 {:rawBalance "2500"
:hasError false}
:2 {:rawBalance "3000"
:hasError false}
:3 {:rawBalance "<nil>"
:hasError false}}
:marketValuesPerCurrency {:USD {:price 200}}} ;; total should be 1100
{:decimals 10
:symbol "DAI"
:name "Dai Stablecoin"
:balancesPerChain {:1 {:rawBalance "10000000000"
:hasError false}
:2 {:rawBalance "0"
:hasError false}
:3 {:rawBalance "<nil>"
:hasError false}}
:marketValuesPerCurrency {:USD {:price 1000}}}]}) ;; total should be 1000
(def tokens-0x1
[{:decimals 1
:symbol "ETH"
:name "Ether"
:balances-per-chain {1 {:raw-balance "20" :has-error false}
2 {:raw-balance "10" :has-error false}}
:market-values-per-currency {:usd {:price 1000}}}
{:decimals 2
:symbol "DAI"
:name "Dai Stablecoin"
:balances-per-chain {1 {:raw-balance "100" :has-error false}
2 {:raw-balance "150" :has-error false}}
:market-values-per-currency {:usd {:price 100}}}])
(def tokens-0x2
[{:decimals 3
:symbol "ETH"
:name "Ether"
:balances-per-chain {1 {:raw-balance "2500" :has-error false}
2 {:raw-balance "3000" :has-error false}
3 {:raw-balance "<nil>" :has-error false}}
:market-values-per-currency {:usd {:price 200}}}
{:decimals 10
:symbol "DAI"
:name "Dai Stablecoin"
:balances-per-chain {1 {:raw-balance "10000000000" :has-error false}
2 {:raw-balance "0" :has-error false}
3 {:raw-balance "<nil>" :has-error false}}
:market-values-per-currency {:usd {:price 1000}}}])
(def accounts
{"0x1" {:path "m/44'/60'/0'/0/0"
@@ -65,7 +57,8 @@
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false}
:removed false
:tokens tokens-0x1}
"0x2" {:path "m/44'/60'/0'/0/1"
:emoji "💎"
:key-uid "0x2f5ea39"
@@ -84,66 +77,63 @@
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false}})
:removed false
:tokens tokens-0x2}})
(h/deftest-sub :wallet/balances
[sub-name]
(testing "returns seq of maps containing :address and :balance"
(swap! rf-db/app-db #(-> %
(assoc-in [:wallet :accounts] accounts)
(assoc :wallet/tokens tokens)))
(is (= `({:address "0x1"
:balance 3250}
{:address "0x2"
:balance 2100})
(testing "a map: address->balance"
(swap! rf-db/app-db #(assoc-in % [:wallet :accounts] accounts))
(is (= {"0x1" 3250 "0x2" 2100}
(rf/sub [sub-name])))))
(h/deftest-sub :wallet/accounts
[sub-name]
(testing "returns all accounts without balance"
(swap! rf-db/app-db
#(-> %
(assoc-in [:wallet :accounts] accounts)
(assoc :wallet/tokens tokens)))
(swap! rf-db/app-db #(assoc-in % [:wallet :accounts] accounts))
(is
(= `({:path "m/44'/60'/0'/0/0"
:emoji "😃"
:key-uid "0x2f5ea39"
:address "0x1"
:wallet false
:name "Account One"
:type :generated
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:position 0
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false}
{:path "m/44'/60'/0'/0/1"
:emoji "💎"
:key-uid "0x2f5ea39"
:address "0x2"
:wallet false
:name "Account Two"
:type :generated
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :purple
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:position 1
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false})
(= (list {:path "m/44'/60'/0'/0/0"
:emoji "😃"
:key-uid "0x2f5ea39"
:address "0x1"
:wallet false
:name "Account One"
:type :generated
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:position 0
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x1}
{:path "m/44'/60'/0'/0/1"
:emoji "💎"
:key-uid "0x2f5ea39"
:address "0x2"
:wallet false
:name "Account Two"
:type :generated
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :purple
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:position 1
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x2})
(rf/sub [sub-name])))))
(h/deftest-sub :wallet/current-viewing-account
@@ -152,8 +142,8 @@
(swap! rf-db/app-db
#(-> %
(assoc-in [:wallet :accounts] accounts)
(assoc-in [:wallet :current-viewing-account-address] "0x1")
(assoc :wallet/tokens tokens)))
(assoc-in [:wallet :current-viewing-account-address] "0x1")))
(is
(= {:path "m/44'/60'/0'/0/0"
:emoji "😃"
@@ -174,5 +164,6 @@
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:balance 3250}
:balance 3250
:tokens tokens-0x1}
(rf/sub [sub-name])))))
+1 -1
View File
@@ -68,7 +68,7 @@
(let [first-part-of-public-key (subs public-key 0 3)
ellipsis "..."
public-key-size (count public-key)
last-part-of-public-key (subs public-key (- public-key-size 6) public-key-size)
last-part-of-public-key (subs public-key (- public-key-size 5) public-key-size)
abbreviated-public-key (str first-part-of-public-key ellipsis last-part-of-public-key)]
abbreviated-public-key)
nil))
+1 -1
View File
@@ -5,7 +5,7 @@
(deftest get-shortened-compressed-key
(testing "Ensure the function correctly abbreviates a valid public key"
(is (= "zQ3...1sgt5N"
(is (= "zQ3...sgt5N"
(utils.address/get-shortened-compressed-key
"zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N"))))
+6 -3
View File
@@ -2374,12 +2374,15 @@
"reset": "Reset",
"reveal-address": "Reveal address",
"derive-addresses": "Derive addresses",
"address-activity": "This address has activity",
"sign transactions": "sign transactions",
"search-assets": "Search assets",
"account-created": "{{name}} created",
"update-account-name": "Update account name",
"edit-wallet-account-emoji-updated-message": "Account emoji has been updated",
"edit-wallet-account-name-updated-message": "Account name has been updated",
"edit-wallet-account-colour-updated-message": "Account colour has been updated"
"edit-wallet-account-colour-updated-message": "Account colour has been updated",
"search-assets": "Search assets",
"address-activity": "This address has activity",
"keypairs": "Keypairs",
"keypairs-description": "Select keypair to derive your new account from",
"confirm-account-origin": "Confirm account origin"
}