Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General QR code scanner flow #18677

Merged
merged 19 commits into from
Feb 16, 2024
5 changes: 4 additions & 1 deletion modules/react-native-status/ios/RCTStatus/Utils.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,12 @@ + (void) migrateKeystore:(NSString *)accountData
return StatusgoCheckAddressChecksum(address);
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isAddress:(NSString *)address) {
return StatusgoIsAddress(address);
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
return StatusgoToChecksumAddress(address);
}


@end
2 changes: 1 addition & 1 deletion src/legacy/status_im/mobile_sync_settings/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
[(mailserver/process-next-messages-request)
(bottom-sheet/hide-bottom-sheet-old)
(wallet/restart-wallet-service nil)
(add-new-contact/set-new-identity-reconnected)]
#(add-new-contact/set-new-identity-reconnected %)]

logged-in?
[(mailserver/process-next-messages-request)
Expand Down
6 changes: 5 additions & 1 deletion src/legacy/status_im/profile/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,9 @@
{:db (-> db
(assoc :contacts/identity identity)
(assoc :contacts/ens-name ens-name))
:dispatch [:contacts/build-contact identity ens-name true]}
:dispatch [:contacts/build-contact
{:pubkey identity
:ens ens-name
:success-fn (fn [_]
{:dispatch [:open-modal :profile]})}]}
{:dispatch [:navigate-to :my-profile]})))
3 changes: 2 additions & 1 deletion src/legacy/status_im/ui/screens/wallet/recipient/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
:on-change (fn [text]
(re-frame/dispatch [:wallet-legacy/search-recipient-filter-changed text])
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
(debounce/debounce-and-dispatch [:contacts/set-new-identity text] 300))}]]))
(debounce/debounce-and-dispatch [:contacts/set-new-identity {:input text}]
300))}]]))

(defn section
[_ _ _]
Expand Down
2 changes: 1 addition & 1 deletion src/status_im/common/home/top_nav/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
nil)]
[quo/top-nav
{:avatar-on-press #(rf/dispatch [:open-modal :settings])
:scan-on-press #(js/alert "to be implemented")
:scan-on-press #(rf/dispatch [:open-modal :shell-qr-reader])
:activity-center-on-press #(rf/dispatch [:activity-center/open])
:qr-code-on-press #(rf/dispatch [:open-modal :share-shell])
:container-style (merge style/top-nav-container container-style)
Expand Down
28 changes: 19 additions & 9 deletions src/status_im/common/router.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,18 @@

(def web2-domain "status.app")

(def user-path "u#")
(def user-with-data-path "u/")
(def community-path "c#")
(def community-with-data-path "c/")
(def channel-path "cc/")

(def web-urls (map #(str % web2-domain "/") web-prefixes))

(defn path-urls
[path]
(map #(str % path) web-urls))

(def handled-schemes (set (into uri-schemes web-urls)))

(def group-chat-extractor
Expand All @@ -41,15 +51,15 @@

(def routes
[""
{handled-schemes {["c/" :community-data] :community
["cc/" :community-data] :community-chat
["p/" :chat-id] :private-chat
["cr/" :community-id] :community-requests
"g/" group-chat-extractor
["wallet/" :account] :wallet-account
["u/" :user-data] :user
"c" :community
"u" :user}
{handled-schemes {[community-with-data-path :community-data] :community
[channel-path :community-data] :community-chat
["p/" :chat-id] :private-chat
["cr/" :community-id] :community-requests
"g/" group-chat-extractor
["wallet/" :account] :wallet-account
[user-with-data-path :user-data] :user
"c" :community
"u" :user}
ethereum-scheme eip-extractor}])

(defn parse-query-params
Expand Down
119 changes: 65 additions & 54 deletions src/status_im/contexts/chat/home/add_new_contact/events.cljs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
(ns status-im.contexts.chat.home.add-new-contact.events
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm always unsure when we want to use utils.re-frame and re-frame.core.
@ilmotta, @flexsurfer is there any reasoning we have both of these options when a lot of the same logic is accessible from both??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utils.re-frame has one defn marco which is deprecated now that's why I used re-frame.core here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-frame.core shouldn't be used, rf/sub and rf/dispatch should be used instead from utils.re-frame

[status-im.common.validators :as validators]
[status-im.contexts.chat.contacts.events :as data-store.contacts]
status-im.contexts.chat.home.add-new-contact.effects
[status-im.navigation.events :as navigation]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.re-frame :as rf]
[utils.string :as utils.string]))

(defn init-contact
Expand Down Expand Up @@ -87,72 +86,64 @@

(def validate-contact (comp ->state ->type ->id))

(defn dispatcher [event input] (fn [arg] (rf/dispatch [event input arg])))
(declare build-contact)

(rf/defn set-new-identity
{:events [:contacts/set-new-identity]}
[{:keys [db]} input scanned]
(defn set-new-identity
alwx marked this conversation as resolved.
Show resolved Hide resolved
[{:keys [db]} [{:keys [input build-success-fn failure-fn]}]]
(let [user-public-key (get-in db [:profile/profile :public-key])
{:keys [input id ens state]
:as contact} (-> {:user-public-key user-public-key
:input input
:scanned scanned}
:scanned input}
init-contact
validate-contact)]
(case state

:empty {:db (dissoc db :contacts/new-identity)}
(:valid :invalid) {:db (assoc db :contacts/new-identity contact)}
:decompress-key {:db (assoc db :contacts/new-identity contact)
:serialization/decompress-public-key
{:compressed-key id
:on-success
(dispatcher :contacts/set-new-identity-success input)
#(re-frame/dispatch [:contacts/set-new-identity-success
{:input input
:pubkey %
:build-success-fn build-success-fn}])
:on-error
(dispatcher :contacts/set-new-identity-error input)}}
#(re-frame/dispatch [:contacts/set-new-identity-error
{:input input
:pubkey %
:failure-fn failure-fn}])}}
:resolve-ens {:db (assoc db :contacts/new-identity contact)
:effects.contacts/resolve-public-key-from-ens
{:chain-id (chain/chain-id db)
:ens ens
:on-success
(dispatcher :contacts/set-new-identity-success input)
#(re-frame/dispatch [:contacts/set-new-identity-success
{:input input
:pubkey %
:build-success-fn build-success-fn}])
:on-error
(dispatcher :contacts/set-new-identity-error input)}})))

#(re-frame/dispatch [:contacts/set-new-identity-error
{:input input
:pubkey %
:failure-fn failure-fn}])}})))

(re-frame/reg-event-fx :contacts/set-new-identity set-new-identity)

(rf/defn build-contact
{:events [:contacts/build-contact]}
[_ pubkey ens open-profile-modal?]
{:json-rpc/call [{:method "wakuext_buildContact"
:params [{:publicKey pubkey
:ENSName ens}]
:js-response true
:on-success #(rf/dispatch [:contacts/contact-built
pubkey
open-profile-modal?
(data-store.contacts/<-rpc-js %)])}]})

(rf/defn contact-built
{:events [:contacts/contact-built]}
[{:keys [db]} pubkey open-profile-modal? contact]
(merge {:db (assoc-in db [:contacts/contacts pubkey] contact)}
(when open-profile-modal?
{:dispatch [:open-modal :profile]})))

(rf/defn set-new-identity-success
{:events [:contacts/set-new-identity-success]}
[{:keys [db]} input pubkey]
(defn- set-new-identity-success
[{:keys [db]} [{:keys [input pubkey build-success-fn]}]]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
(rf/merge {:db (assoc db
:contacts/new-identity
(->state (assoc contact :public-key pubkey)))}
(build-contact pubkey (:ens contact) false)))))

(rf/defn set-new-identity-error
{:events [:contacts/set-new-identity-error]}
[{:keys [db]} input err]
{:db (assoc db :contacts/new-identity (->state (assoc contact :public-key pubkey)))
:dispatch [:contacts/build-contact
{:pubkey pubkey
:ens (:ens contact)
:success-fn build-success-fn}]})))

(re-frame/reg-event-fx :contacts/set-new-identity-success set-new-identity-success)

(defn- set-new-identity-error
[{:keys [db]} [{:keys [input err failure-fn]}]]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
(let [state (cond
Expand All @@ -163,21 +154,41 @@
(string/includes? (:message err) "no such host")))
{:state :invalid :msg :t/lost-connection}
:else {:state :invalid})]
{:db (assoc db :contacts/new-identity (merge contact state))}))))
(merge {:db (assoc db :contacts/new-identity (merge contact state))}
(when failure-fn
(failure-fn)))))))

(re-frame/reg-event-fx :contacts/set-new-identity-error set-new-identity-error)

(rf/defn clear-new-identity
{:events [:contacts/clear-new-identity :contacts/new-chat-focus]}
(defn- build-contact
[_ [{:keys [pubkey ens success-fn]}]]
{:json-rpc/call [{:method "wakuext_buildContact"
:params [{:publicKey pubkey
:ENSName ens}]
:js-response true
:on-success #(re-frame/dispatch [:contacts/build-contact-success
{:pubkey pubkey
:contact (data-store.contacts/<-rpc-js %)
:success-fn success-fn}])}]})

(re-frame/reg-event-fx :contacts/build-contact build-contact)

(defn- build-contact-success
[{:keys [db]} [{:keys [pubkey contact success-fn]}]]
(merge {:db (assoc-in db [:contacts/contacts pubkey] contact)}
(when success-fn
(success-fn contact))))

(re-frame/reg-event-fx :contacts/build-contact-success build-contact-success)

(defn- clear-new-identity
[{:keys [db]}]
{:db (dissoc db :contacts/new-identity)})

(rf/defn qr-code-scanned
{:events [:contacts/qr-code-scanned]}
[{:keys [db] :as cofx} scanned]
(rf/merge cofx
(set-new-identity scanned scanned)
(navigation/navigate-back)))
(re-frame/reg-event-fx :contacts/clear-new-identity clear-new-identity)

(rf/defn set-new-identity-reconnected
(defn set-new-identity-reconnected
[{:keys [db]}]
(let [input (get-in db [:contacts/new-identity :input])]
(rf/dispatch [:contacts/set-new-identity input])))
(re-frame/dispatch [:contacts/set-new-identity {:input input}])))

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(:require
[cljs.test :refer-macros [deftest are]]
matcher-combinators.test
[re-frame.core :as re-frame]
[status-im.contexts.chat.home.add-new-contact.events :as events]))

(def user-ukey
Expand Down Expand Up @@ -90,8 +91,8 @@
:config {:NetworkId 1}}}})

(deftest set-new-identity-test
(with-redefs [events/dispatcher (fn [& args] args)]
(are [i edb] (match? (events/set-new-identity {:db db} i nil) edb)
(with-redefs [re-frame/dispatch (fn [& args] args)]
(are [i edb] (match? (events/set-new-identity {:db db} [{:input i}]) edb)

"" {:db db}

Expand All @@ -103,6 +104,7 @@
:id ukey
:type :public-key
:public-key ukey
:scanned ukey
:state :invalid
:msg :t/not-a-chatkey}))}

Expand All @@ -115,6 +117,7 @@
:type :ens
:ens ens-stateofus-eth
:public-key nil ; not yet...
:scanned ens
:state :resolve-ens}))
:effects.contacts/resolve-public-key-from-ens
{:chain-id 1
Expand All @@ -131,6 +134,7 @@
:id user-ckey
:type :compressed-key
:public-key nil ; not yet...
:scanned user-ckey
:state :decompress-key}))
:serialization/decompress-public-key
{:compressed-key user-ckey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
(rn/dismiss-keyboard!))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:on-success-scan #(debounce/debounce-and-dispatch [:contacts/set-new-identity % %] 300)}]]))
:on-success-scan #(debounce/debounce-and-dispatch [:contacts/set-new-identity {:input %}]
300)}]]))

(defn view
[]
Expand Down
5 changes: 3 additions & 2 deletions src/status_im/contexts/chat/home/add_new_contact/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
paste-on-input #(clipboard/get-string
(fn [clipboard-text]
(reset! input-value clipboard-text)
(rf/dispatch [:contacts/set-new-identity clipboard-text nil])))]
(rf/dispatch [:contacts/set-new-identity
{:input clipboard-text}])))]
(let [{:keys [scanned]} (rf/sub [:contacts/new-identity])
empty-input? (and (string/blank? @input-value)
(string/blank? scanned))]
Expand All @@ -86,7 +87,7 @@
:value (or scanned @input-value)
:on-change-text (fn [new-text]
(reset! input-value new-text)
(as-> [:contacts/set-new-identity new-text nil] $
(as-> [:contacts/set-new-identity {:input new-text}] $
(if (string/blank? scanned)
(debounce/debounce-and-dispatch $ 600)
(rf/dispatch-sync $))))}]
Expand Down
Loading