Skip to content

Instantly share code, notes, and snippets.

@schnogz
Last active March 1, 2017 04:02
Show Gist options
  • Save schnogz/adf271f89de85e0202d576d41b319305 to your computer and use it in GitHub Desktop.
Save schnogz/adf271f89de85e0202d576d41b319305 to your computer and use it in GitHub Desktop.
RazPi-Electron-Snippets
{
"directory": "public/bower_modules/"
}
// dependencies
const request = require('request');
const btc = require('blockchain.info/exchange');
const stats = require('blockchain.info/statistics');
const apiCode = require('./apiCode');
module.exports = {
// fetches current BTC price across multiple exchanges
// using X-testing header allows for 100 requests per 24 hours
getExchangePrices: (req, res) => {
request({
url: 'https://apiv2.bitcoinaverage.com/exchanges/all',
headers: { 'X-testing': 'testing' }
}, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.send(JSON.parse(body));
} else {
res.send(response);
}
});
},
// fetches historical BTC with given timespan
// example timespan's ==> '14d' (14 days), '90d' (90 days), '1y' (1 year), 'all' (all time)
// example request ==> https://api.blockchain.info/charts/market-price?timespan=1y
getHistoricalPriceChart: (req, res) => {
stats.getChartData('market-price', { timespan: req.query.timespan, apiCode: apiCode ? apiCode : null })
.then((resp) => {
res.send(resp);
})
}
}
app/
├── package.json
├── bower.json
├── .bowerrc
├── main.js
├── server.js
├── /controllers
└── api.js
└── apiCode.js
└── /public
├── /css
├── /js
└── index.js
(function(){
'use strict';
angular
.module('app', ['ngMaterial','ngAnimate','ui.router','md.data.table','app.markets','app.blocks','app.network'])
.config(['$stateProvider', '$urlRouterProvider', '$mdThemingProvider',
function config($stateProvider, $urlRouterProvider, $mdThemingProvider) {
// configure app states
$stateProvider.state({
name: 'markets',
url: '/markets',
controller: 'marketsCtrl',
templateUrl: 'js/markets/markets.html'
});
// when there is an empty route, redirect to /markets
$urlRouterProvider.when('', '/markets');
// configure theme
$mdThemingProvider.theme('default')
.primaryPalette('teal')
.accentPalette('red');
}
]);
})();
"name": "app",
"version": "0.0.1",
"dependencies": {
"angular": "1.5.10",
"angular-animate": "1.5.10",
"angular-aria": "1.5.10",
"angular-material": "1.1.1",
"angular-ui-router": "1.0.0-rc.1",
"amcharts3": "3.20.20",
"lodash": "^4.17.4"
},
"resolutions": {
"angular": "1.5.10"
}
}
<!DOCTYPE html>
<html>
<head>
<title>Bitcoin Stats</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
<link rel="stylesheet" href="bower_modules/angular-material/angular-material.css">
<link rel="stylesheet" href="bower_modules/angular-material-data-table/dist/md-data-table.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="css/main.css">
<!-- client side libraries -->
<script type="text/javascript" src="bower_modules/lodash/lodash.js"></script>
<script type="text/javascript" src="bower_modules/moment/min/moment.min.js"></script>
<script type="text/javascript" src="bower_modules/socket.io-client/dist/socket.io.slim.js"></script>
<script type="text/javascript" src="bower_modules/amcharts3/amcharts/amcharts.js"></script>
<script type="text/javascript" src="bower_modules/amcharts3/amcharts/serial.js"></script>
<script type="text/javascript" src="bower_modules/angular/angular.js"></script>
<script type="text/javascript" src="bower_modules/angular-animate/angular-animate.js"></script>
<script type="text/javascript" src="bower_modules/angular-aria/angular-aria.js"></script>
<script type="text/javascript" src="bower_modules/angular-material/angular-material.js"></script>
<script type="text/javascript" src="bower_modules/angular-ui-router/release/angular-ui-router.js"></script>
<script type="text/javascript" src="bower_modules/angular-material-data-table/dist/md-data-table.js"></script>
</head>
<!-- init angular app -->
<body ng-app="app" layout="row">
<!-- sidenav -->
<md-sidenav
ng-include
src="'js/layout/sidenav.html'"
ng-controller="sidenavCtrl"
layout="column"
class="md-sidenav-left md-whiteframe-z2"
md-is-locked-open="true">
</md-sidenav>
<div layout="row" class="relative" layout-fill role="main">
<md-content layout="column" flex md-scroll-y>
<md-card flex>
<md-card-content flex ui-view>
<!-- page content loads here -->
</md-card-content>
</md-card>
</md-content>
</div>
<!-- app source -->
<script src="js/app.js"></script>
<script src="js/layout/sidenav.controller.js"></script>
<script src="js/markets/markets.controller.js"></script>
</body>
</html>
const {app, BrowserWindow} = require('electron');
// keep reference to window object otherwise it will be
// closed automatically when the JS object is garbage collected.
let win;
function createWindow () {
// start express server
app.server = require(__dirname + '/server.js')();
// create the broweser window
win = new BrowserWindow({width: 1200, height: 1000});
// load our app (index.html)
win.loadURL('http://localhost:3000');
// auto open the dev tools for easy debugging
win.webContents.openDevTools();
// event handler for closing the app
win.on('closed', () => {
win = null
})
}
// create window when Electron is ready
app.on('ready', createWindow);
// quit when all windows are closed.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
});
// fix for macOS, as it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
app.on('activate', () => {
if (win === null) {
createWindow()
}
});
angular.module('app.markets', []).controller('marketsCtrl', function ($scope, $http) {
$scope.isLoading = true;
$scope.timePeriod = '30d';
// watch for user changes to timePeriod dropdown
$scope.$watch('timePeriod', function (newVal) {
$scope.isLoading = true;
$http.get('/priceChart?timespan=' + newVal)
.then(function(resp) {
// convert unix timestamps to JS date objects
_.each(resp.data, function(point) {
point.x = AmCharts.formatDate(new Date(parseInt(point.x) * 1000), "M/D/YY");
});
_buildChart(resp.data);
$scope.isLoading = false;
});
});
function _buildChart(chartData) {
// configuration for AmChart
AmCharts.makeChart("priceChart", {
type: "serial",
categoryField: "x", // date
dataDateFormat: "MM/DD/YY",
startDuration: 1,
handDrawScatter: 1,
precision: 2,
processCount: 1005,
theme: "default",
categoryAxis: { gridPosition: "start" },
chartCursor: {
limitToGraph: "priceChart",
enabled: true
},
chartScrollbar: { enabled: true },
graphs: [{
balloonText: "$[[value]]",
valueField: "y" // price
}],
guides: [],
valueAxes: [{
title: "Price",
unit: '$',
unitPosition: 'left'
}],
balloon: {},
titles: [{
size: 18,
color: 'rgb(0,105,92)',
text: "Average Market Price (USD)"
}],
dataProvider: chartData
});
}
});
<div ng-show="isLoading" flex layout="row" layout-align="space-around center">
<md-progress-circular md-mode="indeterminate"></md-progress-circular>
</div>
<div ng-hide="isLoading" layout="row" layout-align="end" id="timePeriodSelect">
<md-select ng-model="timePeriod" placeholder="Time Period" class="md-no-underline">
<md-option value="30d">1 Month</md-option>
<md-option value="90d">3 Month</md-option>
<md-option value="180d">6 Month</md-option>
<md-option value="1year">1 Year</md-option>
<md-option value="4year">All</md-option>
</md-select>
</div>
<div ng-hide="isLoading" id="priceChart"></div>
{
"name" : "app",
"version" : "0.1.0",
"main": "main.js",
"scripts": {
"start": "electron main.js "
},
"dependencies": {
"blockchain.info": "2.6.0",
"body-parser": "1.16.0",
"bower": "^1.8.0",
"chalk": "1.1.3",
"electron-prebuilt": "1.4.13",
"errorhandler": "1.5.0",
"express": "4.14.1",
"express-status-monitor": "0.1.9",
"morgan": "1.7.0"
}
}
module.exports = () => {
// dependencies
const bodyParser = require('body-parser');
const chalk = require('chalk');
const errorHandler = require('errorhandler');
const express = require('express');
const expressStatusMonitor = require('express-status-monitor');
const logger = require('morgan');
const path = require('path');
const apiController = require('./controllers/api');
const app = express();
// set app port
app.set('port', 3000);
// configure middleware
app.use(expressStatusMonitor());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// serve all files in the /public folder
app.use(express.static(path.join(__dirname, 'public')));
// configure app endpoints
app.get('/currentPrice', apiController.getCurrentPrice);
app.get('/priceChart', apiController.getHistoricalPriceChart);
// error handler
app.use(errorHandler());
// start express
app.listen(app.get('port'), () => {
console.log('%s App is running at http://localhost:%d in %s mode',
chalk.green('✓'), app.get('port'), app.get('env'));
console.log(' Press CTRL-C to stop\n');
});
};
angular.module('app').controller('sidenavCtrl', function ($scope, $http, $interval) {
$scope.menu = [{
state: 'markets',
title: 'Markets',
icon: 'timeline'
}];
$scope.getExchangePrices = function() {
$http.get('/exchangePrices')
.then(function(response) {
// pull only the exchanges we care about and sort by name
$scope.exchanges = _.sortBy(_.filter(response.data, function(e) {
return e.name === 'bitstamp' || e.name === 'bitfinex' || e.name === 'gdax' || e.name === 'gemini';
}), function(exchanges) {
return exchanges.name
});
// format last updated timestamp
$scope.lastUpdated = window.moment().format('h:mm A');
});
};
// update prices every 20 minutes
$interval(function() {
$scope.getExchangePrices();
}, 200000);
// immediately fetch exchange prices
$scope.getExchangePrices();
});
<md-toolbar class="md-hue-2" layout-align="center center" layout-padding>
Bitcoin Statistics
</md-toolbar>
<ul class="sidenav">
<li ng-repeat="item in menu">
<md-button ui-sref="{{item.state}}" ui-sref-active="activeNav">
<md-icon>{{item.icon}}</md-icon>
<span>{{item.title}}</span>
</md-button>
</li>
</ul>
<span flex></span>
<md-table-container>
<table md-table id="sidebarTable">
<thead md-head>
<tr md-row>
<th md-column>Exchange</th>
<th md-column md-numeric>Price</th>
<th md-column md-numeric>Volume</th>
</tr>
</thead>
<tbody md-body>
<tr md-row ng-repeat="stats in exchanges">
<td md-cell>{{stats.display_name}}</td>
<td ng-class="{
'priceUp': stats.symbols.BTCUSD.last < stats.symbols.BTCUSD.ask,
'priceDown': stats.symbols.BTCUSD.last > stats.symbols.BTCUSD.ask }" md-cell>
<span ng-if="stats.symbols">${{stats.symbols.BTCUSD.last}}</span>
<span ng-if="!stats.symbols">N/A</span>
</td>
<td md-cell>
<span ng-if="stats.symbols">{{stats.symbols.BTCUSD.volume}}</span>
<span ng-if="!stats.symbols">N/A</span>
</tr>
</tbody>
</table>
</md-table-container>
<div id="lastUpdated" layout="row" layout-align="space-around center">
<div>
Last Updated: {{lastUpdated}}
</div>
<md-button class="md-icon-button" aria-label="Refresh" ng-click="getBtcPrice()">
<md-icon>refresh</md-icon>
</md-button>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment