[keycard] Allow to restore kk multiacc using pairing
This commit is contained in:
parent
79cf87be86
commit
5101d4d6a5
|
@ -19,6 +19,7 @@
|
||||||
keycard-match? (= keycard-instance-uid instance-uid)
|
keycard-match? (= keycard-instance-uid instance-uid)
|
||||||
hash (get-in db [:hardwallet :hash])
|
hash (get-in db [:hardwallet :hash])
|
||||||
data (get-in db [:hardwallet :data])
|
data (get-in db [:hardwallet :data])
|
||||||
|
typed? (get-in db [:hardwallet :typed?])
|
||||||
pin (common/vector->string (get-in db [:hardwallet :pin :sign]))
|
pin (common/vector->string (get-in db [:hardwallet :pin :sign]))
|
||||||
from (get-in db [:signing/tx :from :address])
|
from (get-in db [:signing/tx :from :address])
|
||||||
path (reduce
|
path (reduce
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
:hardwallet/sign {:hash (ethereum/naked-address hash)
|
:hardwallet/sign {:hash (ethereum/naked-address hash)
|
||||||
:data data
|
:data data
|
||||||
:pairing pairing
|
:pairing pairing
|
||||||
|
:typed? typed?
|
||||||
:pin pin
|
:pin pin
|
||||||
:path path}}
|
:path path}}
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[taoensso.timbre :as log]))
|
[taoensso.timbre :as log]
|
||||||
|
[status-im.multiaccounts.create.core :as multiaccounts.create]))
|
||||||
|
|
||||||
(def initial-state
|
(def initial-state
|
||||||
{:card-connected? false
|
{:card-connected? false
|
||||||
|
@ -36,6 +37,23 @@
|
||||||
:key-uid (get-in @re-frame.db/app-db [:multiaccounts/login :key-uid])})
|
:key-uid (get-in @re-frame.db/app-db [:multiaccounts/login :key-uid])})
|
||||||
(connect-card))
|
(connect-card))
|
||||||
|
|
||||||
|
(def initialization (atom false))
|
||||||
|
|
||||||
|
(defn connect-pairing-card []
|
||||||
|
(reset! initialization false)
|
||||||
|
(swap! state assoc :application-info
|
||||||
|
{:free-pairing-slots 5
|
||||||
|
:app-version "2.2"
|
||||||
|
:secure-channel-pub-key "04c3071768912a515c00aeab7ceb8a5bfda91d036f4a4e60b7944cee3ca7fb67b6d118e8df1e2480b87fd636c6615253245bbbc93a6a407f155f2c58f76c96ef0e",
|
||||||
|
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
|
||||||
|
:paired? true
|
||||||
|
:has-master-key? true
|
||||||
|
:initialized? true
|
||||||
|
:pin-retry-counter 3
|
||||||
|
:puk-retry-counter 5
|
||||||
|
:key-uid "0x16839e8b1b8a395acb18100c7e2b161701c225adf31eefa02114099b4d81a30b"})
|
||||||
|
(connect-card))
|
||||||
|
|
||||||
(defn disconnect-card []
|
(defn disconnect-card []
|
||||||
(swap! state assoc :card-connected? false)
|
(swap! state assoc :card-connected? false)
|
||||||
(doseq [callback (vals (get @state :on-card-disconnected))]
|
(doseq [callback (vals (get @state :on-card-disconnected))]
|
||||||
|
@ -45,7 +63,8 @@
|
||||||
(reset! state initial-state))
|
(reset! state initial-state))
|
||||||
|
|
||||||
(defn- later [f]
|
(defn- later [f]
|
||||||
(utils/set-timeout f 500))
|
(when f
|
||||||
|
(utils/set-timeout f 500)))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
@ -88,6 +107,7 @@
|
||||||
(def kk1-password "000000")
|
(def kk1-password "000000")
|
||||||
(def default-puk "000000000000")
|
(def default-puk "000000000000")
|
||||||
(defn init-card [{:keys [pin on-success]}]
|
(defn init-card [{:keys [pin on-success]}]
|
||||||
|
(reset! initialization true)
|
||||||
(swap! state assoc :application-info
|
(swap! state assoc :application-info
|
||||||
{:free-pairing-slots 5
|
{:free-pairing-slots 5
|
||||||
:app-version "2.2"
|
:app-version "2.2"
|
||||||
|
@ -107,48 +127,84 @@
|
||||||
|
|
||||||
(def kk1-pair "ADEol+GCD67EO7zU6ko0DNK7XrNs9w2+h9GxcibNY4yf")
|
(def kk1-pair "ADEol+GCD67EO7zU6ko0DNK7XrNs9w2+h9GxcibNY4yf")
|
||||||
|
|
||||||
|
(def derived-acc (atom nil))
|
||||||
|
|
||||||
|
(defn multiaccount->keys [pin data]
|
||||||
|
(let [{:keys [selected-id multiaccounts root-key derived]}
|
||||||
|
data
|
||||||
|
|
||||||
|
{:keys [id address public-key derived key-uid]}
|
||||||
|
(or (->> multiaccounts
|
||||||
|
(filter #(= (:id %) selected-id))
|
||||||
|
first)
|
||||||
|
(assoc root-key :derived derived))
|
||||||
|
|
||||||
|
whisper (get derived constants/path-whisper-keyword)
|
||||||
|
wallet (get derived constants/path-default-wallet-keyword)
|
||||||
|
wallet-root (get derived constants/path-wallet-root-keyword)
|
||||||
|
password (ethereum/sha3 pin)
|
||||||
|
response {:key-uid key-uid
|
||||||
|
:encryption-public-key password
|
||||||
|
:address address
|
||||||
|
:whisper-public-key (:public-key whisper)
|
||||||
|
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
|
||||||
|
:wallet-root-public-key (:public-key wallet-root)
|
||||||
|
:wallet-root-address (:address wallet-root)
|
||||||
|
:whisper-address (:address whisper)
|
||||||
|
:public-key public-key
|
||||||
|
:whisper-private-key "34bc7d0c258c4f2ac1dac4fd6c55c9478bac1f4a9d8b9f1152c8551ab7187b43"
|
||||||
|
:wallet-address (:address wallet)
|
||||||
|
:wallet-public-key (:public-key wallet)}]
|
||||||
|
[id response]))
|
||||||
|
|
||||||
(defn pair [{:keys [password on-success]}]
|
(defn pair [{:keys [password on-success]}]
|
||||||
|
(when (and (not @initialization)
|
||||||
|
(not @derived-acc))
|
||||||
|
(status/multiaccount-import-mnemonic
|
||||||
|
"night fortune spider version version armed amused winner matter tonight cave flag"
|
||||||
|
nil
|
||||||
|
(fn [result]
|
||||||
|
(let [{:keys [id] :as root-data}
|
||||||
|
(multiaccounts.create/normalize-multiaccount-data-keys
|
||||||
|
(types/json->clj result))]
|
||||||
|
(status-im.native-module.core/multiaccount-derive-addresses
|
||||||
|
id
|
||||||
|
[constants/path-wallet-root
|
||||||
|
constants/path-eip1581
|
||||||
|
constants/path-whisper
|
||||||
|
constants/path-default-wallet]
|
||||||
|
(fn [result]
|
||||||
|
(let [derived-data (multiaccounts.create/normalize-derived-data-keys
|
||||||
|
(types/json->clj result))
|
||||||
|
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
|
||||||
|
(status/gfycat-identicon-async
|
||||||
|
public-key
|
||||||
|
(fn [name photo-path]
|
||||||
|
(let [derived-data-extended
|
||||||
|
(update derived-data
|
||||||
|
constants/path-whisper-keyword
|
||||||
|
merge {:name name :photo-path photo-path})]
|
||||||
|
(reset! derived-acc
|
||||||
|
{:root-key root-data
|
||||||
|
:derived derived-data-extended})))))))))))
|
||||||
(when (= password kk1-password)
|
(when (= password kk1-password)
|
||||||
(later #(on-success kk1-pair))))
|
(later #(on-success (str (rand-int 10000000))))))
|
||||||
|
|
||||||
(defn generate-and-load-key
|
(defn generate-and-load-key
|
||||||
[{:keys [pin pairing on-success]}]
|
[{:keys [pin on-success]}]
|
||||||
(when (and (= pin (get @state :pin))
|
(when (= pin (get @state :pin))
|
||||||
(= pairing kk1-pair))
|
(let [[id response] (multiaccount->keys
|
||||||
(let [{:keys [selected-id multiaccounts root-key derived]}
|
pin
|
||||||
(:intro-wizard @re-frame.db/app-db)
|
(:intro-wizard @re-frame.db/app-db))]
|
||||||
|
|
||||||
{:keys [id address public-key derived key-uid]}
|
|
||||||
(or (->> multiaccounts
|
|
||||||
(filter #(= (:id %) selected-id))
|
|
||||||
first)
|
|
||||||
(assoc root-key :derived derived))
|
|
||||||
|
|
||||||
whisper (get derived constants/path-whisper-keyword)
|
|
||||||
wallet (get derived constants/path-default-wallet-keyword)
|
|
||||||
wallet-root (get derived constants/path-wallet-root-keyword)
|
|
||||||
password (ethereum/sha3 pin)
|
|
||||||
response {:key-uid key-uid
|
|
||||||
:encryption-public-key (ethereum/sha3 pin)
|
|
||||||
:address address
|
|
||||||
:whisper-public-key (:public-key whisper)
|
|
||||||
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
|
|
||||||
:wallet-root-public-key (:public-key wallet-root)
|
|
||||||
:wallet-root-address (:address wallet-root)
|
|
||||||
:whisper-address (:address whisper)
|
|
||||||
:public-key public-key
|
|
||||||
:whisper-private-key "34bc7d0c258c4f2ac1dac4fd6c55c9478bac1f4a9d8b9f1152c8551ab7187b43"
|
|
||||||
:wallet-address (:address wallet)
|
|
||||||
:wallet-public-key (:public-key wallet)}]
|
|
||||||
(log/debug "[simulated kk] generate-and-load-key response" response)
|
(log/debug "[simulated kk] generate-and-load-key response" response)
|
||||||
(status/multiaccount-store-derived
|
(status/multiaccount-store-derived
|
||||||
id
|
id
|
||||||
key-uid
|
(:key-uid response)
|
||||||
[constants/path-wallet-root
|
[constants/path-wallet-root
|
||||||
constants/path-eip1581
|
constants/path-eip1581
|
||||||
constants/path-whisper
|
constants/path-whisper
|
||||||
constants/path-default-wallet]
|
constants/path-default-wallet]
|
||||||
password
|
(ethereum/sha3 pin)
|
||||||
#(on-success response)))))
|
#(on-success response)))))
|
||||||
|
|
||||||
(defn unblock-pin
|
(defn unblock-pin
|
||||||
|
@ -168,9 +224,8 @@
|
||||||
#js {:code "EUNSPECIFIED"
|
#js {:code "EUNSPECIFIED"
|
||||||
:message "Unexpected error SW, 0x63C2"})))))
|
:message "Unexpected error SW, 0x63C2"})))))
|
||||||
|
|
||||||
(defn verify-pin [{:keys [pin pairing on-success on-failure]}]
|
(defn verify-pin [{:keys [pin on-success on-failure]}]
|
||||||
(if (and (= pairing kk1-pair)
|
(if (= pin (get @state :pin))
|
||||||
(= pin (get @state :pin)))
|
|
||||||
(later #(on-success 3))
|
(later #(on-success 3))
|
||||||
(do
|
(do
|
||||||
(swap! state update-in
|
(swap! state update-in
|
||||||
|
@ -242,9 +297,20 @@
|
||||||
(do
|
(do
|
||||||
(swap! state assoc :pin pin)
|
(swap! state assoc :pin pin)
|
||||||
(later
|
(later
|
||||||
#(on-success
|
(if @derived-acc
|
||||||
{:key-uid (get-in @state [:application-info :key-uid])
|
(let [[id keys] (multiaccount->keys pin @derived-acc)]
|
||||||
:encryption-public-key (ethereum/sha3 pin)})))
|
(status/multiaccount-store-derived
|
||||||
|
id
|
||||||
|
(:key-uid keys)
|
||||||
|
[constants/path-wallet-root
|
||||||
|
constants/path-eip1581
|
||||||
|
constants/path-whisper
|
||||||
|
constants/path-default-wallet]
|
||||||
|
(ethereum/sha3 pin)
|
||||||
|
#(on-success keys)))
|
||||||
|
#(on-success
|
||||||
|
{:key-uid (get-in @state [:application-info :key-uid])
|
||||||
|
:encryption-public-key (ethereum/sha3 pin)}))))
|
||||||
(do
|
(do
|
||||||
(log/debug "Incorrect PIN" pin)
|
(log/debug "Incorrect PIN" pin)
|
||||||
(swap! state update-in
|
(swap! state update-in
|
||||||
|
@ -255,7 +321,7 @@
|
||||||
#js {:code "EUNSPECIFIED"
|
#js {:code "EUNSPECIFIED"
|
||||||
:message "Unexpected error SW, 0x63C2"})))))
|
:message "Unexpected error SW, 0x63C2"})))))
|
||||||
|
|
||||||
(defn sign [{:keys [pin hash data path on-success on-failure]}]
|
(defn sign [{:keys [pin hash data path typed? on-success on-failure]}]
|
||||||
(if (= pin (get @state :pin))
|
(if (= pin (get @state :pin))
|
||||||
(later
|
(later
|
||||||
#(let [address
|
#(let [address
|
||||||
|
@ -269,18 +335,30 @@
|
||||||
(-> (:multiaccount/accounts @re-frame.db/app-db)
|
(-> (:multiaccount/accounts @re-frame.db/app-db)
|
||||||
first
|
first
|
||||||
:address))
|
:address))
|
||||||
params (types/clj->json
|
password (ethereum/sha3 pin)]
|
||||||
{:account address
|
(if-not typed?
|
||||||
:password (ethereum/sha3 pin)
|
(let [params (types/clj->json
|
||||||
:data (or data (str "0x" hash))})]
|
{:account address
|
||||||
(status/sign-message
|
:password password
|
||||||
params
|
:data (or data (str "0x" hash))})]
|
||||||
(fn [res]
|
(status/sign-message
|
||||||
(let [signature (-> res
|
params
|
||||||
types/json->clj
|
(fn [res]
|
||||||
:result
|
(let [signature (-> res
|
||||||
ethereum/normalized-hex)]
|
types/json->clj
|
||||||
(on-success signature))))))
|
:result
|
||||||
|
ethereum/normalized-hex)]
|
||||||
|
(on-success signature)))))
|
||||||
|
(status/sign-typed-data
|
||||||
|
data
|
||||||
|
address
|
||||||
|
password
|
||||||
|
(fn [res]
|
||||||
|
(let [signature (-> res
|
||||||
|
types/json->clj
|
||||||
|
:result
|
||||||
|
ethereum/normalized-hex)]
|
||||||
|
(on-success signature)))))))
|
||||||
(do
|
(do
|
||||||
(swap! state update-in
|
(swap! state update-in
|
||||||
[:application-info :pin-retry-counter]
|
[:application-info :pin-retry-counter]
|
||||||
|
@ -313,58 +391,86 @@
|
||||||
(defrecord SimulatedKeycard []
|
(defrecord SimulatedKeycard []
|
||||||
keycard/Keycard
|
keycard/Keycard
|
||||||
(keycard/check-nfc-support [this args]
|
(keycard/check-nfc-support [this args]
|
||||||
|
(log/debug "simulated card check-nfc-support")
|
||||||
(check-nfc-support args))
|
(check-nfc-support args))
|
||||||
(keycard/check-nfc-enabled [this args]
|
(keycard/check-nfc-enabled [this args]
|
||||||
|
(log/debug "simulated card check-nfc-enabled")
|
||||||
(check-nfc-enabled args))
|
(check-nfc-enabled args))
|
||||||
(keycard/open-nfc-settings [this]
|
(keycard/open-nfc-settings [this]
|
||||||
|
(log/debug "simulated card open-nfc-setting")
|
||||||
(open-nfc-settings))
|
(open-nfc-settings))
|
||||||
(keycard/register-card-events [this args]
|
(keycard/register-card-events [this args]
|
||||||
|
(log/debug "simulated card register-card-event")
|
||||||
(register-card-events args))
|
(register-card-events args))
|
||||||
(keycard/on-card-connected [this callback]
|
(keycard/on-card-connected [this callback]
|
||||||
|
(log/debug "simulated card on-card-connected")
|
||||||
(on-card-connected callback))
|
(on-card-connected callback))
|
||||||
(keycard/on-card-disconnected [this callback]
|
(keycard/on-card-disconnected [this callback]
|
||||||
|
(log/debug "simulated card on-card-disconnected")
|
||||||
(on-card-disconnected callback))
|
(on-card-disconnected callback))
|
||||||
(keycard/remove-event-listener [this event]
|
(keycard/remove-event-listener [this event]
|
||||||
|
(log/debug "simulated card remove-event-listener")
|
||||||
(remove-event-listener event))
|
(remove-event-listener event))
|
||||||
(keycard/remove-event-listeners [this]
|
(keycard/remove-event-listeners [this]
|
||||||
|
(log/debug "simulated card remove-event-listener")
|
||||||
(remove-event-listeners))
|
(remove-event-listeners))
|
||||||
(keycard/get-application-info [this args]
|
(keycard/get-application-info [this args]
|
||||||
|
(log/debug "simulated card get-application-info")
|
||||||
(get-application-info args))
|
(get-application-info args))
|
||||||
(keycard/install-applet [this args]
|
(keycard/install-applet [this args]
|
||||||
|
(log/debug "simulated card install-applet")
|
||||||
(install-applet args))
|
(install-applet args))
|
||||||
(keycard/init-card [this args]
|
(keycard/init-card [this args]
|
||||||
|
(log/debug "simulated card init-card")
|
||||||
(init-card args))
|
(init-card args))
|
||||||
(keycard/install-applet-and-init-card [this args]
|
(keycard/install-applet-and-init-card [this args]
|
||||||
|
(log/debug "simulated card install-applet-and-init-card")
|
||||||
(install-applet-and-init-card args))
|
(install-applet-and-init-card args))
|
||||||
(keycard/pair [this args]
|
(keycard/pair [this args]
|
||||||
|
(log/debug "simulated card pair")
|
||||||
(pair args))
|
(pair args))
|
||||||
(keycard/generate-and-load-key [this args]
|
(keycard/generate-and-load-key [this args]
|
||||||
|
(log/debug "simulated card generate-and-load-key")
|
||||||
(generate-and-load-key args))
|
(generate-and-load-key args))
|
||||||
(keycard/unblock-pin [this args]
|
(keycard/unblock-pin [this args]
|
||||||
|
(log/debug "simulated card unblock-pin")
|
||||||
(unblock-pin args))
|
(unblock-pin args))
|
||||||
(keycard/verify-pin [this args]
|
(keycard/verify-pin [this args]
|
||||||
|
(log/debug "simulated card verify-pin")
|
||||||
(verify-pin args))
|
(verify-pin args))
|
||||||
(keycard/change-pin [this args]
|
(keycard/change-pin [this args]
|
||||||
|
(log/debug "simulated card change-pin")
|
||||||
(change-pin args))
|
(change-pin args))
|
||||||
(keycard/unpair [this args]
|
(keycard/unpair [this args]
|
||||||
|
(log/debug "simulated card unpair")
|
||||||
(unpair args))
|
(unpair args))
|
||||||
(keycard/delete [this args]
|
(keycard/delete [this args]
|
||||||
|
(log/debug "simulated card delete")
|
||||||
(delete args))
|
(delete args))
|
||||||
(keycard/remove-key [this args]
|
(keycard/remove-key [this args]
|
||||||
|
(log/debug "simulated card remove-key")
|
||||||
(remove-key args))
|
(remove-key args))
|
||||||
(keycard/remove-key-with-unpair [this args]
|
(keycard/remove-key-with-unpair [this args]
|
||||||
|
(log/debug "simulated card remove-key-with-unpair")
|
||||||
(remove-key-with-unpair args))
|
(remove-key-with-unpair args))
|
||||||
(keycard/export-key [this args]
|
(keycard/export-key [this args]
|
||||||
|
(log/debug "simulated card export-key")
|
||||||
(export-key args))
|
(export-key args))
|
||||||
(keycard/unpair-and-delete [this args]
|
(keycard/unpair-and-delete [this args]
|
||||||
|
(log/debug "simulated card unpair-and-delete")
|
||||||
(unpair-and-delete args))
|
(unpair-and-delete args))
|
||||||
(keycard/get-keys [this args]
|
(keycard/get-keys [this args]
|
||||||
|
(log/debug "simulated card get-keys")
|
||||||
(get-keys args))
|
(get-keys args))
|
||||||
(keycard/sign [this args]
|
(keycard/sign [this args]
|
||||||
|
(log/debug "simulated card sign")
|
||||||
(sign args))
|
(sign args))
|
||||||
(keycard/save-multiaccount-and-login [this args]
|
(keycard/save-multiaccount-and-login [this args]
|
||||||
|
(log/debug "simulated card save-multiaccount-and-login")
|
||||||
(save-multiaccount-and-login args))
|
(save-multiaccount-and-login args))
|
||||||
(keycard/login [this args]
|
(keycard/login [this args]
|
||||||
|
(log/debug "simulated card login")
|
||||||
(login args))
|
(login args))
|
||||||
(keycard/send-transaction-with-signature [this args]
|
(keycard/send-transaction-with-signature [this args]
|
||||||
|
(log/debug "simulated card send-transaction-with-signature")
|
||||||
(send-transaction-with-signature args)))
|
(send-transaction-with-signature args)))
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
:align-items :center}}
|
:align-items :center}}
|
||||||
[button "conn" :connect-card simulated-keycard/connect-card]
|
[button "conn" :connect-card simulated-keycard/connect-card]
|
||||||
[button "conn sell" :connect-selected-card simulated-keycard/connect-selected-card]
|
[button "conn sell" :connect-selected-card simulated-keycard/connect-selected-card]
|
||||||
|
[button "pair" :connect-pairing-card simulated-keycard/connect-pairing-card]
|
||||||
[button "disc" :disconnect-card simulated-keycard/disconnect-card]
|
[button "disc" :disconnect-card simulated-keycard/disconnect-card]
|
||||||
[button "res" :keycard-reset-state simulated-keycard/reset-state]])
|
[button "res" :keycard-reset-state simulated-keycard/reset-state]])
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
(let [{:keys [result error]} (types/json->clj result)]
|
(let [{:keys [result error]} (types/json->clj result)]
|
||||||
{:db (update db :hardwallet assoc
|
{:db (update db :hardwallet assoc
|
||||||
:hash result
|
:hash result
|
||||||
:type? typed?
|
:typed? typed?
|
||||||
:data data)}))
|
:data data)}))
|
||||||
|
|
||||||
(fx/defn hash-transaction
|
(fx/defn hash-transaction
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.ui.screens.hardwallet.setup.subs
|
(ns status-im.ui.screens.hardwallet.setup.subs
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[clojure.string :as string]))
|
[clojure.string :as string]
|
||||||
|
[status-im.ethereum.core :as ethereum]))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:hardwallet-setup-step
|
:hardwallet-setup-step
|
||||||
|
@ -101,4 +102,4 @@
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:hardwallet-multiaccount-whisper-public-key
|
:hardwallet-multiaccount-whisper-public-key
|
||||||
(fn [db]
|
(fn [db]
|
||||||
(str "0x" (get-in db [:hardwallet :multiaccount-whisper-public-key]))))
|
(ethereum/normalized-hex (get-in db [:hardwallet :multiaccount-whisper-public-key]))))
|
||||||
|
|
Loading…
Reference in New Issue