Merge pull request #170 from trybeee/macchiato-example

Fixes: #169 add macchiato example app using cljs-web3
This commit is contained in:
Teemu Patja 2017-11-16 20:35:53 +02:00 committed by GitHub
commit f0f6cc9dcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 550 additions and 0 deletions

21
macchiato-app/Dockerfile Normal file
View File

@ -0,0 +1,21 @@
FROM mhart/alpine-node:latest
MAINTAINER Your Name <you@example.com>
# Create app directory
RUN mkdir -p /macchiato-web3-example
WORKDIR /macchiato-web3-example
# Install app dependencies
COPY package.json /macchiato-web3-example
RUN npm install pm2 -g
RUN npm install
# Bundle app source
COPY target/release/macchiato-web3-example.js /macchiato-web3-example/macchiato-web3-example.js
COPY public /macchiato-web3-example/public
ENV HOST 0.0.0.0
EXPOSE 3000
CMD [ "pm2-docker", "/macchiato-web3-example/macchiato-web3-example.js" ]

14
macchiato-app/README.md Normal file
View File

@ -0,0 +1,14 @@
# macchiato-web3-example
Example app built with Macchiato framework and cljs-web3 library
## Run
1. Start figwheel: `lein build`
2. Run node: `node target/out/macchiato-web3-example.js`
3. Start test rpc: `testrpc -p 8545`
## Available endpoints
* `curl http://localhost:3000/accounts` eth accounts
* `curl http://localhost:3000/balance` eth balance of the first account

View File

@ -0,0 +1,13 @@
(ns ^:figwheel-always macchiato-web3-example.app
(:require
[macchiato-web3-example.core :as core]
[cljs.nodejs :as node]
[mount.core :as mount]))
(mount/in-cljc-mode)
(cljs.nodejs/enable-util-print!)
(.on js/process "uncaughtException" #(js/console.error %))
(set! *main-cli-fn* core/server)

11
macchiato-app/env/dev/user.clj vendored Normal file
View File

@ -0,0 +1,11 @@
(ns user
(:require [figwheel-sidecar.repl-api :as ra]))
(defn start-fw []
(ra/start-figwheel!))
(defn stop-fw []
(ra/stop-figwheel!))
(defn cljs []
(ra/cljs-repl))

View File

@ -0,0 +1,11 @@
(ns macchiato-web3-example.app
(:require
[macchiato-web3-example.core :as core]
[cljs.nodejs]
[mount.core :as mount]))
(mount/in-cljc-mode)
(cljs.nodejs/enable-util-print!)
(set! *main-cli-fn* core/server)

View File

@ -0,0 +1,8 @@
(ns macchiato-web3-example.app
(:require
[doo.runner :refer-macros [doo-tests]]
[macchiato-web3-example.core-test]))
(doo-tests 'macchiato-web3-example.core-test)

227
macchiato-app/package-lock.json generated Normal file
View File

@ -0,0 +1,227 @@
{
"name": "macchiato-web3-example",
"version": "0.1.0-SNAPSHOT",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"bignumber.js": {
"version": "github:debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9"
},
"concat-stream": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz",
"integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=",
"requires": {
"inherits": "2.0.3",
"readable-stream": "2.0.6",
"typedarray": "0.0.6"
}
},
"content-type": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
"integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0="
},
"cookies": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.6.2.tgz",
"integrity": "sha1-asGwUolSCOj8TE9fhqntMbnLXM8=",
"requires": {
"depd": "1.1.1",
"keygrip": "1.0.2"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"crypto-js": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz",
"integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU="
},
"depd": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
},
"etag": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz",
"integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg="
},
"fd-slicer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
"integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
"requires": {
"pend": "1.2.0"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"keygrip": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz",
"integrity": "sha1-rTKXxVcGneqLz+ek+kkbdcXd65E="
},
"lru": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lru/-/lru-3.1.0.tgz",
"integrity": "sha1-6n+4VG2DczOWoTCR12z+tMBoN9U=",
"requires": {
"inherits": "2.0.3"
}
},
"multiparty": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.1.2.tgz",
"integrity": "sha1-VPjslxIFL6Hf2OyXUFbIIw1vI3A=",
"requires": {
"fd-slicer": "1.0.1"
}
},
"options": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
"integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8="
},
"pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
},
"qs": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz",
"integrity": "sha1-9AOyZPI7wBIox0ExtAfxjV6l1EI="
},
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
},
"random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "0.10.31",
"util-deprecate": "1.0.2"
}
},
"scmp": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/scmp/-/scmp-0.0.3.tgz",
"integrity": "sha1-NkjfLXKUZB5/eGc//CloHZutkHM="
},
"simple-encryptor": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-encryptor/-/simple-encryptor-1.1.0.tgz",
"integrity": "sha1-ZTuxkmyPD8K41wOFd8yEYFMmOug=",
"requires": {
"scmp": "0.0.3"
}
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
"source-map-support": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.6.tgz",
"integrity": "sha1-MlUqpktFg5KoXqs7C17mFScWeus=",
"requires": {
"source-map": "0.5.7"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"ultron": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
"integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po="
},
"url": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
"requires": {
"punycode": "1.3.2",
"querystring": "0.2.0"
}
},
"utf8": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz",
"integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"web3": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/web3/-/web3-0.14.0.tgz",
"integrity": "sha1-lxPLGvK/+9SjL+fMkQ2utCdnEVo=",
"requires": {
"bignumber.js": "github:debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9",
"crypto-js": "3.1.8",
"utf8": "2.1.2",
"xmlhttprequest": "1.8.0"
}
},
"ws": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-1.1.1.tgz",
"integrity": "sha1-CC3bbGQehdS7RR8D1S8G6r2x8Bg=",
"requires": {
"options": "0.0.6",
"ultron": "1.0.2"
}
},
"xmlhttprequest": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
"integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw="
}
}
}

View File

@ -0,0 +1,25 @@
{
"private": true,
"name": "macchiato-web3-example",
"description": "FIXME: write this!",
"version": "0.1.0-SNAPSHOT",
"dependencies": {
"random-bytes": "1.0.0",
"multiparty": "4.1.2",
"source-map-support": "0.4.6",
"ws": "1.1.1",
"web3": "0.14.0",
"cookies": "0.6.2",
"etag": "1.7.0",
"lru": "3.1.0",
"qs": "6.3.0",
"content-type": "1.0.2",
"url": "0.11.0",
"simple-encryptor": "1.1.0",
"concat-stream": "1.5.2"
},
"main": "target/out/macchiato-web3-example.js",
"scripts": {
"start": "node target/out/macchiato-web3-example.js"
}
}

87
macchiato-app/project.clj Normal file
View File

@ -0,0 +1,87 @@
(defproject macchiato-web3-example "0.1.0-SNAPSHOT"
:description "FIXME: write this!"
:url "http://example.com/FIXME"
:dependencies [[bidi "2.1.2"]
[com.cemerick/piggieback "0.2.2"]
[com.taoensso/timbre "4.10.0"]
[macchiato/hiccups "0.4.1"]
[macchiato/core "0.2.2"]
[macchiato/env "0.0.6"]
[mount "0.1.11"]
[cljs-web3 "0.19.0-0-7"]
[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.908"]]
:min-lein-version "2.0.0"
:jvm-opts ^:replace ["-Xmx1g" "-server"]
:plugins [[lein-doo "0.1.7"]
[macchiato/lein-npm "0.6.3"]
[lein-figwheel "0.5.13"]
[lein-cljsbuild "1.1.5"]]
:npm {:dependencies [[source-map-support "0.4.6"]
[web3 "0.14.0"]]
:write-package-json true}
:source-paths ["src" "target/classes"]
:clean-targets ["target"]
:target-path "target"
:profiles
{:dev
{:npm {:package {:main "target/out/macchiato-web3-example.js"
:scripts {:start "node target/out/macchiato-web3-example.js"}}}
:dependencies [[figwheel-sidecar "0.5.13"]]
:cljsbuild
{:builds {:dev
{:source-paths ["env/dev" "src"]
:figwheel true
:compiler {:main macchiato-web3-example.app
:output-to "target/out/macchiato-web3-example.js"
:output-dir "target/out"
:target :nodejs
:optimizations :none
:pretty-print true
:source-map true
:source-map-timestamp false}}}}
:figwheel
{:http-server-root "public"
:nrepl-port 7000
:reload-clj-files {:clj false :cljc true}
:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
:source-paths ["env/dev"]
:repl-options {:init-ns user}}
:test
{:cljsbuild
{:builds
{:test
{:source-paths ["env/test" "src" "test"]
:compiler {:main macchiato-web3-example.app
:output-to "target/test/macchiato-web3-example.js"
:target :nodejs
:optimizations :none
:pretty-print true
:source-map true}}}}
:doo {:build "test"}}
:release
{:npm {:package {:main "target/release/macchiato-web3-example.js"
:scripts {:start "node target/release/macchiato-web3-example.js"}}}
:cljsbuild
{:builds
{:release
{:source-paths ["env/prod" "src"]
:compiler {:main macchiato-web3-example.app
:output-to "target/release/macchiato-web3-example.js"
:language-in :ecmascript5
:target :nodejs
:optimizations :simple
:pretty-print false}}}}}}
:aliases
{"build" ["do"
["clean"]
["npm" "install"]
["figwheel" "dev"]]
"package" ["do"
["clean"]
["npm" "install"]
["with-profile" "release" "npm" "init" "-y"]
["with-profile" "release" "cljsbuild" "once"]]
"test" ["do"
["npm" "install"]
["with-profile" "test" "doo" "node"]]})

View File

@ -0,0 +1,34 @@
.body-container {
font-family: 'Helvetica Neue', Verdana, Helvetica, Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding-top: 72px;
-webkit-font-smoothing: antialiased;
font-size: 1.125em;
color: #333;
line-height: 1.5em;
}
h1, h2, h3 {
color: #000;
}
h1 {
font-size: 2.5em
}
h2 {
font-size: 2em
}
h3 {
font-size: 1.5em
}
a {
text-decoration: none;
color: #09f;
}
a:hover {
text-decoration: underline;
}

View File

@ -0,0 +1,6 @@
(ns macchiato-web3-example.config
(:require [macchiato.env :as config]
[mount.core :refer [defstate]]))
(defstate env :start (config/env))

View File

@ -0,0 +1,19 @@
(ns macchiato-web3-example.core
(:require
[macchiato-web3-example.config :refer [env]]
[macchiato-web3-example.middleware :refer [wrap-defaults]]
[macchiato-web3-example.routes :refer [router]]
[macchiato.server :as http]
[macchiato.middleware.session.memory :as mem]
[mount.core :as mount :refer [defstate]]
[taoensso.timbre :refer-macros [log trace debug info warn error fatal]]))
(defn server []
(mount/start)
(let [host (or (:host @env) "127.0.0.1")
port (or (some-> @env :port js/parseInt) 3000)]
(http/start
{:handler (wrap-defaults router)
:host host
:port port
:on-success #(info "macchiato-web3-example started on" host ":" port)})))

View File

@ -0,0 +1,8 @@
(ns macchiato-web3-example.middleware
(:require
[macchiato.middleware.defaults :as defaults]))
(defn wrap-defaults [handler]
(defaults/wrap-defaults handler defaults/site-defaults))

View File

@ -0,0 +1,56 @@
(ns macchiato-web3-example.routes
(:require
[bidi.bidi :as bidi]
[macchiato.util.response :as r]
[cljs.nodejs :as node]
[cljs-web3.core :as web3]
[cljs-web3.eth :as web3-eth])
(:require-macros
[hiccups.core :refer [html]]))
;; (enable-console-print!)
(def Web3 (node/require "web3"))
(def web3 (web3/create-web3 Web3 "http://localhost:8545/"))
(defn- clj->json [m]
(->> m
clj->js
(.stringify js/JSON)))
(defn- eth-accounts []
(web3-eth/accounts web3))
(defn- account-balance [address]
(web3/from-wei Web3
(web3-eth/get-balance web3 address)
:ether))
(defn- accounts [req res raise]
(-> {:accounts (eth-accounts)}
clj->json
(r/ok)
(r/content-type "application/json")
(res)))
(defn- balance [req res raise]
(-> {:balance
{:eth (-> (eth-accounts) first account-balance)}}
clj->json
(r/ok)
(r/content-type "application/json")
(res)))
(defn not-found [req res raise]
(-> (r/not-found)
(r/content-type "application/json")
(res)))
(def routes
["/" {"accounts" accounts
"balance" balance}])
(defn router [req res raise]
(if-let [{:keys [handler route-params]} (bidi/match-route* routes (:uri req) req)]
(handler (assoc req :route-params route-params) res raise)
(not-found req res raise)))

View File

@ -0,0 +1 @@
java.runtime.version=1.8

View File

@ -0,0 +1,9 @@
(ns macchiato-web3-example.core-test
(:require
[cljs.test :refer-macros [is are deftest testing use-fixtures]]
[macchiato-web3-example.core]))
(deftest test-core
(is (= true true)))