Compare commits

...
Author SHA1 Message Date
Brian Sztamfater b5a48dc06d feat: integrate send transaction endpoint
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-12-08 00:35:47 -03:00
Brian Sztamfater 4c604abe5b feat: implement getSuggestedRoutes in the wallet Send Flow
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-12-08 00:32:52 -03:00
Ulises Manuel de4e233884 [#17974] text combinations - username component (#17987)
* Move docstring to be available while using `colors/resolve-color`
* Add text combinations - username component and tests
* Add username related svg icons
2023-12-07 17:44:24 -06:00
24 changed files with 592 additions and 136 deletions
+54 -6
View File
@@ -118,13 +118,61 @@
"M2.79504 9.01494C2.89473 8.85584 3.00297 8.70977 3.11963 8.5761C3.90594 7.67512 4.97212 7.45024 5.99992 7.45024C7.02772 7.45024 8.0939 7.67512 8.88021 8.5761C8.99688 8.70978 9.10512 8.85585 9.2048 9.01495C8.9501 9.28561 8.66149 9.52401 8.34577 9.72335C8.25403 9.55824 8.15512 9.41818 8.05145 9.29939C7.56503 8.74204 6.88121 8.55024 5.99992 8.55024C5.11862 8.55024 4.43481 8.74204 3.94839 9.29939C3.84472 9.41818 3.74582 9.55824 3.65408 9.72334C3.33835 9.524 3.04975 9.2856 2.79504 9.01494ZM5.99992 3.5502C5.47525 3.5502 5.04992 3.97552 5.04992 4.5002C5.04992 5.02487 5.47525 5.4502 5.99992 5.4502C6.52459 5.4502 6.94992 5.02487 6.94992 4.5002C6.94992 3.97552 6.52459 3.5502 5.99992 3.5502ZM3.94992 4.5002C3.94992 3.36801 4.86773 2.4502 5.99992 2.4502C7.1321 2.4502 8.04992 3.36801 8.04992 4.5002C8.04992 5.63238 7.1321 6.5502 5.99992 6.5502C4.86773 6.5502 3.94992 5.63238 3.94992 4.5002Z"
:fill color-2}]])
(defn- contact-20
[{:keys [color color-2]
:or {color colors/neutral-100
color-2 colors/white}
:as props}]
[container props
[svg/circle
{:cx 10
:cy 10
:r 7.5
:fill color}]
[svg/path
{:d
"M8.65002 7.99998C8.65002 7.25439 9.25443 6.64998 10 6.64998C10.7456 6.64998 11.35 7.25439 11.35 7.99998C11.35 8.74556 10.7456 9.34998 10 9.34998C9.25443 9.34998 8.65002 8.74556 8.65002 7.99998ZM10 5.34998C8.53646 5.34998 7.35002 6.53642 7.35002 7.99998C7.35002 9.46353 8.53646 10.65 10 10.65C11.4636 10.65 12.65 9.46353 12.65 7.99998C12.65 6.53642 11.4636 5.34998 10 5.34998ZM10 13.65C8.67557 13.65 7.53064 14.4186 6.98692 15.5341C6.60094 15.3235 6.23942 15.0737 5.90771 14.79C6.69408 13.3369 8.23179 12.35 10 12.35C11.7682 12.35 13.306 13.3369 14.0923 14.79C13.7606 15.0737 13.3991 15.3235 13.0131 15.5341C12.4694 14.4186 11.3245 13.65 10 13.65Z"
:fill color-2}]])
(defn- verified-20
[{:keys [color color-2]
:or {color colors/neutral-100
color-2 colors/white}
:as props}]
[container props
[svg/path
{:d
"M18 10C18 8.77003 17.1118 7.74751 15.9418 7.53891C16.6216 6.56407 16.5267 5.21294 15.6569 4.34321C14.7872 3.47344 13.436 3.37852 12.4611 4.05845C12.2526 2.88834 11.23 2 10 2C8.77 2 7.74747 2.88827 7.53889 4.05832C6.56406 3.37846 5.21292 3.47339 4.34318 4.34313C3.47343 5.21288 3.3785 6.56404 4.05839 7.53888C2.88831 7.74743 2 8.76998 2 10C2 11.23 2.88824 12.2525 4.05826 12.4611C3.3784 13.4359 3.47333 14.7871 4.34307 15.6568C5.21284 16.5266 6.56403 16.6215 7.53887 15.9416C7.74741 17.1117 8.76996 18 10 18C11.23 18 12.2525 17.1117 12.4611 15.9417C13.4359 16.6215 14.7871 16.5266 15.6568 15.6569C16.5265 14.7871 16.6215 13.436 15.9416 12.4611C17.1117 12.2526 18 11.23 18 10Z"
:fill color}]
[svg/path
{:d "M7.25 10.75L9.25 12.25L12.75 7.75"
:stroke color-2
:stroke-width "1.2"}]])
(defn- untrustworthy-20
[{:keys [color color-2]
:or {color colors/neutral-100
color-2 colors/white}
:as props}]
[container props
[svg/path
{:d "M10 2L15.6569 4.34315L18 10L15.6569 15.6569L10 18L4.34315 15.6569L2 10L4.34315 4.34315L10 2Z"
:fill color}]
[svg/path
{:d
"M10.75 5.5L10.55 11.5H9.45L9.25 5.5H10.75ZM10 13C10.4142 13 10.75 13.3358 10.75 13.75C10.75 14.1642 10.4142 14.5 10 14.5C9.58579 14.5 9.25 14.1642 9.25 13.75C9.25 13.3358 9.58579 13 10 13Z"
:fill color-2}]])
(def ^:private icons
{:i/clear-20 clear-20
:i/dropdown-20 dropdown-20
:i/pullup-20 pullup-20
:i/dropdown-12 dropdown-12
:i/pullup-12 pullup-12
:i/contact-12 contact-12})
{:i/clear-20 clear-20
:i/dropdown-20 dropdown-20
:i/pullup-20 pullup-20
:i/dropdown-12 dropdown-12
:i/pullup-12 pullup-12
:i/contact-12 contact-12
:i/contact-20 contact-20
:i/verified-20 verified-20
:i/untrustworthy-20 untrustworthy-20})
(defn- append-to-keyword
[k & xs]
@@ -0,0 +1,68 @@
(ns quo.components.text-combinations.username.component-spec
(:require [quo.components.text-combinations.username.view :as username]
[test-helpers.component :as h]))
(defn test-all-status
[component-to-render component-props]
(h/test "Verified status"
(h/render [component-to-render (assoc component-props :status :verified)])
(h/is-truthy (h/get-by-label-text :username-status-icon)))
(h/test "Contact status"
(h/render [component-to-render (assoc component-props :status :contact)])
(h/is-truthy (h/get-by-label-text :username-status-icon)))
(h/test "Untrustworthy status"
(h/render [component-to-render (assoc component-props :status :untrustworthy)])
(h/is-truthy (h/get-by-label-text :username-status-icon)))
(h/test "Untrustworthy contact status"
(h/render [component-to-render (assoc component-props :status :untrustworthy-contact)])
(let [icons (h/get-all-by-label-text :username-status-icon)]
(h/is-truthy (aget icons 0))
(h/is-truthy (aget icons 1))))
(h/test "Blocked status"
(h/render [component-to-render (assoc component-props :status :blocked)])
(h/is-truthy (h/get-by-label-text :username-status-icon))))
(h/describe "Text combinations - Username"
(h/test "Renders default"
(h/render [username/view {:username "Test username"}])
(h/is-truthy (h/get-by-text "Test username")))
(h/describe "Render different :name-type values"
(h/describe "default"
(let [props {:name-type :default
:username "Test username"}]
(h/test "default render"
(h/render [username/view props])
(h/is-truthy (h/get-by-text "Test username")))
(h/describe "All status are rendered"
(test-all-status username/view props))))
(h/describe "ens"
(let [props {:name-type :ens
:username "test-username.eth"}]
(h/test "no status render"
(h/render [username/view props])
(h/is-truthy (h/get-by-text "test-username.eth")))
(h/describe "All status are rendered"
(test-all-status username/view props))))
(h/describe "nickname"
(let [props {:name-type :nickname
:username "Nickname"
:name "Real name"}]
(h/test "no status render"
(h/render [username/view props])
(h/is-truthy (h/get-by-text "Nickname"))
(h/is-truthy (h/get-by-text "Real name")))
(h/describe "All status are rendered"
(test-all-status username/view props))))))
@@ -0,0 +1,30 @@
(ns quo.components.text-combinations.username.style
(:require [quo.foundations.colors :as colors]))
(def container
{:flex-direction :row
:height 32})
(def username-text-container
{:flex-direction :row
:align-items :flex-end})
(defn real-name-text
[theme blur?]
{:color (if blur?
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
(colors/theme-colors colors/neutral-60 colors/neutral-40 theme))})
(defn real-name-dot
[theme blur?]
(assoc (real-name-text theme blur?) :margin-horizontal 6))
(defn status-icon-container
[name-type status]
(cond-> {:flex-direction :row
:margin-left 4}
(#{:default :ens} name-type) (assoc :margin-top 8
:margin-bottom 4)
(= :nickname name-type) (assoc :margin-top 10
:margin-bottom 2)
(= status :untrustworthy-contact) (assoc :margin-right 2)))
@@ -0,0 +1,57 @@
(ns quo.components.text-combinations.username.view
(:require [quo.components.icon :as icon]
[quo.components.markdown.text :as text]
[quo.components.text-combinations.username.style :as style]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]))
(defn- username-text
[{:keys [theme name-type username blur?]
real-name :name}]
[rn/view {:style style/username-text-container}
[text/text
{:size :heading-1
:weight :semi-bold}
username]
(when (= name-type :nickname)
[:<>
[text/text
{:style (style/real-name-dot theme blur?)
:size :paragraph-1
:weight :medium}
"∙"]
[text/text
{:style (style/real-name-text theme blur?)
:size :paragraph-1
:weight :medium}
real-name]])])
(defn- icon-20
[icon-name theme color]
[icon/icon icon-name
{:accessibility-label :username-status-icon
:size 20
:color (colors/resolve-color color theme)}])
(defn status-icon
[{:keys [theme name-type status]
:or {name-type :default}}]
[rn/view {:style (style/status-icon-container name-type status)}
(case status
:verified [icon-20 :i/verified theme :success]
:contact [icon-20 :i/contact theme :blue]
:untrustworthy [icon-20 :i/untrustworthy theme :danger]
:blocked [icon-20 :i/block theme :danger]
:untrustworthy-contact [:<>
[icon-20 :i/untrustworthy theme :danger]
[icon-20 :i/contact theme :blue]]
nil)])
(defn view-internal
[props]
[rn/view {:style style/container}
[username-text props]
[status-icon props]])
(def view (quo.theme/with-theme view-internal))
@@ -6,14 +6,14 @@
(h/describe "Wallet: Token Input"
(h/test "Token label renders"
(h/render [token-input/view
{:token :snt
{:token {:symbol "snt"}
:currency :eur
:conversion 1}])
(h/is-truthy (h/get-by-text "SNT")))
(h/test "Amount renders"
(h/render [token-input/view
{:token :snt
{:token {:symbol "snt"}
:currency :eur
:conversion 1}])
(h/is-truthy (h/get-by-text "€0.00"))))
@@ -43,7 +43,7 @@
:align-items :flex-end}}
[rn/image
{:style style/token
:source (resources/get-token token)}]
:source (resources/get-token (keyword (string/lower-case token)))}]
[rn/text-input
(cond-> {:auto-focus true
:ref #(reset! input-ref %)
+2
View File
@@ -141,6 +141,7 @@
quo.components.tags.token-tag.view
quo.components.text-combinations.channel-name.view
quo.components.text-combinations.standard-title.view
quo.components.text-combinations.username.view
quo.components.text-combinations.view
quo.components.wallet.account-card.view
quo.components.wallet.account-origin.view
@@ -385,6 +386,7 @@
(def channel-name quo.components.text-combinations.channel-name.view/view)
(def standard-title quo.components.text-combinations.standard-title.view/view)
(def text-combinations quo.components.text-combinations.view/view)
(def username quo.components.text-combinations.username.view/view)
;;;; Wallet
(def account-card quo.components.wallet.account-card.view/view)
+1
View File
@@ -77,6 +77,7 @@
[quo.components.tags.summary-tag.component-spec]
[quo.components.tags.tiny-tag.component-spec]
[quo.components.text-combinations.channel-name.component-spec]
[quo.components.text-combinations.username.component-spec]
[quo.components.wallet.account-card.component-spec]
[quo.components.wallet.account-origin.component-spec]
[quo.components.wallet.account-overview.component-spec]
+6 -5
View File
@@ -285,10 +285,6 @@
(get-in colors-map [color suffix]))))
(defn- resolve-color*
"(resolve-color color theme opacity)
color hex string or keyword (resolves from custom, network and semantic colors)
theme :light/:dark
opacity 0-100 (optional) - if set theme is ignored and goes to 50 suffix internally"
([color theme]
(resolve-color* color theme nil))
([color theme opacity]
@@ -300,7 +296,12 @@
suffix (get-from-colors-map suffix)
opacity (alpha (/ opacity 100))))))
(def resolve-color (memoize resolve-color*))
(def resolve-color
"(resolve-color color theme opacity)
color hex string or keyword (resolves from custom, network and semantic colors)
theme :light/:dark
opacity 0-100 (optional) - if set theme is ignored and goes to 50 suffix internally"
(memoize resolve-color*))
(def ^{:deprecated true :superseded-by "resolve-color"}
custom-color
+1 -2
View File
@@ -172,8 +172,7 @@
:use-mailservers? true
:recovered recovered}
config/default-multiaccount)
;; The address from which we derive any chat
;; account/encryption keys
;; The address from which we derive any chat account/encryption keys
eip1581-address
(assoc :eip1581-address eip1581-address)
save-mnemonic?
+12
View File
@@ -393,3 +393,15 @@
(def ^:const status-address-domain ".stateofus.eth")
(def ^:const eth-address-domain ".eth")
(def ^:const gas-rate-low 0)
(def ^:const gas-rate-medium 1)
(def ^:const gas-rate-high 2)
(def ^:const send-type-transfer 0)
(def ^:const send-type-ens-register 1)
(def ^:const send-type-ens-release 2)
(def ^:const send-type-ens-set-pub-key 3)
(def ^:const send-type-stickers-buy 4)
(def ^:const send-type-bridge 5)
(def ^:const send-type-erc-721-transfer 6)
@@ -166,6 +166,7 @@
[status-im2.contexts.quo-preview.text-combinations.preview :as
text-combinations]
[status-im2.contexts.quo-preview.text-combinations.standard-title :as standard-title]
[status-im2.contexts.quo-preview.text-combinations.username :as username]
[status-im2.contexts.quo-preview.wallet.account-card :as account-card]
[status-im2.contexts.quo-preview.wallet.account-origin :as account-origin]
[status-im2.contexts.quo-preview.wallet.account-overview :as
@@ -461,7 +462,9 @@
{:name :channel-name
:component channel-name/view}
{:name :standard-title
:component standard-title/view}]
:component standard-title/view}
{:name :username
:component username/view}]
:wallet [{:name :account-card :component account-card/view}
{:name :account-origin :component account-origin/view}
{:name :account-overview
@@ -0,0 +1,52 @@
(ns status-im2.contexts.quo-preview.text-combinations.username
(:require [quo.core :as quo]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:key :name-type
:type :select
:options [{:key :default}
{:key :ens
:value "ENS"}
{:key :nickname}]}
{:key :username
:type :text}
{:key :name
:type :text}
{:key :status
:type :select
:options [{:key nil
:value "(Nothing)"}
{:key :verified}
{:key :contact}
{:key :untrustworthy}
{:key :untrustworthy-contact}
{:key :blocked}]}
{:key :blur?
:type :boolean}])
(defn- set-username-based-on-name-type
[_ ratom {previous-type :name-type} {new-type :name-type}]
(when (not= previous-type new-type)
(swap! ratom assoc
:username
(if (= new-type :ens)
"juan.eth"
"Juanito Mdz"))))
(defn view
[]
(let [state (reagent/atom {:name-type :default
:username "Juanito Mdz"
:name "Juan Méndez"
:status nil
:blur? true})
_ (add-watch state :on-state-change set-username-based-on-name-type)]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:show-blur-background? true
:blur? (:blur? @state)}
[quo/username @state]])))
@@ -15,6 +15,7 @@
(defn get-derivation-path
[number-of-accounts]
(str constants/path-wallet-root "/" number-of-accounts))
(defn format-derivation-path
[path]
(string/replace path "/" " / "))
@@ -43,12 +44,15 @@
(when balance-in-chain
(calculate-raw-balance (:raw-balance balance-in-chain) decimals))))
(defn calculate-balance-for-token
[token]
(* (total-token-value-in-all-chains token)
(-> token :market-values-per-currency :usd :price)))
(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))))
(map #(calculate-balance-for-token %))
(reduce +)))
(defn network-list
@@ -0,0 +1,133 @@
(ns status-im2.contexts.wallet.send.events
(:require
[native-module.core :as native-module]
[status-im2.constants :as constants]
[taoensso.timbre :as log]
[utils.datetime :as datetime]
[utils.money :as money]
[utils.number]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :wallet/suggested-routes-success
(fn [{:keys [db]} [suggested-routes timestamp]]
(when (= (get-in db [:wallet :ui :send :suggested-routes-call-timestamp]) timestamp)
{:db (-> db
(assoc-in [:wallet :ui :send :suggested-routes] suggested-routes)
(assoc-in [:wallet :ui :send :route] (first (:Best suggested-routes)))
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false))})))
(rf/reg-event-fx :wallet/suggested-routes-error
(fn [{:keys [db]} [_error]]
{:db (-> db
(update-in [:wallet :ui :send] dissoc :suggested-routes)
(update-in [:wallet :ui :send] dissoc :route)
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false))}))
(rf/reg-event-fx :wallet/clean-suggested-routes
(fn [{:keys [db]}]
{:db (-> db
(update-in [:wallet :ui :send] dissoc :suggested-routes)
(update-in [:wallet :ui :send] dissoc :route)
(update-in [:wallet :ui :send] dissoc :loading-suggested-routes?))}))
(rf/reg-event-fx :wallet/select-send-address
(fn [{:keys [db]} [address]]
{:db (assoc-in db [:wallet :ui :send :to-address] address)}))
(rf/reg-event-fx :wallet/send-select-token
(fn [{:keys [db]} [token stack-id]]
{:db (assoc-in db [:wallet :ui :send :token] token)
:fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]}))
(rf/reg-event-fx :wallet/send-select-amount
(fn [{:keys [db]} [amount stack-id]]
{:db (assoc-in db [:wallet :ui :send :amount] amount)
:fx [[:navigate-to-within-stack [:wallet-transaction-confirmation stack-id]]]}))
(rf/reg-event-fx :wallet/get-suggested-routes
(fn [{:keys [db]} [amount]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
token (get-in db [:wallet :ui :send :token])
to-address (get-in db [:wallet :ui :send :to-address])
token-decimal (:decimals token)
token-id (:symbol token)
network-preferences [constants/mainnet-chain-id]
gas-rates constants/gas-rate-low
amount-in (money/mul (money/bignumber amount)
(money/from-decimal token-decimal))
from-address wallet-address
request-params [constants/send-type-transfer
from-address
to-address
(money/to-hex amount-in)
token-id
[]
[]
network-preferences
gas-rates
{}]
timestamp (datetime/timestamp)]
{:db (-> db
(assoc-in [:wallet :ui :send :loading-suggested-routes?] true)
(assoc-in [:wallet :ui :send :suggested-routes-call-timestamp]
timestamp))
:json-rpc/call [{:method "wallet_getSuggestedRoutes"
:params request-params
:on-success (fn [suggested-routes]
(rf/dispatch [:wallet/suggested-routes-success suggested-routes
timestamp]))
:on-error (fn [error]
(rf/dispatch [:wallet/suggested-routes-error error])
(log/error "failed to get suggested routes"
{:event :wallet/get-suggested-routes
:error error
:params request-params}))}]})))
(rf/reg-event-fx :wallet/send-transaction
(fn [{:keys [db]} [password]]
(let [route (get-in db [:wallet :ui :send :route])
from-address (get-in db [:wallet :current-viewing-account-address])
to-address (get-in db [:wallet :ui :send :to-address])
from (:From route)
token (get-in db [:wallet :ui :send :token])
token-id (:symbol token)
from-asset token-id
to-asset token-id
bridge-name (:BridgeName route)
chain-id (:chainId from)
multi-transaction-command {:fromAddress from-address
:toAddress to-address
:fromAsset from-asset
:toAsset to-asset
:fromAmount (:AmountOut route)
:type 0}
transaction-bridge
[{:BridgeName bridge-name
:ChainID chain-id
:TransferTx {:From from-address
:To to-address
:Gas (money/to-hex (:GasAmount route))
:GasPrice (money/to-hex (money/->wei :gwei
(:gasPrice (:GasFees route))))
:Value (:AmountOut route)
:Nonce nil
:MaxFeePerGas (money/to-hex
(money/->wei :gwei
(:maxFeePerGasMedium (:GasFees route))))
:MaxPriorityFeePerGas (money/to-hex (money/->wei :gwei
(:maxPriorityFeePerGas
(:GasFees
route))))
:Input ""
:Data "0x"}}]
sha3-pwd (native-module/sha3 (str (security/safe-unmask-data password)))
request-params [multi-transaction-command transaction-bridge sha3-pwd]]
{:json-rpc/call [{:method "wallet_createMultiTransaction"
:params request-params
:on-success #(rf/dispatch [:dismiss-modal :wallet-select-address])
:on-error (fn [error]
(log/error "failed to send transaction"
{:event :wallet/send-transaction
:error error
:params request-params}))}]})))
@@ -17,7 +17,13 @@
:short-name "eth"
:network-name :ethereum
:chain-id 1
:related-chain-id 5}]})
:related-chain-id 5}]
:wallet {:ui {:send {:token {:symbol "ETH"
:decimals 18
:total-balance 1
:total-balance-fiat 10
:loading-suggested-routes? false
:route {}}}}}})
(h/describe "Send > input amount screen"
(h/test "Default render"
@@ -7,6 +7,7 @@
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.contexts.wallet.send.input-amount.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -47,71 +48,88 @@
current))
(defn- f-view-internal
[{:keys [token limit rate]}]
(let [bottom (safe-area/get-bottom)
{:keys [currency]} (rf/sub [:profile/profile])
networks (rf/sub [:wallet/network-details])
;; Temporary values
token (or token :eth)
conversion-rate (or rate 10)
limit-crypto (or limit 2860000.32)
limit-fiat (* limit-crypto conversion-rate)
input-value (reagent/atom "")
current-limit (reagent/atom {:amount limit-crypto
:currency token})
handle-swap (fn [crypto?]
(let [num-value (parse-double @input-value)]
(reset! current-limit (if crypto?
{:amount limit-crypto
:currency token}
{:amount limit-fiat
:currency currency}))
(when (> num-value (:amount @current-limit))
(reset! input-value ""))))
handle-keyboard-press (fn [v]
(let [current-value @input-value
new-value (make-new-input current-value v)
num-value (or (parse-double new-value) 0)]
(when (<= num-value (:amount @current-limit))
(reset! input-value new-value)
(reagent/flush))))
handle-delete (fn [_]
(swap! input-value #(subs % 0 (dec (count %))))
(reagent/flush))
handle-on-change (fn [v]
(when (valid-input? @input-value v)
(let [num-value (or (parse-double v) 0)
current-limit-amount (:amount @current-limit)]
(if (> num-value current-limit-amount)
(reset! input-value (str current-limit-amount))
(reset! input-value v))
(reagent/flush))))]
[{:keys [rate]}]
(let [bottom (safe-area/get-bottom)
{:keys [currency]} (rf/sub [:profile/profile])
networks (rf/sub [:wallet/network-details])
wallet-send (get-in (rf/sub [:wallet]) [:ui :send])
token (:token wallet-send)
token-symbol (:symbol token)
limit-crypto (:total-balance token)
limit-fiat (:total-balance-fiat token)
conversion-rate (or rate 10)
input-value (reagent/atom "")
current-limit (reagent/atom {:amount limit-crypto
:currency token-symbol})
loading-suggested-routes? (:loading-suggested-routes? wallet-send)
handle-swap (fn [crypto?]
(let [num-value (parse-double @input-value)]
(reset! current-limit (if crypto?
{:amount limit-crypto
:currency token-symbol}
{:amount limit-fiat
:currency currency}))
(when (> num-value (:amount @current-limit))
(reset! input-value ""))))
handle-keyboard-press (fn [v]
(let [current-value @input-value
new-value (make-new-input current-value v)
num-value (or (parse-double new-value) 0)]
(when (and (not loading-suggested-routes?)
(<= num-value (:amount @current-limit)))
(reset! input-value new-value)
(reagent/flush))))
handle-delete (fn [_]
(when-not loading-suggested-routes?
(swap! input-value #(subs % 0 (dec (count %))))
(reagent/flush)))
handle-on-change (fn [v]
(when (valid-input? @input-value v)
(let [num-value (or (parse-double v) 0)
current-limit-amount (:amount @current-limit)]
(if (> num-value current-limit-amount)
(reset! input-value (str current-limit-amount))
(reset! input-value v))
(reagent/flush))))]
(fn [{:keys [on-confirm]
:or {on-confirm #(js/alert "Confirmed")}}]
(let [limit-label (make-limit-label @current-limit)
input-num-value (parse-double @input-value)
confirm-disabled? (or
(empty? @input-value)
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))]
:or {on-confirm #(rf/dispatch [:wallet/send-select-amount @input-value
:wallet-send-input-amount])}}]
(let [limit-label (make-limit-label @current-limit)
input-num-value (parse-double @input-value)
route (get-in (rf/sub [:wallet]) [:ui :send :route])
loading-suggested-routes? (get-in (rf/sub [:wallet]) [:ui :send :loading-suggested-routes?])
confirm-disabled? (or
(nil? route)
(empty? @input-value)
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))]
(rn/use-effect
(fn []
(let [dismiss-keyboard-fn #(when (= % "active") (rn/dismiss-keyboard!))
app-keyboard-listener (.addEventListener rn/app-state "change" dismiss-keyboard-fn)]
#(.remove app-keyboard-listener))))
(rn/use-effect (fn []
(rf/dispatch [:wallet/clean-suggested-routes])
(when-not (or
(empty? @input-value)
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))
(debounce/debounce-and-dispatch [:wallet/get-suggested-routes @input-value]
100)))
[@input-value])
[rn/view
{:style style/screen}
[quo/page-nav
{:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:on-press #(rf/dispatch [:navigate-back-within-stack :wallet-send-input-amount])
:right-side :account-switcher
:account-switcher {:customization-color :yellow
:emoji "🎮"
:on-press #(js/alert "Switch account")}}]
[quo/token-input
{:container-style style/input-container
:token token
:token token-symbol
:currency currency
:networks networks
:title (i18n/label :t/send-limit {:limit limit-label})
@@ -122,7 +140,16 @@
:on-change-text (fn [text]
(handle-on-change text))}]
;; Network routing content to be added
[rn/scroll-view]
[rn/scroll-view
{:content-container-style {:flex-grow 1
:align-items :center
:justify-content :center}}
(cond loading-suggested-routes?
[quo/text "Loading routes"]
(and (not loading-suggested-routes?) route)
[quo/text "Route found"]
(and (not loading-suggested-routes?) (nil? route))
[quo/text "Route not found"])]
[quo/bottom-actions
{:actions :1-action
:button-one-label (i18n/label :t/confirm)
@@ -47,7 +47,7 @@
[input-value input-focused?]
(fn []
(let [scanned-address (rf/sub [:wallet/scanned-address])
send-address (rf/sub [:wallet/send-address])
send-address (get-in (rf/sub [:wallet]) [:ui :send :to-address])
valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?])
chain-id (rf/sub [:chain-id])
contacts (rf/sub [:contacts/active])]
@@ -19,10 +19,13 @@
(defn- asset-component
[]
(fn [token _ _ _]
(let [on-press #(js/alert "Not implemented yet")
(let [on-press
#(if (= (:symbol token) "ETH")
(rf/dispatch [:wallet/send-select-token token :wallet-select-asset])
(js/alert "Only ETH transfers are allowed."))
total-balance-formatted (.toFixed (:total-balance token) 2)
balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2)
currency-symbol "$"]
balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2)
currency-symbol "$"]
[quo/token-network
{:token (quo.resources/get-token (keyword (string/lower-case (:symbol token))))
:label (:name token)
@@ -5,14 +5,15 @@
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.utils.utils :as utils]
[status-im2.common.resources :as resources]
[status-im2.common.standard-authentication.core :as standard-auth]
[status-im2.contexts.wallet.send.transaction-confirmation.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- transaction-title
[]
[token amount account to-address]
[rn/view {:style style/content-container}
[rn/view {:style {:flex-direction :row}}
[quo/text
@@ -22,7 +23,7 @@
:accessibility-label :send-label}
(i18n/label :t/send)]
[quo/summary-tag
{:label "150 ETH"
{:label (str amount " " (:symbol token))
:type :token
:image-source (quo.resources/get-token :eth)}]]
[rn/view
@@ -35,10 +36,10 @@
:accessibility-label :send-label}
(i18n/label :t/from)]
[quo/summary-tag
{:label "Collectibles vault"
{:label (:name account)
:type :account
:emoji "🍑"
:customization-color :purple}]]
:emoji (:emoji account)
:customization-color (:color account)}]]
[rn/view
{:style {:flex-direction :row
:margin-top 4}}
@@ -49,13 +50,11 @@
:accessibility-label :send-label}
(i18n/label :t/to)]
[quo/summary-tag
{:label "Mark Libot"
:type :user
:image-source (resources/get-mock-image :user-picture-male4)
:customization-color :magenta}]]])
{:type :address
:label (utils/get-shortened-address to-address)}]]])
(defn- transaction-from
[status-account-props theme]
[amount account-props theme]
[rn/view
{:style {:padding-horizontal 20
:padding-bottom 16}}
@@ -68,13 +67,13 @@
[quo/summary-info
{:type :status-account
:networks? true
:values {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props status-account-props}]])
:values {:ethereum amount
:optimism 0
:arbitrum 0}
:account-props account-props}]])
(defn- transaction-to
[user-props theme]
[amount user-props theme]
[rn/view
{:style {:padding-horizontal 20
:padding-bottom 16}}
@@ -87,13 +86,13 @@
[quo/summary-info
{:type :user
:networks? true
:values {:ethereum 150
:optimism 50
:arbitrum 25}
:values {:ethereum amount
:optimism 0
:arbitrum 0}
:account-props user-props}]])
(defn- transaction-details
[theme]
[estimated-time-min max-fees-eth token amount to-address theme]
[rn/view
{:style {:padding-horizontal 20
:padding-bottom 16}}
@@ -116,7 +115,7 @@
:status :default
:size :small
:title (i18n/label :t/est-time)
:subtitle "3-5 min"}]
:subtitle (str estimated-time-min " min")}]
[quo/data-item
{:container-style {:flex 1
:height 36}
@@ -128,7 +127,7 @@
:status :default
:size :small
:title (i18n/label :t/max-fees)
:subtitle "€188,70"}]
:subtitle (str "$" max-fees-eth)}]
[quo/data-item
{:container-style {:flex 1
:height 36}
@@ -139,35 +138,42 @@
:label :none
:status :default
:size :small
:title (i18n/label :t/user-gets {:name "Mark"})
:subtitle "149.99 ETH"}]]])
:title (i18n/label :t/user-gets {:name (utils/get-shortened-address to-address)})
:subtitle (str amount " " (:symbol token))}]]])
(defn- f-view-internal
[_]
(let [reset-slider? (reagent/atom false)
margin-top (safe-area/get-top)
biometric-auth? true
on-close #(rf/dispatch [:navigate-back-within-stack :wallet-select-asset])
status-account-props {:customization-color :purple
:size 32
:emoji "🍑"
:type :default
:name "Collectibles vault"
:address "0x0ah...78b"}
user-props {:full-name "M L"
:status-indicator? false
:size :small
:ring-background (resources/get-mock-image :ring)
:customization-color :blue
:name "Mark Libot"
:address "0x0ah...78b"
:status-account (merge status-account-props
{:size 16
:name "New house"
:emoji "🍔"})}]
(let [margin-top (safe-area/get-top)
biometric-auth? false
on-close #(rf/dispatch [:navigate-back-within-stack :wallet-select-asset])
send-transaction-data (get-in (rf/sub [:wallet]) [:ui :send])
token (:token send-transaction-data)
amount (:amount send-transaction-data)
route (:route send-transaction-data)
estimated-time-min (:EstimatedTime route)
max-fees-eth 5.28 ; calculate gas price in fiat
to-address (:to-address send-transaction-data)
account (rf/sub [:wallet/current-viewing-account])
account-props {:customization-color (:color account)
:size 32
:emoji (:emoji account)
:type :default
:name (:name account)
:address (utils/get-shortened-address (:address account))}
user-props {:full-name "M L"
:status-indicator? false
:size :small
:ring-background (resources/get-mock-image :ring)
:customization-color :blue
:name "Mark Libot"
:address "0x0ah...78b"
:status-account (merge account-props
{:size 16
:name "New house"
:emoji "🍔"})}]
(fn [{:keys [theme]}]
[rn/view {:style {:flex 1}}
[quo/gradient-cover {:customization-color :purple}]
[quo/gradient-cover {:customization-color (:color account)}]
[rn/view {:style (style/container margin-top)}
[quo/page-nav
{:icon-name :i/arrow-left
@@ -176,18 +182,18 @@
:right-side [{:icon-name :i/advanced
:on-press (fn callback [] nil)
:accessibility-label "Advanced"}]}]
[transaction-title]
[transaction-from status-account-props theme]
[transaction-to user-props theme]
[transaction-details theme]
[transaction-title token amount account to-address]
[transaction-from amount account-props theme]
[transaction-to amount user-props theme]
[transaction-details estimated-time-min max-fees-eth token amount to-address theme]
[rn/view {:style style/slide-button-container}
[quo/slide-button
{:size :size/s-48
:customization-color :purple
:on-reset (when @reset-slider? #(reset! reset-slider? false))
:on-complete #(js/alert "Not implemented yet")
:track-icon (if biometric-auth? :i/face-id :password)
:track-text (i18n/label :t/slide-to-send)}]]]])))
[standard-auth/slide-button
{:size :size-40
:track-text (i18n/label :t/slide-to-send)
:customization-color (:color account)
:on-enter-password #(rf/dispatch [:wallet/send-transaction %])
:biometric-auth? biometric-auth?
:auth-button-label (i18n/label :t/confirm)}]]]])))
(defn view-internal
[props]
+1
View File
@@ -22,6 +22,7 @@
status-im2.contexts.shell.share.events
status-im2.contexts.syncing.events
status-im2.contexts.wallet.events
status-im2.contexts.wallet.send.events
[status-im2.db :as db]
[utils.re-frame :as rf]))
-1
View File
@@ -156,7 +156,6 @@
(reg-root-key-sub :wallet/scanned-address :wallet/scanned-address)
(reg-root-key-sub :wallet/local-suggestions :wallet/local-suggestions)
(reg-root-key-sub :wallet/valid-ens-or-address? :wallet/valid-ens-or-address?)
(reg-root-key-sub :wallet/send-address :wallet/send-address)
;;debug
(when js/goog.DEBUG
+2 -2
View File
@@ -48,7 +48,7 @@
:<- [:wallet/balances]
:<- [:wallet/tokens-loading?]
(fn [[accounts balances tokens-loading?]]
(mapv (fn [{:keys [color address type] :as account}]
(mapv (fn [{:keys [color address] :as account}]
(assoc account
:customization-color color
:type (if (= type :watch) :watch-only :empty)
@@ -75,7 +75,7 @@
(assoc token
:networks (utils/network-list token networks)
:total-balance (utils/total-token-value-in-all-chains token)
:total-balance-fiat (utils/calculate-balance token)))
:total-balance-fiat (utils/calculate-balance-for-token token)))
(:tokens account))
sorted-tokens
+6 -2
View File
@@ -152,7 +152,7 @@
;; E.g. for Ether, it's smallest part is wei or 10^(-18) of 1 ether
;; for arbitrary ERC20 token the smallest part is 10^(-decimals) of 1 token
;;
;; Different tokens can have different number of allowed decimals, so it's neccessary to include the
;; Different tokens can have different number of allowed decimals, so it's necessary to include the
;; decimals parameter
;; to get the amount scale right.
@@ -205,10 +205,14 @@
(with-precision 2)
str))
(defn add
(defn- add*
[bn1 n2]
(.add ^js bn1 n2))
(def add
"Add with defaults, this version is able to receive `nil` and takes them as 0."
(fnil add* (bignumber 0) (bignumber 0)))
(defn mul
[bn1 bn2]
(.mul ^js bn1 bn2))