Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3fd33d63a | ||
|
|
08fea7fe5f | ||
|
|
792caf5259 | ||
|
|
c02d97d380 | ||
|
|
3001fa91e9 | ||
|
|
2714c7b9e5 | ||
|
|
307155a4ca | ||
|
|
a5ef314d6a | ||
|
|
2ba16e6762 | ||
|
|
6acda08ebb | ||
|
|
90166ad45a | ||
|
|
ef8490961a | ||
|
|
e4ae78bb25 | ||
|
|
ea07780e9c | ||
|
|
ff569f328a | ||
|
|
e4b42fc0ca | ||
|
|
9397dd46e8 | ||
|
|
34d6b3c1d5 | ||
|
|
3c7d299ef7 | ||
|
|
43a8be9d52 | ||
|
|
adff7a5120 | ||
|
|
4db4b5c84b | ||
|
|
23d84a54fc | ||
|
|
5d51ae55b5 | ||
|
|
d51d88fc0b | ||
|
|
bf8fa45e52 |
@@ -55,26 +55,36 @@
|
||||
theme))}])]))
|
||||
|
||||
(defn- left-title
|
||||
[{:keys [title blur?]}]
|
||||
[{:keys [title blur? title-icon]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style style/title-container}
|
||||
[text/text
|
||||
{:weight :regular
|
||||
:size :paragraph-2
|
||||
:style (style/title blur? theme)}
|
||||
title]]))
|
||||
title]
|
||||
(when title-icon
|
||||
[icons/icon title-icon
|
||||
{:accessibility-label :title-icon
|
||||
:size 12
|
||||
:color (if blur?
|
||||
colors/neutral-40
|
||||
(colors/theme-colors colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme))}])]))
|
||||
|
||||
(defn- left-side
|
||||
"The description can either be given as a string `subtitle-type` or a component `custom-subtitle`"
|
||||
[{:keys [title status size blur? custom-subtitle icon subtitle subtitle-type subtitle-color icon-color
|
||||
customization-color network-image emoji]
|
||||
customization-color network-image emoji title-icon]
|
||||
:as props}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style style/left-side}
|
||||
[left-title
|
||||
{:title title
|
||||
:blur? blur?
|
||||
:theme theme}]
|
||||
[rn/view
|
||||
[left-title
|
||||
{:title title
|
||||
:title-icon title-icon
|
||||
:blur? blur?}]]
|
||||
(if (= status :loading)
|
||||
[left-loading
|
||||
{:size size
|
||||
@@ -132,6 +142,7 @@
|
||||
[:subtitle {:optional true} [:maybe [:or :string :double]]]
|
||||
[:custom-subtitle {:optional true} [:maybe fn?]]
|
||||
[:icon {:optional true} [:maybe :keyword]]
|
||||
[:title-icon {:optional true} [:maybe :keyword]]
|
||||
[:emoji {:optional true} [:maybe :string]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:network-image {:optional true} [:maybe :schema.common/image-source]]
|
||||
|
||||
@@ -59,12 +59,15 @@
|
||||
- :image-source - resource - image to display on :network, :collectible and :user
|
||||
- :theme - :light / :dark"
|
||||
[{:keys [label customization-color type container-style]
|
||||
:as props
|
||||
:or {customization-color colors/neutral-80-opa-5}}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
:as props}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
default-color (if (= theme :light)
|
||||
colors/neutral-80-opa-5
|
||||
colors/white-opa-5)
|
||||
color (or customization-color default-color)]
|
||||
[rn/view
|
||||
{:accessibility-label :container
|
||||
:style (merge (style/main (assoc props :customization-color customization-color)
|
||||
:style (merge (style/main (assoc props :customization-color color)
|
||||
theme)
|
||||
container-style)}
|
||||
[left-view props]
|
||||
|
||||
@@ -295,6 +295,8 @@
|
||||
|
||||
(def ^:const token-sort-priority {"SNT" 1 "STT" 1 "ETH" 2 "DAI" 3})
|
||||
|
||||
(def ^:const token-display-precision 6)
|
||||
|
||||
(def ^:const dapp-permission-contact-code "contact-code")
|
||||
(def ^:const dapp-permission-web3 "web3")
|
||||
(def ^:const dapp-permission-qr-code "qr-code")
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
{:key :i/copy}
|
||||
{:key nil
|
||||
:value "None"}]}
|
||||
{:type :select
|
||||
:key :title-icon
|
||||
:options [{:key :i/chevron-right}
|
||||
{:key :i/copy}
|
||||
{:key nil
|
||||
:value "None"}]}
|
||||
{:type :select
|
||||
:key :right-content
|
||||
:options [{:key nil
|
||||
|
||||
@@ -445,7 +445,7 @@
|
||||
(defn transaction-path
|
||||
[{:keys [from-address to-address token-id-from token-address token-id-to route data
|
||||
slippage-percentage eth-transfer?]}]
|
||||
(let [{:keys [bridge-name amount-in bonder-fees from
|
||||
(let [{:keys [bridge-name amount-in from
|
||||
to]} route
|
||||
tx-data (transaction-data {:from-address from-address
|
||||
:to-address to-address
|
||||
@@ -453,6 +453,7 @@
|
||||
:route route
|
||||
:data data
|
||||
:eth-transfer? eth-transfer?})
|
||||
bonder-fees (-> route :bounder-fees money/to-string)
|
||||
to-chain-id (:chain-id to)
|
||||
from-chain-id (:chain-id from)]
|
||||
(cond-> {:BridgeName bridge-name
|
||||
|
||||
@@ -233,13 +233,12 @@
|
||||
|
||||
(defn new->old-route-path
|
||||
[new-path]
|
||||
(let [bonder-fees (:tx-bonder-fees new-path)
|
||||
token-fees (+ (money/wei->ether bonder-fees)
|
||||
(money/wei->ether (:tx-token-fees new-path)))]
|
||||
(let [bonder-fees (-> new-path :tx-bonder-fees money/bignumber)
|
||||
token-fees (-> new-path :tx-token-fees money/bignumber)]
|
||||
{:from (:from-chain new-path)
|
||||
:amount-in-locked (:amount-in-locked new-path)
|
||||
:amount-in (:amount-in new-path)
|
||||
:max-amount-in "0x0"
|
||||
:max-amount-in (:max-amount-in new-path)
|
||||
:gas-fees {:gas-price "0"
|
||||
:base-fee (send-utils/convert-to-gwei (:tx-base-fee
|
||||
new-path)
|
||||
|
||||
@@ -104,16 +104,19 @@
|
||||
:wallet/wallet-send-tx-type :tx/send
|
||||
:wallet/wallet-send-fee-fiat-formatted "$5,00"
|
||||
:wallet/sending-collectible? false
|
||||
:wallet/total-amount (money/bignumber "250")})
|
||||
:wallet/send-total-amount-formatted "250 ETH"
|
||||
:wallet/total-amount (money/bignumber "250")
|
||||
:wallet/bridge-to-network-details nil
|
||||
:wallet/send-amount-fixed ""
|
||||
:wallet/send-display-token-decimals 5})
|
||||
|
||||
(h/describe "Send > input amount screen"
|
||||
(h/setup-restorable-re-frame)
|
||||
|
||||
(h/test "Default render"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 2))
|
||||
(h/render-with-theme-provider [input-amount/view
|
||||
{:crypto-decimals 2
|
||||
:limit-crypto (money/bignumber 250)
|
||||
{:limit-crypto (money/bignumber 250)
|
||||
:initial-crypto-currency? false}])
|
||||
(h/is-truthy (h/get-by-text "0"))
|
||||
(h/is-truthy (h/get-by-text "USD"))
|
||||
@@ -122,12 +125,11 @@
|
||||
(h/is-disabled (h/get-by-label-text :button-one)))
|
||||
|
||||
(h/test "Fill token input and confirm"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 10))
|
||||
|
||||
(let [on-confirm (h/mock-fn)]
|
||||
(h/render-with-theme-provider [input-amount/view
|
||||
{:crypto-decimals 10
|
||||
:limit-crypto (money/bignumber 1000)
|
||||
{:limit-crypto (money/bignumber 1000)
|
||||
:on-confirm on-confirm
|
||||
:initial-crypto-currency? true}])
|
||||
|
||||
@@ -147,10 +149,9 @@
|
||||
(h/was-called on-confirm)))))))
|
||||
|
||||
(h/test "Try to fill more than limit"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 1))
|
||||
(h/render-with-theme-provider [input-amount/view
|
||||
{:crypto-decimals 1
|
||||
:limit-crypto (money/bignumber 1)}])
|
||||
{:limit-crypto (money/bignumber 1)}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
|
||||
@@ -159,11 +160,10 @@
|
||||
(h/is-truthy (h/get-by-label-text :container-error)))
|
||||
|
||||
(h/test "Switch from crypto to fiat and check limit"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 1))
|
||||
(h/render-with-theme-provider [input-amount/view
|
||||
{:crypto-decimals 1
|
||||
:limit-crypto (money/bignumber 10)
|
||||
:on-confirm #()}])
|
||||
{:limit-crypto (money/bignumber 10)
|
||||
:on-confirm #()}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
(ns status-im.contexts.wallet.send.input-amount.estimated-fees
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.contexts.wallet.send.input-amount.style :as style]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- bonder-fee-info-sheet
|
||||
[]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:title (i18n/label :t/understanding-bonder-fees-title)}]
|
||||
[rn/view {:style {:padding-horizontal 20}}
|
||||
[quo/text
|
||||
{:weight :regular
|
||||
:size :paragraph-2}
|
||||
(i18n/label :t/understanding-bonder-fees-description)]]])
|
||||
|
||||
(defn- show-bonder-fee-info
|
||||
[]
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet {:content bonder-fee-info-sheet}]))
|
||||
|
||||
(defn- received-amount
|
||||
[{:keys [loading-routes?]}]
|
||||
(let [amount (rf/sub [:wallet/send-total-amount-formatted])
|
||||
tx-type (rf/sub [:wallet/wallet-send-tx-type])
|
||||
{:keys [full-name]} (rf/sub [:wallet/bridge-to-network-details])]
|
||||
[quo/data-item
|
||||
(cond-> {:container-style style/amount-data-item
|
||||
:status (if loading-routes? :loading :default)
|
||||
:size :small
|
||||
:title (i18n/label :t/recipient-gets)
|
||||
:subtitle amount}
|
||||
|
||||
(= tx-type :tx/bridge)
|
||||
(assoc
|
||||
:title-icon :i/info
|
||||
:title (i18n/label :t/bridged-to
|
||||
{:network full-name})
|
||||
:on-press show-bonder-fee-info))]))
|
||||
|
||||
(defn view
|
||||
[{:keys [loading-routes? fees]}]
|
||||
[rn/view {:style style/estimated-fees-container}
|
||||
(when (ff/enabled? ::ff/wallet.advanced-sending)
|
||||
[rn/view {:style style/estimated-fees-content-container}
|
||||
[quo/button
|
||||
{:icon-only? true
|
||||
:type :outline
|
||||
:size 32
|
||||
:inner-style {:opacity 1}
|
||||
:accessibility-label :advanced-button
|
||||
:disabled? loading-routes?
|
||||
:on-press not-implemented/alert}
|
||||
:i/advanced]])
|
||||
[quo/data-item
|
||||
{:container-style style/fees-data-item
|
||||
:status (if loading-routes? :loading :default)
|
||||
:size :small
|
||||
:title (i18n/label :t/fees)
|
||||
:subtitle fees}]
|
||||
[received-amount {:loading-routes? loading-routes?}]])
|
||||
@@ -11,45 +11,17 @@
|
||||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||
[status-im.contexts.wallet.common.asset-list.view :as asset-list]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.send.input-amount.estimated-fees :as estimated-fees]
|
||||
[status-im.contexts.wallet.send.input-amount.style :as style]
|
||||
[status-im.contexts.wallet.send.routes.view :as routes]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert]
|
||||
[status-im.feature-flags :as ff]
|
||||
[status-im.setup.hot-reload :as hot-reload]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- estimated-fees
|
||||
[{:keys [loading-routes? fees amount]}]
|
||||
[rn/view {:style style/estimated-fees-container}
|
||||
(when (ff/enabled? ::ff/wallet.advanced-sending)
|
||||
[rn/view {:style style/estimated-fees-content-container}
|
||||
[quo/button
|
||||
{:icon-only? true
|
||||
:type :outline
|
||||
:size 32
|
||||
:inner-style {:opacity 1}
|
||||
:accessibility-label :advanced-button
|
||||
:disabled? loading-routes?
|
||||
:on-press #(js/alert "Not implemented yet")}
|
||||
:i/advanced]])
|
||||
[quo/data-item
|
||||
{:container-style style/fees-data-item
|
||||
:status (if loading-routes? :loading :default)
|
||||
:size :small
|
||||
:title (i18n/label :t/fees)
|
||||
:subtitle fees}]
|
||||
[quo/data-item
|
||||
{:container-style style/amount-data-item
|
||||
:status (if loading-routes? :loading :default)
|
||||
:size :small
|
||||
:title (i18n/label :t/recipient-gets)
|
||||
:subtitle amount}]])
|
||||
|
||||
(defn- every-network-value-is-zero?
|
||||
[sender-network-values]
|
||||
(every? (fn [{:keys [total-amount]}]
|
||||
@@ -165,7 +137,6 @@
|
||||
;; for component tests only
|
||||
[{default-on-confirm :on-confirm
|
||||
default-limit-crypto :limit-crypto
|
||||
default-crypto-decimals :crypto-decimals
|
||||
on-navigate-back :on-navigate-back
|
||||
button-one-label :button-one-label
|
||||
button-one-props :button-one-props
|
||||
@@ -199,17 +170,13 @@
|
||||
:market-values-per-currency
|
||||
currency
|
||||
:price)
|
||||
token-decimals (-> token
|
||||
utils/token-usd-price
|
||||
utils/one-cent-value
|
||||
utils/calc-max-crypto-decimals)
|
||||
token-decimals (rf/sub [:wallet/send-display-token-decimals])
|
||||
[input-state set-input-state] (rn/use-state controlled-input/init-state)
|
||||
clear-input! #(set-input-state controlled-input/delete-all)
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||
route (rf/sub [:wallet/wallet-send-route])
|
||||
on-confirm (or default-on-confirm handle-on-confirm)
|
||||
crypto-decimals (or token-decimals default-crypto-decimals)
|
||||
max-limit (if crypto-currency?
|
||||
(utils/cut-crypto-decimals-to-fit-usd-cents
|
||||
token-balance
|
||||
@@ -221,15 +188,8 @@
|
||||
(controlled-input/input-error input-state)))
|
||||
amount-in-crypto (if crypto-currency?
|
||||
input-value
|
||||
(number/remove-trailing-zeroes
|
||||
(.toFixed (/ input-value conversion-rate)
|
||||
crypto-decimals)))
|
||||
total-amount-receiver (rf/sub [:wallet/total-amount true])
|
||||
amount-text (str (number/remove-trailing-zeroes
|
||||
(.toFixed total-amount-receiver
|
||||
(min token-decimals 6)))
|
||||
" "
|
||||
token-symbol)
|
||||
(rf/sub [:wallet/send-amount-fixed
|
||||
(/ input-value conversion-rate)]))
|
||||
show-select-asset-sheet #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
@@ -382,10 +342,9 @@
|
||||
[not-enough-asset])
|
||||
(when (or (and (not no-routes-found?) (or loading-routes? route))
|
||||
not-enough-asset?)
|
||||
[estimated-fees
|
||||
[estimated-fees/view
|
||||
{:loading-routes? loading-routes?
|
||||
:fees fee-formatted
|
||||
:amount amount-text}])
|
||||
:fees fee-formatted}])
|
||||
(when show-no-routes?
|
||||
[no-routes-found])
|
||||
[quo/bottom-actions
|
||||
@@ -417,7 +376,7 @@
|
||||
:delete-key? true
|
||||
:on-press (fn [c]
|
||||
(let [new-text (str input-value c)
|
||||
max-decimals (if crypto-currency? crypto-decimals 2)
|
||||
max-decimals (if crypto-currency? token-decimals 2)
|
||||
regex-pattern (str "^\\d*\\.?\\d{0," max-decimals "}$")
|
||||
regex (re-pattern regex-pattern)]
|
||||
(when (re-matches regex new-text)
|
||||
|
||||
@@ -243,37 +243,40 @@
|
||||
[{:keys [network-values token-symbol on-press on-long-press receiver? loading-routes?
|
||||
token-not-supported-in-receiver-networks?]}]
|
||||
[rn/view
|
||||
(map-indexed (fn [index
|
||||
{chain-id :chain-id
|
||||
network-value-type :type
|
||||
total-amount :total-amount}]
|
||||
(let [status (cond (and (= network-value-type :not-available)
|
||||
loading-routes?
|
||||
token-not-supported-in-receiver-networks?)
|
||||
:loading
|
||||
(= network-value-type :not-available)
|
||||
:disabled
|
||||
:else network-value-type)]
|
||||
[rn/view
|
||||
{:key (str (if receiver? "to" "from") "-" chain-id)
|
||||
:style {:margin-top (if (pos? index) 11 7.5)}}
|
||||
[quo/network-bridge
|
||||
{:amount (if (= network-value-type :not-available)
|
||||
(i18n/label :t/not-available)
|
||||
(str total-amount " " token-symbol))
|
||||
:network (network-utils/id->network chain-id)
|
||||
:status status
|
||||
:on-press #(when (not loading-routes?)
|
||||
(cond
|
||||
(= network-value-type :edit)
|
||||
(open-preferences)
|
||||
on-press (on-press chain-id total-amount)))
|
||||
:on-long-press #(when (and (not loading-routes?) (not= status :disabled))
|
||||
(cond
|
||||
(= network-value-type :add)
|
||||
(open-preferences)
|
||||
on-long-press (on-long-press chain-id total-amount)))}]]))
|
||||
network-values)])
|
||||
(doall
|
||||
(map-indexed (fn [index
|
||||
{chain-id :chain-id
|
||||
network-value-type :type
|
||||
total-amount :total-amount}]
|
||||
(let [status (cond (and (= network-value-type :not-available)
|
||||
loading-routes?
|
||||
token-not-supported-in-receiver-networks?)
|
||||
:loading
|
||||
(= network-value-type :not-available)
|
||||
:disabled
|
||||
:else network-value-type)
|
||||
amount-formatted (-> (rf/sub [:wallet/send-amount-fixed total-amount])
|
||||
(str " " token-symbol))]
|
||||
^{:key (str (if receiver? "to" "from") "-" chain-id)}
|
||||
[rn/view
|
||||
{:style {:margin-top (if (pos? index) 11 7.5)}}
|
||||
[quo/network-bridge
|
||||
{:amount (if (= network-value-type :not-available)
|
||||
(i18n/label :t/not-available)
|
||||
amount-formatted)
|
||||
:network (network-utils/id->network chain-id)
|
||||
:status status
|
||||
:on-press #(when (not loading-routes?)
|
||||
(cond
|
||||
(= network-value-type :edit)
|
||||
(open-preferences)
|
||||
on-press (on-press chain-id total-amount)))
|
||||
:on-long-press #(when (and (not loading-routes?) (not= status :disabled))
|
||||
(cond
|
||||
(= network-value-type :add)
|
||||
(open-preferences)
|
||||
on-long-press (on-long-press chain-id total-amount)))}]]))
|
||||
network-values))])
|
||||
|
||||
(defn render-network-links
|
||||
[{:keys [network-links sender-network-values]}]
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
(ns status-im.contexts.wallet.send.transaction-confirmation.account-summary
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.send.transaction-confirmation.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- account-summary-header
|
||||
[{:keys [label accessibility-label]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label accessibility-label}
|
||||
label]))
|
||||
|
||||
(defn- current-user-account-summary
|
||||
[{:keys [network-values]}]
|
||||
(let [{:keys [color emoji name address]} (rf/sub [:wallet/current-viewing-account])]
|
||||
[quo/summary-info
|
||||
{:type :status-account
|
||||
:networks? true
|
||||
:values network-values
|
||||
:account-props {:customization-color color
|
||||
:size 32
|
||||
:emoji emoji
|
||||
:type :default
|
||||
:name name
|
||||
:address (utils/get-shortened-address address)}}]))
|
||||
|
||||
(defn- recipient-account-summary
|
||||
[{:keys [network-values]}]
|
||||
(let [{:keys [label emoji customization-color recipient-type]} (rf/sub [:wallet/send-recipient])
|
||||
address (rf/sub [:wallet/send-to-address])
|
||||
shortened-address (utils/get-shortened-address address)
|
||||
summary-type (condp = recipient-type
|
||||
:saved-address :saved-account
|
||||
:account :status-account
|
||||
:address :account
|
||||
:account)]
|
||||
[quo/summary-info
|
||||
{:type summary-type
|
||||
:networks? true
|
||||
:values network-values
|
||||
:account-props (cond-> {:customization-color customization-color
|
||||
:size 32
|
||||
:emoji emoji
|
||||
:type :default
|
||||
:name (or label address)
|
||||
:full-name label
|
||||
:address shortened-address}
|
||||
|
||||
(= recipient-type :address)
|
||||
(assoc :full-name "0 x"
|
||||
:monospace? true
|
||||
:lowercase? true))}]))
|
||||
|
||||
(defn from-summary
|
||||
[]
|
||||
(let [network-values (rf/sub [:wallet/network-values false])]
|
||||
[rn/view {:style style/summary-container}
|
||||
[account-summary-header
|
||||
{:label (i18n/label :t/from-capitalized)
|
||||
:accessibility-label :summary-from-label}]
|
||||
[current-user-account-summary {:network-values network-values}]]))
|
||||
|
||||
(defn to-summary
|
||||
[]
|
||||
(let [network-values (rf/sub [:wallet/network-values true])
|
||||
tx-type (rf/sub [:wallet/send-tx-type])]
|
||||
[rn/view {:style style/summary-container}
|
||||
[account-summary-header
|
||||
{:label (i18n/label :t/to-capitalized)
|
||||
:accessibility-label :summary-to-label}]
|
||||
(if (= tx-type :tx/bridge)
|
||||
[current-user-account-summary {:network-values network-values}]
|
||||
[recipient-account-summary {:network-values network-values}])]))
|
||||
@@ -1,13 +1,17 @@
|
||||
(ns status-im.contexts.wallet.send.transaction-confirmation.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def summary-container
|
||||
{:padding-horizontal 20
|
||||
:padding-bottom 16})
|
||||
|
||||
(def detail-item
|
||||
{:flex 1
|
||||
:height 36
|
||||
:background-color :transparent})
|
||||
|
||||
(def content-container
|
||||
{:padding-top 12
|
||||
{:padding-top 8
|
||||
:padding-horizontal 20
|
||||
:padding-bottom 32})
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
(ns status-im.contexts.wallet.send.transaction-confirmation.transaction-title
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.utils :as rn.utils]
|
||||
[status-im.contexts.wallet.send.transaction-confirmation.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- title-container
|
||||
[& argv]
|
||||
(let [[_ children] (rn.utils/get-props-and-children argv)]
|
||||
(into [rn/view {:style style/content-container}]
|
||||
children)))
|
||||
|
||||
(defn- title-row
|
||||
[& argv]
|
||||
(let [[_ children] (rn.utils/get-props-and-children argv)]
|
||||
(into [rn/view
|
||||
{:style {:flex-direction :row
|
||||
:margin-top 4}}]
|
||||
children)))
|
||||
|
||||
(defn- title-text
|
||||
[text]
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
text])
|
||||
|
||||
(defn- title-token
|
||||
[]
|
||||
(let [amount (rf/sub [:wallet/send-amount])
|
||||
token-display-name (rf/sub [:wallet/wallet-send-token-symbol])]
|
||||
[quo/summary-tag
|
||||
{:token token-display-name
|
||||
:label (str amount " " token-display-name)
|
||||
:type :token}]))
|
||||
|
||||
(defn- title-collectible
|
||||
[]
|
||||
(let [{:keys [collectible-data preview-url]} (rf/sub [:wallet/send-collectible])]
|
||||
[quo/summary-tag
|
||||
{:label (:name collectible-data)
|
||||
:image-source (:uri preview-url)
|
||||
:type :collectible}]))
|
||||
|
||||
(defn- title-network
|
||||
[{:keys [chain-id]}]
|
||||
(let [{:keys [full-name source network-name]} (rf/sub [:wallet/network-details-by-chain-id chain-id])]
|
||||
[quo/summary-tag
|
||||
{:label full-name
|
||||
:type :network
|
||||
:image-source source
|
||||
:customization-color network-name}]))
|
||||
|
||||
(defn- from-bridge-networks
|
||||
[]
|
||||
(let [chain-ids (rf/sub [:wallet/send-from-chain-ids])]
|
||||
[:<>
|
||||
(doall (map-indexed (fn [idx chain-id]
|
||||
^{:key (str "transaction-title" idx)}
|
||||
[title-row
|
||||
[title-text
|
||||
(if (zero? idx)
|
||||
(i18n/label :t/from)
|
||||
(str (i18n/label :t/and) " "))]
|
||||
[title-network {:chain-id chain-id}]])
|
||||
chain-ids))]))
|
||||
|
||||
(defn- to-bridge-network
|
||||
[]
|
||||
(let [chain-id (rf/sub [:wallet/send-bridge-to-chain-id])]
|
||||
[title-network {:chain-id chain-id}]))
|
||||
|
||||
(defn- title-account
|
||||
[]
|
||||
(let [{:keys [name emoji color]} (rf/sub [:wallet/current-viewing-account])]
|
||||
[quo/summary-tag
|
||||
{:label name
|
||||
:type :account
|
||||
:emoji emoji
|
||||
:customization-color color}]))
|
||||
|
||||
(defn- title-recipient
|
||||
[]
|
||||
(let [{:keys [recipient-type emoji label customization-color]} (rf/sub [:wallet/send-recipient])]
|
||||
[quo/summary-tag
|
||||
{:type recipient-type
|
||||
:emoji emoji
|
||||
:label label
|
||||
:customization-color customization-color}]))
|
||||
|
||||
(defn- bridge-title
|
||||
[]
|
||||
[title-container
|
||||
[title-row
|
||||
[title-text (i18n/label :t/bridge)]
|
||||
[title-token]]
|
||||
[from-bridge-networks]
|
||||
[title-row
|
||||
[title-text (i18n/label :t/to)]
|
||||
[to-bridge-network]]
|
||||
[title-row
|
||||
[title-text (i18n/label :t/in)]
|
||||
[title-account]]])
|
||||
|
||||
(defn- send-title
|
||||
[]
|
||||
(let [sending-collectible? (rf/sub [:wallet/sending-collectible?])]
|
||||
[title-container
|
||||
[title-row
|
||||
[title-text (i18n/label :t/send)]
|
||||
(if sending-collectible?
|
||||
[title-collectible]
|
||||
[title-token])]
|
||||
[title-row
|
||||
[title-text (i18n/label :t/from)]
|
||||
[title-account]]
|
||||
[title-row
|
||||
[title-text (i18n/label :t/to)]
|
||||
[title-recipient]]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [tx-type (rf/sub [:wallet/send-tx-type])]
|
||||
(condp = tx-type
|
||||
:tx/bridge [bridge-title]
|
||||
:tx/send [send-title]
|
||||
[send-title])))
|
||||
@@ -1,158 +1,17 @@
|
||||
(ns status-im.contexts.wallet.send.transaction-confirmation.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.send.transaction-confirmation.account-summary :as account-summary]
|
||||
[status-im.contexts.wallet.send.transaction-confirmation.style :as style]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[status-im.contexts.wallet.send.transaction-confirmation.transaction-title :as transaction-title]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn- transaction-title
|
||||
[{:keys [token-display-name amount account route to-network image-url transaction-type
|
||||
collectible? recipient]}]
|
||||
(let [to-network-name (:network-name to-network)
|
||||
to-network-color (if (= to-network-name :mainnet) :ethereum to-network-name)]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
(if (= transaction-type :tx/bridge)
|
||||
(i18n/label :t/bridge)
|
||||
(i18n/label :t/send))]
|
||||
[quo/summary-tag
|
||||
(cond-> {:token (if collectible? "" token-display-name)
|
||||
:label (str amount " " token-display-name)
|
||||
:type (if collectible? :collectible :token)}
|
||||
collectible? (assoc :image-source image-url))]]
|
||||
(if (= transaction-type :tx/bridge)
|
||||
(doall
|
||||
(map-indexed
|
||||
(fn [idx path]
|
||||
(let [from-network (:from path)
|
||||
chain-id (:chain-id from-network)
|
||||
network (rf/sub [:wallet/network-details-by-chain-id
|
||||
chain-id])
|
||||
network-name (:network-name network)
|
||||
network-name-text (name network-name)
|
||||
network-name-capitalized (when (seq network-name-text)
|
||||
(string/capitalize network-name-text))
|
||||
network-color (if (= network-name :mainnet) :ethereum network-name)]
|
||||
(with-meta
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:margin-top 4}}
|
||||
(if (zero? idx)
|
||||
[:<>
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
(i18n/label :t/from)]
|
||||
[quo/summary-tag
|
||||
{:label network-name-capitalized
|
||||
:type :network
|
||||
:image-source (:source network)
|
||||
:customization-color network-color}]]
|
||||
[:<>
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
(str (i18n/label :t/and) " ")]
|
||||
[quo/summary-tag
|
||||
{:label network-name-capitalized
|
||||
:type :network
|
||||
:image-source (:source network)
|
||||
:customization-color network-color}]])]
|
||||
{:key (str "transaction-title" idx)})))
|
||||
route))
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:margin-top 4}}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
(i18n/label :t/from)]
|
||||
[quo/summary-tag
|
||||
{:label (:name account)
|
||||
:type :account
|
||||
:emoji (:emoji account)
|
||||
:customization-color (:color account)}]])
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:margin-top 4}}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
(i18n/label :t/to)]
|
||||
(if (= transaction-type :tx/bridge)
|
||||
[quo/summary-tag
|
||||
{:type :network
|
||||
:image-source (:source to-network)
|
||||
:label (string/capitalize (name (:network-name to-network)))
|
||||
:customization-color to-network-color}]
|
||||
[quo/summary-tag (assoc recipient :type (:recipient-type recipient))])]
|
||||
(when (= transaction-type :tx/bridge)
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:margin-top 4}}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
(i18n/label :t/in)]
|
||||
[quo/summary-tag
|
||||
{:label (:name account)
|
||||
:type :account
|
||||
:emoji (:emoji account)
|
||||
:customization-color (:color account)}]])]))
|
||||
|
||||
(defn- user-summary
|
||||
[{:keys [account-props theme label accessibility-label summary-type recipient bridge-tx? account-to?]}]
|
||||
(let [network-values (rf/sub [:wallet/network-values account-to?])
|
||||
summary-info-type (case (:recipient-type recipient)
|
||||
:saved-address :saved-account
|
||||
:account :status-account
|
||||
summary-type)]
|
||||
[rn/view
|
||||
{:style {:padding-horizontal 20
|
||||
:padding-bottom 16}}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label accessibility-label}
|
||||
label]
|
||||
[quo/summary-info
|
||||
{:type summary-info-type
|
||||
:networks? true
|
||||
:values (send-utils/network-values-for-ui network-values)
|
||||
:account-props (cond-> account-props
|
||||
(and account-to? (not bridge-tx?))
|
||||
(assoc
|
||||
:size 32
|
||||
:name (:label recipient)
|
||||
:full-name (:label recipient)
|
||||
:emoji (:emoji recipient)
|
||||
:customization-color (:customization-color recipient)))}]]))
|
||||
|
||||
(defn- data-item
|
||||
[{:keys [title subtitle]}]
|
||||
[quo/data-item
|
||||
@@ -164,11 +23,53 @@
|
||||
:title title
|
||||
:subtitle subtitle}])
|
||||
|
||||
(defn- estimated-time-view
|
||||
[]
|
||||
(let [estimated-time (rf/sub [:wallet/send-estimated-time])]
|
||||
[data-item
|
||||
{:title (i18n/label :t/est-time)
|
||||
:subtitle (i18n/label :t/time-in-mins
|
||||
{:minutes (str estimated-time)})}]))
|
||||
|
||||
(defn- max-fees-view
|
||||
[]
|
||||
(let [native-currency-symbol (-> (rf/sub [:wallet/send-route])
|
||||
first
|
||||
(get-in [:from :native-currency-symbol]))
|
||||
max-fees (rf/sub [:wallet/wallet-send-fee-fiat-formatted
|
||||
native-currency-symbol])]
|
||||
[data-item
|
||||
{:title (i18n/label :t/max-fees)
|
||||
:subtitle max-fees}]))
|
||||
|
||||
(defn- bridge-received-amount
|
||||
[]
|
||||
(let [to-network (rf/sub [:wallet/bridge-to-network-details])
|
||||
amount (rf/sub [:wallet/send-total-amount-formatted])]
|
||||
[data-item
|
||||
{:title (i18n/label :t/bridged-to
|
||||
{:network (:abbreviated-name to-network)})
|
||||
:subtitle amount}]))
|
||||
|
||||
(defn- send-received-amount
|
||||
[]
|
||||
(let [amount (rf/sub [:wallet/send-total-amount-formatted])]
|
||||
[data-item
|
||||
{:title (i18n/label :t/recipient-gets)
|
||||
:subtitle amount}]))
|
||||
|
||||
(defn- received-amount-view
|
||||
[]
|
||||
(let [tx-type (rf/sub [:wallet/send-tx-type])]
|
||||
(if (= tx-type :tx/bridge)
|
||||
[bridge-received-amount]
|
||||
[send-received-amount])))
|
||||
|
||||
(defn- transaction-details
|
||||
[{:keys [estimated-time-min max-fees token-display-name amount to-network route
|
||||
transaction-type]}]
|
||||
(let [route-loaded? (and route (seq route))
|
||||
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])]
|
||||
[]
|
||||
(let [route-loaded? (seq (rf/sub [:wallet/send-route]))
|
||||
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||
sending-collectible? (rf/sub [:wallet/sending-collectible?])]
|
||||
[rn/view
|
||||
{:style (style/details-container
|
||||
{:loading-suggested-routes? loading-suggested-routes?
|
||||
@@ -176,127 +77,60 @@
|
||||
(cond
|
||||
loading-suggested-routes?
|
||||
[rn/activity-indicator {:style {:flex 1}}]
|
||||
|
||||
route-loaded?
|
||||
[:<>
|
||||
[data-item
|
||||
{:title (i18n/label :t/est-time)
|
||||
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-min)})}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/max-fees)
|
||||
:subtitle max-fees}]
|
||||
[data-item
|
||||
{:title (if (= transaction-type :tx/bridge)
|
||||
(i18n/label :t/bridged-to
|
||||
{:network (:abbreviated-name to-network)})
|
||||
(i18n/label :t/recipient-gets))
|
||||
:subtitle (str amount " " token-display-name)}]]
|
||||
[estimated-time-view]
|
||||
[max-fees-view]
|
||||
(when-not sending-collectible?
|
||||
[received-amount-view])]
|
||||
|
||||
:else
|
||||
[quo/text {:style {:align-self :center}}
|
||||
(i18n/label :t/no-routes-found-confirmation)])]))
|
||||
|
||||
(defn- slide-to-confirm
|
||||
[]
|
||||
(let [route-loaded? (seq (rf/sub [:wallet/send-route]))
|
||||
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||
tx-type (rf/sub [:wallet/send-tx-type])
|
||||
customization-color (rf/sub [:wallet/current-viewing-account-color])]
|
||||
(when (and (not loading-suggested-routes?) route-loaded?)
|
||||
[standard-auth/slide-button
|
||||
{:keycard-supported? true
|
||||
:size :size-48
|
||||
:track-text (if (= tx-type :tx/bridge)
|
||||
(i18n/label :t/slide-to-bridge)
|
||||
(i18n/label :t/slide-to-send))
|
||||
:container-style {:z-index 2}
|
||||
:customization-color customization-color
|
||||
:on-auth-success #(rf/dispatch
|
||||
[:wallet/send-transaction
|
||||
(security/safe-unmask-data %)])
|
||||
:auth-button-label (i18n/label :t/confirm)}])))
|
||||
|
||||
(defn- on-close
|
||||
[]
|
||||
(rf/dispatch [:wallet/transaction-confirmation-navigate-back]))
|
||||
|
||||
(defn view
|
||||
[_]
|
||||
(let [on-close #(rf/dispatch [:wallet/transaction-confirmation-navigate-back])]
|
||||
(fn []
|
||||
(let [theme (quo.theme/use-theme)
|
||||
send-transaction-data (rf/sub [:wallet/wallet-send])
|
||||
{:keys [token-display-name collectible amount
|
||||
route
|
||||
to-address bridge-to-chain-id type
|
||||
recipient]} send-transaction-data
|
||||
collectible? (some? collectible)
|
||||
image-url (when collectible
|
||||
(get-in collectible [:preview-url :uri]))
|
||||
transaction-type (:tx-type send-transaction-data)
|
||||
estimated-time-min (reduce + (map :estimated-time route))
|
||||
token-symbol (or token-display-name
|
||||
(-> send-transaction-data :token :symbol))
|
||||
first-route (first route)
|
||||
native-currency-symbol (get-in first-route
|
||||
[:from :native-currency-symbol])
|
||||
fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted
|
||||
native-currency-symbol])
|
||||
account (rf/sub [:wallet/current-viewing-account])
|
||||
account-color (:color account)
|
||||
bridge-to-network (when bridge-to-chain-id
|
||||
(rf/sub [:wallet/network-details-by-chain-id
|
||||
bridge-to-chain-id]))
|
||||
loading-suggested-routes? (rf/sub
|
||||
[:wallet/wallet-send-loading-suggested-routes?])
|
||||
total-amount-receiver (rf/sub [:wallet/total-amount true])
|
||||
from-account-props {:customization-color account-color
|
||||
:size 32
|
||||
:emoji (:emoji account)
|
||||
:type :default
|
||||
:name (:name account)
|
||||
:address (utils/get-shortened-address
|
||||
(:address
|
||||
account))}
|
||||
user-props {:full-name to-address
|
||||
:address (utils/get-shortened-address
|
||||
to-address)}]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [quo/page-nav
|
||||
{:icon-name :i/arrow-left
|
||||
:on-press on-close
|
||||
:margin-top (safe-area/get-top)
|
||||
:background :blur
|
||||
:accessibility-label :top-bar}]
|
||||
:footer [:<>
|
||||
[transaction-details
|
||||
{:estimated-time-min estimated-time-min
|
||||
:max-fees fee-formatted
|
||||
:token-display-name token-symbol
|
||||
:amount total-amount-receiver
|
||||
:to-network bridge-to-network
|
||||
:theme theme
|
||||
:route route
|
||||
:transaction-type transaction-type}]
|
||||
(when (and (not loading-suggested-routes?) route (seq route))
|
||||
[standard-auth/slide-button
|
||||
{:keycard-supported? true
|
||||
:size :size-48
|
||||
:track-text (if (= transaction-type :tx/bridge)
|
||||
(i18n/label :t/slide-to-bridge)
|
||||
(i18n/label :t/slide-to-send))
|
||||
:container-style {:z-index 2}
|
||||
:customization-color account-color
|
||||
:on-auth-success #(rf/dispatch
|
||||
[:wallet/send-transaction
|
||||
(security/safe-unmask-data %)])
|
||||
:auth-button-label (i18n/label :t/confirm)}])]
|
||||
:gradient-cover? true
|
||||
:customization-color (:color account)}
|
||||
[rn/view
|
||||
[transaction-title
|
||||
{:token-display-name token-symbol
|
||||
:amount amount
|
||||
:account account
|
||||
:type type
|
||||
:recipient recipient
|
||||
:route route
|
||||
:to-network bridge-to-network
|
||||
:image-url image-url
|
||||
:transaction-type transaction-type
|
||||
:collectible? collectible?}]
|
||||
[user-summary
|
||||
{:summary-type :status-account
|
||||
:accessibility-label :summary-from-label
|
||||
:label (i18n/label :t/from-capitalized)
|
||||
:account-props from-account-props
|
||||
:theme theme}]
|
||||
[user-summary
|
||||
{:summary-type (if (= transaction-type :tx/bridge)
|
||||
:status-account
|
||||
:account)
|
||||
:accessibility-label :summary-to-label
|
||||
:label (i18n/label :t/to-capitalized)
|
||||
:account-props (if (= transaction-type :tx/bridge)
|
||||
from-account-props
|
||||
user-props)
|
||||
:recipient recipient
|
||||
:bridge-tx? (= transaction-type :tx/bridge)
|
||||
:account-to? true
|
||||
:theme theme}]]]]))))
|
||||
(let [customization-color (rf/sub [:wallet/current-viewing-account-color])]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [quo/page-nav
|
||||
{:icon-name :i/arrow-left
|
||||
:on-press on-close
|
||||
:margin-top (safe-area/get-top)
|
||||
:background :blur
|
||||
:accessibility-label :top-bar}]
|
||||
:footer [:<>
|
||||
[transaction-details]
|
||||
[slide-to-confirm]]
|
||||
:gradient-cover? true
|
||||
:customization-color customization-color}
|
||||
[rn/view
|
||||
[transaction-title/view]
|
||||
[account-summary/from-summary]
|
||||
[account-summary/to-summary]]]]))
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
(ns status-im.contexts.wallet.send.utils
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[utils.hex :as utils.hex]
|
||||
[utils.money :as money]))
|
||||
|
||||
(defn amount-in-hex
|
||||
@@ -43,21 +41,67 @@
|
||||
[route]
|
||||
(money/wei->ether (reduce money/add (map calculate-gas-fee route))))
|
||||
|
||||
(defn- path-amount-in
|
||||
[path]
|
||||
(-> path :amount-in money/from-hex))
|
||||
|
||||
(defn- path-amount-out
|
||||
[path]
|
||||
(if (= (:bridge-name path) constants/bridge-name-hop)
|
||||
(let [{:keys [token-fees bonder-fees amount-in]} path]
|
||||
(-> amount-in
|
||||
money/from-hex
|
||||
(money/sub token-fees)
|
||||
(money/add bonder-fees)))
|
||||
(-> path :amount-out money/from-hex)))
|
||||
|
||||
(defn- convert-wei-to-eth
|
||||
[amount native-token? token-decimals]
|
||||
(money/with-precision
|
||||
(if native-token?
|
||||
(money/wei->ether amount)
|
||||
(money/token->unit amount token-decimals))
|
||||
constants/token-display-precision))
|
||||
|
||||
(defn network-amounts-by-chain
|
||||
[{:keys [route token-decimals native-token? receiver?]}]
|
||||
(reduce
|
||||
(fn [acc path]
|
||||
(let [amount-hex (if receiver? (:amount-out path) (:amount-in path))
|
||||
amount-units (native-module/hex-to-number
|
||||
(utils.hex/normalize-hex amount-hex))
|
||||
amount (money/with-precision
|
||||
(if native-token?
|
||||
(money/wei->ether amount-units)
|
||||
(money/token->unit amount-units
|
||||
token-decimals))
|
||||
6)
|
||||
chain-id (if receiver? (get-in path [:to :chain-id]) (get-in path [:from :chain-id]))]
|
||||
(update acc chain-id money/add amount)))
|
||||
(let [amount (if receiver?
|
||||
(path-amount-out path)
|
||||
(path-amount-in path))
|
||||
chain-id (if receiver?
|
||||
(get-in path [:to :chain-id])
|
||||
(get-in path [:from :chain-id]))]
|
||||
(as-> amount $
|
||||
(convert-wei-to-eth $ native-token? token-decimals)
|
||||
(update acc chain-id money/add $))))
|
||||
{}
|
||||
route))
|
||||
|
||||
(defn path-estimated-received
|
||||
"Calculates the (`bignumber`) estimated received token amount. For
|
||||
bridge transactions, the amount is the difference between the
|
||||
`amount-in` and the `token-fees`."
|
||||
[path]
|
||||
(if (-> path :bridge-name (= constants/bridge-name-hop))
|
||||
(-> path
|
||||
:amount-in
|
||||
money/from-hex
|
||||
(money/sub (:token-fees path)))
|
||||
(-> path
|
||||
:amount-out
|
||||
money/from-hex)))
|
||||
|
||||
(defn estimated-received-by-chain
|
||||
[route token-decimals native-token?]
|
||||
(reduce
|
||||
(fn [acc path]
|
||||
(let [chain-id (get-in path [:to :chain-id])
|
||||
estimated-received (-> path
|
||||
path-estimated-received
|
||||
(convert-wei-to-eth native-token? token-decimals))]
|
||||
(update acc chain-id money/add estimated-received)))
|
||||
{}
|
||||
route))
|
||||
|
||||
|
||||
@@ -79,9 +79,91 @@
|
||||
:receiver? receiver?})
|
||||
expected {1 (money/bignumber "2")
|
||||
10 (money/bignumber "2")}]
|
||||
(doseq [[chain-id exp-value] expected]
|
||||
(is (money/equal-to (get result chain-id) exp-value)))))
|
||||
|
||||
(testing "Correctly calculates network (out) amounts for bridge transaction"
|
||||
(let [route [{:bridge-name "Hop"
|
||||
:amount-in "0xde0b6b3a7640000"
|
||||
:bonder-fees (money/bignumber "200000000000000")
|
||||
:token-fees (money/bignumber "230000000000000")
|
||||
:to {:chain-id 1}}
|
||||
{:bridge-name "Hop"
|
||||
:bonder-fees (money/bignumber "300000000000000")
|
||||
:token-fees (money/bignumber "410000000000000")
|
||||
:amount-in "0xde0b6b3a7640000"
|
||||
:to {:chain-id 10}}]
|
||||
token-decimals 6
|
||||
native-token? true
|
||||
receiver? true
|
||||
result (utils/network-amounts-by-chain {:route route
|
||||
:token-decimals token-decimals
|
||||
:native-token? native-token?
|
||||
:receiver? receiver?})
|
||||
expected {1 (money/bignumber "0.99997")
|
||||
10 (money/bignumber "0.99989")}]
|
||||
(doseq [[chain-id exp-value] expected]
|
||||
(is (money/equal-to (get result chain-id) exp-value))))))
|
||||
|
||||
(deftest estimated-received-by-chain-test
|
||||
(testing "Correctly calculates the bridge estimated received amount"
|
||||
(let [chain-id 1
|
||||
route [{:bridge-name "Hop"
|
||||
:amount-in "0xde0b6b3a7640000"
|
||||
:token-fees (money/bignumber "230000000000000")
|
||||
:to {:chain-id 1}}]
|
||||
token-decimals 18
|
||||
native-token? true
|
||||
result (utils/estimated-received-by-chain route token-decimals native-token?)
|
||||
expected (money/bignumber "0.99977")]
|
||||
(is (money/equal-to (get result chain-id) expected))))
|
||||
|
||||
(testing "Correctly calculates the estimated received amount with native token"
|
||||
(let [chain-id 1
|
||||
route [{:amount-out "0x1bc16d674ec80000"
|
||||
:to {:chain-id chain-id}}]
|
||||
token-decimals 18
|
||||
native-token? true
|
||||
result (utils/estimated-received-by-chain route token-decimals native-token?)
|
||||
expected (money/bignumber "2")]
|
||||
(is (money/equal-to (get result chain-id) expected))))
|
||||
|
||||
(testing "Correctly calculates the estimated received amount with non-native token"
|
||||
(let [chain-id 10
|
||||
route [{:amount-out "0x1bc16d674ec80000"
|
||||
:to {:chain-id chain-id}}]
|
||||
token-decimals 18
|
||||
native-token? false
|
||||
result (utils/estimated-received-by-chain route token-decimals native-token?)
|
||||
expected (money/bignumber "2")]
|
||||
(is (money/equal-to (get result chain-id) expected))))
|
||||
|
||||
(testing
|
||||
"Correctly calculates the estimated received amount with multiple routes on different networks"
|
||||
(let [route [{:amount-out "0x1bc16d674ec80000"
|
||||
:to {:chain-id 1}}
|
||||
{:amount-out "0xde0b6b3a7640000"
|
||||
:to {:chain-id 10}}]
|
||||
token-decimals 18
|
||||
native-token? false
|
||||
result (utils/estimated-received-by-chain route token-decimals native-token?)
|
||||
expected {10 (money/bignumber "1")
|
||||
1 (money/bignumber "2")}]
|
||||
(doseq [[chain-id exp-value] expected]
|
||||
(is (money/equal-to (get result chain-id) exp-value)))))
|
||||
|
||||
(testing "Correctly calculates the estimated received amount with multiple routes on the same network"
|
||||
(let [chain-id 10
|
||||
route [{:amount-out "0x1bc16d674ec80000"
|
||||
:to {:chain-id chain-id}}
|
||||
{:amount-out "0x1bc16d674ec80000"
|
||||
:to {:chain-id chain-id}}]
|
||||
token-decimals 18
|
||||
native-token? false
|
||||
result (utils/estimated-received-by-chain route token-decimals native-token?)
|
||||
expected (money/bignumber "4")]
|
||||
(is (money/equal-to (get result chain-id) expected)))))
|
||||
|
||||
(deftest network-values-for-ui-test
|
||||
(testing "Sanitizes values correctly for display"
|
||||
(let [amounts {1 (money/bignumber "0")
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns status-im.subs.wallet.networks
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[utils.money :as money]))
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
(def max-network-prefixes 2)
|
||||
|
||||
@@ -62,28 +63,18 @@
|
||||
(re-frame/reg-sub
|
||||
:wallet/network-values
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [{:keys [from-values-by-chain to-values-by-chain token-display-name] :as send-data} [_ to-values?]]
|
||||
:<- [:wallet/send-display-token-decimals]
|
||||
(fn [[{:keys [from-values-by-chain to-values-by-chain token-display-name] :as send-data} token-decimals]
|
||||
[_ to-values?]]
|
||||
(let [network-values (if to-values? to-values-by-chain from-values-by-chain)
|
||||
token-symbol (or token-display-name
|
||||
(-> send-data :token :symbol))]
|
||||
(reduce-kv
|
||||
(fn [acc chain-id amount]
|
||||
(let [network-name (network-utils/id->network chain-id)]
|
||||
(let [network-name (network-utils/id->network chain-id)
|
||||
amount-fixed (number/to-fixed (money/->bignumber amount) token-decimals)]
|
||||
(assoc acc
|
||||
(if (= network-name :mainnet) :ethereum network-name)
|
||||
{:amount amount :token-symbol token-symbol})))
|
||||
{:amount amount-fixed :token-symbol token-symbol})))
|
||||
{}
|
||||
network-values))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/total-amount
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [{:keys [from-values-by-chain to-values-by-chain]} [_ to-values?]]
|
||||
(let [network-values (if to-values? to-values-by-chain from-values-by-chain)]
|
||||
(reduce
|
||||
(fn [acc amount]
|
||||
(if (money/bignumber? amount)
|
||||
(money/add acc amount)
|
||||
acc))
|
||||
(money/bignumber 0)
|
||||
(vals network-values)))))
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
(ns status-im.subs.wallet.send
|
||||
(:require
|
||||
[re-frame.core :as rf]
|
||||
[status-im.contexts.wallet.common.activity-tab.constants :as constants]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.activity-tab.constants :as activity-constants]
|
||||
[status-im.contexts.wallet.common.utils :as common-utils]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[utils.number]))
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-tab
|
||||
@@ -21,6 +24,21 @@
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :recipient)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-to-address
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :to-address)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-route
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :route)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-token
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :token)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-transaction-ids
|
||||
:<- [:wallet/wallet-send]
|
||||
@@ -41,11 +59,28 @@
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :tx-type)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-collectible
|
||||
:<- [:wallet/wallet-send]
|
||||
#(:collectible %))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/sending-collectible?
|
||||
:<- [:wallet/send-tx-type]
|
||||
#(send-utils/tx-type-collectible? %))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-collectible-preview
|
||||
:<- [:wallet/send-collectible]
|
||||
:-> :preview-url
|
||||
:-> :uri)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-collectible-name
|
||||
:<- [:wallet/send-collectible]
|
||||
:-> :collectible-data
|
||||
:-> :name)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-transaction-progress
|
||||
:<- [:wallet/send-transaction-ids]
|
||||
@@ -64,7 +99,7 @@
|
||||
(->> address-activity
|
||||
(sort :timestamp)
|
||||
(keep (fn [{:keys [activity-type recipient]}]
|
||||
(when (= constants/wallet-activity-type-send activity-type)
|
||||
(when (= activity-constants/wallet-activity-type-send activity-type)
|
||||
recipient)))
|
||||
(distinct)))))
|
||||
|
||||
@@ -73,6 +108,12 @@
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :token-not-supported-in-receiver-networks?)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-bridge-to-chain-id
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [send-data]
|
||||
(:bridge-to-chain-id send-data)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/bridge-from-networks
|
||||
:<- [:wallet/wallet-send]
|
||||
@@ -91,3 +132,83 @@
|
||||
(when (not= (:chain-id network) bridge-to-chain-id)
|
||||
(:chain-id network)))
|
||||
networks)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-token-decimals
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [{:keys [token collectible]}]
|
||||
(if collectible 0 (:decimals token))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-display-token-decimals
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [{:keys [token collectible]}]
|
||||
(if collectible
|
||||
0
|
||||
(-> token
|
||||
common-utils/token-usd-price
|
||||
common-utils/one-cent-value
|
||||
common-utils/calc-max-crypto-decimals
|
||||
(min constants/min-token-decimals-to-display)))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-native-token?
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [{:keys [token token-display-name]}]
|
||||
(and token (= token-display-name "ETH"))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/total-amount
|
||||
:<- [:wallet/send-route]
|
||||
:<- [:wallet/send-token-decimals]
|
||||
:<- [:wallet/send-native-token?]
|
||||
(fn [[route token-decimals native-token?]]
|
||||
(let [default-amount (money/bignumber 0)]
|
||||
(if route
|
||||
(->> (send-utils/estimated-received-by-chain
|
||||
route
|
||||
token-decimals
|
||||
native-token?)
|
||||
vals
|
||||
(reduce money/add default-amount))
|
||||
default-amount))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-total-amount-formatted
|
||||
:<- [:wallet/total-amount]
|
||||
:<- [:wallet/send-display-token-decimals]
|
||||
:<- [:wallet/wallet-send-token-symbol]
|
||||
(fn [[amount token-decimals token-symbol]]
|
||||
(-> amount
|
||||
(number/to-fixed token-decimals)
|
||||
(str " " token-symbol))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-amount-fixed
|
||||
:<- [:wallet/send-display-token-decimals]
|
||||
(fn [token-decimals [_ amount]]
|
||||
(number/to-fixed (money/->bignumber amount) token-decimals)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/bridge-to-network-details
|
||||
:<- [:wallet/wallet-send]
|
||||
:<- [:wallet/network-details]
|
||||
(fn [[{:keys [bridge-to-chain-id]} networks]]
|
||||
(when bridge-to-chain-id
|
||||
(some (fn [network]
|
||||
(when
|
||||
(= (:chain-id network) bridge-to-chain-id)
|
||||
network))
|
||||
networks))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-from-chain-ids
|
||||
:<- [:wallet/send-route]
|
||||
(fn [route]
|
||||
(map #(-> % :from :chain-id) route)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-estimated-time
|
||||
:<- [:wallet/send-route]
|
||||
(fn [route]
|
||||
(reduce + (map :estimated-time route))))
|
||||
|
||||
@@ -6,8 +6,15 @@
|
||||
[status-im.subs.root]
|
||||
[status-im.subs.wallet.send]
|
||||
[test-helpers.unit :as h]
|
||||
[utils.money :as money]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def ^:private token-mock
|
||||
{:decimals 8
|
||||
:symbol "ETH"
|
||||
:balances-per-chain {1 {:raw-balance "100"}}
|
||||
:market-values-per-currency {:usd {:price 10000}}})
|
||||
|
||||
(h/deftest-sub :wallet/send-tab
|
||||
[sub-name]
|
||||
(testing "returns active tab for selecting address"
|
||||
@@ -84,3 +91,144 @@
|
||||
:timestamp 1588464000}}})
|
||||
(assoc-in [:wallet :current-viewing-account-address] "acc1"))))
|
||||
(is (match? ["acc2" "acc4"] (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/send-token-decimals
|
||||
[sub-name]
|
||||
(testing "returns the decimals for the chosen token"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :ui :send :token] token-mock)
|
||||
(is (= 8 (rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns 0 if sending collectibles"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :ui :send :collectible] {})
|
||||
(is (match? 0 (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/send-display-token-decimals
|
||||
[sub-name]
|
||||
(testing "returns the decimals based on the token price for the chosen token"
|
||||
(swap! rf-db/app-db assoc-in
|
||||
[:wallet :ui :send :token]
|
||||
{:symbol "ETH"
|
||||
:balances-per-chain {1 {:raw-balance "100"}}
|
||||
:market-values-per-currency {:usd {:price 10000}}})
|
||||
(is (match? 6 (rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns 0 if sending collectibles"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :ui :send :collectible] {})
|
||||
(is (match? 0 (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/send-native-token?
|
||||
[sub-name]
|
||||
(testing "returns true if the chosen token is native (ETH)"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] {})
|
||||
(assoc-in [:wallet :ui :send :token-display-name] "ETH"))))
|
||||
(is (rf/sub [sub-name])))
|
||||
|
||||
(testing "returns false if the chosen token is not native"
|
||||
(swap! rf-db/app-db
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] {})
|
||||
(assoc-in [:wallet :ui :send :token-display-name] "SNT")))))
|
||||
(is (not (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/total-amount
|
||||
[sub-name]
|
||||
(testing "returns the total SEND amount when the route is present"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] token-mock)
|
||||
(assoc-in [:wallet :ui :send :token-display-name] "ETH")
|
||||
(assoc-in [:wallet :ui :send :route]
|
||||
[{:amount-out "0x1bc16d674ec80000"
|
||||
:to {:chain-id 1}}]))))
|
||||
(is (match? (money/bignumber 2) (rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns the total BRIDGE amount when the route is present"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] token-mock)
|
||||
(assoc-in [:wallet :ui :send :token-display-name] "ETH")
|
||||
(assoc-in [:wallet :ui :send :route]
|
||||
[{:bridge-name "Hop"
|
||||
:amount-in "0xde0b6b3a7640000"
|
||||
:token-fees (money/bignumber "230000000000000")
|
||||
:to {:chain-id 1}}]))))
|
||||
(is (match? (money/bignumber 0.99977) (rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns the default total amount (0) when the route is not present"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] token-mock)
|
||||
(assoc-in [:wallet :ui :send :token-display-name] "ETH"))))
|
||||
(is (match? (money/bignumber 0) (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/send-total-amount-formatted
|
||||
[sub-name]
|
||||
(testing "returns the formatted total amount"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] token-mock)
|
||||
(assoc-in [:wallet :ui :send :token-display-name] "ETH")
|
||||
(assoc-in [:wallet :ui :send :route]
|
||||
[{:amount-out "0x2b139f68a611c00" ;; 193999990000000000
|
||||
:to {:chain-id 1}}]))))
|
||||
(is (match? "0.194 ETH" (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/send-amount-fixed
|
||||
[sub-name]
|
||||
(testing "returns the fixed value when the amount is a string"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] token-mock))))
|
||||
(is (match? "2" (rf/sub [sub-name "1.9999999"]))))
|
||||
|
||||
(testing "returns the fixed value when the amount is a number"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] token-mock))))
|
||||
(is (match? "2" (rf/sub [sub-name 1.9999999]))))
|
||||
|
||||
(testing "returns the fixed value when the amount is a bignumber"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :ui :send :token] token-mock))))
|
||||
(is (match? "2" (rf/sub [sub-name (money/bignumber "1.9999999")])))))
|
||||
|
||||
(def ^:private mainnet-network
|
||||
{:short-name "eth"
|
||||
:network-name :mainnet
|
||||
:abbreviated-name "Eth."
|
||||
:full-name "Mainnet"
|
||||
:chain-id 1
|
||||
:related-chain-id 1
|
||||
:layer 1})
|
||||
|
||||
(h/deftest-sub :wallet/bridge-to-network-details
|
||||
[sub-name]
|
||||
(testing "returns the network details for bridge transactions"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :networks] {:prod [mainnet-network]})
|
||||
(assoc-in [:profile/profile :test-networks-enabled?] false)
|
||||
(assoc-in [:wallet :ui :send] {:bridge-to-chain-id 1}))))
|
||||
(is (match? mainnet-network (rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns nil if not on the bridge flow"
|
||||
(swap! rf-db/app-db
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in [:wallet :networks] {:prod [mainnet-network]})
|
||||
(assoc-in [:profile/profile :test-networks-enabled?] false))))
|
||||
(is (match? nil (rf/sub [sub-name])))))
|
||||
|
||||
@@ -154,7 +154,8 @@
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-send-token-symbol
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :token-symbol)
|
||||
(fn [{:keys [token-symbol token]}]
|
||||
(or token-symbol (:symbol token))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-send-disabled-from-chain-ids
|
||||
|
||||
@@ -2631,6 +2631,8 @@
|
||||
"unblock": "Unblock",
|
||||
"unblock-contact": "Unblock this user",
|
||||
"unblocking-a-user-message": "After unblocking {{username}}, you will be able to connect with them as a contact and see their messages in group chats and communities.",
|
||||
"understanding-bonder-fees-description": "The bridged amount can be lower than the amount you send due to Bonder fees. These fees cover the cost of providing liquidity and managing risks associated with your transfer. The fee ranges from 0.05% to 0.30%, depending on factors such as transaction volume and route specifics.",
|
||||
"understanding-bonder-fees-title": "Understanding Bonder fees",
|
||||
"undo": "Undo",
|
||||
"unique-identifiers": "Unique profile identifiers",
|
||||
"universally-unique-identifiers-of-device": "Universally Unique Identifiers of device",
|
||||
|
||||
Reference in New Issue
Block a user