Reintroduced broken PR #7092 with fix

Signed-off-by: Igor Mandrigin <i@mandrigin.ru>
This commit is contained in:
Julien Eluard 2018-12-21 14:11:16 +01:00 committed by Igor Mandrigin
parent dfbc0eb435
commit 5db9aa9ac7
No known key found for this signature in database
GPG Key ID: 4A0EDDE26E66BC8B
9 changed files with 350 additions and 311 deletions

View File

@ -11,7 +11,7 @@
com.taoensso/timbre {:mvn/version "4.10.0"}
hickory {:mvn/version "0.7.1"}
com.cognitect/transit-cljs {:mvn/version "0.8.248"}
status-im/pluto {:mvn/version "iteration-4-5"}
status-im/pluto {:mvn/version "iteration-4-6"}
mvxcvi/alphabase {:mvn/version "1.0.0"}
rasom/cljs-react-navigation {:mvn/version "0.1.4"}}

View File

@ -11,7 +11,7 @@
[com.taoensso/timbre "4.10.0"]
[hickory "0.7.1"]
[com.cognitect/transit-cljs "0.8.248"]
[status-im/pluto "iteration-4-5"]
[status-im/pluto "iteration-4-6"]
[mvxcvi/alphabase "1.0.0"]
[rasom/cljs-react-navigation "0.1.4"]]
:plugins [[lein-cljsbuild "1.1.7"]

View File

@ -115,9 +115,9 @@
"Hook for extensions"
{:properties
{:description? :string
:scope #{:personal-chats :public-chats}
:short-preview :view
:preview :view
:scope #{:personal-chats :public-chats :group-chats}
:short-preview? :view
:preview? :view
:on-send? :event
:on-receive? :event
:on-send-sync? :event
@ -138,8 +138,8 @@
(validate [_ _ _])
(on-send [_ command-message _] (when on-send {:dispatch (on-send command-message)}))
(on-receive [_ command-message _] (when on-receive {:dispatch (on-receive command-message)}))
(short-preview [_ props] (short-preview props))
(preview [_ props] (preview props))
(short-preview [_ props] (when short-preview (short-preview props)))
(preview [_ props] (when preview (preview props)))
protocol/Yielding
(yield-control [_ props _] {:dispatch (on-send-sync props)})
protocol/Extension
@ -152,8 +152,8 @@
(validate [_ _ _])
(on-send [_ command-message _] (when on-send {:dispatch (on-send command-message)}))
(on-receive [_ command-message _] (when on-receive {:dispatch (on-receive command-message)}))
(short-preview [_ props] (short-preview props))
(preview [_ props] (preview props))
(short-preview [_ props] (when short-preview (short-preview props)))
(preview [_ props] (when preview (preview props)))
protocol/Extension
(extension-id [_] extension-id)))]
(load-commands cofx [new-command])))

View File

@ -8,6 +8,7 @@
[status-im.chat.commands.impl.transactions :as transactions]
[status-im.ui.components.button.view :as button]
[status-im.ui.components.checkbox.view :as checkbox]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.screens.wallet.settings.views :as settings]
@ -21,8 +22,7 @@
status-im.extensions.ethereum
[status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.ethereum.core :as ethereum]
[status-im.chat.commands.sending :as commands-sending]
[status-im.ui.components.icons.vector-icons :as icons]))
[status-im.chat.commands.sending :as commands-sending]))
(re-frame/reg-fx
::identity-event
@ -90,7 +90,7 @@
:<- [:balance]
(fn [[all-tokens network balance] [_ _ {token :token}]]
(let [{:keys [decimals]} (get-token-for network all-tokens token)
value (get balance (keyword token))]
value (or (get balance (keyword token)) (money/bignumber 0))]
{:value (money/token->unit value decimals)
:value-in-wei value})))
@ -98,20 +98,26 @@
:extensions.wallet/token
:<- [:wallet/all-tokens]
:<- [:network]
(fn [[all-tokens network] [_ _ {token :token amount :amount}]]
(fn [[all-tokens network] [_ _ {token :token amount :amount amount-in-wei :amount-in-wei}]]
(let [{:keys [decimals] :as m} (get-token-for network all-tokens token)]
(merge m
(when amount {:amount (money/unit->token amount decimals)})))))
(when amount {:amount-in-wei (money/unit->token amount decimals)})
(when amount-in-wei {:amount (money/token->unit amount-in-wei decimals)})))))
(defn normalize-token [m]
(update m :symbol name))
(re-frame/reg-sub
:extensions.wallet/tokens
:<- [:wallet/all-tokens]
:<- [:wallet/visible-tokens-symbols]
:<- [:network]
(fn [[all-tokens network] [_ _ {filter-vector :filter}]]
(let [tokens (tokens/sorted-tokens-for all-tokens (ethereum/network->chain-keyword network))]
(if (= :all (first filter-vector))
tokens
(filter #((set filter-vector) (:symbol %)) tokens)))))
(fn [[all-tokens visible-tokens-symbols network] [_ _ {filter-vector :filter visible :visible}]]
(let [tokens (map normalize-token (filter #(and (not (:nft? %)) (if visible (contains? visible-tokens-symbols (:symbol %)) true))
(tokens/sorted-tokens-for all-tokens (ethereum/network->chain-keyword network))))]
(if filter-vector
(filter #((set filter-vector) (:symbol %)) tokens)
tokens))))
(re-frame/reg-sub
:store/get
@ -360,29 +366,43 @@
(defn picker [{:keys [style on-change selected enabled data]}]
[react/picker {:style style :on-change #(re-frame/dispatch (on-change {:value %})) :selected selected :enabled enabled :data data}])
(defn- wrap-text-child [o]
(if (ifn? o) o (str o)))
(defn text [o & children]
(if (map? o)
[react/text o children]
(into [react/text {} o] children)))
(into [react/text o] (map wrap-text-child children))
(into [react/text {} o] (map wrap-text-child children))))
(defn- wrap-view-child [child]
(if (vector? child) child [text {} child]))
(defn view [o & children]
(defn abstract-view [type o & children]
(if (map? o)
(into [react/view o] (map wrap-view-child children))
(into [react/view {} (wrap-view-child o)] (map wrap-view-child children))))
(into [type o] (map wrap-view-child children))
(into [type {} (wrap-view-child o)] (map wrap-view-child children))))
(defn icon [o]
[icons/icon (:key o) o])
(defn view [o & children]
(apply abstract-view react/view o children))
(defn scroll-view [o & children]
(apply abstract-view react/scroll-view o children))
(defn keyboard-avoiding-view [o & children]
(apply abstract-view react/keyboard-avoiding-view o children))
(defn icon [{:keys [key] :as o}]
[icons/icon key o])
(def capacities
{:components {'view {:value view}
'scroll-view {:value scroll-view}
'keyboard-avoiding-view {:value react/keyboard-avoiding-view}
'text {:value text}
'touchable-opacity {:value touchable-opacity :properties {:on-press :event}}
'icon {:value icon :properties {:key :keyword :color :any}}
'image {:value image :properties {:uri :string :source :numeric}}
'input {:value input :properties {:on-change :event :change-delay :number :placeholder :string :keyboard-type :keyword :placeholder-text-color :any}}
'image {:value image :properties {:uri :string :source :string}}
'input {:value input :properties {:on-change :event :placeholder :string :keyboard-type :keyword :change-delay? :number :placeholder-text-color :any}}
'button {:value button :properties {:enabled :boolean :disabled :boolean :on-click :event}}
'link {:value link :properties {:uri :string}}
'list {:value list :properties {:data :vector :item-view :view :key? :keyword}}
@ -395,8 +415,8 @@
'store/get {:value :store/get :arguments {:key :string}}
'wallet/collectibles {:value :get-collectible-token :arguments {:token :string :symbol :string}}
'wallet/balance {:value :extensions.wallet/balance :arguments {:token :string}}
'wallet/token {:value :extensions.wallet/token :arguments {:token :string :amount? :numeric}}
'wallet/tokens {:value :extensions.wallet/tokens :arguments {:filter :vector}}}
'wallet/token {:value :extensions.wallet/token :arguments {:token :string :amount? :number :amount-in-wei? :number}}
'wallet/tokens {:value :extensions.wallet/tokens :arguments {:filter? :vector :visible? :boolean}}}
:events {'identity
{:permissions [:read]
:value :extensions/identity-event
@ -437,7 +457,7 @@
{:permissions [:read]
:value :extensions/arithmetic
:arguments {:values :vector
:operation :keyword
:operation {:one-of #{:plus :minus :times :divide}}
:on-result :event}}
'schedule/start
{:permissions [:read]
@ -506,13 +526,15 @@
{:permissions [:read]
:value :extensions/ethereum-transaction-receipt
:arguments {:value :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum/sign
{:permissions [:read]
:value :extensions/ethereum-sign
:arguments {:message? :string
:data? :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum/send-transaction
{:permissions [:read]
:value :extensions/ethereum-send-transaction
@ -523,31 +545,29 @@
:method? :string
:params? :vector
:nonce? :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum/logs
{:permissions [:read]
:value :extensions/ethereum-logs
:arguments {:fromBlock? :string
:toBlock? :string
:arguments {:from? :string
:to? :string
:address? :vector
:topics? :vector
:blockhash? :string
:on-result :event}}
'ethereum/resolve-ens
{:permissions [:read]
:value :extensions/ethereum-resolve-ens
:arguments {:name :string
:on-result :event}}
:block-hash? :string
:on-success :event
:on-failure? :event}}
'ethereum/create-filter
{:permissions [:read]
:value :extensions/ethereum-create-filter
:arguments {:filter-type :string
:arguments {:type {:one-of #{:filter :block :pending-transaction}}
:from? :string
:to? :string
:address? :vector
:topics? :vector
:block-hash? :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum/logs-changes
{:permissions [:read]
:value :extensions/ethereum-logs-changes
@ -556,24 +576,33 @@
{:permissions [:read]
:value :extensions/ethereum-cancel-filter
:arguments {:id :string}}
'ethereum.ens/resolve
{:permissions [:read]
:value :extensions/ethereum-resolve-ens
:arguments {:name :string
:on-success :event
:on-failure? :event}}
'ethereum.erc20/total-supply
{:permissions [:read]
:value :extensions/ethereum-erc20-total-supply
:arguments {:contract :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc20/balance-of
{:permissions [:read]
:value :extensions/ethereum-erc20-balance-of
:arguments {:contract :string
:token-owner :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc20/transfer
{:permissions [:read]
:value :extensions/ethereum-erc20-transfer
:arguments {:contract :string
:to :string
:value :number
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc20/transfer-from
{:permissions [:read]
:value :extensions/ethereum-erc20-transfer-from
@ -581,47 +610,54 @@
:from :string
:to :string
:value :number
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc20/approve
{:permissions [:read]
:value :extensions/ethereum-erc20-approve
:arguments {:contract :string
:spender :string
:value :number
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc20/allowance
{:permissions [:read]
:value :extensions/ethereum-erc20-allowance
:arguments {:contract :string
:token-owner :string
:spender :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc721/owner-of
{:permissions [:read]
:value :extensions/ethereum-erc721-owner-of
:arguments {:contract :string
:token-id :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc721/is-approved-for-all
{:permissions [:read]
:value :extensions/ethereum-erc721-is-approved-for-all
:arguments {:contract :string
:owner :string
:operator :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc721/get-approved
{:permissions [:read]
:value :extensions/ethereum-erc721-get-approved
:arguments {:contract :string
:token-id :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc721/set-approval-for-all
{:permissions [:read]
:value :extensions/ethereum-erc721-set-approval-for-all
:arguments {:contract :string
:operator :string
:approved :boolean
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum.erc721/safe-transfer-from
{:permissions [:read]
:value :extensions/ethereum-erc721-safe-transfer-from
@ -630,7 +666,8 @@
:to :string
:token-id :string
:data? :string
:on-result :event}}
:on-success :event
:on-failure? :event}}
'ethereum/call
{:permissions [:read]
:value :extensions/ethereum-call
@ -638,7 +675,8 @@
:method :string
:params? :vector
:outputs? :vector
:on-result :event}}}
:on-success :event
:on-failure? :event}}}
:hooks {:chat.command commands/command-hook
:wallet.settings settings/hook}})

View File

@ -17,22 +17,19 @@
[status-im.native-module.core :as status]))
(handlers/register-handler-fx
:extensions/wallet-ui-on-result
(fn [cofx [_ on-result id result method]]
:extensions/wallet-ui-on-success
(fn [cofx [_ on-success _ result _]]
(fx/merge cofx
(when on-result
{:dispatch (on-result {:error nil :result result})})
(cond
(= method constants/web3-send-transaction) (navigation/navigate-to-clean :wallet-transaction-sent nil)
(= method constants/web3-personal-sign) (navigation/navigate-back)))))
{:dispatch (on-success {:value result})}
(navigation/navigate-back))))
(handlers/register-handler-fx
:extensions/wallet-ui-on-error
(fn [{db :db} [_ on-result message]]
(when on-result {:dispatch (on-result {:error message :result nil})})))
:extensions/wallet-ui-on-failure
(fn [_ [_ on-failure message]]
(when on-failure {:dispatch (on-failure {:value message})})))
(defn- wrap-with-resolution [db arguments address-keyword f]
"funtction responsible to resolve ens taken from argument
"function responsible to resolve ens taken from argument
and call the specified function with resolved address"
(let [address (get arguments address-keyword)
first-address (if (vector? address) ;; currently we only support one ens for address
@ -46,8 +43,7 @@
(ens/get-addr web3 registry first-address #(f db (assoc arguments address-keyword %))))
(f db arguments))))
;; EXTENSION TRANSACTION -> SEND TRANSACTION
(defn prepare-extension-transaction [params contacts on-result]
(defn prepare-extension-transaction [params contacts on-success on-failure]
(let [{:keys [to value data gas gasPrice nonce]} params
contact (get contacts (hex/normalize-hex to))]
(cond-> {:id "extension-id"
@ -66,15 +62,15 @@
:gas-price (when gasPrice
(money/bignumber gasPrice))
:data data
:on-result [:extensions/wallet-ui-on-result on-result]
:on-error [:extensions/wallet-ui-on-error on-result]}
:on-result [:extensions/wallet-ui-on-success on-success]
:on-error [:extensions/wallet-ui-on-failure on-failure]}
nonce
(assoc :nonce nonce))))
(defn- execute-send-transaction [db {:keys [method params on-result] :as arguments}]
(defn- execute-send-transaction [db {:keys [method params on-success on-failure] :as arguments}]
(let [tx-object (assoc (select-keys arguments [:to :gas :gas-price :value :nonce])
:data (when (and method params) (abi-spec/encode method params)))
transaction (prepare-extension-transaction tx-object (:contacts/contacts db) on-result)]
transaction (prepare-extension-transaction tx-object (:contacts/contacts db) on-success on-failure)]
(models.wallet/open-modal-wallet-for-transaction db transaction tx-object)))
(handlers/register-handler-fx
@ -82,123 +78,151 @@
(fn [{db :db} [_ _ arguments]]
(wrap-with-resolution db arguments :to execute-send-transaction)))
(defn- execute-ethcall [_ {:keys [to method params outputs on-result]}]
(defn- rpc-args [method params]
{:jsonrpc "2.0"
:method method
:params params})
(defn- rpc-dispatch [error result f on-success on-failure]
(when result
(re-frame/dispatch (on-success {:result (f result)})))
(when (and error on-failure)
(re-frame/dispatch (on-failure {:result error}))))
(defn- rpc-handler [o f on-success on-failure]
(let [{:keys [error result]} (types/json->clj o)]
(rpc-dispatch error result f on-success on-failure)))
(defn- rpc-call [method params f {:keys [on-success on-failure]}]
(let [payload (types/clj->json (rpc-args method params))]
(status/call-private-rpc payload #(rpc-handler % f on-success on-failure))))
(defn parse-call-result [o outputs]
(let [result (get (js->clj o) "result")]
(cond
(= "0x" result) nil
(and outputs result)
(abi-spec/decode (string/replace result #"^0x" "") outputs)
:else result)))
(defn- execute-ethcall [_ {:keys [to method params outputs on-success on-failure]}]
(let [tx-object {:to to :data (when method (abi-spec/encode method params))}]
{:browser/call-rpc [{"jsonrpc" "2.0"
"method" "eth_call"
"params" [tx-object "latest"]}
#(let [result-str (when %2
(get (js->clj %2) "result"))
result (cond
(= "0x" result-str) nil
(and outputs result-str)
(abi-spec/decode (string/replace result-str #"0x" "") outputs)
:else result-str)]
(re-frame/dispatch (on-result (merge {:result result} (when %1 {:error %1})))))]}))
{:browser/call-rpc [(rpc-args "eth_call" [tx-object "latest"])
#(rpc-dispatch %1 %2 (fn [o] (parse-call-result o outputs)) on-success on-failure)]}))
(handlers/register-handler-fx
:extensions/ethereum-call
(fn [{db :db} [_ _ {:keys [to] :as arguments}]]
(fn [{db :db} [_ _ arguments]]
(wrap-with-resolution db arguments :to execute-ethcall)))
(handlers/register-handler-fx
:extensions/ethereum-erc20-total-supply
(fn [{db :db} [_ _ {:keys [contract on-result]}]]
(fn [{db :db} [_ _ {:keys [contract on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "totalSupply()"
:outputs ["uint256"]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-ethcall))))
(handlers/register-handler-fx
:extensions/ethereum-erc20-balance-of
(fn [{db :db} [_ _ {:keys [contract token-owner on-result]}]]
(fn [{db :db} [_ _ {:keys [contract token-owner on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "balanceOf(address)"
:params [token-owner]
:outputs ["uint256"]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-ethcall))))
(handlers/register-handler-fx
:extensions/ethereum-erc20-allowance
(fn [{db :db} [_ _ {:keys [contract token-owner spender on-result]}]]
(fn [{db :db} [_ _ {:keys [contract token-owner spender on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "allowance(address,address)"
:params [token-owner spender]
:outputs ["uint256"]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-ethcall))))
(handlers/register-handler-fx
:extensions/ethereum-erc20-transfer
(fn [{db :db} [_ _ {:keys [contract to value on-result]}]]
(fn [{db :db} [_ _ {:keys [contract to value on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "transfer(address,uint256)"
:params [to value]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-send-transaction))))
(handlers/register-handler-fx
:extensions/ethereum-erc20-transfer-from
(fn [{db :db} [_ _ {:keys [contract from to value on-result]}]]
(fn [{db :db} [_ _ {:keys [contract from to value on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "transferFrom(address,address,uint256)"
:params [from to value]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-send-transaction))))
(handlers/register-handler-fx
:extensions/ethereum-erc20-approve
(fn [{db :db} [_ _ {:keys [contract spender value on-result]}]]
(fn [{db :db} [_ _ {:keys [contract spender value on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "approve(address,uint256)"
:params [spender value]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-send-transaction))))
(handlers/register-handler-fx
:extensions/ethereum-erc721-owner-of
(fn [{db :db} [_ _ {:keys [contract token-id on-result]}]]
(fn [{db :db} [_ _ {:keys [contract token-id on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "ownerOf(uint256)"
:params [token-id]
:outputs ["address"]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-ethcall))))
(handlers/register-handler-fx
:extensions/ethereum-erc721-is-approved-for-all
(fn [{db :db} [_ _ {:keys [contract owner operator on-result]}]]
(fn [{db :db} [_ _ {:keys [contract owner operator on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "isApprovedForAll(address,address)"
:params [owner operator]
:outputs ["bool"]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-ethcall))))
(handlers/register-handler-fx
:extensions/ethereum-erc721-get-approved
(fn [{db :db} [_ _ {:keys [contract token-id on-result]}]]
(fn [{db :db} [_ _ {:keys [contract token-id on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "getApproved(uint256)"
:params [token-id]
:outputs ["address"]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-ethcall))))
(handlers/register-handler-fx
:extensions/ethereum-erc721-set-approval-for-all
(fn [{db :db} [_ _ {:keys [contract to approved on-result]}]]
(fn [{db :db} [_ _ {:keys [contract to approved on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method "setApprovalForAll(address,bool)"
:params [to approved]
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-send-transaction))))
(handlers/register-handler-fx
:extensions/ethereum-erc721-safe-transfer-from
(fn [{db :db} [_ _ {:keys [contract from to token-id data on-result]}]]
(fn [{db :db} [_ _ {:keys [contract from to token-id data on-success on-failure]}]]
(let [json-rpc-args {:to contract
:method (if data
"safeTransferFrom(address,address,uint256,bytes)"
@ -206,19 +230,21 @@
:params (if data
[from to token-id data]
[from to token-id])
:on-result on-result}]
:on-success on-success
:on-failure on-failure}]
(wrap-with-resolution db json-rpc-args :to execute-send-transaction))))
(defn- parse-log [{:keys [address transactionHash blockHash transactionIndex topics blockNumber logIndex removed data]}]
{:address address
:transaction-hash transactionHash
:blockHash blockHash
:transaction-index (abi-spec/hex-to-number transactionIndex)
:topics topics ;; TODO parse topics
:block-number (abi-spec/hex-to-number blockNumber)
:log-index (abi-spec/hex-to-number logIndex)
:removed removed
:data data})
(merge {:data data
:topics topics
:address address
:removed removed}
;; TODO parse data and topics, filter useless solidity first topic, aggregate as events ?
(when logIndex {:log-index (abi-spec/hex-to-number logIndex)})
(when transactionIndex {:transaction-index (abi-spec/hex-to-number transactionIndex)})
(when transactionHash {:transaction-hash transactionHash})
(when blockHash {:block-hash blockHash})
(when blockNumber {:block-number (abi-spec/hex-to-number blockNumber)})))
(defn- parse-receipt [m]
(when m
@ -238,16 +264,8 @@
(handlers/register-handler-fx
:extensions/ethereum-transaction-receipt
(fn [_ [_ _ {:keys [value on-result]}]]
(let [args {:jsonrpc "2.0"
:method constants/web3-transaction-receipt
:params [value]}
payload (types/clj->json args)]
(status/call-private-rpc payload #(let [{:keys [error result]} (types/json->clj %1)
response (merge {:result (parse-receipt result)} (when error {:error error}))]
(re-frame/dispatch (on-result response)))))))
;; eth_getLogs implementation
(fn [_ [_ _ {:keys [value] :as m}]]
(rpc-call constants/web3-transaction-receipt [value] parse-receipt m)))
(defn- event-topic-enc [event params]
(let [eventid (str event "(" (string/join "," params) ")")]
@ -264,17 +282,16 @@
:else :bytes))
(defn- values-topic-enc [type values]
(let [mapped-type (types-mapping type)]
(mapv #(str "0x" (abi-spec/enc {:type mapped-type :value %})) values)))
(mapv #(str "0x" (abi-spec/enc {:type (types-mapping type) :value %})) values))
(defn- parse-topic [t]
(defn- generate-topic [t]
(cond
(or (nil? t) (string? t)) t ;; nil topic ;; immediate topic (extension encode topic by its own) ;; vector of immediate topics
(vector? t) (mapv parse-topic t) ;; descend in vector elements
(vector? t) (mapv generate-topic t) ;; descend in vector elements
(map? t) ;; simplified topic interface, we need to encode
(let [{:keys [event params type values]} t]
(cond
(some? event) (event-topic-enc event params);; event params topic
(some? event) (event-topic-enc event params);; event params topic {:event "Transfer" :params ["uint"]}
(some? type) (values-topic-enc type values) ;; indexed values topic
:else nil)) ;; error
:else nil))
@ -285,19 +302,13 @@
(re-matches #"^[0-9]+$" block) (str "0x" (abi-spec/number-to-hex block))
:else block))
(defn- execute-get-logs [_ {:keys [fromBlock toBlock address topics blockhash on-result]}]
(let [parsed-topics (mapv parse-topic topics)
args {:jsonrpc "2.0"
:method constants/web3-get-logs
:params [{:fromBlock (ensure-hex-bn fromBlock)
:toBlock (ensure-hex-bn toBlock)
(defn- execute-get-logs [_ {:keys [from to address topics block-hash] :as m}]
(let [params [{:from (ensure-hex-bn from)
:to (ensure-hex-bn to)
:address address
:topics parsed-topics
:blockhash blockhash}]}
payload (types/clj->json args)]
(status/call-private-rpc payload #(let [{:keys [error result]} (types/json->clj %1)
response (merge {:result result} (when error {:error error}))]
(re-frame/dispatch (on-result response))))))
:topics (generate-topic topics)
:blockhash block-hash}]]
(rpc-call constants/web3-get-logs params #(map parse-log %) m)))
(handlers/register-handler-fx
:extensions/ethereum-logs
@ -306,71 +317,59 @@
(handlers/register-handler-fx
:extensions/ethereum-resolve-ens
(fn [{db :db} [_ _ {:keys [name on-result]}]]
(fn [{db :db} [_ _ {:keys [name on-success on-failure]}]]
(if (ens/is-valid-eth-name? name)
(let [{:keys [web3 network]} db
network-info (get-in db [:account/account :networks network])
chain (ethereum/network->chain-keyword network-info)
registry (get ens/ens-registries chain)]
(ens/get-addr web3 registry name #(re-frame/dispatch (on-result {:result %}))))
(re-frame/dispatch (on-result {:error (str "'" name "' is not a valid name")})))))
(ens/get-addr web3 registry name #(re-frame/dispatch (on-success {:value %}))))
(when on-failure
(re-frame/dispatch (on-failure {:value (str "'" name "' is not a valid name")}))))))
;; EXTENSION SIGN -> SIGN MESSAGE
(handlers/register-handler-fx
:extensions/ethereum-sign
(fn [{db :db :as cofx} [_ _ {:keys [message data id on-result]}]]
(if (= (nil? message) (nil? data))
{:dispatch (on-result {:error "only one of :message and :data can be used"})}
(fn [{db :db :as cofx} [_ _ {:keys [message data id on-success on-failure]}]]
(if (and message data)
(when on-failure
{:dispatch (on-failure {:error "only one of :message and :data can be used"})})
(fx/merge cofx
{:db (assoc-in db [:wallet :send-transaction]
{:id id
:from (ethereum/normalized-address (get-in db [:account/account :address]))
:data (or data (str "0x" (abi-spec/from-utf8 message)))
:on-result [:extensions/wallet-ui-on-result on-result]
:on-error [:extensions/wallet-ui-on-error on-result]
:on-result [:extensions/wallet-ui-on-success on-success]
:on-error [:extensions/wallet-ui-on-failure on-failure]
:method constants/web3-personal-sign})}
(navigation/navigate-to-cofx :wallet-sign-message-modal nil)))))
;; poll logs implementation
(handlers/register-handler-fx
:extensions/ethereum-logs-changes
(fn [_ [_ _ {:keys [filterId on-result]}]]
(let [args {:jsonrpc "2.0"
:method constants/web3-get-filter-changes
:params [filterId]}
payload (types/clj->json args)]
(status/call-private-rpc payload #(let [{:keys [error result]} (types/json->clj %1)
response (merge {:result result} (when error {:error error}))]
(mapv (fn [one-result]
(re-frame/dispatch (on-result one-result))) result))))))
(fn [_ [_ _ {:keys [id] :as m}]]
(rpc-call constants/web3-get-filter-changes [(abi-spec/number-to-hex id)] #(map parse-log %) m)))
(handlers/register-handler-fx
:extensions/ethereum-cancel-filter
(fn [_ [_ _ {:keys [filterId on-result]}]]
(let [args {:jsonrpc "2.0"
:method constants/web3-uninstall-filter
:params [filterId]}
payload (types/clj->json args)]
(status/call-private-rpc payload #(let [{:keys [error result]} (types/json->clj %1)
response (merge {:result result} (when error {:error error}))]
(re-frame/dispatch (on-result response)))))))
(fn [_ [_ _ {:keys [id] :as m}]]
(rpc-call constants/web3-uninstall-filter [(abi-spec/number-to-hex id)] #(abi-spec/hex-to-value % "bool") m)))
(defn create-filter-method [type]
(case type
:filter constants/web3-new-filter
:block constants/web3-new-block-filter
:pending-transaction constants/web3-new-pending-transaction-filter))
(defn create-filter-arguments [type {:keys [from to address block-hash topics]}]
(case type
:filter
[{:fromBlock (ensure-hex-bn from)
:toBlock (ensure-hex-bn to)
:address address
:topics (mapv generate-topic topics)
:blockhash block-hash}]))
(handlers/register-handler-fx
:extensions/ethereum-create-filter
(fn [_ [_ _ {:keys [filter-type from to address topics block-hash on-result]}]]
(let [parsed-topics (mapv parse-topic topics)
args (case filter-type
"filter" {:jsonrpc "2.0"
:method constants/web3-new-filter
:params [{:fromBlock (ensure-hex-bn from)
:toBlock (ensure-hex-bn to)
:address address
:topics parsed-topics
:blockhash block-hash}]}
"block" {:jsonrpc "2.0"
:method constants/web3-new-block-filter}
"pendingTransaction" {:jsonrpc "2.0"
:method constants/web3-new-pending-transaction-filter})
payload (types/clj->json args)]
(status/call-private-rpc payload #(let [{:keys [error result]} (types/json->clj %1)
response (merge {:result result} (when error {:error error}))]
(re-frame/dispatch (on-result response)))))))
(fn [_ [_ _ {:keys [type] :as m}]]
(rpc-call (create-filter-method type) (create-filter-arguments type m) abi-spec/hex-to-number m)))

View File

@ -15,8 +15,9 @@
hooks (get-in account [:extensions extension-id :hooks])]
(apply fx/merge cofx
(mapcat (fn [[_ extension-hooks]]
(map (fn [[hook-id {:keys [hook-ref parsed]}]]
(partial hook-fn (:hook hook-ref) hook-id {:id extension-id} parsed))
(map (fn [[hook-id {parsed :parsed {hook :hook} :hook-ref}]]
(when hook
(partial hook-fn hook hook-id {:id extension-id} parsed)))
extension-hooks))
hooks))))

View File

@ -18,13 +18,12 @@
"Hook for extensions"
{:properties
{:label :string
:view :view
:on-click? :event}
:view :view}
:hook
(reify hooks/Hook
(hook-in [_ id env {:keys [label view on-click]} {:keys [db]}]
{:db (assoc-in db [:wallet :settings id] {:label label :view view :on-click on-click})})
(unhook [_ id env _ {:keys [db]}]
(hook-in [_ id _ {:keys [label view _]} {:keys [db]}]
{:db (assoc-in db [:wallet :settings id] {:label label :view view})})
(unhook [_ id _ _ {:keys [db]}]
{:db (update-in db [:wallet :settings] dissoc id)}))})
(defn- render-token [{:keys [symbol name icon]} visible-tokens]
@ -57,7 +56,8 @@
:render-fn #(render-token % visible-tokens)}]]]))
(defview settings-hook []
(letsubs [{:keys [label view]} [:get-screen-params :wallet-settings-hook]]
(letsubs [{:keys [label view]} [:get-screen-params :wallet-settings-hook]
{address :address} [:account/account]]
[react/view {:style {:flex 1 :background-color colors/white}}
[status-bar/status-bar {:type :modal-wallet}]
[toolbar/toolbar {:style wallet.styles/toolbar}
@ -65,14 +65,11 @@
(re-frame/dispatch [:navigate-back])))]
[toolbar/content-title {:color colors/white}
label]]
[view]]))
[view {:address (ethereum/normalized-address address)}]]))
(defn- setting->action [{:keys [label on-click] :as m}]
(defn- setting->action [{:keys [label] :as m}]
{:label label
:action #(do
(when on-click
(re-frame/dispatch (on-click {})))
(re-frame/dispatch [:navigate-to :wallet-settings-hook m]))})
:action #(re-frame/dispatch [:navigate-to :wallet-settings-hook m])})
(defview toolbar-view []
(letsubs [settings [:wallet/settings]]

View File

@ -22,16 +22,20 @@
(.leftPad utils x (+ len to-pad)))))
(defn to-two-complement [x]
(subs (.toTwosComplement utils x) 2))
(when x
(subs (.toTwosComplement utils x) 2)))
(defn from-utf8 [x]
(subs (.fromUtf8 utils x) 2))
(when x
(subs (.fromUtf8 utils x) 2)))
(defn bytes-to-hex [x]
(subs (.bytesToHex utils x) 2))
(when x
(subs (.bytesToHex utils x) 2)))
(defn number-to-hex [x]
(subs (.numberToHex utils x) 2))
(when x
(subs (.numberToHex utils x) 2)))
(defn hex-to-utf8 [x]
(.hexToUtf8 utils (str "0x" x)))

View File

@ -8,33 +8,33 @@
(testing "topic parsing check - events"
(is (= ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
"0x29f31b934498b0deabbe211b01cc30eee6475abf0f0d553e7eb8ca71deeb24b3"]
(ethereum/parse-topic [{:event "Transfer" :params ["address" "address" "uint256"]}
(ethereum/generate-topic [{:event "Transfer" :params ["address" "address" "uint256"]}
{:event "drawBet" :params ["uint256" "uint8" "int8" "address" "uint256"]}])))))
(deftest test-parse-topic-indexed-values-address
(testing "topic parsing check - indexed values address"
(is (= ["0x000000000000000000000000299b18709d4aacbda99048721448f65893a0c73a"
"0x00000000000000000000000094eaa5fa6b313968b2abd6da375ef28077d95d53"]
(ethereum/parse-topic {:type "address" :values ["0x299b18709d4aacbda99048721448f65893a0c73a" "0x94eaa5fa6b313968b2abd6da375ef28077d95d53"]})))))
(ethereum/generate-topic {:type "address" :values ["0x299b18709d4aacbda99048721448f65893a0c73a" "0x94eaa5fa6b313968b2abd6da375ef28077d95d53"]})))))
(deftest test-parse-topic-indexed-values-uint256
(testing "topic parsing check - indexed values uint256"
(is (= ["0x00000000000000000000000000000000000000000000000000000000000003fd"
"0x0000000000000000000000000000000000000000000000000000000000000078"]
(ethereum/parse-topic {:type "uint256" :values ["0x3fd" "120"]})))))
(ethereum/generate-topic {:type "uint256" :values ["0x3fd" "120"]})))))
(deftest test-parse-topic-indexed-values-direct
(testing "topic parsing check - indexed values direct"
(is (= ["0x00000000000000000000000000000000000000000000000000000000000003fd"
"0x0000000000000000000000000000000000000000000000000000000000000078"]
(ethereum/parse-topic ["0x00000000000000000000000000000000000000000000000000000000000003fd"
(ethereum/generate-topic ["0x00000000000000000000000000000000000000000000000000000000000003fd"
"0x0000000000000000000000000000000000000000000000000000000000000078"])))))
(deftest test-parse-topic-indexed-nil
(testing "topic parsing check - nil"
(is (= ["0x00000000000000000000000000000000000000000000000000000000000003fd"
nil]
(ethereum/parse-topic ["0x00000000000000000000000000000000000000000000000000000000000003fd"
(ethereum/generate-topic ["0x00000000000000000000000000000000000000000000000000000000000003fd"
nil])))))
(deftest test-ensure-hex-bn-nonnumber