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"} com.taoensso/timbre {:mvn/version "4.10.0"}
hickory {:mvn/version "0.7.1"} hickory {:mvn/version "0.7.1"}
com.cognitect/transit-cljs {:mvn/version "0.8.248"} 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"} mvxcvi/alphabase {:mvn/version "1.0.0"}
rasom/cljs-react-navigation {:mvn/version "0.1.4"}} rasom/cljs-react-navigation {:mvn/version "0.1.4"}}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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