[#8666] Add account via BIP 44
Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
parent
fde55b80d0
commit
ba112a765b
|
@ -306,6 +306,7 @@
|
|||
:wallet-request-assets
|
||||
:choose-recipient
|
||||
:recent-recipients
|
||||
:select-account
|
||||
:wallet-send-transaction-request
|
||||
:contact-code
|
||||
:wallet-settings-hook)
|
||||
|
@ -317,6 +318,7 @@
|
|||
|
||||
colors/white)})
|
||||
bottom-background (when (#{:recent-recipients
|
||||
:select-account
|
||||
:wallet-send-assets
|
||||
:wallet-request-assets} current-view)
|
||||
[view {:background-color colors/white
|
||||
|
|
|
@ -244,6 +244,7 @@ var TopLevel = {
|
|||
"messaging" : function () {},
|
||||
"method" : function () {},
|
||||
"minus" : function () {},
|
||||
"plus" : function () {},
|
||||
"mkdir" : function () {},
|
||||
"module" : function () {},
|
||||
"moveFile" : function () {},
|
||||
|
@ -563,5 +564,9 @@ var TopLevel = {
|
|||
"createAppContainer" : function () {},
|
||||
"useScreens" : function () {},
|
||||
"multiAccountGenerateAndDeriveAddresses" : function () {},
|
||||
"multiAccountStoreDerived" : function () {}
|
||||
"multiAccountStoreDerived" : function () {},
|
||||
"multiAccountDeriveAddresses" : function () {},
|
||||
"multiAccountReset" : function () {},
|
||||
"multiAccountLoadAccount" : function () {},
|
||||
"multiAccountStoreAccount" : function () {}
|
||||
}
|
||||
|
|
|
@ -660,6 +660,82 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void multiAccountStoreAccount(final String json, final Callback callback) {
|
||||
Log.d(TAG, "multiAccountStoreAccount");
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.multiAccountStoreAccount(json);
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void multiAccountLoadAccount(final String json, final Callback callback) {
|
||||
Log.d(TAG, "multiAccountLoadAccount");
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.multiAccountLoadAccount(json);
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void multiAccountReset(final Callback callback) {
|
||||
Log.d(TAG, "multiAccountReset");
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.multiAccountReset();
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void multiAccountDeriveAddresses(final String json, final Callback callback) {
|
||||
Log.d(TAG, "multiAccountDeriveAddresses");
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.multiAccountDeriveAddresses(json);
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void multiAccountGenerateAndDeriveAddresses(final String json, final Callback callback) {
|
||||
Log.d(TAG, "multiAccountGenerateAndDeriveAddresses");
|
||||
|
|
|
@ -345,6 +345,35 @@ RCT_EXPORT_METHOD(multiAccountGenerateAndDeriveAddresses:(NSString *)json
|
|||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountStoreAccount
|
||||
RCT_EXPORT_METHOD(multiAccountStoreAccount:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"MultiAccountStoreAccount() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoMultiAccountStoreAccount(json);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountLoadAccount
|
||||
RCT_EXPORT_METHOD(multiAccountLoadAccount:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"MultiAccountLoadAccount() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoMultiAccountLoadAccount(json);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountReset
|
||||
RCT_EXPORT_METHOD(multiAccountReset:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"MultiAccountReset() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoMultiAccountReset();
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountStoreDerived
|
||||
RCT_EXPORT_METHOD(multiAccountStoreDerived:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
|
@ -355,6 +384,15 @@ RCT_EXPORT_METHOD(multiAccountStoreDerived:(NSString *)json
|
|||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountDeriveAddresses
|
||||
RCT_EXPORT_METHOD(multiAccountDeriveAddresses:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"MultiAccountDeriveAddresses() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoMultiAccountDeriveAddresses(json);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// login
|
||||
RCT_EXPORT_METHOD(login:(NSString *)json
|
||||
|
|
|
@ -60,8 +60,9 @@
|
|||
|
||||
(def assets-separator [react/view transactions-styles/asset-separator])
|
||||
|
||||
(defview choose-asset [nft?]
|
||||
(letsubs [assets [:wallet/visible-assets-with-amount]]
|
||||
(defn choose-asset [nft?] [react/view])
|
||||
;;TODO we'll need to specify address here
|
||||
#_(letsubs [assets [:wallet/visible-assets-with-amount]]
|
||||
[react/view
|
||||
[list/flat-list {:data (filter #(if nft?
|
||||
(:nft? %)
|
||||
|
@ -74,7 +75,7 @@
|
|||
:enableEmptySections true
|
||||
:separator assets-separator
|
||||
:keyboardShouldPersistTaps :always
|
||||
:bounces false}]]))
|
||||
:bounces false}]])
|
||||
|
||||
(defn choose-asset-suggestion []
|
||||
[choose-asset false])
|
||||
|
|
|
@ -237,6 +237,7 @@
|
|||
|
||||
(def ^:const status-create-address "status_createaddress")
|
||||
|
||||
(def ^:const path-root "m/44'/60'/0'/0")
|
||||
(def ^:const path-default-wallet "m/44'/60'/0'/0/0")
|
||||
(def ^:const path-whisper "m/43'/60'/1581'/0'/0")
|
||||
|
||||
|
|
|
@ -255,3 +255,4 @@
|
|||
(def v26 (update v25 :properties merge {:root-address {:type :string :optional true}
|
||||
:accounts {:type :string :optional true}}))
|
||||
|
||||
(def v27 (update v26 :properties merge {:latest-derived-path {:type :int :optional true}}))
|
||||
|
|
|
@ -128,6 +128,11 @@
|
|||
extension/v12
|
||||
account/v26])
|
||||
|
||||
(def v32 [network/v1
|
||||
bootnode/v4
|
||||
extension/v12
|
||||
account/v27])
|
||||
|
||||
;; put schemas ordered by version
|
||||
(def schemas [{:schema v1
|
||||
:schemaVersion 1
|
||||
|
@ -221,4 +226,7 @@
|
|||
:migration (constantly nil)}
|
||||
{:schema v31
|
||||
:schemaVersion 31
|
||||
:migration (constantly nil)}
|
||||
{:schema v32
|
||||
:schemaVersion 32
|
||||
:migration (constantly nil)}])
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
"status_startOneOnOneChat" {}
|
||||
"status_removeChat" {}
|
||||
"wallet_getTransfers" {}
|
||||
"wallet_getTransfersByAddress" {}
|
||||
"browsers_getBrowsers" {}
|
||||
"browsers_addBrowser" {}
|
||||
"browsers_deleteBrowser" {}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
(fx/defn new-block
|
||||
[{:keys [db] :as cofx} historical? block-number accounts]
|
||||
(let [{:keys [:wallet/all-tokens]} db
|
||||
accounts (get-in db [:multiaccount :accounts]) ;;TODO https://github.com/status-im/status-go/issues/1566
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))]
|
||||
|
@ -34,20 +35,23 @@
|
|||
(not historical?)
|
||||
(assoc :db (assoc db :ethereum/current-block block-number))
|
||||
|
||||
(not-empty accounts)
|
||||
(assoc ::transactions/get-transfers {:chain-tokens chain-tokens
|
||||
true ;(not-empty accounts) ;;TODO https://github.com/status-im/status-go/issues/1566
|
||||
(assoc ::transactions/get-transfers {:accounts accounts
|
||||
:chain-tokens chain-tokens
|
||||
:from-block block-number}))
|
||||
(transactions/check-watched-transactions))))
|
||||
|
||||
(fx/defn reorg
|
||||
[{:keys [db] :as cofx} block-number accounts]
|
||||
(let [{:keys [:wallet/all-tokens]} db
|
||||
accounts (get-in db [:multiaccount :accounts]) ;;TODO https://github.com/status-im/status-go/issues/1566
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))]
|
||||
{:db (update-in db [:wallet :transactions]
|
||||
wallet/remove-transactions-since-block block-number)
|
||||
::transactions/get-transfers {:chain-tokens chain-tokens
|
||||
::transactions/get-transfers {:accounts accounts
|
||||
:chain-tokens chain-tokens
|
||||
:from-block block-number}}))
|
||||
|
||||
(fx/defn new-wallet-event
|
||||
|
|
|
@ -119,36 +119,26 @@
|
|||
watched-transactions))))
|
||||
|
||||
(fx/defn add-transfer
|
||||
[{:keys [db] :as cofx} {:keys [hash id] :as transfer}]
|
||||
(let [transfer-by-hash (get-in db [:wallet :transactions hash])
|
||||
transfer-by-id (get-in db [:wallet :transaction id])
|
||||
unique-id (when-not (or transfer-by-id
|
||||
(= transfer transfer-by-hash))
|
||||
[{:keys [db] :as cofx} {:keys [hash id] :as transfer} address]
|
||||
(let [transfer-by-hash (get-in db [:wallet :accounts address :transactions hash])]
|
||||
;;transfer-by-id (get-in db [:wallet :transaction id]) ;; TODO didn't found any usage of this
|
||||
(when-let [unique-id (when (not= transfer transfer-by-hash) ;(or transfer-by-id)
|
||||
(if (and transfer-by-hash
|
||||
(not (= :pending
|
||||
(:type transfer-by-hash))))
|
||||
id
|
||||
hash))]
|
||||
(when unique-id
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:wallet :transactions unique-id]
|
||||
{:db (assoc-in db [:wallet :accounts address :transactions unique-id]
|
||||
(assoc transfer :hash unique-id))}
|
||||
(check-transaction transfer)))))
|
||||
|
||||
(fx/defn new-transfers
|
||||
{:events [::new-transfers]}
|
||||
[{:keys [db] :as cofx} transfers]
|
||||
(let [add-transfers-fx (map add-transfer transfers)]
|
||||
[{:keys [db] :as cofx} address transfers]
|
||||
(let [add-transfers-fx (map #(add-transfer % address) transfers)]
|
||||
(apply fx/merge cofx (conj add-transfers-fx
|
||||
wallet/update-balances))))
|
||||
|
||||
(fx/defn handle-history
|
||||
[{:keys [db] :as cofx} transactions]
|
||||
(fx/merge cofx
|
||||
{:db (update-in db
|
||||
[:wallet :transactions]
|
||||
#(merge transactions %))}
|
||||
wallet/update-balances))
|
||||
(wallet/update-balances [address])))))
|
||||
|
||||
(fx/defn handle-token-history
|
||||
[{:keys [db]} transactions]
|
||||
|
@ -158,21 +148,22 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::get-transfers
|
||||
(fn [{:keys [chain-tokens from-block to-block]
|
||||
(fn [{:keys [accounts chain-tokens from-block to-block]
|
||||
:or {from-block "0"
|
||||
to-block nil}}]
|
||||
;; start inbound token transaction subscriptions
|
||||
;; outbound token transactions are already caught in new blocks filter
|
||||
(doseq [{:keys [address]} accounts]
|
||||
(json-rpc/call
|
||||
{:method "wallet_getTransfers"
|
||||
:params [(encode/uint from-block) (encode/uint to-block)]
|
||||
:on-success #(re-frame/dispatch
|
||||
[::new-transfers (enrich-transfers chain-tokens %)])})))
|
||||
{:method "wallet_getTransfersByAddress"
|
||||
:params [address (encode/uint from-block) (encode/uint to-block)]
|
||||
:on-success #(re-frame/dispatch [::new-transfers address (enrich-transfers chain-tokens %)])}))))
|
||||
|
||||
(fx/defn initialize
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [:wallet/all-tokens]} db
|
||||
(let [accounts (get-in db [:multiaccount :accounts]) ;;TODO https://github.com/status-im/status-go/issues/1566
|
||||
{:keys [:wallet/all-tokens]} db
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))]
|
||||
{::get-transfers {:chain-tokens chain-tokens}}))
|
||||
{::get-transfers {:accounts accounts :chain-tokens chain-tokens}}))
|
||||
|
|
|
@ -1788,12 +1788,6 @@
|
|||
(fn [cofx [_ id handler]]
|
||||
(ethereum.subscriptions/register-subscription cofx id handler)))
|
||||
|
||||
;; ethereum transactions events
|
||||
(handlers/register-handler-fx
|
||||
:ethereum.transactions.callback/fetch-history-success
|
||||
(fn [cofx [_ transactions]]
|
||||
(ethereum.transactions/handle-history cofx transactions)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:ethereum.transactions.callback/etherscan-error
|
||||
(fn [cofx [event error]]
|
||||
|
@ -1834,8 +1828,8 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:wallet/token-found
|
||||
(fn [cofx [_ symbol balance]]
|
||||
(wallet/configure-token-balance-and-visibility cofx symbol balance)))
|
||||
(fn [cofx [_ address symbol balance]]
|
||||
(wallet/configure-token-balance-and-visibility cofx address symbol balance)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.settings.ui/navigate-back-pressed
|
||||
|
@ -1844,12 +1838,12 @@
|
|||
(when on-close
|
||||
{:dispatch on-close})
|
||||
(navigation/navigate-back)
|
||||
(wallet/update-balances))))
|
||||
(wallet/update-balances nil))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.callback/update-balance-success
|
||||
(fn [cofx [_ balance]]
|
||||
(wallet/update-balance cofx balance)))
|
||||
(fn [cofx [_ address balance]]
|
||||
(wallet/update-balance cofx address balance)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.callback/update-balance-fail
|
||||
|
@ -1858,8 +1852,8 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.callback/update-token-balance-success
|
||||
(fn [cofx [_ symbol balance]]
|
||||
(wallet/update-token-balance cofx symbol balance)))
|
||||
(fn [cofx [_ address symbol balance]]
|
||||
(wallet/update-token-balance cofx address symbol balance)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.callback/update-token-balance-fail
|
||||
|
@ -1878,8 +1872,8 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.ui/show-transaction-details
|
||||
(fn [cofx [_ hash]]
|
||||
(wallet/open-transaction-details cofx hash)))
|
||||
(fn [cofx [_ hash address]]
|
||||
(wallet/open-transaction-details cofx hash address)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.setup.ui/navigate-back-pressed
|
||||
|
|
|
@ -48,11 +48,13 @@
|
|||
|
||||
(defn create-multiaccount! [{:keys [id password]}]
|
||||
(if id
|
||||
(do
|
||||
;(status/multiaccount-store-account id password #()) ;; TODO if i add this, i'm unable to login after
|
||||
(status/multiaccount-store-derived
|
||||
id
|
||||
[constants/path-whisper constants/path-default-wallet]
|
||||
password
|
||||
#(re-frame/dispatch [:multiaccounts.create.callback/create-multiaccount-success password]))
|
||||
#(re-frame/dispatch [:multiaccounts.create.callback/create-multiaccount-success password])))
|
||||
(status/create-multiaccount
|
||||
password
|
||||
#(re-frame/dispatch [:multiaccounts.create.callback/create-multiaccount-success (types/json->clj %) password]))))
|
||||
|
@ -243,6 +245,7 @@
|
|||
new-multiaccount {;;multiaccount
|
||||
:root-address (:address multiaccount)
|
||||
:public-key publicKey
|
||||
:latest-derived-path 0
|
||||
:installation-id (get-in db [:multiaccounts/new-installation-id]) ;;TODO why can't we generate it here?
|
||||
:address address
|
||||
:name (gfycat/generate-gfy publicKey)
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
(fx/defn initialize-wallet [cofx]
|
||||
(fx/merge cofx
|
||||
(wallet/initialize-tokens)
|
||||
(wallet/update-balances)
|
||||
(wallet/update-balances nil)
|
||||
(wallet/update-prices)
|
||||
(transactions/initialize)))
|
||||
|
||||
|
|
|
@ -19,6 +19,18 @@
|
|||
(defn create-multiaccount [password callback]
|
||||
(native-module/create-account password callback))
|
||||
|
||||
(defn multiaccount-store-account [account-id password callback]
|
||||
(native-module/multiaccount-store-account account-id password callback))
|
||||
|
||||
(defn multiaccount-load-account [address password callback]
|
||||
(native-module/multiaccount-load-account address password callback))
|
||||
|
||||
(defn multiaccount-reset [callback]
|
||||
(native-module/multiaccount-reset callback))
|
||||
|
||||
(defn multiaccount-derive-addresses [account-id paths callback]
|
||||
(native-module/multiaccount-derive-addresses account-id paths callback))
|
||||
|
||||
(defn recover-multiaccount [passphrase password callback]
|
||||
(native-module/recover-account passphrase password callback))
|
||||
|
||||
|
|
|
@ -71,6 +71,32 @@
|
|||
:paths paths})
|
||||
on-result)))
|
||||
|
||||
(defn multiaccount-derive-addresses [account-id paths on-result]
|
||||
(when (and @node-started (status))
|
||||
(.multiAccountDeriveAddresses (status)
|
||||
(types/clj->json {:accountID account-id
|
||||
:paths paths})
|
||||
on-result)))
|
||||
|
||||
(defn multiaccount-store-account [account-id password on-result]
|
||||
(when (and @node-started (status))
|
||||
(.multiAccountStoreAccount (status)
|
||||
(types/clj->json {:accountID account-id
|
||||
:password password})
|
||||
on-result)))
|
||||
|
||||
(defn multiaccount-load-account [address password on-result]
|
||||
(when (and @node-started (status))
|
||||
(.multiAccountLoadAccount (status)
|
||||
(types/clj->json {:address address
|
||||
:password password})
|
||||
on-result)))
|
||||
|
||||
(defn multiaccount-reset [on-result]
|
||||
(when (and @node-started (status))
|
||||
(.multiAccountReset (status)
|
||||
on-result)))
|
||||
|
||||
(defn multiaccount-store-derived [account-id paths password on-result]
|
||||
(when (and @node-started (status))
|
||||
(.multiAccountStoreDerived (status)
|
||||
|
|
|
@ -137,7 +137,8 @@
|
|||
:token token
|
||||
:symbol symbol}))))))
|
||||
|
||||
(defn parse-tx-obj [db {:keys [to value data]}]
|
||||
(defn parse-tx-obj [db {:keys [from to value data]}]
|
||||
(merge {:from {:address from}}
|
||||
(if (nil? to)
|
||||
{:contact {:name (i18n/label :t/new-contract)}}
|
||||
(let [eth-value (when value (money/bignumber value))
|
||||
|
@ -154,7 +155,7 @@
|
|||
token
|
||||
:else
|
||||
{:to to
|
||||
:contact {:address (ethereum/normalized-address to)}}))))
|
||||
:contact {:address (ethereum/normalized-address to)}})))))
|
||||
|
||||
(defn prepare-tx [db {{:keys [data gas gasPrice] :as tx-obj} :tx-obj :as tx}]
|
||||
(merge
|
||||
|
|
|
@ -181,6 +181,7 @@
|
|||
(reg-root-key-sub :intro-wizard :intro-wizard)
|
||||
|
||||
(reg-root-key-sub :popover/popover :popover/popover)
|
||||
(reg-root-key-sub :generate-account :generate-account)
|
||||
|
||||
;;GENERAL ==============================================================================================================
|
||||
|
||||
|
@ -800,6 +801,7 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:chats/transaction-status
|
||||
;;TODO address here for transactions
|
||||
:<- [:wallet/transactions]
|
||||
:<- [:ethereum/current-block]
|
||||
(fn [[transactions current-block] [_ hash]]
|
||||
|
@ -965,8 +967,21 @@
|
|||
(re-frame/reg-sub
|
||||
:balance
|
||||
:<- [:wallet]
|
||||
(fn [wallet [_ address]]
|
||||
(get-in wallet [:accounts address :balance])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:balance-default
|
||||
:<- [:wallet]
|
||||
:<- [:multiaccount]
|
||||
(fn [[wallet {:keys [accounts]}]]
|
||||
(get-in wallet [:accounts (:address (ethereum/get-default-account accounts)) :balance])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:balances
|
||||
:<- [:wallet]
|
||||
(fn [wallet]
|
||||
(:balance wallet)))
|
||||
(map :balance (vals (:accounts wallet)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:price
|
||||
|
@ -986,20 +1001,6 @@
|
|||
(fn [settings]
|
||||
(or (get-in settings [:wallet :currency]) :usd)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:asset-value
|
||||
(fn [[_ fsym decimals tsym]]
|
||||
[(re-frame/subscribe [:balance])
|
||||
(re-frame/subscribe [:price fsym tsym])
|
||||
(re-frame/subscribe [:wallet/currency])])
|
||||
(fn [[balance price currency] [_ fsym decimals tsym]]
|
||||
(when (and balance price)
|
||||
(-> (money/internal->formatted (get balance fsym) fsym decimals)
|
||||
(money/crypto->fiat price)
|
||||
(money/with-precision 2)
|
||||
str
|
||||
(i18n/format-currency (:code currency))))))
|
||||
|
||||
(defn- get-balance-total-value
|
||||
[balance prices currency token->decimals]
|
||||
(reduce-kv (fn [acc symbol value]
|
||||
|
@ -1012,21 +1013,39 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:portfolio-value
|
||||
:<- [:balance]
|
||||
:<- [:balances]
|
||||
:<- [:prices]
|
||||
:<- [:wallet/currency]
|
||||
:<- [:ethereum/chain-keyword]
|
||||
:<- [:wallet/all-tokens]
|
||||
(fn [[balance prices currency chain all-tokens] [_ currency-code]]
|
||||
(fn [[balances prices currency chain all-tokens]]
|
||||
(if (and balances prices)
|
||||
(let [assets (tokens/tokens-for all-tokens chain)
|
||||
token->decimals (into {} (map #(vector (:symbol %) (:decimals %)) assets))
|
||||
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) false))
|
||||
"0"))
|
||||
"...")))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:account-portfolio-value
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:balance address])
|
||||
(re-frame/subscribe [:prices])
|
||||
(re-frame/subscribe [:wallet/currency])
|
||||
(re-frame/subscribe [:ethereum/chain-keyword])
|
||||
(re-frame/subscribe [:wallet/all-tokens])])
|
||||
(fn [[balance prices currency chain all-tokens]]
|
||||
(if (and balance prices)
|
||||
(let [assets (tokens/tokens-for all-tokens chain)
|
||||
token->decimals (into {} (map #(vector (:symbol %) (:decimals %)) assets))
|
||||
balance-total-value
|
||||
(get-balance-total-value balance
|
||||
prices
|
||||
(or currency-code
|
||||
(-> currency :code keyword))
|
||||
token->decimals)]
|
||||
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)
|
||||
|
@ -1050,12 +1069,6 @@
|
|||
(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/balance-loading?
|
||||
:<- [:wallet]
|
||||
(fn [wallet]
|
||||
(:balance-loading? wallet)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/error-message
|
||||
:<- [:wallet]
|
||||
|
@ -1082,18 +1095,19 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:wallet/visible-assets-with-amount
|
||||
:<- [:balance]
|
||||
:<- [:wallet/visible-assets]
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:balance address])
|
||||
(re-frame/subscribe [:wallet/visible-assets])])
|
||||
(fn [[balance visible-assets]]
|
||||
(map #(assoc % :amount (get balance (:symbol %))) visible-assets)))
|
||||
|
||||
(defn update-value [balance prices currency]
|
||||
(fn [{:keys [symbol decimals] :as token}]
|
||||
(defn update-value [prices currency]
|
||||
(fn [{:keys [symbol decimals amount] :as token}]
|
||||
(let [price (get-in prices [symbol (-> currency :code keyword) :price])]
|
||||
(assoc token
|
||||
:price price
|
||||
:value (when (and balance price)
|
||||
(-> (money/internal->formatted (get balance symbol) symbol decimals)
|
||||
:value (when (and amount price)
|
||||
(-> (money/internal->formatted amount symbol decimals)
|
||||
(money/crypto->fiat price)
|
||||
(money/with-precision 2)
|
||||
str
|
||||
|
@ -1101,19 +1115,45 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:wallet/visible-assets-with-values
|
||||
:<- [:wallet/visible-assets-with-amount]
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet/visible-assets-with-amount address])
|
||||
(re-frame/subscribe [:prices])
|
||||
(re-frame/subscribe [:wallet/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 [bl (get %2 sym)]
|
||||
(.plus %1 bl)
|
||||
%1)
|
||||
(money/bignumber 0)
|
||||
balances))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/all-visible-assets-with-amount
|
||||
:<- [:balances]
|
||||
:<- [:wallet/visible-assets]
|
||||
(fn [[balances visible-assets]]
|
||||
(map #(assoc % :amount (get-asset-amount balances (:symbol %))) visible-assets)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/all-visible-assets-with-values
|
||||
:<- [:wallet/all-visible-assets-with-amount]
|
||||
:<- [:prices]
|
||||
:<- [:wallet/currency]
|
||||
:<- [:balance]
|
||||
(fn [[assets prices currency balance]]
|
||||
(fn [[assets prices currency]]
|
||||
(let [{:keys [tokens nfts]} (group-by #(if (:nft? %) :nfts :tokens) assets)
|
||||
tokens-with-values (map (update-value balance prices currency) tokens)]
|
||||
tokens-with-values (map (update-value prices currency) tokens)]
|
||||
{:tokens tokens-with-values
|
||||
:nfts nfts})))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/transferrable-assets-with-amount
|
||||
:<- [:wallet/visible-assets-with-amount]
|
||||
(fn [[_ address]]
|
||||
(re-frame/subscribe [:wallet/visible-assets-with-amount address]))
|
||||
(fn [all-assets]
|
||||
(filter #(not (:nft? %)) all-assets)))
|
||||
|
||||
|
@ -1128,8 +1168,8 @@
|
|||
(re-frame/reg-sub
|
||||
:wallet/transactions
|
||||
:<- [:wallet]
|
||||
(fn [wallet]
|
||||
(get wallet :transactions)))
|
||||
(fn [wallet [_ address]]
|
||||
(get-in wallet [:accounts address :transactions])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/filters
|
||||
|
@ -1161,14 +1201,15 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/transactions
|
||||
:<- [:wallet/transactions]
|
||||
:<- [:contacts/contacts-by-address]
|
||||
:<- [:ethereum/native-currency]
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet/transactions address])
|
||||
(re-frame/subscribe [:contacts/contacts-by-address])
|
||||
(re-frame/subscribe [:ethereum/native-currency])])
|
||||
(fn [[transactions contacts native-currency]]
|
||||
(reduce (fn [acc [hash transaction]]
|
||||
(assoc acc
|
||||
hash
|
||||
(enrich-transaction transaction contacts native-currency)))
|
||||
(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)))
|
||||
|
||||
|
@ -1212,7 +1253,8 @@
|
|||
|
||||
(defn- enrich-transaction-for-list
|
||||
[filters
|
||||
{:keys [type from-contact from to-contact to hash timestamp] :as transaction}]
|
||||
{:keys [type from-contact from to-contact to hash timestamp] :as transaction}
|
||||
address]
|
||||
(when (filters type)
|
||||
(assoc (case type
|
||||
:inbound
|
||||
|
@ -1229,7 +1271,7 @@
|
|||
:contact to-contact
|
||||
:address to))
|
||||
:time-formatted (datetime/timestamp->time timestamp)
|
||||
:on-touch-fn #(re-frame/dispatch [:wallet.ui/show-transaction-details hash]))))
|
||||
:on-touch-fn #(re-frame/dispatch [:wallet.ui/show-transaction-details hash address]))))
|
||||
|
||||
(defn- group-transactions-by-date
|
||||
[transactions]
|
||||
|
@ -1243,33 +1285,28 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions.history/screen
|
||||
:<- [:wallet.transactions/transactions]
|
||||
:<- [:wallet/filters]
|
||||
:<- [:wallet.transactions/all-filters?]
|
||||
(fn [[transactions filters all-filters?]]
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet.transactions/transactions address])
|
||||
(re-frame/subscribe [:wallet/filters])
|
||||
(re-frame/subscribe [:wallet.transactions/all-filters?])])
|
||||
(fn [[transactions filters all-filters?] [_ address]]
|
||||
{:all-filters? all-filters?
|
||||
:transaction-history-sections
|
||||
(->> transactions
|
||||
vals
|
||||
(keep #(enrich-transaction-for-list filters %))
|
||||
(keep #(enrich-transaction-for-list filters % address))
|
||||
(group-transactions-by-date))}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/current-transaction
|
||||
:<- [:wallet]
|
||||
(fn [wallet]
|
||||
(:current-transaction wallet)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions.details/current-transaction
|
||||
:<- [:wallet.transactions/transactions]
|
||||
:<- [:wallet.transactions/current-transaction]
|
||||
:<- [:ethereum/native-currency]
|
||||
:<- [:ethereum/chain-keyword]
|
||||
(fn [[transactions current-transaction native-currency chain-keyword]]
|
||||
(fn [[_ hash address] _]
|
||||
[(re-frame/subscribe [:wallet.transactions/transactions address])
|
||||
(re-frame/subscribe [:ethereum/native-currency])
|
||||
(re-frame/subscribe [:ethereum/chain-keyword])])
|
||||
(fn [[transactions native-currency chain-keyword] [_ hash _]]
|
||||
(let [{:keys [gas-used gas-price hash timestamp type token value]
|
||||
:as transaction}
|
||||
(get transactions current-transaction)
|
||||
(get transactions hash)
|
||||
native-currency-text (name (or (:symbol-display native-currency)
|
||||
(:symbol native-currency)))]
|
||||
(when transaction
|
||||
|
@ -1301,8 +1338,9 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions.details/screen
|
||||
:<- [:wallet.transactions.details/current-transaction]
|
||||
:<- [:ethereum/current-block]
|
||||
(fn [[_ hash address] _]
|
||||
[(re-frame/subscribe [:wallet.transactions.details/current-transaction hash address])
|
||||
(re-frame/subscribe [:ethereum/current-block])])
|
||||
(fn [[transaction current-block]]
|
||||
(let [confirmations (wallet.db/get-confirmations transaction
|
||||
current-block)]
|
||||
|
@ -1358,11 +1396,12 @@
|
|||
(re-frame/reg-sub
|
||||
:wallet.send/transaction
|
||||
:<- [::send-transaction]
|
||||
:<- [:balance]
|
||||
(fn [[{:keys [amount symbol] :as transaction} balance]]
|
||||
:<- [:wallet]
|
||||
(fn [[{:keys [amount symbol from] :as transaction} wallet]]
|
||||
(let [balance (get-in wallet [:accounts from :balance])]
|
||||
(-> transaction
|
||||
(check-sufficient-funds balance symbol amount)
|
||||
(check-sufficient-gas balance symbol amount))))
|
||||
(check-sufficient-gas balance symbol amount)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/settings
|
||||
|
@ -1960,8 +1999,9 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:signing/amount-errors
|
||||
:<- [:signing/tx]
|
||||
:<- [:balance]
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:signing/tx])
|
||||
(re-frame/subscribe [:balance address])])
|
||||
(fn [[{:keys [amount token gas gasPrice approve?]} balance]]
|
||||
(if (and amount token (not approve?))
|
||||
(let [amount-bn (money/formatted->internal (money/bignumber amount) (:symbol token) (:decimals token))
|
||||
|
|
|
@ -57,3 +57,11 @@
|
|||
(def text-gray gray)
|
||||
|
||||
(def default-chat-color "#a187d5") ;; legacy
|
||||
|
||||
(def account-colors ["#9B832F"
|
||||
"#D37EF4"
|
||||
"#1D806F"
|
||||
"#FA6565"
|
||||
"#7CDA00"
|
||||
"#887AF9"
|
||||
"#8B3131"])
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.list-item.styles :as styles]
|
||||
[status-im.utils.image :as utils.image]
|
||||
[status-im.ui.components.tooltip.views :as tooltip]))
|
||||
[status-im.ui.components.tooltip.views :as tooltip]
|
||||
[status-im.ui.components.action-button.styles :as st]))
|
||||
|
||||
; type - optional :default , :small
|
||||
|
||||
; accessories - optional vector of :chevron, :check or component or string
|
||||
|
||||
; theme - optional :default, :wallet
|
||||
; theme - optional :default, :wallet, :action
|
||||
|
||||
(defn list-item [{:keys [title subtitle accessories image image-path type theme on-press error content] :or {type :default theme :default}}]
|
||||
(defn list-item [{:keys [title subtitle accessories image image-path icon type theme on-press error content] :or {type :default theme :default}}]
|
||||
(let [small? (= :small type)]
|
||||
[react/touchable-highlight {:on-press on-press :disabled (not on-press)}
|
||||
[react/view {:style (styles/container small?)}
|
||||
|
@ -22,6 +23,13 @@
|
|||
(if (vector? image)
|
||||
image
|
||||
[image])])
|
||||
;;Icon
|
||||
(when icon
|
||||
[react/view {:margin-left 16}
|
||||
[react/view (when (= theme :action) (st/action-button-icon-container nil))
|
||||
[icons/icon icon (if (= theme :action)
|
||||
st/action-button-label
|
||||
{:color colors/gray-transparent-40})]]])
|
||||
(when image-path
|
||||
[react/view {:margin-left 16}
|
||||
[react/image {:source (utils.image/source image-path)
|
||||
|
@ -29,7 +37,8 @@
|
|||
;;Title
|
||||
(when title
|
||||
[react/view {:style {:margin-left 16 :margin-right 16}}
|
||||
[react/text {:style (styles/title small? subtitle)
|
||||
[react/text {:style (merge (styles/title small? subtitle)
|
||||
(when (= theme :action) st/action-button-label))
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail}
|
||||
title]
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
:wallet-send-assets {:type :wallet}
|
||||
:wallet-request-assets {:type :wallet}
|
||||
:recent-recipients {:type :wallet}
|
||||
:select-account {:type :wallet}
|
||||
:contact-code {:type :wallet}
|
||||
:wallet-send-transaction-request {:type :wallet}
|
||||
:wallet-settings-assets {:type :main}
|
||||
|
|
|
@ -358,4 +358,5 @@
|
|||
::collectibles
|
||||
::extensions-store
|
||||
:registry/registry
|
||||
::two-pane-ui-enabled?]))
|
||||
::two-pane-ui-enabled?
|
||||
::generate-account]))
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
(hide-panel-anim bottom-anim-value alpha-value (- window-height)))))
|
||||
:reagent-render (fn []
|
||||
(when @current-popover
|
||||
(let [view (:view @current-popover)]
|
||||
(let [{:keys [view style]} @current-popover]
|
||||
[react/view {:position :absolute :top 0 :bottom 0 :left 0 :right 0}
|
||||
[react/animated-view {:style {:flex 1 :background-color :black :opacity alpha-value}}]
|
||||
[react/animated-view {:style
|
||||
|
@ -66,13 +66,14 @@
|
|||
:transform [{:translateY bottom-anim-value}]}}
|
||||
[react/touchable-highlight {:style {:flex 1} :on-press #(re-frame/dispatch [:hide-popover])}
|
||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||
[react/view {:background-color :white
|
||||
[react/view (merge {:background-color :white
|
||||
:border-radius 16
|
||||
:margin 32
|
||||
:shadow-offset {:width 0 :height 2}
|
||||
:shadow-radius 8
|
||||
:shadow-opacity 1
|
||||
:shadow-color "rgba(0, 9, 26, 0.12)"}
|
||||
style)
|
||||
(cond
|
||||
(vector? view)
|
||||
view
|
||||
|
|
|
@ -64,7 +64,8 @@
|
|||
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
|
||||
[status-im.ui.screens.wallet.custom-tokens.views :as custom-tokens]
|
||||
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||
[status-im.ui.screens.wallet.account.views :as wallet.account]))
|
||||
[status-im.ui.screens.wallet.account.views :as wallet.account]
|
||||
[status-im.ui.screens.wallet.add-new.views :as add-account]))
|
||||
|
||||
(def all-screens
|
||||
{:login login/login
|
||||
|
@ -140,12 +141,11 @@
|
|||
:contact-code wallet.components/contact-code
|
||||
:wallet-send-transaction send/send-transaction
|
||||
:recent-recipients wallet.components/recent-recipients
|
||||
:select-account wallet.components/accounts
|
||||
:recipient-qr-code wallet.components/recipient-qr-code
|
||||
:wallet-send-assets wallet.components/send-assets
|
||||
:wallet-send-transaction-request request/send-transaction-request
|
||||
:wallet-request-assets wallet.components/request-assets
|
||||
:unsigned-transactions wallet-transactions/transactions
|
||||
:transactions-history wallet-transactions/transactions
|
||||
:wallet-transaction-details wallet-transactions/transaction-details
|
||||
:wallet-settings-hook wallet-settings/settings-hook
|
||||
:selection-modal-screen [:modal extensions.module/selection-modal-screen-view]
|
||||
|
@ -186,7 +186,10 @@
|
|||
:keycard-settings hardwallet.settings/keycard-settings
|
||||
:mobile-network-settings mobile-network-settings/mobile-network-settings
|
||||
:welcome [:modal home/welcome]
|
||||
:keycard-welcome keycard/welcome})
|
||||
:keycard-welcome keycard/welcome
|
||||
:add-new-account add-account/add-account
|
||||
:add-new-account-password add-account/password
|
||||
:account-added add-account/account-added})
|
||||
|
||||
(defn get-screen [screen]
|
||||
(get all-screens screen #(throw (str "Screen " screen " is not defined."))))
|
||||
|
|
|
@ -4,12 +4,16 @@
|
|||
{:name :wallet-stack
|
||||
:screens [:wallet
|
||||
:wallet-account
|
||||
:add-new-account
|
||||
:add-new-account-password
|
||||
:account-added
|
||||
:collectibles-list
|
||||
:wallet-onboarding-setup
|
||||
:contact-code
|
||||
{:name :send-transaction-stack
|
||||
:screens [:wallet-send-transaction
|
||||
:recent-recipients
|
||||
:select-account
|
||||
:enter-pin-sign
|
||||
:hardwallet-connect-sign
|
||||
:recipient-qr-code
|
||||
|
@ -18,8 +22,6 @@
|
|||
:screens [:wallet-send-transaction-request
|
||||
:wallet-request-assets
|
||||
:recent-recipients]}
|
||||
:unsigned-transactions
|
||||
:transactions-history
|
||||
:wallet-transaction-details
|
||||
:wallet-settings-hook
|
||||
:extension-screen-holder
|
||||
|
|
|
@ -55,9 +55,9 @@
|
|||
(multiaccounts/displayed-name contact)
|
||||
(:address contact)))
|
||||
|
||||
(defn contact-item [contact]
|
||||
(defn contact-item [title contact]
|
||||
[list-item/list-item {:type :small
|
||||
:title (i18n/label :t/to)
|
||||
:title title
|
||||
:accessories [[react/text {:ellipsize-mode :middle :number-of-lines 1 :style {:flex-wrap :wrap}}
|
||||
(displayed-name contact)]]}])
|
||||
|
||||
|
@ -205,11 +205,11 @@
|
|||
[react/text (or formatted-data "")]]]
|
||||
[password-view sign]]]))
|
||||
|
||||
(views/defview sheet [{:keys [contact amount token approve?] :as tx}]
|
||||
(views/defview sheet [{:keys [from contact amount token approve?] :as tx}]
|
||||
(views/letsubs [fee [:signing/fee]
|
||||
sign [:signing/sign]
|
||||
chain [:ethereum/chain-keyword]
|
||||
{:keys [amount-error gas-error]} [:signing/amount-errors]
|
||||
{:keys [amount-error gas-error]} [:signing/amount-errors (:address from)]
|
||||
keycard-multiaccount? [:keycard-multiaccount?]]
|
||||
(let [display-symbol (wallet.utils/display-symbol token)
|
||||
fee-display-symbol (wallet.utils/display-symbol (tokens/native-currency chain))]
|
||||
|
@ -220,7 +220,9 @@
|
|||
[react/view {:padding-top 20}
|
||||
[password-view sign]]
|
||||
[react/view
|
||||
[contact-item contact]
|
||||
[contact-item (i18n/label :t/from) from]
|
||||
[separator]
|
||||
[contact-item (i18n/label :t/to) contact]
|
||||
[separator]
|
||||
[token-item token display-symbol]
|
||||
(when-not approve?
|
||||
|
@ -286,4 +288,4 @@
|
|||
(views/letsubs [tx [:signing/tx]
|
||||
{window-height :height} [:dimensions/window]]
|
||||
;;we use select-keys here because we don't want to update view if other keys in map is changed
|
||||
[signing-view (when tx (select-keys tx [:contact :amount :token :approve? :message])) window-height]))
|
||||
[signing-view (when tx (select-keys tx [:from :contact :amount :token :approve? :message])) window-height]))
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
(defview price-badge [price id owned pending]
|
||||
(letsubs [chain [:ethereum/chain-keyword]
|
||||
balance [:balance]]
|
||||
balance [:balance-default]]
|
||||
(let [snt (money/to-number (if (= :mainnet chain) (:SNT balance) (:STT balance)))
|
||||
not-enough-snt? (> price snt)
|
||||
no-snt? (or (nil? snt) (zero? snt))]
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
(ns status-im.ui.screens.wallet.account.styles
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn card [window-width]
|
||||
{:width (- window-width 64) :height 161
|
||||
:background-color colors/blue
|
||||
(defn card [window-width color]
|
||||
{:width (- window-width 30)
|
||||
:height 161
|
||||
:background-color color
|
||||
:shadow-offset {:width 0 :height 2}
|
||||
:shadow-radius 8
|
||||
:shadow-opacity 1
|
||||
|
|
|
@ -38,11 +38,11 @@
|
|||
[icons/icon icon {:color colors/white}]
|
||||
[react/text {:style {:margin-left 8 :color colors/white}} label]]]])
|
||||
|
||||
(views/defview account-card [{:keys [address]}]
|
||||
(views/defview account-card [{:keys [address color]}]
|
||||
(views/letsubs [currency [:wallet/currency]
|
||||
portfolio-value [:portfolio-value]
|
||||
portfolio-value [:account-portfolio-value address]
|
||||
window-width [:dimensions/window-width]]
|
||||
[react/view {:style (styles/card window-width)}
|
||||
[react/view {:style (styles/card window-width color)}
|
||||
[react/view {:padding 16 :padding-bottom 12 :flex 1 :justify-content :space-between}
|
||||
[react/nested-text {:style {:color colors/white-transparent :line-height 38
|
||||
:font-weight "600" :font-size 32}}
|
||||
|
@ -66,20 +66,19 @@
|
|||
[react/view {:style styles/divider}]
|
||||
[button (i18n/label :t/receive) :main-icons/receive #(re-frame/dispatch [:show-popover {:view :share-account :address address}])]]]))
|
||||
|
||||
(views/defview transactions []
|
||||
(views/defview transactions [address]
|
||||
(views/letsubs [{:keys [transaction-history-sections]}
|
||||
[:wallet.transactions.history/screen]]
|
||||
[:wallet.transactions.history/screen address]]
|
||||
[history/history-list transaction-history-sections]))
|
||||
|
||||
(views/defview assets-and-collections []
|
||||
(views/letsubs [{:keys [tokens nfts]} [:wallet/visible-assets-with-values]
|
||||
(views/defview assets-and-collections [address]
|
||||
(views/letsubs [{:keys [tokens nfts]} [:wallet/visible-assets-with-values address]
|
||||
currency [:wallet/currency]]
|
||||
(let [{:keys [tab]} @state]
|
||||
[react/view {:flex 1}
|
||||
[react/view {:flex-direction :row :margin-bottom 8 :padding-horizontal 4}
|
||||
[accounts/tab-title state :assets (i18n/label :t/wallet-assets) (= tab :assets)]
|
||||
(when (seq nfts)
|
||||
[accounts/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)])
|
||||
[accounts/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)]
|
||||
[accounts/tab-title state :history (i18n/label :t/history) (= tab :history)]]
|
||||
(cond
|
||||
(= tab :assets)
|
||||
|
@ -91,6 +90,7 @@
|
|||
:align-self :stretch}}]
|
||||
:render-fn (accounts/render-asset (:code currency))}]
|
||||
(= tab :nft)
|
||||
(if (seq nfts)
|
||||
[list/flat-list {:data nfts
|
||||
:default-separator? false
|
||||
:key-fn :name
|
||||
|
@ -98,11 +98,14 @@
|
|||
{:style {:height tabs.styles/tabs-diff
|
||||
:align-self :stretch}}]
|
||||
:render-fn accounts/render-collectible}]
|
||||
[react/view {:align-items :center :margin-top 32}
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/no-collectibles)]])
|
||||
(= tab :history)
|
||||
[transactions])])))
|
||||
[transactions address])])))
|
||||
|
||||
(views/defview account []
|
||||
(views/letsubs [{:keys [name] :as account} [:get-screen-params]]
|
||||
(views/letsubs [{:keys [name address] :as account} [:get-screen-params]]
|
||||
[react/view {:flex 1 :background-color colors/white}
|
||||
[toolbar-view name]
|
||||
[react/scroll-view
|
||||
|
@ -110,4 +113,4 @@
|
|||
[react/scroll-view {:horizontal true}
|
||||
[react/view {:flex-direction :row :padding-top 8 :padding-bottom 12}
|
||||
[account-card account]]]]
|
||||
[assets-and-collections]]]))
|
||||
[assets-and-collections address]]]))
|
|
@ -50,10 +50,10 @@
|
|||
|
||||
(defn add-account []
|
||||
[react/view
|
||||
[action-button/action-button-disabled {:label (i18n/label :t/add-an-account)
|
||||
[action-button/action-button {:label (i18n/label :t/add-an-account)
|
||||
:icon :main-icons/add
|
||||
:icon-opts {:color :blue}
|
||||
:on-press #(hide-sheet-and-dispatch [:navigate-to])}]
|
||||
:on-press #(hide-sheet-and-dispatch [:navigate-to :add-new-account])}]
|
||||
[action-button/action-button-disabled {:label (i18n/label :t/add-a-watch-account)
|
||||
:icon :main-icons/watch
|
||||
:icon-opts {:color :blue}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
(defn card [color]
|
||||
{:width 156
|
||||
:height 145
|
||||
:margin-right 16
|
||||
:background-color color
|
||||
:shadow-offset {:width 0 :height 2}
|
||||
:shadow-radius 8
|
||||
|
@ -20,7 +21,6 @@
|
|||
(def add-card
|
||||
{:width 156
|
||||
:height 145
|
||||
:margin-left 16
|
||||
:margin-top 5
|
||||
:margin-right 5
|
||||
:margin-bottom 5
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
(views/defview account-card [{:keys [name color address] :as account}]
|
||||
(views/letsubs [currency [:wallet/currency]
|
||||
portfolio-value [:portfolio-value]]
|
||||
portfolio-value [:account-portfolio-value address]]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :wallet-account account])
|
||||
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn [] [sheets/send-receive address])
|
||||
|
@ -97,7 +97,7 @@
|
|||
:accessories [items-number :chevron]}]]))
|
||||
|
||||
(views/defview assets-and-collections []
|
||||
(views/letsubs [{:keys [tokens nfts]} [:wallet/visible-assets-with-values]
|
||||
(views/letsubs [{:keys [tokens nfts]} [:wallet/all-visible-assets-with-values]
|
||||
currency [:wallet/currency]]
|
||||
(let [{:keys [tab]} @state]
|
||||
[react/view {:flex 1}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
(ns status-im.ui.screens.wallet.add-new.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
[status-im.ui.components.toolbar.view :as toolbar]
|
||||
[status-im.i18n :as i18n]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.list-header.views :as list-header]
|
||||
[status-im.ui.components.list-item.views :as list-item]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.ui.components.icons.vector-icons :as icons]
|
||||
[status-im.ui.components.text-input.view :as text-input]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]
|
||||
[cljs.spec.alpha :as spec]
|
||||
[status-im.multiaccounts.db :as multiaccounts.db]))
|
||||
|
||||
(defn add-account []
|
||||
[react/view {:flex 1}
|
||||
[status-bar/status-bar]
|
||||
[toolbar/toolbar {:transparent? true} toolbar/default-nav-back nil]
|
||||
[react/scroll-view {:keyboard-should-persist-taps :handled
|
||||
:style {:flex 1}}
|
||||
[react/view {:align-items :center :padding-horizontal 40}
|
||||
[react/text {:style {:typography :header :margin-top 16}} (i18n/label :t/add-an-account)]
|
||||
[react/text {:style {:color colors/gray :text-align :center :margin-top 16 :line-height 22}}
|
||||
(i18n/label :t/add-account-description)]]
|
||||
[react/view {:height 52}]
|
||||
[list-header/list-header (i18n/label :t/default)]
|
||||
[list-item/list-item {:title (i18n/label :t/generate-a-new-account) :theme :action
|
||||
:icon :main-icons/add :accessories [:chevron]
|
||||
:on-press #(re-frame/dispatch [:navigate-to :add-new-account-password])}]]])
|
||||
|
||||
(defview colors-popover [selected-color]
|
||||
(letsubs [width [:dimensions/window-width]]
|
||||
[react/view {:padding-bottom 16}
|
||||
[react/scroll-view {:style {:margin 16}}
|
||||
(doall
|
||||
(for [color colors/account-colors]
|
||||
^{:key color}
|
||||
[react/touchable-highlight {:on-press #(do
|
||||
(re-frame/dispatch [:set-in [:generate-account :account :color] color])
|
||||
(re-frame/dispatch [:hide-popover]))}
|
||||
[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}])]]]))]
|
||||
[components.common/button {:on-press #(re-frame/dispatch [:hide-popover])
|
||||
:label (i18n/label :t/cancel)
|
||||
:background? false}]]))
|
||||
|
||||
(defview account-added []
|
||||
(letsubs [{:keys [account]} [:generate-account]]
|
||||
[react/keyboard-avoiding-view {:flex 1}
|
||||
[status-bar/status-bar]
|
||||
[react/scroll-view {:keyboard-should-persist-taps :handled
|
||||
:style {:margin-top 70 :flex 1}}
|
||||
[react/view {:align-items :center :padding-horizontal 40}
|
||||
[react/view {:height 40 :width 40 :border-radius 20 :align-items :center :justify-content :center
|
||||
:background-color (:color account)}
|
||||
[icons/icon :main-icons/check {:color colors/white}]]
|
||||
[react/text {:style {:typography :header :margin-top 16}}
|
||||
(i18n/label :t/account-added)]
|
||||
[react/text {:style {:color colors/gray :text-align :center :margin-top 16 :line-height 22}}
|
||||
(i18n/label :t/you-can-change-account)]]
|
||||
[react/view {:height 52}]
|
||||
[react/view {:margin-horizontal 16}
|
||||
[text-input/text-input-with-label
|
||||
{:label (i18n/label :t/account-name)
|
||||
:auto-focus false
|
||||
:default-value (:name account)
|
||||
:on-change-text #(re-frame/dispatch [:set-in [:generate-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 [colors-popover (:color account)]
|
||||
: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}]]]]]
|
||||
[react/view {:style {:flex-direction :row
|
||||
:justify-content :flex-end
|
||||
:align-self :stretch
|
||||
:padding-vertical 16
|
||||
:border-top-width 1
|
||||
:border-top-color colors/gray-lighter
|
||||
:padding-right 12}}
|
||||
[components.common/bottom-button {:label (i18n/label :t/finish)
|
||||
:on-press #(re-frame/dispatch [:wallet.accounts/save-generated-account])
|
||||
:disabled? (string/blank? (:name account))
|
||||
:forward? true}]]]))
|
||||
|
||||
(defview password []
|
||||
(letsubs [{:keys [error]} [:generate-account]
|
||||
entered-password (reagent/atom "")]
|
||||
[react/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[status-bar/status-bar {:flat? true}]
|
||||
[toolbar/toolbar {:transparent? true} toolbar/default-nav-back nil]
|
||||
[react/view {:flex 1}
|
||||
[react/view {:style {:flex 1
|
||||
:justify-content :space-between
|
||||
:align-items :center :margin-horizontal 16}}
|
||||
[react/text {:style {:typography :header :margin-top 16}} (i18n/label :t/enter-your-password)]
|
||||
[react/view {:style {:justify-content :center :flex 1}}
|
||||
[react/text-input {:secure-text-entry true
|
||||
:auto-focus true
|
||||
:text-align :center
|
||||
:placeholder ""
|
||||
:style {:typography :header}
|
||||
:on-change-text #(reset! entered-password %)}]
|
||||
(when error
|
||||
[react/text {:style {:text-align :center :color colors/red :margin-top 76}} error])]
|
||||
[react/text {:style {:color colors/gray :text-align :center :margin-bottom 16}}
|
||||
(i18n/label :t/to-encrypt-enter-password)]]
|
||||
[react/view {:style {:flex-direction :row
|
||||
:justify-content :flex-end
|
||||
:align-self :stretch
|
||||
:padding-vertical 16
|
||||
:border-top-width 1
|
||||
:border-top-color colors/gray-lighter
|
||||
:padding-right 12}}
|
||||
[components.common/bottom-button {:label (i18n/label :t/generate-account)
|
||||
:on-press #(re-frame/dispatch
|
||||
[:wallet.accounts/generate-new-account @entered-password])
|
||||
:disabled? (not (spec/valid? ::multiaccounts.db/password @entered-password))
|
||||
:forward? true}]]]]))
|
|
@ -29,7 +29,8 @@
|
|||
[status-im.wallet.utils :as wallet.utils]
|
||||
[status-im.utils.core :as utils.core]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.utils :as utils.utils])
|
||||
[status-im.utils.utils :as utils.utils]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
;; Wallet tab has a different coloring scheme (dark) that forces color changes (background, text)
|
||||
|
@ -120,8 +121,8 @@
|
|||
(wallet.utils/display-symbol token)]]
|
||||
[list/item-secondary (wallet.utils/format-amount amount decimals)]]]]])
|
||||
|
||||
(views/defview assets [type]
|
||||
(views/letsubs [assets [:wallet/transferrable-assets-with-amount]]
|
||||
(views/defview assets [type address]
|
||||
(views/letsubs [assets [:wallet/transferrable-assets-with-amount address]]
|
||||
[simple-screen
|
||||
[toolbar (i18n/label :t/wallet-assets)]
|
||||
[react/view {:style (assoc components.styles/flex :background-color :white)}
|
||||
|
@ -130,11 +131,13 @@
|
|||
:key-fn (comp str :symbol)
|
||||
:render-fn #(render-token % type)}]]]))
|
||||
|
||||
(defn send-assets []
|
||||
[assets :send])
|
||||
(views/defview send-assets []
|
||||
(views/letsubs [address [:get-screen-params]]
|
||||
[assets :send address]))
|
||||
|
||||
(defn request-assets []
|
||||
[assets :request])
|
||||
(views/defview request-assets []
|
||||
(views/letsubs [address [:get-screen-params]]
|
||||
[assets :request address]))
|
||||
|
||||
(defn- type->view [k]
|
||||
(case k
|
||||
|
@ -142,14 +145,14 @@
|
|||
:request :wallet-request-assets
|
||||
(throw (str "Unknown type: " k))))
|
||||
|
||||
(views/defview asset-selector [{:keys [disabled? type symbol error]}]
|
||||
(views/letsubs [balance [:balance]
|
||||
(views/defview asset-selector [{:keys [disabled? type symbol error address]}]
|
||||
(views/letsubs [balance [:balance address]
|
||||
chain [:ethereum/chain-keyword]
|
||||
all-tokens [:wallet/all-tokens]]
|
||||
(let [{:keys [name icon decimals color] :as token} (tokens/asset-for all-tokens chain symbol)]
|
||||
(when name
|
||||
[react/view
|
||||
[cartouche {:disabled? disabled? :on-press #(re-frame/dispatch [:navigate-to (type->view type)])}
|
||||
[cartouche {:disabled? disabled? :on-press #(re-frame/dispatch [:navigate-to (type->view type) address])}
|
||||
(i18n/label :t/wallet-asset)
|
||||
[react/view {:style styles/asset-content-container
|
||||
:accessibility-label :choose-asset-button}
|
||||
|
@ -202,6 +205,17 @@
|
|||
:accessibility-label :contact-address-text}
|
||||
(eip55/address->checksum (ethereum/normalized-address (:address contact)))]]]])
|
||||
|
||||
(defn render-account [account]
|
||||
[list/touchable-item #(re-frame/dispatch [:wallet/fill-request-from-contact account false])
|
||||
[list/item
|
||||
[chat-icon/custom-icon-view-list (:name account) (:color account)]
|
||||
[list/item-content
|
||||
[list/item-primary {:accessibility-label :contact-name-text}
|
||||
(:name account)]
|
||||
[react/text {:style list.styles/secondary-text
|
||||
:accessibility-label :contact-address-text}
|
||||
(eip55/address->checksum (ethereum/normalized-address (:address account)))]]]])
|
||||
|
||||
(views/defview recent-recipients []
|
||||
(views/letsubs [contacts [:contacts/active]
|
||||
{:keys [request?]} [:get-screen-params :recent-recipients]]
|
||||
|
@ -212,6 +226,15 @@
|
|||
:key-fn :address
|
||||
:render-fn #(render-contact % request?)}]]]))
|
||||
|
||||
(views/defview accounts []
|
||||
(views/letsubs [{:keys [accounts]} [:multiaccount]]
|
||||
[simple-screen
|
||||
[toolbar (i18n/label :t/accounts)]
|
||||
[react/view styles/recent-recipients
|
||||
[list/flat-list {:data accounts
|
||||
:key-fn :address
|
||||
:render-fn render-account}]]]))
|
||||
|
||||
(defn contact-code []
|
||||
(let [content (reagent/atom nil)]
|
||||
(fn []
|
||||
|
@ -252,7 +275,9 @@
|
|||
[{:label (i18n/label :t/recent-recipients)
|
||||
:action #(re-frame/dispatch [:navigate-to :recent-recipients {:request? request?}])}]
|
||||
(when-not contact-only?))
|
||||
:options [{:label (i18n/label :t/scan-qr)
|
||||
:options [{:label (i18n/label :t/accounts)
|
||||
:action #(re-frame/dispatch [:navigate-to :select-account])}
|
||||
{:label (i18n/label :t/scan-qr)
|
||||
:action request-camera-permissions}
|
||||
{:label (i18n/label :t/recipient-code)
|
||||
:action #(re-frame/dispatch [:navigate-to :contact-code])}]}))
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
:auto-focus false
|
||||
:placeholder "18"}]]]
|
||||
[react/view {:height 16}]
|
||||
[text-input/text-input-with-label
|
||||
#_[text-input/text-input-with-label
|
||||
{:label (i18n/label :t/balance)
|
||||
:default-value (when (and balance decimals)
|
||||
(wallet.utils/format-amount balance decimals))
|
||||
|
|
|
@ -32,3 +32,7 @@
|
|||
(defmethod navigation/preload-data! :wallet-add-custom-token
|
||||
[db [event]]
|
||||
(dissoc db :wallet/custom-token-screen))
|
||||
|
||||
(defmethod navigation/preload-data! :add-new-account
|
||||
[db [event]]
|
||||
(dissoc db :generate-account))
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
(eip55/address->checksum address)]]]
|
||||
[react/view {:height 1 :background-color colors/gray-lighter :margin-top 8}]
|
||||
[react/view {:padding-bottom 16}
|
||||
[components.common/button {:on-press #(re-frame/dispatch [:wallet.accounts/share])
|
||||
[components.common/button {:on-press #(re-frame/dispatch [:wallet.accounts/share address])
|
||||
:button-style {:margin-vertical 20 :margin-horizontal 16}
|
||||
:accessibility-label :share-address-button
|
||||
:label (i18n/label :t/share-address)}]
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
colors/white-light-transparent)}]]])
|
||||
|
||||
(defn- render-send-transaction-view [{:keys [chain transaction scroll all-tokens amount-input network-status]}]
|
||||
(let [{:keys [amount amount-text amount-error asset-error to to-name sufficient-funds? symbol]} transaction
|
||||
(let [{:keys [from amount amount-text amount-error asset-error to to-name sufficient-funds? symbol]} transaction
|
||||
{:keys [decimals] :as token} (tokens/asset-for all-tokens chain symbol)
|
||||
online? (= :online network-status)]
|
||||
[wallet.components/simple-screen {:avoid-keyboard? true
|
||||
|
@ -54,6 +54,7 @@
|
|||
:name to-name}]
|
||||
[wallet.components/asset-selector
|
||||
{:error asset-error
|
||||
:address from
|
||||
:type :send
|
||||
:symbol symbol}]
|
||||
[wallet.components/amount-selector
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
(def empty-text
|
||||
{:text-align :center
|
||||
:color colors/gray
|
||||
:margin-top 22
|
||||
:margin-horizontal 92})
|
||||
|
||||
|
|
|
@ -11,17 +11,14 @@
|
|||
[status-im.ui.screens.wallet.transactions.styles :as styles])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TRANSACTION HISTORY
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn history-action
|
||||
[all-filters?]
|
||||
(cond->
|
||||
{:icon :main-icons/filter
|
||||
(cond-> {:icon :main-icons/filter
|
||||
:icon-opts {:accessibility-label :filters-button}
|
||||
:handler #(re-frame/dispatch [:navigate-to :wallet-transactions-filter])}
|
||||
(not all-filters?) (assoc-in [:icon-opts :overlay-style] styles/corner-dot)))
|
||||
|
||||
(not all-filters?)
|
||||
(assoc-in [:icon-opts :overlay-style] styles/corner-dot)))
|
||||
|
||||
(defn- toolbar-view
|
||||
[all-filters?]
|
||||
|
@ -102,19 +99,6 @@
|
|||
:key :transactions-history-empty}]
|
||||
:refreshing false}]])
|
||||
|
||||
(defview transactions
|
||||
[]
|
||||
(letsubs [{:keys [transaction-history-sections all-filters?]}
|
||||
[:wallet.transactions.history/screen]]
|
||||
[react/view styles/transactions-view
|
||||
[status-bar/status-bar]
|
||||
[toolbar-view all-filters?]
|
||||
[history-list transaction-history-sections]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TRANSACTION FILTERS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- render-item-filter [{:keys [id label checked? on-touch]}]
|
||||
[react/view {:accessibility-label :filter-item}
|
||||
[list/list-item-with-checkbox
|
||||
|
@ -151,10 +135,6 @@
|
|||
:data filters}]
|
||||
:key-fn :id}]]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TRANSACTION DETAILS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn details-header
|
||||
[date type amount-text currency-text]
|
||||
[react/view {:style styles/details-header}
|
||||
|
@ -237,11 +217,11 @@
|
|||
{:label (i18n/label :t/open-on-etherscan)
|
||||
:action #(.openURL (react/linking) url)}])])
|
||||
|
||||
(defview transaction-details []
|
||||
(letsubs [{:keys [hash url type confirmations confirmations-progress
|
||||
(defview transaction-details-view [hash address]
|
||||
(letsubs [{:keys [url type confirmations confirmations-progress
|
||||
date amount-text currency-text]
|
||||
:as transaction}
|
||||
[:wallet.transactions.details/screen]]
|
||||
[:wallet.transactions.details/screen hash address]]
|
||||
[react/view {:style components.styles/flex}
|
||||
[status-bar/status-bar]
|
||||
[toolbar/toolbar {}
|
||||
|
@ -253,3 +233,8 @@
|
|||
[details-confirmations confirmations confirmations-progress (= :failed type)]
|
||||
[react/view {:style styles/details-separator}]
|
||||
[details-list transaction]]]))
|
||||
|
||||
(defview transaction-details []
|
||||
(letsubs [{:keys [hash address]} [:get-screen-params]]
|
||||
(when (and hash address)
|
||||
[transaction-details-view hash address])))
|
|
@ -4,14 +4,67 @@
|
|||
[status-im.utils.fx :as fx]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:list.selection/open-share
|
||||
(fn [obj]
|
||||
(list-selection/open-share obj)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet.accounts/generate-account
|
||||
(fn [{:keys [address password path-num]}]
|
||||
(status/multiaccount-load-account
|
||||
address
|
||||
password
|
||||
(fn [value]
|
||||
(let [{:keys [id error]} (types/json->clj value)]
|
||||
(if error
|
||||
(re-frame/dispatch [:set-in [:generate-account :error] (i18n/label :t/add-account-incorrect-password)])
|
||||
(let [path (str constants/path-root "/" path-num)]
|
||||
(status/multiaccount-derive-addresses
|
||||
id
|
||||
[path]
|
||||
#(re-frame/dispatch [:wallet.accounts/account-generated
|
||||
(merge
|
||||
(get (types/json->clj %) (keyword path))
|
||||
{:name (str "Account " path-num)
|
||||
:color (rand-nth colors/account-colors)})])))))))))
|
||||
|
||||
(fx/defn set-symbol-request
|
||||
{:events [:wallet.accounts/share]}
|
||||
[{:keys [db]}]
|
||||
{:list.selection/open-share {:message (eip55/address->checksum (ethereum/default-address db))}})
|
||||
[_ address]
|
||||
{:list.selection/open-share {:message (eip55/address->checksum address)}})
|
||||
|
||||
(fx/defn generate-new-account
|
||||
{:events [:wallet.accounts/generate-new-account]}
|
||||
[{:keys [db]} password]
|
||||
{:wallet.accounts/generate-account {:address (get-in db [:multiaccount :address])
|
||||
:path-num (inc (get-in db [:multiaccount :latest-derived-path]))
|
||||
:password password}})
|
||||
|
||||
(fx/defn account-generated
|
||||
{:events [:wallet.accounts/account-generated]}
|
||||
[{:keys [db] :as cofx} account]
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :generate-account {:account account})}
|
||||
(navigation/navigate-to-cofx :account-added nil)))
|
||||
|
||||
(fx/defn save-account
|
||||
{:events [:wallet.accounts/save-generated-account]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [new-account (get-in db [:generate-account :account])
|
||||
{:keys [accounts latest-derived-path]} (:multiaccount db)]
|
||||
(fx/merge cofx
|
||||
(multiaccounts.update/multiaccount-update {:accounts (conj accounts new-account)
|
||||
:latest-derived-path (inc latest-derived-path)} nil)
|
||||
(wallet/update-balances nil)
|
||||
(navigation/navigate-to-cofx :wallet nil))))
|
|
@ -29,6 +29,16 @@
|
|||
:on-success on-success
|
||||
:on-error on-error})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet/get-balances
|
||||
(fn [addresses]
|
||||
(doseq [address addresses]
|
||||
(json-rpc/call
|
||||
{:method "eth_getBalance"
|
||||
:params [address "latest"]
|
||||
:on-success #(re-frame/dispatch [:wallet.callback/update-balance-success address %])
|
||||
:on-error #(re-frame/dispatch [:wallet.callback/update-balance-fail %])}))))
|
||||
|
||||
;; TODO(oskarth): At some point we want to get list of relevant
|
||||
;; assets to get prices for
|
||||
(re-frame/reg-fx
|
||||
|
@ -55,21 +65,17 @@
|
|||
[{:keys [db]} err]
|
||||
(log/debug "Unable to get balance: " err)
|
||||
{:db (-> db
|
||||
(assoc-error-message :balance-update :error-unable-to-get-balance)
|
||||
(assoc-in [:wallet :balance-loading?] false))})
|
||||
(assoc-error-message :balance-update :error-unable-to-get-balance))})
|
||||
|
||||
(fx/defn on-update-token-balance-fail
|
||||
[{:keys [db]} symbol err]
|
||||
(log/debug "Unable to get token " symbol "balance: " err)
|
||||
{:db (-> db
|
||||
(assoc-error-message :balance-update :error-unable-to-get-token-balance)
|
||||
(assoc-in [:wallet :balance-loading?] false))})
|
||||
(assoc-error-message :balance-update :error-unable-to-get-token-balance))})
|
||||
|
||||
(fx/defn open-transaction-details
|
||||
[{:keys [db] :as cofx} hash]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:wallet :current-transaction] hash)}
|
||||
(navigation/navigate-to-cofx :wallet-transaction-details nil)))
|
||||
[{:keys [db] :as cofx} hash address]
|
||||
(navigation/navigate-to-cofx cofx :wallet-transaction-details {:hash hash :address address}))
|
||||
|
||||
(defn- validate-token-name!
|
||||
[{:keys [address symbol name]}]
|
||||
|
@ -136,18 +142,23 @@
|
|||
(validate-token-name! token))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet/get-tokens-balance
|
||||
(fn [{:keys [account-address tokens on-success on-error]}]
|
||||
:wallet/get-tokens-balances
|
||||
(fn [{:keys [addresses tokens assets]}]
|
||||
;;TODO not great to have so many calls , should be optimized, there is wallet_getTokensBalances why wouldn't use it?
|
||||
(doseq [{:keys [address symbol]} tokens]
|
||||
(doseq [account-address addresses]
|
||||
(json-rpc/eth-call
|
||||
{:contract address
|
||||
:method "balanceOf(address)"
|
||||
:params [account-address]
|
||||
:outputs ["uint256"]
|
||||
:on-success
|
||||
(fn [[balance]]
|
||||
(on-success symbol (money/bignumber balance)))
|
||||
:on-error #(on-error symbol %)}))))
|
||||
:on-success (fn [[balance]]
|
||||
(if (and assets (assets symbol))
|
||||
(re-frame/dispatch [:wallet.callback/update-token-balance-success account-address symbol balance])
|
||||
;; NOTE: when there it is not a visible assets we make an initialization round
|
||||
(when (pos? balance)
|
||||
(re-frame/dispatch [:wallet/token-found account-address symbol balance]))))
|
||||
:on-error #(re-frame/dispatch [:wallet.callback/update-token-balance-fail symbol %])})))))
|
||||
|
||||
(defn clear-error-message [db error-type]
|
||||
(update-in db [:wallet :errors] dissoc error-type))
|
||||
|
@ -176,8 +187,8 @@
|
|||
|
||||
(fx/defn update-balances
|
||||
[{{:keys [network-status :wallet/all-tokens]
|
||||
{:keys [settings]} :multiaccount :as db} :db :as cofx}]
|
||||
(let [normalized-address (ethereum/current-address db)
|
||||
{:keys [settings accounts]} :multiaccount :as db} :db :as cofx} addresses]
|
||||
(let [addresses (or addresses (map :address accounts))
|
||||
chain (ethereum/chain-keyword db)
|
||||
assets (get-in settings [:wallet :visible-tokens chain])
|
||||
tokens (->> (tokens/tokens-for all-tokens chain)
|
||||
|
@ -185,36 +196,12 @@
|
|||
(when (not= network-status :offline)
|
||||
(fx/merge
|
||||
cofx
|
||||
{:wallet/get-balance
|
||||
{:account-address normalized-address
|
||||
:on-success #(re-frame/dispatch
|
||||
[:wallet.callback/update-balance-success %])
|
||||
:on-error #(re-frame/dispatch
|
||||
[:wallet.callback/update-balance-fail %])}
|
||||
|
||||
:wallet/get-tokens-balance
|
||||
{:account-address normalized-address
|
||||
:tokens tokens
|
||||
:on-success
|
||||
(fn [symbol balance]
|
||||
(if (and assets
|
||||
(assets symbol))
|
||||
(re-frame/dispatch
|
||||
[:wallet.callback/update-token-balance-success symbol balance])
|
||||
;; NOTE: when there it is not a visible assets
|
||||
;; we make an initialization round
|
||||
(when (> balance 0)
|
||||
(re-frame/dispatch
|
||||
[:wallet/token-found symbol balance]))))
|
||||
:on-error
|
||||
(fn [symbol error]
|
||||
(re-frame/dispatch
|
||||
[:wallet.callback/update-token-balance-fail symbol error]))}
|
||||
|
||||
:db
|
||||
(-> db
|
||||
(clear-error-message :balance-update)
|
||||
(assoc-in [:wallet :balance-loading?] true))}
|
||||
{:wallet/get-balances addresses
|
||||
:wallet/get-tokens-balances {:addresses addresses
|
||||
:assets assets
|
||||
:tokens tokens}
|
||||
:db (-> db
|
||||
(clear-error-message :balance-update))}
|
||||
(when-not assets
|
||||
(multiaccounts.update/update-settings
|
||||
(assoc-in settings
|
||||
|
@ -260,16 +247,14 @@
|
|||
:prices-loading? false)})
|
||||
|
||||
(fx/defn update-balance
|
||||
[{:keys [db]} balance]
|
||||
[{:keys [db]} address balance]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :balance :ETH] (money/bignumber balance))
|
||||
(assoc-in [:wallet :balance-loading?] false))})
|
||||
(assoc-in [:wallet :accounts address :balance :ETH] (money/bignumber balance)))})
|
||||
|
||||
(fx/defn update-token-balance
|
||||
[{:keys [db]} symbol balance]
|
||||
[{:keys [db]} address symbol balance]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :balance symbol] (money/bignumber balance))
|
||||
(assoc-in [:wallet :balance-loading?] false))})
|
||||
(assoc-in [:wallet :accounts address :balance symbol] (money/bignumber balance)))})
|
||||
|
||||
(defn update-toggle-in-settings
|
||||
[{{:keys [multiaccount] :as db} :db} symbol checked?]
|
||||
|
@ -297,11 +282,11 @@
|
|||
(multiaccounts.update/update-settings cofx new-settings {})))
|
||||
|
||||
(fx/defn configure-token-balance-and-visibility
|
||||
[cofx symbol balance]
|
||||
[cofx address symbol balance]
|
||||
(fx/merge cofx
|
||||
(toggle-visible-token symbol true)
|
||||
;;TODO(goranjovic): move `update-token-balance-success` function to wallet models
|
||||
(update-token-balance symbol balance)))
|
||||
(update-token-balance address symbol balance)))
|
||||
|
||||
(defn set-and-validate-amount-db [db amount symbol decimals]
|
||||
(let [{:keys [value error]} (wallet.db/parse-amount amount decimals)]
|
||||
|
|
|
@ -91,8 +91,7 @@
|
|||
(fx/defn total-supply-result
|
||||
[{:keys [db]} contract total-supply]
|
||||
(if (money/valid? total-supply)
|
||||
{:wallet.custom-token/get-balance
|
||||
[contract (ethereum/default-address db)]}
|
||||
{:wallet.custom-token/get-name contract}
|
||||
{:db (update db
|
||||
:wallet/custom-token-screen
|
||||
merge {:in-progress? nil
|
||||
|
|
|
@ -66,8 +66,7 @@
|
|||
#{:inbound :outbound :pending :failed})
|
||||
|
||||
(def default-wallet
|
||||
{:filters default-wallet-filters
|
||||
:transactions empty-transaction-map})
|
||||
{:filters default-wallet-filters})
|
||||
|
||||
(defn get-confirmations
|
||||
[{:keys [block]} current-block]
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
(testing "first tx object is parsed"
|
||||
(is (= (dissoc (get-in sign-first [:db :signing/tx]) :token)
|
||||
(merge first-tx
|
||||
{:gas nil
|
||||
{:from {:address nil}
|
||||
:gas nil
|
||||
:gasPrice nil
|
||||
:data nil
|
||||
:to to
|
||||
|
@ -49,7 +50,8 @@
|
|||
(testing "second tx object is parsed"
|
||||
(is (= (dissoc (get-in first-discarded [:db :signing/tx]) :token)
|
||||
(merge second-tx
|
||||
{:gas nil
|
||||
{:from {:address nil}
|
||||
:gas nil
|
||||
:gasPrice nil
|
||||
:data data
|
||||
:to contract
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
"intro-wizard-text7": "Status will notify you about new messages. You can edit your notification preferences later in settings",
|
||||
"generate-a-key": "Generate a key",
|
||||
"generate-a-new-key": "Generate a new key",
|
||||
"enter-your-password": "Enter your password...",
|
||||
"enter-your-password": "Enter your password",
|
||||
"generating-keys": "Generating keys...",
|
||||
"you-will-need-this-code": "You'll need this code to open Status and sign transactions",
|
||||
"this-device": "This device",
|
||||
|
@ -1259,5 +1259,15 @@
|
|||
"not-keycard-title": "Not a Keycard",
|
||||
"not-keycard-text": "The card you used is not a Keycard. You need to purchase a Keycard to use it",
|
||||
"create-new-key": "Create a new key",
|
||||
"add-another-key": "Add another key"
|
||||
"add-another-key": "Add another key",
|
||||
"generate-a-new-account": "Generate a new account",
|
||||
"generate-account": "Generate account",
|
||||
"add-account-description": "You can import any type of Ethereum account to add it to your Status wallet",
|
||||
"account-added": "Account added",
|
||||
"you-can-change-account": "You can change the account name and color to what you wish",
|
||||
"account-name": "Account name",
|
||||
"account-color": "Account color",
|
||||
"to-encrypt-enter-password": "To encrypt the account please enter your password",
|
||||
"accounts": "Accounts",
|
||||
"add-account-incorrect-password": "Password seems to be incorrect. Enter the password you use to unlock the app."
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue