chore: remove legacy wallet code (#18749)
This commit is contained in:
parent
b0133e97cf
commit
42d2690c85
|
@ -1,7 +1,6 @@
|
|||
(ns legacy.status-im.currency.core
|
||||
(:require
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[legacy.status-im.wallet.prices :as prices]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn get-currency
|
||||
|
@ -16,5 +15,4 @@
|
|||
:currency
|
||||
currency
|
||||
;; on changing currency, we should fetch tokens prices again
|
||||
{:on-success #(rf/dispatch [:wallet/get-wallet-token])})
|
||||
(prices/update-prices)))
|
||||
{:on-success #(rf/dispatch [:wallet/get-wallet-token])})))
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
[legacy.status-im.ethereum.ens :as ens]
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[legacy.status-im.utils.random :as random]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.navigation.events :as navigation]
|
||||
|
@ -126,7 +125,7 @@
|
|||
{:events [::set-pub-key]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [username address custom-domain?]} (:ens/registration db)
|
||||
address (or address (wallet.utils/default-address db))
|
||||
address address
|
||||
{:keys [public-key]} (:profile/profile db)
|
||||
chain-id (chain/chain-id db)
|
||||
username (fullname custom-domain? username)]
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
[legacy.status-im.ethereum.decode :as decode]
|
||||
[legacy.status-im.ethereum.encode :as encode]
|
||||
[legacy.status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.common.json-rpc.events :as json-rpc]
|
||||
[taoensso.timbre :as log]
|
||||
|
@ -256,24 +255,13 @@
|
|||
(let [checksum (eip55/address->checksum address)
|
||||
max-known-block (get-max-block-with-transfers db address)
|
||||
effects (cond-> [(when (seq transfers)
|
||||
(set-lowest-fetched-block checksum transfers))
|
||||
(wallet/set-max-block-with-transfers checksum transfers)]
|
||||
(set-lowest-fetched-block checksum transfers))]
|
||||
|
||||
(seq transfers)
|
||||
(concat
|
||||
[]
|
||||
(mapv add-transfer transfers))
|
||||
|
||||
(and max-known-block
|
||||
(some #(> (:block %) max-known-block) transfers))
|
||||
(conj (wallet/update-balances
|
||||
[address]
|
||||
(zero? max-known-block)))
|
||||
|
||||
(and (zero? max-known-block)
|
||||
(empty? transfers))
|
||||
(conj (wallet/set-zero-balances {:address address}))
|
||||
|
||||
(< (count transfers) limit)
|
||||
(conj (tx-history-end-reached checksum)))]
|
||||
(apply rf/merge cofx (tx-fetching-ended [checksum]) effects)))
|
||||
|
@ -282,8 +270,7 @@
|
|||
{:events [::new-transfers]}
|
||||
[cofx transfers params]
|
||||
(rf/merge cofx
|
||||
(handle-new-transfer transfers params)
|
||||
(wallet/stop-fetching-on-empty-tx-history transfers)))
|
||||
(handle-new-transfer transfers params)))
|
||||
|
||||
(rf/defn tx-fetching-failed
|
||||
{:events [::tx-fetching-failed]}
|
||||
|
|
|
@ -32,10 +32,6 @@
|
|||
legacy.status-im.visibility-status-popover.core
|
||||
legacy.status-im.visibility-status-updates.core
|
||||
legacy.status-im.waku.core
|
||||
legacy.status-im.wallet.accounts.core
|
||||
legacy.status-im.wallet.choose-recipient.core
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
legacy.status-im.wallet.custom-tokens.core
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.core :as rn]
|
||||
|
@ -141,7 +137,6 @@
|
|||
(rf/merge cofx
|
||||
{:db (dissoc db :app-in-background-since)}
|
||||
(mailserver/process-next-messages-request)
|
||||
(wallet/restart-wallet-service-after-background app-in-background-since)
|
||||
(when-not new-account?
|
||||
(universal-links/process-stored-event))
|
||||
#(when-let [chat-id (:current-chat-id db)]
|
||||
|
@ -198,10 +193,8 @@
|
|||
:reset-card (keycard/reset-card-screen-did-load %)
|
||||
:enter-pin-settings (keycard/enter-pin-screen-did-load %)
|
||||
:keycard-login-pin (keycard/login-pin-screen-did-load %)
|
||||
:add-new-account-pin (keycard/enter-pin-screen-did-load %)
|
||||
:keycard-authentication-method (keycard/authentication-method-screen-did-load %)
|
||||
:multiaccounts (keycard/multiaccounts-screen-did-load %)
|
||||
:wallet-legacy (wallet/wallet-will-focus %)
|
||||
nil)))
|
||||
|
||||
;;TODO :replace by named events
|
||||
|
|
|
@ -401,15 +401,12 @@
|
|||
(merge
|
||||
args
|
||||
{:on-success
|
||||
(fn [response]
|
||||
(fn [_response]
|
||||
(log/debug "[keycard response succ] export-key")
|
||||
(re-frame/dispatch [:keycard.callback/on-export-key-success
|
||||
response]))
|
||||
(js/alert "feature no longer supported"))
|
||||
:on-failure
|
||||
(fn [response]
|
||||
(log/debug "[keycard response fail] export-key")
|
||||
(re-frame/dispatch [:keycard.callback/on-export-key-error
|
||||
(error-object->map response)]))})))
|
||||
(fn [_response]
|
||||
(log/debug "[keycard response fail] export-key"))})))
|
||||
|
||||
(defn unpair-and-delete
|
||||
[args]
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
[legacy.status-im.keycard.recovery :as recovery]
|
||||
[legacy.status-im.keycard.sign :as sign]
|
||||
legacy.status-im.keycard.unpair
|
||||
[legacy.status-im.keycard.wallet :as wallet]
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[re-frame.db]
|
||||
[status-im.navigation.events :as navigation]
|
||||
|
@ -401,10 +400,6 @@
|
|||
(= pin-code-length numbers-entered))
|
||||
(common/verify-pin {:pin-step :current})
|
||||
|
||||
(and (= enter-step :export-key)
|
||||
(= pin-code-length numbers-entered))
|
||||
(wallet/verify-pin-with-delay)
|
||||
|
||||
(and (= enter-step :sign)
|
||||
(= pin-code-length numbers-entered))
|
||||
(sign/prepare-to-sign)
|
||||
|
|
|
@ -1,51 +1,13 @@
|
|||
(ns legacy.status-im.keycard.export-key
|
||||
(:require
|
||||
[legacy.status-im.keycard.common :as common]
|
||||
[legacy.status-im.keycard.wallet :as wallet]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn on-export-key-error
|
||||
{:events [:keycard.callback/on-export-key-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] export key error" error)
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
(cond
|
||||
tag-was-lost?
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(common/set-on-card-connected :wallet-legacy.accounts/generate-new-keycard-account))
|
||||
|
||||
(not (nil? pin-retries))
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries)
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:status :error
|
||||
:enter-step :export-key
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:sign []
|
||||
:export-key []
|
||||
:error-label :t/pin-mismatch))}
|
||||
(common/hide-connection-sheet)
|
||||
(when (zero? pin-retries) (common/frozen-keycard-popup)))
|
||||
:else
|
||||
(rf/merge cofx
|
||||
(common/show-wrong-keycard-alert)
|
||||
(common/clear-pin)
|
||||
(common/hide-connection-sheet)))))
|
||||
|
||||
(rf/defn on-export-key-success
|
||||
{:events [:keycard.callback/on-export-key-success]}
|
||||
[{:keys [db] :as cofx} pubkey]
|
||||
(let [callback-fn (get-in db [:keycard :on-export-success])]
|
||||
(rf/merge cofx
|
||||
{:dispatch (callback-fn pubkey)}
|
||||
(wallet/hide-pin-sheet)
|
||||
(common/clear-pin)
|
||||
(common/hide-connection-sheet))))
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
[clojure.string :as string]
|
||||
[legacy.status-im.keycard.common :as common]
|
||||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
|
@ -24,8 +23,7 @@
|
|||
typed? (get-in db [:keycard :typed?])
|
||||
pin (common/vector->string (get-in db [:keycard :pin :sign]))
|
||||
from (or (get-in db [:signing/tx :from :address])
|
||||
(get-in db [:signing/tx :message :from])
|
||||
(wallet.utils/default-address db))
|
||||
(get-in db [:signing/tx :message :from]))
|
||||
path (reduce
|
||||
(fn [_ {:keys [address path]}]
|
||||
(when (address/address= from address)
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
(ns legacy.status-im.keycard.wallet
|
||||
(:require
|
||||
[legacy.status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[legacy.status-im.keycard.common :as common]
|
||||
[legacy.status-im.ui.screens.wallet.add-new.views :as add-new.views]
|
||||
[legacy.status-im.utils.hex :as utils.hex]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.constants :as constants]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn show-pin-sheet
|
||||
{:events [:keycard/new-account-pin-sheet]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :enter-step] :export-key)
|
||||
(update-in [:keycard :pin] dissoc :export-key))
|
||||
:dismiss-keyboard nil}
|
||||
(bottom-sheet/show-bottom-sheet-old {:view {:content add-new.views/pin}})))
|
||||
|
||||
(rf/defn verify-pin-with-delay
|
||||
[cofx]
|
||||
{:utils/dispatch-later
|
||||
;; We need to give previous sheet some time to be fully hidden
|
||||
[{:ms 200
|
||||
:dispatch [:wallet-legacy.accounts/verify-pin]}]})
|
||||
|
||||
(rf/defn hide-pin-sheet
|
||||
{:events [:keycard/new-account-pin-sheet-hide]}
|
||||
[cofx]
|
||||
(bottom-sheet/hide-bottom-sheet-old cofx))
|
||||
|
||||
(defn public-key->address
|
||||
[public-key]
|
||||
(let [length (count public-key)
|
||||
normalized-key (case length
|
||||
132 (str "0x" (subs public-key 4))
|
||||
130 public-key
|
||||
128 (str "0x" public-key)
|
||||
nil)]
|
||||
(when normalized-key
|
||||
(subs (native-module/sha3 normalized-key) 26))))
|
||||
|
||||
(rf/defn generate-new-keycard-account
|
||||
{:events [:wallet-legacy.accounts/generate-new-keycard-account]}
|
||||
[{:keys [db]}]
|
||||
(let [path-num (inc (get-in db [:profile/profile :latest-derived-path]))
|
||||
path (str constants/path-wallet-root "/" path-num)
|
||||
pin (common/vector->string (get-in db [:keycard :pin :export-key]))]
|
||||
{:db
|
||||
(assoc-in
|
||||
db
|
||||
[:keycard :on-export-success]
|
||||
#(vector :wallet-legacy.accounts/account-stored
|
||||
(let [public-key (utils.hex/normalize-hex %)]
|
||||
{;; Strip leading 04 prefix denoting uncompressed key format
|
||||
:address (eip55/address->checksum
|
||||
(str "0x"
|
||||
(public-key->address
|
||||
(subs public-key 2))))
|
||||
:public-key (str "0x" public-key)
|
||||
:path path})))
|
||||
|
||||
:keycard/export-key {:pin pin :path path}}))
|
||||
|
||||
(rf/defn verify-pin
|
||||
{:events [:wallet-legacy.accounts/verify-pin]}
|
||||
[cofx]
|
||||
(common/verify-pin
|
||||
cofx
|
||||
{:pin-step :export-key
|
||||
:on-card-connected :wallet-legacy.accounts/verify-pin
|
||||
:on-success :wallet-legacy.accounts/generate-new-keycard-account
|
||||
:on-failure :keycard/new-account-pin-sheet}))
|
|
@ -5,7 +5,6 @@
|
|||
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[legacy.status-im.utils.mobile-sync :as utils]
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
[status-im.contexts.chat.home.add-new-contact.events :as add-new-contact]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
|
@ -35,7 +34,6 @@
|
|||
(and logged-in? initialized?)
|
||||
[(mailserver/process-next-messages-request)
|
||||
(bottom-sheet/hide-bottom-sheet-old)
|
||||
(wallet/restart-wallet-service nil)
|
||||
#(add-new-contact/set-new-identity-reconnected %)]
|
||||
|
||||
logged-in?
|
||||
|
@ -67,8 +65,7 @@
|
|||
(boolean remember-choice?)
|
||||
{})
|
||||
(when (and cellular? sync?)
|
||||
(mailserver/process-next-messages-request))
|
||||
(wallet/restart-wallet-service nil))))))
|
||||
(mailserver/process-next-messages-request)))))))
|
||||
|
||||
(rf/defn mobile-network-continue-syncing
|
||||
{:events [:mobile-network/continue-syncing]}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
(ns legacy.status-im.multiaccounts.logout.core
|
||||
(:require
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.common.keychain.events :as keychain]
|
||||
|
@ -39,7 +38,6 @@
|
|||
:profile/get-profiles-overview #(rf/dispatch
|
||||
[:profile/get-profiles-overview-success %])}
|
||||
(keychain/save-auth-method key-uid auth-method)
|
||||
(wallet/clear-timeouts)
|
||||
(initialize-app-db))))
|
||||
|
||||
(rf/defn logout
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
(:require
|
||||
["@react-native-community/netinfo" :default net-info]
|
||||
[legacy.status-im.mobile-sync-settings.core :as mobile-network]
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
|
@ -11,12 +10,7 @@
|
|||
(rf/defn change-network-status
|
||||
[{:keys [db] :as cofx} is-connected?]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :network-status (if is-connected? :online :offline))}
|
||||
(when (and is-connected?
|
||||
(or (not= (count (get-in db [:wallet-legacy :accounts]))
|
||||
(count (get db :profile/wallet-accounts)))
|
||||
(wallet/has-empty-balances? db)))
|
||||
(wallet/update-balances nil nil))))
|
||||
{:db (assoc db :network-status (if is-connected? :online :offline))}))
|
||||
|
||||
(rf/defn change-network-type
|
||||
[{:keys [db] :as cofx} old-network-type network-type expensive?]
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
(ns legacy.status-im.search.core-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest testing is]]
|
||||
[legacy.status-im.subs.wallet.search :as search.subs]))
|
||||
|
||||
(defn extract-chat-attributes
|
||||
[chat]
|
||||
(let [{:keys [name alias tags]} (val chat)]
|
||||
(into [name alias] tags)))
|
||||
|
||||
(deftest filter-chats
|
||||
(let [chats {:chat-1 {:name "name1"
|
||||
:alias "alias1"
|
||||
:tags #{"tag1"}}
|
||||
:chat-2 {:name "name2"
|
||||
:alias "alias2"
|
||||
:tags #{"tag2" "tag3"}}
|
||||
:chat-3 {:name "name3"
|
||||
:alias "alias3"
|
||||
:tags #{}}
|
||||
:chat-4 {:name "name4"
|
||||
:alias "alias4"
|
||||
:tags #{"tag4"}}}]
|
||||
(testing "no search filter"
|
||||
(is (= (count chats)
|
||||
(count (search.subs/apply-filter ""
|
||||
chats
|
||||
extract-chat-attributes
|
||||
false)))))
|
||||
(testing "searching for a specific tag"
|
||||
(is (= 1
|
||||
(count (search.subs/apply-filter "tag2"
|
||||
chats
|
||||
extract-chat-attributes
|
||||
false)))))
|
||||
(testing "searching for a partial tag"
|
||||
(is (= 3
|
||||
(count (search.subs/apply-filter "tag"
|
||||
chats
|
||||
extract-chat-attributes
|
||||
false)))))
|
||||
(testing "searching for a specific alias"
|
||||
(is (= 1
|
||||
(count (search.subs/apply-filter "alias4"
|
||||
chats
|
||||
extract-chat-attributes
|
||||
false)))))
|
||||
(testing "searching for a partial alias"
|
||||
(is (= 4
|
||||
(count (search.subs/apply-filter "alias"
|
||||
chats
|
||||
extract-chat-attributes
|
||||
false)))))
|
||||
(testing "searching for a specific chat name"
|
||||
(is (= 1
|
||||
(count (search.subs/apply-filter "name4"
|
||||
chats
|
||||
extract-chat-attributes
|
||||
false)))))))
|
|
@ -10,9 +10,6 @@
|
|||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[legacy.status-im.utils.hex :as utils.hex]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
[legacy.status-im.wallet.prices :as prices]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.common.json-rpc.events :as json-rpc]
|
||||
|
@ -83,7 +80,7 @@
|
|||
[{{:signing/keys [sign tx] :as db} :db}]
|
||||
(let [{{:keys [data typed? from v4]} :message} tx
|
||||
{:keys [in-progress? password]} sign
|
||||
from (or from (wallet.utils/default-address db))
|
||||
from from
|
||||
hashed-password (native-module/sha3 (security/safe-unmask-data
|
||||
password))]
|
||||
(when-not in-progress?
|
||||
|
@ -335,7 +332,7 @@
|
|||
:dismiss-keyboard nil}
|
||||
#(when-not wallet-set-up-passed?
|
||||
{:dispatch-later [{:dispatch [:show-popover {:view :signing-phrase}] :ms 200}]})
|
||||
(prices/update-prices)
|
||||
|
||||
#(when-not gas
|
||||
{:db (assoc-in (:db %) [:signing/edit-fee :gas-loading?] true)
|
||||
:signing/update-estimated-gas {:obj (-> tx-obj
|
||||
|
@ -395,7 +392,6 @@
|
|||
:signing/show-transaction-result nil}
|
||||
(prepare-unconfirmed-transaction result tx-obj symbol amount)
|
||||
(check-queue)
|
||||
(wallet/watch-tx (get from :address) result)
|
||||
#(when on-result
|
||||
{:dispatch (conj on-result result)}))))
|
||||
|
||||
|
@ -408,7 +404,6 @@
|
|||
(rf/merge
|
||||
cofx
|
||||
{:db (dissoc db :signing/tx :signing/sign)}
|
||||
(wallet/watch-tx (get from :address) transaction-hash)
|
||||
(if (keycard.common/keycard-multiaccount? db)
|
||||
(signing.keycard/hash-message
|
||||
{:data data
|
||||
|
@ -511,8 +506,8 @@
|
|||
{:dispatch (conj on-error "transaction was cancelled by user")}))))
|
||||
|
||||
(defn normalize-tx-obj
|
||||
[db tx]
|
||||
(update-in tx [:tx-obj :from] #(eip55/address->checksum (or % (wallet.utils/default-address db)))))
|
||||
[_db tx]
|
||||
(update-in tx [:tx-obj :from] #(eip55/address->checksum %)))
|
||||
|
||||
(rf/defn sign
|
||||
"Signing transaction or message, shows signing sheet
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
(ns legacy.status-im.stickers.core
|
||||
(:require
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[utils.ethereum.chain :as chain]
|
||||
|
@ -39,15 +38,6 @@
|
|||
:params []
|
||||
:on-success #(re-frame/dispatch [:stickers/stickers-recent-success %])}]})
|
||||
|
||||
(rf/defn buy-pack
|
||||
{:events [:stickers/buy-pack]}
|
||||
[{db :db} pack-id]
|
||||
{:json-rpc/call [{:method "stickers_buyPrepareTx"
|
||||
:params [(chain/chain-id db) (wallet.utils/default-address db) (int pack-id)]
|
||||
:on-success #(re-frame/dispatch [:signing.ui/sign
|
||||
{:tx-obj %
|
||||
:on-result [:stickers/pending-pack pack-id]}])}]})
|
||||
|
||||
(rf/defn pending-pack
|
||||
{:events [:stickers/pending-pack]}
|
||||
[{db :db} id]
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
legacy.status-im.subs.mailservers
|
||||
legacy.status-im.subs.networks
|
||||
legacy.status-im.subs.stickers
|
||||
legacy.status-im.subs.wallet.search
|
||||
legacy.status-im.subs.wallet.signing
|
||||
legacy.status-im.subs.wallet.transactions
|
||||
legacy.status-im.subs.wallet.wallet
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defn reg-root-key-sub
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
(ns legacy.status-im.subs.wallet.search
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.utils.currency :as currency]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defn sort-by-timestamp
|
||||
[coll]
|
||||
(when (not-empty coll)
|
||||
(sort-by #(-> % second :timestamp)
|
||||
>
|
||||
(into {} coll))))
|
||||
|
||||
(defn apply-filter
|
||||
"extract-attributes-fn is a function that take an element from the collection
|
||||
and returns a vector of attributes which are strings
|
||||
apply-filter returns the elements for which at least one attribute includes
|
||||
the search-filter
|
||||
apply-filter returns nil if there is no element that match the filter
|
||||
apply-filter returns full collection if the search-filter is empty"
|
||||
[search-filter coll extract-attributes-fn sort?]
|
||||
(let [results (if (not-empty search-filter)
|
||||
(let [search-filter (string/lower-case search-filter)]
|
||||
(filter (fn [element]
|
||||
(some (fn [v]
|
||||
(let [s (cond (string? v) v
|
||||
(keyword? v) (name v))]
|
||||
(when (string? s)
|
||||
(string/includes? (string/lower-case s)
|
||||
search-filter))))
|
||||
(extract-attributes-fn element)))
|
||||
coll))
|
||||
coll)]
|
||||
(if sort?
|
||||
(sort-by-timestamp results)
|
||||
results)))
|
||||
|
||||
(defn extract-currency-attributes
|
||||
[currency]
|
||||
(let [{:keys [code display-name]} (val currency)]
|
||||
[code display-name]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/search-filtered-currencies
|
||||
:<- [:search/currency-filter]
|
||||
(fn [search-currency-filter]
|
||||
{:search-filter search-currency-filter
|
||||
:currencies (apply-filter search-currency-filter
|
||||
currency/currencies
|
||||
extract-currency-attributes
|
||||
false)}))
|
||||
|
||||
(defn extract-token-attributes
|
||||
[token]
|
||||
[(:symbol token) (:name token)])
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/search-token-filter
|
||||
:<- [:ui/search]
|
||||
(fn [search]
|
||||
(get search :token-filter)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/filtered-grouped-chain-tokens
|
||||
:<- [:wallet-legacy/grouped-chain-tokens]
|
||||
:<- [:wallet-legacy/search-token-filter]
|
||||
(fn [[{custom-tokens true default-tokens nil} search-token-filter]]
|
||||
{:search-filter search-token-filter
|
||||
:tokens {true (apply-filter search-token-filter custom-tokens extract-token-attributes false)
|
||||
nil (apply-filter search-token-filter
|
||||
default-tokens
|
||||
extract-token-attributes
|
||||
false)}}))
|
|
@ -1,235 +0,0 @@
|
|||
(ns legacy.status-im.subs.wallet.signing
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ethereum.tokens :as tokens]
|
||||
[legacy.status-im.signing.gas :as signing.gas]
|
||||
[legacy.status-im.wallet.db :as wallet.db]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::send-transaction
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet]
|
||||
(:send-transaction wallet)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.send/symbol
|
||||
:<- [::send-transaction]
|
||||
(fn [send-transaction]
|
||||
(:symbol send-transaction)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.send/camera-flashlight
|
||||
:<- [::send-transaction]
|
||||
(fn [send-transaction]
|
||||
(:camera-flashlight send-transaction)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/settings
|
||||
:<- [:wallet-legacy]
|
||||
(fn [{:keys [settings]}]
|
||||
(reduce-kv #(conj %1 %3) [] settings)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.request/transaction
|
||||
:<- [:wallet-legacy]
|
||||
:request-transaction)
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/binance-chain?
|
||||
:<- [:current-network]
|
||||
(fn [network]
|
||||
(chain/binance-chain-id? (get-in network [:config :NetworkId]))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:signing/fee
|
||||
:<- [:signing/tx]
|
||||
(fn [{:keys [gas gasPrice maxFeePerGas]}]
|
||||
(signing.gas/calculate-max-fee gas (or maxFeePerGas gasPrice))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:signing/currencies
|
||||
:<- [:prices]
|
||||
:<- [:wallet-legacy/currency]
|
||||
:<- [:ethereum/native-currency]
|
||||
(fn [[prices {:keys [code]} {sym :symbol}]]
|
||||
[(name sym)
|
||||
code
|
||||
(get-in prices [sym (keyword code)])]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:signing/priority-fee-suggestions-range
|
||||
:<- [:wallet-legacy/current-priority-fee]
|
||||
:<- [:wallet-legacy/slow-base-fee]
|
||||
:<- [:wallet-legacy/normal-base-fee]
|
||||
:<- [:wallet-legacy/fast-base-fee]
|
||||
(fn [[latest-tip slow normal fast]]
|
||||
(reduce
|
||||
(fn [acc [k fees]]
|
||||
(assoc acc
|
||||
k
|
||||
(reduce
|
||||
(fn [acc [k fee]]
|
||||
(assoc acc
|
||||
k
|
||||
(-> fee
|
||||
money/wei->gwei
|
||||
(money/to-fixed 2))))
|
||||
{}
|
||||
fees)))
|
||||
{}
|
||||
(signing.gas/get-fee-options latest-tip slow normal fast))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:signing/phrase
|
||||
:<- [:profile/profile]
|
||||
(fn [{:keys [signing-phrase]}]
|
||||
signing-phrase))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:signing/sign-message
|
||||
:<- [:signing/sign]
|
||||
:<- [:profile/wallet-accounts]
|
||||
:<- [:prices]
|
||||
(fn [[sign wallet-accounts prices]]
|
||||
(if (= :pinless (:type sign))
|
||||
(let [message (get-in sign [:formatted-data :message])
|
||||
wallet-acc (some #(when (= (:address %) (:receiver message)) %) wallet-accounts)]
|
||||
(cond-> sign
|
||||
(and (:amount message) (:currency message))
|
||||
(assoc :fiat-amount
|
||||
(money/fiat-amount-value (:amount message)
|
||||
(:currency message)
|
||||
:USD
|
||||
prices)
|
||||
:fiat-currency "USD")
|
||||
(and (:receiver message) wallet-acc)
|
||||
(assoc :account wallet-acc)))
|
||||
sign)))
|
||||
|
||||
(defn- too-precise-amount?
|
||||
"Checks if number has any extra digit beyond the allowed number of decimals.
|
||||
It does so by checking the number against its rounded value."
|
||||
[amount decimals]
|
||||
(let [^js bn (money/bignumber amount)]
|
||||
(not (.eq bn (.round bn decimals)))))
|
||||
|
||||
(defn get-amount-error
|
||||
[amount decimals]
|
||||
(when (and (seq amount) decimals)
|
||||
(let [normalized-amount (money/normalize amount)
|
||||
value (money/bignumber normalized-amount)]
|
||||
(cond
|
||||
(not (money/valid? value))
|
||||
{:amount-error (i18n/label :t/validation-amount-invalid-number)}
|
||||
|
||||
(too-precise-amount? normalized-amount decimals)
|
||||
{:amount-error (i18n/label :t/validation-amount-is-too-precise {:decimals decimals})}
|
||||
|
||||
:else nil))))
|
||||
|
||||
(defn get-sufficient-funds-error
|
||||
[balance sym amount]
|
||||
(when-not (money/sufficient-funds? amount (get balance sym))
|
||||
{:amount-error (i18n/label :t/wallet-insufficient-funds)}))
|
||||
|
||||
(defn gas-required-exceeds-allowance?
|
||||
[gas-error-message]
|
||||
(and gas-error-message
|
||||
(string/starts-with?
|
||||
gas-error-message
|
||||
"gas required exceeds allowance")))
|
||||
|
||||
(defn get-sufficient-gas-error
|
||||
[gas-error-message balance sym amount ^js gas ^js gasPrice]
|
||||
(if (and gas gasPrice)
|
||||
(let [^js fee (.times gas gasPrice)
|
||||
^js available-ether (money/bignumber (get balance :ETH 0))
|
||||
^js available-for-gas (if (= :ETH sym)
|
||||
(.minus available-ether (money/bignumber amount))
|
||||
available-ether)]
|
||||
(merge {:gas-error-state (when gas-error-message :gas-is-set)}
|
||||
(when-not (money/sufficient-funds? fee (money/bignumber available-for-gas))
|
||||
{:gas-error (i18n/label :t/wallet-insufficient-gas)})))
|
||||
(let [insufficient-balance? (gas-required-exceeds-allowance? gas-error-message)]
|
||||
{:gas-error-state (when gas-error-message :gas-isnt-set)
|
||||
:insufficient-balalce? insufficient-balance?
|
||||
:gas-error (if insufficient-balance?
|
||||
(i18n/label :t/insufficient-balance-to-cover-fee)
|
||||
(or gas-error-message
|
||||
(i18n/label :t/invalid-number)))})))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:signing/amount-errors
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:signing/tx])
|
||||
(re-frame/subscribe [:balance address])])
|
||||
(fn [[{:keys [amount token gas gasPrice maxFeePerGas approve? gas-error-message]} balance]]
|
||||
(let [gas-price (or maxFeePerGas gasPrice)]
|
||||
(if (and amount token (not approve?))
|
||||
(let [amount-bn (money/formatted->internal (money/bignumber amount)
|
||||
(:symbol token)
|
||||
(:decimals token))
|
||||
amount-error (or (get-amount-error amount (:decimals token))
|
||||
(get-sufficient-funds-error balance (:symbol token) amount-bn))]
|
||||
(merge
|
||||
amount-error
|
||||
(get-sufficient-gas-error gas-error-message balance (:symbol token) amount-bn gas gas-price)))
|
||||
(get-sufficient-gas-error gas-error-message balance nil nil gas gas-price)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.send/prepare-transaction-with-balance
|
||||
:<- [:wallet-legacy/prepare-transaction]
|
||||
:<- [:wallet-legacy]
|
||||
:<- [:offline?]
|
||||
:<- [:wallet-legacy/all-tokens]
|
||||
:<- [:current-network]
|
||||
(fn [[{:keys [from to amount-text] :as transaction}
|
||||
wallet offline? all-tokens current-network]]
|
||||
(let [sym (:symbol transaction)
|
||||
balance (get-in wallet [:accounts (:address from) :balance])
|
||||
{:keys [decimals] :as token} (tokens/asset-for all-tokens current-network sym)
|
||||
{:keys [value error]} (wallet.db/parse-amount amount-text decimals)
|
||||
amount (money/formatted->internal value sym decimals)
|
||||
{:keys [amount-error] :as transaction-new}
|
||||
(merge transaction
|
||||
{:amount-error error}
|
||||
(when amount
|
||||
(get-sufficient-funds-error balance sym amount)))]
|
||||
(assoc transaction-new
|
||||
:amount amount
|
||||
:balance balance
|
||||
:token (assoc token :amount (get balance (:symbol token)))
|
||||
:sign-enabled? (and to
|
||||
(nil? amount-error)
|
||||
(not (nil? amount))
|
||||
(not offline?))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.request/prepare-transaction-with-balance
|
||||
:<- [:wallet-legacy/prepare-transaction]
|
||||
:<- [:wallet-legacy]
|
||||
:<- [:offline?]
|
||||
:<- [:wallet-legacy/all-tokens]
|
||||
:<- [:current-network]
|
||||
(fn [[{:keys [from to amount-text] :as transaction}
|
||||
wallet offline? all-tokens current-network]]
|
||||
(let [sym (:symbol transaction)
|
||||
balance (get-in wallet [:accounts (:address from) :balance])
|
||||
{:keys [decimals] :as token} (tokens/asset-for all-tokens current-network sym)
|
||||
{:keys [value error]} (wallet.db/parse-amount amount-text decimals)
|
||||
amount (money/formatted->internal value sym decimals)
|
||||
{:keys [amount-error] :as transaction-new}
|
||||
(assoc transaction :amount-error error)]
|
||||
(assoc transaction-new
|
||||
:amount amount
|
||||
:balance balance
|
||||
:token (assoc token :amount (get balance (:symbol token)))
|
||||
:sign-enabled? (and to
|
||||
from
|
||||
(nil? amount-error)
|
||||
(not (nil? amount))
|
||||
(not offline?))))))
|
|
@ -1,247 +0,0 @@
|
|||
(ns legacy.status-im.subs.wallet.transactions
|
||||
(:require
|
||||
[legacy.status-im.ethereum.transactions.core :as transactions]
|
||||
[legacy.status-im.notifications.wallet :as notifications.wallet]
|
||||
[legacy.status-im.wallet.db :as wallet.db]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.datetime :as datetime]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/accounts
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet]
|
||||
(get wallet :accounts)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/account-by-transaction-hash
|
||||
:<- [:wallet-legacy/accounts]
|
||||
(fn [accounts [_ tx-hash]]
|
||||
(some (fn [[address account]]
|
||||
(when-let [transaction (get-in account [:transactions tx-hash])]
|
||||
(assoc transaction :address address)))
|
||||
accounts)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/transactions
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet [_ address]]
|
||||
(get-in wallet [:accounts address :transactions])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/filters
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet]
|
||||
(get wallet :filters)))
|
||||
|
||||
(defn enrich-transaction
|
||||
[{:keys [type to from value token] :as transaction}
|
||||
contacts native-currency]
|
||||
(let [[contact-address key-contact key-wallet]
|
||||
(if (= type :inbound)
|
||||
[from :from-contact :to-wallet]
|
||||
[to :to-contact :from-wallet])
|
||||
wallet (i18n/label :t/main-wallet)
|
||||
contact (get contacts contact-address)
|
||||
{:keys [symbol-display decimals] :as asset}
|
||||
(or token native-currency)
|
||||
amount-text (if value
|
||||
(wallet.utils/format-amount value decimals)
|
||||
"...")
|
||||
currency-text (when asset
|
||||
(clojure.core/name (or symbol-display
|
||||
(:symbol asset))))]
|
||||
(cond-> transaction
|
||||
contact (assoc key-contact (:name contact))
|
||||
:always (assoc key-wallet
|
||||
wallet
|
||||
:amount-text amount-text
|
||||
:currency-text currency-text))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.transactions/transactions
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet-legacy/transactions address])
|
||||
(re-frame/subscribe [:contacts/contacts-by-address])
|
||||
(re-frame/subscribe [:ethereum/native-currency])])
|
||||
(fn [[transactions contacts native-currency]]
|
||||
(reduce (fn [acc [tx-hash transaction]]
|
||||
(assoc acc
|
||||
tx-hash
|
||||
(enrich-transaction transaction contacts native-currency))) ;;TODO this doesn't
|
||||
;;look good for performance, we need to calculate this only once for each transaction
|
||||
{}
|
||||
transactions)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.transactions/all-filters?
|
||||
:<- [:wallet-legacy/filters]
|
||||
(fn [filters]
|
||||
(= wallet.db/default-wallet-filters
|
||||
filters)))
|
||||
|
||||
(def filters-labels
|
||||
{:inbound (i18n/label :t/incoming)
|
||||
:outbound (i18n/label :t/outgoing)
|
||||
:pending (i18n/label :t/pending)
|
||||
:failed (i18n/label :t/failed)})
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.transactions/filters
|
||||
:<- [:wallet-legacy/filters]
|
||||
(fn [filters]
|
||||
(map (fn [id]
|
||||
(let [checked? (filters id)]
|
||||
{:id id
|
||||
:label (filters-labels id)
|
||||
:checked? checked?
|
||||
:on-touch #(if checked?
|
||||
(re-frame/dispatch [:wallet-legacy.transactions/remove-filter id])
|
||||
(re-frame/dispatch [:wallet-legacy.transactions/add-filter id]))}))
|
||||
wallet.db/default-wallet-filters)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.transactions.filters/screen
|
||||
:<- [:wallet-legacy.transactions/filters]
|
||||
:<- [:wallet-legacy.transactions/all-filters?]
|
||||
(fn [[filters all-filters?]]
|
||||
{:all-filters? all-filters?
|
||||
:filters filters
|
||||
:on-touch-select-all (when-not all-filters?
|
||||
#(re-frame/dispatch
|
||||
[:wallet-legacy.transactions/add-all-filters]))}))
|
||||
|
||||
(defn- enrich-transaction-for-list
|
||||
[filters
|
||||
{:keys [type from-contact from to-contact to timestamp] :as transaction}
|
||||
address]
|
||||
(when (filters type)
|
||||
(assoc
|
||||
(case type
|
||||
:inbound
|
||||
(assoc transaction
|
||||
:label (i18n/label :t/from-capitalized)
|
||||
:contact-accessibility-label :sender-text
|
||||
:address-accessibility-label :sender-address-text
|
||||
:contact from-contact
|
||||
:address from)
|
||||
(assoc transaction
|
||||
:label (i18n/label :t/to-capitalized)
|
||||
:contact-accessibility-label :recipient-name-text
|
||||
:address-accessibility-label :recipient-address-text
|
||||
:contact to-contact
|
||||
:address to))
|
||||
:time-formatted (datetime/timestamp->time timestamp)
|
||||
:on-touch-fn #(re-frame/dispatch [:wallet-legacy.ui/show-transaction-details
|
||||
(:hash transaction)
|
||||
address]))))
|
||||
|
||||
(defn group-transactions-by-date
|
||||
[transactions]
|
||||
(->> transactions
|
||||
(group-by #(datetime/timestamp->date-key (:timestamp %)))
|
||||
(sort-by key >)
|
||||
(map (fn [[date-key transactions]]
|
||||
{:title (datetime/timestamp->mini-date (:timestamp (first transactions)))
|
||||
:key date-key
|
||||
:data (sort-by :timestamp > transactions)}))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.transactions.history/screen
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet-legacy.transactions/transactions address])
|
||||
(re-frame/subscribe [:wallet-legacy/filters])
|
||||
(re-frame/subscribe [:wallet-legacy.transactions/all-filters?])])
|
||||
(fn [[transactions filters all-filters?] [_ address]]
|
||||
{:all-filters? all-filters?
|
||||
:total (count transactions)
|
||||
:transaction-history-sections
|
||||
(->> transactions
|
||||
vals
|
||||
(keep #(enrich-transaction-for-list filters % address))
|
||||
(group-transactions-by-date))}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/recipient-recent-txs
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet-legacy.transactions/transactions address])])
|
||||
(fn [[transactions] _]
|
||||
(->> transactions
|
||||
vals
|
||||
(sort-by :timestamp >)
|
||||
(remove #(= (:type %) :pending))
|
||||
(take 3))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.transactions.details/current-transaction
|
||||
(fn [[_ _ address] _]
|
||||
[(re-frame/subscribe [:wallet-legacy.transactions/transactions address])
|
||||
(re-frame/subscribe [:ethereum/native-currency])
|
||||
(re-frame/subscribe [:chain-id])])
|
||||
(fn [[transactions native-currency chain-id] [_ tx-hash _]]
|
||||
(let [{:keys [gas-used gas-price fee-cap tip-cap timestamp type]
|
||||
:as transaction}
|
||||
(get transactions tx-hash)
|
||||
native-currency-text (name (or (:symbol-display native-currency)
|
||||
(:symbol native-currency)))]
|
||||
(when transaction
|
||||
(merge transaction
|
||||
{:gas-price-eth (if gas-price
|
||||
(money/wei->str :eth
|
||||
gas-price
|
||||
native-currency-text)
|
||||
"-")
|
||||
:gas-price-gwei (if gas-price
|
||||
(money/wei->str :gwei
|
||||
gas-price)
|
||||
"-")
|
||||
:fee-cap-gwei (if fee-cap
|
||||
(money/wei->str :gwei
|
||||
fee-cap)
|
||||
"-")
|
||||
:tip-cap-gwei (if tip-cap
|
||||
(money/wei->str :gwei
|
||||
tip-cap)
|
||||
"-")
|
||||
:date (datetime/timestamp->long-date timestamp)}
|
||||
(if (= type :unsigned)
|
||||
{:block (i18n/label :t/not-applicable)
|
||||
:cost (i18n/label :t/not-applicable)
|
||||
:gas-limit (i18n/label :t/not-applicable)
|
||||
:gas-used (i18n/label :t/not-applicable)
|
||||
:nonce (i18n/label :t/not-applicable)
|
||||
:hash (i18n/label :t/not-applicable)}
|
||||
{:cost (when gas-used
|
||||
(money/wei->str :eth
|
||||
(money/fee-value gas-used gas-price)
|
||||
native-currency-text))
|
||||
:url (transactions/get-transaction-details-url
|
||||
chain-id
|
||||
(:hash transaction))}))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy.transactions.details/screen
|
||||
(fn [[_ tx-hash address] _]
|
||||
[(re-frame/subscribe [:wallet-legacy.transactions.details/current-transaction tx-hash address])
|
||||
(re-frame/subscribe [:ethereum/current-block])])
|
||||
(fn [[transaction current-block]]
|
||||
(let [confirmations (wallet.db/get-confirmations transaction
|
||||
current-block)]
|
||||
(assoc transaction
|
||||
:confirmations confirmations
|
||||
:confirmations-progress
|
||||
(if (>= confirmations transactions/confirmations-count-threshold)
|
||||
100
|
||||
(* 100 (/ confirmations transactions/confirmations-count-threshold)))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:push-notifications/wallet-transactions
|
||||
:<- [:push-notifications/preferences]
|
||||
(fn [pref]
|
||||
(first (filter #(notifications.wallet/preference= %
|
||||
{:service "wallet"
|
||||
:event "transaction"
|
||||
:identifier "all"})
|
||||
pref))))
|
|
@ -1,295 +0,0 @@
|
|||
(ns legacy.status-im.subs.wallet.wallet
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ethereum.tokens :as tokens]
|
||||
[legacy.status-im.utils.currency :as currency]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.config :as config]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:balance
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet [_ address]]
|
||||
(get-in wallet [:accounts address :balance])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:balance-default
|
||||
:<- [:wallet-legacy]
|
||||
:<- [:profile/wallet-accounts]
|
||||
(fn [[wallet accounts]]
|
||||
(get-in wallet [:accounts (:address (wallet.utils/get-default-account accounts)) :balance])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:balances
|
||||
:<- [:wallet-legacy]
|
||||
:<- [:multiaccount/visible-accounts]
|
||||
(fn [[wallet accounts]]
|
||||
(let [accounts (map :address accounts)]
|
||||
(map :balance (vals (select-keys (:accounts wallet) accounts))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:empty-balances?
|
||||
:<- [:balances]
|
||||
(fn [balances]
|
||||
(every?
|
||||
(fn [balance]
|
||||
(every?
|
||||
(fn [^js asset]
|
||||
(or (nil? asset) (.isZero asset)))
|
||||
(vals balance)))
|
||||
balances)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:price
|
||||
:<- [:prices]
|
||||
(fn [prices [_ fsym tsym]]
|
||||
(get-in prices [fsym tsym])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:last-day
|
||||
:<- [:prices]
|
||||
(fn [prices [_ fsym tsym]]
|
||||
(get-in prices [fsym tsym :last-day])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/settings-currency
|
||||
:<- [:profile/profile]
|
||||
(fn [settings]
|
||||
(or (get settings :currency) :usd)))
|
||||
|
||||
(defn get-balance-total-value
|
||||
[balance prices currency token->decimals]
|
||||
(reduce-kv (fn [acc sym value]
|
||||
(if-let [price (get-in prices [sym currency])]
|
||||
(+ acc
|
||||
(or (some-> (money/internal->formatted value sym (token->decimals sym))
|
||||
^js (money/crypto->fiat price)
|
||||
.toNumber)
|
||||
0))
|
||||
acc))
|
||||
0
|
||||
balance))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/token->decimals
|
||||
:<- [:wallet-legacy/all-tokens]
|
||||
(fn [all-tokens]
|
||||
(into {} (map #(vector (:symbol %) (:decimals %)) (vals all-tokens)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:portfolio-value
|
||||
:<- [:balances]
|
||||
:<- [:prices]
|
||||
:<- [:wallet-legacy/currency]
|
||||
:<- [:wallet-legacy/token->decimals]
|
||||
(fn [[balances prices currency token->decimals]]
|
||||
(if (and balances prices)
|
||||
(let [currency-key (-> currency :code keyword)
|
||||
balance-total-value (apply
|
||||
+
|
||||
(map #(get-balance-total-value % prices currency-key token->decimals)
|
||||
balances))]
|
||||
(if (pos? balance-total-value)
|
||||
(-> balance-total-value
|
||||
(money/with-precision 2)
|
||||
str
|
||||
(i18n/format-currency (:code currency)))
|
||||
"0"))
|
||||
"...")))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:account-portfolio-value
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:balance address])
|
||||
(re-frame/subscribe [:prices])
|
||||
(re-frame/subscribe [:wallet-legacy/currency])
|
||||
(re-frame/subscribe [:wallet-legacy/token->decimals])])
|
||||
(fn [[balance prices currency token->decimals]]
|
||||
(if (and balance prices)
|
||||
(let [currency-key (-> currency :code keyword)
|
||||
balance-total-value (get-balance-total-value balance prices currency-key token->decimals)]
|
||||
(if (pos? balance-total-value)
|
||||
(-> balance-total-value
|
||||
(money/with-precision 2)
|
||||
str
|
||||
(i18n/format-currency (:code currency)))
|
||||
"0"))
|
||||
"...")))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/sorted-tokens
|
||||
:<- [:wallet-legacy/all-tokens]
|
||||
(fn [all-tokens]
|
||||
(tokens/sorted-tokens-for all-tokens)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/grouped-chain-tokens
|
||||
:<- [:wallet-legacy/sorted-tokens]
|
||||
:<- [:wallet-legacy/visible-tokens-symbols]
|
||||
(fn [[all-tokens visible-tokens]]
|
||||
(let [vt-set (set visible-tokens)]
|
||||
(group-by :custom?
|
||||
(map #(assoc % :checked? (boolean (get vt-set (keyword (:symbol %))))) all-tokens)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/fetching-tx-history?
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet [_ address]]
|
||||
(get-in wallet [:fetching address :history?])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/fetching-recent-tx-history?
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet [_ address]]
|
||||
(get-in wallet [:fetching address :recent?])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/tx-history-fetched?
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet [_ address]]
|
||||
(get-in wallet [:fetching address :all-fetched?])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/chain-explorer-link
|
||||
(fn [db [_ address]]
|
||||
(let [network (:networks/current-network db)
|
||||
link (get-in config/default-networks-by-id
|
||||
[network :chain-explorer-link])]
|
||||
(when link
|
||||
(str link address)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/error-message
|
||||
:<- [:wallet-legacy]
|
||||
(fn [wallet]
|
||||
(or (get-in wallet [:errors :balance-update])
|
||||
(get-in wallet [:errors :prices-update]))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/visible-tokens-symbols
|
||||
:<- [:ethereum/chain-keyword]
|
||||
:<- [:profile/profile]
|
||||
(fn [[chain current-multiaccount]]
|
||||
(get-in current-multiaccount [:wallet-legacy/visible-tokens chain])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/visible-assets
|
||||
:<- [:current-network]
|
||||
:<- [:wallet-legacy/visible-tokens-symbols]
|
||||
:<- [:wallet-legacy/sorted-tokens]
|
||||
(fn [[network visible-tokens-symbols all-tokens-sorted]]
|
||||
(conj (filter #(contains? visible-tokens-symbols (:symbol %)) all-tokens-sorted)
|
||||
(tokens/native-currency network))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/visible-assets-with-amount
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:balance address])
|
||||
(re-frame/subscribe [:wallet-legacy/visible-assets])])
|
||||
(fn [[balance visible-assets]]
|
||||
(map #(assoc % :amount (get balance (:symbol %))) visible-assets)))
|
||||
|
||||
(defn update-value
|
||||
[prices currency]
|
||||
(fn [{:keys [decimals amount] :as token}]
|
||||
(let [sym (:symbol token)
|
||||
currency-kw (-> currency :code keyword)
|
||||
price (get-in prices [sym currency-kw])]
|
||||
(assoc token
|
||||
:price price
|
||||
:value (when (and amount price)
|
||||
(-> (money/internal->formatted amount sym decimals)
|
||||
(money/crypto->fiat price)
|
||||
(money/with-precision 2)
|
||||
str
|
||||
(i18n/format-currency (:code currency))))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/visible-assets-with-values
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet-legacy/visible-assets-with-amount address])
|
||||
(re-frame/subscribe [:prices])
|
||||
(re-frame/subscribe [:wallet-legacy/currency])])
|
||||
(fn [[assets prices currency]]
|
||||
(let [{:keys [tokens nfts]} (group-by #(if (:nft? %) :nfts :tokens) assets)
|
||||
tokens-with-values (map (update-value prices currency) tokens)]
|
||||
{:tokens tokens-with-values
|
||||
:nfts nfts})))
|
||||
|
||||
(defn get-asset-amount
|
||||
[balances sym]
|
||||
(reduce #(if-let [^js bl (get %2 sym)]
|
||||
(.plus ^js (or ^js %1 ^js (money/bignumber 0)) bl)
|
||||
%1)
|
||||
nil
|
||||
balances))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/all-visible-assets-with-amount
|
||||
:<- [:balances]
|
||||
:<- [:wallet-legacy/visible-assets]
|
||||
(fn [[balances visible-assets]]
|
||||
(map #(assoc % :amount (get-asset-amount balances (:symbol %))) visible-assets)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/all-visible-assets-with-values
|
||||
:<- [:wallet-legacy/all-visible-assets-with-amount]
|
||||
:<- [:prices]
|
||||
:<- [:wallet-legacy/currency]
|
||||
(fn [[assets prices currency]]
|
||||
(let [{:keys [tokens nfts]} (group-by #(if (:nft? %) :nfts :tokens) assets)
|
||||
tokens-with-values (map (update-value prices currency) tokens)]
|
||||
{:tokens tokens-with-values
|
||||
:nfts nfts})))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/transferrable-assets-with-amount
|
||||
(fn [[_ address]]
|
||||
(re-frame/subscribe [:wallet-legacy/visible-assets-with-amount address]))
|
||||
(fn [all-assets]
|
||||
(filter #(not (:nft? %)) all-assets)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/currency
|
||||
:<- [:wallet-legacy/settings-currency]
|
||||
(fn [currency-id]
|
||||
(get currency/currencies currency-id (get currency/currencies :usd))))
|
||||
|
||||
(defn filter-recipient-favs
|
||||
[search-filter {:keys [name]}]
|
||||
(string/includes? (string/lower-case (str name)) search-filter))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/favourites-filtered
|
||||
:<- [:wallet-legacy/favourites]
|
||||
:<- [:wallet-legacy/search-recipient-filter]
|
||||
(fn [[favs search-filter]]
|
||||
(let [favs (vals favs)]
|
||||
(if (string/blank? search-filter)
|
||||
favs
|
||||
(filter (partial filter-recipient-favs
|
||||
(string/lower-case search-filter))
|
||||
favs)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/collectible-collection
|
||||
:<- [:wallet-legacy/collectible-collections]
|
||||
(fn [all-collections [_ address]]
|
||||
(when address
|
||||
(let [all-collections (get all-collections (string/lower-case address) [])]
|
||||
(sort-by :name all-collections)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/collectible-assets-by-collection-and-address
|
||||
:<- [:wallet-legacy/collectible-assets]
|
||||
(fn [all-assets [_ address collectible-slug]]
|
||||
(get-in all-assets [address collectible-slug] [])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-legacy/fetching-assets-by-collectible-slug
|
||||
:<- [:wallet-legacy/fetching-collection-assets]
|
||||
(fn [fetching-collection-assets [_ collectible-slug]]
|
||||
(get fetching-collection-assets collectible-slug false)))
|
|
@ -1,152 +0,0 @@
|
|||
(ns legacy.status-im.subs.wallet.wallet-test
|
||||
(:require
|
||||
[cljs.test :refer [deftest is testing]]
|
||||
[legacy.status-im.subs.wallet.transactions :as wallet.transactions]
|
||||
[legacy.status-im.subs.wallet.wallet :as wallet]
|
||||
[re-frame.db :as rf-db]
|
||||
[test-helpers.unit :as h]
|
||||
[utils.money :as money]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def money-zero (money/bignumber 0))
|
||||
(def money-eth (money/bignumber 8000000000000000000))
|
||||
(def money-snt (money/bignumber 756000000000000000000))
|
||||
(def main-account-id "0x0Fbd")
|
||||
|
||||
(def accounts
|
||||
[{:address "0x0Fbd"
|
||||
:name "Main account"
|
||||
:hidden false
|
||||
:removed false}
|
||||
{:address "0x5B03"
|
||||
:name "Secondary account"
|
||||
:hidden false
|
||||
:removed false}])
|
||||
|
||||
(def wallet
|
||||
{:accounts {main-account-id
|
||||
{:balance {:ETH money-eth :SNT money-snt}
|
||||
:transactions {}
|
||||
:max-block 0}
|
||||
"0x5B03"
|
||||
{:balance {:ETH money-eth :SNT money-snt}
|
||||
:transactions {}
|
||||
:max-block 10}}})
|
||||
|
||||
(def prices
|
||||
{:ETH {:USD 1282.23}
|
||||
:SNT {:USD 0.0232}})
|
||||
|
||||
(def tokens
|
||||
{"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
||||
{:address "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
||||
:name "Ether"
|
||||
:symbol :ETH
|
||||
:decimals 18
|
||||
:chainId 1}
|
||||
"0x744d70fdbe2ba4cf95131626614a1763df805b9e"
|
||||
{:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e"
|
||||
:name "Status Network Token"
|
||||
:symbol :SNT
|
||||
:decimals 18
|
||||
:chainId 1}})
|
||||
|
||||
(h/deftest-sub :balances
|
||||
[sub-name]
|
||||
(swap! rf-db/app-db assoc
|
||||
:profile/wallet-accounts accounts
|
||||
:wallet-legacy wallet)
|
||||
(is (= [{:ETH money-eth
|
||||
:SNT money-snt}
|
||||
{:ETH money-eth
|
||||
:SNT money-snt}]
|
||||
(rf/sub [sub-name]))))
|
||||
|
||||
(h/deftest-sub :wallet-legacy/token->decimals
|
||||
[sub-name]
|
||||
(swap! rf-db/app-db assoc :wallet-legacy/all-tokens tokens)
|
||||
(is (= {:SNT 18 :ETH 18}
|
||||
(rf/sub [sub-name]))))
|
||||
|
||||
(deftest get-balance-total-value-test
|
||||
(is (= 697.53
|
||||
(wallet/get-balance-total-value
|
||||
{:ETH (money/bignumber 1000000000000000000)
|
||||
:SNT (money/bignumber 100000000000000000000)
|
||||
:AST (money/bignumber 10000)}
|
||||
{:ETH {:USD 677.91}
|
||||
:SNT {:USD 0.1562}
|
||||
:AST {:USD 4}}
|
||||
:USD
|
||||
{:ETH 18
|
||||
:SNT 18
|
||||
:AST 4}))))
|
||||
|
||||
(h/deftest-sub :portfolio-value
|
||||
[sub-name]
|
||||
(testing "returns fallback value when balances and prices are not available"
|
||||
(is (= "..." (rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns zero when balance is not positive"
|
||||
(let [empty-wallet {:accounts {main-account-id
|
||||
{:balance {:ETH money-zero
|
||||
:SNT money-zero}}}}]
|
||||
(swap! rf-db/app-db assoc
|
||||
:profile/wallet-accounts accounts
|
||||
:prices prices
|
||||
:wallet-legacy empty-wallet
|
||||
:wallet-legacy/all-tokens tokens)
|
||||
(is (= "0" (rf/sub [sub-name])))))
|
||||
|
||||
(testing "returns formatted value in the default USD currency"
|
||||
(swap! rf-db/app-db assoc
|
||||
:profile/wallet-accounts accounts
|
||||
:prices prices
|
||||
:wallet-legacy wallet
|
||||
:wallet-legacy/all-tokens tokens)
|
||||
(is (= "20,550.76" (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :account-portfolio-value
|
||||
[sub-name]
|
||||
(testing "returns fallback value when balances and prices are not available"
|
||||
(is (= "..." (rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns zero when balance is not positive"
|
||||
(let [empty-wallet {:accounts {main-account-id
|
||||
{:balance {:ETH money-zero
|
||||
:SNT money-zero}}}}]
|
||||
(swap! rf-db/app-db assoc
|
||||
:profile/wallet-accounts accounts
|
||||
:prices prices
|
||||
:wallet-legacy empty-wallet
|
||||
:wallet-legacy/all-tokens tokens)
|
||||
(is (= "0" (rf/sub [sub-name main-account-id])))))
|
||||
|
||||
(testing "returns formatted value in the default USD currency"
|
||||
(swap! rf-db/app-db assoc
|
||||
:profile/wallet-accounts accounts
|
||||
:prices prices
|
||||
:wallet-legacy wallet
|
||||
:wallet-legacy/all-tokens tokens)
|
||||
(is (= "10,275.38" (rf/sub [sub-name main-account-id])))))
|
||||
|
||||
(def transactions
|
||||
[{:timestamp "1505912551000"}
|
||||
{:timestamp "1505764322000"}
|
||||
{:timestamp "1505750000000"}])
|
||||
|
||||
(def grouped-transactions
|
||||
'({:title "20 Sep"
|
||||
:key :20170920
|
||||
:data
|
||||
({:timestamp "1505912551000"})}
|
||||
{:title "18 Sep"
|
||||
:key :20170918
|
||||
:data
|
||||
({:timestamp "1505764322000"}
|
||||
{:timestamp "1505750000000"})}))
|
||||
|
||||
(deftest group-transactions-by-date
|
||||
(testing "Check if transactions are sorted by date"
|
||||
(is (= (wallet.transactions/group-transactions-by-date transactions)
|
||||
grouped-transactions))))
|
|
@ -11,7 +11,6 @@
|
|||
[legacy.status-im.ui.screens.browser.accounts :as accounts]
|
||||
[legacy.status-im.ui.screens.browser.empty-tab.styles :as styles]
|
||||
[legacy.status-im.ui.screens.browser.views :as browser]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as components]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]
|
||||
|
@ -144,7 +143,7 @@
|
|||
:container-style styles/input-container-style
|
||||
:accessibility-label :dapp-url-input
|
||||
:return-key-type :go}]
|
||||
[components/separator-dark]
|
||||
[react/view {:style {:height 1 :background-color (colors/alpha colors/black 0.1)}}]
|
||||
[list/flat-list
|
||||
{:header [list-header (empty? bookmarks)]
|
||||
:data bookmarks
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as components]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
|
@ -32,7 +31,7 @@
|
|||
:subtitle (utils/get-shortened-checksum-address (:address account))
|
||||
:accessory [icons/icon :main-icons/check {:color colors/gray}]}]
|
||||
[react/view {:padding-vertical 8}
|
||||
[components/separator]]
|
||||
[react/view {:style {:height 1 :background-color (colors/alpha colors/black 0.1)}}]]
|
||||
[list.item/list-item
|
||||
{:theme :negative
|
||||
:title (i18n/label :t/revoke-access)
|
||||
|
@ -86,7 +85,7 @@
|
|||
(js/setTimeout
|
||||
#(browser/share-link url)
|
||||
200))}]
|
||||
[components/separator]])
|
||||
[react/view {:style {:height 1 :background-color (colors/alpha colors/black 0.1)}}]])
|
||||
(if connected?
|
||||
[list.item/list-item
|
||||
{:icon [chat-icon/custom-icon-view-list (:name account) (:color account)]
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
[legacy.status-im.ui.components.plus-button :as components.plus-button]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as components]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]
|
||||
|
@ -67,7 +66,7 @@
|
|||
:on-press #(do (re-frame/dispatch [:browser.ui/clear-all-browsers-pressed])
|
||||
(re-frame/dispatch [:browser.ui/open-empty-tab]))}]
|
||||
:title (i18n/label :t/tabs)}]
|
||||
[components/separator-dark]
|
||||
[react/view {:style {:height 1 :background-color (colors/alpha colors/black 0.1)}}]
|
||||
[list/flat-list
|
||||
{:data (conj browsers
|
||||
{:empty-tab true
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
[legacy.status-im.ui.screens.browser.permissions.views :as permissions.views]
|
||||
[legacy.status-im.ui.screens.browser.site-blocked.views :as site-blocked.views]
|
||||
[legacy.status-im.ui.screens.browser.styles :as styles]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as components]
|
||||
[legacy.status-im.utils.js-resources :as js-res]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.permissions :as components.permissions]
|
||||
|
@ -258,7 +257,7 @@
|
|||
url-original (browser/get-current-url current-browser)]
|
||||
[react/view {:style styles/browser}
|
||||
[toolbar-content url url-original secure? url-editing? unsafe?]
|
||||
[components/separator-dark]
|
||||
[react/view {:style {:height 1 :background-color (colors/alpha colors/black 0.1)}}]
|
||||
[react/view
|
||||
(when loading?
|
||||
[connectivity/loading-indicator-anim window-width])]
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.chat.utils :as chat.utils]
|
||||
[legacy.status-im.ui.screens.profile.components.views :as profile.components]
|
||||
[legacy.status-im.ui.screens.wallet.send.sheets :as sheets]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
|
@ -292,9 +291,7 @@
|
|||
:title (:name account)
|
||||
:subtitle (utils/get-shortened-checksum-address (:address account))
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content (fn [] [sheets/accounts-list :from
|
||||
::ens/change-address])}])}]))
|
||||
:on-press #(js/alert "funcitonality no longer supported")}]))
|
||||
|
||||
(defn- registration
|
||||
[checked contract address public-key]
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
[legacy.status-im.ui.screens.reset-password.views :as reset-password.views]
|
||||
[legacy.status-im.ui.screens.signing.sheets :as signing-sheets]
|
||||
[legacy.status-im.ui.screens.signing.views :as signing]
|
||||
[legacy.status-im.ui.screens.wallet.request.views :as request]
|
||||
[legacy.status-im.ui.screens.wallet.signing-phrase.views :as signing-phrase]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.platform :as platform]
|
||||
[reagent.core :as reagent]))
|
||||
|
@ -131,12 +129,6 @@
|
|||
(vector? view)
|
||||
view
|
||||
|
||||
(= :signing-phrase view)
|
||||
[signing-phrase/signing-phrase]
|
||||
|
||||
(= :share-account view)
|
||||
[request/share-address]
|
||||
|
||||
(= :share-chat-key view)
|
||||
[profile.user/share-chat-key]
|
||||
|
||||
|
|
|
@ -49,19 +49,6 @@
|
|||
[legacy.status-im.ui.screens.sync-settings.views :as sync-settings]
|
||||
[legacy.status-im.ui.screens.wakuv2-settings.edit-node.views :as edit-wakuv2-node]
|
||||
[legacy.status-im.ui.screens.wakuv2-settings.views :as wakuv2-settings]
|
||||
[legacy.status-im.ui.screens.wallet.account-settings.views :as account-settings]
|
||||
[legacy.status-im.ui.screens.wallet.account.views :as wallet.account]
|
||||
[legacy.status-im.ui.screens.wallet.accounts-manage.views :as accounts-manage]
|
||||
[legacy.status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||
[legacy.status-im.ui.screens.wallet.add-new.views :as add-account]
|
||||
[legacy.status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto]
|
||||
[legacy.status-im.ui.screens.wallet.collectibles.views :as wallet.collectibles]
|
||||
[legacy.status-im.ui.screens.wallet.custom-tokens.views :as custom-tokens]
|
||||
[legacy.status-im.ui.screens.wallet.recipient.views :as recipient]
|
||||
[legacy.status-im.ui.screens.wallet.send.views :as wallet.send]
|
||||
[legacy.status-im.ui.screens.wallet.settings.views :as wallet-settings]
|
||||
[legacy.status-im.ui.screens.wallet.swap.views :as wallet.swap]
|
||||
[legacy.status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
|
||||
[status-im.contexts.chat.group-details.view :as group-details]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
|
@ -106,86 +93,11 @@
|
|||
;;TODO custom subtitle
|
||||
:component group-chat/new-group}
|
||||
|
||||
;;WALLET
|
||||
|
||||
{:name :wallet-legacy
|
||||
:on-focus [:wallet-legacy/tab-opened]
|
||||
;;TODO wallet redesign
|
||||
;;:options {:statusBar {:backgroundColor quo.colors/neutral-5}}
|
||||
:component wallet.accounts/accounts-overview-old}
|
||||
{:name :wallet-account
|
||||
;;TODO dynamic titleaccounts-overview
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet.account/account}
|
||||
{:name :add-new-account
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true :bottom? true}}
|
||||
:component add-account/add-account-view}
|
||||
{:name :add-new-account-pin
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true}}
|
||||
:component add-account/pin}
|
||||
{:name :account-settings
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true}}
|
||||
:component account-settings/account-settings}
|
||||
{:name :wallet-transaction-details
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet-transactions/transaction-details}
|
||||
{:name :wallet-settings-assets
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet-settings/manage-assets}
|
||||
{:name :wallet-add-custom-token
|
||||
:on-focus [:wallet-legacy/wallet-add-custom-token]
|
||||
:options {:topBar {:title {:text (i18n/label :t/add-custom-token)}}
|
||||
:insets {:top? true}}
|
||||
:component custom-tokens/add-custom-token}
|
||||
{:name :wallet-custom-token-details
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true}}
|
||||
:component custom-tokens/custom-token-details}
|
||||
{:name :currency-settings
|
||||
:options {:topBar {:title {:text (i18n/label :t/main-currency)}}
|
||||
:insets {:top? true}}
|
||||
:component currency-settings/currency-settings}
|
||||
|
||||
{:name :manage-accounts
|
||||
:options {:topBar {:title {:text (i18n/label :t/wallet-manage-accounts)}}
|
||||
:insets {:top? true}}
|
||||
:component accounts-manage/manage}
|
||||
|
||||
{:name :token-swap
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet.swap/swap}
|
||||
|
||||
{:name :token-swap-advanced-nonce
|
||||
:options {:topBar {:title {:text (i18n/label :t/nonce)}}
|
||||
:insets {:top? true}}
|
||||
:component wallet.swap/nonce-modal}
|
||||
|
||||
{:name :token-swap-advanced-approve-token
|
||||
:options {:topBar {:title {:text (i18n/label :t/approve-token)}}
|
||||
:insets {:top? true}}
|
||||
:component wallet.swap/approve-token-modal}
|
||||
|
||||
{:name :token-swap-advanced-transaction-fee
|
||||
:options {:topBar {:title {:text (i18n/label :t/transaction-fee)}}
|
||||
:insets {:top? true}}
|
||||
:component wallet.swap/transaction-fee-modal}
|
||||
|
||||
{:name :token-swap-advanced-swap-details
|
||||
:options {:topBar {:title {:text (i18n/label :t/swap-details)}}
|
||||
:insets {:top? true}}
|
||||
:component wallet.swap/swap-details-modal}
|
||||
|
||||
{:name :swap-asset-selector
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet.swap/asset-selector}
|
||||
|
||||
;;PROFILE
|
||||
|
||||
{:name :my-profile
|
||||
|
@ -404,20 +316,6 @@
|
|||
:top? true}}
|
||||
:component communities.invite/legacy-invite}
|
||||
|
||||
;[Wallet] Recipient
|
||||
{:name :recipient
|
||||
;;TODO accessories
|
||||
:options {:insets {:bottom? true
|
||||
:top? true}}
|
||||
:component recipient/recipient}
|
||||
|
||||
;[Wallet] New favourite
|
||||
{:name :new-favourite
|
||||
:options {:topBar {:title {:text (i18n/label :t/new-favourite)}}
|
||||
:insets {:bottom? true
|
||||
:top? true}}
|
||||
:component recipient/new-favourite}
|
||||
|
||||
;QR Scanner
|
||||
{:name :qr-scanner
|
||||
;;TODO custom topbar
|
||||
|
@ -438,44 +336,6 @@
|
|||
:top? true}}
|
||||
:component notifications-settings/notifications-settings}
|
||||
|
||||
;[Wallet] Prepare Transaction
|
||||
{:name :prepare-send-transaction
|
||||
:on-dissmiss [:wallet-legacy/cancel-transaction-command]
|
||||
:options {:topBar {:title {:text (i18n/label :t/send-transaction)}}
|
||||
:swipeToDismiss false
|
||||
:hardwareBackButton {:dismissModalOnPress false}
|
||||
:insets {:bottom? true
|
||||
:top? true}}
|
||||
:component wallet.send/prepare-send-transaction}
|
||||
|
||||
;[Wallet] Request Transaction
|
||||
{:name :request-transaction
|
||||
:on-dissmiss [:wallet-legacy/cancel-transaction-command]
|
||||
:options {:topBar {:title {:text (i18n/label :t/request-transaction)}}
|
||||
:swipeToDismiss false
|
||||
:hardwareBackButton {:dismissModalOnPress false}
|
||||
:insets {:bottom? true
|
||||
:top? true}}
|
||||
:component wallet.send/request-transaction}
|
||||
|
||||
;[Wallet] Buy crypto
|
||||
{:name :buy-crypto
|
||||
:insets {:bottom? true}
|
||||
:component wallet.buy-crypto/container}
|
||||
|
||||
;[Wallet] Buy crypto website
|
||||
{:name :buy-crypto-website
|
||||
;;TODO subtitle
|
||||
:options {:insets {:bottom? true
|
||||
:top? true}}
|
||||
:component wallet.buy-crypto/website}
|
||||
|
||||
{:name :nft-details
|
||||
;;TODO dynamic title
|
||||
:options {:insets {:bottom? true
|
||||
:top? true}}
|
||||
:component wallet.collectibles/nft-details-modal}
|
||||
|
||||
;[Browser] New bookmark
|
||||
{:name :new-bookmark
|
||||
;;TODO dynamic title
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
(:require-macros [legacy.status-im.utils.views :as views])
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ethereum.tokens :as tokens]
|
||||
[legacy.status-im.react-native.resources :as resources]
|
||||
[legacy.status-im.signing.eip1559 :as eip1559]
|
||||
[legacy.status-im.ui.components.bottom-panel.views :as bottom-panel]
|
||||
|
@ -15,10 +14,8 @@
|
|||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.screens.signing.sheets :as sheets]
|
||||
[legacy.status-im.ui.screens.signing.styles :as styles]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as wallet.components]
|
||||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
|
@ -57,11 +54,7 @@
|
|||
:style {:margin-right 8}}
|
||||
display-symbol]
|
||||
(if icon
|
||||
[wallet.components/token-icon
|
||||
(assoc icon
|
||||
:style {:background-color colors/gray-lighter
|
||||
:border-radius 16}
|
||||
:image-style {:width 24 :height 24})]
|
||||
[react/view]
|
||||
[chat-icon/custom-icon-view-list (:name token) color 32])]}]
|
||||
[separator]]))
|
||||
|
||||
|
@ -328,7 +321,6 @@
|
|||
[{:keys [from contact amount token cancel?] :as tx}]
|
||||
(views/letsubs [fee [:signing/fee]
|
||||
sign [:signing/sign]
|
||||
chain [:current-network]
|
||||
{:keys [amount-error gas-error gas-error-state insufficient-balalce?]}
|
||||
[:signing/amount-errors (:address from)]
|
||||
keycard-multiaccount? [:keycard-multiaccount?]
|
||||
|
@ -337,8 +329,8 @@
|
|||
mainnet? [:mainnet?]
|
||||
prices-loading? [:prices-loading?]
|
||||
management-enabled? [:wallet-legacy/transactions-management-enabled?]]
|
||||
(let [display-symbol (wallet.utils/display-symbol token)
|
||||
fee-display-symbol (wallet.utils/display-symbol (tokens/native-currency chain))]
|
||||
(let [display-symbol nil
|
||||
fee-display-symbol nil]
|
||||
[react/view (styles/sheet)
|
||||
[header sign tx display-symbol fee fee-display-symbol]
|
||||
[separator]
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
(or owned free)
|
||||
(re-frame/dispatch [:stickers/install-pack id])
|
||||
not-enough-snt? nil
|
||||
:else (re-frame/dispatch [:stickers/buy-pack id]))}
|
||||
:else (fn [] (js/alert "feature no longer supported")))}
|
||||
[react/view (styles/price-badge (and (not (or owned free)) not-enough-snt?))
|
||||
(when (and (not free) (not owned))
|
||||
[icons/tiny-icon :tiny-icons/tiny-snt
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.account.styles
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ui.components.animation :as animation]
|
||||
[legacy.status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn card
|
||||
[window-width color]
|
||||
{:width (- window-width 30)
|
||||
:height 161
|
||||
:background-color (if (string/blank? color)
|
||||
colors/blue
|
||||
color)
|
||||
:shadow-offset {:width 0 :height 2}
|
||||
:shadow-radius 8
|
||||
:shadow-opacity 1
|
||||
:shadow-color (if (colors/dark?)
|
||||
"rgba(0, 0, 0, 0.75)"
|
||||
"rgba(0, 9, 26, 0.12)")
|
||||
:elevation 2
|
||||
:border-radius 8
|
||||
:justify-content :space-between})
|
||||
|
||||
(defn divider
|
||||
[]
|
||||
{:height 52
|
||||
:width 1
|
||||
:background-color colors/black-transparent-20
|
||||
:shadow-offset {:width 0 :height 2}
|
||||
:shadow-radius 8
|
||||
:shadow-opacity 1
|
||||
:shadow-color (if (colors/dark?)
|
||||
"rgba(0, 0, 0, 0.75)"
|
||||
"rgba(0, 9, 26, 0.12)")})
|
||||
|
||||
(defn bottom-send-recv-buttons-raise
|
||||
[anim-y]
|
||||
(animation/timing
|
||||
anim-y
|
||||
{:toValue 0
|
||||
:duration 200
|
||||
:easing (.-ease ^js animation/easing)
|
||||
:useNativeDriver true}))
|
||||
|
||||
(defn bottom-send-recv-buttons-lower
|
||||
[anim-y y]
|
||||
(animation/timing
|
||||
anim-y
|
||||
{:toValue y
|
||||
:duration 200
|
||||
:easing (.-ease ^js animation/easing)
|
||||
:useNativeDriver true}))
|
||||
|
||||
(def round-action-button
|
||||
{:background-color colors/blue
|
||||
:height 44
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:width 44
|
||||
:border-radius 44})
|
||||
|
||||
(def top-actions
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:width "60%"
|
||||
:align-self :center})
|
|
@ -1,363 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.account.views
|
||||
(:require
|
||||
[legacy.status-im.ui.components.animation :as animation]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as components.core]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.spacing :as spacing]
|
||||
[legacy.status-im.ui.components.tabs :as tabs]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.account.styles :as styles]
|
||||
[legacy.status-im.ui.screens.wallet.accounts.common :as common]
|
||||
[legacy.status-im.ui.screens.wallet.accounts.sheets :as sheets]
|
||||
[legacy.status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto]
|
||||
[legacy.status-im.ui.screens.wallet.collectibles.views :as collectibles.views]
|
||||
[legacy.status-im.ui.screens.wallet.transactions.views :as history]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as quo.colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.config :as config]
|
||||
[utils.address :as address]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf])
|
||||
(:require-macros [legacy.status-im.utils.views :as views]))
|
||||
|
||||
(def state (reagent/atom {:tab :assets}))
|
||||
(def selected-tab (reagent/atom :tokens))
|
||||
|
||||
(defn button
|
||||
[label icon color handler]
|
||||
[react/touchable-highlight {:on-press handler :style {:flex 1}}
|
||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||
[react/view {:flex-direction :row :align-items :center}
|
||||
[icons/icon icon {:color color}]
|
||||
[react/text {:style {:margin-left 8 :color color}} label]]]])
|
||||
|
||||
(def button-group-height 52)
|
||||
|
||||
(views/defview account-card
|
||||
[{:keys [address color type] :as account}]
|
||||
(views/letsubs [currency [:wallet-legacy/currency]
|
||||
portfolio-value [:account-portfolio-value address]
|
||||
window-width [:dimensions/window-width]
|
||||
prices-loading? [:prices-loading?]]
|
||||
[react/view {:style (styles/card window-width color)}
|
||||
[react/view {:padding 16 :padding-bottom 12 :flex 1 :justify-content :space-between}
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
(if prices-loading?
|
||||
[react/small-loading-indicator :colors/white-persist]
|
||||
[react/text {:style {:font-size 32 :color colors/white-persist :font-weight "600"}}
|
||||
portfolio-value])
|
||||
[react/text {:style {:font-size 32 :color colors/white-transparent-persist :font-weight "600"}}
|
||||
(str " " (:code currency))]]
|
||||
[components.core/text
|
||||
{:number-of-lines 1
|
||||
:ellipsize-mode :middle
|
||||
:monospace true
|
||||
:size :small
|
||||
:style {:width (/ window-width 3)
|
||||
:line-height 22
|
||||
:color colors/white-transparent-70-persist}}
|
||||
(address/normalized-hex address)]]
|
||||
[react/view {:position :absolute :top 12 :right 12}
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet-legacy/share-popover address])}
|
||||
[icons/icon :main-icons/share
|
||||
{:color colors/white-persist
|
||||
:accessibility-label :share-wallet-address-icon}]]]
|
||||
[react/view
|
||||
{:height button-group-height
|
||||
:background-color colors/black-transparent-20
|
||||
:border-bottom-right-radius 8
|
||||
:border-bottom-left-radius 8
|
||||
:flex-direction :row}
|
||||
(if (= type :watch)
|
||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||
[react/text {:style {:margin-left 8 :color colors/white-persist}}
|
||||
(i18n/label :t/watch-only)]]
|
||||
[button
|
||||
(i18n/label :t/wallet-send)
|
||||
:main-icons/send
|
||||
colors/white-persist
|
||||
#(re-frame/dispatch [:wallet-legacy/prepare-transaction-from-wallet account])])
|
||||
[react/view {:style (styles/divider)}]
|
||||
[button
|
||||
(i18n/label :t/receive)
|
||||
:main-icons/receive
|
||||
colors/white-persist
|
||||
#(re-frame/dispatch [:wallet-legacy/share-popover address])]]]))
|
||||
|
||||
(views/defview transactions
|
||||
[address]
|
||||
(views/letsubs [data [:wallet-legacy.transactions.history/screen address]]
|
||||
[history/history-list data address]))
|
||||
|
||||
(defn opensea-link
|
||||
[address]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:browser.ui/open-url (str "https://opensea.io/" address)])}
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:padding-horizontal 14
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color colors/blue-light
|
||||
:height 52}}
|
||||
[icons/tiny-icon
|
||||
:tiny-icons/tiny-external
|
||||
{:color colors/blue
|
||||
:container-style {:margin-right 5}}]
|
||||
[react/text
|
||||
{:style {:color colors/blue}}
|
||||
(i18n/label :t/check-on-opensea)]]])
|
||||
|
||||
(views/defview assets-and-collections-new
|
||||
[address]
|
||||
(views/letsubs [{:keys [tokens]} [:wallet-legacy/visible-assets-with-values address]
|
||||
currency [:wallet-legacy/currency]
|
||||
opensea-enabled? [:opensea-enabled?]
|
||||
collectible-collection [:wallet-legacy/collectible-collection address]]
|
||||
;ethereum-network? [:ethereum-network?]]
|
||||
(let [tab @selected-tab]
|
||||
[react/view {:flex 1}
|
||||
[react/view {:padding-horizontal 20 :padding-bottom 20}
|
||||
[quo/tabs
|
||||
{:size 24
|
||||
:on-change #(reset! selected-tab %)
|
||||
:default-active :tokens
|
||||
:data [{:id :tokens :label "Tokens"}
|
||||
{:id :nft :label "NFTs"}
|
||||
{:id :activity :label "Activity"}]}]]
|
||||
(cond
|
||||
(= tab :tokens)
|
||||
[react/scroll-view
|
||||
(for [item tokens]
|
||||
^{:key (:name item)}
|
||||
[common/render-asset-new item nil nil (:code currency)])]
|
||||
(= tab :nft)
|
||||
[:<>
|
||||
[opensea-link address]
|
||||
;; Hide collectibles behind a feature flag
|
||||
(when config/collectibles-enabled?
|
||||
(cond
|
||||
(not opensea-enabled?)
|
||||
[collectibles.views/enable-opensea-view]
|
||||
|
||||
(and opensea-enabled? (seq collectible-collection))
|
||||
[collectibles.views/nft-collections address]
|
||||
|
||||
:else
|
||||
[react/view {:align-items :center :margin-top 32}
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/no-collectibles)]]))]
|
||||
(= tab :activity)
|
||||
[transactions address])])))
|
||||
|
||||
(views/defview bottom-send-recv-buttons
|
||||
[{:keys [address type] :as account} anim-y]
|
||||
[react/animated-view
|
||||
{:style {:background-color colors/white
|
||||
:bottom 0
|
||||
:flex-direction :row
|
||||
:height button-group-height
|
||||
:position :absolute
|
||||
:shadow-offset {:width 0 :height 1}
|
||||
:shadow-opacity 0.75
|
||||
:shadow-radius 1
|
||||
:transform [{:translateY anim-y}]
|
||||
:width "100%"}}
|
||||
(if (= type :watch)
|
||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||
[react/text {:style {:margin-left 8 :color colors/blue-persist}}
|
||||
(i18n/label :t/watch-only)]]
|
||||
[button
|
||||
(i18n/label :t/wallet-send)
|
||||
:main-icons/send
|
||||
colors/blue-persist
|
||||
#(re-frame/dispatch [:wallet-legacy/prepare-transaction-from-wallet account])])
|
||||
[button
|
||||
(i18n/label :t/receive)
|
||||
:main-icons/receive
|
||||
colors/blue-persist
|
||||
#(re-frame/dispatch [:wallet-legacy/share-popover address])]])
|
||||
|
||||
(defn anim-listener
|
||||
[anim-y scroll-y]
|
||||
(let [to-show (atom false)]
|
||||
(animation/add-listener
|
||||
scroll-y
|
||||
(fn [anim]
|
||||
(let [y-trigger 149]
|
||||
(cond
|
||||
(and (>= (.-value anim) y-trigger) (not @to-show))
|
||||
(animation/start
|
||||
(styles/bottom-send-recv-buttons-raise anim-y)
|
||||
#(reset! to-show true))
|
||||
|
||||
(and (< (.-value anim) y-trigger) @to-show)
|
||||
(animation/start
|
||||
(styles/bottom-send-recv-buttons-lower anim-y button-group-height)
|
||||
#(reset! to-show false))))))))
|
||||
|
||||
(defn round-action-button
|
||||
[{:keys [icon title on-press]}]
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:align-items :center
|
||||
:margin-vertical (:large spacing/spacing)}}
|
||||
[react/touchable-opacity
|
||||
{:style styles/round-action-button
|
||||
:on-press on-press}
|
||||
(icons/icon icon {:color colors/white})]
|
||||
[components.core/text
|
||||
{:color :secondary
|
||||
:size :small
|
||||
:style {:margin-top (:tiny spacing/spacing)}}
|
||||
title]])
|
||||
|
||||
(defn top-actions
|
||||
[]
|
||||
[react/view {:style styles/top-actions}
|
||||
[round-action-button
|
||||
{:icon :main-icons/add
|
||||
:title (i18n/label :t/buy-crypto)
|
||||
:on-press #(re-frame/dispatch [:buy-crypto.ui/open-screen])}]
|
||||
[round-action-button
|
||||
{:icon :main-icons/change
|
||||
:title (i18n/label :t/swap)
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap])}]])
|
||||
|
||||
(views/defview assets-and-collections
|
||||
[address]
|
||||
(views/letsubs [{:keys [tokens]} [:wallet-legacy/visible-assets-with-values address]
|
||||
currency [:wallet-legacy/currency]
|
||||
opensea-enabled? [:opensea-enabled?]
|
||||
collectible-collection [:wallet-legacy/collectible-collection address]
|
||||
ethereum-network? [:ethereum-network?]]
|
||||
(let [{:keys [tab]} @state]
|
||||
[react/view {:flex 1}
|
||||
[react/view {:flex-direction :row :margin-bottom 8 :padding-horizontal 4}
|
||||
[tabs/tab-title state :assets (i18n/label :t/wallet-assets) (= tab :assets)]
|
||||
(when ethereum-network?
|
||||
[tabs/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)])
|
||||
[tabs/tab-title state :history (i18n/label :t/history) (= tab :history)]]
|
||||
[quo/separator {:style {:margin-top -8}}]
|
||||
(cond
|
||||
(= tab :assets)
|
||||
[:<>
|
||||
(for [item tokens]
|
||||
^{:key (:name item)}
|
||||
[common/render-asset item nil nil (:code currency)])]
|
||||
(= tab :nft)
|
||||
[:<>
|
||||
[opensea-link address]
|
||||
;; Hide collectibles behind a feature flag
|
||||
(when config/collectibles-enabled?
|
||||
(cond
|
||||
(not opensea-enabled?)
|
||||
[collectibles.views/enable-opensea-view]
|
||||
|
||||
(and opensea-enabled? (seq collectible-collection))
|
||||
[collectibles.views/nft-collections address]
|
||||
|
||||
:else
|
||||
[react/view {:align-items :center :margin-top 32}
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/no-collectibles)]]))]
|
||||
(= tab :history)
|
||||
[transactions address])])))
|
||||
|
||||
(defn account-new
|
||||
[selected-account]
|
||||
(let [;{:keys [name address] :as account} (rf/sub [:account-by-address selected-account])
|
||||
currency (rf/sub [:wallet-legacy/currency])
|
||||
portfolio-value (rf/sub [:account-portfolio-value selected-account])
|
||||
width (rf/sub [:dimensions/window-width])
|
||||
button-width (/ (- width 40 (* 2 12)) 3)]
|
||||
;fetching-error (rf/sub [:wallet-legacy/fetching-error])]
|
||||
[react/view
|
||||
{:flex 1
|
||||
:background-color (quo.colors/theme-colors quo.colors/white quo.colors/neutral-90)
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20
|
||||
:elevation 4
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 20
|
||||
:shadow-color (:shadow-01 @colors/theme)
|
||||
:shadow-offset {:width 0 :height 4}}
|
||||
[react/view {:padding 20}
|
||||
[quo/text {:size :heading-2 :weight :semi-bold} (str portfolio-value " " (:code currency))]]
|
||||
[react/view
|
||||
[react/scroll-view {:horizontal true :margin-bottom 32 :showsHorizontalScrollIndicator false}
|
||||
[react/view {:width 20}]
|
||||
[quo/button {:size 56 :width button-width :above :i/placeholder} "Buy"]
|
||||
[react/view {:width 12}]
|
||||
[quo/button {:size 56 :width button-width :type :secondary :above :i/placeholder} "Send"]
|
||||
[react/view {:width 12}]
|
||||
[quo/button {:size 56 :width button-width :type :secondary :above :i/placeholder}
|
||||
"Receive"]
|
||||
[react/view {:width 12}]
|
||||
[quo/button {:size 56 :width button-width :type :secondary :above :i/placeholder} "Swap"]
|
||||
[react/view {:width 20}]]]
|
||||
[assets-and-collections-new selected-account]]))
|
||||
|
||||
(views/defview account
|
||||
[]
|
||||
(views/letsubs [{:keys [name address] :as current-account} [:multiaccount/current-account]
|
||||
fetching-error [:wallet-legacy/fetching-error]]
|
||||
(let [anim-y (animation/create-value button-group-height)
|
||||
scroll-y (animation/create-value 0)]
|
||||
(anim-listener anim-y scroll-y)
|
||||
[:<>
|
||||
[topbar/topbar
|
||||
{:title name
|
||||
:right-accessories
|
||||
[{:icon :main-icons/more
|
||||
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content sheets/account-settings
|
||||
:content-height 60}])}]}]
|
||||
[react/animated-scroll-view
|
||||
{:contentContainerStyle {:padding-bottom button-group-height}
|
||||
:on-scroll (animation/event
|
||||
[{:nativeEvent {:contentOffset {:y scroll-y}}}]
|
||||
{:useNativeDriver true})
|
||||
:scrollEventThrottle 1
|
||||
:refreshControl (common/refresh-control
|
||||
(and
|
||||
@common/updates-counter
|
||||
@(re-frame/subscribe [:wallet-legacy/refreshing-history?])))}
|
||||
(when fetching-error
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:align-items :center
|
||||
:margin 8}}
|
||||
[icons/icon
|
||||
:main-icons/warning
|
||||
{:color :red
|
||||
:container-style {:background-color (colors/get-color :negative-02)
|
||||
:height 40
|
||||
:width 40
|
||||
:border-radius 20
|
||||
:align-items :center
|
||||
:justify-content :center}}]
|
||||
[react/view
|
||||
{:style {:justify-content :center
|
||||
:align-items :center
|
||||
:margin-top 8
|
||||
:margin-horizontal 67.5
|
||||
:text-align :center}}
|
||||
[components.core/text
|
||||
{:color :secondary
|
||||
:size :small
|
||||
:style {:text-align :center}}
|
||||
(i18n/label :t/transfers-fetching-failure)]]])
|
||||
[react/view {:padding-left 16}
|
||||
[react/scroll-view {:horizontal true}
|
||||
[react/view {:flex-direction :row :padding-top 8 :padding-bottom 12}
|
||||
[account-card current-account]]]]
|
||||
(if config/swap-enabled?
|
||||
[top-actions]
|
||||
[buy-crypto/banner])
|
||||
[assets-and-collections address]]
|
||||
[bottom-send-recv-buttons current-account anim-y]])))
|
|
@ -1,177 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.account-settings.views
|
||||
(:require-macros [legacy.status-im.utils.views :refer [defview letsubs]])
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.copyable-text :as copyable-text]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn not-valid-password?
|
||||
[password]
|
||||
(< (count (security/safe-unmask-data password)) 6))
|
||||
|
||||
(defn delete-account
|
||||
[_]
|
||||
(let [password (reagent/atom nil)
|
||||
text-input-ref (atom nil)
|
||||
error (reagent/atom nil)]
|
||||
(fn [account]
|
||||
(when (and @text-input-ref error (not @password))
|
||||
(.clear ^js @text-input-ref))
|
||||
[react/view {:padding 20 :width 300}
|
||||
[quo/text-input
|
||||
{:style {:margin-bottom 40}
|
||||
:label (i18n/label :t/password)
|
||||
:show-cancel false
|
||||
:secure-text-entry true
|
||||
:return-key-type :next
|
||||
:on-submit-editing nil
|
||||
:auto-focus true
|
||||
:on-change-text #(reset! password (security/mask-data %))
|
||||
:get-ref #(reset! text-input-ref %)
|
||||
:error (when (and @error (not @password))
|
||||
(if (= :wrong-password @error)
|
||||
(i18n/label :t/wrong-password)
|
||||
(str @error)))}]
|
||||
[quo/button
|
||||
{:on-press (fn []
|
||||
(re-frame/dispatch [:wallet-legacy.accounts/delete-key
|
||||
account
|
||||
@password
|
||||
#(reset! error :wrong-password)])
|
||||
(reset! password nil))
|
||||
:theme :negative
|
||||
:accessibility-label :delete-account-confirm
|
||||
:disabled (not-valid-password? @password)}
|
||||
(i18n/label :t/delete)]])))
|
||||
|
||||
(defview colors-popover
|
||||
[selected-color on-press]
|
||||
(letsubs [width [:dimensions/window-width]]
|
||||
[react/view {:flex 1 :padding-bottom 16}
|
||||
[react/scroll-view {:style {:margin 16}}
|
||||
(doall
|
||||
(for [color colors/account-colors]
|
||||
^{:key color}
|
||||
[react/touchable-highlight {:on-press #(on-press color)}
|
||||
[react/view
|
||||
{:height 52
|
||||
:background-color color
|
||||
:border-radius 8
|
||||
:width (* 0.7 width)
|
||||
:justify-content :center
|
||||
:padding-left 12
|
||||
:margin-bottom 16}
|
||||
[react/view
|
||||
{:height 32
|
||||
:width 32
|
||||
:border-radius 20
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:background-color colors/black-transparent}
|
||||
(when (= selected-color color)
|
||||
[icons/icon :main-icons/check {:color colors/white}])]]]))]
|
||||
[toolbar/toolbar
|
||||
{:center
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:hide-popover])
|
||||
:type :secondary}
|
||||
(i18n/label :t/cancel)]}]]))
|
||||
|
||||
(defn property
|
||||
[label value]
|
||||
[react/view {:margin-top 28}
|
||||
[react/text {:style {:color colors/gray}} label]
|
||||
(if (string? value)
|
||||
[react/text {:style {:margin-top 6}} value]
|
||||
value)])
|
||||
|
||||
(defview account-settings
|
||||
[]
|
||||
(letsubs [{:keys [address color path type] :as account} [:multiaccount/current-account]
|
||||
new-account (reagent/atom nil)
|
||||
keycard? [:keycard-multiaccount?]]
|
||||
[react/keyboard-avoiding-view
|
||||
{:style {:flex 1}
|
||||
:ignore-offset true}
|
||||
[topbar/topbar
|
||||
(cond-> {:title (i18n/label :t/account-settings)}
|
||||
(and @new-account (not= "" (:name @new-account)))
|
||||
(assoc :right-accessories
|
||||
[{:label (i18n/label :t/apply)
|
||||
:on-press
|
||||
#(do
|
||||
(re-frame/dispatch [:wallet-legacy.accounts/save-account
|
||||
account
|
||||
@new-account])
|
||||
(reset! new-account nil))}]))]
|
||||
[react/scroll-view
|
||||
{:keyboard-should-persist-taps :handled
|
||||
:style {:flex 1}}
|
||||
[react/view {:padding-bottom 28 :padding-top 10}
|
||||
[react/view {:margin-horizontal 16}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/account-name)
|
||||
:auto-focus false
|
||||
:default-value (:name account)
|
||||
:accessibility-label :enter-account-name
|
||||
:on-change-text #(swap! new-account assoc :name %)}]
|
||||
[react/text {:style {:margin-top 16 :color colors/gray}} (i18n/label :t/account-color)]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:show-popover
|
||||
{:view [colors-popover color
|
||||
(fn [new-color]
|
||||
(swap! new-account assoc :color new-color)
|
||||
(re-frame/dispatch [:hide-popover]))]
|
||||
:style {:max-height "60%"}}])}
|
||||
[react/view
|
||||
{:height 52
|
||||
:margin-top 12
|
||||
:background-color (or (:color @new-account) color)
|
||||
:border-radius 8
|
||||
:align-items :flex-end
|
||||
:justify-content :center
|
||||
:padding-right 12}
|
||||
[icons/icon :main-icons/dropdown {:color colors/white}]]]
|
||||
[property (i18n/label :t/type)
|
||||
(case type
|
||||
:watch (i18n/label :t/watch-only)
|
||||
(:key :seed) (i18n/label :t/off-status-tree)
|
||||
(i18n/label :t/on-status-tree))]
|
||||
[property (i18n/label :t/wallet-address)
|
||||
[copyable-text/copyable-text-view
|
||||
{:copied-text address}
|
||||
[quo/text
|
||||
{:style {:margin-top 6}
|
||||
:monospace true}
|
||||
address]]]
|
||||
(when-not (= type :watch)
|
||||
[property (i18n/label :t/derivation-path)
|
||||
[copyable-text/copyable-text-view
|
||||
{:copied-text path}
|
||||
[quo/text
|
||||
{:style {:margin-top 6}
|
||||
:monospace true} path]]])
|
||||
(when-not (= type :watch)
|
||||
[property (i18n/label :t/storage)
|
||||
(i18n/label (if keycard?
|
||||
:t/keycard
|
||||
:t/this-device))])]
|
||||
(when (#{:key :seed :watch} type)
|
||||
[react/view
|
||||
[react/view {:margin-bottom 8 :margin-top 28 :height 1 :background-color colors/gray-lighter}]
|
||||
[list.item/list-item
|
||||
{:theme :negative
|
||||
:title (i18n/label :t/delete-account)
|
||||
:on-press #(if (= :watch type)
|
||||
(re-frame/dispatch [:wallet-legacy.settings/show-delete-account-confirmation
|
||||
account])
|
||||
(re-frame/dispatch [:show-popover {:view [delete-account account]}]))}]])]]]))
|
|
@ -1,81 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.accounts.common
|
||||
(:require
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[legacy.status-im.ui.components.core :as components]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as wallet.components]
|
||||
[legacy.status-im.utils.utils :as utils.utils]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as quo.colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; Note(rasom): sometimes `refreshing` might get stuck on iOS if action happened
|
||||
;; too fast. By updating this atom in 1s we ensure that `refreshing?` property
|
||||
;; is updated properly in this case.
|
||||
(def updates-counter (reagent/atom 0))
|
||||
|
||||
(defn schedule-counter-reset
|
||||
[]
|
||||
(utils.utils/set-timeout
|
||||
(fn []
|
||||
(swap! updates-counter inc)
|
||||
(when @(re-frame/subscribe [:wallet-legacy/refreshing-history?])
|
||||
(schedule-counter-reset)))
|
||||
1000))
|
||||
|
||||
(defn refresh-action
|
||||
[]
|
||||
(schedule-counter-reset)
|
||||
(re-frame/dispatch [:wallet-legacy.ui/pull-to-refresh-history]))
|
||||
|
||||
(defn refresh-control
|
||||
[refreshing?]
|
||||
(reagent/as-element
|
||||
[rn/refresh-control
|
||||
{:refreshing (boolean refreshing?)
|
||||
:onRefresh refresh-action}]))
|
||||
|
||||
(defn render-asset
|
||||
[{:keys [icon decimals amount color value] :as token} _ _ currency]
|
||||
[list.item/list-item
|
||||
{:title [components/text {:weight :medium}
|
||||
[components/text {:weight :inherit}
|
||||
(str (if amount
|
||||
(wallet.utils/format-amount amount decimals)
|
||||
"...")
|
||||
" ")]
|
||||
[components/text
|
||||
{:color :secondary
|
||||
:weight :inherit}
|
||||
(wallet.utils/display-symbol token)]]
|
||||
:subtitle (str (if value value "...") " " currency)
|
||||
:accessibility-label (str (:symbol token) "-asset-value")
|
||||
:icon (if icon
|
||||
[wallet.components/token-icon icon]
|
||||
[chat-icon/custom-icon-view-list (:name token) color])}])
|
||||
|
||||
(defn render-asset-new
|
||||
[{:keys [icon decimals amount color value name] :as token} _ _ currency]
|
||||
[rn/view {:height 56 :margin-horizontal 8 :margin-top 4}
|
||||
[rn/view {:position :absolute :left 12 :top 12}
|
||||
(if icon
|
||||
[wallet.components/token-icon (merge icon {:width 32 :height 32})]
|
||||
[chat-icon/custom-icon-view-list (:name token) color])]
|
||||
[rn/view {:position :absolute :left 52 :top 8 :right 12}
|
||||
[rn/view {:flex-direction :row :justify-content :space-between :align-items :center}
|
||||
[quo/text {:weight :semi-bold :style {:height 22}}
|
||||
name]
|
||||
[quo/text {:size :paragraph-2 :weight :medium}
|
||||
(str (if value value "...") " " currency)]]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style {:color (quo.colors/theme-colors quo.colors/neutral-50 quo.colors/neutral-40)}}
|
||||
(str (if amount
|
||||
(wallet.utils/format-amount amount decimals)
|
||||
"...")
|
||||
" "
|
||||
(wallet.utils/display-symbol token))]]])
|
|
@ -1,135 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.accounts.sheets
|
||||
(:require
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn hide-sheet-and-dispatch
|
||||
[event]
|
||||
(re-frame/dispatch [:bottom-sheet/hide-old])
|
||||
(re-frame/dispatch event))
|
||||
|
||||
(defn accounts-options
|
||||
[mnemonic]
|
||||
(fn []
|
||||
[:<>
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/wallet-manage-accounts)
|
||||
:icon :main-icons/account
|
||||
:accessibility-label :wallet-manage-accounts
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:navigate-to :manage-accounts])}]
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/wallet-manage-assets)
|
||||
:icon :main-icons/token
|
||||
:accessibility-label :wallet-manage-assets
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:navigate-to :wallet-settings-assets])}]
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/scan-tokens)
|
||||
:icon :main-icons/refresh
|
||||
:accessibility-label :wallet-scan-token
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy/update-balances nil true])}]
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/set-currency)
|
||||
:icon :main-icons/language
|
||||
:accessibility-label :wallet-set-currency
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:navigate-to :currency-settings])}]
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/view-signing)
|
||||
:icon :main-icons/info
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:show-popover {:view :signing-phrase}])}]
|
||||
(when mnemonic
|
||||
[list.item/list-item
|
||||
{:theme :negative
|
||||
:title (i18n/label :t/wallet-backup-recovery-title)
|
||||
:icon :main-icons/security
|
||||
:accessibility-label :wallet-backup-recovery-title
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:navigate-to :backup-seed])}])]))
|
||||
|
||||
(defn account-card-actions
|
||||
[account type wallet]
|
||||
[react/view
|
||||
(when-not (= type :watch)
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/wallet-send)
|
||||
:icon :main-icons/send
|
||||
:accessibility-label :send-transaction-button
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy/prepare-transaction-from-wallet account])}])
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/share)
|
||||
:icon :main-icons/share
|
||||
:accessibility-label :share-account-button
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy/share-popover (:address account)])}]
|
||||
(when-not wallet
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/hide)
|
||||
:icon :main-icons/hide
|
||||
:accessibility-label :hide-account-button
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy.accounts/save-account account {:hidden true}])}])])
|
||||
|
||||
(defn add-account
|
||||
[]
|
||||
(let [keycard? @(re-frame/subscribe [:keycard-multiaccount?])]
|
||||
[react/view
|
||||
[list.item/list-item
|
||||
{:title (i18n/label :t/generate-a-new-account)
|
||||
:theme :accent
|
||||
:icon :main-icons/add
|
||||
:accessibility-label :add-account-sheet-generate
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy.accounts/start-adding-new-account
|
||||
{:type :generate}])}]
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/add-a-watch-account)
|
||||
:icon :main-icons/show
|
||||
:accessibility-label :add-account-sheet-watch
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy.accounts/start-adding-new-account
|
||||
{:type :watch}])}]
|
||||
(when-not keycard?
|
||||
[list.item/list-item
|
||||
{:title (i18n/label :t/enter-a-seed-phrase)
|
||||
:theme :accent
|
||||
:icon :main-icons/text
|
||||
:accessibility-label :add-account-sheet-seed
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy.accounts/start-adding-new-account
|
||||
{:type :seed}])}])
|
||||
(when-not keycard?
|
||||
[list.item/list-item
|
||||
{:title (i18n/label :t/enter-a-private-key)
|
||||
:theme :accent
|
||||
:icon :main-icons/address
|
||||
:accessibility-label :add-account-sheet-private-key
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy.accounts/start-adding-new-account
|
||||
{:type :key}])}])]))
|
||||
|
||||
(defn account-settings
|
||||
[]
|
||||
[react/view
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/account-settings)
|
||||
:accessibility-label :account-settings-bottom-sheet
|
||||
:icon :main-icons/info
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:navigate-to :account-settings])}]])
|
|
@ -1,165 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.accounts.styles
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def dot-size 6)
|
||||
|
||||
(def dot-container
|
||||
{:height 200
|
||||
:flex-direction :column
|
||||
:flex-wrap :wrap
|
||||
:padding-horizontal 8})
|
||||
|
||||
(defn dot-selector
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center})
|
||||
|
||||
(defn dot-style
|
||||
[selected]
|
||||
{:background-color (if selected colors/blue colors/blue-light)
|
||||
:overflow :hidden
|
||||
:opacity 1
|
||||
:margin-horizontal 3
|
||||
:width dot-size
|
||||
:height dot-size
|
||||
:border-radius 3})
|
||||
|
||||
(defn container
|
||||
[{:keys [minimized]}]
|
||||
(when-not minimized
|
||||
{:padding-bottom 8
|
||||
:padding-horizontal 16}))
|
||||
|
||||
(defn value-container
|
||||
[{:keys [minimized animation]}]
|
||||
(when minimized
|
||||
{:opacity animation}))
|
||||
|
||||
(defn value-text
|
||||
[{:keys [minimized]}]
|
||||
{:font-size (if minimized 20 32)
|
||||
:line-height 40
|
||||
:color colors/black})
|
||||
|
||||
(defn accounts-mnemonic
|
||||
[{:keys [animation]}]
|
||||
{:opacity (if animation 1 0)
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0})
|
||||
|
||||
(def card-margin 8)
|
||||
(defn page-width
|
||||
[card-width]
|
||||
(+ card-width (* card-margin 2)))
|
||||
|
||||
(defn card-common
|
||||
[card-width]
|
||||
{:margin card-margin
|
||||
:width card-width
|
||||
:height 82
|
||||
:border-radius 16})
|
||||
|
||||
(defn card
|
||||
[color card-width]
|
||||
(merge (card-common card-width)
|
||||
{:background-color (if (string/blank? color)
|
||||
colors/blue
|
||||
color)
|
||||
:justify-content :space-between
|
||||
:padding-horizontal 12
|
||||
:padding-top 12
|
||||
:padding-bottom 10}))
|
||||
|
||||
(defn add-card
|
||||
[card-width]
|
||||
(merge (card-common card-width)
|
||||
{:background-color colors/white
|
||||
:flex-direction :row
|
||||
:border-width 1
|
||||
:border-color colors/gray-lighter
|
||||
:justify-content :center
|
||||
:align-items :center}))
|
||||
|
||||
(def add-text
|
||||
{:color colors/blue
|
||||
:margin-left 8
|
||||
:font-weight "500"
|
||||
:font-size 15
|
||||
:line-height 22})
|
||||
|
||||
(def card-name
|
||||
{:color colors/white-persist
|
||||
:font-weight "500"
|
||||
:font-size 15
|
||||
:line-height 22})
|
||||
|
||||
(def card-address
|
||||
{:number-of-lines 1
|
||||
:ellipsize-mode :middle
|
||||
:size :small
|
||||
:monospace true
|
||||
:style {:width 110
|
||||
:font-size 15
|
||||
:line-height 22
|
||||
:color colors/white-transparent-70-persist}})
|
||||
|
||||
(def card-value
|
||||
{:color colors/white-persist
|
||||
:font-size 22
|
||||
:font-weight "500"})
|
||||
|
||||
(def card-value-currency
|
||||
{:color colors/white-persist
|
||||
:font-size 22
|
||||
:font-weight "500"})
|
||||
|
||||
(def card-icon-more
|
||||
{:border-radius 32
|
||||
:width 36
|
||||
:height 36
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color colors/black-transparent})
|
||||
|
||||
(def card-icon-type
|
||||
{:border-radius 32
|
||||
:width 36
|
||||
:height 36
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:margin-left :auto
|
||||
:margin-right 12
|
||||
:background-color colors/white-persist})
|
||||
|
||||
(def send-button-container
|
||||
{:position :absolute
|
||||
:z-index 2
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 56
|
||||
:height 40})
|
||||
|
||||
(defn send-button
|
||||
[]
|
||||
{:width 40
|
||||
:height 40
|
||||
:background-color colors/blue
|
||||
:border-radius 20
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:shadow-offset {:width 0 :height 1}
|
||||
:shadow-radius 6
|
||||
:shadow-opacity 1
|
||||
:shadow-color (if (colors/dark?)
|
||||
"rgba(0, 0, 0, 0.75)"
|
||||
"rgba(0, 12, 63, 0.2)")
|
||||
:elevation 2})
|
|
@ -1,302 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.accounts.views
|
||||
(:require
|
||||
[legacy.status-im.keycard.login :as keycard.login]
|
||||
[legacy.status-im.qr-scanner.core :as qr-scanner]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as components.core]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.screens.wallet.account.views :as account.views]
|
||||
[legacy.status-im.ui.screens.wallet.accounts.common :as common]
|
||||
[legacy.status-im.ui.screens.wallet.accounts.sheets :as sheets]
|
||||
[legacy.status-im.ui.screens.wallet.accounts.styles :as styles]
|
||||
[legacy.status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as quo.colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [legacy.status-im.utils.views :as views]))
|
||||
|
||||
(views/defview account-card
|
||||
[{:keys [name color address type wallet] :as account} keycard? card-width]
|
||||
(views/letsubs [currency [:wallet-legacy/currency]
|
||||
portfolio-value [:account-portfolio-value address]
|
||||
prices-loading? [:prices-loading?]]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:navigate-to :wallet-account account])
|
||||
:accessibility-label (str "accountcard" name)}
|
||||
[react/view {:style (styles/card color card-width)}
|
||||
[react/view {:flex-direction :row :align-items :center :justify-content :space-between}
|
||||
[react/text {:style styles/card-name} name]
|
||||
[components.core/text styles/card-address
|
||||
address]]
|
||||
[react/view {:flex-direction :row :align-items :center :justify-content :space-between}
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
(if prices-loading?
|
||||
[react/small-loading-indicator :colors/white-persist]
|
||||
[react/text
|
||||
{:style styles/card-value
|
||||
:accessibility-label "account-total-value"} portfolio-value])
|
||||
[react/text {:style styles/card-value-currency} (str " " (:code currency))]]
|
||||
(let [icon (cond
|
||||
(= type :watch)
|
||||
:main-icons/show
|
||||
|
||||
(and (not= type :watch) keycard?)
|
||||
:main-icons/keycard-account)]
|
||||
(when icon
|
||||
[icons/icon icon
|
||||
{:container-style styles/card-icon-type
|
||||
:color color}]))
|
||||
[react/touchable-highlight
|
||||
{:style styles/card-icon-more
|
||||
:on-press #(re-frame/dispatch
|
||||
[:bottom-sheet/show-sheet-old
|
||||
{:content (fn [] [sheets/account-card-actions account type wallet])
|
||||
:content-height 130}])}
|
||||
[icons/icon :main-icons/more {:color colors/white-persist}]]]]]))
|
||||
|
||||
(defn add-card
|
||||
[card-width]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content sheets/add-account
|
||||
:content-height 260}])
|
||||
:accessibility-label "add-new-account"}
|
||||
[react/view {:style (styles/add-card card-width)}
|
||||
[icons/icon :main-icons/add-circle {:color colors/blue}]
|
||||
[react/text {:style styles/add-text} (i18n/label :t/add-account)]]])
|
||||
|
||||
(views/defview assets
|
||||
[]
|
||||
(views/letsubs [{:keys [tokens]} [:wallet-legacy/all-visible-assets-with-values]
|
||||
currency [:wallet-legacy/currency]]
|
||||
[:<>
|
||||
(for [item tokens]
|
||||
^{:key (:name item)}
|
||||
[common/render-asset item nil nil (:code currency)])]))
|
||||
|
||||
(views/defview send-button
|
||||
[]
|
||||
(views/letsubs [account [:multiaccount/default-account]]
|
||||
[react/view styles/send-button-container
|
||||
[components.core/button
|
||||
{:accessibility-label :send-transaction-button
|
||||
:type :scale
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy/prepare-transaction-from-wallet
|
||||
account])}
|
||||
[react/view (styles/send-button)
|
||||
[icons/icon :main-icons/send {:color colors/white-persist}]]]]))
|
||||
|
||||
(defn dot
|
||||
[]
|
||||
(fn [{:keys [selected]}]
|
||||
[react/view {:style (styles/dot-style selected)}]))
|
||||
|
||||
(defn dots-selector
|
||||
[{:keys [n selected]}]
|
||||
[react/view {:style (styles/dot-selector)}
|
||||
(for [i (range n)]
|
||||
^{:key i}
|
||||
[dot {:selected (= selected i)}])])
|
||||
|
||||
;;ACCOUNTS OLD
|
||||
(views/defview accounts-old
|
||||
[]
|
||||
(views/letsubs [accounts [:multiaccount/visible-accounts]
|
||||
keycard? [:keycard-multiaccount?]
|
||||
window-width [:dimensions/window-width]
|
||||
index (reagent/atom 0)]
|
||||
(let [card-width (quot window-width 1.1)
|
||||
page-width (styles/page-width card-width)]
|
||||
[react/view
|
||||
{:style {:align-items :center
|
||||
:flex 1
|
||||
:justify-content :flex-end}}
|
||||
[react/scroll-view
|
||||
{:horizontal true
|
||||
:deceleration-rate "fast"
|
||||
:snap-to-interval page-width
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:scroll-event-throttle 64
|
||||
:on-scroll #(let [x (.-nativeEvent.contentOffset.x ^js %)]
|
||||
(reset! index (Math/max (Math/round (/ x page-width))
|
||||
0)))}
|
||||
[react/view styles/dot-container
|
||||
(doall
|
||||
(for [account accounts]
|
||||
^{:key account}
|
||||
[account-card account keycard? card-width]))
|
||||
[add-card card-width]]]
|
||||
(let [columns (Math/ceil (/ (inc (count accounts)) 2))
|
||||
totalwidth (* (styles/page-width card-width) columns)
|
||||
n (Math/ceil (/ totalwidth window-width))]
|
||||
(when (> n 1)
|
||||
[dots-selector
|
||||
{:selected @index
|
||||
:n n}]))])))
|
||||
|
||||
;;TOTAL VALUE OLD
|
||||
(views/defview total-value-old
|
||||
[{:keys [animation minimized]}]
|
||||
(views/letsubs [currency [:wallet-legacy/currency]
|
||||
portfolio-value [:portfolio-value]
|
||||
empty-balances? [:empty-balances?]
|
||||
frozen-card? [:keycard/frozen-card?]
|
||||
{:keys [mnemonic]} [:profile/profile]]
|
||||
[reanimated/view {:style (styles/container {:minimized minimized})}
|
||||
(when (or
|
||||
(and frozen-card? minimized)
|
||||
(and mnemonic minimized (not empty-balances?)))
|
||||
[reanimated/view {:style (styles/accounts-mnemonic {:animation animation})}
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch
|
||||
(if frozen-card?
|
||||
[::keycard.login/reset-pin]
|
||||
[:navigate-to :backup-seed]))}
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:align-items :center}
|
||||
[react/view
|
||||
{:width 14
|
||||
:height 14
|
||||
:background-color colors/gray
|
||||
:border-radius 7
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:margin-right 9}
|
||||
[react/text
|
||||
{:style {:color colors/white
|
||||
:font-size 13
|
||||
:font-weight "700"}}
|
||||
"!"]]
|
||||
[react/text
|
||||
{:style {:color colors/gray}
|
||||
:accessibility-label :back-up-your-seed-phrase-warning}
|
||||
(if frozen-card?
|
||||
(i18n/label :t/your-card-is-frozen)
|
||||
(i18n/label :t/back-up-your-seed-phrase))]]]])
|
||||
|
||||
[reanimated/view
|
||||
{:style (styles/value-container {:minimized minimized
|
||||
:animation animation})
|
||||
:pointer-events :none}
|
||||
[reanimated/view {:style {:justify-content :center}}
|
||||
[components.core/text
|
||||
{:animated? true
|
||||
:weight :semi-bold
|
||||
:style (styles/value-text {:minimized minimized})}
|
||||
portfolio-value
|
||||
[components.core/text
|
||||
{:animated? true
|
||||
:size :inherit
|
||||
:weight :inherit
|
||||
:color :secondary}
|
||||
(str " " (:code currency))]]]]
|
||||
(when-not minimized
|
||||
[reanimated/view
|
||||
[components.core/text {:color :secondary}
|
||||
(i18n/label :t/wallet-total-value)]])]))
|
||||
|
||||
(views/defview total-value
|
||||
[]
|
||||
(views/letsubs [currency [:wallet-legacy/currency]
|
||||
portfolio-value [:portfolio-value]]
|
||||
[react/view {:padding-vertical 12}
|
||||
[quo/text (i18n/label :t/wallet-total-value)]
|
||||
[quo/text {:size :heading-1 :weight :semi-bold}
|
||||
(str portfolio-value " " (:code currency))]
|
||||
[react/scroll-view {:horizontal true}]]))
|
||||
|
||||
(views/defview accounts
|
||||
[selected-account-atom]
|
||||
(views/letsubs [visible-accounts [:multiaccount/visible-accounts]]
|
||||
(do
|
||||
(reset! selected-account-atom (:address (first visible-accounts)))
|
||||
(let [accounts-data (for [account visible-accounts]
|
||||
{:label (:name account)
|
||||
:id (:address account)})]
|
||||
[react/scroll-view
|
||||
{:horizontal true
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:scroll-event-throttle 64
|
||||
:margin-top 12
|
||||
:margin-bottom 20}
|
||||
[react/view {:flex-direction :row}
|
||||
[quo/tabs
|
||||
{:default-active (:address (first visible-accounts))
|
||||
:on-change #(reset! selected-account-atom %)
|
||||
:data accounts-data}]
|
||||
[quo/button
|
||||
{:type :grey
|
||||
:size 32
|
||||
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content sheets/add-account
|
||||
:content-height 260}])}
|
||||
"Add account"]]]))))
|
||||
|
||||
(defn accounts-overview
|
||||
[]
|
||||
(let [mnemonic @(re-frame/subscribe [:mnemonic])
|
||||
selected-account-atom (reagent/atom nil)]
|
||||
(fn []
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:padding-top (safe-area/get-top)
|
||||
:background-color (quo.colors/theme-colors quo.colors/neutral-5
|
||||
quo.colors/neutral-95)}}
|
||||
[react/view {:padding-horizontal 20}
|
||||
[react/view {:flex-direction :row :height 56 :align-items :center :justify-content :flex-end}
|
||||
[quo/button
|
||||
{:icon true
|
||||
:size 32
|
||||
:type :grey
|
||||
:accessibility-label :accounts-qr-code
|
||||
:on-press #(re-frame/dispatch
|
||||
[::qr-scanner/scan-code
|
||||
{:handler :wallet-legacy.send/qr-scanner-result}])}
|
||||
:i/placeholder]
|
||||
[react/view {:width 12}]
|
||||
[quo/button
|
||||
{:icon true
|
||||
:size 32
|
||||
:type :grey
|
||||
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content (sheets/accounts-options mnemonic)}])
|
||||
:accessibility-label :accounts-more-options}
|
||||
:i/placeholder]]
|
||||
[total-value]
|
||||
[accounts selected-account-atom]]
|
||||
[account.views/account-new @selected-account-atom]])))
|
||||
|
||||
(defn accounts-overview-old
|
||||
[]
|
||||
(let [mnemonic @(re-frame/subscribe [:mnemonic])
|
||||
mainnet? @(re-frame/subscribe [:mainnet?])]
|
||||
[react/view
|
||||
{:style {:flex 1}}
|
||||
[components.core/animated-header
|
||||
{:extended-header total-value-old
|
||||
:refresh-control common/refresh-control
|
||||
:refreshing-sub (re-frame/subscribe [:wallet-legacy/refreshing-history?])
|
||||
:refreshing-counter common/updates-counter
|
||||
:use-insets true
|
||||
:right-accessories [{:on-press #(re-frame/dispatch
|
||||
[::qr-scanner/scan-code
|
||||
{:handler :wallet-legacy.send/qr-scanner-result}])
|
||||
:icon :main-icons/qr
|
||||
:accessibility-label :accounts-qr-code}
|
||||
{:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content (sheets/accounts-options
|
||||
mnemonic)}])
|
||||
:icon :main-icons/more
|
||||
:accessibility-label :accounts-more-options}]}
|
||||
[accounts-old]
|
||||
(when mainnet?
|
||||
[buy-crypto/banner])
|
||||
[assets]
|
||||
[react/view {:height 68}]]
|
||||
[send-button]]))
|
|
@ -1,38 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.accounts-manage.views
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.list.views :as list]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[reagent.core :as reagent]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn render-account
|
||||
[_]
|
||||
(reagent/create-class
|
||||
{:should-component-update
|
||||
(fn [_ [_ old-item] [_ new-item]]
|
||||
(not= (:hidden old-item) (:hidden new-item)))
|
||||
:reagent-render
|
||||
(fn [{:keys [hidden name address wallet] :as account}]
|
||||
[list.item/list-item
|
||||
{:accessory [icons/icon
|
||||
(if hidden :main-icos/hide :main-icos/show)
|
||||
(merge {:accessibility-label (if hidden :hide-icon :show-icon)}
|
||||
(when wallet {:color colors/gray}))]
|
||||
:animated-accessory? false
|
||||
:animated false
|
||||
:disabled wallet
|
||||
:title name
|
||||
:subtitle (utils/get-shortened-checksum-address address)
|
||||
:on-press #(rf/dispatch [:wallet-legacy.accounts/save-account account
|
||||
{:hidden (not hidden)}])}])}))
|
||||
|
||||
(defn manage
|
||||
[]
|
||||
(let [accounts (rf/sub [:profile/wallet-accounts])]
|
||||
[list/flat-list
|
||||
{:key-fn :address
|
||||
:data accounts
|
||||
:render-fn render-account}]))
|
|
@ -1,173 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.add-new.views
|
||||
(:require-macros [legacy.status-im.utils.views :refer [defview letsubs]])
|
||||
(:require
|
||||
[cljs.spec.alpha :as spec]
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.multiaccounts.db :as multiaccounts.db]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.account-settings.views :as account-settings]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn add-account-topbar
|
||||
[type]
|
||||
(let [title (case type
|
||||
:generate :t/generate-an-account
|
||||
:watch :t/add-watch-account
|
||||
:seed :t/add-seed-account
|
||||
:key :t/add-private-key-account
|
||||
"")]
|
||||
[topbar/topbar
|
||||
(merge {:title (i18n/label title)}
|
||||
(when (= type :watch)
|
||||
{:right-accessories
|
||||
[{:icon :qr
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.add-new/qr-scanner
|
||||
{:handler
|
||||
:wallet-legacy.add-new/qr-scanner-result}])}]}))]))
|
||||
|
||||
(defn common-settings
|
||||
[account]
|
||||
[react/view {:margin-horizontal 16}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/account-name)
|
||||
:auto-focus false
|
||||
:default-value (:name account)
|
||||
:accessibility-label :enter-account-name
|
||||
:placeholder (i18n/label :t/account-name)
|
||||
:on-change-text #(re-frame/dispatch [:set-in [:add-account :account :name] %])}]
|
||||
[react/text {:style {:margin-top 30}} (i18n/label :t/account-color)]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch
|
||||
[:show-popover
|
||||
{:view [account-settings/colors-popover (:color account)
|
||||
(fn [new-color]
|
||||
(re-frame/dispatch [:set-in [:add-account :account :color] new-color])
|
||||
(re-frame/dispatch [:hide-popover]))]
|
||||
:style {:max-height "60%"}}])}
|
||||
[react/view
|
||||
{:height 52
|
||||
:margin-top 12
|
||||
:background-color (:color account)
|
||||
:border-radius 8
|
||||
:align-items :flex-end
|
||||
:justify-content :center
|
||||
:padding-right 12}
|
||||
[icons/icon :main-icons/dropdown {:color colors/white}]]]])
|
||||
|
||||
(defn settings
|
||||
[{:keys [type scanned-address password-error account-error]}
|
||||
entered-password]
|
||||
[react/view
|
||||
{:padding-horizontal 16
|
||||
:padding-vertical 16}
|
||||
(if (= type :watch)
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/wallet-key-title)
|
||||
:auto-focus false
|
||||
:default-value scanned-address
|
||||
:monospace true
|
||||
:placeholder (i18n/label :t/enter-address)
|
||||
:accessibility-label :add-account-enter-watch-address
|
||||
:on-change-text #(re-frame/dispatch [:wallet-legacy.accounts/set-account-to-watch %])}]
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/password)
|
||||
:show-cancel false
|
||||
:auto-focus false
|
||||
:placeholder (i18n/label :t/enter-your-password)
|
||||
:secure-text-entry true
|
||||
:text-content-type :none
|
||||
:accessibility-label :add-account-enter-password
|
||||
:bottom-value 0
|
||||
:error (when password-error (i18n/label :t/add-account-incorrect-password))
|
||||
:on-change-text #(do
|
||||
(re-frame/dispatch [:set-in [:add-account :password-error] nil])
|
||||
(reset! entered-password %))}])
|
||||
(when (= type :seed)
|
||||
[react/view {:padding-top 16}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/recovery-phrase)
|
||||
:auto-focus false
|
||||
:placeholder (i18n/label :t/multiaccounts-recover-enter-phrase-title)
|
||||
:auto-correct false
|
||||
:keyboard-type :visible-password
|
||||
:multiline true
|
||||
:height 95
|
||||
:error account-error
|
||||
:accessibility-label :add-account-enter-seed
|
||||
:monospace true
|
||||
:on-change-text
|
||||
#(do
|
||||
(re-frame/dispatch [:set-in [:add-account :account-error] nil])
|
||||
(re-frame/dispatch [:set-in [:add-account :seed]
|
||||
(security/mask-data (string/lower-case %))]))}]])
|
||||
(when (= type :key)
|
||||
[react/view {:margin-top 30}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/private-key)
|
||||
:auto-focus false
|
||||
:placeholder (i18n/label :t/enter-a-private-key)
|
||||
:auto-correct false
|
||||
:keyboard-type :visible-password
|
||||
:error account-error
|
||||
:secure-text-entry true
|
||||
:accessibility-label :add-account-enter-private-key
|
||||
:text-content-type :none
|
||||
:on-change-text
|
||||
#(do
|
||||
(re-frame/dispatch [:set-in [:add-account :account-error] nil])
|
||||
(re-frame/dispatch [:set-in [:add-account :private-key] (security/mask-data %)]))}]])])
|
||||
|
||||
(defn pin
|
||||
[]
|
||||
[react/view])
|
||||
|
||||
(defview add-account-view
|
||||
[]
|
||||
(letsubs [{:keys [type account] :as add-account} [:add-account]
|
||||
add-account-disabled? [:add-account-disabled?]
|
||||
entered-password (reagent/atom "")
|
||||
keycard? [:keycard-multiaccount?]]
|
||||
[react/keyboard-avoiding-view
|
||||
{:style {:flex 1}
|
||||
:ignore-offset true}
|
||||
[add-account-topbar type]
|
||||
[react/scroll-view
|
||||
{:keyboard-should-persist-taps :handled
|
||||
:style {:flex 1 :padding-top 20}}
|
||||
(when (or (not keycard?)
|
||||
(= type :watch))
|
||||
[settings add-account entered-password])
|
||||
[common-settings account]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:after :main-icon/next
|
||||
:accessibility-label :add-account-add-account-button
|
||||
:on-press
|
||||
(if (and keycard?
|
||||
(not= type :watch))
|
||||
#(re-frame/dispatch [:keycard/new-account-pin-sheet
|
||||
{:view {:content pin
|
||||
:height 256}}])
|
||||
#(re-frame/dispatch [:wallet-legacy.accounts/add-new-account
|
||||
(native-module/sha3 @entered-password)]))
|
||||
:disabled
|
||||
(or add-account-disabled?
|
||||
(and
|
||||
(not (= type :watch))
|
||||
(and
|
||||
(not keycard?)
|
||||
(not (spec/valid? ::multiaccounts.db/password
|
||||
@entered-password)))))}
|
||||
(i18n/label :t/add-account)]}]]))
|
|
@ -1,34 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.buy-crypto.sheets
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]))
|
||||
|
||||
;; This needs to be a function because `colors/x` is a mutable reference
|
||||
;; and changes dynamically based on the appearance settings
|
||||
(defn banner-container
|
||||
[]
|
||||
{:margin-horizontal 16
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:flex 1
|
||||
:margin-top 16
|
||||
:border-radius 16
|
||||
:margin-bottom 8
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 5
|
||||
:background-color colors/blue-light})
|
||||
|
||||
(defn highlight-container
|
||||
[]
|
||||
{:padding 4
|
||||
:justify-content :center
|
||||
:border-radius 4
|
||||
:background-color colors/blue})
|
||||
|
||||
(def highlight-text
|
||||
{:text-transform :uppercase
|
||||
:color "#FFFFFF"})
|
||||
|
||||
(def icon
|
||||
{:width 68
|
||||
:height 36})
|
|
@ -1,167 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.buy-crypto.views
|
||||
(:require
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.list.views :as list]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.components.webview :as components.webview]
|
||||
[legacy.status-im.ui.screens.browser.views :as browser.views]
|
||||
[legacy.status-im.ui.screens.chat.photos :as photos]
|
||||
[legacy.status-im.ui.screens.wallet.buy-crypto.sheets :as sheets]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [legacy.status-im.utils.views :as views]))
|
||||
|
||||
(def learn-more-url "")
|
||||
|
||||
(def webview-ref (atom nil))
|
||||
|
||||
(defn on-buy-crypto-pressed
|
||||
[]
|
||||
(re-frame/dispatch [:buy-crypto.ui/open-screen]))
|
||||
|
||||
(defn render-on-ramp
|
||||
[{:keys [name fees logo-url description] :as on-ramp}]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:open-modal :buy-crypto-website on-ramp])
|
||||
:style {:flex 1}}
|
||||
[list.item/list-item
|
||||
{:title [react/view {:style {:flex 1}}
|
||||
[quo/text
|
||||
{:size :large
|
||||
:weight :bold}
|
||||
name]
|
||||
[quo/text {} description]]
|
||||
:subtitle [react/view {:style {:flex 1}}
|
||||
[quo/text
|
||||
{:size :small
|
||||
:color :secondary} fees]]
|
||||
:icon [photos/photo logo-url {:size 40}]
|
||||
:left-side-alignment :flex-start
|
||||
:accessory :text}]])
|
||||
|
||||
(defn buy-crypto-header
|
||||
[]
|
||||
[react/view
|
||||
{:padding-bottom 16
|
||||
:align-items :center}
|
||||
[react/view
|
||||
{:padding-top 16
|
||||
:padding-bottom 8}
|
||||
[quo/text
|
||||
{:weight :bold
|
||||
:size :x-large}
|
||||
(i18n/label :t/buy-crypto)]]
|
||||
[quo/text {:color :secondary}
|
||||
(i18n/label :t/buy-crypto-choose-a-service)]
|
||||
(when (seq learn-more-url)
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/open-url learn-more-url])}
|
||||
[react/view {:padding-vertical 11}
|
||||
[quo/text {:color :link} (i18n/label :t/learn-more)]]])])
|
||||
|
||||
(views/defview buy-crypto
|
||||
[]
|
||||
(views/letsubs [on-ramps [:buy-crypto/on-ramps]]
|
||||
[list/flat-list
|
||||
{:data on-ramps
|
||||
:key-fn :site-url
|
||||
:header [buy-crypto-header]
|
||||
:render-fn render-on-ramp}]))
|
||||
|
||||
(defn website
|
||||
[]
|
||||
(let [has-loaded? (reagent/atom false)
|
||||
initialized? (reagent/atom false)
|
||||
{:keys [name
|
||||
hostname
|
||||
logo-url
|
||||
site-url]}
|
||||
@(re-frame/subscribe [:get-screen-params])]
|
||||
;;it crashes on android , probably because of modal animation
|
||||
(js/setTimeout #(reset! initialized? true) 500)
|
||||
(fn []
|
||||
;; overflow hidden needed for the crash on android
|
||||
[react/view {:flex 1 :overflow :hidden}
|
||||
[topbar/topbar
|
||||
{:content [react/view
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
[quo/text
|
||||
{:weight :semi-bold}
|
||||
(i18n/label :t/buy-crypto)]
|
||||
[quo/text {:color :secondary}
|
||||
hostname]]
|
||||
:modal? true}]
|
||||
(when-not @has-loaded?
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:position :absolute
|
||||
:top 56
|
||||
:left 0
|
||||
:right 0
|
||||
:z-index 1
|
||||
:background-color "#ffffff"
|
||||
:bottom 0
|
||||
:align-items :center
|
||||
:justify-content :center}}
|
||||
[photos/photo logo-url {:size 40}]
|
||||
[quo/text
|
||||
{:size :x-large}
|
||||
(i18n/label :t/opening-buy-crypto {:site name})]
|
||||
[react/view {:style {:padding-horizontal 32}}
|
||||
[quo/text
|
||||
{:align :center
|
||||
:color :secondary}
|
||||
(i18n/label :t/buy-crypto-leaving)]]])
|
||||
(when @initialized?
|
||||
[components.webview/webview
|
||||
{:onLoadEnd #(reset! has-loaded? true)
|
||||
:ref #(reset! webview-ref %)
|
||||
:on-permission-request #(browser.views/request-resources-access-for-page
|
||||
(-> ^js % .-nativeEvent .-resources)
|
||||
site-url
|
||||
@webview-ref)
|
||||
:java-script-enabled true
|
||||
;; This is to avoid crashes on android devices due to
|
||||
;; https://github.com/react-native-webview/react-native-webview/issues/1838
|
||||
;; We can't disable hardware acceleration as we need to use camera
|
||||
:style {:opacity 0.99}
|
||||
:local-storage-enabled true
|
||||
:source {:uri site-url}}])])))
|
||||
|
||||
(defn container
|
||||
[]
|
||||
(reagent/create-class
|
||||
{:component-did-mount #(re-frame/dispatch [:buy-crypto.ui/loaded])
|
||||
:reagent-render buy-crypto}))
|
||||
|
||||
(defn banner
|
||||
[]
|
||||
(fn []
|
||||
[react/touchable-highlight {:on-press on-buy-crypto-pressed}
|
||||
[react/view {:style (sheets/banner-container)}
|
||||
[react/view {:flex-direction :row}
|
||||
[react/view {:style (sheets/highlight-container)}
|
||||
[quo/text
|
||||
{:weight :bold
|
||||
:size :tiny
|
||||
:style sheets/highlight-text}
|
||||
(i18n/label :t/new)]]
|
||||
[react/view
|
||||
{:style {:justify-content :center
|
||||
:align-items :center
|
||||
:padding-left 8}}
|
||||
[quo/text
|
||||
{:size :large
|
||||
:weight :medium
|
||||
:color :link} (i18n/label :t/buy-crypto)]]]
|
||||
[react/view
|
||||
{:style {:align-content :flex-end
|
||||
:align-self :flex-end}}
|
||||
[react/image
|
||||
{:source (icons/icon-source :buy-crypto)
|
||||
:style sheets/icon}]]]]))
|
|
@ -1,314 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.collectibles.views
|
||||
(:require
|
||||
["react-native-svg" :refer (SvgUri)]
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[legacy.status-im.react-native.resources :as resources]
|
||||
[legacy.status-im.ui.components.accordion :as accordion]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.toastable-highlight :refer [toastable-highlight-view]]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as wallet.components]
|
||||
[legacy.status-im.wallet.core :as wallet-legacy]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def svg-uri (reagent/adapt-react-class SvgUri))
|
||||
|
||||
(defn is-image?
|
||||
[nft]
|
||||
(and (seq (:image_url nft))
|
||||
(not (string/ends-with? (:image_url nft) ".svg"))
|
||||
(not (string/ends-with? (:image_url nft) ".mp4"))))
|
||||
|
||||
(defn is-vector?
|
||||
[nft]
|
||||
(and (seq (:image_url nft))
|
||||
(string/ends-with? (:image_url nft) ".svg")))
|
||||
|
||||
(defn missing-image-placeholder
|
||||
[]
|
||||
[react/view
|
||||
{:style {:width "100%"
|
||||
:flex 1
|
||||
:align-items :center
|
||||
:border-radius 16
|
||||
:background-color colors/gray-lighter
|
||||
:justify-content :center
|
||||
:aspect-ratio 1}}
|
||||
[icons/icon :photo {:color colors/gray}]])
|
||||
|
||||
(defn nft-assets-skeleton
|
||||
[num-assets]
|
||||
[:<>
|
||||
(for [i (range num-assets)]
|
||||
^{:key i}
|
||||
[react/view
|
||||
{:style {:width "48%"
|
||||
:margin-bottom 16}}
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:aspect-ratio 1
|
||||
:border-width 1
|
||||
:background-color colors/gray-transparent-10
|
||||
:border-color colors/gray-lighter
|
||||
:border-radius 16}}]])])
|
||||
|
||||
(defn nft-trait-card
|
||||
[trait]
|
||||
[react/view
|
||||
{:style {:border-width 1
|
||||
:border-radius 12
|
||||
:margin-right 8
|
||||
:padding-vertical 4
|
||||
:padding-horizontal 8
|
||||
:border-color colors/gray-lighter}}
|
||||
[quo/text
|
||||
{:size :small
|
||||
:color :secondary}
|
||||
(:trait_type trait)]
|
||||
[quo/text {}
|
||||
(:value trait)]])
|
||||
|
||||
(defn nft-traits-scroller
|
||||
[traits]
|
||||
[react/scroll-view
|
||||
{:horizontal true
|
||||
:deceleration-rate "fast"
|
||||
:snap-to-alignment "start"
|
||||
:shows-horizontal-scroll-indicator
|
||||
false
|
||||
:scroll-event-throttle 64
|
||||
:style {:padding-left 16
|
||||
:margin-vertical 16
|
||||
:padding-bottom 8}}
|
||||
(for [trait traits]
|
||||
^{:key (:trait_type trait)}
|
||||
[nft-trait-card trait])
|
||||
|
||||
;; spacer
|
||||
[react/view
|
||||
{:style {:height 40
|
||||
:width 40}}]])
|
||||
|
||||
(defn no-assets-error
|
||||
[]
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:justify-content :center
|
||||
:padding 16
|
||||
:margin-vertical 16
|
||||
:align-items :center
|
||||
:border-radius 16}}
|
||||
[icons/icon :photo {:color colors/red}]
|
||||
[quo/text
|
||||
{:color :secondary
|
||||
:style {:magin-top 8}}
|
||||
(i18n/label :t/no-collectibles)]])
|
||||
|
||||
(defn render-asset
|
||||
[{:keys [asset width clickable?]}]
|
||||
[(if clickable? react/touchable-opacity react/view)
|
||||
{:style
|
||||
{:width width
|
||||
:border-radius 16
|
||||
:margin-bottom 16}
|
||||
:on-press (when clickable? #(re-frame/dispatch [::wallet-legacy/show-nft-details asset]))
|
||||
:accessibility-label
|
||||
:nft-asset}
|
||||
(cond
|
||||
;; pngs and jpegs
|
||||
(is-image? asset)
|
||||
[react/image
|
||||
{:style {:flex 1
|
||||
:aspect-ratio 1
|
||||
:border-width 1
|
||||
:border-color colors/gray-lighter
|
||||
:border-radius 16}
|
||||
:source {:uri (:image_url asset)}}]
|
||||
|
||||
;; vectors
|
||||
(is-vector? asset)
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:aspect-ratio 1
|
||||
:border-width 1
|
||||
:border-color colors/gray-lighter
|
||||
:border-radius 16}}
|
||||
[svg-uri
|
||||
{:uri (:image_url asset)
|
||||
:width "100%"
|
||||
:height "100%"}]]
|
||||
|
||||
;; ¯\_(ツ)_/¯
|
||||
:else [missing-image-placeholder])])
|
||||
|
||||
(defn nft-assets
|
||||
[{:keys [num-assets address collectible-slug]}]
|
||||
(let [assets (rf/sub [:wallet-legacy/collectible-assets-by-collection-and-address address
|
||||
collectible-slug])
|
||||
fetching? (rf/sub [:wallet-legacy/fetching-assets-by-collectible-slug collectible-slug])]
|
||||
[react/view
|
||||
{:flex 1
|
||||
:flex-wrap :wrap
|
||||
:justify-content :space-between
|
||||
:flex-direction :row
|
||||
:style {:padding-horizontal 16}}
|
||||
(cond
|
||||
fetching? [nft-assets-skeleton num-assets]
|
||||
|
||||
;; <shivekkhurana> OpenSea sometimes doesn't return an asset. This condition handles it
|
||||
(and (not fetching?)
|
||||
(not (seq assets)))
|
||||
[no-assets-error]
|
||||
|
||||
(seq assets)
|
||||
(for [asset assets]
|
||||
^{:key (:id asset)}
|
||||
[render-asset
|
||||
{:asset asset
|
||||
:clickable? true
|
||||
:width "48%"}]))]))
|
||||
|
||||
(defn nft-collections
|
||||
[address]
|
||||
(let [collection (rf/sub [:wallet-legacy/collectible-collection address])]
|
||||
[:<>
|
||||
(for [[index collectible] (map-indexed vector collection)]
|
||||
^{:key (:slug collectible)}
|
||||
[accordion/section
|
||||
{:title
|
||||
[react/view {:flex 1}
|
||||
[list.item/list-item
|
||||
{:title (:name collectible)
|
||||
:text-size :large
|
||||
:accessibility-label
|
||||
(keyword (str "collection-" index))
|
||||
:icon (if (seq (:image_url collectible))
|
||||
[wallet.components/token-icon
|
||||
{:style {:border-radius 40
|
||||
:overflow :hidden
|
||||
:border-width 1
|
||||
:border-color colors/gray-lighter}
|
||||
:source {:uri (:image_url collectible)}}]
|
||||
:main-icons/photo)
|
||||
:accessory :text
|
||||
:accessory-text (:owned_asset_count collectible)}]]
|
||||
:padding-vertical 0
|
||||
:dropdown-margin-left -12
|
||||
:open-container-style {:border-top-width 8
|
||||
:border-bottom-width 8
|
||||
:border-color colors/gray-lighter}
|
||||
:on-open #(re-frame/dispatch
|
||||
[::wallet-legacy/fetch-collectible-assets-by-owner-and-collection
|
||||
address
|
||||
(:slug collectible)
|
||||
(:owned_asset_count collectible)])
|
||||
:content [nft-assets
|
||||
{:address address
|
||||
:num-assets (:owned_asset_count collectible)
|
||||
:collectible-slug (:slug collectible)}]}])]))
|
||||
|
||||
(defn enable-opensea-view
|
||||
[]
|
||||
[react/view {:style {:padding 16}}
|
||||
[react/view
|
||||
{:style {:border-color colors/gray-lighter
|
||||
:border-width 1
|
||||
:align-self :center
|
||||
:padding 4
|
||||
:border-radius 12}}
|
||||
[react/image
|
||||
{:source (resources/get-theme-image :collectible)
|
||||
:style {:align-self :center
|
||||
:resize-mode :contain}}]]
|
||||
[quo/text
|
||||
{:align :center
|
||||
:style {:margin-vertical 16}}
|
||||
(i18n/label :t/collectibles-leak-metadata)]
|
||||
[react/view {:align-items :center}
|
||||
[quo/button
|
||||
{:accessibility-label :enable-opensea-nft-visibility
|
||||
:on-press
|
||||
#(re-frame/dispatch
|
||||
[::multiaccounts.update/toggle-opensea-nfts-visiblity true])
|
||||
:theme :main
|
||||
:type :primary}
|
||||
(i18n/label :t/display-collectibles)]]
|
||||
[quo/text
|
||||
{:size :small
|
||||
:color :secondary
|
||||
:align :center
|
||||
:style {:margin-top 10}}
|
||||
(i18n/label :t/disable-later-in-settings)]])
|
||||
|
||||
(defn nft-details-modal
|
||||
[]
|
||||
(let [nft (rf/sub [:wallet-legacy/selected-collectible])]
|
||||
[react/scroll-view
|
||||
[topbar/topbar
|
||||
{:navigation {:icon :main-icons/close}
|
||||
:border-bottom false}]
|
||||
[react/view {:padding-horizontal 16}
|
||||
[quo/text
|
||||
{:size :large
|
||||
:weight :bold}
|
||||
(:name nft)]
|
||||
[quo/text
|
||||
{:size :small
|
||||
:color :secondary
|
||||
:style {:margin-top 4}}
|
||||
(-> nft :collection :name)]
|
||||
|
||||
[render-asset
|
||||
{:asset nft
|
||||
:clickable? false
|
||||
:width "100%"}]
|
||||
|
||||
[quo/text {:style {:margin-top 12}}
|
||||
(:description nft)]]
|
||||
|
||||
(when (seq (:traits nft))
|
||||
[nft-traits-scroller (:traits nft)])
|
||||
|
||||
;; seperator
|
||||
[react/view
|
||||
{:style {:border-bottom-width 1
|
||||
:padding-top 8
|
||||
:border-color colors/gray-lighter}}]
|
||||
|
||||
;; TODO <shivekkhurana>: Enable txns
|
||||
;; [list/list-item {:title (i18n/label :t/wallet-send)
|
||||
;; :icon :main-icons/send :accessibility-label :nft-send :theme :accent
|
||||
;; :on-press #()}]
|
||||
|
||||
;; TODO <shivekkhurana>: What to do with share? Share links or share image?
|
||||
;; [list/list-item {:title (i18n/label :t/share)
|
||||
;; :theme :accent
|
||||
;; :accessibility-label
|
||||
;; :nft-share
|
||||
;; :on-press #()
|
||||
;; :icon :main-icons/share}]
|
||||
[list.item/list-item
|
||||
{:title (i18n/label :t/view-on-opensea)
|
||||
:theme :accent
|
||||
:icon :main-icons/browser
|
||||
:on-press #(re-frame/dispatch [:browser.ui/open-url (:permalink nft)])}]
|
||||
(when (is-image? nft)
|
||||
[toastable-highlight-view
|
||||
;; the last string is an emoji. It might not show up in all editors but its there
|
||||
{:toast-label (str (i18n/label :t/profile-picture-updated)) " " "😎"}
|
||||
[list.item/list-item
|
||||
{:title (i18n/label :t/use-as-profile-picture)
|
||||
:theme :accent
|
||||
:on-press #(re-frame/dispatch [:profile.settings/save-profile-picture-from-url
|
||||
(:image_url nft)])
|
||||
:icon :main-icons/profile
|
||||
:accessibility-label
|
||||
:set-nft-as-pfp}]])]))
|
|
@ -1,13 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.components.styles
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn separator
|
||||
[]
|
||||
{:height 1
|
||||
:background-color colors/gray-lighter})
|
||||
|
||||
(defn separator-dark
|
||||
[]
|
||||
{:height 1
|
||||
:background-color colors/black-transparent})
|
|
@ -1,22 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.components.views
|
||||
(:require
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.screens.wallet.components.styles :as styles]))
|
||||
|
||||
(defn separator
|
||||
[]
|
||||
[react/view (styles/separator)])
|
||||
|
||||
(defn separator-dark
|
||||
[]
|
||||
[react/view (styles/separator-dark)])
|
||||
|
||||
(defn token-icon
|
||||
[{:keys [style source image-style width height]}]
|
||||
[react/view {:style style}
|
||||
[react/image
|
||||
{:source (if (fn? source) (source) source)
|
||||
:style (merge
|
||||
{:width (or width 40)
|
||||
:height (or height 40)}
|
||||
image-style)}]])
|
|
@ -1,171 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.custom-tokens.views
|
||||
(:require-macros [legacy.status-im.utils.views :refer [defview letsubs]])
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def debounce-timers (atom {}))
|
||||
|
||||
(defn debounce-and-save
|
||||
[field-key value]
|
||||
(let [timeout (get @debounce-timers field-key)]
|
||||
(when timeout (js/clearTimeout timeout))
|
||||
(swap! debounce-timers assoc
|
||||
field-key
|
||||
(js/setTimeout
|
||||
#(re-frame/dispatch [:wallet-legacy.custom-token.ui/field-is-edited field-key
|
||||
(string/trim value)])
|
||||
500))))
|
||||
|
||||
(defview add-custom-token
|
||||
[]
|
||||
(letsubs [{:keys [contract name decimals in-progress? error error-name error-symbol]
|
||||
:as m}
|
||||
[:wallet-legacy/custom-token-screen]]
|
||||
(let [sym (:symbol m)]
|
||||
[react/keyboard-avoiding-view {:flex 1 :background-color colors/white}
|
||||
[react/scroll-view
|
||||
{:keyboard-should-persist-taps :handled
|
||||
:style {:flex 1
|
||||
:padding-horizontal 16}}
|
||||
[react/view {:padding-vertical 8}
|
||||
[react/view
|
||||
{:style {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-vertical 10}}
|
||||
[react/text (i18n/label :t/contract-address)]
|
||||
(when in-progress?
|
||||
[react/view {:flex-direction :row :justify-content :center}
|
||||
[react/view {:height 20}
|
||||
[react/activity-indicator {:width 24 :height 24 :animating true}]]
|
||||
[react/text {:style {:color colors/gray :margin-left 5}}
|
||||
(i18n/label :t/processing)]])]
|
||||
(when-not in-progress?
|
||||
;;tooltip covers button
|
||||
[react/view {:position :absolute :z-index 1000 :right 0 :top 10}
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:wallet-legacy.custom-token.ui/contract-address-paste])}
|
||||
[react/text {:style {:color colors/blue}}
|
||||
(i18n/label :t/paste)]]])
|
||||
[quo/text-input
|
||||
{:on-change-text #(debounce-and-save :contract %)
|
||||
:error error
|
||||
:default-value contract
|
||||
:monospace true
|
||||
:multiline true
|
||||
:height 78
|
||||
:auto-focus false
|
||||
:placeholder (i18n/label :t/specify-address)}]]
|
||||
[react/view {:padding-vertical 8}
|
||||
[quo/text-input
|
||||
{:on-change-text #(debounce-and-save :name %)
|
||||
:label (i18n/label :t/name)
|
||||
:default-value name
|
||||
:error error-name
|
||||
:auto-focus false
|
||||
:placeholder (i18n/label :t/name-of-token)}]]
|
||||
[react/view {:padding-vertical 8}
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[react/view
|
||||
{:flex 1
|
||||
:padding-right 8}
|
||||
[quo/text-input
|
||||
{:on-change-text #(debounce-and-save :symbol %)
|
||||
:label (i18n/label :t/symbol)
|
||||
:error error-symbol
|
||||
:default-value sym
|
||||
:auto-focus false
|
||||
:show-cancel false
|
||||
:placeholder "ABC"}]]
|
||||
[react/view
|
||||
{:flex 1
|
||||
:padding-left 8}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/decimals)
|
||||
:on-change-text #(debounce-and-save :decimals %)
|
||||
:default-value decimals
|
||||
:keyboard-type :number-pad
|
||||
:max-length 2
|
||||
:auto-focus false
|
||||
:show-cancel false
|
||||
:placeholder "18"}]]]]
|
||||
#_[quo/text-input
|
||||
{:label (i18n/label :t/balance)
|
||||
:default-value (when (and balance decimals)
|
||||
(wallet.utils/format-amount balance decimals))
|
||||
:editable false
|
||||
:placeholder (i18n/label :t/no-tokens-found)}]]
|
||||
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:after :main-icon/next
|
||||
:disabled (boolean
|
||||
(or in-progress?
|
||||
error
|
||||
error-name
|
||||
error-symbol
|
||||
(string/blank? contract)
|
||||
(string/blank? name)
|
||||
(string/blank? sym)
|
||||
(string/blank? decimals)))
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.custom-token.ui/add-pressed])}
|
||||
(i18n/label :t/add)]}]])))
|
||||
|
||||
(defview custom-token-details
|
||||
[]
|
||||
(letsubs [{:keys [address name decimals custom?] :as token}
|
||||
[:get-screen-params]]
|
||||
[react/keyboard-avoiding-view
|
||||
{:style {:flex 1}
|
||||
:ignore-offset true}
|
||||
[topbar/topbar {:title name}]
|
||||
[react/scroll-view
|
||||
{:keyboard-should-persist-taps :handled
|
||||
:style {:flex 1}}
|
||||
[react/view {:padding-horizontal 16}
|
||||
[react/view {:padding-vertical 8}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/contract-address)
|
||||
:default-value address
|
||||
:multiline true
|
||||
:height 78
|
||||
:editable false}]]
|
||||
[react/view {:padding-vertical 8}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/name)
|
||||
:default-value name
|
||||
:editable false}]]
|
||||
[react/view {:padding-vertical 8}
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[react/view
|
||||
{:flex 1
|
||||
:padding-right 8}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/symbol)
|
||||
:editable false
|
||||
:show-cancel false
|
||||
:default-value (:symbol token)}]]
|
||||
[react/view {:flex 1 :padding-left 8}
|
||||
[quo/text-input
|
||||
{:label (i18n/label :t/decimals)
|
||||
:show-cancel false
|
||||
:default-value (str decimals)
|
||||
:editable false}]]]]]
|
||||
[react/view {:height 24}]
|
||||
(when custom?
|
||||
[list.item/list-item
|
||||
{:theme :negative
|
||||
:title (i18n/label :t/remove-token)
|
||||
:icon :main-icons/delete
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.custom-token.ui/remove-pressed token
|
||||
true])}])]]))
|
|
@ -1,350 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.recipient.views
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.search-input.view :as search-input]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as components]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.address :as address]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.ens.stateofus :as stateofus]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.string :as utils.string])
|
||||
(:require-macros [legacy.status-im.utils.views :as views]))
|
||||
|
||||
(defn- recipient-topbar
|
||||
[]
|
||||
[topbar/topbar
|
||||
{:navigation {:on-press
|
||||
#(do
|
||||
(re-frame/dispatch [:wallet-legacy/recipient-modal-closed])
|
||||
(re-frame/dispatch [:wallet-legacy/search-recipient-filter-changed nil])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
:modal? true
|
||||
:border-bottom false
|
||||
:title (i18n/label :t/recipient)
|
||||
:right-accessories
|
||||
[{:icon :qr
|
||||
:accessibility-label :scan-contact-code-button
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.send/qr-scanner
|
||||
{:ignore-url true
|
||||
:handler :wallet-legacy.send/qr-scanner-result}])}]}])
|
||||
|
||||
(defonce search-active? (reagent/atom false))
|
||||
|
||||
(defn search-input-wrapper
|
||||
[]
|
||||
(let [search-filter @(re-frame/subscribe [:wallet-legacy/search-recipient-filter])]
|
||||
[react/view
|
||||
{:padding-horizontal 16
|
||||
:padding-vertical 10}
|
||||
[search-input/search-input-old
|
||||
{:search-active? search-active?
|
||||
:search-filter search-filter
|
||||
:on-cancel #(re-frame/dispatch [:wallet-legacy/search-recipient-filter-changed nil])
|
||||
:on-change (fn [text]
|
||||
(re-frame/dispatch [:wallet-legacy/search-recipient-filter-changed text])
|
||||
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
|
||||
(debounce/debounce-and-dispatch [:contacts/set-new-identity {:input text}]
|
||||
300))}]]))
|
||||
|
||||
(defn section
|
||||
[_ _ _]
|
||||
(let [opened? (reagent/atom false)]
|
||||
(fn [title cnt content]
|
||||
[react/view {:padding-vertical 8}
|
||||
[list.item/list-item
|
||||
{:title title
|
||||
:on-press #(swap! opened? not)
|
||||
:accessory
|
||||
[react/view {:flex-direction :row :align-items :center}
|
||||
(when (pos? cnt)
|
||||
[react/text {:style {:color colors/gray}} cnt])
|
||||
[icons/icon (if @opened? :main-icons/dropdown :main-icons/next)
|
||||
{:container-style {:align-items :center
|
||||
:margin-left 8
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:color colors/black}]]}]
|
||||
(when @opened?
|
||||
content)])))
|
||||
|
||||
(defn render-account
|
||||
[account]
|
||||
[list.item/list-item
|
||||
{:icon [chat-icon/custom-icon-view-list (:name account) (:color account)]
|
||||
:title (:name account)
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.send/set-recipient (:address account)])
|
||||
:subtitle [quo/text
|
||||
{:monospace true
|
||||
:color :secondary}
|
||||
(utils/get-shortened-checksum-address (:address account))]}])
|
||||
|
||||
(def scroll-view-ref (atom nil))
|
||||
|
||||
(defn contacts-list-item
|
||||
[{:keys [name] :as contact}]
|
||||
[list.item/list-item
|
||||
{:title (:primary-name contact)
|
||||
:subtitle (:secondary-name contact)
|
||||
:on-press #(do
|
||||
(some-> ^js @scroll-view-ref
|
||||
(.scrollTo #js {:x 0 :animated true}))
|
||||
(re-frame/dispatch [:wallet-legacy.recipient/address-changed name]))
|
||||
:icon [chat-icon/contact-icon-contacts-tab contact]}])
|
||||
|
||||
(defn empty-items
|
||||
[icon title]
|
||||
[react/view {:height 94 :align-items :center :justify-content :center}
|
||||
[icons/icon icon
|
||||
{:color colors/gray}]
|
||||
[react/text {:style {:color colors/gray :margin-top 8}}
|
||||
title]])
|
||||
|
||||
(views/defview accounts-section
|
||||
[]
|
||||
(views/letsubs [accounts [:accounts-for-recipient]]
|
||||
(let [cnt (count accounts)]
|
||||
[section
|
||||
(i18n/label :t/my-accounts)
|
||||
cnt
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [account accounts]
|
||||
[render-account account])]
|
||||
[empty-items :main-icons/address (i18n/label :t/my-accounts-empty)])])))
|
||||
|
||||
(defn render-recent
|
||||
[{:keys [from to type amount-text currency-text]}]
|
||||
(let [inbound? (= type :inbound)
|
||||
address (if inbound? from to)]
|
||||
[list.item/list-item
|
||||
{:title [quo/text {:monospace true}
|
||||
(utils/get-shortened-checksum-address address)]
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.recipient/address-changed address])
|
||||
:size :small
|
||||
:accessory [react/text
|
||||
{:style {:flex-shrink 1
|
||||
:color colors/gray}}
|
||||
(str (if inbound? "↓ " "↑ ") amount-text " " currency-text)]}]))
|
||||
|
||||
(defn recent-section
|
||||
[]
|
||||
(let [{:keys [from]} @(re-frame/subscribe [:wallet-legacy/prepare-transaction])
|
||||
txs @(re-frame/subscribe [:wallet-legacy/recipient-recent-txs (:address from)])
|
||||
cnt (count txs)]
|
||||
[section
|
||||
(i18n/label :t/recent)
|
||||
cnt
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [tx txs]
|
||||
[render-recent tx])]
|
||||
[empty-items :main-icons/history (i18n/label :t/recent-empty)])]))
|
||||
|
||||
(defn render-fav
|
||||
[{:keys [address name]}]
|
||||
(let [noname? (string/blank? name)
|
||||
short-address (utils/get-shortened-checksum-address address)]
|
||||
[list.item/list-item
|
||||
{:icon [chat-icon/custom-icon-view-list
|
||||
(if noname? " 2" name)
|
||||
(rand-nth colors/chat-colors)]
|
||||
:title (if noname?
|
||||
[quo/text {:monospace true}
|
||||
short-address]
|
||||
name)
|
||||
:subtitle (when-not noname?
|
||||
[quo/text
|
||||
{:monospace true
|
||||
:color :secondary}
|
||||
short-address])
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.send/set-recipient address])
|
||||
:size (when noname? :small)}]))
|
||||
|
||||
(views/defview fav-section
|
||||
[]
|
||||
(views/letsubs [favourites [:wallet-legacy/favourites-filtered]]
|
||||
(let [cnt (count favourites)]
|
||||
[section
|
||||
(i18n/label :t/favourites)
|
||||
cnt
|
||||
[react/view
|
||||
;;TODO implement later
|
||||
#_[list/list-item
|
||||
{:title "Add favourite"
|
||||
:icon :main-icons/add
|
||||
:theme :accent}]
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [data favourites]
|
||||
[render-fav data])]
|
||||
[empty-items :main-icons/favourite (i18n/label :t/favourites-empty)])]])))
|
||||
|
||||
(views/defview contacts-section
|
||||
[]
|
||||
(views/letsubs [contacts [:contacts/active-with-ens-names]]
|
||||
(let [cnt (count contacts)]
|
||||
[section
|
||||
(i18n/label :t/contacts)
|
||||
cnt
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [contact contacts]
|
||||
[contacts-list-item contact])]
|
||||
[empty-items :main-icons/username (i18n/label :t/contacts-empty)])])))
|
||||
|
||||
(views/defview search-results
|
||||
[]
|
||||
(views/letsubs [contacts [:contacts/active-with-ens-names]
|
||||
favourites [:wallet-legacy/favourites-filtered]
|
||||
accounts [:accounts-for-recipient]]
|
||||
[react/view
|
||||
(for [account accounts]
|
||||
[render-account account])
|
||||
(for [data favourites]
|
||||
[render-fav data])
|
||||
(for [contact contacts]
|
||||
[contacts-list-item contact])]))
|
||||
|
||||
(defn accordion
|
||||
[search-filter]
|
||||
(if (not (string/blank? search-filter))
|
||||
[search-results]
|
||||
[react/view
|
||||
[components/separator]
|
||||
[accounts-section]
|
||||
[components/separator]
|
||||
[recent-section]
|
||||
[components/separator]
|
||||
[fav-section]
|
||||
[components/separator]
|
||||
[contacts-section]
|
||||
[components/separator]]))
|
||||
|
||||
(views/defview new-favourite
|
||||
[]
|
||||
(views/letsubs [{:keys [resolved-address]} [:wallet-legacy/recipient]
|
||||
fav-name (atom "")]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[react/view {:flex 1}
|
||||
[react/scroll-view {:style {:flex 1}}
|
||||
[react/view {:padding-horizontal 16}
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:height 40
|
||||
:margin-vertical 8}
|
||||
[quo/text (i18n/label :t/address-or-ens-name)]]
|
||||
[quo/text-input
|
||||
{:multiline true
|
||||
:default-value resolved-address
|
||||
:height 70
|
||||
:editable false
|
||||
:accessibility-label :fav-address}]]
|
||||
[react/view {:height 16}]
|
||||
[quo/list-header (i18n/label :t/name-optional)]
|
||||
[react/view {:padding-horizontal 16}
|
||||
[quo/text-input
|
||||
{:show-cancel false
|
||||
:accessibility-label :fav-name
|
||||
:on-change-text #(reset! fav-name %)}]]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:center
|
||||
[quo/button
|
||||
{:accessibility-label :add-fav
|
||||
:type :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy/add-favourite resolved-address
|
||||
@fav-name])}
|
||||
(i18n/label :t/add)]}]]]))
|
||||
|
||||
(views/defview recipient
|
||||
[]
|
||||
(views/letsubs [{:keys [address resolved-address searching]} [:wallet-legacy/recipient]
|
||||
search-filter [:wallet-legacy/search-recipient-filter]]
|
||||
(let [disabled? (or searching (not resolved-address))]
|
||||
[kb-presentation/keyboard-avoiding-view
|
||||
{:style {:flex 1}
|
||||
:ignore-offset true}
|
||||
[react/view {:flex 1}
|
||||
[recipient-topbar]
|
||||
[search-input-wrapper]
|
||||
[react/scroll-view
|
||||
{:style {:flex 1}
|
||||
:keyboard-should-persist-taps :handled
|
||||
:ref #(reset! scroll-view-ref %)}
|
||||
[react/view
|
||||
[components/separator]
|
||||
[react/view {:padding-horizontal 16 :margin-bottom 16}
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:height 40
|
||||
:margin-vertical 8}
|
||||
[quo/text (i18n/label :t/address-or-ens-name)]
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.recipient/address-paste-pressed])}
|
||||
(i18n/label :t/paste)]]
|
||||
[quo/text-input
|
||||
{:multiline true
|
||||
:default-value address
|
||||
:height 70
|
||||
:placeholder (i18n/label :t/recipient-code-placeholder)
|
||||
:text-align-vertical :top
|
||||
:on-change-text #(do
|
||||
(re-frame/dispatch [:set-in [:wallet-legacy/recipient :searching]
|
||||
:searching])
|
||||
(debounce/debounce-and-dispatch
|
||||
[:wallet-legacy.recipient/address-changed
|
||||
(utils.string/safe-trim %)]
|
||||
600))
|
||||
:accessibility-label :recipient-address-input}]]
|
||||
[react/view {:align-items :center :height 30 :padding-bottom 8}
|
||||
(if searching
|
||||
[react/small-loading-indicator]
|
||||
(when resolved-address
|
||||
[quo/text
|
||||
{:style {:margin-horizontal 16}
|
||||
:size :small
|
||||
:align :center
|
||||
:color :secondary}
|
||||
(when-not (address/address? address)
|
||||
(str (stateofus/username-with-domain address) " • "))
|
||||
[quo/text
|
||||
{:monospace true
|
||||
:size :inherit
|
||||
:color :inherit}
|
||||
(utils/get-shortened-address resolved-address)]]))]
|
||||
[accordion search-filter]]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left
|
||||
[quo/button
|
||||
{:accessibility-label :participant-add-to-favs
|
||||
:type :secondary
|
||||
:disabled disabled?
|
||||
:on-press #(re-frame/dispatch [:open-modal :new-favourite])}
|
||||
(i18n/label :t/add-to-favourites)]
|
||||
:right
|
||||
[quo/button
|
||||
{:accessibility-label :participant-done
|
||||
:type :secondary
|
||||
:after :main-icons/next
|
||||
:disabled disabled?
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.send/set-recipient
|
||||
resolved-address])}
|
||||
(i18n/label :t/done)]}]]])))
|
|
@ -1,42 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.request.views
|
||||
(:require
|
||||
[legacy.status-im.ui.components.copyable-text :as copyable-text]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.qr-codes.view :as qr-codes]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.ethereum.eip.eip681 :as eip681]
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [legacy.status-im.utils.views :as views]))
|
||||
|
||||
(views/defview share-address
|
||||
[]
|
||||
(views/letsubs [{:keys [address]} [:popover/popover]
|
||||
chain-id [:chain-id]
|
||||
width (reagent/atom nil)]
|
||||
[react/view {:on-layout #(reset! width (-> ^js % .-nativeEvent .-layout .-width))}
|
||||
[react/view {:style {:padding-top 16 :padding-horizontal 16}}
|
||||
(when @width
|
||||
[qr-codes/qr-code
|
||||
{:url (eip681/generate-uri address {:chain-id chain-id})
|
||||
:size (- @width 32)}])
|
||||
[copyable-text/copyable-text-view
|
||||
{:label :t/ethereum-address
|
||||
:container-style {:margin-top 12 :margin-bottom 4}
|
||||
:copied-text (eip55/address->checksum address)}
|
||||
[quo/text
|
||||
{:number-of-lines 1
|
||||
:ellipsize-mode :middle
|
||||
:accessibility-label :address-text
|
||||
:monospace true}
|
||||
(eip55/address->checksum address)]]]
|
||||
[react/view
|
||||
{:padding-top 12
|
||||
:padding-horizontal 16
|
||||
:padding-bottom 16}
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:wallet-legacy.accounts/share address])
|
||||
:accessibility-label :share-address-button}
|
||||
(i18n/label :t/share-address)]]]))
|
|
@ -1,53 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.send.sheets
|
||||
(:require-macros [legacy.status-im.utils.views :as views])
|
||||
(:require
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.list.views :as list]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.screens.wallet.accounts.common :as common]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defn asset
|
||||
[currency token]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:wallet-legacy.send/set-symbol (:symbol token)])}
|
||||
[common/render-asset token nil nil (:code currency)]])
|
||||
|
||||
(views/defview assets
|
||||
[address]
|
||||
(views/letsubs [{:keys [tokens]} [:wallet-legacy/visible-assets-with-values address]
|
||||
currency [:wallet-legacy/currency]]
|
||||
[react/view
|
||||
{:style {:height 300}}
|
||||
[list/flat-list
|
||||
{:data tokens
|
||||
:key-fn :symbol
|
||||
:render-fn (partial asset currency)}]]))
|
||||
|
||||
(defn render-account
|
||||
[account _ _ {:keys [field event]}]
|
||||
[list.item/list-item
|
||||
{:icon [chat-icon/custom-icon-view-list (:name account) (:color account)]
|
||||
:title (:name account)
|
||||
:on-press #(re-frame/dispatch [event field account])}])
|
||||
|
||||
(views/defview accounts-list
|
||||
[field event]
|
||||
(views/letsubs [accounts [:multiaccount/visible-accounts]
|
||||
accounts-whithout-watch [:visible-accounts-without-watch-only]]
|
||||
[list/flat-list
|
||||
{:data (if (= :to field) accounts accounts-whithout-watch)
|
||||
:key-fn :address
|
||||
:render-data {:field field
|
||||
:event event}
|
||||
:render-fn render-account}]))
|
||||
|
||||
(defn show-accounts-list
|
||||
[]
|
||||
(re-frame/dispatch [:bottom-sheet/hide-old])
|
||||
(js/setTimeout #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content (fn [] [accounts-list :to
|
||||
:wallet-legacy.send/set-field])
|
||||
:content-height 300}])
|
||||
400))
|
|
@ -1,34 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.send.styles
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn sheet
|
||||
[]
|
||||
{:flex 1})
|
||||
|
||||
(defn acc-sheet
|
||||
[]
|
||||
{:background-color colors/white
|
||||
:border-top-right-radius 16
|
||||
:border-top-left-radius 16
|
||||
:padding-bottom 60})
|
||||
|
||||
(defn header
|
||||
[small-screen?]
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between
|
||||
:padding-top (when-not small-screen? 16)
|
||||
:padding-left 16})
|
||||
|
||||
(defn set-max-button
|
||||
[]
|
||||
{:height 35
|
||||
:border-radius 40
|
||||
:background-color colors/blue-light
|
||||
:margin-horizontal 12
|
||||
:align-self :flex-start
|
||||
:margin-bottom 12
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:padding-horizontal 12})
|
|
@ -1,271 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.send.views
|
||||
(:require-macros [legacy.status-im.utils.views :as views])
|
||||
(:require
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as components.core]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.tooltip.views :as tooltip]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as components]
|
||||
[legacy.status-im.ui.screens.wallet.send.sheets :as sheets]
|
||||
[legacy.status-im.ui.screens.wallet.send.styles :as styles]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[quo.core :as quo]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[utils.address :as address]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]))
|
||||
|
||||
(defn header
|
||||
[{:keys [label small-screen?]}]
|
||||
[react/view (styles/header small-screen?)
|
||||
[react/view {:flex 1}
|
||||
[react/text {:style (merge {:typography :title-bold} (when small-screen? {:font-size 15}))}
|
||||
(i18n/label (or label :t/send-transaction))]]])
|
||||
|
||||
(defn asset-selector
|
||||
[{:keys [request? token from]} window-width]
|
||||
(let [{:keys [name icon color]} token]
|
||||
[react/touchable-highlight
|
||||
{:on-press (when-not request?
|
||||
#(do
|
||||
(re-frame/dispatch [:dismiss-keyboard])
|
||||
(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content (fn [] [sheets/assets (:address from)])
|
||||
:content-height 300}])))}
|
||||
[react/view
|
||||
{:style {:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-left 16}
|
||||
:accessibility-label :choose-asset-button}
|
||||
(if icon
|
||||
[components/token-icon
|
||||
(assoc icon
|
||||
:style {:background-color colors/gray-lighter
|
||||
:border-radius 50}
|
||||
:image-style {:width 32 :height 32})]
|
||||
[chat-icon/custom-icon-view-list name color 32])
|
||||
[react/text
|
||||
{:style {:margin-left 8
|
||||
:max-width (/ window-width 4)}
|
||||
:number-of-lines 2}
|
||||
(wallet.utils/display-symbol token)]
|
||||
(when-not request?
|
||||
[icons/icon :main-icons/dropdown {:color colors/gray}])]]))
|
||||
|
||||
(defn render-account
|
||||
[account {:keys [amount decimals] :as token} event]
|
||||
[list.item/list-item
|
||||
{:icon [chat-icon/custom-icon-view-list (:name account) (:color account)]
|
||||
:title (:name account)
|
||||
:subtitle (when token
|
||||
(str (wallet.utils/format-amount amount decimals)
|
||||
" "
|
||||
(wallet.utils/display-symbol token)))
|
||||
:chevron true
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:dismiss-keyboard])
|
||||
(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content (fn [] [sheets/accounts-list :from event])
|
||||
:content-height 300}]))}])
|
||||
|
||||
(defn render-contact
|
||||
[{:keys [address] :as contact} from-chat?]
|
||||
(if from-chat?
|
||||
[list.item/list-item
|
||||
{:title (profile.utils/displayed-name contact)
|
||||
:subtitle [components.core/text
|
||||
{:monospace true
|
||||
:color :secondary}
|
||||
(utils/get-shortened-checksum-address address)]
|
||||
:icon [chat-icon/contact-icon-contacts-tab contact]}]
|
||||
[list.item/list-item
|
||||
(merge {:title (if-not contact
|
||||
(i18n/label :t/wallet-choose-recipient)
|
||||
[components.core/text
|
||||
{:size :large
|
||||
:monospace true}
|
||||
(utils/get-shortened-checksum-address
|
||||
(if (string? contact) contact address))])
|
||||
:accessibility-label :choose-recipient-button
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:dismiss-keyboard])
|
||||
(re-frame/dispatch
|
||||
[:wallet-legacy.send/navigate-to-recipient-code]))
|
||||
:chevron true}
|
||||
(when-not contact
|
||||
{:icon :main-icons/add
|
||||
:theme :accent}))]))
|
||||
|
||||
(defn set-max
|
||||
[token]
|
||||
[react/touchable-highlight
|
||||
{:on-press
|
||||
#(when token
|
||||
(re-frame/dispatch [:wallet-legacy.send/set-max-amount token]))}
|
||||
[react/view {:style (styles/set-max-button)}
|
||||
[react/text {:style {:color colors/blue}} (i18n/label :t/set-max)]]])
|
||||
|
||||
(defn fiat-value
|
||||
[amount {sym :symbol} prices wallet-currency]
|
||||
(when-let [price (get-in prices [(keyword sym) (keyword (:code wallet-currency)) :price])]
|
||||
(let [norm-amount (js/parseFloat (money/normalize amount))
|
||||
amount (if (js/isNaN norm-amount) 0 norm-amount)]
|
||||
[react/text
|
||||
{:style {:color colors/gray
|
||||
:margin-left 16
|
||||
:margin-bottom 8
|
||||
:font-size 15
|
||||
:line-height 22}}
|
||||
(str (i18n/format-currency (* amount price) (:code wallet-currency))
|
||||
" "
|
||||
(:code wallet-currency))])))
|
||||
|
||||
(views/defview request-transaction
|
||||
[_]
|
||||
(views/letsubs [{:keys [amount-error amount-text from token sign-enabled?] :as tx}
|
||||
[:wallet-legacy.request/prepare-transaction-with-balance]
|
||||
window-width [:dimensions/window-width]
|
||||
prices [:prices]
|
||||
wallet-currency [:wallet-legacy/currency]]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[:<>
|
||||
[react/scroll-view
|
||||
{:style {:flex 1}
|
||||
:keyboard-should-persist-taps :handled}
|
||||
[react/view {:style (styles/sheet)}
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 24
|
||||
:align-items :center
|
||||
:margin-vertical 16}
|
||||
[react/text-input
|
||||
{:style {:font-size 38
|
||||
:color (if amount-error colors/red colors/black)
|
||||
:flex-shrink 1}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount-text
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [:wallet-legacy.request/set-amount-text %])
|
||||
:placeholder "0.0 "}]
|
||||
[asset-selector tx window-width]
|
||||
(when amount-error
|
||||
[tooltip/tooltip amount-error
|
||||
{:bottom-value 2
|
||||
:font-size 12}])]
|
||||
[fiat-value amount-text token prices wallet-currency]
|
||||
[components/separator]
|
||||
[components.core/list-header
|
||||
(i18n/label :t/to-capitalized)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-account from token :wallet-legacy.request/set-field]]]]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right
|
||||
[components.core/button
|
||||
{:type :secondary
|
||||
:after :main-icon/next
|
||||
:accessibility-label :request-transaction-bottom-sheet
|
||||
:disabled (not sign-enabled?)
|
||||
:on-press #(do
|
||||
(re-frame/dispatch
|
||||
[:wallet-legacy.ui/request-transaction-button-clicked tx])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
(i18n/label :t/wallet-request)]}]]]))
|
||||
|
||||
(views/defview prepare-send-transaction
|
||||
[_]
|
||||
(views/letsubs [{:keys [amount-error amount-text
|
||||
request?
|
||||
from token to sign-enabled? from-chat?]
|
||||
:as tx}
|
||||
[:wallet-legacy.send/prepare-transaction-with-balance]
|
||||
prices [:prices]
|
||||
wallet-currency [:wallet-legacy/currency]
|
||||
window-width [:dimensions/window-width]]
|
||||
(let [to-norm (address/normalized-hex (if (string? to) to (:address to)))]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[:<>
|
||||
[quo/page-nav
|
||||
{:type :title
|
||||
:text-align :left
|
||||
:title (i18n/label :t/send-transaction)
|
||||
:icon-name :i/arrow-left
|
||||
:on-press (fn []
|
||||
(re-frame/dispatch [:navigate-back])
|
||||
(re-frame/dispatch [:wallet-legacy/cancel-transaction-command]))
|
||||
:accessibility-label :back-button}]
|
||||
[react/scroll-view
|
||||
{:style {:flex 1}
|
||||
:keyboard-should-persist-taps :handled}
|
||||
[react/view {:style (styles/sheet)}
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:margin-top 12
|
||||
:margin-bottom 4}
|
||||
[react/text-input
|
||||
{:style {:font-size 38
|
||||
:max-width (- (* (/ window-width 4) 3) 106)
|
||||
:color (if amount-error colors/red colors/black)}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount-text
|
||||
:editable (not request?)
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [:wallet-legacy.send/set-amount-text %])
|
||||
:placeholder "0.0 "}]
|
||||
[asset-selector tx window-width]
|
||||
(when amount-error
|
||||
[tooltip/tooltip
|
||||
(if from
|
||||
amount-error
|
||||
(i18n/label :t/select-account-first))
|
||||
{:bottom-value 2
|
||||
:font-size 12}])]
|
||||
[fiat-value amount-text token prices wallet-currency]
|
||||
(when-not (or request? from-chat?)
|
||||
[set-max token])
|
||||
[components/separator]
|
||||
[components.core/list-header (i18n/label :t/from-capitalized)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-account from token :wallet-legacy.send/set-field]]]
|
||||
[components.core/list-header
|
||||
(i18n/label :t/to-capitalized)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-contact to from-chat?]]]]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right
|
||||
[quo/button
|
||||
{:accessibility-label :send-transaction-bottom-sheet
|
||||
:type :secondary
|
||||
:after :main-icon/next
|
||||
:disabled (not sign-enabled?)
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:navigate-back])
|
||||
(re-frame/dispatch
|
||||
[(cond
|
||||
request?
|
||||
:wallet-legacy.ui/sign-transaction-button-clicked-from-request
|
||||
from-chat?
|
||||
:wallet-legacy.ui/sign-transaction-button-clicked-from-chat
|
||||
:else
|
||||
:wallet-legacy.ui/sign-transaction-button-clicked) tx]))}
|
||||
|
||||
(if (and (not request?) from-chat? (not to-norm))
|
||||
(i18n/label :t/wallet-send)
|
||||
(i18n/label :t/next))]}]]])))
|
|
@ -1,125 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.settings.views
|
||||
(:require
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.list.views :as list]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.search-input.view :as search-input]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as wallet.components]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [legacy.status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defonce search-active? (reagent/atom false))
|
||||
|
||||
(defn toolbar
|
||||
[]
|
||||
[topbar/topbar
|
||||
{:title (i18n/label :t/wallet-assets)
|
||||
:navigation
|
||||
{:on-press #(re-frame/dispatch [:wallet-legacy.settings.ui/navigate-back-pressed])}}])
|
||||
|
||||
(defn hide-sheet-and-dispatch
|
||||
[event]
|
||||
(re-frame/dispatch [:bottom-sheet/hide-old])
|
||||
(re-frame/dispatch event))
|
||||
|
||||
(defn custom-token-actions-view
|
||||
[{:keys [custom?] :as token}]
|
||||
(fn []
|
||||
[react/view
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/token-details)
|
||||
:icon :main-icons/warning
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:navigate-to :wallet-custom-token-details token])}]
|
||||
(when custom?
|
||||
[list.item/list-item
|
||||
{:theme :negative
|
||||
:title (i18n/label :t/remove-token)
|
||||
:icon :main-icons/delete
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:wallet-legacy.custom-token.ui/remove-pressed token])}])]))
|
||||
|
||||
(defn render-token
|
||||
[_]
|
||||
(reagent/create-class
|
||||
{:should-component-update
|
||||
(fn [_ [_ old-token] [_ new-token]]
|
||||
(not= (:checked? old-token) (:checked? new-token)))
|
||||
:reagent-render
|
||||
(fn [{sym :symbol
|
||||
title :name
|
||||
icon :icon
|
||||
color :color
|
||||
checked? :checked?
|
||||
:as token}]
|
||||
[list.item/list-item
|
||||
{:active checked?
|
||||
:accessory :checkbox
|
||||
:animated-accessory? false
|
||||
:animated false
|
||||
:icon (if icon
|
||||
[wallet.components/token-icon icon]
|
||||
[chat-icon/custom-icon-view-list title color])
|
||||
:title title
|
||||
:subtitle (name sym)
|
||||
:on-press #(re-frame/dispatch [:wallet-legacy.settings/toggle-visible-token
|
||||
(keyword sym)
|
||||
(not checked?)])
|
||||
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||
{:content (custom-token-actions-view token)}])}])}))
|
||||
|
||||
(defn- render-token-wrapper
|
||||
[token]
|
||||
[render-token token])
|
||||
|
||||
(defview manage-assets
|
||||
[]
|
||||
(letsubs [{search-filter :search-filter
|
||||
{custom-tokens true default-tokens nil} :tokens}
|
||||
[:wallet-legacy/filtered-grouped-chain-tokens]]
|
||||
{:component-will-unmount #(do
|
||||
(re-frame/dispatch [:wallet-legacy/search-token-filter-changed nil])
|
||||
(reset! search-active? false))}
|
||||
[react/view {:flex 1 :background-color colors/white}
|
||||
[toolbar]
|
||||
[react/view {:flex 1}
|
||||
[react/view
|
||||
{:padding-horizontal 16
|
||||
:padding-vertical 10}
|
||||
[search-input/search-input-old
|
||||
{:search-active? search-active?
|
||||
:search-filter search-filter
|
||||
:on-cancel #(re-frame/dispatch [:wallet-legacy/search-token-filter-changed nil])
|
||||
:on-focus (fn [search-filter]
|
||||
(when-not search-filter
|
||||
(re-frame/dispatch [:wallet-legacy/search-token-filter-changed ""])))
|
||||
:on-change (fn [text]
|
||||
(re-frame/dispatch [:wallet-legacy/search-token-filter-changed text]))}]]
|
||||
[list/section-list
|
||||
{:header
|
||||
[react/view {:margin-top 16}
|
||||
[list.item/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/add-custom-token)
|
||||
:icon :main-icons/add
|
||||
:on-press
|
||||
#(re-frame/dispatch [:navigate-to :wallet-add-custom-token])}]]
|
||||
:sections (concat
|
||||
(when (seq custom-tokens)
|
||||
[{:title (i18n/label :t/custom)
|
||||
:data custom-tokens}])
|
||||
[{:title (i18n/label :t/default-assets)
|
||||
:data default-tokens}])
|
||||
:key-fn :address
|
||||
:stickySectionHeadersEnabled false
|
||||
:render-section-header-fn
|
||||
(fn [{:keys [title]}]
|
||||
[quo/list-header title])
|
||||
:render-fn render-token-wrapper}]]]))
|
|
@ -1,54 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.signing-phrase.views
|
||||
(:require-macros [legacy.status-im.utils.views :as views])
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(views/defview signing-phrase
|
||||
[]
|
||||
(views/letsubs [phrase [:signing/phrase]
|
||||
{:keys [wallet-set-up-passed?]} [:profile/profile]]
|
||||
[react/view
|
||||
[react/view {:margin-top 24 :margin-horizontal 24 :align-items :center}
|
||||
[react/view
|
||||
{:background-color colors/blue-light
|
||||
:width 32
|
||||
:height 32
|
||||
:border-radius 16
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
[icons/icon :main-icons/security {:color colors/blue}]]
|
||||
[react/text {:style {:typography :title-bold :margin-top 16 :margin-bottom 8}}
|
||||
(i18n/label :t/this-is-you-signing)]
|
||||
[react/text {:style {:color colors/gray :text-align :center}}
|
||||
(i18n/label :t/three-words-description)]]
|
||||
[react/view
|
||||
{:margin-vertical 16
|
||||
:height 52
|
||||
:background-color colors/gray-lighter
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
[react/text phrase]]
|
||||
[react/view
|
||||
{:padding-bottom 8
|
||||
:padding-horizontal 24
|
||||
:align-items :center}
|
||||
[react/text {:style {:color colors/gray :text-align :center}}
|
||||
(i18n/label :t/three-words-description-2)]
|
||||
(when-not wallet-set-up-passed?
|
||||
[react/view {:style {:margin-top 16}}
|
||||
[quo/button {:on-press #(re-frame/dispatch [:hide-popover])}
|
||||
(i18n/label :t/remind-me-later)]])
|
||||
[react/view {:style {:padding-vertical 8}}
|
||||
[quo/button
|
||||
{:on-press #(do
|
||||
(when-not wallet-set-up-passed?
|
||||
(re-frame/dispatch [:profile.settings/update-value
|
||||
:wallet-set-up-passed? true]))
|
||||
(re-frame/dispatch [:hide-popover]))
|
||||
:type :secondary}
|
||||
(i18n/label :t/ok-got-it)]]]]))
|
|
@ -1,505 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.swap.views
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ethereum.tokens :as tokens]
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.search-input.view :as search-input]
|
||||
[legacy.status-im.ui.components.slider :as slider]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.components.views :as wallet.components]
|
||||
[legacy.status-im.wallet.swap.core :as wallet-legacy.swap]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn render-asset
|
||||
[{{:keys
|
||||
[icon decimals amount color value]
|
||||
:as token}
|
||||
:token
|
||||
currency :currency
|
||||
on-press :on-press}]
|
||||
[list.item/list-item
|
||||
{:title [quo/text {:weight :medium}
|
||||
[quo/text {:weight :inherit}
|
||||
(str (if amount
|
||||
(wallet.utils/format-amount amount decimals)
|
||||
"...")
|
||||
" ")]
|
||||
[quo/text
|
||||
{:color :secondary
|
||||
:weight :inherit}
|
||||
(wallet.utils/display-symbol token)]]
|
||||
:on-press on-press
|
||||
:subtitle (str (if value value "...") " " currency)
|
||||
:accessibility-label
|
||||
(str (:symbol token) "-asset-value")
|
||||
:icon (if icon
|
||||
[wallet.components/token-icon icon]
|
||||
[chat-icon/custom-icon-view-list (:name token) color])}])
|
||||
|
||||
(defn asset-selector
|
||||
[]
|
||||
(let [{:keys [address]} (rf/sub [:multiaccount/current-account])
|
||||
{:keys [tokens]} (rf/sub [:wallet-legacy/visible-assets-with-values address])
|
||||
source? (rf/sub [:wallet-legacy/modal-selecting-source-token?])
|
||||
currency (rf/sub [:wallet-legacy/currency])]
|
||||
[:<>
|
||||
[topbar/topbar
|
||||
{:title (if source?
|
||||
(i18n/label :t/select-token-to-swap)
|
||||
(i18n/label :t/select-token-to-receive))
|
||||
:modal? true}]
|
||||
|
||||
[search-input/search-input-old
|
||||
{:search-active? true}]
|
||||
|
||||
[react/scroll-view
|
||||
(for [token tokens]
|
||||
^{:key (:name token)}
|
||||
[render-asset
|
||||
{:token token
|
||||
:on-press #(re-frame/dispatch
|
||||
[(if source?
|
||||
::wallet-legacy.swap/set-from-token
|
||||
::wallet-legacy.swap/set-to-token)
|
||||
(:symbol token)])
|
||||
:currency (:code currency)}])]]))
|
||||
|
||||
(defn pill-button
|
||||
[{:keys [on-press label margin-left]}]
|
||||
[react/touchable-opacity
|
||||
{:on-press on-press
|
||||
:style {:background-color colors/blue-light
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 2
|
||||
:border-radius 24
|
||||
:margin-left (or margin-left 8)}}
|
||||
[quo/text
|
||||
{:color :link
|
||||
:weight :medium} label]])
|
||||
|
||||
(defn token-display
|
||||
"Show token and act as an anchor to open selector."
|
||||
[{:keys [token source?]}]
|
||||
(let [token-icon-source (-> token :icon :source)]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [::wallet-legacy.swap/open-asset-selector-modal source?])}
|
||||
[react/view
|
||||
{:style {:flex-direction :row
|
||||
:align-items :center
|
||||
:border-width 1
|
||||
:border-color colors/gray-lighter
|
||||
:border-radius 8
|
||||
:margin-left 16
|
||||
:padding-horizontal 8
|
||||
:padding-vertical 2}
|
||||
:accessibility-label
|
||||
:choose-asset-button}
|
||||
[quo/text {:style {:margin-right 8}}
|
||||
(-> token :symbol name)]
|
||||
[react/image
|
||||
{:source (if (fn? token-icon-source)
|
||||
(token-icon-source)
|
||||
token-icon-source)}]]]))
|
||||
|
||||
(defn token-input
|
||||
"Component to get the amount and type of tokens"
|
||||
[{:keys [amount error label token max-from source?]}]
|
||||
(let [window-width (rf/sub [:dimensions/window-width])]
|
||||
[react/view
|
||||
{:style {:justify-content :space-between
|
||||
:flex-direction :row
|
||||
:align-items :center}}
|
||||
[react/view {:flex 2}
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:align-items :center}
|
||||
[quo/text label]
|
||||
(when max-from
|
||||
[pill-button
|
||||
{:on-press #()
|
||||
:label "Max 0.043"}])]
|
||||
[react/text-input
|
||||
{:style {:font-size 38
|
||||
:max-width (- (* (/ window-width 4) 3) 106)
|
||||
:color (if error colors/red colors/black)}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount
|
||||
:editable true
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [(when source?
|
||||
::wallet-legacy.swap/set-from-token-amount)
|
||||
%])
|
||||
:placeholder "0.0"}]]
|
||||
[token-display
|
||||
{:token token
|
||||
:source? source?}]]))
|
||||
|
||||
(defn separator-with-icon
|
||||
[]
|
||||
[react/view
|
||||
{:margin-vertical 8}
|
||||
[quo/separator]
|
||||
[react/touchable-opacity
|
||||
{:on-press #(re-frame/dispatch [::wallet-legacy.swap/switch-from-token-with-to])}
|
||||
[react/view
|
||||
{:style {:background-color colors/gray-lighter
|
||||
:width 40
|
||||
:height 40
|
||||
:border-radius 40
|
||||
:border-width 4
|
||||
:border-color colors/white
|
||||
:margin-top -20
|
||||
:margin-bottom -20
|
||||
:align-self :center
|
||||
:align-items :center
|
||||
:justify-content :center}}
|
||||
[react/image
|
||||
{:source (icons/icon-source :main-icons/change)
|
||||
:style {:tint-color colors/gray
|
||||
:transform [{:rotate "90deg"}]}}]]]])
|
||||
|
||||
(defn floating-card
|
||||
[{:keys [icon title body on-press]}]
|
||||
[react/view
|
||||
{:style {:border-width 1
|
||||
:padding 2 ;; need a padding because border breaks otherwise
|
||||
:border-radius 12
|
||||
:margin-top 12
|
||||
:border-color colors/gray-lighter}}
|
||||
[list.item/list-item
|
||||
{:title title
|
||||
:subtitle body
|
||||
:active-background-enabled
|
||||
false
|
||||
:on-press on-press
|
||||
:theme :main
|
||||
:chevron true
|
||||
:icon [react/view
|
||||
{:style {:background-color colors/blue-light
|
||||
:padding 8
|
||||
:border-radius 4}}
|
||||
(icons/icon icon {:color :dark})]}]])
|
||||
|
||||
(defn card-body-row
|
||||
[k value primary?]
|
||||
[react/view {:flex-direction :row}
|
||||
[quo/text {:color (when-not primary? :secondary)} k]
|
||||
[quo/text
|
||||
{:style {:margin-right 4}
|
||||
:color (when-not primary? :secondary)} ":"]
|
||||
[quo/text
|
||||
{:ellipsize-mode :middle
|
||||
:number-of-lines 1
|
||||
:style {:width "50%"}
|
||||
:color (when-not primary? :secondary)
|
||||
:weight :semi-bold} value]])
|
||||
|
||||
(defn transaction-fee-card
|
||||
[{:keys [gas-amount price-limit tip-limit gas-in-eth gas-in-usd]}]
|
||||
[floating-card
|
||||
{:title (i18n/label :t/transaction-fee)
|
||||
:icon :main-icons/gas
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-transaction-fee])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/gas-amount-limit) gas-amount]
|
||||
[card-body-row (i18n/label :t/per-gas-price-limit) price-limit]
|
||||
[card-body-row (i18n/label :t/per-gas-tip-limit) tip-limit]
|
||||
[card-body-row (i18n/label :t/total-gas)
|
||||
(str gas-in-eth " • $" gas-in-usd)
|
||||
true]]}])
|
||||
|
||||
(defn swap-details-card
|
||||
[{:keys [slippage price-impact]}]
|
||||
[floating-card
|
||||
{:title (i18n/label :t/swap-details)
|
||||
:icon :main-icons/change
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-swap-details])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/slippage) (str slippage " %")]
|
||||
[card-body-row (i18n/label :t/price-impact) (str price-impact " %")]]}])
|
||||
|
||||
(defn nonce-card
|
||||
[{:keys [nonce]}]
|
||||
[floating-card
|
||||
{:title (i18n/label :t/nonce)
|
||||
:icon :main-icons/channel
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-nonce])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/nonce) nonce]]}])
|
||||
|
||||
(defn approve-token-card
|
||||
[{:keys [token contract-address approve-limit]}]
|
||||
[floating-card
|
||||
{:title (i18n/label :t/approve)
|
||||
:icon :main-icons/check
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-approve-token])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/token) token]
|
||||
[card-body-row (i18n/label :t/contract-address) contract-address]
|
||||
[card-body-row (i18n/label :t/approve-limit) approve-limit]]}])
|
||||
|
||||
(defn advanced-input
|
||||
[{:keys [label label-help value on-change after]}]
|
||||
[react/view
|
||||
{:style {:padding-horizontal 16
|
||||
:margin-bottom 16}}
|
||||
[react/view
|
||||
{:style {:flex-direction :row
|
||||
:justify-content :space-between}}
|
||||
[quo/text {} label]
|
||||
label-help]
|
||||
|
||||
[quo/text-input
|
||||
{:default-value (str value)
|
||||
:show-cancel false
|
||||
:style {:margin-top 12
|
||||
:border-radius 8}
|
||||
:after {:component after}
|
||||
:on-change-text on-change}]])
|
||||
|
||||
(defn help-label-kv
|
||||
[{k :key v :value}]
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[quo/text {:color :secondary} k]
|
||||
[quo/text
|
||||
{:color :secondary
|
||||
:style {:margin-right 4}} ":"]
|
||||
[quo/text {:color :secondary} v]])
|
||||
|
||||
(defn nonce-modal
|
||||
[]
|
||||
(let [last-txn-nonce 22
|
||||
nonce 23]
|
||||
[kb-presentation/keyboard-avoiding-view
|
||||
{:style {:flex 1
|
||||
:margin-top 16}
|
||||
:ignore-offset true}
|
||||
[advanced-input
|
||||
{:label (i18n/label :t/nonce)
|
||||
:label-help [help-label-kv
|
||||
{:key (i18n/label :t/last-transaction)
|
||||
:value last-txn-nonce}]
|
||||
:value nonce
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left [quo/button {:type :secondary}
|
||||
(i18n/label :t/cancel)]
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/save)]}]]))
|
||||
|
||||
(defn approve-token-modal
|
||||
[]
|
||||
[quo/text "modal"])
|
||||
|
||||
(defn transaction-fee-modal
|
||||
[]
|
||||
(let [gas-amount-limit 21000
|
||||
gas-amount 21000
|
||||
per-gas-price-limit 7.3
|
||||
current-avg-per-gas-price-limit 7.3
|
||||
per-gas-tip-limit 150
|
||||
current-avg-per-gas-tip-limit 150]
|
||||
[kb-presentation/keyboard-avoiding-view
|
||||
{:style {:flex 1
|
||||
:margin-top 16}
|
||||
:ignore-offset true}
|
||||
[react/view {:flex 1}
|
||||
[advanced-input
|
||||
{:label (i18n/label :t/gas-amount-limit)
|
||||
:label-help [help-label-kv
|
||||
{:key (i18n/label :t/limit)
|
||||
:value gas-amount-limit}]
|
||||
:value gas-amount
|
||||
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[advanced-input
|
||||
{:label (i18n/label :t/per-gas-price-limit)
|
||||
:label-help [help-label-kv
|
||||
{:key (i18n/label :t/current-average)
|
||||
:value current-avg-per-gas-price-limit}]
|
||||
:value per-gas-price-limit
|
||||
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[advanced-input
|
||||
{:label (i18n/label :t/per-gas-price-limit)
|
||||
:label-help [help-label-kv
|
||||
{:key (i18n/label :t/current-average)
|
||||
:value current-avg-per-gas-tip-limit}]
|
||||
:value per-gas-tip-limit
|
||||
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[list.item/list-item
|
||||
{:title (i18n/label :t/maximum-fee)
|
||||
:text-size :base
|
||||
:title-text-weight :regular
|
||||
:accessory :text
|
||||
:accessory-text [quo/text "0.3 ETH"]
|
||||
:container-style {:margin-top 16}}]
|
||||
[quo/text
|
||||
{:color :secondary
|
||||
:style {:padding-horizontal 16}}
|
||||
(i18n/label :t/maximum-fee-desc)]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left [quo/button {:type :secondary}
|
||||
(i18n/label :t/cancel)]
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/save)]}]]))
|
||||
|
||||
(defn swap-details-modal
|
||||
[]
|
||||
(let [slippage-limit 20
|
||||
slippage 0.5
|
||||
price-impact 4]
|
||||
[kb-presentation/keyboard-avoiding-view
|
||||
{:style {:flex 1
|
||||
:margin-top 16}
|
||||
:ignore-offset true}
|
||||
[react/view {:flex 1}
|
||||
[advanced-input
|
||||
{:label (str (i18n/label :t/slippage) " %")
|
||||
:label-help [help-label-kv
|
||||
{:key (i18n/label :t/limit)
|
||||
:value (str slippage-limit "%")}]
|
||||
:value slippage
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[list.item/list-item
|
||||
{:title (i18n/label :t/price-impact)
|
||||
:text-size :base
|
||||
:title-text-weight :regular
|
||||
:accessory :text
|
||||
:accessory-text (str price-impact "%")
|
||||
:container-style {:margin-top 16}}]
|
||||
[quo/text
|
||||
{:color :secondary
|
||||
:style {:padding-horizontal 16}}
|
||||
(i18n/label :t/price-impact-desc)]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left [quo/button {:type :secondary}
|
||||
(i18n/label :t/cancel)]
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/save)]}]]))
|
||||
|
||||
(defn advanced-settings
|
||||
[]
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:padding-horizontal 16}}
|
||||
[react/view {:align-self :flex-start}
|
||||
[pill-button
|
||||
{:label (i18n/label :t/switch-to-simple-interface)
|
||||
:margin-left 0
|
||||
:on-press #(re-frame/dispatch [::wallet-legacy.swap/set-advanced-mode false])}]]
|
||||
[transaction-fee-card
|
||||
{:gas-amount 21000
|
||||
:price-limit 74
|
||||
:tip-limit 21
|
||||
:gas-in-eth 0.0031
|
||||
:gas-in-usd 34.28}]
|
||||
[swap-details-card
|
||||
{:slippage 0.5
|
||||
:price-impact 4}]
|
||||
[approve-token-card
|
||||
{:token "USDC"
|
||||
:contract-address "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2"
|
||||
:approve-limit "unlimited"}]
|
||||
[nonce-card {:nonce 22}]])
|
||||
|
||||
(defn swap
|
||||
[]
|
||||
(let [{:keys [name]}
|
||||
(rf/sub [:multiaccount/current-account])
|
||||
all-tokens (rf/sub [:wallet-legacy/all-tokens])
|
||||
from-symbol (rf/sub [:wallet-legacy/swap-from-token])
|
||||
to-symbol (rf/sub [:wallet-legacy/swap-to-token])
|
||||
advanced-mode? (rf/sub [:wallet-legacy/swap-advanced-mode?])
|
||||
amount "0.02"
|
||||
from-token (tokens/symbol->token all-tokens (or from-symbol :DGX))
|
||||
to-token (tokens/symbol->token all-tokens (or to-symbol :SNT))]
|
||||
|
||||
[kb-presentation/keyboard-avoiding-view
|
||||
{:style (merge
|
||||
{:flex 1})
|
||||
:ignore-offset true}
|
||||
[topbar/topbar
|
||||
{:title name
|
||||
:subtitle (string/upper-case (i18n/label :t/powered-by-paraswap))
|
||||
:modal? true}]
|
||||
|
||||
[react/view
|
||||
(merge {:padding-horizontal 16
|
||||
:margin-vertical 32}
|
||||
(when-not advanced-mode?
|
||||
{:flex 1}))
|
||||
[token-input
|
||||
{:amount amount
|
||||
:error nil
|
||||
:label (i18n/label :t/amount)
|
||||
:token from-token
|
||||
:source? true
|
||||
:max-from 67.28}]
|
||||
|
||||
[separator-with-icon]
|
||||
|
||||
[token-input
|
||||
{:amount "0.01"
|
||||
:error nil
|
||||
:label (i18n/label :t/minimum-received)
|
||||
:source? false
|
||||
:token to-token}]]
|
||||
|
||||
(when-not advanced-mode?
|
||||
[react/view
|
||||
{:style {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-horizontal 16
|
||||
:align-items :center}}
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[quo/text {} (i18n/label :t/priority)]
|
||||
[pill-button
|
||||
{:label (i18n/label :t/advanced)
|
||||
:on-press #(re-frame/dispatch [::wallet-legacy.swap/set-advanced-mode true])}]]
|
||||
|
||||
[quo/text {:color :secondary} "0.0034 ETH/ $ 8.09"]])
|
||||
|
||||
(comment
|
||||
(re-frame/dispatch [::wallet-legacy.swap/set-advanced-mode false]))
|
||||
|
||||
(when-not advanced-mode?
|
||||
[react/view {:style {:padding-horizontal 16}}
|
||||
[slider/animated-slider
|
||||
{:minimum-value 0
|
||||
:maximum-value 100
|
||||
:style {:margin-vertical 8}}]])
|
||||
|
||||
(when advanced-mode?
|
||||
[quo/text "here"]
|
||||
[advanced-settings])
|
||||
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/swap)]}]]))
|
|
@ -1,141 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.transactions.styles
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.utils.styles :as styles]))
|
||||
|
||||
(def forward
|
||||
{:color colors/gray})
|
||||
|
||||
(def empty-text
|
||||
{:text-align :center
|
||||
:color colors/gray
|
||||
:margin-top 22
|
||||
:margin-horizontal 92})
|
||||
|
||||
(styles/def amount-time
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-right 22
|
||||
:padding-left 17
|
||||
:ios {:padding-top 13}
|
||||
:android {:padding-top 14}})
|
||||
|
||||
(def tx-amount
|
||||
{:flex-grow 1
|
||||
:flex-shrink 1
|
||||
:margin-right 10
|
||||
:font-size 17})
|
||||
|
||||
(def tx-time
|
||||
{:flex-grow 1
|
||||
:font-size 14
|
||||
:text-align :right
|
||||
:color colors/blue})
|
||||
|
||||
(def address-row
|
||||
{:flex-direction :row
|
||||
:padding-right 22
|
||||
:padding-left 17
|
||||
:padding-top 4})
|
||||
|
||||
(def address-label
|
||||
{:margin-right 5
|
||||
:font-size 16
|
||||
:color colors/gray})
|
||||
|
||||
(def address-contact
|
||||
{:margin-right 5
|
||||
:font-size 16})
|
||||
|
||||
(def address-hash
|
||||
{:flex-shrink 1})
|
||||
|
||||
(defn transaction-icon-background
|
||||
[color]
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:width 40
|
||||
:height 40
|
||||
:border-radius 32
|
||||
:background-color color})
|
||||
|
||||
;; transaction details
|
||||
|
||||
(def details-row
|
||||
{:flex-direction :row
|
||||
:margin-vertical 5})
|
||||
|
||||
(def details-item-label
|
||||
{:flex 1
|
||||
:margin-right 10
|
||||
:color colors/gray})
|
||||
|
||||
(def details-item-value-wrapper
|
||||
{:flex 5})
|
||||
|
||||
(def details-item-value
|
||||
{:font-size 14})
|
||||
|
||||
(def details-item-extra-value
|
||||
{:font-size 14
|
||||
:color colors/gray})
|
||||
|
||||
(def details-header
|
||||
{:margin-horizontal 16
|
||||
:margin-top 10
|
||||
:flex-direction :row})
|
||||
|
||||
(def details-header-icon
|
||||
{:margin-vertical 7})
|
||||
|
||||
(def details-header-infos
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:margin-left 12
|
||||
:margin-vertical 7})
|
||||
|
||||
(def details-header-value
|
||||
{:font-size 16})
|
||||
|
||||
(def details-header-date
|
||||
{:font-size 14
|
||||
:color colors/gray})
|
||||
|
||||
(def details-block
|
||||
{:margin-horizontal 16})
|
||||
|
||||
(def progress-bar
|
||||
{:flex-direction :row
|
||||
:margin-vertical 10
|
||||
:height 2})
|
||||
|
||||
(defn progress-bar-done
|
||||
[done failed?]
|
||||
{:flex done
|
||||
:background-color (if failed?
|
||||
colors/red
|
||||
colors/blue)})
|
||||
|
||||
(defn progress-bar-todo
|
||||
[todo failed?]
|
||||
{:flex todo
|
||||
:background-color (if failed?
|
||||
colors/red
|
||||
colors/blue)
|
||||
:opacity 0.30})
|
||||
|
||||
(def details-confirmations-count
|
||||
{:margin-vertical 2})
|
||||
|
||||
(def details-failed
|
||||
{:color colors/red
|
||||
:margin-vertical 2})
|
||||
|
||||
(def details-confirmations-helper-text
|
||||
{:color colors/gray
|
||||
:margin-vertical 2})
|
||||
|
||||
(def details-separator
|
||||
{:background-color colors/black-transparent
|
||||
:height 1
|
||||
:margin-vertical 10})
|
|
@ -1,304 +0,0 @@
|
|||
(ns legacy.status-im.ui.screens.wallet.transactions.views
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.list-selection :as list-selection]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.list.views :as list]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.wallet.transactions.styles :as styles]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [legacy.status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn- transaction-icon
|
||||
[icon-key background-color color]
|
||||
{:icon icon-key
|
||||
:icon-color color
|
||||
:icon-bg-color background-color})
|
||||
|
||||
(defn- transaction-type->icon
|
||||
[k]
|
||||
(case k
|
||||
:inbound (transaction-icon :main-icons/arrow-left
|
||||
colors/green-transparent-10
|
||||
colors/green)
|
||||
:outbound (transaction-icon :main-icons/arrow-right
|
||||
colors/blue-transparent-10
|
||||
colors/blue)
|
||||
:failed (transaction-icon :main-icons/warning
|
||||
colors/black-transparent
|
||||
colors/red)
|
||||
:pending (transaction-icon :main-icons/arrow-right
|
||||
colors/black-transparent
|
||||
colors/gray)
|
||||
(throw (js/Error. (str "Unknown transaction type: " k)))))
|
||||
|
||||
(defn render-transaction
|
||||
[{:keys [label contact address contact-accessibility-label
|
||||
currency-text amount-text
|
||||
time-formatted on-touch-fn type]
|
||||
:as transaction}
|
||||
_ _ {:keys [keycard-account?]}]
|
||||
[:<>
|
||||
[list.item/list-item
|
||||
(merge
|
||||
{:on-press on-touch-fn
|
||||
:accessibility-label :transaction-item
|
||||
:title (str amount-text " " currency-text)
|
||||
:subtitle (str label
|
||||
" "
|
||||
(when contact
|
||||
[react/text
|
||||
{:style styles/address-contact
|
||||
:accessibility-label contact-accessibility-label}
|
||||
contact])
|
||||
" "
|
||||
(utils/get-shortened-address address)
|
||||
" "
|
||||
(i18n/label :t/at)
|
||||
" "
|
||||
time-formatted)
|
||||
:chevron true}
|
||||
(when type (transaction-type->icon (keyword type))))]
|
||||
;; Disabling for now as we have added nonce which is more reliable, until we address the ux
|
||||
;; issues
|
||||
(when (and false
|
||||
(not keycard-account?)
|
||||
(= type :pending))
|
||||
[react/view {:flex-direction :row :padding 16 :justify-content :space-between}
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:signing.ui/increase-gas-pressed (:hash transaction)])}
|
||||
(i18n/label :t/increase-gas)]
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:signing.ui/cancel-transaction-pressed (:hash transaction)])}
|
||||
(i18n/label :t/cancel)]])])
|
||||
|
||||
(defn chain-explorer-link
|
||||
[address]
|
||||
(let [link @(re-frame/subscribe [:wallet-legacy/chain-explorer-link address])]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(when link
|
||||
(.openURL ^js react/linking link))}
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:padding-horizontal 14
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color colors/blue-light
|
||||
:height 52}}
|
||||
[icons/tiny-icon
|
||||
:tiny-icons/tiny-external
|
||||
{:color colors/blue
|
||||
:container-style {:margin-right 5}}]
|
||||
[react/text
|
||||
{:style {:color colors/blue}}
|
||||
(i18n/label :t/check-on-block-explorer)]]]))
|
||||
|
||||
(defn custom-node
|
||||
[]
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:padding-horizontal 14
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color (colors/get-color :warning-02)
|
||||
:height 52}}
|
||||
[react/text
|
||||
{:style {:color (colors/get-color :warning-01)}}
|
||||
(i18n/label :t/custom-node)]])
|
||||
|
||||
(defn non-archival-node
|
||||
[]
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:padding-horizontal 14
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color (colors/get-color :negative-02)
|
||||
:height 52}}
|
||||
[react/text
|
||||
{:style {:color (colors/get-color :negative-01)}}
|
||||
(i18n/label :t/non-archival-node)]])
|
||||
|
||||
(defn history-list
|
||||
[{:keys [transaction-history-sections total]} address]
|
||||
(let [fetching-recent-history? @(re-frame/subscribe [:wallet-legacy/fetching-recent-tx-history?
|
||||
address])
|
||||
fetching-more-history? @(re-frame/subscribe [:wallet-legacy/fetching-tx-history? address])
|
||||
keycard-account? @(re-frame/subscribe [:multiaccounts/keycard-account?])
|
||||
custom-rpc-node? @(re-frame/subscribe [:custom-rpc-node])
|
||||
non-archival-rpc-node? @(re-frame/subscribe [:wallet-legacy/non-archival-node])
|
||||
binance-chain? @(re-frame/subscribe [:wallet-legacy/binance-chain?])
|
||||
all-fetched? @(re-frame/subscribe [:wallet-legacy/tx-history-fetched? address])
|
||||
syncing-allowed? @(re-frame/subscribe [:mobile-network/syncing-allowed?])]
|
||||
[react/view {:flex 1}
|
||||
[chain-explorer-link address]
|
||||
(cond (or non-archival-rpc-node? binance-chain?)
|
||||
[non-archival-node]
|
||||
custom-rpc-node?
|
||||
[custom-node])
|
||||
(when fetching-recent-history?
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:height 40
|
||||
:margin-vertical 16}}
|
||||
[react/activity-indicator
|
||||
{:size :large
|
||||
:animating true}]])
|
||||
[list/section-list
|
||||
{:sections transaction-history-sections
|
||||
:key-fn :hash
|
||||
:render-data {:keycard-account? keycard-account?}
|
||||
:render-fn render-transaction
|
||||
:empty-component
|
||||
[react/i18n-text
|
||||
{:style styles/empty-text
|
||||
:key (if (or fetching-recent-history? fetching-more-history?)
|
||||
:transactions-history-loading
|
||||
:transactions-history-empty)}]}]
|
||||
(when (and (not fetching-recent-history?)
|
||||
(not= all-fetched? :all))
|
||||
(if fetching-more-history?
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:height 40
|
||||
:margin-vertical 8}}
|
||||
[react/activity-indicator
|
||||
{:size :large
|
||||
:animating true}]]
|
||||
[toolbar/toolbar
|
||||
{:center
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:disabled (and (not syncing-allowed?)
|
||||
(or (= all-fetched? :all-preloaded)
|
||||
(zero? total)))
|
||||
:on-press (when-not fetching-more-history?
|
||||
#(re-frame/dispatch
|
||||
[:transactions/fetch-more address]))}
|
||||
(i18n/label :t/transactions-load-more)]}]))]))
|
||||
|
||||
(defn details-header
|
||||
[date type amount-text currency-text]
|
||||
[list.item/list-item
|
||||
(merge
|
||||
{:title [react/nested-text {:style styles/details-header-value}
|
||||
[{:accessibility-label :amount-text} amount-text]
|
||||
" "
|
||||
[{:accessibility-label :currency-text} currency-text]]
|
||||
:subtitle date}
|
||||
(transaction-type->icon type))])
|
||||
|
||||
(defn progress-bar
|
||||
[progress failed?]
|
||||
[react/view {:style styles/progress-bar}
|
||||
[react/view {:style (styles/progress-bar-done progress failed?)}]
|
||||
[react/view {:style (styles/progress-bar-todo (- 100 progress) failed?)}]])
|
||||
|
||||
(defn details-confirmations
|
||||
[confirmations confirmations-progress failed?]
|
||||
[react/view {:style styles/details-block}
|
||||
[progress-bar confirmations-progress failed?]
|
||||
(if failed?
|
||||
[react/i18n-text
|
||||
{:style styles/details-failed
|
||||
:key :failed}]
|
||||
[react/text {:style styles/details-confirmations-count}
|
||||
(str confirmations " " (i18n/label :t/confirmations))])
|
||||
[react/i18n-text
|
||||
{:style styles/details-confirmations-helper-text
|
||||
:key :confirmations-helper-text}]])
|
||||
|
||||
(defn details-list-row
|
||||
([label props-value]
|
||||
(details-list-row label props-value nil))
|
||||
([label props-value extra-props-value]
|
||||
(let [[props value] (if (string? props-value)
|
||||
[nil props-value]
|
||||
props-value)
|
||||
[extra-props extra-value] (if (string? extra-props-value)
|
||||
[nil extra-props-value]
|
||||
extra-props-value)]
|
||||
[react/view {:style styles/details-row}
|
||||
[react/i18n-text {:style styles/details-item-label :key label}]
|
||||
[react/view {:style styles/details-item-value-wrapper}
|
||||
[quo/text
|
||||
(merge {:size :small
|
||||
:monospace true}
|
||||
props)
|
||||
(str (or value "-"))]
|
||||
[quo/text
|
||||
(merge {:size :small
|
||||
:color :secondary
|
||||
:monospace true}
|
||||
extra-props)
|
||||
(str extra-value)]]])))
|
||||
|
||||
(defn details-list
|
||||
[{:keys [block from from-wallet from-contact
|
||||
to to-wallet to-contact
|
||||
gas-limit gas-price-gwei gas-price-eth gas-used
|
||||
fee-cap-gwei tip-cap-gwei
|
||||
cost nonce data]
|
||||
:as tx}]
|
||||
[react/view {:style styles/details-block}
|
||||
[details-list-row :t/block block]
|
||||
[details-list-row :t/hash (:hash tx)]
|
||||
[details-list-row :t/from-capitalized
|
||||
[{:accessibility-label (if from-wallet :sender-name-text :sender-address-text)}
|
||||
(or from-wallet from-contact from)]
|
||||
(when (or from-wallet from-contact)
|
||||
[{:accessibility-label :sender-address-text}
|
||||
from])]
|
||||
[details-list-row :t/to-capitalized
|
||||
[{:accessibility-label (if to-wallet :recipient-name-text :recipient-address-text)}
|
||||
(or to-wallet to-contact to)]
|
||||
(when (or to-wallet to-contact)
|
||||
[{:accessibility-label :recipient-address-text}
|
||||
to])]
|
||||
[details-list-row :t/gas-limit [{:monospace true} gas-limit]]
|
||||
[details-list-row :t/gas-price gas-price-gwei [{:monospace false} gas-price-eth]]
|
||||
[details-list-row :t/fee-cap fee-cap-gwei]
|
||||
[details-list-row :t/tip-cap tip-cap-gwei]
|
||||
[details-list-row :t/gas-used gas-used]
|
||||
[details-list-row :t/cost-fee [{:monospace false} cost]]
|
||||
[details-list-row :t/nonce nonce]
|
||||
[details-list-row :t/data data]])
|
||||
|
||||
(defn details-action
|
||||
[tx-hash url]
|
||||
[{:label (i18n/label :t/copy-transaction-hash)
|
||||
:action #(react/copy-to-clipboard tx-hash)}
|
||||
{:label (i18n/label :t/open-on-block-explorer)
|
||||
:action #(.openURL ^js react/linking url)}])
|
||||
|
||||
(defview transaction-details-view
|
||||
[tx-hash address]
|
||||
(letsubs [{:keys [url type confirmations confirmations-progress
|
||||
date amount-text currency-text]
|
||||
:as transaction}
|
||||
[:wallet-legacy.transactions.details/screen tx-hash address]]
|
||||
[react/view {:flex 1}
|
||||
;;TODO options should be replaced by bottom sheet ,and topbar should be used here
|
||||
[topbar/topbar
|
||||
{:title (i18n/label :t/transaction-details)
|
||||
:right-accessories (when transaction
|
||||
[{:icon :main-icons/more
|
||||
:on-press #(list-selection/show {:options
|
||||
(details-action tx-hash url)})}])}]
|
||||
[react/scroll-view {:flex 1}
|
||||
[details-header date type amount-text currency-text]
|
||||
[details-confirmations confirmations confirmations-progress (= :failed type)]
|
||||
[react/view {:style styles/details-separator}]
|
||||
[details-list transaction]]]))
|
||||
|
||||
(defview transaction-details
|
||||
[]
|
||||
(letsubs [{tx-hash :hash address :address} [:get-screen-params]]
|
||||
(when (and tx-hash address)
|
||||
[transaction-details-view tx-hash address])))
|
|
@ -1,394 +0,0 @@
|
|||
(ns legacy.status-im.wallet.accounts.core
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ens.core :as ens.core]
|
||||
[legacy.status-im.ethereum.mnemonic :as mnemonic]
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.list-selection :as list-selection]
|
||||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[legacy.status-im.utils.hex :as hex]
|
||||
[legacy.status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[legacy.status-im.wallet.core :as wallet-legacy]
|
||||
[legacy.status-im.wallet.prices :as prices]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
[utils.ens.stateofus :as stateofus]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.ethereum.eip.eip681 :as eip681]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(rf/defn start-adding-new-account
|
||||
{:events [:wallet-legacy.accounts/start-adding-new-account]}
|
||||
[{:keys [db] :as cofx} {:keys [type] :as add-account}]
|
||||
(let [{:keys [latest-derived-path]} (:profile/profile db)
|
||||
path-num (inc latest-derived-path)
|
||||
account (merge
|
||||
{:color (rand-nth colors/account-colors)}
|
||||
(when (= type :generate)
|
||||
{:name (str "Account " path-num)}))]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :add-account (assoc add-account :account account))}
|
||||
(navigation/navigate-to :add-new-account nil))))
|
||||
|
||||
(rf/defn new-account-error
|
||||
{:events [::new-account-error]}
|
||||
[{:keys [db]} error-key error]
|
||||
{:db (update db
|
||||
:add-account
|
||||
merge
|
||||
{error-key error
|
||||
:step nil})})
|
||||
|
||||
(defn account-stored
|
||||
[path type]
|
||||
(fn [result]
|
||||
(let [{:keys [error publicKey address]} (types/json->clj result)]
|
||||
(if error
|
||||
(re-frame/dispatch [::new-account-error :account-error error])
|
||||
(re-frame/dispatch [:wallet-legacy.accounts/account-stored
|
||||
{:address address
|
||||
:public-key publicKey
|
||||
:type type
|
||||
:path path}])))))
|
||||
|
||||
(defn normalize-path
|
||||
[path]
|
||||
(if (string/starts-with? path "m/")
|
||||
(str constants/path-wallet-root
|
||||
"/"
|
||||
(last (string/split path "/")))
|
||||
path))
|
||||
|
||||
(defn derive-and-store-account
|
||||
[key-uid path hashed-password type accounts]
|
||||
(fn [value]
|
||||
(let [{:keys [id error keyUid]} (types/json->clj value)]
|
||||
(if error
|
||||
(re-frame/dispatch [::new-account-error :password-error error])
|
||||
(native-module/multiaccount-derive-addresses
|
||||
id
|
||||
[path]
|
||||
(fn [derived]
|
||||
(let [derived-address (get-in (types/json->clj derived) [(keyword path) :address])]
|
||||
(if (some #(= derived-address (get % :address)) accounts)
|
||||
(re-frame/dispatch [::new-account-error :account-error
|
||||
(i18n/label :t/account-exists-title)])
|
||||
(native-module/multiaccount-store-derived
|
||||
id
|
||||
key-uid
|
||||
[path]
|
||||
hashed-password
|
||||
(fn [result]
|
||||
(let [{:keys [error] :as result} (types/json->clj result)
|
||||
{:keys [publicKey address]} (get result (keyword path))]
|
||||
(if error
|
||||
(re-frame/dispatch [::new-account-error :account-error error])
|
||||
(re-frame/dispatch
|
||||
[:wallet-legacy.accounts/account-stored
|
||||
{:address address
|
||||
:public-key publicKey
|
||||
:key-uid keyUid
|
||||
:type type
|
||||
:path (normalize-path path)}])))))))))))))
|
||||
|
||||
(def pass-error
|
||||
"cannot retrieve a valid key for a given account: could not decrypt key with given password")
|
||||
|
||||
(defn store-account
|
||||
[key-uid path hashed-password type]
|
||||
(fn [value]
|
||||
(let [{:keys [id error]} (types/json->clj value)]
|
||||
(if error
|
||||
(re-frame/dispatch [::new-account-error
|
||||
(if (= error pass-error) :password-error :account-error)
|
||||
error])
|
||||
(native-module/multiaccount-store-account
|
||||
id
|
||||
key-uid
|
||||
hashed-password
|
||||
(account-stored path type))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::verify-password
|
||||
(fn [{:keys [address hashed-password]}]
|
||||
(native-module/verify
|
||||
address
|
||||
hashed-password
|
||||
#(re-frame/dispatch [:wallet-legacy.accounts/add-new-account-password-verified %
|
||||
hashed-password]))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::generate-account
|
||||
(fn [{:keys [derivation-info hashed-password accounts key-uid]}]
|
||||
(let [{:keys [address path]} derivation-info]
|
||||
(native-module/multiaccount-load-account
|
||||
address
|
||||
hashed-password
|
||||
(derive-and-store-account key-uid path hashed-password :generated accounts)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::import-account-seed
|
||||
(fn [{:keys [passphrase hashed-password accounts key-uid]}]
|
||||
(native-module/multiaccount-import-mnemonic
|
||||
(mnemonic/sanitize-passphrase (security/unmask passphrase))
|
||||
""
|
||||
(derive-and-store-account key-uid constants/path-default-wallet hashed-password :seed accounts))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::import-account-private-key
|
||||
(fn [{:keys [private-key hashed-password key-uid]}]
|
||||
(native-module/multiaccount-import-private-key
|
||||
(string/trim (security/unmask private-key))
|
||||
(store-account key-uid constants/path-default-wallet hashed-password :key))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::validate-mnemonic
|
||||
(fn [[passphrase callback]]
|
||||
(native-module/validate-mnemonic passphrase callback)))
|
||||
|
||||
(rf/defn generate-new-account
|
||||
[{:keys [db]} hashed-password]
|
||||
(let [{:keys [key-uid wallet-root-address]}
|
||||
(get db :profile/profile)
|
||||
path-num (inc (get-in db [:profile/profile :latest-derived-path]))
|
||||
accounts (:profile/wallet-accounts db)]
|
||||
{:db (assoc-in db [:add-account :step] :generating)
|
||||
::generate-account {:derivation-info {:path (str "m/" path-num)
|
||||
:address wallet-root-address}
|
||||
:hashed-password hashed-password
|
||||
:accounts accounts
|
||||
:key-uid key-uid}}))
|
||||
|
||||
(rf/defn import-new-account-seed
|
||||
[{:keys [db]} passphrase hashed-password]
|
||||
{:db (assoc-in db [:add-account :step] :generating)
|
||||
::validate-mnemonic [(security/safe-unmask-data passphrase)
|
||||
#(re-frame/dispatch [:wallet-legacy.accounts/seed-validated % passphrase
|
||||
hashed-password])]})
|
||||
|
||||
(rf/defn new-account-seed-validated
|
||||
{:events [:wallet-legacy.accounts/seed-validated]}
|
||||
[{:keys [db] :as cofx} phrase-warnings passphrase hashed-password]
|
||||
(let [error (:error (types/json->clj phrase-warnings))
|
||||
{:keys [key-uid]} (:profile/profile db)]
|
||||
(if-not (string/blank? error)
|
||||
(new-account-error cofx :account-error error)
|
||||
(let [accounts (:profile/wallet-accounts db)]
|
||||
{::import-account-seed {:passphrase passphrase
|
||||
:hashed-password hashed-password
|
||||
:accounts accounts
|
||||
:key-uid key-uid}}))))
|
||||
|
||||
(rf/defn import-new-account-private-key
|
||||
[{:keys [db]} private-key hashed-password]
|
||||
(let [{:keys [key-uid]} (:profile/profile db)]
|
||||
{:db (assoc-in db [:add-account :step] :generating)
|
||||
::import-account-private-key {:private-key private-key
|
||||
:hashed-password hashed-password
|
||||
:key-uid key-uid}}))
|
||||
|
||||
(rf/defn save-new-account
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [latest-derived-path]} (:profile/profile db)
|
||||
{:keys [account type]} (:add-account db)
|
||||
{:keys [address name key-uid]} account
|
||||
main-key-uid (or key-uid (get-in db [:profile/profile :key-uid]))
|
||||
accounts (:profile/wallet-accounts db)
|
||||
new-accounts (conj accounts account)
|
||||
;; Note(rasom): in case if a new account is created using a mnemonic or
|
||||
;; a private key we add a new keypair to the database, otherwise we just
|
||||
;; keep using "profile" keypair
|
||||
[method params]
|
||||
(if key-uid
|
||||
["accounts_saveKeypair"
|
||||
[{:key-uid main-key-uid
|
||||
:name name
|
||||
:type (if (= type :seed)
|
||||
"seed"
|
||||
"key")
|
||||
:derived-from address
|
||||
:last-used-derivation-index 0
|
||||
:synced-from ""
|
||||
:clock 0
|
||||
:accounts [account]}]]
|
||||
["accounts_saveAccount"
|
||||
[(assoc account :key-uid key-uid)]])]
|
||||
(when account
|
||||
(rf/merge cofx
|
||||
{:json-rpc/call [{:method method
|
||||
:params params
|
||||
:on-success #(re-frame/dispatch [::wallet-legacy/restart])}]
|
||||
:db (-> db
|
||||
(assoc :profile/wallet-accounts new-accounts)
|
||||
(dissoc :add-account))}
|
||||
(when (= type :generate)
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:latest-derived-path
|
||||
(inc latest-derived-path)
|
||||
{}))))))
|
||||
|
||||
(rf/defn account-generated
|
||||
{:events [:wallet-legacy.accounts/account-stored]}
|
||||
[{:keys [db] :as cofx} {:keys [address] :as account}]
|
||||
(let [accounts (:profile/wallet-accounts db)]
|
||||
(if (some #(when (= (:address %) address) %) accounts)
|
||||
(new-account-error cofx :account-error (i18n/label :t/account-exists-title))
|
||||
(rf/merge cofx
|
||||
{:db (update-in db [:add-account :account] merge account)}
|
||||
(save-new-account)
|
||||
(if (utils.mobile-sync/syncing-allowed? cofx)
|
||||
(wallet-legacy/set-max-block address 0)
|
||||
(wallet-legacy/update-balances nil true))
|
||||
(wallet-legacy/fetch-collectibles-collection)
|
||||
(prices/update-prices)
|
||||
(navigation/navigate-back)))))
|
||||
|
||||
(rf/defn add-watch-account
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [address (get-in db [:add-account :address])]
|
||||
(account-generated cofx
|
||||
{:address (eip55/address->checksum (address/normalized-hex address))
|
||||
:type :watch})))
|
||||
|
||||
(rf/defn add-new-account-password-verified
|
||||
{:events [:wallet-legacy.accounts/add-new-account-password-verified]}
|
||||
[{:keys [db] :as cofx} result hashed-password]
|
||||
(let [{:keys [error]} (types/json->clj result)]
|
||||
(if (not (string/blank? error))
|
||||
(new-account-error cofx :password-error error)
|
||||
(let [{:keys [type seed private-key]} (:add-account db)]
|
||||
(case type
|
||||
:seed
|
||||
(import-new-account-seed cofx seed hashed-password)
|
||||
:key
|
||||
(import-new-account-private-key cofx private-key hashed-password)
|
||||
nil)))))
|
||||
|
||||
(rf/defn add-new-account-verify-password
|
||||
[{:keys [db]} hashed-password]
|
||||
{:db (assoc-in db [:add-account :step] :generating)
|
||||
::verify-password {:address (get-in db [:profile/profile :wallet-root-address])
|
||||
:hashed-password hashed-password}})
|
||||
|
||||
(rf/defn set-account-to-watch
|
||||
{:events [:wallet-legacy.accounts/set-account-to-watch]}
|
||||
[{:keys [db]} account]
|
||||
(let [name? (and (>= (count account) 3)
|
||||
(not (hex/valid-hex? account)))]
|
||||
(log/debug "[wallet] set-account-to-watch" account
|
||||
"name?" name?)
|
||||
(cond-> {:db (assoc-in db [:add-account :address] account)}
|
||||
name?
|
||||
(assoc ::ens.core/resolve-address
|
||||
[(chain/chain-id db)
|
||||
(stateofus/ens-name-parse account)
|
||||
#(re-frame/dispatch
|
||||
[:wallet-legacy.accounts/set-account-to-watch %])]))))
|
||||
|
||||
(rf/defn add-new-account
|
||||
{:events [:wallet-legacy.accounts/add-new-account]}
|
||||
[{:keys [db] :as cofx} hashed-password]
|
||||
(let [{:keys [type step]} (:add-account db)]
|
||||
(log/debug "[wallet] add-new-account"
|
||||
"type" type
|
||||
"step" step)
|
||||
(when-not step
|
||||
(case type
|
||||
:watch
|
||||
(add-watch-account cofx)
|
||||
:generate
|
||||
(generate-new-account cofx hashed-password)
|
||||
(:seed :key)
|
||||
(add-new-account-verify-password cofx hashed-password)
|
||||
nil))))
|
||||
|
||||
(rf/defn save-account
|
||||
{:events [:wallet-legacy.accounts/save-account]}
|
||||
[{:keys [db]} account {:keys [name color hidden]}]
|
||||
(let [accounts (:profile/wallet-accounts db)
|
||||
new-account (cond-> account
|
||||
name (assoc :name name)
|
||||
color (assoc :color color)
|
||||
(not (nil? hidden)) (assoc :hidden hidden))
|
||||
new-accounts (replace {account new-account} accounts)]
|
||||
{:json-rpc/call [{:method "accounts_saveAccount"
|
||||
:params [new-account]
|
||||
:on-success #()}]
|
||||
:db (assoc db :profile/wallet-accounts new-accounts)}))
|
||||
|
||||
(rf/defn delete-account
|
||||
{:events [:wallet-legacy.accounts/delete-account]}
|
||||
[{:keys [db] :as cofx} account]
|
||||
(let [accounts (:profile/wallet-accounts db)
|
||||
new-accounts (vec (remove #(= account %) accounts))
|
||||
deleted-address (:address account)]
|
||||
(rf/merge cofx
|
||||
{:json-rpc/call [{:method "accounts_deleteAccount"
|
||||
:params [(:address account)]
|
||||
:on-success #()}]
|
||||
:db (-> db
|
||||
(assoc :profile/wallet-accounts new-accounts)
|
||||
(update-in [:wallet-legacy :accounts] dissoc deleted-address))}
|
||||
(navigation/pop-to-root :shell-stack))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:key-storage/delete-imported-key
|
||||
(fn [{:keys [key-uid address password on-success on-error]}]
|
||||
(let [hashed-pass (native-module/sha3 (security/safe-unmask-data password))]
|
||||
(native-module/delete-imported-key
|
||||
key-uid
|
||||
(string/lower-case (subs address 2))
|
||||
hashed-pass
|
||||
(fn [result]
|
||||
(let [{:keys [error]} (types/json->clj result)]
|
||||
(if-not (string/blank? error)
|
||||
(on-error error)
|
||||
(on-success))))))))
|
||||
|
||||
(rf/defn delete-account-key
|
||||
{:events [:wallet-legacy.accounts/delete-key]}
|
||||
[{:keys [db] :as cofx} account password on-error]
|
||||
(let [deleted-address (:address account)
|
||||
dapps-address (get-in cofx [:db :profile/profile :dapps-address])]
|
||||
(if (= (string/lower-case dapps-address) (string/lower-case deleted-address))
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/warning)
|
||||
:content (i18n/label :t/account-is-used)}}
|
||||
{:key-storage/delete-imported-key
|
||||
{:key-uid (get-in db [:profile/profile :key-uid])
|
||||
:address (:address account)
|
||||
:password password
|
||||
:on-success #(do
|
||||
(re-frame/dispatch [:hide-popover])
|
||||
(re-frame/dispatch [:wallet-legacy.accounts/delete-account account]))
|
||||
:on-error on-error}})))
|
||||
|
||||
(rf/defn view-only-qr-scanner-result
|
||||
{:events [:wallet-legacy.add-new/qr-scanner-result]}
|
||||
[{db :db :as cofx} data _]
|
||||
(let [address (:address (eip681/parse-uri data))]
|
||||
(rf/merge cofx
|
||||
(merge {:db (-> db
|
||||
(assoc-in [:add-account :scanned-address] address)
|
||||
(assoc-in [:add-account :address] address))}
|
||||
(when-not address
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/error)
|
||||
:content (i18n/label :t/invalid-address-qr-code)}}))
|
||||
(navigation/navigate-back))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:list.selection/open-share
|
||||
(fn [obj]
|
||||
(list-selection/open-share obj)))
|
||||
|
||||
(rf/defn wallet-accounts-share
|
||||
{:events [:wallet-legacy.accounts/share]}
|
||||
[_ address]
|
||||
{:list.selection/open-share {:message (eip55/address->checksum address)}})
|
|
@ -1,182 +0,0 @@
|
|||
(ns legacy.status-im.wallet.choose-recipient.core
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[legacy.status-im.contact.db :as contact.db]
|
||||
[legacy.status-im.ethereum.ens :as ens]
|
||||
[legacy.status-im.ethereum.tokens :as tokens]
|
||||
[legacy.status-im.qr-scanner.core :as qr-scaner]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.common.router :as router]
|
||||
[status-im.common.universal-links :as links]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
|
||||
;; FIXME(Ferossgp): Should be part of QR scanner not wallet
|
||||
(rf/defn toggle-flashlight
|
||||
{:events [:wallet-legacy/toggle-flashlight]}
|
||||
[{:keys [db]}]
|
||||
(let [flashlight-state (get-in db [:wallet-legacy :send-transaction :camera-flashlight])
|
||||
toggled-state (if (= :on flashlight-state) :off :on)]
|
||||
{:db (assoc-in db [:wallet-legacy :send-transaction :camera-flashlight] toggled-state)}))
|
||||
|
||||
(defn- find-address-name
|
||||
[db address]
|
||||
(:name (contact.db/find-contact-by-address (:contacts/contacts db) address)))
|
||||
|
||||
(rf/defn set-recipient
|
||||
{:events [:wallet-legacy.send/set-recipient]}
|
||||
[{:keys [db]} address]
|
||||
{:db (-> db
|
||||
(dissoc :wallet-legacy/recipient)
|
||||
(assoc-in [:ui/search :recipient-filter] nil)
|
||||
(assoc-in [:wallet-legacy/prepare-transaction :to] address))
|
||||
:dispatch [:navigate-back]})
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-addresses
|
||||
(fn [{:keys [chain-id ens-names callback]}]
|
||||
;; resolve all addresses then call the callback function with the array of
|
||||
;;addresses as parameter
|
||||
(-> (js/Promise.all
|
||||
(clj->js (mapv (fn [ens-name]
|
||||
(js/Promise.
|
||||
(fn [resolve-fn _]
|
||||
(ens/address chain-id ens-name resolve-fn))))
|
||||
ens-names)))
|
||||
(.then callback)
|
||||
(.catch (fn [error]
|
||||
(js/console.log error))))))
|
||||
|
||||
(defn- fill-prepare-transaction-details
|
||||
[db
|
||||
{address :address
|
||||
name :name
|
||||
value :value
|
||||
sym :symbol
|
||||
gas :gas
|
||||
gas-price :gasPrice
|
||||
gas-limit :gasLimit
|
||||
:or {sym :ETH}}
|
||||
all-tokens]
|
||||
(assoc db
|
||||
:wallet-legacy/prepare-transaction
|
||||
(cond-> {:to address
|
||||
:to-name (or name (find-address-name db address))
|
||||
:from (wallet.utils/get-default-account
|
||||
(get db :profile/wallet-accounts))}
|
||||
gas (assoc :gas (money/bignumber gas))
|
||||
gas-limit (assoc :gas (money/bignumber gas-limit))
|
||||
gas-price (assoc :gasPrice (money/bignumber gas-price))
|
||||
value (assoc :amount-text
|
||||
(if (= :ETH sym)
|
||||
(str (money/internal->formatted value sym (get all-tokens sym)))
|
||||
(str value)))
|
||||
sym (assoc :symbol sym))))
|
||||
|
||||
(defn parse-eth-value
|
||||
"Takes a map as returned by `parse-uri` and returns value as BigNumber"
|
||||
[s]
|
||||
(when (string? s)
|
||||
(let [eth? (string/ends-with? s "ETH")
|
||||
^js n (money/bignumber (string/replace s "ETH" ""))]
|
||||
(if eth? (.times n 1e18) n))))
|
||||
|
||||
(defn extract-request-details
|
||||
"Return a map encapsulating request details (with keys `value`, `address` and `symbol`) from a parsed URI.
|
||||
Supports ethereum and erc20 token."
|
||||
[{:keys [value address function-name function-arguments] :as details} all-tokens]
|
||||
(when address
|
||||
(merge details
|
||||
(case function-name
|
||||
nil
|
||||
{:value (parse-eth-value value)
|
||||
:symbol :ETH
|
||||
:address address}
|
||||
"transfer"
|
||||
{:value (money/bignumber (:uint256 function-arguments))
|
||||
:symbol (:symbol (tokens/address->token all-tokens address))
|
||||
:address (:address function-arguments)}
|
||||
nil))))
|
||||
|
||||
(rf/defn request-uri-parsed
|
||||
{:events [:wallet-legacy/request-uri-parsed]}
|
||||
[{{:networks/keys [networks current-network]
|
||||
:wallet-legacy/keys [all-tokens]
|
||||
:as db}
|
||||
:db}
|
||||
{:keys [chain-id] :as data}
|
||||
uri]
|
||||
(let [{:keys [address gasPrice] :as details}
|
||||
(extract-request-details data all-tokens)]
|
||||
(if address
|
||||
(if (:wallet-legacy/recipient db)
|
||||
{:db (update db
|
||||
:wallet-legacy/recipient assoc
|
||||
:resolved-address address
|
||||
:address address)}
|
||||
(if (:wallet-legacy/prepare-transaction db)
|
||||
{:db (update db
|
||||
:wallet-legacy/prepare-transaction assoc
|
||||
:to address
|
||||
:to-name (find-address-name db address))}
|
||||
(let [current-chain-id (get-in networks [current-network :config :NetworkId])]
|
||||
(merge {:db (fill-prepare-transaction-details db details all-tokens)
|
||||
:dispatch [:open-modal :prepare-send-transaction]}
|
||||
(when-not gasPrice
|
||||
{:signing/update-gas-price
|
||||
{:success-callback
|
||||
#(re-frame/dispatch
|
||||
[:wallet-legacy.send/update-gas-price-success :wallet-legacy/prepare-transaction
|
||||
%])
|
||||
:network-id (get-in (chain/current-network db)
|
||||
[:config :NetworkId])}})
|
||||
(when (and chain-id (not= current-chain-id chain-id))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-chain-id
|
||||
{:data uri :chain current-chain-id})})))))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})})))
|
||||
|
||||
(rf/defn qr-scanner-allowed
|
||||
{:events [:wallet-legacy.send/qr-scanner]}
|
||||
[{:keys [db] :as cofx} options]
|
||||
(rf/merge cofx
|
||||
(bottom-sheet/hide-bottom-sheet-old)
|
||||
(qr-scaner/scan-qr-code options)))
|
||||
|
||||
(rf/defn parse-eip681-uri-and-resolve-ens
|
||||
{:events [:wallet-legacy/parse-eip681-uri-and-resolve-ens]}
|
||||
[{db :db :as cofx} {:keys [message uri paths ens-names error]} ignore-url]
|
||||
(if-not error
|
||||
;; first we get a vector of ens-names to resolve and a vector of paths of these names
|
||||
(if (empty? ens-names)
|
||||
;; if there are no ens-names, we dispatch request-uri-parsed immediately
|
||||
(request-uri-parsed cofx message uri)
|
||||
{::resolve-addresses
|
||||
{:chain-id (chain/chain-id db)
|
||||
:ens-names ens-names
|
||||
:callback
|
||||
(fn [addresses]
|
||||
(re-frame/dispatch
|
||||
[:wallet-legacy/request-uri-parsed
|
||||
;; we replace ens-names at their path in the message by their actual address
|
||||
(reduce (fn [message [path address]]
|
||||
(assoc-in message path address))
|
||||
message
|
||||
(map vector paths addresses)) uri]))}})
|
||||
(if (and (url/url? uri) (not ignore-url))
|
||||
(if (links/universal-link? uri)
|
||||
{:dispatch [:universal-links/handle-url uri]}
|
||||
{:browser/show-browser-selection uri})
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})})))
|
||||
|
||||
(rf/defn qr-scanner-result
|
||||
{:events [:wallet-legacy.send/qr-scanner-result]}
|
||||
[cofx data {:keys [ignore-url]}]
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(parse-eip681-uri-and-resolve-ens (router/match-eip681 data) ignore-url)))
|
File diff suppressed because it is too large
Load Diff
|
@ -1,128 +0,0 @@
|
|||
(ns legacy.status-im.wallet.custom-tokens.core
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
[legacy.status-im.wallet.prices :as prices]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[utils.address :as address]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet-legacy.custom-token/contract-address-paste
|
||||
(fn []
|
||||
(react/get-from-clipboard
|
||||
#(re-frame/dispatch [:wallet-legacy.custom-token/contract-address-is-pasted (string/trim %)]))))
|
||||
|
||||
(defn field-exists?
|
||||
[{:wallet-legacy/keys [all-tokens]} field-key field-value]
|
||||
(some #(= field-value (get % field-key))
|
||||
(vals all-tokens)))
|
||||
|
||||
(defn token-in-list?
|
||||
[{:wallet-legacy/keys [all-tokens]} contract]
|
||||
(not (nil? (get all-tokens (string/lower-case contract)))))
|
||||
|
||||
(rf/defn contract-address-is-changed
|
||||
{:events [:wallet-legacy.custom-token/contract-address-is-pasted]}
|
||||
[{:keys [db]} contract]
|
||||
(if (address/address? contract)
|
||||
(if (token-in-list? db contract)
|
||||
{:db (assoc db
|
||||
:wallet-legacy/custom-token-screen
|
||||
{:contract contract :error (i18n/label :t/already-have-asset)})}
|
||||
{:db (assoc db
|
||||
:wallet-legacy/custom-token-screen
|
||||
{:contract contract :in-progress? true})
|
||||
:json-rpc/call [{:method "wallet_discoverToken"
|
||||
:params [(chain/chain-id db) contract]
|
||||
:on-success #(re-frame/dispatch
|
||||
[:wallet-legacy.custom-token/token-discover-result %])
|
||||
:on-error #(re-frame/dispatch [:wallet-legacy.custom-token/not-supported])}]})
|
||||
{:db (assoc db
|
||||
:wallet-legacy/custom-token-screen
|
||||
{:contract contract
|
||||
:error (i18n/label :t/wrong-address)})}))
|
||||
|
||||
(rf/defn token-discover-result
|
||||
{:events [:wallet-legacy.custom-token/token-discover-result]}
|
||||
[{:keys [db]} {:keys [name symbol decimals]}]
|
||||
(let [symbol-exists? (field-exists? db :symbol (keyword symbol))]
|
||||
{:db (update db
|
||||
:wallet-legacy/custom-token-screen
|
||||
merge
|
||||
{:name name
|
||||
:symbol symbol
|
||||
:error-symbol (when symbol-exists?
|
||||
(i18n/label :t/you-already-have-an-asset {:value symbol}))
|
||||
:decimals (str decimals)
|
||||
:in-progress? nil})}))
|
||||
|
||||
(rf/defn not-supported
|
||||
{:events [:wallet-legacy.custom-token/not-supported]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc-in db [:wallet-legacy/custom-token-screen :in-progress?] nil)
|
||||
:effects.utils/show-popup {:content (i18n/label :t/contract-isnt-supported)}})
|
||||
|
||||
(rf/defn add-custom-token
|
||||
{:events [:wallet-legacy.custom-token.ui/add-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [contract name symbol decimals]} (get db :wallet-legacy/custom-token-screen)
|
||||
symbol (keyword symbol)
|
||||
new-token {:address contract
|
||||
:name name
|
||||
:symbol symbol
|
||||
:decimals (int decimals)
|
||||
:color (rand-nth colors/chat-colors)}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:wallet-legacy/all-tokens contract]
|
||||
(assoc new-token :custom? true))
|
||||
:json-rpc/call [{:method "wallet_addCustomToken"
|
||||
:params [new-token]
|
||||
:on-success #()}]}
|
||||
(wallet/add-custom-token new-token)
|
||||
(prices/update-prices)
|
||||
(navigation/navigate-back))))
|
||||
|
||||
(rf/defn remove-custom-token
|
||||
{:events [:wallet-legacy.custom-token.ui/remove-pressed]}
|
||||
[{:keys [db] :as cofx} {:keys [address] :as token} navigate-back?]
|
||||
(rf/merge cofx
|
||||
{:db (update db :wallet-legacy/all-tokens dissoc address)
|
||||
:json-rpc/call [{:method "wallet_deleteCustomToken"
|
||||
:params [address]
|
||||
:on-success #()}]}
|
||||
(wallet/remove-custom-token token)
|
||||
(when navigate-back?
|
||||
(navigation/navigate-back))))
|
||||
|
||||
(rf/defn field-is-edited
|
||||
{:events [:wallet-legacy.custom-token.ui/field-is-edited]}
|
||||
[{:keys [db] :as cofx} field-key value]
|
||||
(case field-key
|
||||
:contract (contract-address-is-changed cofx value)
|
||||
:name {:db (update db
|
||||
:wallet-legacy/custom-token-screen
|
||||
merge
|
||||
{field-key
|
||||
value
|
||||
:error-name
|
||||
(when (field-exists? db field-key value)
|
||||
(i18n/label :t/you-already-have-an-asset
|
||||
{:value value}))})}
|
||||
:symbol {:db (update db
|
||||
:wallet-legacy/custom-token-screen
|
||||
merge
|
||||
{field-key
|
||||
value
|
||||
:error-symbol
|
||||
(when (field-exists? db field-key (keyword value))
|
||||
(i18n/label :t/you-already-have-an-asset {:value value}))})}
|
||||
:decimals {:db (assoc-in db
|
||||
[:wallet-legacy/custom-token-screen :decimals]
|
||||
value)}))
|
|
@ -1,55 +0,0 @@
|
|||
(ns legacy.status-im.wallet.db
|
||||
(:require
|
||||
[legacy.status-im.utils.priority-map :refer [empty-transaction-map]]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]))
|
||||
|
||||
(defn- too-precise-amount?
|
||||
"Checks if number has any extra digit beyond the allowed number of decimals.
|
||||
It does so by checking the number against its rounded value."
|
||||
[amount decimals]
|
||||
(let [^js bn (money/bignumber amount)]
|
||||
(not (.eq bn
|
||||
(.round bn decimals)))))
|
||||
|
||||
(defn parse-amount
|
||||
[amount decimals]
|
||||
(when-not (empty? amount)
|
||||
(let [normalized-amount (money/normalize amount)
|
||||
value (money/bignumber normalized-amount)]
|
||||
(cond
|
||||
(not (money/valid? value))
|
||||
{:error (i18n/label :t/validation-amount-invalid-number) :value value}
|
||||
|
||||
(too-precise-amount? normalized-amount decimals)
|
||||
{:error (i18n/label :t/validation-amount-is-too-precise {:decimals decimals}) :value value}
|
||||
|
||||
:else
|
||||
{:value value}))))
|
||||
|
||||
(def default-wallet-filters
|
||||
#{:inbound :outbound :pending :failed})
|
||||
|
||||
(def default-wallet
|
||||
{:filters default-wallet-filters})
|
||||
|
||||
(defn get-confirmations
|
||||
[{:keys [block]} current-block]
|
||||
(if (and current-block block)
|
||||
(inc (- current-block block))
|
||||
0))
|
||||
|
||||
(defn remove-transactions-since-block
|
||||
[accounts block]
|
||||
(reduce-kv (fn [acc account-address account]
|
||||
(assoc acc
|
||||
account-address
|
||||
(update account
|
||||
:transactions
|
||||
(fn [transactions]
|
||||
(into empty-transaction-map
|
||||
(drop-while (fn [[_ v]]
|
||||
(>= (int (:block v)) block))
|
||||
transactions))))))
|
||||
{}
|
||||
accounts))
|
|
@ -1,59 +0,0 @@
|
|||
(ns legacy.status-im.wallet.db-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
[legacy.status-im.wallet.db :as wallet.db]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]))
|
||||
|
||||
(deftest test-too-precise-amount?
|
||||
(testing "try both decimal and scientific or hex format"
|
||||
(is (false? (#'legacy.status-im.wallet.db/too-precise-amount? "100" 2)))
|
||||
(is (false? (#'legacy.status-im.wallet.db/too-precise-amount? "100" 0)))
|
||||
(is (true? (#'legacy.status-im.wallet.db/too-precise-amount? "100.1" 0)))
|
||||
(is (false? (#'legacy.status-im.wallet.db/too-precise-amount? "100.23" 2)))
|
||||
(is (true? (#'legacy.status-im.wallet.db/too-precise-amount? "100.233" 2)))
|
||||
(is (true? (#'legacy.status-im.wallet.db/too-precise-amount? "100.0000000000000000001" 18)))
|
||||
(is (false? (#'legacy.status-im.wallet.db/too-precise-amount? "100.000000000000000001" 18)))
|
||||
(is (false? (#'legacy.status-im.wallet.db/too-precise-amount? "1e-18" 18)))
|
||||
(is (true? (#'legacy.status-im.wallet.db/too-precise-amount? "1e-19" 18)))
|
||||
(is (true? (#'legacy.status-im.wallet.db/too-precise-amount? "0xa.a" 2))) ;; 0xa.a is 10.625
|
||||
(is (false? (#'legacy.status-im.wallet.db/too-precise-amount? "0xa.a" 3)))
|
||||
(is (false? (#'legacy.status-im.wallet.db/too-precise-amount? "1000" 3)))))
|
||||
|
||||
(defn- equal-results?
|
||||
[a b]
|
||||
(and (= (:error a) (:error b))
|
||||
(or (and (nil? (:amount a))
|
||||
(nil? (:amount b)))
|
||||
(.eq ^js (:amount a) (:amount b)))))
|
||||
|
||||
(deftest test-parse-amount
|
||||
(testing "test amount parsing"
|
||||
(is (equal-results? {:value (money/bignumber "100")} (wallet.db/parse-amount "100" 2)))
|
||||
(is (equal-results? {:value (money/bignumber "100")} (wallet.db/parse-amount "100" 0)))
|
||||
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 0})
|
||||
:value (money/bignumber "100.1")}
|
||||
(wallet.db/parse-amount "100.1" 0)))
|
||||
(is (equal-results? {:value (money/bignumber "100.23")} (wallet.db/parse-amount "100.23" 2)))
|
||||
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 2})
|
||||
:value (money/bignumber "100.233")}
|
||||
(wallet.db/parse-amount "100.233" 2)))
|
||||
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 18})
|
||||
:value (money/bignumber "100.0000000000000000001")}
|
||||
(wallet.db/parse-amount "100.0000000000000000001" 18)))
|
||||
(is (equal-results? {:value (money/bignumber "100.000000000000000001")}
|
||||
(wallet.db/parse-amount "100.000000000000000001" 18)))
|
||||
(is (equal-results? {:value (money/bignumber "1e-18")} (wallet.db/parse-amount "1e-18" 18)))
|
||||
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 18})
|
||||
:value (money/bignumber "1e-19")}
|
||||
(wallet.db/parse-amount "1e-19" 18)))
|
||||
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 2})
|
||||
:value (money/bignumber "10.625")}
|
||||
(wallet.db/parse-amount "0xa.a" 2)))
|
||||
(is (equal-results? {:value (money/bignumber "10.625")} (wallet.db/parse-amount "0xa.a" 3)))
|
||||
(is (equal-results? {:error (i18n/label :t/validation-amount-invalid-number)
|
||||
:value nil}
|
||||
(wallet.db/parse-amount "SOMETHING" 5)))
|
||||
(is (nil? (wallet.db/parse-amount nil 5)))
|
||||
(is (nil? (wallet.db/parse-amount "" 5)))
|
||||
(is (equal-results? {:value (money/bignumber "1000")} (wallet.db/parse-amount "1000" 3)))))
|
|
@ -1,77 +0,0 @@
|
|||
(ns legacy.status-im.wallet.prices
|
||||
(:require
|
||||
[clojure.set :as set]
|
||||
[legacy.status-im.ethereum.tokens :as tokens]
|
||||
[legacy.status-im.utils.currency :as currency]
|
||||
[legacy.status-im.utils.prices :as prices]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn assoc-error-message
|
||||
[db error-type err]
|
||||
(assoc-in db [:wallet-legacy :errors error-type] (or err :unknown-error)))
|
||||
|
||||
(defn clear-error-message
|
||||
[db error-type]
|
||||
(update-in db [:wallet-legacy :errors] dissoc error-type))
|
||||
|
||||
(defn tokens-symbols
|
||||
[visible-token-symbols all-tokens]
|
||||
(set/difference (set visible-token-symbols)
|
||||
(set (map :symbol (tokens/nfts-for all-tokens)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet-legacy/get-prices
|
||||
(fn [{:keys [from to mainnet? success-event error-event]}]
|
||||
(prices/get-prices from
|
||||
to
|
||||
mainnet?
|
||||
#(re-frame/dispatch [success-event %])
|
||||
#(re-frame/dispatch [error-event %]))))
|
||||
|
||||
(rf/defn on-update-prices-success
|
||||
{:events [::update-prices-success]}
|
||||
[{:keys [db]} prices]
|
||||
{:db (assoc db
|
||||
:prices prices
|
||||
:prices-loading? false)})
|
||||
|
||||
(rf/defn on-update-prices-fail
|
||||
{:events [::update-prices-fail]}
|
||||
[{:keys [db]} err]
|
||||
(log/debug "Unable to get prices: " err)
|
||||
{:db (-> db
|
||||
(assoc-error-message :prices-update :error-unable-to-get-prices)
|
||||
(assoc :prices-loading? false))})
|
||||
|
||||
(rf/defn update-prices
|
||||
{:events [:wallet-legacy.ui/pull-to-refresh]}
|
||||
[{{:keys [network-status :wallet-legacy/all-tokens]
|
||||
{:keys [currency :wallet-legacy/visible-tokens]
|
||||
:or {currency :usd}}
|
||||
:profile/profile
|
||||
:as db}
|
||||
:db}]
|
||||
(let [chain (chain/chain-keyword db)
|
||||
mainnet? (= :mainnet chain)
|
||||
assets (get visible-tokens chain #{})
|
||||
tokens (tokens-symbols assets all-tokens)
|
||||
currency (get currency/currencies currency)]
|
||||
(when (not= network-status :offline)
|
||||
{:wallet-legacy/get-prices
|
||||
{:from (if mainnet?
|
||||
(conj tokens "ETH")
|
||||
[(-> (tokens/native-currency (chain/get-current-network db))
|
||||
(wallet.utils/exchange-symbol))])
|
||||
:to [(:code currency)]
|
||||
:mainnet? mainnet?
|
||||
:success-event ::update-prices-success
|
||||
:error-event ::update-prices-fail}
|
||||
|
||||
:db
|
||||
(-> db
|
||||
(clear-error-message :prices-update)
|
||||
(assoc :prices-loading? true))})))
|
|
@ -1,107 +0,0 @@
|
|||
(ns legacy.status-im.wallet.recipient.core
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ethereum.ens :as ens]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.utils.random :as random]
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.common.json-rpc.events :as json-rpc]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[utils.address :as address]
|
||||
[utils.ens.core :as utils.ens]
|
||||
[utils.ens.stateofus :as stateofus]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.string :as utils.string]))
|
||||
|
||||
;;NOTE we want to handle only last resolve
|
||||
(def resolve-last-id (atom nil))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-address
|
||||
(fn [{:keys [chain-id ens-name cb]}]
|
||||
(ens/address chain-id ens-name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet-legacy.recipient/address-paste
|
||||
(fn []
|
||||
(react/get-from-clipboard
|
||||
#(re-frame/dispatch [:wallet-legacy.recipient/address-changed (string/trim %)]))))
|
||||
|
||||
(rf/defn address-paste-pressed
|
||||
{:events [:wallet-legacy.recipient/address-paste-pressed]}
|
||||
[_]
|
||||
{:wallet-legacy.recipient/address-paste nil})
|
||||
|
||||
(rf/defn set-recipient
|
||||
{:events [::recipient-address-resolved]}
|
||||
[{:keys [db] :as cofx} raw-recipient id]
|
||||
(when (or (not id) (= id @resolve-last-id))
|
||||
(reset! resolve-last-id nil)
|
||||
(let [recipient (utils.string/safe-trim raw-recipient)]
|
||||
(cond
|
||||
(address/address? recipient)
|
||||
(let [checksum (eip55/address->checksum recipient)]
|
||||
(if (eip55/valid-address-checksum? checksum)
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet-legacy/recipient :searching] false)
|
||||
(assoc-in [:wallet-legacy/recipient :resolved-address] checksum))}
|
||||
(json-rpc/call
|
||||
{:method "eth_getCode"
|
||||
:params [checksum "latest"]
|
||||
:on-success #(when (not= "0x" %)
|
||||
(utils/show-popup (i18n/label :t/warning)
|
||||
(i18n/label
|
||||
:t/warning-sending-to-contract-descr)))
|
||||
:number-of-retries 3}))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address-checksum {:data recipient})
|
||||
:db (assoc-in db [:wallet-legacy/recipient :searching] false)}))
|
||||
(and (not (string/blank? recipient))
|
||||
(not (string/starts-with? recipient "0x"))
|
||||
(utils.ens/valid-eth-name-prefix? recipient))
|
||||
(let [ens-name (if (= (.indexOf ^js recipient ".") -1)
|
||||
(stateofus/subdomain recipient)
|
||||
recipient)]
|
||||
(if (utils.ens/is-valid-eth-name? ens-name)
|
||||
(do
|
||||
(reset! resolve-last-id (random/id))
|
||||
{::resolve-address
|
||||
{:chain-id (chain/chain-id db)
|
||||
:ens-name ens-name
|
||||
:cb #(re-frame/dispatch [::recipient-address-resolved % @resolve-last-id])}})
|
||||
{:db (assoc-in db [:wallet-legacy/recipient :searching] false)}))
|
||||
:else
|
||||
{:db (assoc-in db [:wallet-legacy/recipient :searching] false)}))))
|
||||
|
||||
(rf/defn address-changed
|
||||
{:events [:wallet-legacy.recipient/address-changed]}
|
||||
[{:keys [db] :as cofx} new-identity]
|
||||
(rf/merge cofx
|
||||
{:db (update db
|
||||
:wallet-legacy/recipient assoc
|
||||
:address new-identity
|
||||
:resolved-address nil
|
||||
:searching true)}
|
||||
(set-recipient new-identity nil)))
|
||||
|
||||
(rf/defn recipient-modal-closed
|
||||
{:events [:wallet-legacy/recipient-modal-closed]}
|
||||
[{:keys [db]}]
|
||||
{:db (dissoc db :wallet-legacy/recipient)})
|
||||
|
||||
(rf/defn add-favourite
|
||||
{:events [:wallet-legacy/add-favourite]}
|
||||
[{:keys [db] :as cofx} address name]
|
||||
(let [new-favourite {:address address
|
||||
:name (or name "")
|
||||
:favourite true}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:wallet-legacy/favourites address] new-favourite)
|
||||
:json-rpc/call [{:method "wallet_addSavedAddress"
|
||||
:params [new-favourite]
|
||||
:on-success #()}]}
|
||||
(navigation/navigate-back))))
|
|
@ -1,52 +0,0 @@
|
|||
(ns legacy.status-im.wallet.swap.core
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[re-frame.db :as re-frame.db]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;; "source? true" means we are selecting the source asset. false implies
|
||||
;; selection of sink asset."
|
||||
(re-frame/reg-event-fx ::open-asset-selector-modal
|
||||
(fn [{:keys [db]} [source?]]
|
||||
{:db (assoc db :wallet-legacy/modal-selecting-source-token? source?)
|
||||
:fx [[:dispatch [:open-modal :swap-asset-selector {}]]]}))
|
||||
|
||||
(rf/defn set-from-token
|
||||
{:events [::set-from-token]}
|
||||
[{:keys [db]} from-symbol]
|
||||
(rf/merge {:db (assoc db :wallet-legacy/swap-from-token from-symbol)}
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(rf/defn set-to-token
|
||||
{:events [::set-to-token]}
|
||||
[{:keys [db]} to-symbol]
|
||||
(rf/merge {:db (assoc db :wallet-legacy/swap-to-token to-symbol)}
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(rf/defn set-from-token-amount
|
||||
[{:keys [db]} from-amount]
|
||||
{:db (assoc db :wallet-legacy/swap-from-token-amount from-amount)})
|
||||
|
||||
(rf/defn set-max-from-token-amount
|
||||
[{:keys [db]} _]
|
||||
{:db (assoc db :wallet-legacy/swap-from-token-amount 0)})
|
||||
|
||||
(rf/defn switch-from-token-with-to
|
||||
{:events [::switch-from-token-with-to]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db
|
||||
:wallet-legacy/swap-from-token (:wallet-legacy/swap-to-token db)
|
||||
:wallet-legacy/swap-to-token (:wallet-legacy/swap-from-token db))})
|
||||
|
||||
(rf/defn set-advanced-mode
|
||||
{:events [::set-advanced-mode]}
|
||||
[{:keys [db]} mode]
|
||||
{:db (assoc db :wallet-legacy/swap-advanced-mode? mode)})
|
||||
|
||||
(comment
|
||||
(->> re-frame.db/app-db
|
||||
deref
|
||||
:wallet-legacy/all-tokens
|
||||
vals
|
||||
(map #(str (:name %) "-" (:symbol %)))))
|
|
@ -1,11 +0,0 @@
|
|||
(ns legacy.status-im.wallet.transactions-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is]]
|
||||
[legacy.status-im.ethereum.transactions.core :as transactions]))
|
||||
|
||||
(deftest get-transaction-details-url
|
||||
(is (= "https://etherscan.io/tx/asdfasdf"
|
||||
(transactions/get-transaction-details-url 1 "asdfasdf")))
|
||||
(is (nil? (transactions/get-transaction-details-url 7787878 "asdfasdfg")))
|
||||
(is (thrown? js/Error (transactions/get-transaction-details-url nil "asdfasdfg")))
|
||||
(is (thrown? js/Error (transactions/get-transaction-details-url 676868 1))))
|
|
@ -1,37 +0,0 @@
|
|||
(ns legacy.status-im.wallet.utils
|
||||
(:require
|
||||
[utils.money :as money]))
|
||||
|
||||
(defn format-amount
|
||||
[amount decimals]
|
||||
(-> amount
|
||||
(or (money/bignumber 0))
|
||||
(money/token->unit decimals)
|
||||
money/to-fixed))
|
||||
|
||||
;;NOTE(goranjovic) - we are internally using symbol ETH for native currencies of any ethereum network
|
||||
;; some sidechains have different names for this native currency, which we handle with `symbol-display`
|
||||
;; override.
|
||||
(defn display-symbol
|
||||
[m]
|
||||
(when-let [some-symbol (or (:symbol-display m) (:symbol m))]
|
||||
(name some-symbol)))
|
||||
|
||||
;;NOTE(goranjovic) - in addition to custom symbol display, some sidechain native currencies are listed
|
||||
;;under a different
|
||||
;; ticker on exchange networks. We handle that with `symbol-exchange` override.
|
||||
(defn exchange-symbol
|
||||
[m]
|
||||
(name (or (:symbol-exchange m)
|
||||
(:symbol-display m)
|
||||
(:symbol m))))
|
||||
|
||||
(defn get-default-account
|
||||
[accounts]
|
||||
(some #(when (:wallet %) %) accounts))
|
||||
|
||||
(defn default-address
|
||||
[db]
|
||||
(-> (get db :profile/wallet-accounts)
|
||||
get-default-account
|
||||
:address))
|
|
@ -13,7 +13,6 @@
|
|||
[legacy.status-im.pairing.core :as models.pairing]
|
||||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[legacy.status-im.visibility-status-updates.core :as models.visibility-status-updates]
|
||||
[legacy.status-im.wallet.core :as wallet]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.contacts.events :as models.contact]
|
||||
[status-im.contexts.chat.events :as chat.events]
|
||||
|
@ -175,8 +174,7 @@
|
|||
(do
|
||||
(js-delete response-js "accounts")
|
||||
(rf/merge cofx
|
||||
(process-next response-js sync-handler)
|
||||
(wallet/update-wallet-accounts (types/js->clj accounts))))
|
||||
(process-next response-js sync-handler)))
|
||||
|
||||
(seq settings)
|
||||
(do
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
(ns status-im.db
|
||||
(:require
|
||||
[legacy.status-im.fleet.core :as fleet]
|
||||
[legacy.status-im.wallet.db :as wallet.db]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.shell.activity-center.events :as activity-center]))
|
||||
|
||||
|
@ -19,8 +18,6 @@
|
|||
:sync-state :done
|
||||
:link-previews-whitelist []
|
||||
:app-state "active"
|
||||
:wallet-legacy wallet.db/default-wallet
|
||||
:wallet-legacy/all-tokens {}
|
||||
:peers-count 0
|
||||
:node-info {}
|
||||
:peers-summary []
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
[legacy.status-im.fleet.core :as fleet]
|
||||
[legacy.status-im.multiaccounts.db :as multiaccounts.db]
|
||||
[legacy.status-im.utils.currency :as currency]
|
||||
[legacy.status-im.wallet.utils :as wallet.utils]
|
||||
[quo.theme :as theme]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.common.pixel-ratio :as pixel-ratio]
|
||||
|
@ -126,9 +125,9 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:multiaccount/default-account
|
||||
:<- [:profile/wallet-accounts]
|
||||
:<- [:wallet/accounts]
|
||||
(fn [accounts]
|
||||
(wallet.utils/get-default-account accounts)))
|
||||
(first accounts)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:multiaccount/visible-accounts
|
||||
|
|
Loading…
Reference in New Issue