This commit is contained in:
michaelr 2016-03-03 22:16:19 +02:00
parent d1f00320a1
commit 14df49232b
6 changed files with 223 additions and 75 deletions

View File

@ -1,5 +1,6 @@
(ns cljs-tests.core
(:require [cljs-tests.whisper-protocol :as p]))
(:require [cljs-tests.protocol.api :as p]
[cljs-tests.utils.logging :as log]))
(enable-console-print!)
@ -10,20 +11,34 @@
)
(comment
(p/init-protocol {:ethereum-rpc-url "http://localhost:4546"
:handler (fn [{:keys [event-type] :as event}]
(log/info "Event:" (clj->js event)))})
(p/send-user-msg {:to "0x04a877ae4dcd6005c8f4a576f8c11df56889f5252360cbf7e274bfcfc13f4028f10a3e29ebbb4af12c751d989fbaba09c570a78bc2c5e55773f0ee8579355a1358"
:content "Hello World!"})
(p/my-identity)
)
(comment
;;;;;;;;;;;; CHAT USER 1
(def web3 (p/make-web3 "http://localhost:8545"))
(def user1-ident (p/new-identity web3))
(def listener (p/whisper-listen web3 (fn [err]
(println "Whisper listener caught an error: " (js->clj err)))))
(def web3-2 (p/make-web3 "http://localhost:8546"))
(def user2-ident (p/new-identity web3-2))
(p/send-message web3-2 user2-ident user1-ident "Hello World!")
;(def web3 (p/make-web3 "http://localhost:4546"))
;(def user1-ident (p/new-identity web3))
;(def listener (p/whisper-listen web3 (fn [err]
; (println "Whisper listener caught an error: " (js->clj err)))))
;
;
;(def web3-2 (p/make-web3 "http://localhost:4547"))
;(def user2-ident (p/new-identity web3-2))
;(p/make-whisper-msg web3-2 user2-ident user1-ident "Hello World!")
)

View File

@ -0,0 +1,48 @@
(ns cljs-tests.protocol.api
(:require [cljs-tests.protocol.state :as state]
[cljs-tests.protocol.whisper :as whisper]))
(def default-content-type "text/plain")
(defn create-connection [ethereum-rpc-url]
(whisper/make-web3 ethereum-rpc-url))
(defn create-identity [connection]
(whisper/new-identity connection))
(defn init-protocol
"Required [handler ethereum-rpc-url]
Optional [whisper-identity] - if not passed a new identity is created automatically
(fn handler [{:keys [event-type...}])
:event-type can be:
:new-msg - [from payload]
:error - [error-msg]
:msg-acked [msg-id]
"
[{:keys [handler ethereum-rpc-url identity]}]
(state/set-handler handler)
(let [connection (create-connection ethereum-rpc-url)
identity (or identity
(create-identity connection))]
(state/set-connection connection)
(state/set-identity identity)
(whisper/listen connection)
{:identity identity}))
(defn send-user-msg [{:keys [to content]}]
(let [[msg-id msg] (whisper/make-msg {:from (state/my-identity)
:to to
:payload {:content content
:content-type default-content-type
:type :user-msg}})]
(state/add-pending-message msg-id msg)
(whisper/post-msg (state/connection) msg)))
(defn my-identity []
(state/my-identity))
(defn current-connection []
(state/connection))

View File

@ -0,0 +1,34 @@
(ns cljs-tests.protocol.state)
(def state (atom {:pending-messages {}
:filters {}
:handler nil
:identity nil
:connection nil}))
(defn add-pending-message [msg-id msg]
(swap! state assoc-in [:pending-messages msg-id] msg))
(defn add-filter [topics filter]
(swap! state assoc-in [:filters topics] filter))
(defn remove-pending-message [msg-id]
(swap! state update-in [:pending-messages] dissoc msg-id))
(defn set-handler [handler]
(swap! state assoc :handler handler))
(defn set-identity [identity]
(swap! state assoc :identity identity))
(defn set-connection [connection]
(swap! state assoc :connection connection))
(defn connection []
(:connection @state))
(defn my-identity []
(:identity @state))
(defn handler []
(:handler @state))

View File

@ -0,0 +1,104 @@
(ns cljs-tests.protocol.whisper
(:require [cljsjs.web3]
[cljsjs.chance]
[cljs-tests.utils.logging :as log]
[cljs-tests.protocol.state :as state]
[cljs.reader :refer [read-string]]))
(def syng-app-topic "SYNG-APP-CHAT-TOPIC")
(def syng-msg-ttl 100)
(defn from-ascii [s]
(.fromAscii js/Web3.prototype s))
(defn whisper [web3]
(.-shh web3))
(defn make-topics [topics]
(->> {:topics (mapv from-ascii topics)}
(clj->js)))
(defn make-web3 [rpc-url]
(->> (js/Web3.providers.HttpProvider. rpc-url)
(js/Web3.)))
(defn new-identity [web3]
(.newIdentity (.-shh web3)))
(defn invoke-handler [event-type params]
((state/handler) (assoc params :event-type event-type)))
(defn handle-ack [msg-id]
(log/info "Got ack for message:" msg-id)
(state/remove-pending-message msg-id)
(invoke-handler :msg-acked {:msg-id msg-id}))
(defn post-msg [web3 msg]
(let [js-msg (clj->js msg)]
(log/info "Sending whisper message:" js-msg)
(-> (whisper web3)
(.post js-msg))))
(defn make-msg
"Returns [msg-id msg], `msg` is formed for Web3.shh.post()"
[{:keys [from to ttl topics payload]
:or {ttl syng-msg-ttl
topics []}}]
(let [msg-id (.guid js/chance)]
[msg-id (cond-> {:ttl ttl
:topics (->> (conj topics syng-app-topic)
(mapv from-ascii))
:payload (->> (merge payload {:msg-id msg-id})
(str)
(from-ascii))}
from (assoc :from from)
to (assoc :to to))]))
(defn send-ack [web3 to msg-id]
(log/info "Acking message:" msg-id "To:" to)
(->> (make-msg {:from (state/my-identity)
:to to
:payload {:type :ack
:msg-id msg-id}})
(post-msg web3)))
(defn handle-user-msg [web3 from {:keys [msg-id] :as payload}]
(send-ack web3 from msg-id)
(invoke-handler :new-msg {:from from
:payload payload}))
(defn handle-arriving-whisper-msg [web3 msg]
(log/info "Got whisper message:" msg)
(let [{from :from
to :to
topics :topics ;; always empty (bug in go-ethereum?)
payload :payload
:as msg} (js->clj msg :keywordize-keys true)]
(if (= to (state/my-identity))
(let [{msg-type :type
msg-id :msg-id
:as payload} (->> (from-ascii payload)
(read-string))]
(case msg-type
:ack (handle-ack msg-id)
:user-msg (handle-user-msg web3 from payload)))
(log/warn "My identity:" (state/my-identity) "Message To:" to "Message is encrypted for someone else, ignoring"))))
(defn listen
"Returns a filter which can be stopped with (stop-whisper-listener)"
[web3]
(let [topics [syng-app-topic]
shh (whisper web3)
filter (.filter shh (make-topics topics))
watch (.watch filter (fn [error msg]
(if error
(invoke-handler :error {:error-msg error})
(handle-arriving-whisper-msg web3 msg))))]
(state/add-filter topics filter)))
(defn stop-listener [filter]
(.stopWatching filter))

View File

@ -0,0 +1,11 @@
(ns cljs-tests.utils.logging)
(defn info [& args]
(.apply (.-log js/console) js/console (into-array args)))
(defn warn [& args]
(.apply (.-warn js/console) js/console (into-array args)))
(defn error [& args]
(.apply (.-error js/console) js/console (into-array args)))

View File

@ -1,64 +0,0 @@
(ns cljs-tests.whisper-protocol
(:require [cljsjs.web3]
[cljsjs.chance]))
(def pending-messages (atom {}))
(def syng-app-topic "SYNG-APP-CHAT-TOPIC")
(def syng-msg-ttl 100)
(def default-content-type "text/plain")
(defn from-ascii [s]
(.fromAscii js/Web3.prototype s))
(defn whisper [web3]
(.-shh web3))
(defn make-web3 [rpc-url]
(->> (js/Web3.providers.HttpProvider. rpc-url)
(js/Web3.)))
(defn make-topics [topics]
(->> {:topics (mapv from-ascii topics)}
(clj->js)))
(defn new-identity [web3]
(.newIdentity (.-shh web3)))
(defn whisper-listen
"Returns a filter which can be used with (stop-whisper-listener)"
[web3 on-error]
(let [shh (whisper web3)
filter (.filter shh (make-topics [syng-app-topic]))
watch (.watch filter (fn [error result]
(if error
(on-error error)
(println "got whisper msg:" (js->clj result)))))]
filter))
(defn stop-whisper-listener [filter]
(.stopWatching filter))
(defn send-message
([web3 from to content]
(let [msg-id (.guid js/chance)
msg (cond-> {:ttl syng-msg-ttl
:topics [(from-ascii syng-app-topic)]
:payload (from-ascii content)
;(->> (str {:msg-id msg-id
; :msg-num 122
; :type :user-message
; :content encoded-msg
; :content-type default-content-type})
; (from-ascii))
:from from}
to (assoc :to to))]
(println "sending:" msg)
(.log js/console (clj->js msg))
(swap! pending-messages assoc msg-id msg)
(.post (.-shh web3)
(clj->js
(dissoc msg :from :to)))
))
([web3 from content]
(send-message web3 from nil content)))