aboutsummaryrefslogtreecommitdiffstats
path: root/public/js
diff options
context:
space:
mode:
Diffstat (limited to 'public/js')
-rw-r--r--public/js/calculator.coffee2
-rw-r--r--public/js/calculator.js231
-rw-r--r--public/js/deposit.js102
-rw-r--r--public/js/index.js51
-rw-r--r--public/js/register.js6
-rw-r--r--public/js/report.js63
-rw-r--r--public/js/setup.coffee5
-rw-r--r--public/js/setup.js72
8 files changed, 530 insertions, 2 deletions
diff --git a/public/js/calculator.coffee b/public/js/calculator.coffee
index 99560e86..039ffd73 100644
--- a/public/js/calculator.coffee
+++ b/public/js/calculator.coffee
@@ -80,7 +80,7 @@ setup = ->
$('#logo').click -> $(location).attr("href","/#{g.user}/edit")
address = g.address
if g.user? and g.user
- address = "<a href='/#{g.user}/report'>#{address}</a>"
+ address = "<a href='http://blockchain.info/address/#{address}'>#{address}</a>"
if check_address(g.address)
$('#address').html(address)
diff --git a/public/js/calculator.js b/public/js/calculator.js
new file mode 100644
index 00000000..88fcbd22
--- /dev/null
+++ b/public/js/calculator.js
@@ -0,0 +1,231 @@
+(function() {
+ var ADDRESS_FAIL, EXCHANGE_FAIL, SOCKET_FAIL, activateTip, clear, fail, fetchExchangeRate, finalize, g, get, setup, setupSocket, tip, updateTotal;
+
+ EXCHANGE_FAIL = "Error fetching exchange rate";
+
+ SOCKET_FAIL = "Error connecting to payment server";
+
+ ADDRESS_FAIL = "Invalid address";
+
+ tip = 1;
+
+ g = typeof exports !== "undefined" && exports !== null ? exports : this;
+
+ $(function() {
+ g.user = $('#user').val();
+ g.title = get('title');
+ g.address = get('address');
+ g.symbol = get('symbol');
+ g.currency = get('currency');
+ g.commission = parseFloat(get('commission'));
+ g.logo = get('logo');
+ g.errors = [];
+ g.receivable = 0;
+ if (g.user) {
+ $.ajax({
+ url: g.user + '.json',
+ dataType: 'json',
+ success: function(data) {
+ if (data != null) {
+ g.title = data.title;
+ g.address = data.address;
+ g.currency = data.currency;
+ g.symbol = data.symbol;
+ g.commission = data.commission;
+ g.logo = data.logo;
+ }
+ return setup();
+ }
+ });
+ } else {
+ setup();
+ }
+ $('#tip button').click(function() {
+ var value;
+ value = $(this).html().slice(0, -1);
+ $(this).siblings().css('font-weight', 'normal').removeClass('active');
+ $(this).css('font-weight', 'bold');
+ tip = 1 + (parseFloat(value) / 100);
+ return updateTotal();
+ });
+ $('#tip button').first().click();
+ $('#amount').keyup(updateTotal);
+ return $('#amount').focus(function() {
+ $('#received').hide();
+ $('#payment').fadeIn('slow');
+ $(this).val('');
+ return updateTotal();
+ });
+ });
+
+ activateTip = function(p) {};
+
+ setup = function() {
+ var address;
+ g.address || (g.address = '');
+ g.commission || (g.commission = 0);
+ g.symbol || (g.symbol = 'quadrigacx');
+ if (g.title) {
+ $('#title').html(g.title).show();
+ }
+ if (g.logo) {
+ $('#logo').attr('src', g.logo).show();
+ } else if (!g.title) {
+ $('#logo').attr('src', 'img/bitcoin.png').show();
+ }
+ $('#logo').click(function() {
+ return $(location).attr("href", "/" + g.user + "/edit");
+ });
+ address = g.address;
+ if ((g.user != null) && g.user) {
+ address = "<a href='http://blockchain.info/address/" + address + "'>" + address + "</a>";
+ }
+ if (check_address(g.address)) {
+ $('#address').html(address);
+ } else {
+ fail(ADDRESS_FAIL);
+ }
+ $('#symbol').html(g.symbol + " bid");
+ $('#currency').html(g.currency);
+ $('#received').hide();
+ return fetchExchangeRate();
+ };
+
+ fetchExchangeRate = function() {
+ $.ajax({
+ url: "ticker?currency=" + g.currency + "&symbol=" + g.symbol + "&type=bid",
+ success: function(exchange) {
+ if (exchange != null) {
+ clear(EXCHANGE_FAIL);
+ } else {
+ fail(EXCHANGE_FAIL);
+ return;
+ }
+ if (!g.setupComplete) {
+ finalize();
+ }
+ g.exchange = exchange - exchange * g.commission * 0.01;
+ $('#exchange').val(g.exchange.toFixed(2));
+ return updateTotal();
+ },
+ error: function() {
+ return fail(EXCHANGE_FAIL);
+ }
+ });
+ return setTimeout(fetchExchangeRate, 900000);
+ };
+
+ finalize = function() {
+ $('#amount').focus();
+ return g.setupComplete = true;
+ };
+
+ setupSocket = function() {
+ setTimeout(setupSocket, 10000);
+ if (!(g.websocket && g.websocket.readyState === 1)) {
+ g.websocket = new WebSocket("wss://ws.blockchain.info/inv");
+ g.websocket.onopen = function() {
+ return g.websocket.send('{"op":"addr_sub", "addr":"' + g.address + '"}');
+ };
+ g.websocket.onerror = function() {
+ g.websocket = null;
+ return fail(SOCKET_FAIL);
+ };
+ g.websocket.onclose = function() {
+ return setupSocket();
+ };
+ return g.websocket.onmessage = function(e) {
+ var from_address, received, results;
+ results = eval('(' + e.data + ')');
+ from_address = '';
+ received = 0;
+ $.each(results.x.out, function(i, v) {
+ if (v.addr === g.address) {
+ return received += v.value / 100000000;
+ }
+ });
+ $.each(results.x.inputs, function(i, v) {
+ from_address = v.prev_out.addr;
+ if (v.prev_out.addr === g.address) {
+ return input -= v.prev_out.value / 100000000;
+ }
+ });
+ if (g.receivable <= received) {
+ $('#amount').blur();
+ $('#payment').hide();
+ $('#received').fadeIn('slow');
+ }
+ if (g.user) {
+ return $.post("/" + g.user + "/transactions", {
+ address: from_address,
+ date: moment().format("YYYY-MM-DD HH:mm:ss"),
+ received: received,
+ exchange: g.exchange
+ });
+ }
+ };
+ }
+ };
+
+ updateTotal = function() {
+ var amount, total;
+ amount = parseFloat($('#amount').val() * tip);
+ total = (amount * 1000 / g.exchange).toFixed(5);
+ g.receivable = (amount / g.exchange).toFixed(8);
+ if (!$.isNumeric(total)) {
+ total = '';
+ }
+ $('#total').html(total.toString());
+ $('#qr').html('');
+ return new QRCode('qr', "bitcoin:" + g.address + "?amount=" + (g.receivable.toString()));
+ };
+
+ fail = function(msg) {
+ g.errors.push(msg);
+ g.errors = g.errors.uniq();
+ $('#calculator').hide();
+ return $('#error').show().html(g.errors.toString());
+ };
+
+ clear = function(msg) {
+ var i;
+ i = g.errors.indexOf(msg);
+ if (i >= 0) {
+ g.errors.splice(i, 1);
+ }
+ if (g.errors.length > 0) {
+ return $('#error').show().html(g.errors.toString());
+ } else {
+ $('#error').hide();
+ return $('#calculator').fadeIn('slow');
+ }
+ };
+
+ get = function(name) {
+ var regex, regexS, results;
+ name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
+ regexS = "[\\?&]" + name + "=([^&#]*)";
+ regex = new RegExp(regexS);
+ results = regex.exec(window.location.search);
+ if (results === null) {
+ return "";
+ } else {
+ return decodeURIComponent(results[1].replace(/\+/g, " "));
+ }
+ };
+
+ Array.prototype.uniq = function() {
+ var key, output, value, _i, _ref, _results;
+ output = {};
+ for (key = _i = 0, _ref = this.length; 0 <= _ref ? _i < _ref : _i > _ref; key = 0 <= _ref ? ++_i : --_i) {
+ output[this[key]] = this[key];
+ }
+ _results = [];
+ for (key in output) {
+ value = output[key];
+ _results.push(value);
+ }
+ return _results;
+ };
+
+}).call(this);
diff --git a/public/js/deposit.js b/public/js/deposit.js
new file mode 100644
index 00000000..3bb5bf23
--- /dev/null
+++ b/public/js/deposit.js
@@ -0,0 +1,102 @@
+(function() {
+ var ADDRESS_FAIL, EXCHANGE_FAIL, SOCKET_FAIL, clear, fail, g, get, setupSocket;
+
+ EXCHANGE_FAIL = "Error fetching exchange rate";
+
+ SOCKET_FAIL = "Error connecting to payment server";
+
+ ADDRESS_FAIL = "Invalid address";
+
+ g = typeof exports !== "undefined" && exports !== null ? exports : this;
+
+ $(function() {
+ g.address || (g.address = '1VAnbtCAnYccECnjaMCPnWwt81EHCVgNr');
+ setupSocket();
+ setupQR();
+ return displayQR('bitcoin:' + g.address);
+ });
+
+ setupSocket = function() {
+ g.address = "1VAnbtCAnYccECnjaMCPnWwt81EHCVgNr";
+ setTimeout(setupSocket, 10000);
+ if (!(g.websocket && g.websocket.readyState === 1)) {
+ g.websocket = new WebSocket("ws://api.blockchain.info:8335/inv");
+ g.websocket.onopen = function() {
+ return g.websocket.send('{"op":"addr_sub", "addr":"' + g.address + '"}');
+ };
+ g.websocket.onerror = g.websocket.onclose = function() {
+ return fail(SOCKET_FAIL);
+ };
+ return g.websocket.onmessage = function(e) {
+ var from_address, received, results, total;
+ results = eval('(' + e.data + ')');
+ from_address = '';
+ total = 0;
+ received = 0;
+ $.each(results.x.out, function(i, v) {
+ if (v.addr === g.address) {
+ return received += v.value;
+ }
+ });
+ $.each(results.x.inputs, function(i, v) {
+ from_address = v.prev_out.addr;
+ if (v.prev_out.addr === g.address) {
+ return input -= v.prev_out.value;
+ }
+ });
+ return $.get("/issue/" + received, function(data) {
+ return $('#received').text(data);
+ });
+ };
+ }
+ };
+
+ fail = function(msg) {
+ g.errors.push(msg);
+ g.errors = g.errors.uniq();
+ $('#calculator').hide();
+ return $('#error').show().html(g.errors.toString());
+ };
+
+ clear = function(msg) {
+ var i;
+ i = g.errors.indexOf(msg);
+ if (i >= 0) {
+ g.errors.splice(i, 1);
+ }
+ if (g.errors.length > 0) {
+ return $('#error').show().html(g.errors.toString());
+ } else {
+ $('#error').hide();
+ return $('#calculator').fadeIn('slow');
+ }
+ };
+
+ get = function(name) {
+ var regex, regexS, results;
+ name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
+ regexS = "[\\?&]" + name + "=([^&#]*)";
+ regex = new RegExp(regexS);
+ results = regex.exec(window.location.search);
+ if (results === null) {
+ return "";
+ } else {
+ return decodeURIComponent(results[1].replace(/\+/g, " "));
+ }
+ };
+
+ Array.prototype.uniq = function() {
+ var key, output, value, _i, _ref, _results;
+ output = {};
+ for (key = _i = 0, _ref = this.length; 0 <= _ref ? _i < _ref : _i > _ref; key = 0 <= _ref ? ++_i : --_i) {
+ output[this[key]] = this[key];
+ }
+ _results = [];
+ for (key in output) {
+ value = output[key];
+ _results.push(value);
+ }
+ return _results;
+ };
+
+}).call(this);
diff --git a/public/js/index.js b/public/js/index.js
new file mode 100644
index 00000000..7b799c1e
--- /dev/null
+++ b/public/js/index.js
@@ -0,0 +1,51 @@
+(function() {
+ var fetchExchangeRate, g;
+
+ g = typeof exports !== "undefined" && exports !== null ? exports : this;
+
+ $(function() {
+ fetchExchangeRate('ask');
+ fetchExchangeRate('bid');
+ $('#username').blur(function() {
+ return $.get("/" + ($(this).val()) + "/exists", {
+ username: $(this).val()
+ }, function(data) {
+ if (data === "true") {
+ $('#username').prev().css('color', 'red').html('Username (taken)');
+ return g.preventSubmit = true;
+ } else {
+ $('#username').prev().css('color', 'black').html('Username');
+ return g.preventSubmit = false;
+ }
+ });
+ });
+ return $('#signup').submit(function() {
+ if (g.preventSubmit) {
+ return false;
+ }
+ return true;
+ });
+ });
+
+ fetchExchangeRate = function(type) {
+ var commission;
+ commission = 0.015;
+ if (type === 'bid') {
+ commission *= -1;
+ }
+ return $.ajax({
+ url: "/ticker?symbol=virtexCAD&type=" + type + "&amount=100",
+ success: function(exchange) {
+ if (exchange == null) {
+ exchange = '??';
+ }
+ exchange = exchange - exchange * commission;
+ return $("#" + type).html(exchange.toFixed(2));
+ },
+ error: function() {
+ return $("#" + type).html('??');
+ }
+ });
+ };
+
+}).call(this);
diff --git a/public/js/register.js b/public/js/register.js
new file mode 100644
index 00000000..b75cc305
--- /dev/null
+++ b/public/js/register.js
@@ -0,0 +1,6 @@
+(function() {
+ $(function() {
+ return $('#username').focus();
+ });
+
+}).call(this);
diff --git a/public/js/report.js b/public/js/report.js
new file mode 100644
index 00000000..1fd882a7
--- /dev/null
+++ b/public/js/report.js
@@ -0,0 +1,63 @@
+(function() {
+ var display, filterDates, g;
+
+ g = typeof exports !== "undefined" && exports !== null ? exports : this;
+
+ $(function() {
+ $('#from').val(moment().subtract('days', 7).format("MM/DD/YYYY"));
+ $('#to').val(moment().format("MM/DD/YYYY"));
+ $('.date').datepicker({
+ onClose: filterDates
+ });
+ return $.getJSON('transactions.json', function(data) {
+ g.transactions = data.transactions;
+ display(g.transactions);
+ return filterDates();
+ });
+ });
+
+ filterDates = function() {
+ var transactions;
+ transactions = $.grep(g.transactions, function(e, i) {
+ var amount, d, from, to;
+ if (!e) {
+ return false;
+ }
+ from = moment($('#from').val(), "MM/DD/YYYY");
+ to = moment($('#to').val(), "MM/DD/YYYY");
+ d = moment(e.date);
+ amount = parseFloat(e.exchange) * parseFloat(e.received);
+ return !isNaN(parseFloat(amount)) && isFinite(amount) && ((from == null) || d.diff(from) >= 0) && ((to == null) || d.diff(to) <= 0);
+ });
+ return display(transactions);
+ };
+
+ display = function(transactions) {
+ var btc, cad;
+ $('tbody tr').remove();
+ $('thead, tfoot').show();
+ if (transactions.length === 0) {
+ $('tbody').append("<tr>\n <td colspan='5'>\n No transactions were found for the specified time period\n </td>\n</tr>");
+ $('thead, tfoot').hide();
+ }
+ $.each(transactions, function() {
+ var amount, exchange, received;
+ exchange = parseFloat(this.exchange);
+ received = parseFloat(this.received);
+ amount = received * exchange;
+ received *= 1000;
+ return $('tbody').append("<tr>\n <td>" + this.date + "</td>\n <td>" + this.address + "</td>\n <td>" + (exchange.toFixed(2)) + "</td>\n <td>" + (received.toFixed(5)) + "</td>\n <td>" + (amount.toFixed(2)) + "</td>\n</tr>");
+ });
+ btc = 0;
+ $('table.report td:nth-child(4)').each(function() {
+ return btc += parseFloat($(this).html());
+ });
+ $('#btc').html(btc.toFixed(5));
+ cad = 0;
+ $('table.report td:nth-child(5)').each(function() {
+ return cad += parseFloat($(this).html());
+ });
+ return $('#cad').html(cad.toFixed(2));
+ };
+
+}).call(this);
diff --git a/public/js/setup.coffee b/public/js/setup.coffee
index e8b4e09b..9b4bf5d2 100644
--- a/public/js/setup.coffee
+++ b/public/js/setup.coffee
@@ -8,6 +8,7 @@ g = exports ? this
g.proceed = false
$(->
+ $('#title').focus()
$.getJSON("/js/rates.json", (data) ->
currencies = Object.keys(data)
currencies = currencies.sort()
@@ -22,7 +23,9 @@ $(->
$('#currency').change(->
$('#symbol option').remove()
- symbols = Object.keys(data[$(this).val()])
+ symbol = $(this).val()
+ return unless symbol
+ symbols = Object.keys(data[symbol])
$.each(symbols, (i, v) ->
$('#symbol').append("<option value='#{v}'>#{v} bid price</option>")
)
diff --git a/public/js/setup.js b/public/js/setup.js
new file mode 100644
index 00000000..56b2f067
--- /dev/null
+++ b/public/js/setup.js
@@ -0,0 +1,72 @@
+(function() {
+ var g;
+
+ g = typeof exports !== "undefined" && exports !== null ? exports : this;
+
+ g.proceed = false;
+
+ $(function() {
+ $('#title').focus();
+ return $.getJSON("/js/rates.json", function(data) {
+ var currencies, user;
+ currencies = Object.keys(data);
+ currencies = currencies.sort();
+ currencies.pop();
+ $.each(currencies, function(i, v) {
+ return $('#currency').append("<option value='" + v + "'>" + v + "</option>");
+ });
+ $("#currency option[value='CAD']").attr('selected', 'selected');
+ user = $('#username').val();
+ $('#currency').change(function() {
+ var symbol, symbols;
+ $('#symbol option').remove();
+ symbol = $(this).val();
+ if (!symbol) {
+ return;
+ }
+ symbols = Object.keys(data[symbol]);
+ $.each(symbols, function(i, v) {
+ return $('#symbol').append("<option value='" + v + "'>" + v + " bid price</option>");
+ });
+ switch ($(this).val()) {
+ case 'CAD':
+ return $("#symbol option[value='quadrigacx']").attr('selected', 'selected');
+ case 'USD':
+ return $("#symbol option[value='bitstamp']").attr('selected', 'selected');
+ }
+ }).change();
+ $('#address').change(function() {
+ if (check_address($(this).val())) {
+ return $(this).css('color', 'black');
+ } else {
+ return $(this).css('color', 'red');
+ }
+ });
+ $('#confirm').blur(function() {
+ $('#confirm_error').remove();
+ if ($('#password').val() !== $('#confirm').val()) {
+ $('#password, #confirm').parent().addClass('has-error');
+ return $('#confirm').parent().after('<div id="confirm_error" class="alert alert-danger">Passwords don\'t match</div>');
+ } else {
+ return $('#password, #confirm').parent().removeClass('has-error');
+ }
+ });
+ $('#setup').submit(function() {
+ if ($('.has-error').length()) {
+ return false;
+ }
+ });
+ if (user) {
+ $('#setup').attr('action', "/" + user + "/update").attr('method', 'post');
+ return $.getJSON("/" + user + ".json", function(data) {
+ $('#title').val(data.title);
+ $('#logo').val(data.logo);
+ $('#address').val(data.address);
+ $("#symbol option[value='" + data.symbol + "']").attr('selected', 'selected');
+ return $('#commission').val(data.commission);
+ });
+ }
+ });
+ });
+
+}).call(this);