Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d730a25d06 | ||
|
|
97aff27980 | ||
|
|
0c3e836272 | ||
|
|
60fc4f1b9a | ||
|
|
b97e2df2fb | ||
|
|
f539bb5ca2 |
@@ -1,4 +1,5 @@
|
||||
(ns quo.components.buttons.wallet-ctas.style)
|
||||
(ns quo.components.buttons.wallet-ctas.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def inner-container
|
||||
{:flex-direction :row
|
||||
@@ -10,3 +11,9 @@
|
||||
:width 77.75
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(defn action-button-text
|
||||
[theme disabled?]
|
||||
(cond-> {:margin-top 4
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}
|
||||
disabled? (assoc :opacity 0.5)))
|
||||
|
||||
@@ -3,28 +3,28 @@
|
||||
[quo.components.buttons.wallet-button.view :as wallet-button]
|
||||
[quo.components.buttons.wallet-ctas.style :as style]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
|
||||
(defn action-button
|
||||
[{:keys [icon text on-press theme accessibility-label]}]
|
||||
[{:keys [icon text on-press theme accessibility-label disabled?]}]
|
||||
[rn/view
|
||||
{:style style/button-container
|
||||
:accessibility-label accessibility-label}
|
||||
[wallet-button/view
|
||||
{:icon icon
|
||||
:on-press on-press}]
|
||||
{:icon icon
|
||||
:disabled? disabled?
|
||||
:on-press on-press}]
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style {:margin-top 4
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}} text]])
|
||||
:style (style/action-button-text theme disabled?)} text]])
|
||||
|
||||
(defn view
|
||||
[{:keys [buy-action send-action receive-action bridge-action swap-action container-style]}]
|
||||
[{:keys [buy-action send-action receive-action bridge-action swap-action bridge-disabled?
|
||||
swap-disabled? container-style]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style container-style}
|
||||
[rn/view {:style style/inner-container}
|
||||
@@ -52,10 +52,12 @@
|
||||
:text (i18n/label :t/swap)
|
||||
:on-press swap-action
|
||||
:theme theme
|
||||
:disabled? swap-disabled?
|
||||
:accessibility-label :swap}])
|
||||
[action-button
|
||||
{:icon :i/bridge
|
||||
:text (i18n/label :t/bridge)
|
||||
:on-press bridge-action
|
||||
:theme theme
|
||||
:disabled? bridge-disabled?
|
||||
:accessibility-label :bridge}]]]))
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
(defn enabled? [v] (= "1" v))
|
||||
|
||||
(goog-define INFURA_TOKEN "62f3cee52dbb484198e7339837e263f3")
|
||||
(goog-define INFURA_TOKEN "")
|
||||
(goog-define POKT_TOKEN "3ef2018191814b7e1009b8d9")
|
||||
(goog-define STATUS_BUILD_PROXY_USER "")
|
||||
(goog-define STATUS_BUILD_PROXY_PASSWORD "")
|
||||
|
||||
@@ -619,3 +619,12 @@
|
||||
(def router-error-code-not-enough-liquidity "WPP-038")
|
||||
(def router-error-code-price-impact-too-high "WPP-039")
|
||||
(def router-error-code-not-enough-native-balance "WR-002")
|
||||
|
||||
(def ^:const wallet-transaction-estimation
|
||||
{:unknown 0
|
||||
:less-than-one-minute 1
|
||||
:less-than-three-minutes 2
|
||||
:less-than-five-minutes 3
|
||||
:more-than-five-minutes 4})
|
||||
|
||||
(def ^:const wallet-connect-transaction-refresh-interval-ms 10000)
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
(let [selected-tab (or (rf/sub [:wallet/account-tab]) first-tab-id)
|
||||
{:keys [name color formatted-balance
|
||||
watch-only?]} (rf/sub [:wallet/current-viewing-account])
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
testnet-mode? (rf/sub [:profile/test-networks-enabled?])]
|
||||
(hot-reload/use-safe-unmount (fn []
|
||||
(rf/dispatch [:wallet/close-account-page])
|
||||
(rf/dispatch [:wallet/clean-current-viewing-account])))
|
||||
@@ -46,23 +47,25 @@
|
||||
[quo/wallet-graph {:time-frame :empty}])
|
||||
(when (not watch-only?)
|
||||
[quo/wallet-ctas
|
||||
{:container-style style/cta-buttons
|
||||
:send-action (fn []
|
||||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:wallet/wizard-navigate-forward
|
||||
{:start-flow? true
|
||||
:flow-id :wallet-send-flow}]))
|
||||
:receive-action #(rf/dispatch [:open-modal :screen/wallet.share-address
|
||||
{:status :receive}])
|
||||
:buy-action #(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}])
|
||||
:bridge-action (fn []
|
||||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:wallet/start-bridge]))
|
||||
:swap-action (when (ff/enabled? ::ff/wallet.swap)
|
||||
(fn []
|
||||
(rf/dispatch [:wallet.tokens/get-token-list])
|
||||
(rf/dispatch [:open-modal :screen/wallet.swap-select-asset-to-pay])))}])
|
||||
{:container-style style/cta-buttons
|
||||
:send-action (fn []
|
||||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:wallet/wizard-navigate-forward
|
||||
{:start-flow? true
|
||||
:flow-id :wallet-send-flow}]))
|
||||
:receive-action #(rf/dispatch [:open-modal :screen/wallet.share-address
|
||||
{:status :receive}])
|
||||
:buy-action #(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}])
|
||||
:bridge-action (fn []
|
||||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:wallet/start-bridge]))
|
||||
:swap-action (when (ff/enabled? ::ff/wallet.swap)
|
||||
(fn []
|
||||
(rf/dispatch [:wallet.tokens/get-token-list])
|
||||
(rf/dispatch [:open-modal :screen/wallet.swap-select-asset-to-pay])))
|
||||
:bridge-disabled? testnet-mode?
|
||||
:swap-disabled? testnet-mode?}])
|
||||
[quo/tabs
|
||||
{:style style/tabs
|
||||
:size 32
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im.contexts.wallet.common.token-value.view
|
||||
(:require [quo.core :as quo]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.feature-flags :as ff]
|
||||
@@ -18,15 +17,15 @@
|
||||
:right-icon :i/external})
|
||||
|
||||
(defn- action-send
|
||||
[send-params entry-point]
|
||||
[{:keys [disabled?] :as params} entry-point]
|
||||
{:icon :i/send
|
||||
:accessibility-label :send
|
||||
:label (i18n/label :t/send)
|
||||
:disabled? (:disabled? send-params)
|
||||
:disabled? disabled?
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:wallet/set-token-to-send send-params entry-point]))})
|
||||
(rf/dispatch [:wallet/set-token-to-send params entry-point]))})
|
||||
|
||||
(defn- action-receive
|
||||
[selected-account?]
|
||||
@@ -38,21 +37,26 @@
|
||||
#(rf/dispatch [:open-modal :screen/share-shell {:initial-tab :wallet}]))})
|
||||
|
||||
(defn- action-bridge
|
||||
[bridge-params]
|
||||
[{:keys [bridge-disabled? testnet-mode?] :as params}]
|
||||
{:icon :i/bridge
|
||||
:accessibility-label :bridge
|
||||
:label (i18n/label :t/bridge)
|
||||
:disabled? (:bridge-disabled? bridge-params)
|
||||
:disabled? (or testnet-mode? bridge-disabled?)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:wallet/bridge-select-token bridge-params]))})
|
||||
(rf/dispatch [:wallet/bridge-select-token params]))})
|
||||
|
||||
(defn- action-swap
|
||||
[]
|
||||
[{:keys [token token-symbol testnet-mode?]}]
|
||||
{:icon :i/swap
|
||||
:accessibility-label :swap
|
||||
:label (i18n/label :t/swap)
|
||||
:on-press #(not-implemented/alert)})
|
||||
:disabled? testnet-mode?
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:wallet.swap/start
|
||||
{:asset-to-pay (or token {:symbol token-symbol})
|
||||
:open-new-screen? true}]))})
|
||||
|
||||
(defn- action-manage-tokens
|
||||
[watch-only?]
|
||||
@@ -71,47 +75,39 @@
|
||||
|
||||
(defn token-value-drawer
|
||||
[token watch-only? entry-point]
|
||||
(let [token-symbol (:token token)
|
||||
token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
{:query token-symbol}]))
|
||||
fiat-unformatted-value (get-in token [:values :fiat-unformatted-value])
|
||||
has-balance? (money/greater-than fiat-unformatted-value (money/bignumber "0"))
|
||||
selected-account? (rf/sub [:wallet/current-viewing-account-address])
|
||||
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
|
||||
send-params (if selected-account?
|
||||
{:token token-data
|
||||
:stack-id :screen/wallet.accounts
|
||||
:disabled? (not has-balance?)
|
||||
:start-flow? true
|
||||
:owners token-owners}
|
||||
{:token-symbol token-symbol
|
||||
:stack-id :wallet-stack
|
||||
:start-flow? true
|
||||
:owners token-owners})
|
||||
bridge-params (if selected-account?
|
||||
{:token token-data
|
||||
:bridge-disabled? (or (not has-balance?)
|
||||
(send-utils/bridge-disabled? token-symbol))
|
||||
:stack-id :screen/wallet.accounts
|
||||
:start-flow? true
|
||||
:owners token-owners}
|
||||
{:token-symbol token-symbol
|
||||
:bridge-disabled? (send-utils/bridge-disabled? token-symbol)
|
||||
:stack-id :wallet-stack
|
||||
:start-flow? true
|
||||
:owners token-owners})]
|
||||
(let [token-symbol (:token token)
|
||||
token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
{:query token-symbol}]))
|
||||
selected-account (rf/sub [:wallet/current-viewing-account-address])
|
||||
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
|
||||
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
|
||||
params (cond-> {:start-flow? true
|
||||
:owners token-owners
|
||||
:testnet-mode? testnet-mode?}
|
||||
selected-account
|
||||
(assoc :token token-data
|
||||
:stack-id :screen/wallet.accounts
|
||||
:has-balance? (-> (get-in token [:values :fiat-unformatted-value])
|
||||
(money/greater-than (money/bignumber "0"))))
|
||||
(not selected-account)
|
||||
(assoc :token-symbol token-symbol
|
||||
:stack-id :wallet-stack))]
|
||||
[quo/action-drawer
|
||||
[(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens)
|
||||
(action-manage-tokens watch-only?))
|
||||
(when (ff/enabled? ::ff/wallet.assets-modal-hide)
|
||||
(action-hide))]
|
||||
(not watch-only?) (concat [(action-buy)
|
||||
(when (seq token-owners)
|
||||
(action-send send-params entry-point))
|
||||
(action-receive selected-account?)
|
||||
(when (ff/enabled? ::ff/wallet.swap) (action-swap))
|
||||
(when (seq (seq token-owners))
|
||||
(action-bridge bridge-params))]))]]))
|
||||
(not watch-only?)
|
||||
(concat [(action-buy)
|
||||
(when (seq token-owners)
|
||||
(action-send params entry-point))
|
||||
(action-receive selected-account)
|
||||
(when (ff/enabled? ::ff/wallet.swap)
|
||||
(action-swap params))
|
||||
(when (seq token-owners)
|
||||
(action-bridge (assoc params
|
||||
:bridge-disabled?
|
||||
(send-utils/bridge-disabled? token-symbol))))]))]]))
|
||||
|
||||
(defn view
|
||||
[item _ _ {:keys [watch-only? entry-point]}]
|
||||
|
||||
@@ -493,3 +493,13 @@
|
||||
:available-balance (calculate-total-token-balance token)
|
||||
:total-balance (calculate-total-token-balance token chain-ids)))
|
||||
tokens))
|
||||
|
||||
(defn estimated-time-format
|
||||
"Formats the estimated time for a transaction"
|
||||
[estimated-time]
|
||||
(condp = estimated-time
|
||||
(:unknown constants/wallet-transaction-estimation) ">5"
|
||||
(:less-than-one-minute constants/wallet-transaction-estimation) "<1"
|
||||
(:less-than-three-minutes constants/wallet-transaction-estimation) "1-3"
|
||||
(:less-than-five-minutes constants/wallet-transaction-estimation) "3-5"
|
||||
">5"))
|
||||
|
||||
@@ -14,22 +14,36 @@
|
||||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start
|
||||
(fn [{:keys [db]} [{:keys [asset-to-pay asset-to-receive network]}]]
|
||||
(let [asset-to-receive' (or asset-to-receive
|
||||
(swap-utils/select-asset-to-receive
|
||||
(:wallet db)
|
||||
(:profile/profile db)
|
||||
asset-to-pay))
|
||||
network' (or network
|
||||
(swap-utils/select-network asset-to-pay))]
|
||||
(fn [{:keys [db]} [{:keys [network open-new-screen?] :as data}]]
|
||||
(let [{:keys [wallet]} db
|
||||
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
|
||||
account (swap-utils/wallet-account wallet)
|
||||
asset-to-pay (if (get-in data [:asset-to-pay :networks])
|
||||
(:asset-to-pay data)
|
||||
(swap-utils/select-asset-to-pay-by-symbol
|
||||
{:wallet wallet
|
||||
:account account
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:token-symbol (get-in data [:asset-to-pay :symbol])}))
|
||||
asset-to-receive (or (:asset-to-receive data)
|
||||
(swap-utils/select-default-asset-to-receive
|
||||
{:wallet wallet
|
||||
:account account
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:asset-to-pay asset-to-pay}))
|
||||
network' (or network
|
||||
(swap-utils/select-network asset-to-pay))]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay)
|
||||
(assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive')
|
||||
(assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive)
|
||||
(assoc-in [:wallet :ui :swap :network] network'))
|
||||
:fx (if network'
|
||||
[[:dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]]]
|
||||
[[:dispatch [:wallet/switch-current-viewing-account (:address account)]]
|
||||
[:dispatch
|
||||
(if open-new-screen?
|
||||
[:navigate-to :screen/wallet.setup-swap]
|
||||
[:navigate-to-within-stack
|
||||
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]])]
|
||||
[:dispatch [:wallet.swap/set-default-slippage]]]
|
||||
[[:dispatch
|
||||
[:show-bottom-sheet
|
||||
@@ -41,8 +55,9 @@
|
||||
(rf/dispatch
|
||||
[:wallet.swap/start
|
||||
{:asset-to-pay asset-to-pay
|
||||
:asset-to-receive asset-to-receive'
|
||||
:network network}]))}])}]]])})))
|
||||
:asset-to-receive asset-to-receive
|
||||
:network network
|
||||
:open-new-screen? open-new-screen?}]))}])}]]])})))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-pay
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
(defn- assets-view
|
||||
[search-text on-change-text]
|
||||
(let [on-token-press (fn [token]
|
||||
(rf/dispatch [:wallet.swap/start {:asset-to-pay token}]))]
|
||||
(rf/dispatch [:wallet.swap/start
|
||||
{:asset-to-pay token
|
||||
:open-new-screen? false}]))]
|
||||
[:<>
|
||||
[search-input search-text on-change-text]
|
||||
[asset-list/view
|
||||
|
||||
@@ -30,22 +30,61 @@
|
||||
:else
|
||||
(i18n/label :t/something-went-wrong-please-try-again-later)))
|
||||
|
||||
(defn select-asset-to-receive
|
||||
[wallet profile asset-to-pay]
|
||||
(let [wallet-address (get-in wallet [:current-viewing-account-address])
|
||||
account (-> wallet
|
||||
:accounts
|
||||
vals
|
||||
(utils/get-account-by-address wallet-address))
|
||||
test-networks-enabled? (get profile :test-networks-enabled?)
|
||||
networks (-> (get-in wallet
|
||||
[:wallet :networks (if test-networks-enabled? :test :prod)])
|
||||
(network-utils/sorted-networks-with-details))]
|
||||
(defn- first-operable-account
|
||||
[accounts]
|
||||
(->> accounts
|
||||
vals
|
||||
(remove :watch-only?)
|
||||
(filter :operable?)
|
||||
(sort-by :position)
|
||||
first))
|
||||
|
||||
(defn wallet-account
|
||||
"Picks the account that's gonna be used for the swap operation.
|
||||
It's gonna be either the preselected account defined by
|
||||
`[:wallet :current-viewing-account-address]` in `db`
|
||||
or the first operable account."
|
||||
[wallet]
|
||||
(if-let [wallet-address (get wallet :current-viewing-account-address)]
|
||||
(-> wallet
|
||||
:accounts
|
||||
vals
|
||||
(utils/get-account-by-address wallet-address))
|
||||
(-> wallet :accounts first-operable-account)))
|
||||
|
||||
(defn select-asset-to-pay-by-symbol
|
||||
"Selects an asset to pay by token symbol.
|
||||
It's used for cases when only token symbol is available and the information
|
||||
about token needs to be extracted from the database.
|
||||
That happens when token is being selected on the home screen and
|
||||
it basically indicates that no account pre-selection was made."
|
||||
[{:keys [wallet account test-networks-enabled? token-symbol]}]
|
||||
(let [networks (-> (get-in wallet [:networks (if test-networks-enabled? :test :prod)])
|
||||
(network-utils/sorted-networks-with-details))
|
||||
token (->> account
|
||||
:tokens
|
||||
(filter #(= token-symbol (:symbol %)))
|
||||
first)]
|
||||
(assoc token :networks (network-utils/network-list token networks))))
|
||||
|
||||
(defn select-default-asset-to-receive
|
||||
"Selects an asset to receive if it was not provided explicitly.
|
||||
The principle of how the asset is being selected is simple: we get the
|
||||
whole list, remove the currently selected `asset-to-pay` from it, and choose
|
||||
the first one of what's left."
|
||||
[{:keys [wallet account test-networks-enabled? asset-to-pay]}]
|
||||
(let [networks (-> (get-in wallet [:networks (if test-networks-enabled? :test :prod)])
|
||||
(network-utils/sorted-networks-with-details))]
|
||||
(->> (utils/tokens-with-balance (:tokens account) networks nil)
|
||||
(remove #(= (:symbol %) (:symbol asset-to-pay)))
|
||||
first)))
|
||||
|
||||
(defn select-network
|
||||
"Chooses the network.
|
||||
Usually user needs to do the selection first and if the selection was done
|
||||
then the list of networks for the defined token will always contain
|
||||
one entry. Otherwise `nil` will be returned from here which will serve
|
||||
as an indicator that the network selector needs to be displayed."
|
||||
[{:keys [networks]}]
|
||||
(when (= (count networks) 1)
|
||||
(first networks)))
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.signing :as signing]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transactions]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.typed-data :as typed-data]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
@@ -123,11 +124,11 @@
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/sign-typed-data
|
||||
(fn [{:keys [password address data version chain-id on-success on-error]}]
|
||||
(-> (signing/eth-sign-typed-data (security/safe-unmask-data password)
|
||||
address
|
||||
data
|
||||
chain-id
|
||||
version)
|
||||
(-> (typed-data/sign (security/safe-unmask-data password)
|
||||
address
|
||||
data
|
||||
chain-id
|
||||
version)
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-error))))
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||
data-store]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.signing :as signing]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transactions]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.typed-data :as typed-data]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(rf/reg-event-fx
|
||||
@@ -37,7 +37,9 @@
|
||||
(assoc-in [:wallet-connect/current-request :response-sent?] false))
|
||||
:fx [(condp = method
|
||||
constants/wallet-connect-eth-send-transaction-method
|
||||
[:dispatch [:wallet-connect/process-eth-send-transaction]]
|
||||
[:dispatch
|
||||
[:wallet-connect/process-eth-send-transaction
|
||||
{:on-success (fn [] (rf/dispatch [:wallet-connect/show-request-modal]))}]]
|
||||
|
||||
constants/wallet-connect-eth-sign-method
|
||||
[:dispatch [:wallet-connect/process-eth-sign]]
|
||||
@@ -94,22 +96,25 @@
|
||||
:raw-data prepared-tx
|
||||
:transaction tx
|
||||
:chain-id chain-id
|
||||
:display-data display-data)
|
||||
:fx [[:dispatch [:wallet-connect/show-request-modal]]]})))
|
||||
:display-data display-data)})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/process-eth-send-transaction
|
||||
(fn [{:keys [db]}]
|
||||
(fn [{:keys [db]} [{:keys [on-success]}]]
|
||||
(let [event (data-store/get-db-current-request-event db)
|
||||
tx (-> event data-store/get-request-params first)
|
||||
chain-id (-> event
|
||||
(get-in [:params :chainId])
|
||||
networks/eip155->chain-id)]
|
||||
{:fx [[:effects.wallet-connect/prepare-transaction
|
||||
{:tx tx
|
||||
:chain-id chain-id
|
||||
:on-success #(rf/dispatch [:wallet-connect/prepare-transaction-success % chain-id])
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-processing-error %])}]]})))
|
||||
(when tx
|
||||
{:fx [[:effects.wallet-connect/prepare-transaction
|
||||
{:tx tx
|
||||
:chain-id chain-id
|
||||
:on-success (fn [data]
|
||||
(rf/dispatch [:wallet-connect/prepare-transaction-success data chain-id])
|
||||
(when on-success
|
||||
(rf/call-continuation on-success)))
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-processing-error %])}]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/process-eth-sign-transaction
|
||||
@@ -130,16 +135,13 @@
|
||||
(fn [{:keys [db]}]
|
||||
(try
|
||||
(let [[address raw-data] (data-store/get-db-current-request-params db)
|
||||
parsed-raw-data (transforms/js-parse raw-data)
|
||||
session-chain-id (-> (data-store/get-db-current-request-event db)
|
||||
(get-in [:params :chainId])
|
||||
networks/eip155->chain-id)
|
||||
data-chain-id (-> parsed-raw-data
|
||||
transforms/js->clj
|
||||
signing/typed-data-chain-id)
|
||||
parsed-data (-> parsed-raw-data
|
||||
(transforms/js-dissoc :types :primaryType)
|
||||
(transforms/js-stringify 2))]
|
||||
typed-data (-> raw-data
|
||||
transforms/js-parse
|
||||
transforms/js->clj)
|
||||
data-chain-id (typed-data/get-chain-id typed-data)]
|
||||
(if (and data-chain-id
|
||||
(not= session-chain-id data-chain-id))
|
||||
{:fx [[:dispatch
|
||||
@@ -150,7 +152,7 @@
|
||||
[:wallet-connect/current-request]
|
||||
assoc
|
||||
:address (string/lower-case address)
|
||||
:display-data (or parsed-data raw-data)
|
||||
:display-data (typed-data/flatten-typed-data typed-data)
|
||||
:raw-data raw-data)
|
||||
:fx [[:dispatch [:wallet-connect/show-request-modal]]]}))
|
||||
(catch js/Error err
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.standard-authentication.core :as standard-authentication]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.footer.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -14,17 +15,25 @@
|
||||
(rf/dispatch [:wallet-connect/respond-current-session password]))
|
||||
|
||||
(defn view
|
||||
[{:keys [warning-label slide-button-text error-text]} & children]
|
||||
[{:keys [warning-label slide-button-text error-state]} & children]
|
||||
(let [{:keys [customization-color]} (rf/sub [:wallet-connect/current-request-account-details])
|
||||
offline? (rf/sub [:network/offline?])
|
||||
theme (quo.theme/use-theme)]
|
||||
[:<>
|
||||
(when (or offline? error-text)
|
||||
(when (or offline? error-state)
|
||||
[quo/alert-banner
|
||||
{:action? false
|
||||
:text (if offline?
|
||||
(i18n/label :t/wallet-connect-no-internet-warning)
|
||||
error-text)}])
|
||||
{:action? (when error-state true)
|
||||
:text (if offline?
|
||||
(i18n/label :t/wallet-connect-no-internet-warning)
|
||||
(i18n/label (condp = error-state
|
||||
:not-enough-assets-to-pay-gas-fees
|
||||
:t/not-enough-assets-to-pay-gas-fees
|
||||
|
||||
:not-enough-assets
|
||||
:t/not-enough-assets-for-transaction)))
|
||||
:button-text (i18n/label :t/buy-eth)
|
||||
:on-button-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}])}])
|
||||
[rn/view {:style style/content-container}
|
||||
(into [rn/view
|
||||
{:style style/data-items-container}]
|
||||
@@ -33,7 +42,7 @@
|
||||
[standard-authentication/slide-button
|
||||
{:size :size-48
|
||||
:track-text slide-button-text
|
||||
:disabled? (or offline? (seq error-text))
|
||||
:disabled? (or offline? error-state)
|
||||
:customization-color customization-color
|
||||
:on-auth-success on-auth-success
|
||||
:auth-button-label (i18n/label :t/confirm)}]]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.modals.common.style
|
||||
(:require [status-im.constants :as constants]))
|
||||
(:require [quo.foundations.colors :as colors]
|
||||
[status-im.constants :as constants]))
|
||||
|
||||
(defn container
|
||||
[bottom]
|
||||
@@ -21,3 +22,23 @@
|
||||
(def data-item
|
||||
{:flex 1
|
||||
:background-color :transparent})
|
||||
|
||||
(def typed-data-item
|
||||
(assoc data-item :margin-bottom 4))
|
||||
|
||||
(def data-border-container
|
||||
{:padding-horizontal 12
|
||||
:padding-top 8
|
||||
:margin-top 10.5
|
||||
:margin-bottom 0
|
||||
:border-width 1
|
||||
:border-color colors/neutral-10
|
||||
:border-radius 16})
|
||||
|
||||
(def data-item-container
|
||||
{:padding 10
|
||||
:margin-top 10.5
|
||||
:margin-bottom 0
|
||||
:border-width 1
|
||||
:border-color colors/neutral-10
|
||||
:border-radius 16})
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
(:require [quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.fees-data-item.view :as
|
||||
fees-data-item]
|
||||
@@ -10,19 +12,71 @@
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transaction-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- refetch-transaction
|
||||
[]
|
||||
(rf/dispatch [:wallet-connect/process-eth-send-transaction]))
|
||||
|
||||
(def tabs-data
|
||||
[{:id :tab/data :label (i18n/label :t/data)}
|
||||
{:id :tab/hex :label (i18n/label :t/hex)}])
|
||||
|
||||
(defn- render-item
|
||||
[props]
|
||||
(let [[label value] props]
|
||||
[quo/data-item
|
||||
{:card? false
|
||||
:container-style style/data-item
|
||||
:title (str (name label) ":")
|
||||
:subtitle value}]))
|
||||
|
||||
(defn- tab-view
|
||||
[selected-tab]
|
||||
(let [{:keys [transaction]} (rf/sub [:wallet-connect/current-request])
|
||||
transaction-items (rn/use-memo #(-> transaction
|
||||
(transaction-utils/transaction-hex-values->number)
|
||||
(transaction-utils/transactions->display-array))
|
||||
[transaction])]
|
||||
[:<>
|
||||
(case selected-tab
|
||||
:tab/data [gesture/flat-list
|
||||
{:data transaction-items
|
||||
:content-container-style style/data-item-container
|
||||
:render-fn render-item
|
||||
:shows-vertical-scroll-indicator false}]
|
||||
:tab/hex [data-block/view])]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [bottom (safe-area/get-bottom)
|
||||
(let [bottom (safe-area/get-bottom)
|
||||
{:keys [customization-color]
|
||||
:as account} (rf/sub [:wallet-connect/current-request-account-details])
|
||||
dapp (rf/sub [:wallet-connect/current-request-dapp])
|
||||
network (rf/sub [:wallet-connect/current-request-network])
|
||||
:as account} (rf/sub [:wallet-connect/current-request-account-details])
|
||||
dapp (rf/sub [:wallet-connect/current-request-dapp])
|
||||
network (rf/sub [:wallet-connect/current-request-network])
|
||||
{:keys [max-fees-fiat-formatted
|
||||
error-state]} (rf/sub [:wallet-connect/current-request-transaction-information])]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet-connect/on-request-modal-dismissed]))
|
||||
error-state estimated-time]} (rf/sub
|
||||
[:wallet-connect/current-request-transaction-information])
|
||||
[selected-tab set-selected-tab] (rn/use-state (:id (first tabs-data)))
|
||||
on-change-tab #(set-selected-tab %)
|
||||
refetch-interval-ref (rn/use-ref nil)
|
||||
clear-interval (rn/use-callback (fn []
|
||||
(when (.-current refetch-interval-ref)
|
||||
(js/clearInterval
|
||||
(.-current refetch-interval-ref))))
|
||||
[refetch-interval-ref])]
|
||||
(rn/use-mount
|
||||
(fn []
|
||||
(clear-interval)
|
||||
(set! (.-current refetch-interval-ref)
|
||||
(js/setInterval refetch-transaction constants/wallet-connect-transaction-refresh-interval-ms))))
|
||||
|
||||
(rn/use-unmount (fn []
|
||||
(clear-interval)
|
||||
(rf/dispatch [:wallet-connect/on-request-modal-dismissed])))
|
||||
|
||||
[rn/view {:style (style/container bottom)}
|
||||
[quo/gradient-cover {:customization-color customization-color}]
|
||||
[page-nav/view
|
||||
@@ -33,17 +87,17 @@
|
||||
{:label (i18n/label :t/wallet-connect-send-transaction-header)
|
||||
:dapp dapp
|
||||
:account account}]
|
||||
[data-block/view]]
|
||||
[quo/segmented-control
|
||||
{:size 32
|
||||
:blur? false
|
||||
:default-active :tab/data
|
||||
:data tabs-data
|
||||
:on-change on-change-tab}]
|
||||
[tab-view selected-tab]]
|
||||
[footer/view
|
||||
{:warning-label (i18n/label :t/wallet-connect-sign-warning)
|
||||
:slide-button-text (i18n/label :t/slide-to-send)
|
||||
:error-text (when error-state
|
||||
(i18n/label (condp = error-state
|
||||
:not-enough-assets-to-pay-gas-fees
|
||||
:t/not-enough-assets-to-pay-gas-fees
|
||||
|
||||
:not-enough-assets
|
||||
:t/not-enough-assets)))}
|
||||
:error-state error-state}
|
||||
[quo/data-item
|
||||
{:status :default
|
||||
:card? false
|
||||
@@ -54,5 +108,12 @@
|
||||
:subtitle (:full-name network)}]
|
||||
[fees-data-item/view
|
||||
{:fees max-fees-fiat-formatted
|
||||
:fees-error error-state}]]]]))
|
||||
:fees-error error-state}]
|
||||
[quo/data-item
|
||||
{:card? false
|
||||
:container-style style/data-item
|
||||
:title (i18n/label :t/est-time)
|
||||
:subtitle (if estimated-time
|
||||
(i18n/label :t/time-in-mins {:minutes estimated-time})
|
||||
(i18n/label :t/unknown))}]]]]))
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.modals.sign-message.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
|
||||
[status-im.common.raw-data-block.view :as data-block]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.fees-data-item.view :as
|
||||
fees-data-item]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.footer.view :as footer]
|
||||
@@ -12,6 +13,37 @@
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn typed-data-field
|
||||
[{:keys [label value]}]
|
||||
[quo/data-item
|
||||
{:card? false
|
||||
:container-style style/typed-data-item
|
||||
:title label
|
||||
:subtitle value}])
|
||||
|
||||
(defn typed-data-view
|
||||
[]
|
||||
(let [display-data (rf/sub [:wallet-connect/current-request-display-data])]
|
||||
[gesture/flat-list
|
||||
{:data display-data
|
||||
:style style/data-border-container
|
||||
:over-scroll-mode :never
|
||||
:content-container-style {:padding-bottom 12}
|
||||
:render-fn typed-data-field
|
||||
:shows-vertical-scroll-indicator false}]))
|
||||
|
||||
(defn message-data-view
|
||||
[]
|
||||
(let [display-data (rf/sub [:wallet-connect/current-request-display-data])]
|
||||
[data-block/view display-data]))
|
||||
|
||||
(defn display-data-view
|
||||
[]
|
||||
(let [typed-data? (rf/sub [:wallet-connect/typed-data-request?])]
|
||||
(if typed-data?
|
||||
[typed-data-view]
|
||||
[message-data-view])))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [bottom (safe-area/get-bottom)
|
||||
@@ -29,7 +61,7 @@
|
||||
{:label (i18n/label :t/wallet-connect-sign-message-header)
|
||||
:dapp dapp
|
||||
:account account}]
|
||||
[data-block/view]]
|
||||
[display-data-view]]
|
||||
[footer/view
|
||||
{:warning-label (i18n/label :t/wallet-connect-sign-warning)
|
||||
:slide-button-text (i18n/label :t/slide-to-sign)}
|
||||
|
||||
@@ -57,3 +57,8 @@
|
||||
[chain-id]
|
||||
(-> (rpc-events/call-async "wallet_getSuggestedFees" true chain-id)
|
||||
(promesa/then transforms/js->clj)))
|
||||
|
||||
(defn wallet-get-transaction-estimated-time
|
||||
[chain-id max-fee-per-gas]
|
||||
(-> (rpc-events/call-async "wallet_getTransactionEstimatedTime" true chain-id max-fee-per-gas)
|
||||
(promesa/then transforms/js->clj)))
|
||||
|
||||
@@ -1,28 +1,12 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.utils.signing
|
||||
(:require [native-module.core :as native-module]
|
||||
[promesa.core :as promesa]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||
data-store]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
|
||||
[utils.hex :as hex]
|
||||
[utils.number :as number]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(defn typed-data-chain-id
|
||||
"Returns the `:chain-id` from typed data if it's present and if the EIP712 domain defines it. Without
|
||||
the `:chain-id` in the domain type, it will not be signed as part of the typed-data."
|
||||
[typed-data]
|
||||
(let [chain-id-type? (->> typed-data
|
||||
:types
|
||||
:EIP712Domain
|
||||
(some #(= "chainId" (:name %))))
|
||||
data-chain-id (-> typed-data
|
||||
:domain
|
||||
:chainId
|
||||
number/parse-int)]
|
||||
(when chain-id-type?
|
||||
data-chain-id)))
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[promesa.core :as promesa]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||
data-store]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
|
||||
[utils.hex :as hex]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(defn eth-sign
|
||||
[password address data]
|
||||
@@ -38,13 +22,3 @@
|
||||
(-> (rpc/wallet-hash-message-eip-191 data)
|
||||
(promesa/then #(rpc/wallet-sign-message % address password))
|
||||
(promesa/then hex/prefix-hex)))
|
||||
|
||||
(defn eth-sign-typed-data
|
||||
[password address data chain-id-eip155 version]
|
||||
(let [legacy? (= version :v1)
|
||||
chain-id (networks/eip155->chain-id chain-id-eip155)]
|
||||
(rpc/wallet-safe-sign-typed-data data
|
||||
address
|
||||
password
|
||||
chain-id
|
||||
legacy?)))
|
||||
|
||||
@@ -51,12 +51,16 @@
|
||||
(transforms/js-stringify 0)))
|
||||
|
||||
(defn beautify-transaction
|
||||
[tx]
|
||||
(-> tx
|
||||
clj->js
|
||||
(js/JSON.stringify nil 2)))
|
||||
|
||||
(defn transaction-hex-values->number
|
||||
[tx]
|
||||
(let [hex->number #(-> % (subs 2) native-module/hex-to-number)]
|
||||
(-> tx
|
||||
(format-tx-hex-values hex->number)
|
||||
clj->js
|
||||
(js/JSON.stringify nil 2))))
|
||||
(format-tx-hex-values hex->number))))
|
||||
|
||||
(defn- gwei->hex
|
||||
[gwei]
|
||||
@@ -121,10 +125,14 @@
|
||||
tx-priority
|
||||
suggested-fees)
|
||||
prepare-transaction-for-rpc
|
||||
(rpc/wallet-build-transaction chain-id))]
|
||||
(rpc/wallet-build-transaction chain-id))
|
||||
estimated-time (rpc/wallet-get-transaction-estimated-time
|
||||
chain-id
|
||||
(:maxPriorityFeePerGas suggested-fees))]
|
||||
{:tx-args tx-args
|
||||
:tx-hash message-to-sign
|
||||
:suggested-fees suggested-fees}))
|
||||
:suggested-fees suggested-fees
|
||||
:estimated-time estimated-time}))
|
||||
|
||||
(defn sign-transaction
|
||||
[password address tx-hash tx-args chain-id]
|
||||
@@ -141,3 +149,11 @@
|
||||
tx-args
|
||||
signature)]
|
||||
tx))
|
||||
|
||||
(defn transactions->display-array
|
||||
[data]
|
||||
(remove (fn [[k v]]
|
||||
(or (= v "0x")
|
||||
(= k :MultiTransactionID)
|
||||
(= k :Symbol)))
|
||||
data))
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.utils.typed-data
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
|
||||
[utils.number :as number]))
|
||||
|
||||
(declare flatten-data)
|
||||
|
||||
(defn- format-flattened-key
|
||||
[k]
|
||||
(cond
|
||||
(keyword? k) (name k)
|
||||
(number? k) (str k)
|
||||
(string? k) k
|
||||
:else "unsupported-key"))
|
||||
|
||||
(defn- flatten-map
|
||||
[data path]
|
||||
(reduce-kv (fn [acc k v]
|
||||
(->> (format-flattened-key k)
|
||||
(conj path)
|
||||
(flatten-data v acc)))
|
||||
[]
|
||||
data))
|
||||
|
||||
(defn- flatten-vec
|
||||
[data path]
|
||||
(->> data
|
||||
(map-indexed vector)
|
||||
(reduce (fn [acc [idx v]]
|
||||
(->> (str idx)
|
||||
(conj path)
|
||||
(flatten-data v acc)))
|
||||
[])))
|
||||
|
||||
(defn flatten-data
|
||||
"Recursively flatten a map or vector into a flat vector.
|
||||
|
||||
e.g. `[[[\"person\" \"first-name\"] \"Rich\"]
|
||||
[[[\"person\" \"last-name\"] \"Hickey\"]]]`"
|
||||
([value]
|
||||
(flatten-data value [] []))
|
||||
([value acc path]
|
||||
(cond
|
||||
(map? value) (into acc (flatten-map value path))
|
||||
(vector? value) (into acc (flatten-vec value path))
|
||||
:else (conj acc [path value]))))
|
||||
|
||||
(defn format-fields
|
||||
"Format the fields into maps with `:label` & `:value`, where the label
|
||||
is the flattened keys joined with a separator
|
||||
|
||||
e.g. `{:label \"person: first-name:\" :value \"Rich\"}`"
|
||||
[data separator]
|
||||
(mapv (fn [[kv v]]
|
||||
{:label (-> separator
|
||||
(string/join kv)
|
||||
(str separator)
|
||||
string/trim)
|
||||
:value v})
|
||||
data))
|
||||
|
||||
(defn flatten-typed-data
|
||||
"Flatten typed data and prepare it for UI"
|
||||
[typed-data]
|
||||
(-> typed-data
|
||||
(select-keys [:domain :message])
|
||||
flatten-data
|
||||
(format-fields ": ")))
|
||||
|
||||
(defn get-chain-id
|
||||
"Returns the `:chain-id` from typed data if it's present and if the EIP712 domain defines it. Without
|
||||
the `:chain-id` in the domain type, it will not be signed as part of the typed-data."
|
||||
[typed-data]
|
||||
(let [chain-id-type? (->> typed-data
|
||||
:types
|
||||
:EIP712Domain
|
||||
(some #(= "chainId" (:name %))))
|
||||
data-chain-id (-> typed-data
|
||||
:domain
|
||||
:chainId
|
||||
number/parse-int)]
|
||||
(when chain-id-type?
|
||||
data-chain-id)))
|
||||
|
||||
(defn sign
|
||||
[password address data chain-id-eip155 version]
|
||||
(let [legacy? (= version :v1)
|
||||
chain-id (networks/eip155->chain-id chain-id-eip155)]
|
||||
(rpc/wallet-safe-sign-typed-data data
|
||||
address
|
||||
password
|
||||
chain-id
|
||||
legacy?)))
|
||||
|
||||
(defn typed-data-request?
|
||||
[method]
|
||||
(contains?
|
||||
#{constants/wallet-connect-eth-sign-typed-v4-method
|
||||
constants/wallet-connect-eth-sign-typed-method}
|
||||
method))
|
||||
@@ -0,0 +1,52 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.utils.typed-data-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.typed-data :as sut]))
|
||||
|
||||
(deftest flatten-data-test
|
||||
(testing "correctly returns the fallback when key is not string/keyword/number"
|
||||
(is (match? [[["unsupported-key"] "value"]]
|
||||
(sut/flatten-data {[1 2] "value"}))))
|
||||
|
||||
(testing "correctly flattens a simple map"
|
||||
(is (match? [[["zero"] 0]
|
||||
[["one"] 1]
|
||||
[["2"] 2]]
|
||||
(sut/flatten-data {:zero 0
|
||||
"one" 1
|
||||
2 2}))))
|
||||
|
||||
(testing "correctly flattens a simple vec"
|
||||
(is (match? [[["0"] "zero"] [["1"] "one"]]
|
||||
(sut/flatten-data ["zero" "one"]))))
|
||||
|
||||
(testing "correctly flattens a nested map"
|
||||
(is (match? [[["nested" "child"] "child value"]
|
||||
[["nested" "nested" "0"] "child one"]
|
||||
[["nested" "nested" "1"] "child two"]
|
||||
[["flat"] "child value"]]
|
||||
(sut/flatten-data {:nested {:child "child value"
|
||||
:nested ["child one" "child two"]}
|
||||
:flat "child value"}))))
|
||||
|
||||
(testing "correctly flattens a nested vector"
|
||||
(is (match? [[["0" "flat"] 1]
|
||||
[["0" "nested-vector" "0"] 1]
|
||||
[["0" "nested-vector" "1"] 2]
|
||||
[["0" "nested-map" "one"] 1]]
|
||||
(sut/flatten-data [{:flat 1
|
||||
:nested-vector [1 2]
|
||||
:nested-map {:one 1}}])))))
|
||||
|
||||
(deftest flatten-typed-data-test
|
||||
(testing "successfully extracts, flattens and formats the typed data"
|
||||
(is (match? [{:label "domain: chain-id:" :value 1}
|
||||
{:label "message: to: address:" :value "0x"}
|
||||
{:label "message: from: address:" :value "0x"}
|
||||
{:label "message: amount:" :value "0x"}]
|
||||
(sut/flatten-typed-data {:domain {:chain-id 1}
|
||||
:types {:Tx [{:name "to"
|
||||
:type "address"}]}
|
||||
:message {:to {:address "0x"}
|
||||
:from {:address "0x"}
|
||||
:amount "0x"}})))))
|
||||
@@ -4,6 +4,7 @@
|
||||
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||
data-store]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.typed-data :as typed-data]
|
||||
[utils.string]))
|
||||
|
||||
(rf/reg-sub
|
||||
@@ -16,6 +17,14 @@
|
||||
:<- [:wallet-connect/current-request]
|
||||
:-> :display-data)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/current-request-method
|
||||
:<- [:wallet-connect/current-request]
|
||||
(fn [request]
|
||||
(-> request
|
||||
:event
|
||||
data-store/get-request-method)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/current-request-account-details
|
||||
:<- [:wallet-connect/current-request-address]
|
||||
@@ -45,3 +54,8 @@
|
||||
:wallet-connect/current-request-network
|
||||
:<- [:wallet-connect/chain-id]
|
||||
networks/chain-id->network-details)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/typed-data-request?
|
||||
:<- [:wallet-connect/current-request-method]
|
||||
typed-data/typed-data-request?)
|
||||
|
||||
@@ -54,20 +54,23 @@
|
||||
:<- [:profile/currency-symbol]
|
||||
(fn [[chain-id max-fees-wei transaction eth-token currency currency-symbol]]
|
||||
(when transaction
|
||||
(let [max-fees-ether (money/wei->ether max-fees-wei)
|
||||
max-fees-fiat (wallet-utils/calculate-token-fiat-value {:currency currency
|
||||
:balance max-fees-ether
|
||||
:token eth-token})
|
||||
max-fees-fiat-formatted (-> (wallet-utils/get-standard-crypto-format eth-token max-fees-ether)
|
||||
(wallet-utils/get-standard-fiat-format currency-symbol
|
||||
max-fees-fiat))
|
||||
balance (-> eth-token
|
||||
(get-in [:balances-per-chain chain-id :raw-balance])
|
||||
money/bignumber)
|
||||
tx-value (money/bignumber (:value transaction))
|
||||
total-transaction-value (money/add max-fees-wei tx-value)]
|
||||
(let [max-fees-ether (money/wei->ether max-fees-wei)
|
||||
max-fees-fiat (wallet-utils/calculate-token-fiat-value {:currency currency
|
||||
:balance max-fees-ether
|
||||
:token eth-token})
|
||||
max-fees-fiat-formatted (-> (wallet-utils/get-standard-crypto-format eth-token
|
||||
max-fees-ether)
|
||||
(wallet-utils/get-standard-fiat-format currency-symbol
|
||||
max-fees-fiat))
|
||||
balance (-> eth-token
|
||||
(get-in [:balances-per-chain chain-id :raw-balance])
|
||||
money/bignumber)
|
||||
tx-value (money/bignumber (:value transaction))
|
||||
total-transaction-value (money/add max-fees-wei tx-value)
|
||||
estimated-time-formatted (wallet-utils/estimated-time-format (:estimated-time transaction))]
|
||||
{:total-transaction-value total-transaction-value
|
||||
:balance balance
|
||||
:estimated-time estimated-time-formatted
|
||||
:max-fees max-fees-wei
|
||||
:max-fees-fiat-value max-fees-fiat
|
||||
:max-fees-fiat-formatted max-fees-fiat-formatted
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v2.3.0",
|
||||
"commit-sha1": "effde33d493ff52b66c8013067c9aa6444d84473",
|
||||
"src-sha256": "1rd0mczdkvjm9pbmza234v1jy1bvqh3ni2xck1l42ha4sld2aqjl"
|
||||
"version": "fix/suggested-path-after-kp-deletion",
|
||||
"commit-sha1": "6f386908f61807353482aad8ed3abc56a21dd2ef",
|
||||
"src-sha256": "1gd9kb3b86g9g98sqxxc7kp22kbr6z75f11p6q2sf3vwrx37yb3j"
|
||||
}
|
||||
|
||||
@@ -111,11 +111,13 @@ def get_app_path():
|
||||
return app_path
|
||||
|
||||
|
||||
log_file_names = ['geth', 'requests', 'Status']
|
||||
def pull_geth(driver):
|
||||
result = driver.pull_file(get_app_path() + 'geth.log')
|
||||
return base64.b64decode(result)
|
||||
|
||||
|
||||
def pull_log_file(driver, log_file_name):
|
||||
result = driver.pull_file(get_app_path() + '%s.log' % log_file_name)
|
||||
def pull_requests_log(driver):
|
||||
result = driver.pull_file(get_app_path() + 'requests.log')
|
||||
return base64.b64decode(result)
|
||||
|
||||
|
||||
@@ -214,7 +216,7 @@ class SingleDeviceTestCase(AbstractTestCase):
|
||||
self.print_sauce_lab_info(self.driver)
|
||||
try:
|
||||
self.add_alert_text_to_report(self.driver)
|
||||
geth_content = pull_log_file(self.driver, 'geth')
|
||||
geth_content = pull_geth(self.driver)
|
||||
self.driver.quit()
|
||||
if pytest_config_global['docker']:
|
||||
appium_container.stop_container()
|
||||
@@ -277,7 +279,7 @@ class SauceMultipleDeviceTestCase(AbstractTestCase):
|
||||
self.add_alert_text_to_report(self.drivers[driver])
|
||||
geth_names.append(
|
||||
'%s_geth%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number)))
|
||||
geth_contents.append(pull_log_file(self.drivers[driver], log_file_name='geth'))
|
||||
geth_contents.append(pull_geth(self.drivers[driver]))
|
||||
self.drivers[driver].quit()
|
||||
except (WebDriverException, AttributeError):
|
||||
pass
|
||||
@@ -381,12 +383,14 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
|
||||
try:
|
||||
self.print_sauce_lab_info(self.drivers[driver])
|
||||
self.add_alert_text_to_report(self.drivers[driver])
|
||||
for log in log_file_names:
|
||||
log_names.append(
|
||||
'%s_%s%s.log' % (test_suite_data.current_test.name, log, str(self.drivers[driver].number)))
|
||||
log_contents.append(pull_log_file(self.drivers[driver], log_file_name=log))
|
||||
except (WebDriverException, AttributeError, RemoteDisconnected, ProtocolError) as e:
|
||||
raise e
|
||||
log_names.append(
|
||||
'%s_geth%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number)))
|
||||
log_contents.append(pull_geth(self.drivers[driver]))
|
||||
log_names.append(
|
||||
'%s_requests%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number)))
|
||||
log_contents.append(pull_requests_log(self.drivers[driver]))
|
||||
except (WebDriverException, AttributeError, RemoteDisconnected, ProtocolError):
|
||||
pass
|
||||
finally:
|
||||
try:
|
||||
logs = {log_names[i]: log_contents[i] for i in range(len(log_names))}
|
||||
@@ -416,14 +420,15 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
|
||||
try:
|
||||
for i, driver in cls.drivers.items():
|
||||
if group_setup_failed:
|
||||
for log in log_file_names:
|
||||
log_contents.append(pull_log_file(driver=driver, log_file_name=log))
|
||||
log_names.append('%s_%s%s.log' % (cls.__name__, log, i))
|
||||
log_contents.append(pull_geth(driver=driver))
|
||||
log_names.append('%s_geth%s.log' % (cls.__name__, i))
|
||||
log_contents.append(pull_requests_log(driver=driver))
|
||||
log_names.append('%s_requests%s.log' % (cls.__name__, i))
|
||||
session_id = driver.session_id
|
||||
try:
|
||||
sauce.jobs.update_job(username=sauce_username, job_id=session_id, name=cls.__name__)
|
||||
except (RemoteDisconnected, SauceException, requests.exceptions.ConnectionError) as e:
|
||||
raise e
|
||||
except (RemoteDisconnected, SauceException, requests.exceptions.ConnectionError):
|
||||
pass
|
||||
try:
|
||||
driver.quit()
|
||||
except WebDriverException:
|
||||
|
||||
@@ -747,8 +747,8 @@ class BaseView(object):
|
||||
return items_in_logcat
|
||||
|
||||
def find_values_in_geth(self, *args):
|
||||
from tests.base_test_case import pull_log_file
|
||||
b64_log = pull_log_file(self.driver, log_file_name='geth')
|
||||
from tests.base_test_case import pull_geth
|
||||
b64_log = pull_geth(self.driver)
|
||||
file = base64.b64decode(b64_log)
|
||||
result = False
|
||||
for value in args:
|
||||
|
||||
@@ -263,20 +263,20 @@ class SignInView(BaseView):
|
||||
# self.identifiers_button.wait_and_click(30)
|
||||
if enable_notifications:
|
||||
self.enable_notifications_button.wait_and_click()
|
||||
# self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
|
||||
# for _ in range(3):
|
||||
self.allow_button.click_if_shown(sec=10)
|
||||
# self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
|
||||
# self.enable_notifications_button.click_if_shown()
|
||||
# if self.chats_tab.is_element_displayed():
|
||||
# break
|
||||
self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
|
||||
for _ in range(3):
|
||||
self.allow_button.click_if_shown(sec=10)
|
||||
self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
|
||||
self.enable_notifications_button.click_if_shown()
|
||||
if self.chats_tab.is_element_displayed():
|
||||
break
|
||||
else:
|
||||
self.maybe_later_button.wait_and_click()
|
||||
# for _ in range(3):
|
||||
# self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
|
||||
# self.maybe_later_button.click_if_shown()
|
||||
# if self.chats_tab.is_element_displayed():
|
||||
# break
|
||||
for _ in range(3):
|
||||
self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
|
||||
self.maybe_later_button.click_if_shown()
|
||||
if self.chats_tab.is_element_displayed():
|
||||
break
|
||||
self.chats_tab.wait_for_visibility_of_element(30)
|
||||
self.driver.info("## New multiaccount is created successfully!", device=False)
|
||||
return self.get_home_view()
|
||||
|
||||
@@ -1124,6 +1124,7 @@
|
||||
"help-improve-status": "Help improve Status",
|
||||
"help-us-improve-status": "Help us improve Status",
|
||||
"here-is-a-cat-in-a-box-instead": "Here’s a cat in a box instead",
|
||||
"hex": "Hex",
|
||||
"hide": "Hide",
|
||||
"hide-content-when-switching-apps": "Block screenshots",
|
||||
"hide-content-when-switching-apps-ios": "Hide preview",
|
||||
@@ -1737,6 +1738,7 @@
|
||||
"not-connected-nodes": "Not connected to a status node",
|
||||
"not-connected-to-peers": "Not connected to any peers",
|
||||
"not-enough-assets": "Not enough assets to complete transaction",
|
||||
"not-enough-assets-for-transaction": "Not enough assets for transaction",
|
||||
"not-enough-assets-to-pay-gas-fees": "Not enough assets to pay gas fees",
|
||||
"not-enough-liquidity": "Not enough liquidity. Lower token amount or try again later.",
|
||||
"not-enough-snt": "Not enough SNT",
|
||||
|
||||
Reference in New Issue
Block a user