Fix topic issue, remove ttt, add db export/import

There were a few issues with topic management:

- Topics/ranges were saved one-by-one, which cause an out of memory
error on some devices
- Topics that were not listened to were saved, and therefore requested
from the mailserver, which caused long syncing time

It also removes tribute to talk and add export/import methods

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2021-01-18 14:01:57 +01:00
parent 9bf4da1edd
commit eba6b63258
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
37 changed files with 248 additions and 2068 deletions

1
.env
View File

@ -28,3 +28,4 @@ MAX_IMAGES_BATCH=5
APN_TOPIC=im.status.ethereum.pr
COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1

View File

@ -28,3 +28,4 @@ APN_TOPIC=im.status.ethereum.pr
VERIFY_TRANSACTION_CHAIN_ID=3
COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=0
DATABASE_MANAGEMENT_ENABLED=1

View File

@ -28,3 +28,4 @@ MAX_IMAGES_BATCH=5
GOOGLE_FREE=0
COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=0
DATABASE_MANAGEMENT_ENABLED=1

View File

@ -21,3 +21,4 @@ ENABLE_REFERRAL_INVITE=0
MAX_IMAGES_BATCH=5
BLANK_PREVIEW=0
COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1

View File

@ -75,6 +75,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
private static final String TAG = "StatusModule";
private static final String logsZipFileName = "Status-debug-logs.zip";
private static final String gethLogFileName = "geth.log";
private static final String exportDBFileName = "export.db";
private static final String statusLogFileName = "Status.log";
private static StatusModule module;
private ReactApplicationContext reactContext;
@ -193,6 +194,16 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
return logFile;
}
private File getExportDBFile() {
final Context context = this.getReactApplicationContext();
// Environment.getExternalStoragePublicDirectory doesn't work as expected on Android Q
// https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)
final File pubDirectory = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
final File filename = new File(pubDirectory, exportDBFileName);
return filename;
}
private File prepareLogsFile(final Context context) {
final File logFile = getLogsFile();
@ -398,6 +409,36 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
}
@ReactMethod
public void exportUnencryptedDatabase(final String accountData, final String password) {
Log.d(TAG, "login");
final File newFile = getExportDBFile();
this.migrateKeyStoreDir(accountData, password);
String result = Statusgo.exportUnencryptedDatabase(accountData, password, newFile.getAbsolutePath());
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "Login result: " + result);
} else {
Log.e(TAG, "Login failed: " + result);
}
}
@ReactMethod
public void importUnencryptedDatabase(final String accountData, final String password) {
Log.d(TAG, "importUnencryptedDatabase");
final File newFile = getExportDBFile();
this.migrateKeyStoreDir(accountData, password);
String result = Statusgo.importUnencryptedDatabase(accountData, password, newFile.getAbsolutePath());
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "import result: " + result);
} else {
Log.e(TAG, "import failed: " + result);
}
}
@ReactMethod
public void logout() {
Log.d(TAG, "logout");

View File

@ -768,7 +768,21 @@ RCT_EXPORT_METHOD(startLocalNotifications) {
StatusgoStartLocalNotifications();
}
RCT_EXPORT_METHOD(exportUnencryptedDatabase:(NSString *)accountData
password:(NSString *)password) {
#if DEBUG
NSLog(@"exportUnencryptedDatabase() method called");
#endif
"";
}
RCT_EXPORT_METHOD(importUnencryptedDatabase:(NSString *)accountData
password:(NSString *)password) {
#if DEBUG
NSLog(@"importUnencryptedDatabase() method called");
#endif
"";
}
RCT_EXPORT_METHOD(setBlankPreviewFlag:(BOOL *)newValue)
{

View File

@ -4,7 +4,6 @@
[status-im.ui.screens.chat.state :as chat.state]
[status-im.data-store.chats :as data-store.chats]
[status-im.data-store.messages :as data-store.messages]
[status-im.transport.filters.core :as filters]
[status-im.mailserver.core :as mailserver]
[status-im.utils.fx :as fx]
[status-im.chat.models.reactions :as reactions]
@ -29,10 +28,8 @@
{}
new-chats)
chats (merge old-chats chats)]
(fx/merge cofx
{:db (assoc db :chats chats
:chats/loading? false)}
(filters/load-filters))))
{:db (assoc db :chats chats
:chats/loading? false)}))
(fx/defn handle-chat-visibility-changed
{:events [:chat.ui/message-visibility-changed]}

View File

@ -5,8 +5,6 @@
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.mailserver.core :as mailserver]
[status-im.transport.filters.core :as transport.filters]
[status-im.tribute-to-talk.db :as tribute-to-talk]
[status-im.tribute-to-talk.whitelist :as whitelist]
[status-im.navigation :as navigation]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]
@ -19,19 +17,10 @@
(dissoc % :address)
%))
all-contacts)
contacts (into {} contacts-list)
tr-to-talk-enabled? (-> db tribute-to-talk/get-settings tribute-to-talk/enabled?)]
(fx/merge cofx
{:db (cond-> (-> db
(update :contacts/contacts #(merge contacts %))
(assoc :contacts/blocked (contact.db/get-blocked-contacts all-contacts)))
tr-to-talk-enabled?
(assoc :contacts/whitelist (whitelist/get-contact-whitelist all-contacts)))}
;; TODO: This is currently called twice, once we load chats & when we load filters.
;; For now leaving as it is as the next step is not to have this being called from status-react
;; as both contacts & chats are in status-go, but we still need to signals the filters to
;; status-react for mailsevers/gaps, so will address separately
(transport.filters/load-filters))))
contacts (into {} contacts-list)]
{:db (cond-> (-> db
(update :contacts/contacts #(merge contacts %))
(assoc :contacts/blocked (contact.db/get-blocked-contacts all-contacts))))}))
(defn build-contact
[{{:keys [multiaccount]
@ -92,7 +81,6 @@
{:db (dissoc db :contacts/new-identity)
:dispatch [:start-profile-chat public-key]}
(upsert-contact contact)
(whitelist/add-to-whitelist public-key)
(send-contact-request contact)
(mailserver/process-next-messages-request)))))
@ -129,17 +117,6 @@
:new-chat-name "")}
(navigation/navigate-to-cofx :create-group-chat nil)))
(fx/defn set-tribute
[{:keys [db] :as cofx} public-key tribute-to-talk]
(let [contact (-> (or (build-contact cofx public-key)
(get-in db [:contacts/contacts public-key]))
(assoc :tribute-to-talk (or tribute-to-talk
{:disabled? true})))]
{:db (assoc-in db [:contacts/contacts public-key] contact)
:insert-identicons [[public-key [:contacts/contacts public-key :identicon]]]
:insert-gfycats [[public-key [:contacts/contacts public-key :name]]
[public-key [:contacts/contacts public-key :alias]]]}))
(fx/defn name-verified
{:events [:contacts/ens-name-verified]}
[{:keys [db now] :as cofx} public-key ens-name]

View File

@ -116,20 +116,6 @@
([db public-key]
(active? (get-in db [:contacts/contacts public-key]))))
;;TODO TTT
#_(defn enrich-ttt-contact
[{:keys [system-tags tribute-to-talk] :as contact}]
(let [tribute (:snt-amount tribute-to-talk)
tribute-status (tribute-to-talk.db/tribute-status contact)
tribute-label (tribute-to-talk.db/status-label tribute-status tribute)]
(-> contact
(assoc-in [:tribute-to-talk :tribute-status] tribute-status)
(assoc-in [:tribute-to-talk :tribute-label] tribute-label)
(assoc :pending? (pending? contact)
:blocked? (blocked? contact)
:active? (active? contact)
:added? (contains? system-tags :contact/added)))))
(defn enrich-contact
([contact] (enrich-contact contact nil nil))
([{:keys [system-tags public-key] :as contact} setting own-public-key]

View File

@ -2,24 +2,16 @@
(:require [clojure.set :as clojure.set]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.fx :as fx]
[status-im.utils.types :as types]
[taoensso.timbre :as log]))
(defn deserialize-tribute-to-talk [t]
(if (seq t)
(types/deserialize t)
{}))
(defn <-rpc [contact]
(-> contact
(update :tributeToTalk deserialize-tribute-to-talk)
(update :systemTags
#(reduce (fn [acc s]
(conj acc (keyword (subs s 1))))
#{}
%))
(clojure.set/rename-keys {:id :public-key
:tributeToTalk :tribute-to-talk
:ensVerifiedAt :ens-verified-at
:ensVerified :ens-verified
:ensVerificationRetries :ens-verification-retries
@ -30,14 +22,12 @@
(defn ->rpc [contact]
(-> contact
(update :tribute-to-talk types/serialize)
(update :system-tags #(mapv str %))
(clojure.set/rename-keys {:public-key :id
:ens-verified :ensVerified
:ens-verified-at :ensVerifiedAt
:last-ens-clock-value :lastENSClockValue
:ens-verification-retries :ensVerificationRetries
:tribute-to-talk :tributeToTalk
:system-tags :systemTags
:last-updated :lastUpdated
:nickname :localNickname})))

View File

@ -7,14 +7,12 @@
:address "address"
:name "name"
:identicon "identicon"
:tribute-to-talk "tribute-to-talk"
:last-updated 1
:system-tags #{:a :b}}
expected-contact {:id "pk"
:address "address"
:name "name"
:identicon "identicon"
:tributeToTalk "\"tribute-to-talk\""
:lastUpdated 1
:systemTags #{":a" ":b"}}]
@ -29,15 +27,12 @@
:address "address"
:name "name"
:identicon "identicon"
:tributeToTalk "\"tribute-to-talk\""
:lastUpdated 1
:systemTags [":a" ":b"]}
expected-contact {:public-key "pk"
:address "address"
:name "name"
:identicon "identicon"
:tribute-to-talk "tribute-to-talk"
:last-updated 1
:system-tags #{:a :b}}]
(testing "<-rpc"

View File

@ -160,9 +160,11 @@
"mailservers_getMailservers" {}
"mailservers_deleteMailserver" {}
"mailservers_addMailserverTopic" {}
"mailservers_addMailserverTopics" {}
"mailservers_getMailserverTopics" {}
"mailservers_deleteMailserverTopic" {}
"mailservers_addChatRequestRange" {}
"mailservers_addChatRequestRanges" {}
"mailservers_getChatRequestRanges" {}
"mailservers_deleteChatRequestRange" {}})

View File

@ -152,9 +152,12 @@
(select-keys multiaccount [:key-uid :name :public-key :identicon :images]))))))
(handlers/register-handler-fx
:login/filters-initialized
(fn [cofx]
(universal-links/process-stored-event cofx)))
::transport/messenger-started
(fn [cofx [_ response]]
(fx/merge
cofx
(transport/messenger-started response)
(universal-links/process-stored-event))))
;; multiaccounts update module

View File

@ -328,7 +328,7 @@
- mailserver disconnected: we try to reconnect
- mailserver connected: we mark the mailserver as trusted peer"
[{:keys [db] :as cofx} previous-summary]
(when (and (not config/nimbus-enabled?) (:multiaccount db))
(when (:multiaccount db)
(if (:mailserver/current-id db)
(let [{:keys [peers-summary peers-count]} db
{:keys [address sym-key-id] :as mailserver} (fetch-current db)
@ -498,7 +498,7 @@
(fx/defn process-next-messages-request
[{:keys [db now] :as cofx}]
(when (and
(:filters/initialized db)
(:messenger/started? db)
(mobile-network-utils/syncing-allowed? cofx)
(fetch-use-mailservers? cofx)
(not (:mailserver/current-request db)))
@ -756,13 +756,11 @@
(fx/merge cofx
{:db (update db :mailserver/ranges merge updated-ranges)
::json-rpc/call
(mapv (fn [chat-requests-range]
{:method "mailservers_addChatRequestRange"
:params [chat-requests-range]
:on-success #()
:on-failure
#(log/error "failed to save chat request range" %)})
(vals updated-ranges))})))
[{:method "mailservers_addChatRequestRanges"
:params [(vals updated-ranges)]
:on-success #()
:on-failure
#(log/error "failed to save chat request range" %)}]})))
(defn prepare-new-gaps [new-gaps ranges {:keys [from to]} chat-ids]
(into
@ -886,14 +884,13 @@
(update :mailserver/planned-gap-requests
dissoc gap))
::json-rpc/call
(mapv (fn [[topic mailserver-topic]]
{:method "mailservers_addMailserverTopic"
:params [(assoc mailserver-topic :topic topic)]
:on-success
#(log/debug "added mailserver-topic successfully")
:on-failure
#(log/error "failed to add mailserver topic" %)})
mailserver-topics)}
[{:method "mailservers_addMailserverTopics"
:params [(mapv (fn [[topic mailserver-topic]]
(assoc mailserver-topic :topic topic)) mailserver-topics)]
:on-success
#(log/debug "added mailserver-topic successfully")
:on-failure
#(log/error "failed to add mailserver topic" %)}]}
(process-next-messages-request))))))))
(fx/defn retry-next-messages-request
@ -1043,7 +1040,9 @@
[cofx]
(fx/merge cofx
{:mailserver/set-limit constants/default-limit}
(set-current-mailserver)))
(set-current-mailserver)
(reset-request-to)
(process-next-messages-request)))
(def enode-address-regex
#"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")

View File

@ -86,8 +86,7 @@
new-mailserver-topic
{:now-s (quot now 1000)})]
(update-topic cofx
(new-chat-ids? old-mailserver-topic
new-mailserver-topic)
true
updated-topic))))
(fx/defn upsert-many [cofx mailserver-topics]

View File

@ -15,7 +15,7 @@
[status-im.notifications.core :as notifications]
[status-im.popover.core :as popover]
[status-im.communities.core :as communities]
[status-im.protocol.core :as protocol]
[status-im.transport.core :as transport]
[status-im.stickers.core :as stickers]
[status-im.ui.screens.mobile-network-settings.events :as mobile-network]
[status-im.navigation :as navigation]
@ -37,6 +37,16 @@
(fn [[key-uid account-data hashed-password]]
(status/login key-uid account-data hashed-password)))
(re-frame/reg-fx
::export-db
(fn [[key-uid account-data hashed-password]]
(status/export-db key-uid account-data hashed-password)))
(re-frame/reg-fx
::import-db
(fn [[key-uid account-data hashed-password]]
(status/import-db key-uid account-data hashed-password)))
(re-frame/reg-fx
::enable-local-notifications
(fn []
@ -87,6 +97,26 @@
:identicon identicon})
(ethereum/sha3 (security/safe-unmask-data password))]}))
(fx/defn export-db-submitted
{:events [:multiaccounts.login.ui/export-db-submitted]}
[{:keys [db]}]
(let [{:keys [key-uid password name identicon]} (:multiaccounts/login db)]
{::export-db [key-uid
(types/clj->json {:name name
:key-uid key-uid
:identicon identicon})
(ethereum/sha3 (security/safe-unmask-data password))]}))
(fx/defn import-db-submitted
{:events [:multiaccounts.login.ui/import-db-submitted]}
[{:keys [db]}]
(let [{:keys [key-uid password name identicon]} (:multiaccounts/login db)]
{::import-db [key-uid
(types/clj->json {:name name
:key-uid key-uid
:identicon identicon})
(ethereum/sha3 (security/safe-unmask-data password))]}))
(fx/defn finish-keycard-setup
[{:keys [db] :as cofx}]
(let [flow (get-in db [:keycard :flow])]
@ -217,9 +247,7 @@
(assoc ::notifications/enable nil))
(acquisition/login)
(initialize-appearance)
;; NOTE: initializing mailserver depends on user mailserver
;; preference which is why we wait for config callback
(protocol/initialize-protocol {:default-mailserver true})
(transport/start-messenger)
(check-network-version network-id)
(chat.loading/initialize-chats)
(communities/fetch)
@ -250,18 +278,12 @@
(fx/merge cofx
{:db (assoc db :chats/loading? true)
::json-rpc/call
[{:method "mailservers_getMailserverTopics"
:on-success #(re-frame/dispatch [::protocol/initialize-protocol {:mailserver-topics (or % {})}])}
{:method "mailservers_getChatRequestRanges"
:on-success #(re-frame/dispatch [::protocol/initialize-protocol {:mailserver-ranges (or % {})}])}
{:method "browsers_getBrowsers"
[{:method "browsers_getBrowsers"
:on-success #(re-frame/dispatch [::initialize-browsers %])}
{:method "browsers_getBookmarks"
:on-success #(re-frame/dispatch [::initialize-bookmarks %])}
{:method "permissions_getDappPermissions"
:on-success #(re-frame/dispatch [::initialize-dapp-permissions %])}
{:method "mailservers_getMailservers"
:on-success #(re-frame/dispatch [::protocol/initialize-protocol {:mailservers (or % [])}])}
{:method "settings_getSettings"
:on-success #(re-frame/dispatch [::get-settings-callback %])}]}
(notifications/load-notification-preferences)
@ -278,24 +300,10 @@
(fx/merge cofx
{:db (-> db
(dissoc :multiaccounts/login)
(assoc
;;NOTE when login the filters are initialized twice
;;once for contacts and once for chats
;;when creating an account we do it only once by calling
;;load-filters directly because we don't have chats and contacts
;;later on there is a check that filters have been initialized twice
;;so here we set it at 1 already so that it passes the check once it has
;;been initialized
:filters/initialized 1)
(assoc-in [:multiaccount :multiaccounts/first-account] first-account?))
:dispatch-later [{:ms 2000 :dispatch [::initialize-wallet accounts nil nil (:recovered multiaccount)]}]
:filters/load-filters [[]]}
:dispatch-later [{:ms 2000 :dispatch [::initialize-wallet accounts nil nil (:recovered multiaccount)]}]}
(finish-keycard-setup)
(protocol/initialize-protocol {:mailservers []
:mailserver-ranges {}
:mailserver-topics {}
:default-mailserver true})
(transport/start-messenger)
(communities/fetch)
(multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist)

View File

@ -72,6 +72,24 @@
key-uid
#(.login ^js (status) account-data hashed-password)))
(defn export-db
"NOTE: beware, the password has to be sha3 hashed"
[key-uid account-data hashed-password]
(log/debug "[native-module] export-db")
(clear-web-data)
(init-keystore
key-uid
#(.exportUnencryptedDatabase ^js (status) account-data hashed-password)))
(defn import-db
"NOTE: beware, the password has to be sha3 hashed"
[key-uid account-data hashed-password]
(log/debug "[native-module] import-db")
(clear-web-data)
(init-keystore
key-uid
#(.importUnencryptedDatabase ^js (status) account-data hashed-password)))
(defn logout []
(log/debug "[native-module] logout")
(clear-web-data)

View File

@ -1,71 +0,0 @@
(ns status-im.protocol.core
(:require [status-im.constants :as constants]
[status-im.transport.core :as transport]
[status-im.utils.fx :as fx]))
(defn add-custom-mailservers
[db custom-mailservers]
(reduce (fn [db {:keys [fleet] :as mailserver}]
(let [{:keys [id] :as mailserver}
(-> mailserver
(update :id keyword)
(dissoc :fleet)
(assoc :user-defined true))]
(assoc-in db
[:mailserver/mailservers (keyword fleet) id]
mailserver)))
db
custom-mailservers))
(defn add-mailserver-topics
[db mailserver-topics]
(assoc db
:mailserver/topics
(reduce (fn [acc {:keys [topic]
:as mailserver-topic}]
(assoc acc topic
(update mailserver-topic :chat-ids
#(into #{} %))))
{}
mailserver-topics)))
(defn add-mailserver-ranges
[db mailserver-ranges]
(assoc db
:mailserver/ranges
(reduce (fn [acc {:keys [chat-id] :as range}]
(assoc acc chat-id range))
{}
mailserver-ranges)))
(fx/defn initialize-protocol
{:events [::initialize-protocol]}
[{:keys [db] :as cofx}
{:keys [mailserver-ranges mailserver-topics mailservers] :as data}]
;; NOTE: we need to wait for `:mailservers` `:mailserver-ranges` and
;; `:mailserver-topics` before we can proceed to init whisper
;; since those are populated by separate events, we check here
;; that everything has been initialized before moving forward
(let [initialization-protocol (apply conj (get db :initialization-protocol #{})
(keys data))
initialization-complete? (= initialization-protocol
#{:mailservers
:mailserver-ranges
:mailserver-topics
:default-mailserver})]
(fx/merge cofx
{:db (cond-> db
mailserver-ranges
(add-mailserver-ranges mailserver-ranges)
mailserver-topics
(add-mailserver-topics mailserver-topics)
mailservers
(add-custom-mailservers mailservers)
initialization-complete?
(assoc :rpc-url constants/ethereum-rpc-url)
initialization-complete?
(dissoc :initialization-protocol)
(not initialization-complete?)
(assoc :initialization-protocol initialization-protocol))}
(when initialization-complete?
(transport/init-messenger)))))

View File

@ -24,9 +24,6 @@
[status-im.chat.models.reactions :as models.reactions]
[status-im.pairing.core :as pairing]
[status-im.signing.gas :as signing.gas]
#_[status-im.tribute-to-talk.core :as tribute-to-talk]
[status-im.tribute-to-talk.db :as tribute-to-talk.db]
[status-im.ui.components.colors :as colors]
[status-im.ui.screens.add-new.new-public-chat.db :as db]
[status-im.ui.screens.mobile-network-settings.utils
:as
@ -403,7 +400,7 @@
:disconnected?
:<- [:peers-count]
(fn [peers-count]
(and (not config/nimbus-enabled?) (zero? peers-count))))
(zero? peers-count)))
(re-frame/reg-sub
:offline?
@ -2152,102 +2149,6 @@
:tokens {true (apply-filter search-token-filter custom-tokens extract-token-attributes false)
nil (apply-filter search-token-filter default-tokens extract-token-attributes false)}}))
;; TRIBUTE TO TALK
(re-frame/reg-sub
:tribute-to-talk/settings
:<- [:multiaccount]
:<- [:ethereum/chain-keyword]
(fn [[multiaccount chain-keyword]]
(get-in multiaccount [:tribute-to-talk]) chain-keyword))
(re-frame/reg-sub
:tribute-to-talk/screen-params
:<- [:screen-params]
(fn [screen-params]
(get screen-params :tribute-to-talk)))
(re-frame/reg-sub
:tribute-to-talk/profile
:<- [:tribute-to-talk/settings]
:<- [:tribute-to-talk/screen-params]
(fn [[{:keys [seen? snt-amount]}
{:keys [state unavailable?]}]]
(let [state (or state (if snt-amount :completed :disabled))
snt-amount (tribute-to-talk.db/from-wei snt-amount)]
(when config/tr-to-talk-enabled?
(if unavailable?
{:subtext "Change network to enable Tribute to Talk"
:active? false
:icon :main-icons/tribute-to-talk
:icon-color colors/gray}
(cond-> {:new? (not seen?)}
(and (not (and seen?
snt-amount
(#{:signing :pending :transaction-failed :completed} state))))
(assoc :subtext (i18n/label :t/tribute-to-talk-desc))
(#{:signing :pending} state)
(assoc :activity-indicator {:animating true
:color colors/blue}
:subtext (case state
:pending (i18n/label :t/pending-confirmation)
:signing (i18n/label :t/waiting-to-sign)))
(= state :transaction-failed)
(assoc :icon :main-icons/warning
:icon-color colors/red
:subtext (i18n/label :t/transaction-failed))
(not (#{:signing :pending :transaction-failed} state))
(assoc :icon :main-icons/tribute-to-talk)
(and (= state :completed)
(not-empty snt-amount))
(assoc :accessory-value (str snt-amount " SNT"))))))))
(re-frame/reg-sub
:tribute-to-talk/enabled?
:<- [:tribute-to-talk/settings]
(fn [settings]
(tribute-to-talk.db/enabled? settings)))
(re-frame/reg-sub
:tribute-to-talk/settings-ui
:<- [:tribute-to-talk/settings]
:<- [:tribute-to-talk/screen-params]
:<- [:prices]
:<- [:wallet/currency]
(fn [[{:keys [seen? snt-amount message]
:as settings}
{:keys [step editing? state error]
:or {step :intro}
screen-snt-amount :snt-amount}
prices currency]]
(let [fiat-value (if snt-amount
(money/fiat-amount-value
snt-amount
:SNT
(-> currency :code keyword)
prices)
"0")]
(cond-> {:seen? seen?
:snt-amount (tribute-to-talk.db/from-wei snt-amount)
:message message
:enabled? (tribute-to-talk.db/enabled? settings)
:error error
:step step
:state (or state (if snt-amount :completed :disabled))
:editing? editing?
:fiat-value (str fiat-value " " (:code currency))}
(= step :set-snt-amount)
(assoc :snt-amount (str screen-snt-amount)
:disable-button?
(boolean (and (= step :set-snt-amount)
(or (string/blank? screen-snt-amount)
(#{"0" "0.0" "0.00"} screen-snt-amount)
(string/ends-with? screen-snt-amount ".")))))))))
;;ENS ==================================================================================================================
(re-frame/reg-sub
:multiaccount/usernames

View File

@ -3,12 +3,13 @@
(:require [re-frame.core :as re-frame]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.mailserver.core :as mailserver]
[status-im.constants :as constants]
[status-im.native-module.core :as status]
[status-im.pairing.core :as pairing]
[status-im.utils.config :as config]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[status-im.utils.publisher :as publisher]
[status-im.transport.filters.core :as transport.filters]
status-im.transport.shh
[taoensso.timbre :as log]))
@ -32,28 +33,68 @@
(fx/defn fetch-node-info-fx [cofx]
{::fetch-node-info []})
(fx/defn init-messenger
(defn add-custom-mailservers
[db custom-mailservers]
(reduce (fn [db {:keys [fleet] :as mailserver}]
(let [{:keys [id] :as mailserver}
(-> mailserver
(update :id keyword)
(dissoc :fleet)
(assoc :user-defined true))]
(assoc-in db
[:mailserver/mailservers (keyword fleet) id]
mailserver)))
db
custom-mailservers))
(defn add-mailserver-topics
[db mailserver-topics]
(assoc db
:mailserver/topics
(reduce (fn [acc {:keys [topic]
:as mailserver-topic}]
(assoc acc topic
(update mailserver-topic :chat-ids
#(into #{} %))))
{}
mailserver-topics)))
(defn add-mailserver-ranges
[db mailserver-ranges]
(assoc db
:mailserver/ranges
(reduce (fn [acc {:keys [chat-id] :as range}]
(assoc acc chat-id range))
{}
mailserver-ranges)))
(fx/defn start-messenger
"We should only start receiving messages/processing topics once all the
initializiation is completed, otherwise we might receive messages/topics
when the state has not been properly initialized."
[cofx]
{::json-rpc/call [{:method (json-rpc/call-ext-method "startMessenger")
:on-success #(do
(log/debug "messenger initialized")
(re-frame/dispatch [::init-whisper]))
:on-failure #(log/error "failed to init messenger")}]})
[{:keys [db] :as cofx}]
{:db (assoc db :rpc-url constants/ethereum-rpc-url)
::json-rpc/call [{:method (json-rpc/call-ext-method "startMessenger")
:on-success #(re-frame/dispatch [::messenger-started %])
:on-failure #(log/error "failed to start messenger")}]})
(fx/defn init-whisper
"Initialises whisper protocol by:
- (optionally) initializing mailserver"
{:events [::init-whisper]}
[cofx]
(log/debug "Initializing whisper")
(fx/defn messenger-started
[{:keys [db] :as cofx} {:keys [filters
mailserverTopics
mailservers
mailserverRanges] :as response}]
(log/info "Messenger started", response, mailserverTopics, mailservers, mailserverRanges)
(fx/merge cofx
{:db (-> db
(assoc :messenger/started? true)
(add-mailserver-ranges mailserverRanges)
(add-mailserver-topics mailserverTopics)
(add-custom-mailservers mailservers))}
(transport.filters/handle-loaded-filters filters)
(fetch-node-info-fx)
(pairing/init)
(publisher/start-fx)
(when-not config/nimbus-enabled? (mailserver/initialize-mailserver))))
(mailserver/initialize-mailserver)))
(fx/defn stop-whisper
"Stops whisper protocol"

View File

@ -1,139 +0,0 @@
(ns status-im.transport.core-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.protocol.core :as protocol]
[status-im.transport.message.core :as message]
[status-im.utils.fx :as fx]))
(deftest init-whisper
(let [cofx {:db {:multiaccount {:public-key "1"}}}]
(testing "custom mailservers"
(let [ms-1 {:id :a
:fleet :eth.staging
:name "name-1"
:address "address-1"
:password "password-1"}
ms-2 {:id :b
:fleet :eth.staging
:name "name-2"
:address "address-2"
:password "password-2"}
ms-3 {:id :c
:fleet :eth.test
:name "name-3"
:address "address-3"
:password "password-3"}
expected-mailservers {:eth.staging {:a (-> ms-1
(dissoc :fleet)
(assoc :user-defined true))
:b (-> ms-2
(dissoc ms-2 :fleet)
(assoc :user-defined true))}
:eth.test {:c (-> ms-3
(dissoc :fleet)
(assoc :user-defined true))}}]
(is (= expected-mailservers
(-> (get-in
(protocol/initialize-protocol cofx {:mailservers [ms-1 ms-2 ms-3]
:mailserver-ranges {}
:mailserver-topics {}
:default-mailserver true})
[:db :mailserver/mailservers])
(update-in [:eth.staging :a] dissoc :generating-sym-key?)
(update-in [:eth.staging :b] dissoc :generating-sym-key?)
(update-in [:eth.test :c] dissoc :generating-sym-key?))))))))
(def sig "0x04325367620ae20dd878dbb39f69f02c567d789dd21af8a88623dc5b529827c2812571c380a2cd8236a2851b8843d6486481166c39debf60a5d30b9099c66213e4")
(def messages [(clj->js {:id "someid"
:metadata {:author {:publicKey sig}}
:payload "[\"~#c4\",[\"F\",\"text/plain\",\"~:public-group-user-message\",152769201438101,1527692014377]]"
:message {:sig sig
:ttl 10
:timestamp 1527692015
:topic "0x9c22ff5f"
:payload "0x5b227e236334222c5b2246222c22746578742f706c61696e222c227e3a7075626c69632d67726f75702d757365722d6d657373616765222c3135323736393230313433383130312c313532373639323031343337375d5d"
:padding "0xbf06347cc7f9aa18b4a846032264a88f559d9b14079975d14b10648847c0543a77a80624e101c082d19b502ae3b4f97958d18abf59eb0a82afc1301aa22470495fac739a30c2f563599fa8d8e09363a43d39311596b7f119dee7b046989c08224f1ef5cdc385"
:pow 0.002631578947368421
:hash "0x220ef9994a4fae64c112b27ed07ef910918159cbe6fcf8ac515ee2bf9a6711a0"}})])
(deftest message-envelopes
(let [chat-id "chat-id"
from "from"
message-id "message-id"
initial-cofx {:db {:messages {chat-id {message-id {:from from}}}
:chats {chat-id {}}}}]
(testing "a single envelope message"
(let [cofx (message/set-message-envelope-hash initial-cofx chat-id message-id :message-type 1)]
(testing "it sets the message-infos"
(is (= {:chat-id chat-id
:message-type :message-type}
(get-in cofx [:db :transport/message-envelopes message-id]))))
(testing "the message is sent"
(is (= :sent
(get-in
(message/update-envelope-status cofx message-id :sent)
[:db :messages chat-id message-id :outgoing-status]))))
(testing "the message is not sent"
(is (= :not-sent
(get-in
(message/update-envelope-status cofx message-id :not-sent)
[:db :messages chat-id message-id :outgoing-status]))))))
(testing "multi envelope message"
(testing "only inserts"
(let [cofx (fx/merge
initial-cofx
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/set-message-envelope-hash chat-id message-id :message-type 3))]
(testing "it sets the message count"
(is (= {:pending-confirmations 3}
(get-in cofx [:db :transport/message-ids->confirmations message-id]))))))
(testing "message sent correctly"
(let [cofx (fx/merge
initial-cofx
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/update-envelope-status message-id :sent)
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/update-envelope-status message-id :sent)
(message/update-envelope-status message-id :sent))]
(testing "it removes the confirmations"
(is (not (get-in cofx [:db :transport/message-ids->confirmations message-id]))))
(testing "the message is sent"
(is (= :sent
(get-in
cofx
[:db :messages chat-id message-id :outgoing-status]))))))
(testing "order of events is reversed"
(let [cofx (fx/merge
initial-cofx
(message/update-envelope-status message-id :sent)
(message/update-envelope-status message-id :sent)
(message/update-envelope-status message-id :sent)
(message/set-message-envelope-hash chat-id message-id :message-type 3))]
(testing "it removes the confirmations"
(is (not (get-in cofx [:db :transport/message-confirmations message-id])))
(is (not (get-in cofx [:db :transport/message-ids->confirmations message-id]))))
(testing "the message is sent"
(is (= :sent
(get-in
cofx
[:db :messages chat-id message-id :outgoing-status]))))))
(testing "message not sent"
(let [cofx (fx/merge
initial-cofx
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/update-envelope-status message-id :sent)
(message/set-message-envelope-hash chat-id message-id :message-type 3)
(message/update-envelope-status message-id :not-sent)
(message/update-envelope-status message-id :sent))]
(testing "it removes the confirmations"
(is (not (get-in cofx [:db :transport/message-ids->confirmations message-id]))))
(testing "the message is sent"
(is (= :not-sent
(get-in
cofx
[:db :messages chat-id message-id :outgoing-status])))))))))

View File

@ -119,7 +119,9 @@
(fx/defn add-filter-to-db
"Set the filter in the db and upsert a mailserver topic"
[{:keys [db] :as cofx} filter]
(when-not (loaded? db filter)
(when (and (not (loaded? db filter))
(not (:ephemeral? filter))
(:listen? filter))
(fx/merge cofx
(set-raw-filter filter)
(upsert-mailserver-topic filter))))
@ -198,25 +200,21 @@
discovery
filterId
chatId
listen
ephemeral
topic
identity]}]
{:chat-id (if (not= identity "") (str "0x" identity) chatId)
:id chatId
:filter-id filterId
:negotiated? negotiated
:ephemeral? ephemeral
:listen? listen
:discovery? discovery
:topic topic})
;; We check that both chats & contacts have been initialized
(defn filters-initialized? [db]
(>= (:filters/initialized db) 2))
(fx/defn set-filters-initialized [{:keys [db] :as cofx}]
(fx/merge
cofx
{:db (update db :filters/initialized inc)}
#(when (filters-initialized? (:db %))
{:dispatch [:login/filters-initialized]})))
(defn messenger-started? [db]
(:messenger/started? db))
(fx/defn handle-filters-added
"Called every time we load a filter from statusgo, either from explicit call
@ -228,12 +226,20 @@
(add-filters-to-db filters)
(upsert-group-chat-topics)
(when (new-filters? db filters)
(mailserver/process-next-messages-request))
(set-filters-initialized)))
(mailserver/process-next-messages-request))))
(fx/defn handle-filters [cofx filters]
(handle-filters-added cofx (map responses->filters filters)))
(fx/defn handle-loaded-filter [cofx filter]
(when (and (not (:ephemeral? filter))
(:listen? filter))
(set-raw-filter cofx filter)))
(fx/defn handle-loaded-filters [cofx filters]
(let [processed-filters (map responses->filters filters)]
(apply fx/merge cofx (map handle-loaded-filter processed-filters))))
(fx/defn handle-filters-removed
"Called when we remove a filter from status-go, it will update the mailserver
topics"
@ -256,23 +262,12 @@
{:filters/add-raw-filters
{:filters new-filters}})))
(fx/defn load-filters
"Load all contacts and chats as filters"
[{:keys [db] :as cofx}]
(log/debug "loading filters")
(let [chats (vals (:chats db))
contacts (vals (:contacts/contacts db))
filters (concat
(chats->filter-requests chats)
(contacts->filter-requests contacts))]
(load-filter-fx filters)))
;; Load functions: utility function to load filters
(fx/defn load-chat
"Check if a filter already exists for that chat, otherw load the filter"
[{:keys [db] :as cofx} chat-id]
(when (and (filters-initialized? db)
(when (and (messenger-started? db)
(not (chat-loaded? db chat-id)))
(let [chat (get-in db [:chats chat-id])]
(load-filter-fx (->filter-request chat)))))
@ -281,7 +276,7 @@
"Check if a filter already exists for that chat, otherw load the filter"
[{:keys [db] :as cofx} chats]
(let [chats (filter #(chat-loaded? db (:chat-id %)) chats)]
(when (and (filters-initialized? db) (seq chats))
(when (and (messenger-started? db) (seq chats))
(load-filter-fx (chats->filter-requests chats)))))
(fx/defn load-contact

View File

@ -119,6 +119,7 @@
(let [expected {:db {:filter/chat-ids #{"chat-id"}
:filter/filters {"filter-id" {:filter-id "filter-id"
:discovery? false
:listen? true
:chat-id "chat-id"
:negotiated? false
:topic "topic"}}
@ -132,8 +133,17 @@
:discovery? false
:chat-id "chat-id"
:negotiated? false
:listen? true
:topic "topic"}))))))
(deftest add-filter-to-db-not-listen
(with-redefs [mailserver.topics/upsert (fn [{:keys [db]} r] {:db (assoc db :upsert r)})]
(is (not (transport.filters/add-filter-to-db {:db {}} {:filter-id "filter-id"
:discovery? false
:chat-id "chat-id"
:negotiated? false
:topic "topic"})))))
(deftest new-filters?
(testing "new-filters?"
(let [db {:filter/filters {"a" {}

View File

@ -1,374 +0,0 @@
(ns status-im.tribute-to-talk.core
(:refer-clojure :exclude [remove])
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.contact.core :as contact]
[status-im.ethereum.contracts :as contracts]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.ethereum.transactions.core :as transactions]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.signing.core :as signing]
[status-im.tribute-to-talk.db :as tribute-to-talk.db]
[status-im.tribute-to-talk.whitelist :as whitelist]
[status-im.navigation :as navigation]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]))
(defn add-transaction-hash
[message db]
(let [to (get-in message [:content :chat-id])
tribute-transaction-hash
(get-in db [:contacts/contacts to :tribute-to-talk :transaction-hash])]
(if tribute-transaction-hash
(assoc-in message
[:content :tribute-transaction]
tribute-transaction-hash)
message)))
(fx/defn update-settings
[{:keys [db] :as cofx} {:keys [snt-amount message update] :as new-settings}]
(let [tribute-to-talk-settings (get-in db [:multiaccount :tribute-to-talk])
chain-keyword (ethereum/chain-keyword db)
tribute-to-talk-chain-settings
(cond-> (merge (tribute-to-talk.db/get-settings db)
new-settings)
new-settings
(assoc :seen? true)
(not new-settings)
(dissoc :snt-amount :manifest)
(and (contains? new-settings :update)
(nil? update))
(dissoc :update))]
(fx/merge cofx
(multiaccounts.update/multiaccount-update
:tribute-to-talk (assoc tribute-to-talk-settings
chain-keyword
tribute-to-talk-chain-settings)
{})
(whitelist/enable-whitelist))))
(fx/defn mark-ttt-as-seen
[{:keys [db] :as cofx}]
(when-not (:seen (tribute-to-talk.db/get-settings db))
(update-settings cofx {:seen? true})))
(fx/defn open-settings
{:events [:tribute-to-talk.ui/menu-item-pressed]}
[{:keys [db] :as cofx}]
(let [settings (tribute-to-talk.db/get-settings db)
updated-settings (:update settings)]
(fx/merge cofx
mark-ttt-as-seen
(navigation/navigate-to-cofx
:tribute-to-talk
(cond
updated-settings
(merge {:step :finish}
updated-settings
(when updated-settings
{:state :pending}))
(:snt-amount settings)
(merge {:step :edit
:editing? true}
(update settings :snt-amount tribute-to-talk.db/from-wei))
:else
{:step :intro
:snt-amount "0"})))))
(fx/defn set-step
[{:keys [db]} step]
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :step] step)})
(fx/defn set-tribute-signing-flow
[{:keys [db] :as cofx} tribute]
(if-let [contract (contracts/get-address db :status/tribute-to-talk)]
(signing/eth-transaction-call
cofx
{:contract contract
:method "setTribute(uint256)"
:params [tribute]
:on-result [:tribute-to-talk.callback/set-tribute-transaction-sent]
:on-error [:tribute-to-talk.callback/set-tribute-transaction-failed]})
{:db (assoc-in db
[:navigation/screen-params :tribute-to-talk :state]
:transaction-failed)}))
(fx/defn remove
{:events [:tribute-to-talk.ui/remove-pressed]}
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk]
{:step :finish
:state :disabled})}
(set-tribute-signing-flow 0)))
(fx/defn set-step-finish
[{:keys [db] :as cofx}]
(let [tribute (get-in db [:navigation/screen-params :tribute-to-talk :snt-amount])]
(fx/merge cofx
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :state] :signing)}
(set-tribute-signing-flow (tribute-to-talk.db/to-wei tribute))
(set-step :finish))))
(fx/defn open-learn-more
{:events [:tribute-to-talk.ui/learn-more-pressed]}
[cofx]
(set-step cofx :learn-more))
(fx/defn step-back
{:events [:tribute-to-talk.ui/step-back-pressed]}
[cofx]
(let [{:keys [step editing?]}
(get-in cofx [:db :navigation/screen-params :tribute-to-talk])]
(case step
(:intro :edit)
(navigation/navigate-back cofx)
(:learn-more :set-snt-amount)
(set-step cofx (if editing?
:edit
:intro))
:finish
(set-step cofx :set-snt-amount))))
(fx/defn step-forward
{:events [:tribute-to-talk.ui/step-forward-pressed]}
[cofx]
(let [{:keys [step editing?]}
(get-in cofx [:db :navigation/screen-params :tribute-to-talk])]
(case step
:intro
(set-step cofx :set-snt-amount)
:set-snt-amount
(set-step-finish cofx)
:finish
(navigation/navigate-back cofx))))
(defn get-new-snt-amount
[snt-amount numpad-symbol]
;; TODO: Put some logic in place so that incorrect numbers can not
;; be entered
(let [snt-amount (or (str snt-amount) "0")]
(if (= numpad-symbol :remove)
(let [len (count snt-amount)
s (subs snt-amount 0 (dec len))]
(cond-> s
;; Remove both the digit after the dot and the dot itself
(string/ends-with? s ".") (subs 0 (- len 2))
;; Set default value if last digit is removed
(string/blank? s) (do "0")))
(cond
;; Disallow two consecutive dots
(and (string/includes? snt-amount ".") (= numpad-symbol "."))
snt-amount
;; Disallow more than 2 digits after the dot
(and (string/includes? snt-amount ".")
(> (count (second (string/split snt-amount #"\."))) 1))
snt-amount
;; Disallow values larger or equal to 1 million
(>= (js/parseFloat (str snt-amount numpad-symbol))
tribute-to-talk.db/max-snt-amount)
snt-amount
;; Replace initial "0" by the first digit
(and (= snt-amount "0") (not= numpad-symbol "."))
(str numpad-symbol)
:else (str snt-amount numpad-symbol)))))
(fx/defn update-snt-amount
{:events [:tribute-to-talk.ui/numpad-key-pressed]}
[{:keys [db]} numpad-symbol]
{:db (update-in db
[:navigation/screen-params :tribute-to-talk :snt-amount]
#(get-new-snt-amount % numpad-symbol))})
(fx/defn start-editing
{:events [:tribute-to-talk.ui/edit-pressed]}
[{:keys [db]}]
{:db (assoc-in db
[:navigation/screen-params :tribute-to-talk :step]
:set-snt-amount)})
(fx/defn on-check-tribute-success
{:events [:tribute-to-talk.callback/check-tribute-success]}
[cofx public-key tribute-to-talk]
(let [tribute-to-talk (when (tribute-to-talk.db/valid? tribute-to-talk)
tribute-to-talk)]
(if-let [me? (= public-key
(get-in cofx [:db :multiaccount :public-key]))]
(update-settings cofx tribute-to-talk)
(contact/set-tribute cofx public-key tribute-to-talk))))
(fx/defn on-no-tribute-found
{:events [:tribute-to-talk.callback/no-tribute-found]}
[cofx public-key]
(if-let [me? (= public-key
(get-in cofx [:db :multiaccount :public-key]))]
(update-settings cofx nil)
(contact/set-tribute cofx public-key nil)))
(re-frame/reg-fx
:tribute-to-talk/get-tribute
(fn [{:keys [contract address on-success]}]
(json-rpc/eth-call
{:contract contract
:method "getTribute(address)"
:params [address]
:outputs ["uint256"]
:on-success on-success})))
(fx/defn check-tribute
[{:keys [db] :as cofx} public-key]
(when (and (not (get-in db [:chats public-key :group-chat]))
(not (get-in db [:contacts/contacts public-key :tribute-to-talk
:transaction-hash]))
(not (whitelist/whitelisted-by?
(get-in db [:contacts/contacts public-key]))))
(if-let [contract (contracts/get-address db :status/tribute-to-talk)]
(let [address (ethereum/public-key->address public-key)]
{:tribute-to-talk/get-tribute
{:contract contract
:address address
:on-success
(fn [[tribute]]
(re-frame/dispatch
(if (pos? tribute)
[:tribute-to-talk.callback/check-tribute-success
public-key
{:snt-amount (str tribute)}]
[:tribute-to-talk.callback/no-tribute-found public-key])))}})
;; update settings if checking own manifest or do nothing otherwise
(if-let [me? (= public-key
(get-in cofx [:db :multiaccount :public-key]))]
(fx/merge cofx
{:db (assoc-in db
[:navigation/screen-params :tribute-to-talk :unavailable?]
true)}
(update-settings nil))
(contact/set-tribute cofx public-key nil)))))
(fx/defn check-own-tribute
[cofx]
(check-tribute cofx (get-in cofx [:db :multiaccount :public-key])))
(fx/defn pay-tribute
{:events [:tribute-to-talk.ui/on-pay-to-chat-pressed]}
[{:keys [db] :as cofx} public-key]
(let [{:keys [address public-key tribute-to-talk]}
(get-in db [:contacts/contacts public-key])
{:keys [snt-amount]} tribute-to-talk]
(signing/eth-transaction-call
cofx
{:contract (contracts/get-address db :status/snt)
:method "transfer(address,uint256)"
:params [address snt-amount]
:on-result [:tribute-to-talk.callback/pay-tribute-transaction-sent public-key]})))
(defn tribute-transaction-trigger
[db {:keys [block error?]}]
(let [current-block (get db :ethereum/current-block)
transaction-block (or block
current-block)]
(or error?
(pos? (- current-block
(js/parseInt transaction-block))))))
(fx/defn on-pay-tribute-transaction-triggered
[{:keys [db] :as cofx}
public-key
{:keys [error? transfer symbol] :as transaction}]
(when (and transfer
(= symbol (ethereum/snt-symbol db))
(not error?))
(whitelist/mark-tribute-paid cofx public-key)))
(fx/defn on-pay-tribute-transaction-sent
{:events [:tribute-to-talk.callback/pay-tribute-transaction-sent]}
[{:keys [db] :as cofx} public-key transaction-hash]
(fx/merge cofx
{:db (assoc-in db [:contacts/contacts public-key
:tribute-to-talk :transaction-hash]
transaction-hash)}
(transactions/watch-transaction
transaction-hash
{:trigger-fn
tribute-transaction-trigger
:on-trigger
#(on-pay-tribute-transaction-triggered public-key %)})))
(fx/defn on-set-tribute-transaction-triggered
[{:keys [db] :as cofx}
tribute
{:keys [error?] :as transaction}]
(if error?
(fx/merge cofx
{:db (assoc-in db [:navigation/screen-params
:tribute-to-talk :state]
:transaction-failed)}
(update-settings {:update nil}))
(fx/merge cofx
{:db (assoc-in db [:navigation/screen-params
:tribute-to-talk :state]
(if tribute
:completed
:disabled))}
(check-own-tribute)
(update-settings {:update nil}))))
(fx/defn on-set-tribute-transaction-sent
{:events [:tribute-to-talk.callback/set-tribute-transaction-sent]}
[{:keys [db] :as cofx} transaction-hash]
(let [{:keys [snt-amount message]} (get-in db [:navigation/screen-params
:tribute-to-talk])]
(fx/merge cofx
{:db (assoc-in db [:navigation/screen-params
:tribute-to-talk :state]
:pending)}
(update-settings {:update {:transaction transaction-hash
:snt-amount snt-amount
:message message}})
(transactions/watch-transaction
transaction-hash
{:trigger-fn
tribute-transaction-trigger
:on-trigger
#(on-set-tribute-transaction-triggered snt-amount %)}))))
(fx/defn on-set-tribute-transaction-failed
{:events [:tribute-to-talk.callback/set-tribute-transaction-failed]}
[{:keys [db] :as cofx} error]
(log/error :set-tribute-transaction-failed error)
{:db (assoc-in db
[:navigation/screen-params :tribute-to-talk :state]
:transaction-failed)})
(fx/defn watch-set-tribute-transaction
"check if there is a pending transaction to set the tribute and
add a watch on that transaction
if there is a transaction check if the trigger is valid already"
[{:keys [db] :as cofx}]
(when-let [tribute-update (get (tribute-to-talk.db/get-settings db)
:update)]
(let [{:keys [transaction snt-amount]} tribute-update]
(fx/merge cofx
(transactions/watch-transaction
transaction
{:trigger-fn
tribute-transaction-trigger
:on-trigger
#(on-set-tribute-transaction-triggered snt-amount %)})
(when-let [transaction (get-in db [:wallet :transactions
transaction])]
(transactions/check-transaction transaction))))))
(fx/defn init
[cofx]
(fx/merge cofx
(check-own-tribute)
(watch-set-tribute-transaction)))

View File

@ -1,139 +0,0 @@
(ns status-im.tribute-to-talk.core-test
(:require [cljs.test :refer-macros [deftest testing is]]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon]
[status-im.tribute-to-talk.core :as tribute-to-talk]
[status-im.utils.money :as money]))
(deftest get-new-snt-amount
(testing "staying under the limit"
(is (= (tribute-to-talk/get-new-snt-amount
"999999.9" "9")
"999999.99")))
(testing "getting over the limit"
(is (= (tribute-to-talk/get-new-snt-amount
"100000" "0")
"100000")))
(testing "replace initial 0 by the first digit"
(is (= (tribute-to-talk/get-new-snt-amount
"0" "1")
"1")))
(testing "disallow more than two dots"
(is (= (tribute-to-talk/get-new-snt-amount
"0." ".")
"0."))
(is (= (tribute-to-talk/get-new-snt-amount
"0.0" ".")
"0.0")))
(testing "disallow more than two digits after dot"
(is (= (tribute-to-talk/get-new-snt-amount
"0.0" "0")
"0.00"))
(is (= (tribute-to-talk/get-new-snt-amount
"0.00" "1")
"0.00")))
(testing "0 remains if removed is pressed on last digit"
(is (= (tribute-to-talk/get-new-snt-amount
"0" :remove)
"0"))
(is (= (tribute-to-talk/get-new-snt-amount
"1" :remove)
"0")))
(testing "dot is removed when last digit after dot is removed"
(= (tribute-to-talk/get-new-snt-amount
"1." :remove)
"1")
(= (tribute-to-talk/get-new-snt-amount
"1.1" :remove)
"1")))
(def recipient-pk "0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97")
(def recipient-address "0xdff1a5e4e57d9723b3294e0f4413372e3ea9a8ff")
(def user-cofx
{:db {:networks/current-network "testnet_rpc"
:networks/networks {"testnet_rpc" {:config {:NetworkId 3}}}
:multiaccount
{:address "954d4393515747ea75808a0301fb73317ae1e460"}
:tribute-to-talk {:testnet {:snt-amount "1000000000000000000"}}
:contacts/contacts
{recipient-pk {:name "bob"
:address recipient-address
:public-key recipient-pk
:tribute-to-talk {:snt-amount "1000000000000000000"}}}
:wallet {:balance {:STT (money/bignumber "1000000000000000000")}}}})
(deftest tribute-transaction-trigger
(testing "transaction error"
(is (tribute-to-talk/tribute-transaction-trigger
{:ethereum/current-block 10}
{:block "5"
:error? true})))
(testing "transaction confirmed"
(is (tribute-to-talk/tribute-transaction-trigger
{:ethereum/current-block 10}
{:block "5"})))
(testing "transaction not confirmed yet"
(is (not (tribute-to-talk/tribute-transaction-trigger
{:ethereum/current-block 5}
{:block "5"})))))
(def public-key "0xabcdef")
(def my-public-key "0x000001")
(def test-db
{:chats
{public-key {:group-chat false}}
:contacts/contacts
{public-key {:tribute-to-talk {}
:system-tags #{}}}
:multiaccount
{:public-key my-public-key}
:networks/current-network "mainnet_rpc"
:networks/networks {"mainnet_rpc" {:id "mainnet_rpc"
:config {:NetworkId 1}}
"testnet_rpc" {:id "testnet_rpc"
:config {:NetworkId 3}}}})
(deftest check-tribute
(with-redefs [gfycat/generate-gfy (constantly "generated")
identicon/identicon (constantly "generated")]
(testing "No contract in network, own public key"
(let [result (tribute-to-talk/check-tribute {:db test-db} my-public-key)]
(is (= (-> test-db
(assoc :navigation/screen-params {:tribute-to-talk {:unavailable? true}})
(assoc-in [:multiaccount :tribute-to-talk] {:mainnet nil}))
(:db result)))))
(testing "No contract in network, another public key"
(let [result (tribute-to-talk/check-tribute {:db test-db} public-key)]
(is (= {:disabled? true}
(get-in result [:db :contacts/contacts public-key :tribute-to-talk])))))
(testing "Contract in network, another public key"
(let [result (tribute-to-talk/check-tribute {:db (assoc test-db :networks/current-network "testnet_rpc")}
public-key)]
(is (= "0xC61aa0287247a0398589a66fCD6146EC0F295432"
(get-in result [:tribute-to-talk/get-tribute :contract])))))
(testing "Added by other user"
(let [result (tribute-to-talk/check-tribute
{:db (update-in test-db
[:contacts/contacts public-key :system-tags]
conj :contact/request-received)}
public-key)]
(is (= result nil))))
(testing "Group chat"
(let [result (tribute-to-talk/check-tribute
{:db (assoc-in test-db [:chats public-key :group-chat] true)}
public-key)]
(is (= result nil))))
(testing "Added by this user"
(let [result (tribute-to-talk/check-tribute
{:db (update-in test-db
[:contacts/contacts public-key :system-tags]
conj :contact/added)}
public-key)]
(is (= {:disabled? true}
(get-in result [:db :contacts/contacts public-key :tribute-to-talk])))))))

View File

@ -1,71 +0,0 @@
(ns status-im.tribute-to-talk.db
(:require [status-im.ethereum.core :as ethereum]
[status-im.i18n :as i18n]
[status-im.utils.money :as money]
["web3-utils" :as utils]))
(defn tribute-received?
[contact]
(contains? (:system-tags contact) :tribute-to-talk/received))
(def max-snt-amount 1000000)
(defn to-wei
[s]
(when s
(.toWei utils s)))
(defn from-wei
[s]
(when s
(.fromWei utils s)))
(defn tribute-status
[{:keys [system-tags tribute-to-talk]}]
(let [{:keys [snt-amount transaction-hash]} tribute-to-talk]
(cond (contains? system-tags :tribute-to-talk/paid) :paid
(not (nil? transaction-hash)) :pending
(pos? snt-amount) :required
:else :none)))
(defn status-label
[tribute-status tribute]
(case tribute-status
:paid (i18n/label :t/tribute-state-paid)
:pending (i18n/label :t/tribute-state-pending)
:required (i18n/label :t/tribute-state-required
{:snt-amount (from-wei tribute)})
nil))
(defn valid?
[{:keys [snt-amount]}]
(when (string? snt-amount)
(try (let [converted-snt-amount (from-wei snt-amount)]
(and (= (to-wei converted-snt-amount)
snt-amount)
(< 0 (js/parseFloat converted-snt-amount) max-snt-amount)))
(catch :default _ nil))))
(defn get-settings
[db]
(let [chain-keyword (ethereum/chain-keyword db)]
(get-in db [:multiaccount :tribute-to-talk chain-keyword])))
(defn enabled?
[settings]
(:snt-amount settings))
(defn valid-tribute-transaction?
[db tribute-required tribute-transaction from-public-key]
(let [{:keys [value block from] :as transaction}
(get-in db [:wallet :transactions tribute-transaction])
current-block (get db :ethereum/current-block)
transaction-block (or block
current-block)]
(and transaction
(pos? (- current-block
(js/parseInt transaction-block)))
(.lessThanOrEqualTo ^js (money/bignumber tribute-required)
(money/bignumber value))
(ethereum/address= (ethereum/public-key->address from-public-key)
from))))

View File

@ -1,81 +0,0 @@
(ns status-im.tribute-to-talk.db-test
(:require [cljs.test :refer-macros [deftest testing is]]
[status-im.tribute-to-talk.db :as db]))
(deftest tribute-status
(is (= (db/tribute-status {:system-tags #{:tribute-to-talk/paid}
:tribute-to-talk {:snt-amount 1000
:transaction-hash "0x"}})
:paid))
(is (= (db/tribute-status {:tribute-to-talk {:snt-amount 1000
:transaction-hash "0x"}})
:pending))
(is (= (db/tribute-status {:tribute-to-talk {:snt-amount 1000}})
:required))
(is (= (db/tribute-status {:tribute-to-talk {:snt-amount 0}})
:none))
(is (= (db/tribute-status {})
:none)))
(deftest valid?
(is (db/valid? {:snt-amount "1000"}))
(is (not (db/valid? {:snt-amount "-1000"})))
(is (not (db/valid? {:snt-amount "1000001000000000000000000"})))
(is (not (db/valid? {:snt-amount 5})))
(is (not (db/valid? {:snt-amount "abcdef"}))))
(def sender-pk "0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97")
(def sender-address "0xdff1a5e4e57d9723b3294e0f4413372e3ea9a8ff")
(deftest valid-tribute-transaction?
(testing "a valid transaction"
(is (db/valid-tribute-transaction?
{:wallet {:transactions
{"transaction-hash-1"
{:value "1000000000000000000"
:block "5"
:from sender-address}}}
:ethereum/current-block 8}
"1000000000000000000"
"transaction-hash-1"
sender-pk)))
(testing "a transaction"
(testing "with insufficient value transfered"
(is (not (db/valid-tribute-transaction?
{:wallet {:transactions
{"transaction-hash-1"
{:value "1"
:block "5"
:from sender-address}}}
:ethereum/current-block 8}
"1000000000000000000"
"transaction-hash-1"
sender-pk)))
(testing "that was not confirmed yet"
(is (not (db/valid-tribute-transaction?
{:wallet {:transactions
{"transaction-hash-1"
{:value "1000000000000000000"
:block "8"
:from sender-address}}}
:ethereum/current-block 8}
"1000000000000000000"
"transaction-hash-1"
sender-pk))))
(testing "from someone else"
(is (not (db/valid-tribute-transaction?
{:wallet {:transactions
{"transaction-hash-1"
{:value "1000000000000000000"
:block "5"
:from "another address"}}}
:ethereum/current-block 8}
"1000000000000000000"
"transaction-hash-1"
sender-pk))))))
(testing "a transaction that does not exist"
(is (not (db/valid-tribute-transaction?
{:ethereum/current-block 8}
"1000000000000000000"
"transaction-hash-1"
sender-pk)))))

View File

@ -1,79 +0,0 @@
(ns status-im.tribute-to-talk.whitelist
(:require [status-im.contact.db :as contact.db]
[status-im.data-store.contacts :as contacts-store]
[status-im.constants :as constants]
[status-im.tribute-to-talk.db :as tribute-to-talk.db]
[status-im.utils.fx :as fx]))
(defn whitelisted-by? [{:keys [system-tags]}]
(or (contains? system-tags :contact/request-received)
(contains? system-tags :tribute-to-talk/paid)
(contains? system-tags :tribute-to-talk/received)))
(defn whitelisted? [{:keys [system-tags]}]
(or (contains? system-tags :contact/added)
(contains? system-tags :tribute-to-talk/paid)
(contains? system-tags :tribute-to-talk/received)))
(defn get-contact-whitelist
[contacts]
(reduce (fn [acc {:keys [public-key] :as contact}]
(if (whitelisted? contact)
(conj acc public-key) acc))
(hash-set) contacts))
(fx/defn add-to-whitelist
"Add contact to whitelist"
[{:keys [db]} public-key]
{:db (update db :contacts/whitelist (fnil conj #{}) public-key)})
(defn- mark-tribute
[{:keys [db now] :as cofx} public-key tag]
(let [contact (-> (contact.db/public-key->contact
(:contacts/contacts db)
public-key)
(assoc :last-updated now)
(update :system-tags conj tag))]
(fx/merge cofx
{:db (-> db
(assoc-in [:contacts/contacts public-key] contact))}
(contacts-store/save-contact contact)
(add-to-whitelist public-key))))
(fx/defn mark-tribute-paid
[cofx public-key]
(mark-tribute cofx public-key :tribute-to-talk/paid))
(fx/defn mark-tribute-received
[cofx public-key]
(mark-tribute cofx public-key :tribute-to-talk/received))
(fx/defn enable-whitelist
[{:keys [db] :as cofx}]
(if (tribute-to-talk.db/enabled? (tribute-to-talk.db/get-settings db))
{:db (assoc db :contacts/whitelist
(get-contact-whitelist (vals (:contacts/contacts db))))}
{:db (dissoc db :contacts/whitelist)}))
(fx/defn filter-message
"clojure semantics of filter, if true the message is allowed
if it is a user message and tribute to talk is enabled, the user must be
in the whitelist or there must be a valid tribute transaction id passed
along the message"
[{:keys [db] :as cofx} received-message-fx message-type tribute-transaction from]
;; if it is not a user-message or the user is whitelisted it passes
(if (or (not= constants/message-type-one-to-one message-type)
(contains? (:contacts/whitelist db) from))
received-message-fx
;; if ttt is disabled it passes
(if-let [snt-amount (:snt-amount (tribute-to-talk.db/get-settings db))]
(let [contact (get-in db [:contacts/contacts from])]
;; if the tribute is not paid the message is dropped
;; otherwise it passes and the user is added to the whitelist
;; through system tags
(when (tribute-to-talk.db/valid-tribute-transaction?
db snt-amount tribute-transaction from)
(fx/merge cofx
received-message-fx
(mark-tribute-received from))))
received-message-fx)))

View File

@ -1,136 +0,0 @@
(ns status-im.tribute-to-talk.whitelist-test
(:require [cljs.test :refer-macros [deftest testing is]]
[status-im.utils.gfycat.core :as gfycat]
[status-im.constants :as constants]
[status-im.utils.identicon :as identicon]
[status-im.tribute-to-talk.whitelist :as whitelist]))
(def user-contacts
{"not whitelisted"
{:public-key "not whitelisted"
:system-tags #{}}
"not whitelisted2"
{:public-key "not whitelisted2"
:system-tags #{:contact/request-received}}
"whitelisted because tribute paid"
{:public-key "whitelisted because tribute paid"
:system-tags #{:tribute-to-talk/paid}}
"whitelisted because tribute received"
{:public-key "whitelisted because tribute received"
:system-tags #{:tribute-to-talk/received}}
"whitelisted because added"
{:public-key "whitelisted because added"
:system-tags #{:contact/added}}})
(deftest get-contact-whitelist
(is (= 3
(count (whitelist/get-contact-whitelist
(vals user-contacts))))))
(deftest add-to-whitelist
(testing "adding contact to whitelist"
(is (= #{"bob" "bob2"}
(get-in (whitelist/add-to-whitelist
{:db {:contacts/whitelist #{"bob2"}}} "bob")
[:db :contacts/whitelist])))
(testing "when there is no whitelist yet"
(is (= #{"bob"}
(get-in (whitelist/add-to-whitelist
{:db {}} "bob")
[:db :contacts/whitelist]))
(whitelist/add-to-whitelist {:db {}} "bob")))
(testing "when already added"
(is (= #{"bob"}
(get-in (whitelist/add-to-whitelist
{:db {:contacts/whitelist #{"bob"}}} "bob")
[:db :contacts/whitelist]))))))
(deftest mark-tribute-paid
(with-redefs [gfycat/generate-gfy (constantly "generated")
identicon/identicon (constantly "generated")]
(let [result (whitelist/mark-tribute-paid {:db {}} "bob")]
(testing "contact was added to whitelist"
(is (= (get-in result
[:db :contacts/whitelist])
#{"bob"})))
(testing "contact was tagged as tribute paid"
(is (= (get-in result
[:db :contacts/contacts "bob" :system-tags])
#{:tribute-to-talk/paid}))))))
(deftest mark-tribute-received
(with-redefs [gfycat/generate-gfy (constantly "generated")
identicon/identicon (constantly "generated")]
(let [result (whitelist/mark-tribute-received {:db {}} "bob")]
(testing "contact was added to whitelist"
(is (= (get-in result
[:db :contacts/whitelist])
#{"bob"})))
(testing "contact was tagged as tribute paid"
(is (= (get-in result
[:db :contacts/contacts "bob" :system-tags])
#{:tribute-to-talk/received}))))))
(def sender-pk "0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97")
(def sender-address "0xdff1a5e4e57d9723b3294e0f4413372e3ea9a8ff")
(def ttt-enabled-multiaccount
{:db {:multiaccount {:tribute-to-talk {:testnet {:snt-amount "1000000000000000000"}}}
:networks/current-network "testnet_rpc"
:networks/networks {"testnet_rpc" {:config {:NetworkId 3}}}
:contacts/contacts user-contacts
:wallet {:transactions
{"transaction-hash-1"
{:value "1000000000000000000"
:block "5"
:from sender-address}}}
:ethereum/current-block 8}})
(def ttt-disabled-multiaccount
{:db {:multiaccount {:tribute-to-talk {}}
:networks/current-network "testnet_rpc"
:networks/networks {"testnet_rpc" {:config {:NetworkId 3}}}
:contacts/contacts user-contacts}})
(deftest enable-whitelist
(testing "ttt enabled multiaccount"
(is (= (get-in (whitelist/enable-whitelist ttt-enabled-multiaccount)
[:db :contacts/whitelist]))))
(testing "ttt disabled multiaccount"
(is (not (get-in (whitelist/enable-whitelist ttt-disabled-multiaccount)
[:db :contacts/whitelist])))))
(deftest filter-message
(with-redefs [gfycat/generate-gfy (constantly "generated")
identicon/identicon (constantly "generated")]
(testing "not a user message"
(whitelist/filter-message
ttt-enabled-multiaccount
:unfiltered-fx
:not-user-message
nil
"public-key"))
(testing "user is whitelisted"
(whitelist/filter-message
(whitelist/enable-whitelist ttt-enabled-multiaccount)
:unfiltered-fx
constants/message-type-one-to-one
nil
"whitelisted because added"))
(testing "tribute to talk is disabled"
(whitelist/filter-message
ttt-disabled-multiaccount
:unfiltered-fx
constants/message-type-one-to-one
nil
"public-key"))
(testing "user is not whitelisted but transaction is valid"
(let [result (whitelist/filter-message
ttt-enabled-multiaccount
#(assoc % :message-received true)
constants/message-type-one-to-one
"transaction-hash-1"
sender-pk)]
(is (contains? (get-in result [:db :contacts/whitelist])
sender-pk))
(is (:message-received result))))))

View File

@ -1,95 +0,0 @@
(ns status-im.ui.screens.chat.ttt
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.styles.main :as style]
[status-im.ui.screens.profile.tribute-to-talk.views
:as
tribute-to-talk.views]))
(defn tribute-to-talk-header
[name]
[react/nested-text {:style (assoc style/intro-header-description
:margin-bottom 32)}
(i18n/label :t/tribute-required-by-multiaccount {:multiaccount-name name})
[{:style {:color colors/blue}
:on-press #(re-frame/dispatch [:navigate-to :tribute-learn-more])}
(str " " (i18n/label :learn-more))]])
(defn pay-to-chat-messages
[snt-amount chat-id tribute-status tribute-label
fiat-amount fiat-currency token]
[tribute-to-talk.views/pay-to-chat-message
{:snt-amount snt-amount
:public-key chat-id
:tribute-status tribute-status
:tribute-label tribute-label
:fiat-amount fiat-amount
:fiat-currency fiat-currency
:token token
:style {:margin-horizontal 8
:align-items :flex-start
:align-self (if snt-amount :flex-start :flex-end)}}])
(defn one-to-one-chat-description-container
[{:keys [chat-id name]
:tribute-to-talk/keys [received? tribute-status
tribute-label snt-amount on-share-my-profile
fiat-amount fiat-currency token]}]
(case tribute-status
:loading
[react/view (assoc (dissoc style/empty-chat-container :flex)
:justify-content :flex-end)
[react/view {:style {:align-items :center :justify-content :flex-end}}
[react/view {:style {:flex-direction :row :justify-content :center}}
[react/text {:style style/loading-text}
(i18n/label :t/loading)]
[react/activity-indicator {:color colors/gray
:animating true}]]]]
:required
[react/view
[tribute-to-talk-header name]
[pay-to-chat-messages snt-amount chat-id tribute-status tribute-label
fiat-amount fiat-currency token]
[react/view {:style style/are-you-friends-bubble}
[react/text {:style (assoc style/are-you-friends-text
:font-weight "500")}
(i18n/label :t/tribute-to-talk-are-you-friends)]
[react/text {:style style/are-you-friends-text}
(i18n/label :t/tribute-to-talk-ask-to-be-added)]
[react/text {:style style/share-my-profile
:on-press on-share-my-profile}
(i18n/label :t/share-my-profile)]]]
:pending
[react/view
[tribute-to-talk-header name]
[pay-to-chat-messages snt-amount chat-id tribute-status tribute-label
fiat-amount fiat-currency token]]
(:paid :none)
[react/view
;[intro-header contact]
(when (= tribute-status :paid)
[pay-to-chat-messages snt-amount chat-id tribute-status tribute-label
fiat-amount fiat-currency token])
(when received?
[pay-to-chat-messages nil nil nil nil nil nil nil])
(when (or (= tribute-status :paid) received?)
[react/view {:style {:margin-top 16 :margin-horizontal 8}}
[react/nested-text {:style style/tribute-received-note}
(when received?
[{:style (assoc style/tribute-received-note :color colors/gray)}
(i18n/label :tribute-to-talk-tribute-received1)])
[{:style (assoc style/tribute-received-note :font-weight "500")}
name]
[{:style (assoc style/tribute-received-note :color colors/gray)}
(i18n/label (if received?
:tribute-to-talk-tribute-received2
:tribute-to-talk-contact-received-your-tribute))]]])]))
;[intro-header contact]))

View File

@ -83,7 +83,17 @@
:height 40}
[react/image {:source (resources/get-image :keycard-logo-blue)
:style {:width 24 :height 24}}]]
:on-press #(hide-sheet-and-dispatch [::keycard/recover-with-keycard-pressed])}])]]))
:on-press #(hide-sheet-and-dispatch [::keycard/recover-with-keycard-pressed])}])
(when config/database-management-enabled?
[quo/list-item {:theme :accent
:on-press #(hide-sheet-and-dispatch [:multiaccounts.login.ui/import-db-submitted])
:icon :main-icons/receive
:title "Import unencrypted"}])
(when config/database-management-enabled?
[quo/list-item {:theme :accent
:on-press #(hide-sheet-and-dispatch [:multiaccounts.login.ui/export-db-submitted])
:icon :main-icons/send
:title "Export unencrypted"}])]]))
(def bottom-sheet
{:content bottom-sheet-view})

View File

@ -1,254 +0,0 @@
(ns status-im.ui.screens.profile.tribute-to-talk.styles
(:require [status-im.ui.components.colors :as colors]))
(def intro-container
{:flex 1
:align-items :center
:margin-horizontal 32})
(def intro-image
{:width 246
:height 219
:margin-vertical 32})
(def intro-text
{:typography :header
:text-align :center})
(def description-label
{:text-align :center
:color colors/gray})
(def step-n
{:margin-top 5
:font-size 14
:text-align :center
:color colors/gray})
(def tribute-to-talk
{:typography :main-medium
:text-align :center})
(def container
{:flex 1
:background-color colors/white})
(def set-snt-amount-container
{:flex-grow 1
:flex-direction :column
:background-color colors/white})
(defn horizontal-separator
[min-height max-height]
{:flex 1
:min-height min-height
:max-height max-height})
(def number-row
{:flex-direction :row})
(def number-pad
{:flex 1
:align-items :center
:margin-bottom 24
:min-height 292
:max-height 328})
(def number-container
{:width 64
:height 64
:border-radius 32
:justify-content :center
:align-items :center
:background-color colors/blue-light})
(def vertical-number-separator
{:flex 1
:min-width 16
:max-width 32})
(def number
{:font-size 22
:color colors/blue})
(def snt-amount-container
{:margin-horizontal 16
:justify-content :center
:align-items :center})
(def snt-amount
{:font-size 32})
(def snt-amount-label
(assoc snt-amount :color colors/gray))
(def snt-asset-value
{:typography :main-medium
:color colors/gray})
(def finish-label
{:typography :header
:text-align :center})
(defn finish-circle [color radius]
{:background-color color
:width (* 2 radius)
:height (* 2 radius)
:border-radius radius
:justify-content :center
:align-items :center})
(def finish-circle-with-shadow
(assoc (finish-circle colors/white 40)
:elevation 5
:shadow-offset {:width 0 :height 2}
:shadow-radius 4
:shadow-color (colors/alpha "#435971" 0.124066)))
(defn icon-view [color]
{:background-color color
:justify-content :center
:align-items :center
:border-radius 20
:width 40
:height 40})
(def current-snt-amount
{:font-size 28
:font-weight "500"})
(def edit-label
{:color colors/blue})
(def edit-note
{:color colors/gray
:margin-top 16
:margin-horizontal 16
:text-align :center})
(def enabled-note
{:border-radius 8
:border-width 1
:padding 12
:border-color colors/gray-lighter
:margin-horizontal 16
:margin-bottom 16})
(def learn-more-container
{:flex-grow 1
:justify-content :flex-start})
(def learn-more-link
{:height 52
:padding-horizontal 32
:margin-bottom 16
:align-items :center
:justify-content :center})
(def learn-more-link-text
{:color colors/blue})
(def learn-more-image
{:width 120
:height 110
:margin-top 32
:margin-left 32
:margin-bottom 16
:align-items :flex-start
:justify-content :center})
(def learn-more-title-text
(assoc intro-text
:text-align :left
:margin-left 32))
(def learn-more-text-container-1
{:margin-horizontal 32
:margin-top 12
:margin-bottom 24})
(def learn-more-text-container-2
{:margin-horizontal 32
:margin-top 16
:margin-bottom 32})
(def learn-more-text
{:typography :title})
(def learn-more-section
{:border-radius 12
:border-width 1
:margin-horizontal 32
:padding 8
:width 238
:border-color colors/gray-lighter})
(def pay-to-chat-bubble
{:background-color colors/blue-light
:padding-horizontal 12
:padding-vertical 8
:margin-top 4
:border-radius 8})
(def pay-to-chat-container
{:justify-content :center
:align-items :center
:flex-direction :row
:padding-top 12
:padding-bottom 4})
(def pay-to-chat-text
{:color colors/blue})
(defn payment-status-icon [pending?]
{:width 24
:height 24
:border-radius 12
:justify-content :center
:align-items :center
:background-color (if pending?
colors/black-transparent
colors/green)})
(def payment-status-text
{:font-size 15
:color colors/gray
:margin-left 6
:line-height 22})
(def edit-container
{:justify-content :space-between
:flex-grow 1})
(def edit-screen-top-row
{:flex-direction :row
:margin-vertical 16
:margin-horizontal 16
:align-items :flex-start
:justify-content :space-between})
(def remove-view
{:flex-direction :row
:justify-content :flex-start
:align-self :flex-start
:margin-horizontal 16
:margin-top 52})
(def remove-text
{:typography :title
:color colors/red
:margin-left 16})
(def remove-note
{:margin-horizontal 16
:color colors/gray
:text-align :center
:margin-top 12})
(def enabled-note-text
{:typography :main-medium})
(def separator-style
{:height 1
:background-color colors/gray-lighter
:align-self :stretch})

View File

@ -1,365 +0,0 @@
(ns status-im.ui.screens.profile.tribute-to-talk.views
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.react-native.resources :as resources]
[status-im.ui.components.colors :as colors]
[quo.core :as quo]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.react :as react]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.screens.profile.tribute-to-talk.styles :as styles])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn separator []
[react/view {:style styles/separator-style}])
(defn steps-numbers [editing?]
{:intro 1
:set-snt-amount (if editing? 1 2)})
(def step-forward-label
{:intro :t/get-started
:set-snt-amount :t/continue
:finish :t/ok-got-it})
(defn intro
[]
[react/scroll-view
[react/view {:style styles/intro-container}
[react/view {:style {:flex 1
:min-height 32}}]
[react/image {:source (resources/get-image :tribute-to-talk)
:style styles/intro-image}]
[react/view {:style {:flex 1
:min-height 32}}]
[react/view
[react/i18n-text {:style styles/intro-text
:key :tribute-to-talk}]
[react/i18n-text {:style (assoc styles/description-label :margin-top 12)
:key :tribute-to-talk-desc}]
[react/view {:style styles/learn-more-link}
[react/text {:style styles/learn-more-link-text
:on-press #(re-frame/dispatch
[:tribute-to-talk.ui/learn-more-pressed])}
(i18n/label :t/learn-more)]]]]])
(defn snt-asset-value
[fiat-value]
[react/text {:style styles/snt-asset-value}
fiat-value])
(defn snt-amount-label
[snt-amount fiat-value]
[react/view {:style styles/snt-amount-container}
[react/nested-text {:style styles/snt-amount-label
:number-of-lines 1
:ellipsize-mode :middle}
[{:style styles/snt-amount} (or snt-amount "0")]
" SNT"]
[snt-asset-value fiat-value]])
(defn number-view
[numpad-symbol {:keys [on-press]}]
[react/touchable-opacity
{:on-press #(on-press numpad-symbol)}
[react/view {:style styles/number-container}
(if (= numpad-symbol :remove)
[icons/icon :main-icons/backspace {:color colors/blue}]
[react/text {:style styles/number} numpad-symbol])]])
(defn number-row
[[left middle right] opts]
[react/view {:style styles/number-row}
[number-view left opts]
[react/view {:style styles/vertical-number-separator}]
[number-view middle opts]
[react/view {:style styles/vertical-number-separator}]
[number-view right opts]])
(defn number-pad
[opts]
[react/view {:style styles/number-pad}
[number-row [1 2 3] opts]
[react/view {:style (styles/horizontal-separator 12 24)}]
[number-row [4 5 6] opts]
[react/view {:style (styles/horizontal-separator 12 24)}]
[number-row [7 8 9] opts]
[react/view {:style (styles/horizontal-separator 12 24)}]
[number-row ["." 0 :remove] opts]])
(defn set-snt-amount
[snt-amount]
[react/scroll-view
{:content-container-style styles/set-snt-amount-container}
[react/view {:style (styles/horizontal-separator 16 32)}]
[snt-amount-label snt-amount]
[react/view {:style (styles/horizontal-separator 16 40)}]
[number-pad {:on-press (fn [numpad-symbol]
(re-frame/dispatch
[:tribute-to-talk.ui/numpad-key-pressed numpad-symbol]))}]
[react/i18n-text {:style (assoc styles/description-label :margin-horizontal 16)
:key :tribute-to-talk-set-snt-amount}]])
(defn finish
[snt-amount state]
[react/view {:style styles/intro-container}
[react/view {:style {:flex 1
:min-height 32}}]
[react/view {:style {:justify-content :center
:align-items :center}}
[react/view {:style (styles/finish-circle
(case state
:completed
colors/green-transparent-10
:disabled
colors/gray-lighter
:pending
colors/gray-lighter
:signing
colors/gray-lighter
:transaction-failed
colors/red-transparent-10)
80)}
[react/view {:style styles/finish-circle-with-shadow}
(if (#{:signing :pending} state)
[react/activity-indicator {:animating true
:size :large
:color colors/gray}]
[icons/icon (case state
:completed :main-icons/check
:disabled :main-icons/cancel
:transaction-failed :main-icons/warning)
{:width 48 :height 48
:color (case state
:completed
colors/green
:disabled
colors/gray
:pending
colors/gray
:signing
colors/gray
:transaction-failed
colors/red)}])]]]
[react/view {:style {:flex 1
:min-height 32}}]
[react/view {:style {:justify-content :center
:align-items :center
:margin-bottom 32}}
[react/text {:style styles/finish-label}
(i18n/label (case state
:completed
:t/you-are-all-set
:disabled
:t/tribute-to-talk-disabled
:pending
:t/tribute-to-talk-pending
:signing
:t/tribute-to-talk-signing
:transaction-failed
:t/transaction-failed))]
(case state
:completed
[react/nested-text {:style (assoc styles/description-label :margin-top 16)}
(i18n/label :t/tribute-to-talk-finish-desc)
[{:style {:color colors/black
:font-weight "600"}} snt-amount]
" SNT"]
:disabled
[react/text {:style (assoc styles/description-label :margin-top 16)}
(i18n/label :t/tribute-to-talk-disabled-note)]
:pending
[react/text {:style (assoc styles/description-label :margin-top 16)}
(i18n/label :t/tribute-to-talk-pending-note)]
:signing
nil
:transaction-failed
[react/text {:style (assoc styles/description-label :margin-top 16)}
(i18n/label :t/tribute-to-talk-transaction-failed-note)])]])
(defn enabled-note
[]
[react/view {:style styles/enabled-note}
[react/view {:flex-direction :row}
[icons/icon :main-icons/info {:color colors/gray}]
[react/text {:style (assoc styles/enabled-note-text
:margin-left 11)}
(i18n/label :t/tribute-to-talk-enabled)]]
[react/text {:style (assoc styles/enabled-note-text
:margin-left 35)}
(i18n/label :t/tribute-to-talk-add-friends)]])
(defn edit
[snt-amount fiat-value]
[react/scroll-view {:content-container-style styles/edit-container}
[react/view {:style styles/edit-screen-top-row}
[react/view {:style {:flex-direction :row
:justify-content :flex-start
:align-items :flex-start}}
[icons/icon :icons/logo {:container-style (styles/icon-view colors/blue)
:width 40
:height 40}]
[react/view {:style {:margin-left 16 :justify-content :flex-start}}
[react/view {:style {:justify-content :center
:align-items :center}}
[react/nested-text {:style styles/current-snt-amount}
snt-amount
[{:style (assoc styles/current-snt-amount :color colors/gray)}
" SNT"]]]
[snt-asset-value fiat-value]]]
[react/view {:flex 1}]
[react/text {:on-press #(re-frame/dispatch
[:tribute-to-talk.ui/edit-pressed])
:style styles/edit-label}
(i18n/label :t/edit)]]
[separator]
[react/text {:style styles/edit-note}
(i18n/label :t/tribute-to-talk-you-require-snt)]
[react/touchable-highlight {:on-press #(re-frame/dispatch
[:tribute-to-talk.ui/remove-pressed])
:style styles/remove-view}
[react/view {:style {:flex-direction :row}}
[react/view {:style (styles/icon-view colors/red-transparent-10)}
[icons/icon :main-icons/logout {:color colors/red}]]
[react/view {:style {:justify-content :center
:align-items :center}}
[react/text {:style styles/remove-text}
(i18n/label :t/remove)]]]]
[react/text {:style styles/remove-note}
(i18n/label :t/tribute-to-talk-removing-note)]
[react/view {:flex 1
:min-height 24}]
[enabled-note]])
(defn pay-to-chat-message
[{:keys [snt-amount style public-key tribute-status
tribute-label fiat-amount fiat-currency token]}]
[react/view {:style style}
[react/view {:style {:flex-direction :row
:align-items :center}}
[react/view {:style {:background-color colors/white
:justify-content :center
:align-items :center}}
[icons/tiny-icon :tiny-icons/tribute-to-talk {:color colors/blue}]]
[react/text {:style {:color colors/gray
:font-size 13
:margin-left 4}}
(i18n/label :t/tribute-to-talk)]]
(when snt-amount
[react/view {:style styles/pay-to-chat-bubble}
[react/nested-text {:style {:font-size 22}}
(str snt-amount)
[{:style {:font-size 22 :color colors/gray}} token]]
[react/nested-text
{:style {:font-size 12}}
fiat-amount
[{:style {:font-size 12 :color colors/gray}}
(str " " fiat-currency)]]
(if (or (nil? public-key) (= tribute-status :required))
[react/view {:style styles/pay-to-chat-container}
[react/text (cond-> {:style styles/pay-to-chat-text}
public-key
(assoc :on-press
#(re-frame/dispatch [:tribute-to-talk.ui/on-pay-to-chat-pressed
public-key])))
(i18n/label :t/pay-to-chat)]]
[react/view {:style styles/pay-to-chat-container}
[react/view {:style (styles/payment-status-icon (= tribute-status :pending))}
[icons/tiny-icon (if (= tribute-status :pending) :tiny-icons/tiny-pending :tiny-icons/tiny-check)
{:color (if (= tribute-status :pending) colors/black colors/white)}]]
[react/text {:style styles/payment-status-text} tribute-label]])])])
(defn learn-more [owner?]
[react/view {:flex 1}
(when-not owner?
[topbar/topbar {:modal? true
:title (i18n/label :t/tribute-to-talk)
:subtitle (i18n/label :t/learn-more)}])
[react/scroll-view {:content-container-style styles/learn-more-container}
[react/image {:source (resources/get-image :tribute-to-talk)
:style styles/learn-more-image}]
[react/text {:style styles/learn-more-title-text}
(i18n/label :t/tribute-to-talk)]
[react/view {:style styles/learn-more-text-container-1}
[react/text {:style styles/learn-more-text}
(i18n/label (if owner? :t/tribute-to-talk-learn-more-1
:t/tribute-to-talk-paywall-learn-more-1))]]
[separator]
[pay-to-chat-message {:snt-amount 1000
:token " SNT"
:fiat-currency "USD"
:fiat-amount "5"
:style (assoc styles/learn-more-section
:align-items :flex-start
:margin-top 24)}]
[react/view {:style styles/learn-more-text-container-2}
[react/text {:style styles/learn-more-text}
(i18n/label (if owner? :t/tribute-to-talk-learn-more-2
:t/tribute-to-talk-paywall-learn-more-2))]]
[react/view {:style (assoc styles/learn-more-section
:flex-direction :row
:align-items :stretch
:padding-horizontal 16
:padding-vertical 12)}
[react/view {:style (styles/icon-view colors/blue-light)}
[icons/icon :main-icons/add-contact {:color colors/blue}]]
[react/view {:style {:margin-left 16 :justify-content :center}}
[react/text {:style (assoc styles/learn-more-text :color colors/blue)}
(i18n/label (if owner? :t/add-to-contacts :t/share-profile))]]]
[react/view {:style styles/learn-more-text-container-2}
[react/text {:style styles/learn-more-text}
(i18n/label (if owner? :t/tribute-to-talk-learn-more-3
:t/tribute-to-talk-paywall-learn-more-3))]]]])
(defview tribute-to-talk []
(letsubs [{:keys [step snt-amount
fiat-value disable-button? state]}
[:tribute-to-talk/settings-ui]]
[react/keyboard-avoiding-view {:style styles/container}
[react/view {:style {:flex 1}}
;; [toolbar/toolbar
;; nil
;; (when-not (= :finish step)
;; (toolbar/nav-button
;; (actions/back #(re-frame/dispatch
;; [:tribute-to-talk.ui/step-back-pressed]))))
;; [react/view
;; [react/text {:style styles/tribute-to-talk}
;; (i18n/label :t/tribute-to-talk)]
;; (when-not (#{:edit :learn-more} step)
;; [react/text {:style styles/step-n}
;; (if (= step :finish)
;; (i18n/label (case state
;; :completed :t/completed
;; :pending :t/pending
;; :signing :t/signing
;; :transaction-failed :t/transaction-failed
;; :disabled :t/disabled))
;; (i18n/label :t/step-i-of-n {:step ((steps-numbers editing?) step)
;; :number (if editing? 2 3)}))])
;; (when (= step :learn-more)
;; [react/text {:style styles/step-n}
;; (i18n/label :t/learn-more)])]]
(case step
:intro [intro]
:set-snt-amount [set-snt-amount snt-amount]
:edit [edit snt-amount fiat-value]
:learn-more [learn-more step]
:finish [finish snt-amount state])
(when-not (#{:learn-more :edit} step)
[toolbar/toolbar
{:show-border? true
:size :large
:center
[quo/button {:disabled disable-button?
:type :secondary
:on-press #(re-frame/dispatch
[:tribute-to-talk.ui/step-forward-pressed])}
(i18n/label (step-forward-label step))]}])]]))

View File

@ -1,7 +1,6 @@
(ns status-im.ui.screens.routing.main
(:require-macros [status-im.utils.views :as views])
(:require [status-im.ui.screens.profile.tribute-to-talk.views :as tr-to-talk]
[status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
(:require [status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
[status-im.ui.screens.wallet.recipient.views :as recipient]
[status-im.ui.screens.qr-scanner.views :as qr-scanner]
[status-im.ui.screens.stickers.views :as stickers]
@ -72,8 +71,6 @@
:component intro-login-stack/intro-stack})
{:name :stickers-pack-modal
:component stickers/pack-modal}
{:name :tribute-learn-more
:component tr-to-talk/learn-more}
{:name :welcome
:back-handler :noop
:component home/welcome}

View File

@ -31,7 +31,6 @@
[status-im.ui.screens.log-level-settings.views :as log-level-settings]
[status-im.ui.screens.fleet-settings.views :as fleet-settings]
[status-im.ui.screens.profile.seed.views :as profile.seed]
[status-im.ui.screens.profile.tribute-to-talk.views :as tr-to-talk]
[status-im.ui.screens.keycard.pin.views :as keycard.pin]
[status-im.ui.screens.keycard.settings.views :as keycard.settings]
[status-im.ui.components.tabbar.styles :as tabbar.styles]
@ -117,8 +116,6 @@
:component mobile-network-settings/mobile-network-settings}
{:name :backup-seed
:component profile.seed/backup-seed}
{:name :tribute-to-talk
:component tr-to-talk/tribute-to-talk}
{:name :delete-profile
:transition :presentation-ios
:insets {:bottom true}

View File

@ -39,7 +39,6 @@
(def blank-preview? (enabled? (get-config :BLANK_PREVIEW "1")))
(def group-chat-enabled? (enabled? (get-config :GROUP_CHATS_ENABLED "0")))
(def tooltip-events? (enabled? (get-config :TOOLTIP_EVENTS "0")))
(def nimbus-enabled? (enabled? (get-config :STATUS_GO_ENABLE_NIMBUS "0")))
(def commands-enabled? (enabled? (get-config :COMMANDS_ENABLED "0")))
(def keycard-test-menu-enabled? (enabled? (get-config :KEYCARD_TEST_MENU "0")))
(def qr-test-menu-enabled? (enabled? (get-config :QR_READ_TEST_MENU "0")))
@ -49,6 +48,7 @@
(def communities-enabled? (enabled? (get-config :COMMUNITIES_ENABLED "0")))
(def communities-management-enabled? (and (enabled? (get-config :COMMUNITIES_MANAGEMENT_ENABLED "0"))
communities-enabled?))
(def database-management-enabled? (enabled? (get-config :DATABASE_MANAGEMENT_ENABLED "0")))
;; CONFIG VALUES
(def log-level

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im",
"repo": "status-go",
"version": "v0.68.8",
"commit-sha1": "d8bccaff1838b674be5fb362c601c8e122f01962",
"src-sha256": "1487b2y849k535mskd81hzfhz622h588mbcmws0p2djhbcdnpvr4"
"version": "v0.69.0",
"commit-sha1": "f73fb9c3f640d610ead693d95246b837b5c16990",
"src-sha256": "01fgsx8j2wvw58l73575b1rh6fjrrgbqqvpkyhzc4lxw2d6zhqk8"
}