Initial commit
This commit is contained in:
commit
86509b1712
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "status-dapp",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"watch": "webpack -d --watch",
|
||||||
|
"build": "webpack -p"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^16.2.0",
|
||||||
|
"react-dom": "^16.2.0",
|
||||||
|
"react-native-web": "^0.3.0-rc.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"webpack": "^3.10.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
(defproject status-dapp "0.1.0-SNAPSHOT"
|
||||||
|
:dependencies [[org.clojure/clojure "1.9.0"]
|
||||||
|
[org.clojure/clojurescript "1.10.191"]
|
||||||
|
[reagent "0.7.0" :exclusions [cljsjs/react cljsjs/react-dom]]
|
||||||
|
[re-frame "0.10.2"]
|
||||||
|
[cljs-web3 "0.19.0-0-9"]
|
||||||
|
[day8.re-frame/http-fx "0.1.5"]]
|
||||||
|
:plugins [[lein-cljsbuild "1.1.7"]]
|
||||||
|
|
||||||
|
:min-lein-version "2.5.3"
|
||||||
|
|
||||||
|
:clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
|
||||||
|
:source-paths ["src/cljs"]
|
||||||
|
:profiles
|
||||||
|
{:dev
|
||||||
|
{:dependencies [[re-frisk "0.5.3"]]
|
||||||
|
:plugins [[lein-figwheel "0.5.15"]]
|
||||||
|
:cljsbuild {:builds {:app {:figwheel {:on-jsload "status-dapp.core/mount-root"}
|
||||||
|
:compiler {:main status-dapp.core
|
||||||
|
:output-dir "resources/public/js/compiled/out"
|
||||||
|
:asset-path "js/compiled/out"}}}}}
|
||||||
|
:prod
|
||||||
|
{:cljsbuild {:builds {:app {:compiler {:optimizations :whitespace
|
||||||
|
:pretty-print false}}}}}}
|
||||||
|
:cljsbuild
|
||||||
|
{:builds
|
||||||
|
{:app {:id "app"
|
||||||
|
:source-paths ["src/cljs"]
|
||||||
|
:compiler {:main status-dapp.core
|
||||||
|
:output-to "resources/public/js/compiled/app.js"
|
||||||
|
:foreign-libs [{:file "resources/public/js/bundle.js"
|
||||||
|
:provides ["cljsjs.react" "cljsjs.react.dom" "webpack.bundle"]}]}}}}
|
||||||
|
|
||||||
|
:aliases {"figwheel-repl" ["with-profile" "dev" "figwheel"]
|
||||||
|
"build-prod" ["do"
|
||||||
|
["clean"]
|
||||||
|
["with-profile" "prod" "cljsbuild" "once"]]})
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<meta content="ie=edge" http-equiv="x-ua-compatible" />
|
||||||
|
<title>DAPP</title>
|
||||||
|
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||||
|
<style>
|
||||||
|
.app, html, body {
|
||||||
|
height:100%;
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
.app {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app" class="app"></div>
|
||||||
|
<script src="js/compiled/app.js"></script>
|
||||||
|
<script>
|
||||||
|
status_dapp.core.init();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,14 @@
|
||||||
|
(ns status-dapp.components
|
||||||
|
(:require [status-dapp.react-native-web :as react]))
|
||||||
|
|
||||||
|
(defn button [label on-press]
|
||||||
|
[react/touchable-highlight {:on-press on-press}
|
||||||
|
[react/view {:style {:flex-direction :row :align-items :center :margin-top 10}}
|
||||||
|
[react/view {:style {:padding 4 :background-color "#4360df" :border-radius 4}}
|
||||||
|
[react/text {:style {:color :white}} label]]]])
|
||||||
|
|
||||||
|
(defn label [label value]
|
||||||
|
[react/view {:style {:flex-direction :row :align-items :center :margin-top 10}}
|
||||||
|
[react/view {:style {:padding 4 :background-color "#4360df99" :border-radius 4}}
|
||||||
|
[react/text {:style {:color :white}} label]]
|
||||||
|
[react/text {:style {:margin-left 10}} value]])
|
|
@ -0,0 +1,4 @@
|
||||||
|
(ns status-dapp.config)
|
||||||
|
|
||||||
|
(def debug?
|
||||||
|
^boolean goog.DEBUG)
|
|
@ -0,0 +1,8 @@
|
||||||
|
(ns status-dapp.constants)
|
||||||
|
|
||||||
|
(def chains
|
||||||
|
{"1" "Mainnet"
|
||||||
|
"3" "Testnet Ropsten"
|
||||||
|
"4" "Testnet Rinkeby"})
|
||||||
|
|
||||||
|
(def stt-ropsten-contract "0x34358C45FbA99ef9b78cB501584E8cBFa6f85Cef")
|
|
@ -0,0 +1,23 @@
|
||||||
|
(ns status-dapp.core
|
||||||
|
(:require [reagent.core :as reagent]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
status-dapp.events
|
||||||
|
status-dapp.subs
|
||||||
|
[status-dapp.views :as views]
|
||||||
|
[status-dapp.config :as config]))
|
||||||
|
|
||||||
|
(defn dev-setup []
|
||||||
|
(when config/debug?
|
||||||
|
(enable-console-print!)
|
||||||
|
(println "dev mode")))
|
||||||
|
|
||||||
|
(defn mount-root []
|
||||||
|
(re-frame/clear-subscription-cache!)
|
||||||
|
(reagent/render [views/main]
|
||||||
|
(.getElementById js/document "app")))
|
||||||
|
|
||||||
|
(defn ^:export init []
|
||||||
|
(re-frame/dispatch-sync [:initialize-db])
|
||||||
|
(re-frame/dispatch [:request-web3-async-data])
|
||||||
|
(dev-setup)
|
||||||
|
(mount-root))
|
|
@ -0,0 +1,6 @@
|
||||||
|
(ns status-dapp.db)
|
||||||
|
|
||||||
|
(def default-db
|
||||||
|
{:web3 (when (exists? js/web3) js/web3)
|
||||||
|
:web3-async-data {}
|
||||||
|
:view-id (if (exists? js/web3) :web3 :no-web3)})
|
|
@ -0,0 +1,106 @@
|
||||||
|
(ns status-dapp.events
|
||||||
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[status-dapp.db :as db]
|
||||||
|
[day8.re-frame.http-fx]))
|
||||||
|
|
||||||
|
(defn set-web3-value [key]
|
||||||
|
(fn [error result]
|
||||||
|
(re-frame/dispatch [:set-in [:web3-async-data key] result])))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:web3-node-fx
|
||||||
|
(fn [web3]
|
||||||
|
(.getNode (.-version web3) (set-web3-value :node))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:web3-network-fx
|
||||||
|
(fn [web3]
|
||||||
|
(.getNetwork (.-version web3) (set-web3-value :network))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:web3-ethereum-fx
|
||||||
|
(fn [web3]
|
||||||
|
(.getEthereum (.-version web3) (set-web3-value :ethereum))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:web3-whisper-fx
|
||||||
|
(fn [web3]
|
||||||
|
(.getWhisper (.-version web3) (set-web3-value :whisper))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:web3-accounts-fx
|
||||||
|
(fn [web3]
|
||||||
|
(.getAccounts (.-eth web3) (set-web3-value :accounts))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:web3-syncyng-fx
|
||||||
|
(fn [web3]
|
||||||
|
(.getSyncing (.-eth web3) (set-web3-value :syncing))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:web3-gas-price-fx
|
||||||
|
(fn [web3]
|
||||||
|
(.getGasPrice (.-eth web3) (set-web3-value :gas-price))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:send-transaction-fx
|
||||||
|
(fn [[web3 data]]
|
||||||
|
(.sendTransaction (.-eth web3) data #())))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
:set
|
||||||
|
(fn [db [_ k v]]
|
||||||
|
(assoc db k v)))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
:set-in
|
||||||
|
(fn [db [_ path v]]
|
||||||
|
(assoc-in db path v)))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
:initialize-db
|
||||||
|
(fn [_ _]
|
||||||
|
db/default-db))
|
||||||
|
|
||||||
|
;; Status web3 doesn't support sync calls
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
:request-web3-async-data
|
||||||
|
(fn [{{:keys [web3] :as db} :db} _]
|
||||||
|
(when web3
|
||||||
|
{:db (update db :web3-async-data
|
||||||
|
assoc
|
||||||
|
:api (.-api (.-version web3))
|
||||||
|
:default-account (.-defaultAccount (.-eth web3))
|
||||||
|
:default-block (.-defaultBlock (.-eth web3)))
|
||||||
|
:web3-node-fx web3
|
||||||
|
:web3-network-fx web3
|
||||||
|
:web3-ethereum-fx web3
|
||||||
|
:web3-whisper-fx web3
|
||||||
|
:web3-accounts-fx web3
|
||||||
|
:web3-syncyng-fx web3
|
||||||
|
:web3-gas-price-fx web3})))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
:send-transaction
|
||||||
|
(fn [{{:keys [web3]} :db} [_ data]]
|
||||||
|
(when web3
|
||||||
|
{:send-transaction-fx [web3 (clj->js data)]})))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
:good-request-ropsten-eth
|
||||||
|
(fn [_ _]
|
||||||
|
(js/alert "Faucet request recieved")))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
:bad-request-ropsten-eth
|
||||||
|
(fn [_ _]
|
||||||
|
(js/alert "Faucet request error")))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
:request-ropsten-eth
|
||||||
|
(fn [_ [_ address]]
|
||||||
|
(js/alert "Requested")
|
||||||
|
{:http-xhrio {:method :get
|
||||||
|
:uri (str "http://51.15.45.169:3001/donate/" address)
|
||||||
|
:on-success [:good-request-ropsten-eth]
|
||||||
|
:on-failure [:bad-request-ropsten-eth]}}))
|
|
@ -0,0 +1,31 @@
|
||||||
|
(ns status-dapp.react-native-web
|
||||||
|
(:require [reagent.core :as reagent]
|
||||||
|
[clojure.string :as string]))
|
||||||
|
|
||||||
|
(defn get-react-property [name]
|
||||||
|
(goog.object/get js/ReactNativeWeb name))
|
||||||
|
|
||||||
|
(defn adapt-class [class]
|
||||||
|
(when class
|
||||||
|
(reagent/adapt-react-class class)))
|
||||||
|
|
||||||
|
(defn get-class [name]
|
||||||
|
(adapt-class (get-react-property name)))
|
||||||
|
|
||||||
|
(def view (get-class "View"))
|
||||||
|
(def text-class (get-class "Text"))
|
||||||
|
(def image (get-class "Image"))
|
||||||
|
(def touchable-highlight (get-class "TouchableOpacity"))
|
||||||
|
(def scroll-view (get-class "ScrollView"))
|
||||||
|
(def text-input (get-class "TextInput"))
|
||||||
|
|
||||||
|
(defn text
|
||||||
|
([t]
|
||||||
|
(reagent/as-element [text-class t]))
|
||||||
|
([{:keys [uppercase?] :as opts} t & ts]
|
||||||
|
(reagent/as-element
|
||||||
|
(let [ts (cond->> (conj ts t)
|
||||||
|
uppercase? (map #(when % (string/upper-case %))))]
|
||||||
|
(vec (concat
|
||||||
|
[text-class opts]
|
||||||
|
ts))))))
|
|
@ -0,0 +1,12 @@
|
||||||
|
(ns status-dapp.subs
|
||||||
|
(:require [re-frame.core :as re-frame]))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:get
|
||||||
|
(fn [db [_ k]]
|
||||||
|
(get db k)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:get-in
|
||||||
|
(fn [db [_ path]]
|
||||||
|
(get-in db path)))
|
|
@ -0,0 +1,68 @@
|
||||||
|
(ns status-dapp.utils
|
||||||
|
(:require [clojure.walk :as w]))
|
||||||
|
|
||||||
|
(defn atom? [sub]
|
||||||
|
(or (vector? sub)
|
||||||
|
(and (seq sub)
|
||||||
|
(#{`reagent.core/atom} (first sub)))))
|
||||||
|
|
||||||
|
(defn walk-sub [sub form->sym]
|
||||||
|
(if (coll? sub)
|
||||||
|
(w/postwalk (fn [f]
|
||||||
|
(or (form->sym f) f)) sub)
|
||||||
|
(or (form->sym sub) sub)))
|
||||||
|
|
||||||
|
(defn prepare-subs [subs]
|
||||||
|
(let [pairs (map (fn [[form sub]]
|
||||||
|
{:form form
|
||||||
|
:sub sub
|
||||||
|
:sym (if (atom? sub)
|
||||||
|
(gensym (str (if (map? form) "keys" form)))
|
||||||
|
form)})
|
||||||
|
(partition 2 subs))
|
||||||
|
form->sym (->> pairs
|
||||||
|
(map (fn [{:keys [form sym]}]
|
||||||
|
[form sym]))
|
||||||
|
(into {}))]
|
||||||
|
[(mapcat (fn [{:keys [form sym sub]}]
|
||||||
|
(if (vector? sub)
|
||||||
|
[sym `(re-frame.core/subscribe ~(walk-sub sub form->sym))]
|
||||||
|
[form (walk-sub sub form->sym)]))
|
||||||
|
pairs)
|
||||||
|
(apply concat (keep (fn [{:keys [sym form sub]}]
|
||||||
|
(when (atom? sub)
|
||||||
|
[form `(deref ~sym)]))
|
||||||
|
pairs))]))
|
||||||
|
|
||||||
|
(defmacro letsubs [args & body])
|
||||||
|
|
||||||
|
(defmacro defview
|
||||||
|
[n params & rest-body]
|
||||||
|
(let [first-symbol (ffirst rest-body)
|
||||||
|
rest-body' (if (and (symbol? first-symbol)
|
||||||
|
(= (name first-symbol) "letsubs"))
|
||||||
|
(rest (first rest-body))
|
||||||
|
rest-body)
|
||||||
|
[subs component-map body] (case (count rest-body')
|
||||||
|
1 [nil {} (first rest-body')]
|
||||||
|
2 [(first rest-body') {} (second rest-body')]
|
||||||
|
3 rest-body')
|
||||||
|
[subs-bindings vars-bindings] (prepare-subs subs)]
|
||||||
|
`(do
|
||||||
|
(when-not (find-ns 're-frame.core)
|
||||||
|
(require 're-frame.core))
|
||||||
|
(defn ~n ~params
|
||||||
|
(let [~@subs-bindings]
|
||||||
|
(reagent.core/create-class
|
||||||
|
(merge ~(->> component-map
|
||||||
|
(map (fn [[k f]]
|
||||||
|
(let [args (gensym "args")]
|
||||||
|
[k `(fn [& ~args]
|
||||||
|
(let [~@vars-bindings]
|
||||||
|
(apply ~f ~args)))])))
|
||||||
|
(into {}))
|
||||||
|
{:display-name (name '~n)
|
||||||
|
:reagent-render
|
||||||
|
(fn ~params
|
||||||
|
(let [~@vars-bindings]
|
||||||
|
~body))})))))))
|
|
@ -0,0 +1,57 @@
|
||||||
|
(ns status-dapp.views
|
||||||
|
(:require-macros [status-dapp.utils :refer [defview letsubs]])
|
||||||
|
(:require [status-dapp.react-native-web :as react]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[status-dapp.components :as ui]
|
||||||
|
[status-dapp.constants :as constants]))
|
||||||
|
|
||||||
|
(defn no-web3 []
|
||||||
|
[react/view {:style {:flex 1 :padding 10 :align-items :center :justify-content :center}}
|
||||||
|
[react/text {:style {:font-weight :bold}}
|
||||||
|
"Can't find web3 library"]])
|
||||||
|
|
||||||
|
(defn send-transaction [from]
|
||||||
|
(re-frame/dispatch [:send-transaction {:from from
|
||||||
|
:to constants/stt-ropsten-contract
|
||||||
|
:value 0
|
||||||
|
:gasPrise 150000}]))
|
||||||
|
|
||||||
|
(defview web3-view []
|
||||||
|
(letsubs [{:keys [api node network ethereum whisper accounts syncing gas-price
|
||||||
|
default-account default-block]}
|
||||||
|
[:get :web3-async-data]]
|
||||||
|
[react/scroll-view {:style {:flex 1}}
|
||||||
|
[react/view {:style {:flex 1 :padding 10}}
|
||||||
|
[react/view {:style {:flex-direction :row}}
|
||||||
|
;[ui/button "Request Ropsten ETH" #(re-frame/dispatch [:request-ropsten-eth (str (first accounts))])]
|
||||||
|
;[react/view {:style {:width 5}}]
|
||||||
|
(when (= "3" network)
|
||||||
|
[ui/button "Request 1000 STT" #(send-transaction (str (first accounts)))])]
|
||||||
|
[react/text {:style {:font-weight :bold :margin-top 20}} "Version"]
|
||||||
|
[ui/label "api" api]
|
||||||
|
[ui/label "node" node]
|
||||||
|
[ui/label "network" (str network " (" (or (constants/chains network) "Unknown") ")")]
|
||||||
|
[ui/label "ethereum" ethereum]
|
||||||
|
[ui/label "whisper" whisper]
|
||||||
|
[react/text {:style {:font-weight :bold :margin-top 20}} "Accounts"]
|
||||||
|
[ui/label "defaultAccount" default-account]
|
||||||
|
[ui/label "accounts" ""]
|
||||||
|
(for [account accounts]
|
||||||
|
[react/text account])
|
||||||
|
[react/text {:style {:font-weight :bold :margin-top 20}} "Eth"]
|
||||||
|
[ui/label "defaultBlock" default-block]
|
||||||
|
(if syncing
|
||||||
|
[react/view
|
||||||
|
[ui/label "isSyncing" "true"]
|
||||||
|
[ui/label "startingBlock" (.-startingBlock syncing)]
|
||||||
|
[ui/label "currentBlock" (.-currentBlock syncing)]
|
||||||
|
[ui/label "highestBlock" (.-highestBlock syncing)]]
|
||||||
|
[ui/label "isSyncing" "false"])
|
||||||
|
(when gas-price
|
||||||
|
[ui/label "gasPrice" (str (.toString gas-price 10) " wei")])]]))
|
||||||
|
|
||||||
|
(defview main []
|
||||||
|
(letsubs [view-id [:get :view-id]]
|
||||||
|
(case view-id
|
||||||
|
:web3 [web3-view]
|
||||||
|
[no-web3])))
|
|
@ -0,0 +1,9 @@
|
||||||
|
window.deps = {
|
||||||
|
'react' : require('react'),
|
||||||
|
'react-dom' : require('react-dom'),
|
||||||
|
'react-native-web' : require('react-native-web'),
|
||||||
|
};
|
||||||
|
|
||||||
|
window.React = window.deps['react'];
|
||||||
|
window.ReactDOM = window.deps['react-dom'];
|
||||||
|
window.ReactNativeWeb = window.deps['react-native-web'];
|
|
@ -0,0 +1,15 @@
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const BUILD_DIR = path.resolve(__dirname, 'resources', 'public', 'js');
|
||||||
|
const APP_DIR = path.resolve(__dirname, 'src', 'js');
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
entry: `${APP_DIR}/main.js`,
|
||||||
|
output: {
|
||||||
|
path: BUILD_DIR,
|
||||||
|
filename: 'bundle.js'
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = config;
|
Loading…
Reference in New Issue