* Fix #1886 Completly rework the way how async handlers work Delay further processing of message till async handler returns result * Fix indent * Fix #1903
This commit is contained in:
parent
bce18bf32c
commit
805d874846
|
@ -352,26 +352,27 @@ function handleSend(params, context) {
|
||||||
gasPrice: calculateGasPrice(params["bot-db"]["sliderValue"])
|
gasPrice: calculateGasPrice(params["bot-db"]["sliderValue"])
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
web3.eth.sendTransaction(data, function(error, hash) {
|
web3.eth.sendTransaction(data, function(error, hash) {
|
||||||
if (error) {
|
if (error) {
|
||||||
status.sendSignal("handler-data", {
|
status.sendSignal("handler-result", {
|
||||||
status: "failed",
|
status: "failed",
|
||||||
messageId: context["message-id"],
|
error: {
|
||||||
error: error
|
markup: status.components.validationMessage(
|
||||||
|
I18n.t('validation_tx_title'),
|
||||||
|
I18n.t('validation_tx_failed')
|
||||||
|
)
|
||||||
|
},
|
||||||
|
origParams: context["orig-params"]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
status.sendSignal("handler-data", {
|
status.sendSignal("handler-result", {
|
||||||
status: "sent",
|
status: "success",
|
||||||
messageId: context["message-id"],
|
hash: hash,
|
||||||
hash: hash
|
origParams: context["orig-params"]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// async handler, so we don't return anything immediately
|
||||||
return {
|
|
||||||
status: 'not-confirmed'
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function previewSend(params, context) {
|
function previewSend(params, context) {
|
||||||
|
@ -449,36 +450,6 @@ function previewSend(params, context) {
|
||||||
} else {
|
} else {
|
||||||
markup = [firstRow];
|
markup = [firstRow];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(context["handler-data"]
|
|
||||||
&& context["handler-data"]["status"] === "sent")) {
|
|
||||||
var pendingRow = status.components.text(
|
|
||||||
{
|
|
||||||
style: {
|
|
||||||
color: "#9199a0",
|
|
||||||
fontSize: 12,
|
|
||||||
lineHeight: 18
|
|
||||||
}
|
|
||||||
},
|
|
||||||
I18n.t('send_transaction_pending')
|
|
||||||
);
|
|
||||||
markup.push(pendingRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context["handler-data"]
|
|
||||||
&& context["handler-data"]["status"] === "failed") {
|
|
||||||
var errorRow = status.components.text(
|
|
||||||
{
|
|
||||||
style: {
|
|
||||||
color: "red",
|
|
||||||
fontSize: 12,
|
|
||||||
lineHeight: 18
|
|
||||||
}
|
|
||||||
},
|
|
||||||
I18n.t('send_transaction_failed')
|
|
||||||
);
|
|
||||||
markup.push(errorRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
markup: status.components.view(
|
markup: status.components.view(
|
||||||
|
@ -512,6 +483,7 @@ var send = {
|
||||||
params: paramsSend,
|
params: paramsSend,
|
||||||
validator: validateSend,
|
validator: validateSend,
|
||||||
handler: handleSend,
|
handler: handleSend,
|
||||||
|
asyncHandler: true,
|
||||||
preview: previewSend,
|
preview: previewSend,
|
||||||
shortPreview: shortPreviewSend
|
shortPreview: shortPreviewSend
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,8 +14,6 @@ I18n.translations = {
|
||||||
send_explanation_3: 'probably within 30 seconds.',
|
send_explanation_3: 'probably within 30 seconds.',
|
||||||
send_explanation_4: 'probably within a few seconds.',
|
send_explanation_4: 'probably within a few seconds.',
|
||||||
send_sending_to: 'to ',
|
send_sending_to: 'to ',
|
||||||
send_transaction_pending: 'transaction pending',
|
|
||||||
send_transaction_failed: 'transaction failed',
|
|
||||||
|
|
||||||
eth: 'ETH',
|
eth: 'ETH',
|
||||||
|
|
||||||
|
@ -25,6 +23,8 @@ I18n.translations = {
|
||||||
request_requesting_from: 'from ',
|
request_requesting_from: 'from ',
|
||||||
|
|
||||||
validation_title: 'Amount',
|
validation_title: 'Amount',
|
||||||
|
validation_tx_title: 'Transaction',
|
||||||
|
validation_tx_failed: 'Transaction failed',
|
||||||
validation_amount_specified: 'Amount must be specified',
|
validation_amount_specified: 'Amount must be specified',
|
||||||
validation_invalid_number: 'Amount is not valid number',
|
validation_invalid_number: 'Amount is not valid number',
|
||||||
validation_amount_is_too_small: 'Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)',
|
validation_amount_is_too_small: 'Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)',
|
||||||
|
|
|
@ -27,6 +27,7 @@ Command.prototype.create = function (com) {
|
||||||
this.description = com.description;
|
this.description = com.description;
|
||||||
this.handler = com.handler;
|
this.handler = com.handler;
|
||||||
this["has-handler"] = com.handler != null;
|
this["has-handler"] = com.handler != null;
|
||||||
|
this["async-handler"] = (com.handler != null) && com.asyncHandler
|
||||||
this["registered-only"] = com.registeredOnly;
|
this["registered-only"] = com.registeredOnly;
|
||||||
this.validator = com.validator;
|
this.validator = com.validator;
|
||||||
this.color = com.color;
|
this.color = com.color;
|
||||||
|
@ -41,6 +42,7 @@ Command.prototype.create = function (com) {
|
||||||
this["execute-immediately?"] = com.executeImmediately;
|
this["execute-immediately?"] = com.executeImmediately;
|
||||||
this["sequential-params"] = com.sequentialParams;
|
this["sequential-params"] = com.sequentialParams;
|
||||||
this["hide-send-button"] = com.hideSendButton;
|
this["hide-send-button"] = com.hideSendButton;
|
||||||
|
|
||||||
this.addToCatalog();
|
this.addToCatalog();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -13,111 +13,110 @@
|
||||||
|
|
||||||
(defn generate-context
|
(defn generate-context
|
||||||
"Generates context for jail call"
|
"Generates context for jail call"
|
||||||
[{:keys [chats handler-data] :accounts/keys [current-account-id]} message-id chat-id to group-id]
|
[{:keys [chats] :accounts/keys [current-account-id]} chat-id to group-id]
|
||||||
(merge {:platform platform/platform
|
(merge {:platform platform/platform
|
||||||
:from current-account-id
|
:from current-account-id
|
||||||
:to to
|
:to to
|
||||||
:chat {:chat-id chat-id
|
:chat {:chat-id chat-id
|
||||||
:group-chat (or (get-in chats [chat-id :group-chat])
|
:group-chat (or (get-in chats [chat-id :group-chat])
|
||||||
(not (nil? group-id)))}
|
(not (nil? group-id)))}}
|
||||||
:handler-data (get handler-data message-id)}
|
|
||||||
i18n/delimeters))
|
i18n/delimeters))
|
||||||
|
|
||||||
;;;; Coeffects
|
;;;; Coeffects
|
||||||
|
|
||||||
(reg-cofx
|
(reg-cofx
|
||||||
::get-persisted-message
|
::get-persisted-message
|
||||||
(fn [coeffects _]
|
(fn [coeffects _]
|
||||||
(assoc coeffects :get-persisted-message msg-store/get-by-id)))
|
(assoc coeffects :get-persisted-message msg-store/get-by-id)))
|
||||||
|
|
||||||
;;;; Effects
|
;;;; Effects
|
||||||
|
|
||||||
(reg-fx
|
(reg-fx
|
||||||
::update-persisted-message
|
::update-persisted-message
|
||||||
(fn [message]
|
(fn [message]
|
||||||
(msg-store/update message)))
|
(msg-store/update message)))
|
||||||
|
|
||||||
|
|
||||||
(reg-fx
|
(reg-fx
|
||||||
:chat-fx/call-jail
|
:chat-fx/call-jail
|
||||||
(fn [{:keys [callback-events-creator] :as opts}]
|
(fn [{:keys [callback-events-creator] :as opts}]
|
||||||
(status/call-jail
|
(status/call-jail
|
||||||
(-> opts
|
(-> opts
|
||||||
(dissoc :callback-events-creator)
|
(dissoc :callback-events-creator)
|
||||||
(assoc :callback
|
(assoc :callback
|
||||||
(fn [jail-response]
|
(fn [jail-response]
|
||||||
(doseq [event (callback-events-creator jail-response)]
|
(doseq [event (callback-events-creator jail-response)]
|
||||||
(dispatch event))))))))
|
(dispatch event))))))))
|
||||||
|
|
||||||
;;;; Handlers
|
;;;; Handlers
|
||||||
|
|
||||||
(register-handler-fx
|
(register-handler-fx
|
||||||
::jail-command-data-response
|
::jail-command-data-response
|
||||||
[trim-v]
|
[trim-v]
|
||||||
(fn [{:keys [db]} [{{:keys [returned]} :result} {:keys [message-id on-requested]} data-type]]
|
(fn [{:keys [db]} [{{:keys [returned]} :result} {:keys [message-id on-requested]} data-type]]
|
||||||
(cond-> {}
|
(cond-> {}
|
||||||
returned
|
returned
|
||||||
(assoc :db (assoc-in db [:message-data data-type message-id] returned))
|
(assoc :db (assoc-in db [:message-data data-type message-id] returned))
|
||||||
(and returned
|
(and returned
|
||||||
(= :preview data-type))
|
(= :preview data-type))
|
||||||
(assoc ::update-persisted-message {:message-id message-id
|
(assoc ::update-persisted-message {:message-id message-id
|
||||||
:preview (prn-str returned)})
|
:preview (prn-str returned)})
|
||||||
on-requested
|
on-requested
|
||||||
(assoc :dispatch (on-requested returned)))))
|
(assoc :dispatch (on-requested returned)))))
|
||||||
|
|
||||||
(register-handler-fx
|
(register-handler-fx
|
||||||
:request-command-data
|
:request-command-data
|
||||||
[trim-v]
|
[trim-v]
|
||||||
(fn [{:keys [db]}
|
(fn [{:keys [db]}
|
||||||
[{{:keys [command content-command params type]} :content
|
[{{:keys [command content-command params type]} :content
|
||||||
:keys [chat-id jail-id group-id message-id] :as message}
|
:keys [chat-id jail-id group-id message-id handler-data] :as message}
|
||||||
data-type]]
|
data-type]]
|
||||||
(let [{:keys [chats]
|
(let [{:keys [chats]
|
||||||
:accounts/keys [current-account-id]
|
:accounts/keys [current-account-id]
|
||||||
:contacts/keys [contacts]} db
|
:contacts/keys [contacts]} db
|
||||||
jail-id (or jail-id chat-id)
|
jail-id (or jail-id chat-id)
|
||||||
jail-id (if (get-in chats [jail-id :group-chat])
|
jail-id (if (get-in chats [jail-id :group-chat])
|
||||||
(get-in chats [jail-id :command-suggestions (keyword command) :owner-id])
|
(get-in chats [jail-id :command-suggestions (keyword command) :owner-id])
|
||||||
jail-id)]
|
jail-id)]
|
||||||
(if (get-in contacts [jail-id :commands-loaded?])
|
(if (get-in contacts [jail-id :commands-loaded?])
|
||||||
(let [path [(if (= :response (keyword type)) :responses :commands)
|
(let [path [(if (= :response (keyword type)) :responses :commands)
|
||||||
(or content-command command)
|
(or content-command command)
|
||||||
data-type]
|
data-type]
|
||||||
to (get-in contacts [chat-id :address])
|
to (get-in contacts [chat-id :address])
|
||||||
jail-params {:parameters params
|
jail-params {:parameters params
|
||||||
:context (generate-context db message-id chat-id to group-id)}]
|
:context (generate-context db chat-id to group-id)}]
|
||||||
{:chat-fx/call-jail {:jail-id jail-id
|
{:chat-fx/call-jail {:jail-id jail-id
|
||||||
:path path
|
:path path
|
||||||
:params jail-params
|
:params jail-params
|
||||||
:callback-events-creator (fn [jail-response]
|
:callback-events-creator (fn [jail-response]
|
||||||
[[::jail-command-data-response
|
[[::jail-command-data-response
|
||||||
jail-response message data-type]])}})
|
jail-response message data-type]])}})
|
||||||
{:dispatch-n [[:add-commands-loading-callback jail-id
|
{:dispatch-n [[:add-commands-loading-callback jail-id
|
||||||
#(dispatch [:request-command-data message data-type])]
|
#(dispatch [:request-command-data message data-type])]
|
||||||
[:load-commands! jail-id]]}))))
|
[:load-commands! jail-id]]}))))
|
||||||
|
|
||||||
(register-handler-fx
|
(register-handler-fx
|
||||||
:execute-command-immediately
|
:execute-command-immediately
|
||||||
[trim-v]
|
[trim-v]
|
||||||
(fn [_ [{command-name :name :as command}]]
|
(fn [_ [{command-name :name :as command}]]
|
||||||
(case (keyword command-name)
|
(case (keyword command-name)
|
||||||
:grant-permissions
|
:grant-permissions
|
||||||
{:dispatch [:request-permissions
|
{:dispatch [:request-permissions
|
||||||
[:read-external-storage]
|
[:read-external-storage]
|
||||||
#(dispatch [:initialize-geth])]}
|
#(dispatch [:initialize-geth])]}
|
||||||
(log/debug "ignoring command: " command))))
|
(log/debug "ignoring command: " command))))
|
||||||
|
|
||||||
(register-handler-fx
|
(register-handler-fx
|
||||||
:request-command-preview
|
:request-command-preview
|
||||||
[trim-v (inject-cofx ::get-persisted-message)]
|
[trim-v (inject-cofx ::get-persisted-message)]
|
||||||
(fn [{:keys [db get-persisted-message]} [{:keys [message-id] :as message}]]
|
(fn [{:keys [db get-persisted-message]} [{:keys [message-id] :as message}]]
|
||||||
(let [previews (get-in db [:message-data :preview])]
|
(let [previews (get-in db [:message-data :preview])]
|
||||||
(when-not (contains? previews message-id)
|
(when-not (contains? previews message-id)
|
||||||
(let [{serialized-preview :preview} (get-persisted-message message-id)]
|
(let [{serialized-preview :preview} (get-persisted-message message-id)]
|
||||||
;; if preview is already cached in db, do not request it from jail
|
;; if preview is already cached in db, do not request it from jail
|
||||||
;; and write it directly to message-data path
|
;; and write it directly to message-data path
|
||||||
(if serialized-preview
|
(if serialized-preview
|
||||||
{:db (assoc-in db
|
{:db (assoc-in db
|
||||||
[:message-data :preview message-id]
|
[:message-data :preview message-id]
|
||||||
(reader/read-string serialized-preview))}
|
(reader/read-string serialized-preview))}
|
||||||
{:dispatch [:request-command-data message :preview]}))))))
|
{:dispatch [:request-command-data message :preview]}))))))
|
||||||
|
|
|
@ -107,20 +107,9 @@
|
||||||
params' (assoc params :command content')]
|
params' (assoc params :command content')]
|
||||||
(dispatch [:prepare-command! wallet-chat-id params'])))))))
|
(dispatch [:prepare-command! wallet-chat-id params'])))))))
|
||||||
|
|
||||||
(register-handler ::check-preview-refetch
|
|
||||||
(fn [db [_ chat-id {:keys [message-id] :as message}]]
|
|
||||||
(let [handler-data (get-in db [:handler-data message-id])]
|
|
||||||
(if (:fetch-preview handler-data)
|
|
||||||
(do (dispatch [:request-command-data (assoc message :jail-id chat-id) :preview])
|
|
||||||
(handler-data/save-data {:message-id message-id
|
|
||||||
:data (dissoc handler-data :fetch-preview)})
|
|
||||||
(update-in db [:handler-data message-id] dissoc :fetch-preview))
|
|
||||||
db))))
|
|
||||||
|
|
||||||
(register-handler ::send-command!
|
(register-handler ::send-command!
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [_ [_ add-to-chat-id params hidden-params]]
|
(fn [_ [_ add-to-chat-id params hidden-params]]
|
||||||
(dispatch [::check-preview-refetch add-to-chat-id (:command params)])
|
|
||||||
(dispatch [::add-command add-to-chat-id params])
|
(dispatch [::add-command add-to-chat-id params])
|
||||||
(dispatch [::save-command! add-to-chat-id params hidden-params])
|
(dispatch [::save-command! add-to-chat-id params hidden-params])
|
||||||
(when (not= add-to-chat-id wallet-chat-id)
|
(when (not= add-to-chat-id wallet-chat-id)
|
||||||
|
@ -163,11 +152,15 @@
|
||||||
to (get-in contacts [chat-id :address])
|
to (get-in contacts [chat-id :address])
|
||||||
identity (or owner-id bot chat-id)
|
identity (or owner-id bot chat-id)
|
||||||
bot-db (get bot-db (or bot chat-id))
|
bot-db (get bot-db (or bot chat-id))
|
||||||
|
;; TODO what's actually semantic difference between `:parameters` and `:context`
|
||||||
|
;; and do we have some clear API for both ? seems very messy and unorganized now
|
||||||
jail-params {:parameters params
|
jail-params {:parameters params
|
||||||
:context {:from address
|
:context (cond-> {:from address
|
||||||
:to to
|
:to to
|
||||||
:current-account (get accounts current-account-id)
|
:current-account (get accounts current-account-id)
|
||||||
:message-id id}}]
|
:message-id id}
|
||||||
|
(:async-handler command)
|
||||||
|
(assoc :orig-params orig-params))}]
|
||||||
(dispatch
|
(dispatch
|
||||||
[:check-and-load-commands!
|
[:check-and-load-commands!
|
||||||
identity
|
identity
|
||||||
|
@ -175,8 +168,11 @@
|
||||||
{:jail-id identity
|
{:jail-id identity
|
||||||
:path [handler-type name :handler]
|
:path [handler-type name :handler]
|
||||||
:params jail-params
|
:params jail-params
|
||||||
:callback (fn [res]
|
:callback (if (:async-handler command) ; async handler, we ignore return value
|
||||||
(dispatch [:command-handler! chat-id orig-params res]))})])))))
|
(fn [_]
|
||||||
|
(log/debug "Async command handler called"))
|
||||||
|
(fn [res]
|
||||||
|
(dispatch [:command-handler! chat-id orig-params res])))})])))))
|
||||||
|
|
||||||
(register-handler :prepare-message
|
(register-handler :prepare-message
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
(ns status-im.commands.events.jail
|
|
||||||
(:require [re-frame.core :as re-frame]
|
|
||||||
[status-im.utils.handlers :as handlers]
|
|
||||||
[status-im.data-store.handler-data :as handler-data]
|
|
||||||
[taoensso.timbre :as log]))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:save-handler-data
|
|
||||||
(fn [data]
|
|
||||||
(handler-data/save-data data)))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
|
||||||
:set-handler-data
|
|
||||||
[re-frame/trim-v]
|
|
||||||
(fn [{:keys [db]} [chat-id {:keys [messageId] :as data}]]
|
|
||||||
(let [;; this is very bad, we should refactor our db ASAP
|
|
||||||
message (->> (get-in db [:chats chat-id :messages])
|
|
||||||
(filter #(= (:message-id %) messageId))
|
|
||||||
first)
|
|
||||||
handler-data (cond-> (dissoc data :messageId)
|
|
||||||
;; message not there yet, indicate we want to re-fetch preview once it lands there
|
|
||||||
(nil? message)
|
|
||||||
(assoc :fetch-preview true))
|
|
||||||
old-handler-data (get-in db [:handler-data messageId] {})
|
|
||||||
new-handler-data (merge old-handler-data handler-data)]
|
|
||||||
(cond-> {:db (assoc-in db [:handler-data messageId] new-handler-data)
|
|
||||||
:save-handler-data {:message-id messageId
|
|
||||||
:data new-handler-data}}
|
|
||||||
;; message was already added to db, we can re-fetch preview
|
|
||||||
(not (nil? message))
|
|
||||||
(assoc :dispatch [:request-command-data (assoc message :jail-id chat-id) :preview])))))
|
|
|
@ -10,14 +10,13 @@
|
||||||
[status-im.constants :refer [console-chat-id]]
|
[status-im.constants :refer [console-chat-id]]
|
||||||
[status-im.i18n :refer [get-contact-translated]]
|
[status-im.i18n :refer [get-contact-translated]]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.data-store.local-storage :as local-storage]
|
[status-im.data-store.local-storage :as local-storage]))
|
||||||
status-im.commands.events.jail))
|
|
||||||
|
|
||||||
(defn command-handler!
|
(defn command-handler!
|
||||||
[_ [chat-id
|
[_ [chat-id
|
||||||
{:keys [command] :as params}
|
{:keys [command] :as params}
|
||||||
{:keys [result error]}]]
|
{:keys [result error]}]]
|
||||||
(let [{:keys [context returned]} result
|
(let [{:keys [returned]} result
|
||||||
{handler-error :error} returned]
|
{handler-error :error} returned]
|
||||||
(cond
|
(cond
|
||||||
handler-error
|
handler-error
|
||||||
|
@ -26,10 +25,8 @@
|
||||||
|
|
||||||
result
|
result
|
||||||
(let [command' (assoc command :handler-data returned)
|
(let [command' (assoc command :handler-data returned)
|
||||||
params' (assoc params :command command')]
|
params' (assoc params :command command')]
|
||||||
(if (:eth_sendTransaction context)
|
(dispatch [:prepare-command! chat-id params']))
|
||||||
(dispatch [:wait-for-transaction (:id command) params'])
|
|
||||||
(dispatch [:prepare-command! chat-id params'])))
|
|
||||||
|
|
||||||
(not (or error handler-error))
|
(not (or error handler-error))
|
||||||
(dispatch [:prepare-command! chat-id params])
|
(dispatch [:prepare-command! chat-id params])
|
||||||
|
|
|
@ -219,7 +219,10 @@
|
||||||
:markup data}])
|
:markup data}])
|
||||||
"send-message" (dispatch [:send-message-from-jail {:chat-id chat_id
|
"send-message" (dispatch [:send-message-from-jail {:chat-id chat_id
|
||||||
:message data}])
|
:message data}])
|
||||||
"handler-data" (dispatch [:set-handler-data chat_id data])
|
"handler-result" (let [orig-params (:origParams data)]
|
||||||
|
;; TODO(janherich): figure out and fix chat_id from event
|
||||||
|
(dispatch [:command-handler! (:chat-id orig-params) orig-params
|
||||||
|
{:result {:returned (dissoc data :origParams)}}]))
|
||||||
(log/debug "Unknown jail signal " type))))
|
(log/debug "Unknown jail signal " type))))
|
||||||
|
|
||||||
(register-handler-fx
|
(register-handler-fx
|
||||||
|
|
Loading…
Reference in New Issue