separated insight API from the front-end
This commit is contained in:
parent
94249a214d
commit
c28dd990b0
91
Gruntfile.js
91
Gruntfile.js
@ -5,9 +5,6 @@ module.exports = function(grunt) {
|
||||
//Load NPM tasks
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-css');
|
||||
grunt.loadNpmTasks('grunt-mocha-test');
|
||||
grunt.loadNpmTasks('grunt-nodemon');
|
||||
grunt.loadNpmTasks('grunt-concurrent');
|
||||
@ -22,37 +19,12 @@ module.exports = function(grunt) {
|
||||
files: ['README.md'],
|
||||
tasks: ['markdown']
|
||||
},
|
||||
jade: {
|
||||
files: ['app/views/**'],
|
||||
options: {
|
||||
livereload: true,
|
||||
},
|
||||
},
|
||||
js: {
|
||||
files: ['Gruntfile.js', 'insight.js', 'app/**/*.js', 'public/js/**'],
|
||||
files: ['Gruntfile.js', 'insight.js', 'app/**/*.js'],
|
||||
tasks: ['jshint'],
|
||||
options: {
|
||||
livereload: true,
|
||||
},
|
||||
},
|
||||
assets: {
|
||||
files: ['public/src/**/*.js', 'public/**/*.css'],
|
||||
tasks: ['compile'],
|
||||
options: {
|
||||
livereload: true,
|
||||
},
|
||||
},
|
||||
html: {
|
||||
files: ['public/views/**'],
|
||||
options: {
|
||||
livereload: true,
|
||||
},
|
||||
},
|
||||
css: {
|
||||
files: ['public/css/**'],
|
||||
options: {
|
||||
livereload: true
|
||||
}
|
||||
},
|
||||
// we monitor only app/models/* because we have test for models only now
|
||||
// test: {
|
||||
@ -62,64 +34,12 @@ module.exports = function(grunt) {
|
||||
},
|
||||
jshint: {
|
||||
all: {
|
||||
src: ['Gruntfile.js', 'insight.js', 'app/**/*.js', 'public/src/js/**/*.js','lib/*.js'],
|
||||
src: ['Gruntfile.js', 'insight.js', 'app/**/*.js', 'lib/*.js'],
|
||||
options: {
|
||||
jshintrc: true
|
||||
}
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
options: {
|
||||
process: function(src, filepath) {
|
||||
if (filepath.substr(filepath.length - 2) === 'js') {
|
||||
return '// Source: ' + filepath + '\n' +
|
||||
src.replace(/(^|\n)[ \t]*('use strict'|"use strict");?\s*/g, '$1');
|
||||
} else {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
},
|
||||
vendors: {
|
||||
src: ['public/lib/momentjs/min/moment.min.js', 'public/lib/qrcode-generator/js/qrcode.js', 'public/lib/zeroclipboard/ZeroClipboard.min.js'],
|
||||
dest: 'public/js/vendors.js'
|
||||
},
|
||||
angular: {
|
||||
src: ['public/lib/angular/angular.min.js', 'public/lib/angular-resource/angular-resource.min.js', 'public/lib/angular-route/angular-route.min.js', 'public/lib/angular-qrcode/qrcode.js', 'public/lib/angular-animate/angular-animate.min.js', 'public/lib/angular-bootstrap/ui-bootstrap.min.js', 'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js', 'public/lib/angular-ui-utils/ui-utils.min.js', 'public/lib/ngprogress/build/ngProgress.min.js'],
|
||||
dest: 'public/js/angularjs-all.js'
|
||||
},
|
||||
main: {
|
||||
src: ['public/src/js/app.js', 'public/src/js/controllers/*.js', 'public/src/js/services/*.js', 'public/src/js/directives.js', 'public/src/js/filters.js', 'public/src/js/config.js', 'public/src/js/init.js'],
|
||||
dest: 'public/js/main.js'
|
||||
},
|
||||
css: {
|
||||
src: ['public/src/css/**/*.css'],
|
||||
dest: 'public/css/main.css'
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n',
|
||||
mangle: false
|
||||
},
|
||||
vendors: {
|
||||
src: 'public/js/vendors.js',
|
||||
dest: 'public/js/vendors.min.js'
|
||||
},
|
||||
angular: {
|
||||
src: 'public/js/angularjs-all.js',
|
||||
dest: 'public/js/angularjs-all.min.js'
|
||||
},
|
||||
main: {
|
||||
src: 'public/js/main.js',
|
||||
dest: 'public/js/main.min.js'
|
||||
}
|
||||
},
|
||||
cssmin: {
|
||||
css: {
|
||||
src: 'public/css/main.css',
|
||||
dest: 'public/css/main.min.css'
|
||||
}
|
||||
},
|
||||
mochaTest: {
|
||||
options: {
|
||||
reporter: 'spec',
|
||||
@ -131,7 +51,7 @@ module.exports = function(grunt) {
|
||||
script: 'insight.js',
|
||||
options: {
|
||||
args: [],
|
||||
ignore: ['public/**/*.html','public/**/*.css', 'public/**/*.js', 'test/**/*','util/**/*', ,'dev-util/**/*'],
|
||||
ignore: ['test/**/*', 'util/**/*', 'dev-util/**/*'],
|
||||
// nodeArgs: ['--debug'],
|
||||
delayTime: 1,
|
||||
env: {
|
||||
@ -170,10 +90,7 @@ module.exports = function(grunt) {
|
||||
grunt.option('force', true);
|
||||
|
||||
//Default task(s).
|
||||
grunt.registerTask('default', ['jshint', 'compile', 'concurrent']);
|
||||
|
||||
//Compile task (concat + minify)
|
||||
grunt.registerTask('compile', ['concat', 'uglify', 'cssmin']);
|
||||
grunt.registerTask('default', ['jshint', 'concurrent']);
|
||||
|
||||
//Test task.
|
||||
grunt.registerTask('test', ['env:test', 'mochaTest']);
|
||||
|
||||
@ -23,7 +23,7 @@ var getAddr = function(req, res, next) {
|
||||
exports.show = function(req, res, next) {
|
||||
var a = getAddr(req, res, next);
|
||||
|
||||
if (a)
|
||||
if (a)
|
||||
a.update(function(err) {
|
||||
if (err) {
|
||||
return common.handleErrors(err, res);
|
||||
@ -39,7 +39,7 @@ exports.show = function(req, res, next) {
|
||||
exports.utxo = function(req, res, next) {
|
||||
var a = getAddr(req, res, next);
|
||||
|
||||
if (a)
|
||||
if (a)
|
||||
a.getUtxo(function(err, utxo) {
|
||||
if (err)
|
||||
return common.handleErrors(err, res);
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
var _getVersion = function() {
|
||||
var pjson = require('../../package.json');
|
||||
return pjson.version;
|
||||
};
|
||||
|
||||
exports.render = function(req, res) {
|
||||
res.render('index');
|
||||
var version = _getVersion();
|
||||
res.send('insight API v' + version);
|
||||
};
|
||||
|
||||
exports.version = function(req, res) {
|
||||
var pjson = require('../../package.json');
|
||||
res.json({version: pjson.version});
|
||||
var version = _getVersion();
|
||||
res.json({ version: version });
|
||||
};
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ module.exports.broadcastTx = function(tx) {
|
||||
t = {
|
||||
txid: tx
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
t = {
|
||||
|
||||
@ -47,7 +47,7 @@ var getTransaction = function(txid, cb) {
|
||||
if (err) console.log(err);
|
||||
|
||||
if (!tx || !tx.info) {
|
||||
console.log('[transactions.js.48]:: TXid %s not found in RPC. CHECK THIS.', txid);
|
||||
console.log('[transactions.js.48]:: TXid %s not found in RPC. CHECK THIS.', txid);
|
||||
return ({ txid: txid });
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
extends layouts/default
|
||||
|
||||
block main
|
||||
h1 Oops something went wrong
|
||||
br
|
||||
span 404
|
||||
|
||||
block content
|
||||
#error-message-box
|
||||
#error-stack-trace
|
||||
pre
|
||||
code!= error
|
||||
@ -1,12 +0,0 @@
|
||||
extends layouts/default
|
||||
|
||||
block main
|
||||
h1 Oops something went wrong
|
||||
br
|
||||
span 500
|
||||
|
||||
block content
|
||||
#error-message-box
|
||||
#error-stack-trace
|
||||
pre
|
||||
code!= error
|
||||
@ -1,7 +0,0 @@
|
||||
#footer(data-ng-include="'/views/includes/footer.html'", role='navigation')
|
||||
|
||||
script(type='text/javascript', src='/socket.io/socket.io.js')
|
||||
script(type='text/javascript', src='/js/vendors.min.js')
|
||||
script(type='text/javascript', src='/js/angularjs-all.min.js')
|
||||
script(type='text/javascript', src='/js/main.min.js')
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
|
||||
meta(name='viewport', content='width=device-width,initial-scale=1.0')
|
||||
meta(name="fragment", content="!")
|
||||
|
||||
title(data-ng-bind="$root.title + $root.titleDetail + ' | #{appName}'")= appName
|
||||
meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
|
||||
meta(name="keywords", content="bitcoins, transactions, blocks, address, block chain, best block, mining difficulty, hash serialized")
|
||||
meta(name="description", content="Bitcoin Insight. View detailed information on all bitcoin transactions and block. {{ $root.title + $root.titleDetail }}")
|
||||
|
||||
link(rel='shortcut icon', href='/img/icons/favicon.ico', type='image/x-icon')
|
||||
|
||||
link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,400italic')
|
||||
link(rel='stylesheet', href='/lib/bootstrap/dist/css/bootstrap.min.css')
|
||||
link(rel='stylesheet', href='/css/main.min.css')
|
||||
|
||||
if (config.keys.segmentio)
|
||||
script(type='text/javascript').
|
||||
window.analytics||(window.analytics=[]),window.analytics.methods=['identify','track','trackLink','trackForm','trackClick','trackSubmit','page','pageview','ab','alias','ready','group','on','once','off'],window.analytics.factory=function(t){return function(){var a=Array.prototype.slice.call(arguments);return a.unshift(t),window.analytics.push(a),window.analytics}};for(var i=0;i<window.analytics.methods.length;i++){var method=window.analytics.methods[i];window.analytics[method]=window.analytics.factory(method)}window.analytics.load=function(t){var a=document.createElement('script');a.type='text/javascript',a.async=!0,a.src=('https:'===document.location.protocol?'https://':'http://')+'d2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/'+t+'/analytics.min.js';var n=document.getElementsByTagName('script')[0];n.parentNode.insertBefore(a,n)},window.analytics.SNIPPET_VERSION='2.0.8',
|
||||
window.analytics.load('#{config.keys.segmentio}');
|
||||
window.analytics.page();
|
||||
@ -1 +0,0 @@
|
||||
.navbar.navbar-default.navbar-fixed-top(data-ng-include="'/views/includes/header.html'", role='navigation')
|
||||
@ -1,4 +0,0 @@
|
||||
extends layouts/default
|
||||
|
||||
block content
|
||||
section.container(data-ng-view)
|
||||
@ -1,8 +0,0 @@
|
||||
doctype
|
||||
html(lang='en', data-ng-app='insight' data-ng-csp)
|
||||
include ../includes/head
|
||||
body
|
||||
#wrap
|
||||
include ../includes/navbar
|
||||
block content
|
||||
include ../includes/foot
|
||||
18
bower.json
18
bower.json
@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "Insight",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"angular": "latest",
|
||||
"angular-resource": "latest",
|
||||
"angular-mocks": "latest",
|
||||
"angular-route": "latest",
|
||||
"bootstrap": "3.0.3",
|
||||
"angular-bootstrap": "0.9.0",
|
||||
"angular-ui-utils": "0.1.0",
|
||||
"angular-qrcode": "latest",
|
||||
"angular-animate": "latest",
|
||||
"momentjs": "~2.5.0",
|
||||
"zeroclipboard": "~1.3.0-beta.1",
|
||||
"ngprogress": "~1.0.4"
|
||||
}
|
||||
}
|
||||
@ -44,11 +44,12 @@ if (!dataDir) {
|
||||
if (isMac) dataDir = process.env.HOME + '/Library/Application Support/Bitcoin/';
|
||||
if (isLinux) dataDir = process.env.HOME + '/.bitcoin/';
|
||||
}
|
||||
dataDir += ((process.env.INSIGHT_NETWORK || 'testnet')==='testnet'?'testnet3':'');
|
||||
dataDir += process.env.INSIGHT_NETWORK === 'testnet' ? 'testnet3' : '';
|
||||
|
||||
module.exports = {
|
||||
root: rootPath,
|
||||
appName: 'Insight ' + env,
|
||||
apiPrefix: '/api',
|
||||
port: port,
|
||||
leveldb: db,
|
||||
bitcoind: {
|
||||
|
||||
@ -21,10 +21,6 @@ module.exports = function(app, historicSync, peerSync) {
|
||||
|
||||
app.set('showStackError', true);
|
||||
|
||||
//Set views path, template engine and default layout
|
||||
app.set('views', config.root + '/app/views');
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
// Compress JSON outputs
|
||||
app.set('json spaces', 0);
|
||||
|
||||
@ -63,14 +59,16 @@ module.exports = function(app, historicSync, peerSync) {
|
||||
console.error(err.stack);
|
||||
|
||||
//Error page
|
||||
res.status(500).render('500', {
|
||||
res.status(500).jsonp({
|
||||
status: 500,
|
||||
error: err.stack
|
||||
});
|
||||
});
|
||||
|
||||
//Assume 404 since no middleware responded
|
||||
app.use(function(req, res) {
|
||||
res.status(404).render('404', {
|
||||
res.status(404).jsonp({
|
||||
status: 404,
|
||||
url: req.originalUrl,
|
||||
error: 'Not found'
|
||||
});
|
||||
|
||||
@ -1,42 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var config = require('./config');
|
||||
|
||||
module.exports = function(app) {
|
||||
|
||||
var apiPrefix = config.apiPrefix;
|
||||
|
||||
//Block routes
|
||||
var blocks = require('../app/controllers/blocks');
|
||||
app.get('/api/blocks', blocks.list);
|
||||
app.get(apiPrefix + '/blocks', blocks.list);
|
||||
|
||||
|
||||
app.get('/api/block/:blockHash', blocks.show);
|
||||
app.get(apiPrefix + '/block/:blockHash', blocks.show);
|
||||
app.param('blockHash', blocks.block);
|
||||
|
||||
app.get('/api/block-index/:height', blocks.blockindex);
|
||||
app.get(apiPrefix + '/block-index/:height', blocks.blockindex);
|
||||
app.param('height', blocks.blockindex);
|
||||
|
||||
// Transaction routes
|
||||
var transactions = require('../app/controllers/transactions');
|
||||
app.get('/api/tx/:txid', transactions.show);
|
||||
app.get(apiPrefix + '/tx/:txid', transactions.show);
|
||||
app.param('txid', transactions.transaction);
|
||||
app.get('/api/txs', transactions.list);
|
||||
app.get(apiPrefix + '/txs', transactions.list);
|
||||
|
||||
// Address routes
|
||||
var addresses = require('../app/controllers/addresses');
|
||||
app.get('/api/addr/:addr', addresses.show);
|
||||
app.get('/api/addr/:addr/utxo', addresses.utxo);
|
||||
app.get(apiPrefix + '/addr/:addr', addresses.show);
|
||||
app.get(apiPrefix + '/addr/:addr/utxo', addresses.utxo);
|
||||
|
||||
// Status route
|
||||
var st = require('../app/controllers/status');
|
||||
app.get('/api/status', st.show);
|
||||
app.get(apiPrefix + '/status', st.show);
|
||||
|
||||
app.get('/api/sync', st.sync);
|
||||
app.get('/api/peer', st.peer);
|
||||
app.get(apiPrefix + '/sync', st.sync);
|
||||
app.get(apiPrefix + '/peer', st.peer);
|
||||
|
||||
// Currency
|
||||
var currency = require('../app/controllers/currency');
|
||||
app.get('/api/currency', currency.index);
|
||||
app.get(apiPrefix + '/currency', currency.index);
|
||||
|
||||
//Home route
|
||||
var index = require('../app/controllers/index');
|
||||
app.get('/api/version', index.version);
|
||||
app.get('*', index.render);
|
||||
app.get(apiPrefix + '/version', index.version);
|
||||
app.get('/', index.render);
|
||||
};
|
||||
|
||||
@ -25,7 +25,6 @@ function spec(b) {
|
||||
var Rpc = b.rpc || require('./Rpc').class();
|
||||
var PoolMatch = b.poolMatch || require('./PoolMatch').class(config);
|
||||
|
||||
var buffertools = require('buffertools');
|
||||
var TransactionDb = require('./TransactionDb.js').class();
|
||||
|
||||
var BlockDb = function() {
|
||||
@ -176,9 +175,9 @@ function spec(b) {
|
||||
|
||||
if (a.isCoinBase) {
|
||||
var coinbaseHexBuffer = new Buffer(a.vin[0].coinbase, 'hex');
|
||||
var a = self.poolMatch.match(coinbaseHexBuffer);
|
||||
var aa = self.poolMatch.match(coinbaseHexBuffer);
|
||||
|
||||
return cb(a);
|
||||
return cb(aa);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -29,7 +29,7 @@ function spec(b) {
|
||||
if (buffertools.indexOf(buffer, k) >= 0) {
|
||||
return self.strings[k];
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return PoolMatch;
|
||||
|
||||
@ -19,21 +19,21 @@ function spec(b) {
|
||||
var b = new Buffer(info.hex,'hex');
|
||||
|
||||
// remove fields we dont need, to speed and adapt the information
|
||||
delete info['hex'];
|
||||
delete info.hex;
|
||||
|
||||
// Inputs => add index + coinBase flag
|
||||
var n =0;
|
||||
info.vin.forEach(function(i) {
|
||||
i.n = n++;
|
||||
if (i.coinbase) info.isCoinBase = true;
|
||||
if (i.scriptSig) delete i.scriptSig['hex'];
|
||||
if (i.scriptSig) delete i.scriptSig.hex;
|
||||
});
|
||||
|
||||
// Outputs => add total
|
||||
var valueOutSat = 0;
|
||||
info.vout.forEach( function(o) {
|
||||
valueOutSat += o.value * bitcoreUtil.COIN;
|
||||
delete o.scriptPubKey['hex'];
|
||||
delete o.scriptPubKey.hex;
|
||||
});
|
||||
info.valueOut = parseInt(valueOutSat) / bitcoreUtil.COIN;
|
||||
info.size = b.length;
|
||||
|
||||
10
package.json
10
package.json
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "insight-bitcore",
|
||||
"name": "insight-bitcore-api",
|
||||
"description": "An open-source bitcoin blockchain API. The Insight API provides you with a convenient, powerful and simple way to query and broadcast data on the bitcoin network and build your own services with it.",
|
||||
"version": "0.1.2",
|
||||
"author": {
|
||||
@ -59,8 +59,6 @@
|
||||
"commander": "*",
|
||||
"bignum": "*",
|
||||
"express": "~3.4.7",
|
||||
"jade": "~1.0.2",
|
||||
"lodash": "~2.4.1",
|
||||
"buffertools": "*",
|
||||
"should": "~2.1.1",
|
||||
"view-helpers": "latest",
|
||||
@ -73,7 +71,6 @@
|
||||
"xmlhttprequest": "~1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bower": "~1.2.8",
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-cli": "~0.1.11",
|
||||
"grunt-env": "~0.4.1",
|
||||
@ -82,10 +79,7 @@
|
||||
"grunt-concurrent": "~0.4.2",
|
||||
"grunt-nodemon": "~0.2.0",
|
||||
"grunt-mocha-test": "~0.8.1",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-uglify": "~0.3.2",
|
||||
"should": "latest",
|
||||
"grunt-css": "~0.5.4",
|
||||
"should": "2.1.1",
|
||||
"grunt-markdown": "~0.5.0"
|
||||
}
|
||||
}
|
||||
|
||||
1
public/css/main.min.css
vendored
1
public/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
0
public/img/.gitignore
vendored
0
public/img/.gitignore
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 148 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 KiB |
9
public/js/angularjs-all.min.js
vendored
9
public/js/angularjs-all.min.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/main.min.js
vendored
2
public/js/main.min.js
vendored
File diff suppressed because one or more lines are too long
3
public/js/vendors.min.js
vendored
3
public/js/vendors.min.js
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,682 +0,0 @@
|
||||
/* Sticky footer styles
|
||||
-------------------------------------------------- */
|
||||
@charset "UTF-8";
|
||||
|
||||
html,
|
||||
body {
|
||||
color: #373D42;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
height: 100%;
|
||||
/* The html and body elements cannot have any padding or margin. */
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
color: #373D42;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
}
|
||||
|
||||
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
|
||||
.ng-cloak, .x-ng-cloak,
|
||||
.ng-hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Styling for the ngProgress itself */
|
||||
#ngProgress {
|
||||
background-color: #6C9032 !important;
|
||||
box-shadow: none !important;
|
||||
color: #373D42 !important;
|
||||
height: 3px !important;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
padding: 0;
|
||||
z-index: 99998;
|
||||
|
||||
/* Add CSS3 styles for transition smoothing */
|
||||
-webkit-transition: all 0.5s ease-in-out;
|
||||
-moz-transition: all 0.5s ease-in-out;
|
||||
-o-transition: all 0.5s ease-in-out;
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
/* Styling for the ngProgress-container */
|
||||
#ngProgress-container {
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 63px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
/* Wrapper for page content to push down footer */
|
||||
#wrap {
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
/* Negative indent footer by its height */
|
||||
margin: 0 auto -51px;
|
||||
/* Pad bottom by footer height */
|
||||
padding: 0 0 75px;
|
||||
}
|
||||
|
||||
.m10h { margin: 0 10px; }
|
||||
.m20h { margin: 0 20px; }
|
||||
.m5v { margin: 5px 0; }
|
||||
.m20v { margin: 20px 0; }
|
||||
.m10v { margin: 10px 0; }
|
||||
.m50v { margin: 50px 0; }
|
||||
.m10b { margin-bottom: 10px; }
|
||||
.m10l { margin-left: 10px; }
|
||||
|
||||
.vm { vertical-align: middle; }
|
||||
|
||||
.bgwhite {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.btn-group .btn+.btn, .btn-group .btn+.btn-group, .btn-group .btn-group+.btn, .btn-group .btn-group+.btn-group {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.table-hover>tbody>tr:hover>td, .table-hover>tbody>tr:hover>th {
|
||||
background-color: #F0F7E2;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-toggle {
|
||||
border-color: #fff;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-toggle .icon-bar { background-color: #fff; }
|
||||
.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus {background-color: #373D42;}
|
||||
|
||||
.navbar-default {
|
||||
background-color: #8DC429;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav>li>a {
|
||||
color: #F4FBE8;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
padding-left: 25px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus {
|
||||
background-color: #6C9032;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav>li>a:hover, .navbar-default .navbar-nav>.active>a:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.navbar-form .form-group {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.navbar-form {
|
||||
width: 35%;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.status {
|
||||
margin: 0;
|
||||
}
|
||||
.navbar-form {
|
||||
width: 15%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.navbar-form {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tabs.nav-justified>li>a:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.insight {
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
font-size: 34px;
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus {
|
||||
color: #fffffe;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-brand {
|
||||
color: #FFFFFF;
|
||||
padding: 22px 15px;
|
||||
}
|
||||
|
||||
.navbar-form .form-control {
|
||||
background-color: #7CAD23;
|
||||
border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border: 0;
|
||||
-webkit-box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10);
|
||||
-moz-box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10);
|
||||
box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10);
|
||||
}
|
||||
|
||||
.navbar-nav>li>a {
|
||||
padding-top: 22px;
|
||||
padding-bottom: 22px;
|
||||
}
|
||||
|
||||
#search {
|
||||
color: #fff;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
}
|
||||
|
||||
#search.loading {
|
||||
background-image: url('/img/loading.gif');
|
||||
background-position: 5px center;
|
||||
background-repeat: no-repeat;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
#search::-webkit-input-placeholder {
|
||||
color: #BCDF7E;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
#search::-moz-placeholder {
|
||||
color: #BCDF7E;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
.status {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
background-color: #597338;
|
||||
border-radius: 3px;
|
||||
margin: 15px 0;
|
||||
padding: 8px 10px;
|
||||
font-size: 12px;
|
||||
color: #eee;
|
||||
text-align: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.status .tooltip {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.col-gray {
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
background-color: #F4F4F4;
|
||||
border-radius: 5px;
|
||||
padding: 14px;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.col-gray-responsive {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.col-gray-fixed {
|
||||
margin-top: 15px;
|
||||
position: fixed;
|
||||
width: 250px;
|
||||
border: 1px solid #eee;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.col-gray-fixed {
|
||||
width:100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 995px) {
|
||||
.col-gray-fixed {
|
||||
position:static;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.col-gray-fixed {
|
||||
width: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.line20 {
|
||||
border: 1px solid #D4D4D4;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.line10 {
|
||||
border: 1px solid #EAEAEA;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.block-id {
|
||||
background-color: #373D42;
|
||||
border: 3px solid #FFFFFF;
|
||||
margin: 0 auto;
|
||||
width: 165px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.block-id span {
|
||||
font-size: 40px;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.block-id h2 {
|
||||
color: #FFFFFF;
|
||||
font-weight: bold;
|
||||
line-height: 30px;
|
||||
font-size: 24px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.icon-block {
|
||||
color: #FFFFFF;
|
||||
font-size: 35px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.icon-block h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.block-tx {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
background-color: #F4F4F4;
|
||||
border-radius: 2px;
|
||||
margin: 20px 0 10px;
|
||||
overflow: hidden;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 2px;
|
||||
}
|
||||
.btn-primary {
|
||||
background-color: #8DC429;
|
||||
border: 2px solid #76AF0F;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus, .btn-primary:active,
|
||||
.btn-primary.active, .open .dropdown-toggle.btn-primary,
|
||||
.btn-success:hover, .btn-success:focus, .btn-success:active,
|
||||
.btn-success.active, .open .dropdown-toggle.btn-success,
|
||||
.btn-danger:hover, .btn-danger:focus, .btn-danger:active,
|
||||
.btn-danger.active, .open .dropdown-toggle.btn-danger {
|
||||
background-color: #fff;
|
||||
border: 2px solid #ccc;
|
||||
color: #373D42;
|
||||
}
|
||||
|
||||
.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
background-color: #E7E7E7;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: #2FA4D7;
|
||||
border: 2px solid #237FA7;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #AC0015;
|
||||
border: 2px solid #6C0000;
|
||||
}
|
||||
|
||||
.txvalues {
|
||||
display: inline-block;
|
||||
padding: .7em 2em;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
font-weight:100;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: baseline;
|
||||
border-radius: .25em;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.txvalues {
|
||||
display: block;
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.txvalues-primary {
|
||||
background-color: #8DC429;
|
||||
}
|
||||
|
||||
.txvalues-default {
|
||||
background-color: #EBEBEB;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.txvalues-success {
|
||||
background-color: #2FA4D7;
|
||||
}
|
||||
|
||||
.txvalues-danger {
|
||||
background-color: #AC0015;
|
||||
}
|
||||
|
||||
.txvalues-normal {
|
||||
background-color: transparent;
|
||||
text-transform: none;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.progress-bar-info { background-color: #8DC429; }
|
||||
|
||||
/* Set the fixed height of the footer here */
|
||||
#footer {
|
||||
background-color: #373D42;
|
||||
color: #fff;
|
||||
height: 51px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#footer a.insight {
|
||||
font-size: 20px;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#footer a.insight:hover {
|
||||
color: #fffffe;
|
||||
}
|
||||
|
||||
#footer a.insight small { font-size: 11px; }
|
||||
.line-footer { border-top: 2px dashed #ccc; }
|
||||
|
||||
.line-bot {
|
||||
border-bottom: 2px solid #EAEAEA;
|
||||
padding: 0 0 10px 0;
|
||||
}
|
||||
.line-mid { padding: 15px 0;}
|
||||
.line-top {
|
||||
border-top: 1px solid #EAEAEA;
|
||||
padding: 15px 0 0 0;
|
||||
}
|
||||
|
||||
/* Custom page CSS
|
||||
-------------------------------------------------- */
|
||||
/* Not required for template or sticky footer method. */
|
||||
|
||||
#wrap > .container { padding: 70px 15px 0; }
|
||||
|
||||
#footer > .container { padding: auto 15px; }
|
||||
|
||||
.code { font-size: 80%; }
|
||||
|
||||
.address { font-size: 11px; }
|
||||
|
||||
.no_matching {
|
||||
-moz-border-radius-bottomleft: 2px;
|
||||
-moz-border-radius-bottomright: 2px;
|
||||
-webkit-border-bottom-left-radius: 2px;
|
||||
-webkit-border-bottom-right-radius: 2px;
|
||||
background-color: #FFFFFF;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-top: none;
|
||||
border: 1px solid #64920F;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 45px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
/*Animations*/
|
||||
.fader.ng-enter {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 1s;
|
||||
-moz-transition: opacity 1s;
|
||||
-o-transition: opacity 1s;
|
||||
transition: opacity 1s;
|
||||
}
|
||||
|
||||
.fader.ng-enter-active { opacity: 1; }
|
||||
|
||||
.tx-bg {
|
||||
background-color: #F4F4F4;
|
||||
left: 0;
|
||||
min-height: 340px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: -9999;
|
||||
}
|
||||
|
||||
.badge {
|
||||
-moz-border-radius: 9px;
|
||||
-webkit-border-radius: 9px;
|
||||
background-color: #999999;
|
||||
border-radius: 9px;
|
||||
color: #ffffff;
|
||||
font-size: 12.025px;
|
||||
font-weight: bold;
|
||||
padding: 1px 9px 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.badge:hover {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.badge-error { background-color: #b94a48; }
|
||||
.badge-error:hover { background-color: #953b39; }
|
||||
.badge-warning { background-color: #f89406; }
|
||||
.badge-warning:hover { background-color: #c67605; }
|
||||
.badge-success { background-color: #468847; }
|
||||
.badge-success:hover { background-color: #356635; }
|
||||
.badge-info { background-color: #3a87ad; }
|
||||
.badge-info:hover { background-color: #2d6987; }
|
||||
.badge-inverse { background-color: #333333; }
|
||||
.badge-inverse:hover { background-color: #1a1a1a; }
|
||||
|
||||
.status .t {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status .text-danger { background: red; }
|
||||
|
||||
.status .text-warning {
|
||||
background: yellow;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.btn-copy {
|
||||
color: #9b9b9b;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
outline: none;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
.btn-expand {
|
||||
color: #9b9b9b;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn-copy:hover, .btn-expand:hover {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-copy {
|
||||
background: transparent url('/img/icons/copy.png') center center no-repeat;
|
||||
}
|
||||
|
||||
.btn-copy .tooltip {
|
||||
display: block;
|
||||
margin-left: 20px;
|
||||
margin-top: -2px;
|
||||
opacity: 0;
|
||||
}
|
||||
.btn-copy.zeroclipboard-is-hover { color: #2a6496; }
|
||||
.btn-copy.zeroclipboard-is-active .tooltip { opacity: 1; }
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.btn-copy {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.txid {
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.tx-id {
|
||||
background-color: #373D42;
|
||||
border: 3px solid #FFFFFF;
|
||||
margin: 0 auto;
|
||||
width: 165px;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tx-id span {
|
||||
font-size: 40px;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.page-header { margin-top: 0; }
|
||||
|
||||
/* Index */
|
||||
#home .btn-more {
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 30px auto 0;
|
||||
text-align: center;
|
||||
width: 90%;
|
||||
}
|
||||
#home .btn-more .btn-default {
|
||||
margin-top: -23px;
|
||||
}
|
||||
|
||||
#powered .powered-text {
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 30px auto 0;
|
||||
text-align: center;
|
||||
width: 90%;
|
||||
}
|
||||
#powered .powered-text small {
|
||||
background-color: #f4f4f4;
|
||||
padding: 4px;
|
||||
position: relative;
|
||||
top: -12px;
|
||||
}
|
||||
|
||||
#powered a {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
height: 45px;
|
||||
}
|
||||
#powered a.bitcore {
|
||||
background-image: url('http://bitcore.io/images/logo.svg');
|
||||
background-size: 80px;
|
||||
width: 30%;
|
||||
}
|
||||
#powered a.nodejs {
|
||||
background-image: url('/img/nodejs.png');
|
||||
background-size: 80px;
|
||||
width: 30%;
|
||||
}
|
||||
#powered a.angularjs {
|
||||
background-image: url('/img/angularjs.png');
|
||||
background-size: 50px;
|
||||
width: 20%;
|
||||
}
|
||||
#powered a.leveldb {
|
||||
background-image: url('/img/leveldb.png');
|
||||
background-size: 50px;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
@keyframes rotateThis {
|
||||
from { transform: scale( 1 ) rotate( 0deg ); }
|
||||
to { transform: scale( 1 ) rotate( 360deg ); }
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotateThis {
|
||||
from { -webkit-transform: scale( 1 ) rotate( 0deg ); }
|
||||
to { -webkit-transform: scale( 1 ) rotate( 360deg ); }
|
||||
}
|
||||
|
||||
.icon-rotate {
|
||||
animation-name: rotateThis;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
-webkit-animation-name: rotateThis;
|
||||
-webkit-animation-duration: 2s;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
-webkit-animation-timing-function: linear;
|
||||
}
|
||||
|
||||
.transaction-vin-vout {
|
||||
|
||||
}
|
||||
|
||||
.v_highlight {
|
||||
background-color: #8DC429;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a.v_highlight_more {
|
||||
background-color: #8DC429;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.secondary_navbar {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
left: 0;
|
||||
border: 1px solid #eee;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight',[
|
||||
'ngAnimate',
|
||||
'ngResource',
|
||||
'ngRoute',
|
||||
'ngProgress',
|
||||
'ui.bootstrap',
|
||||
'ui.route',
|
||||
'monospaced.qrcode',
|
||||
'insight.system',
|
||||
'insight.socket',
|
||||
'insight.blocks',
|
||||
'insight.transactions',
|
||||
'insight.address',
|
||||
'insight.search',
|
||||
'insight.status',
|
||||
'insight.connection',
|
||||
'insight.currency'
|
||||
]);
|
||||
|
||||
angular.module('insight.system', []);
|
||||
angular.module('insight.socket', []);
|
||||
angular.module('insight.blocks', []);
|
||||
angular.module('insight.transactions', []);
|
||||
angular.module('insight.address', []);
|
||||
angular.module('insight.search', []);
|
||||
angular.module('insight.status', []);
|
||||
angular.module('insight.connection', []);
|
||||
angular.module('insight.currency', []);
|
||||
@ -1,64 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
//Setting up route
|
||||
angular.module('insight').config(function($routeProvider) {
|
||||
$routeProvider.
|
||||
when('/block/:blockHash', {
|
||||
templateUrl: '/views/block.html',
|
||||
title: 'Bitcoin Block '
|
||||
}).
|
||||
when('/block-index/:blockHeight', {
|
||||
controller: 'BlocksController',
|
||||
templateUrl: '/views/redirect.html'
|
||||
}).
|
||||
when('/tx/:txId/:v_type?/:v_index?', {
|
||||
templateUrl: '/views/transaction.html',
|
||||
title: 'Bitcoin Transaction '
|
||||
}).
|
||||
when('/', {
|
||||
templateUrl: '/views/index.html',
|
||||
title: 'Home'
|
||||
}).
|
||||
when('/blocks', {
|
||||
templateUrl: '/views/block_list.html',
|
||||
title: 'Bitcoin Blocks solved Today'
|
||||
}).
|
||||
when('/blocks-date/:blockDate', {
|
||||
templateUrl: '/views/block_list.html',
|
||||
title: 'Bitcoin Blocks solved '
|
||||
}).
|
||||
when('/address/:addrStr', {
|
||||
templateUrl: '/views/address.html',
|
||||
title: 'Bitcoin Address '
|
||||
}).
|
||||
when('/status', {
|
||||
templateUrl: '/views/status.html',
|
||||
title: 'Status'
|
||||
})
|
||||
.otherwise({
|
||||
templateUrl: '/views/404.html',
|
||||
title: 'Error'
|
||||
});
|
||||
});
|
||||
|
||||
//Setting HTML5 Location Mode
|
||||
angular.module('insight')
|
||||
.config(function($locationProvider) {
|
||||
$locationProvider.html5Mode(true);
|
||||
$locationProvider.hashPrefix('!');
|
||||
})
|
||||
.run(function($rootScope, $route, ngProgress) {
|
||||
$rootScope.$on('$routeChangeStart', function() {
|
||||
ngProgress.start();
|
||||
});
|
||||
|
||||
$rootScope.$on('$routeChangeSuccess', function() {
|
||||
ngProgress.complete();
|
||||
|
||||
//Change page title, based on Route information
|
||||
$rootScope.titleDetail = '';
|
||||
$rootScope.title = $route.current.title;
|
||||
$rootScope.isCollapsed = true;
|
||||
$rootScope.currentAddr = null;
|
||||
});
|
||||
});
|
||||
@ -1,41 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.address').controller('AddressController',
|
||||
function($scope, $rootScope, $routeParams, $location, Global, Address, getSocket) {
|
||||
$scope.global = Global;
|
||||
|
||||
$scope.findOne = function() {
|
||||
$rootScope.currentAddr = $routeParams.addrStr;
|
||||
|
||||
Address.get({
|
||||
addrStr: $routeParams.addrStr
|
||||
},
|
||||
function(address) {
|
||||
$rootScope.titleDetail = address.addrStr.substring(0, 7) + '...';
|
||||
$rootScope.flashMessage = null;
|
||||
$scope.address = address;
|
||||
},
|
||||
function(e) {
|
||||
if (e.status === 400) {
|
||||
$rootScope.flashMessage = 'Invalid Address: ' + $routeParams.addrStr;
|
||||
} else if (e.status === 503) {
|
||||
$rootScope.flashMessage = 'Backend Error. ' + e.data;
|
||||
} else {
|
||||
$rootScope.flashMessage = 'Address Not Found';
|
||||
}
|
||||
$location.path('/');
|
||||
});
|
||||
};
|
||||
|
||||
var socket = getSocket($scope);
|
||||
socket.on('connect', function() {
|
||||
socket.emit('subscribe', $routeParams.addrStr);
|
||||
socket.on($routeParams.addrStr, function(tx) {
|
||||
console.log('AddressTx event received ' + tx);
|
||||
$rootScope.$broadcast('tx', tx);
|
||||
});
|
||||
});
|
||||
|
||||
$scope.params = $routeParams;
|
||||
|
||||
});
|
||||
@ -1,90 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.blocks').controller('BlocksController',
|
||||
function($scope, $rootScope, $routeParams, $location, Global, Block, Blocks, BlockByHeight) {
|
||||
$scope.global = Global;
|
||||
$scope.loading = false;
|
||||
|
||||
if ($routeParams.blockHeight) {
|
||||
BlockByHeight.get({
|
||||
blockHeight: $routeParams.blockHeight
|
||||
}, function(hash) {
|
||||
$location.path('/block/' + hash.blockHash);
|
||||
}, function() {
|
||||
$rootScope.flashMessage = 'Bad Request';
|
||||
$location.path('/');
|
||||
});
|
||||
}
|
||||
|
||||
//Datepicker
|
||||
var _formatTimestamp = function (date) {
|
||||
var yyyy = date.getUTCFullYear().toString();
|
||||
var mm = (date.getUTCMonth() + 1).toString(); // getMonth() is zero-based
|
||||
var dd = date.getUTCDate().toString();
|
||||
|
||||
return yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]); //padding
|
||||
};
|
||||
|
||||
$scope.$watch('dt', function(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
$location.path('/blocks-date/' + _formatTimestamp(newValue));
|
||||
}
|
||||
});
|
||||
|
||||
$scope.openCalendar = function($event) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
|
||||
$scope.opened = true;
|
||||
};
|
||||
|
||||
$scope.humanSince = function(time) {
|
||||
var m = moment.unix(time).startOf('day');
|
||||
var b = moment().startOf('day');
|
||||
return m.max().from(b);
|
||||
};
|
||||
|
||||
|
||||
$scope.list = function() {
|
||||
$scope.loading = true;
|
||||
|
||||
if ($routeParams.blockDate) {
|
||||
$rootScope.titleDetail = 'on ' + $routeParams.blockDate;
|
||||
}
|
||||
|
||||
Blocks.get({
|
||||
blockDate: $routeParams.blockDate
|
||||
}, function(res) {
|
||||
$scope.loading = false;
|
||||
$scope.blocks = res.blocks;
|
||||
$scope.pagination = res.pagination;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.findOne = function() {
|
||||
$scope.loading = true;
|
||||
|
||||
Block.get({
|
||||
blockHash: $routeParams.blockHash
|
||||
}, function(block) {
|
||||
$rootScope.titleDetail = block.height;
|
||||
$rootScope.flashMessage = null;
|
||||
$scope.loading = false;
|
||||
$scope.block = block;
|
||||
}, function(e) {
|
||||
if (e.status === 400) {
|
||||
$rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId;
|
||||
}
|
||||
else if (e.status === 503) {
|
||||
$rootScope.flashMessage = 'Backend Error. ' + e.data;
|
||||
}
|
||||
else {
|
||||
$rootScope.flashMessage = 'Block Not Found';
|
||||
}
|
||||
$location.path('/');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.params = $routeParams;
|
||||
|
||||
});
|
||||
@ -1,53 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.connection').controller('ConnectionController',
|
||||
function($scope, $window, Status, getSocket, PeerSync) {
|
||||
|
||||
// Set initial values
|
||||
$scope.apiOnline = true;
|
||||
$scope.serverOnline = true;
|
||||
$scope.clienteOnline = true;
|
||||
|
||||
var socket = getSocket($scope);
|
||||
|
||||
// Check for the node server connection
|
||||
socket.on('connect', function() {
|
||||
$scope.serverOnline = true;
|
||||
socket.on('disconnect', function() {
|
||||
$scope.serverOnline = false;
|
||||
});
|
||||
});
|
||||
|
||||
// Check for the api connection
|
||||
$scope.getConnStatus = function() {
|
||||
PeerSync.get({},
|
||||
function(peer) {
|
||||
$scope.apiOnline = peer.connected;
|
||||
$scope.host = peer.host;
|
||||
$scope.port = peer.port;
|
||||
},
|
||||
function() {
|
||||
$scope.apiOnline = false;
|
||||
});
|
||||
};
|
||||
|
||||
socket.emit('subscribe', 'sync');
|
||||
socket.on('status', function(sync) {
|
||||
$scope.sync = sync;
|
||||
$scope.apiOnline = (sync.status !== 'aborted' && sync.status !== 'error');
|
||||
});
|
||||
|
||||
// Check for the client conneciton
|
||||
$window.addEventListener('offline', function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.clienteOnline = false;
|
||||
});
|
||||
}, true);
|
||||
|
||||
$window.addEventListener('online', function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.clienteOnline = true;
|
||||
});
|
||||
}, true);
|
||||
|
||||
});
|
||||
@ -1,51 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.currency').controller('CurrencyController',
|
||||
function($scope, $rootScope, Currency) {
|
||||
|
||||
var _roundFloat = function(x, n) {
|
||||
if(!parseInt(n, 10) || !parseFloat(x)) n = 0;
|
||||
|
||||
return Math.round(x * Math.pow(10, n)) / Math.pow(10, n);
|
||||
};
|
||||
|
||||
$rootScope.currency.getConvertion = function(value) {
|
||||
if (typeof value !== 'undefined' && value !== null) {
|
||||
var response;
|
||||
|
||||
if (this.symbol === 'USD') {
|
||||
response = _roundFloat((value * this.factor), 2);
|
||||
} else if (this.symbol === 'mBTC') {
|
||||
this.factor = 1000;
|
||||
response = _roundFloat((value * this.factor), 5);
|
||||
} else {
|
||||
this.factor = 1;
|
||||
response = value;
|
||||
}
|
||||
|
||||
return response + ' ' + this.symbol;
|
||||
}
|
||||
|
||||
return 'value error';
|
||||
};
|
||||
|
||||
$scope.setCurrency = function(currency) {
|
||||
$rootScope.currency.symbol = currency;
|
||||
|
||||
if (currency === 'USD') {
|
||||
Currency.get({}, function(res) {
|
||||
$rootScope.currency.factor = $rootScope.currency.bitstamp = res.data.bitstamp;
|
||||
});
|
||||
} else if (currency === 'mBTC') {
|
||||
$rootScope.currency.factor = 1000;
|
||||
} else {
|
||||
$rootScope.currency.factor = 1;
|
||||
}
|
||||
};
|
||||
|
||||
// Get initial value
|
||||
Currency.get({}, function(res) {
|
||||
$rootScope.currency.bitstamp = res.data.bitstamp;
|
||||
});
|
||||
|
||||
});
|
||||
@ -1,15 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.system').controller('FooterController',
|
||||
function($scope, Version) {
|
||||
|
||||
var _getVersion = function() {
|
||||
Version.get({},
|
||||
function(res) {
|
||||
$scope.version = res.version;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.version = _getVersion();
|
||||
|
||||
});
|
||||
@ -1,40 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.system').controller('HeaderController',
|
||||
function($scope, $rootScope, getSocket, Global, Block) {
|
||||
$scope.global = Global;
|
||||
|
||||
$rootScope.currency = {
|
||||
factor: 1,
|
||||
bitstamp: 0,
|
||||
symbol: 'BTC'
|
||||
};
|
||||
|
||||
$scope.menu = [{
|
||||
'title': 'Blocks',
|
||||
'link': 'blocks'
|
||||
}, {
|
||||
'title': 'Status',
|
||||
'link': 'status'
|
||||
}];
|
||||
|
||||
var _getBlock = function(hash) {
|
||||
Block.get({
|
||||
blockHash: hash
|
||||
}, function(res) {
|
||||
$scope.totalBlocks = res.height;
|
||||
});
|
||||
};
|
||||
|
||||
var socket = getSocket($scope);
|
||||
socket.on('connect', function() {
|
||||
socket.emit('subscribe', 'inv');
|
||||
|
||||
socket.on('block', function(block) {
|
||||
var blockHash = block.toString();
|
||||
_getBlock(blockHash);
|
||||
});
|
||||
});
|
||||
|
||||
$rootScope.isCollapsed = true;
|
||||
});
|
||||
@ -1,47 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var TRANSACTION_DISPLAYED = 10;
|
||||
var BLOCKS_DISPLAYED = 5;
|
||||
|
||||
angular.module('insight.system').controller('IndexController',
|
||||
function($scope, Global, getSocket, Blocks) {
|
||||
$scope.global = Global;
|
||||
|
||||
var _getBlocks = function() {
|
||||
Blocks.get({
|
||||
limit: BLOCKS_DISPLAYED
|
||||
}, function(res) {
|
||||
$scope.blocks = res.blocks;
|
||||
$scope.blocksLength = res.lenght;
|
||||
});
|
||||
};
|
||||
|
||||
var socket = getSocket($scope);
|
||||
socket.on('connect', function() {
|
||||
socket.emit('subscribe', 'inv');
|
||||
|
||||
socket.on('tx', function(tx) {
|
||||
$scope.txs.unshift(tx);
|
||||
if (parseInt($scope.txs.length, 10) >= parseInt(TRANSACTION_DISPLAYED, 10)) {
|
||||
$scope.txs = $scope.txs.splice(0, TRANSACTION_DISPLAYED);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('block', function() {
|
||||
_getBlocks();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$scope.humanSince = function(time) {
|
||||
var m = moment.unix(time);
|
||||
return m.max().fromNow();
|
||||
};
|
||||
|
||||
$scope.index = function() {
|
||||
_getBlocks();
|
||||
};
|
||||
|
||||
$scope.txs = [];
|
||||
$scope.blocks = [];
|
||||
});
|
||||
@ -1,63 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.search').controller('SearchController',
|
||||
function($scope, $routeParams, $location, $timeout, Global, Block, Transaction, Address, BlockByHeight) {
|
||||
$scope.global = Global;
|
||||
$scope.loading = false;
|
||||
|
||||
var _badQuery = function() {
|
||||
$scope.badQuery = true;
|
||||
|
||||
$timeout(function() {
|
||||
$scope.badQuery = false;
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
var _resetSearch = function() {
|
||||
$scope.q = '';
|
||||
$scope.loading = false;
|
||||
};
|
||||
|
||||
$scope.search = function() {
|
||||
var q = $scope.q;
|
||||
$scope.badQuery = false;
|
||||
$scope.loading = true;
|
||||
|
||||
Block.get({
|
||||
blockHash: q
|
||||
}, function() {
|
||||
_resetSearch();
|
||||
$location.path('block/' + q);
|
||||
}, function() { //block not found, search on TX
|
||||
Transaction.get({
|
||||
txId: q
|
||||
}, function() {
|
||||
_resetSearch();
|
||||
$location.path('tx/' + q);
|
||||
}, function() { //tx not found, search on Address
|
||||
Address.get({
|
||||
addrStr: q
|
||||
}, function() {
|
||||
_resetSearch();
|
||||
$location.path('address/' + q);
|
||||
}, function() { // block by height not found
|
||||
if (isFinite(q)) { // ensure that q is a finite number. A logical height value.
|
||||
BlockByHeight.get({
|
||||
blockHeight: q
|
||||
}, function(hash) {
|
||||
_resetSearch();
|
||||
$location.path('/block/' + hash.blockHash);
|
||||
}, function() { //not found, fail :(
|
||||
_badQuery();
|
||||
});
|
||||
}
|
||||
else {
|
||||
$scope.loading = false;
|
||||
_badQuery();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
@ -1,49 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.status').controller('StatusController',
|
||||
function($scope, $routeParams, $location, Global, Status, Sync, getSocket) {
|
||||
$scope.global = Global;
|
||||
|
||||
$scope.getStatus = function(q) {
|
||||
Status.get({
|
||||
q: 'get' + q
|
||||
},
|
||||
function(d) {
|
||||
$scope.loaded = 1;
|
||||
angular.extend($scope, d);
|
||||
},
|
||||
function(e) {
|
||||
$scope.error = 'API ERROR: ' + e.data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.humanSince = function(time) {
|
||||
var m = moment.unix(time / 1000);
|
||||
return m.max().fromNow();
|
||||
};
|
||||
|
||||
var _onSyncUpdate = function(sync) {
|
||||
$scope.sync = sync;
|
||||
};
|
||||
|
||||
$scope.getSync = function() {
|
||||
Sync.get({},
|
||||
function(sync) {
|
||||
_onSyncUpdate(sync);
|
||||
},
|
||||
function(e) {
|
||||
var err = 'Could not get sync information' + e.toString();
|
||||
$scope.sync = {
|
||||
error: err
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
var socket = getSocket($scope);
|
||||
socket.on('connect', function() {
|
||||
socket.emit('subscribe', 'sync');
|
||||
socket.on('status', function(sync) {
|
||||
_onSyncUpdate(sync);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,172 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.transactions').controller('transactionsController',
|
||||
function($scope, $rootScope, $routeParams, $location, Global, Transaction, TransactionsByBlock, TransactionsByAddress) {
|
||||
$scope.global = Global;
|
||||
$scope.loading = false;
|
||||
$scope.loadedBy = null;
|
||||
|
||||
var pageNum = 0;
|
||||
var pagesTotal = 1;
|
||||
var COIN = 100000000;
|
||||
|
||||
var _aggregateItems = function(items) {
|
||||
if (!items) return [];
|
||||
|
||||
var l = items.length;
|
||||
|
||||
var ret = [];
|
||||
var tmp = {};
|
||||
var u = 0;
|
||||
|
||||
for(var i=0; i < l; i++) {
|
||||
|
||||
var notAddr = false;
|
||||
// non standard input
|
||||
if (items[i].scriptSig && !items[i].addr) {
|
||||
items[i].addr = 'Unparsed address [' + u++ + ']';
|
||||
items[i].notAddr = true;
|
||||
notAddr = true;
|
||||
}
|
||||
|
||||
// non standard output
|
||||
if (items[i].scriptPubKey && !items[i].scriptPubKey.addresses) {
|
||||
items[i].scriptPubKey.addresses = ['Unparsed address [' + u++ + ']'];
|
||||
items[i].notAddr = true;
|
||||
notAddr = true;
|
||||
}
|
||||
|
||||
// multiple addr at output
|
||||
if (items[i].scriptPubKey && items[i].scriptPubKey.addresses.length > 1) {
|
||||
items[i].addr = items[i].scriptPubKey.addresses.join(',');
|
||||
ret.push(items[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
var addr = items[i].addr || (items[i].scriptPubKey && items[i].scriptPubKey.addresses[0]);
|
||||
|
||||
if (!tmp[addr]) {
|
||||
tmp[addr] = {};
|
||||
tmp[addr].valueSat = 0;
|
||||
tmp[addr].count = 0;
|
||||
tmp[addr].addr = addr;
|
||||
tmp[addr].items = [];
|
||||
}
|
||||
tmp[addr].isSpent = items[i].spentTxId;
|
||||
|
||||
tmp[addr].doubleSpentTxID = tmp[addr].doubleSpentTxID || items[i].doubleSpentTxID;
|
||||
tmp[addr].doubleSpentIndex = tmp[addr].doubleSpentIndex || items[i].doubleSpentIndex;
|
||||
tmp[addr].unconfirmedInput += items[i].unconfirmedInput;
|
||||
tmp[addr].dbError = tmp[addr].dbError || items[i].dbError;
|
||||
tmp[addr].valueSat += Math.round(items[i].value * COIN);
|
||||
tmp[addr].items.push(items[i]);
|
||||
tmp[addr].notAddr = notAddr;
|
||||
tmp[addr].count++;
|
||||
}
|
||||
|
||||
angular.forEach(tmp, function(v) {
|
||||
v.value = v.value || parseInt(v.valueSat) / COIN;
|
||||
ret.push(v);
|
||||
});
|
||||
return ret;
|
||||
};
|
||||
|
||||
var _processTX = function(tx) {
|
||||
tx.vinSimple = _aggregateItems(tx.vin);
|
||||
tx.voutSimple = _aggregateItems(tx.vout);
|
||||
};
|
||||
|
||||
var _paginate = function(data) {
|
||||
$scope.loading = false;
|
||||
|
||||
pagesTotal = data.pagesTotal;
|
||||
pageNum += 1;
|
||||
|
||||
data.txs.forEach(function(tx) {
|
||||
_processTX(tx);
|
||||
$scope.txs.push(tx);
|
||||
});
|
||||
};
|
||||
|
||||
var _byBlock = function() {
|
||||
TransactionsByBlock.get({
|
||||
block: $routeParams.blockHash,
|
||||
pageNum: pageNum
|
||||
}, function(data) {
|
||||
_paginate(data);
|
||||
});
|
||||
};
|
||||
|
||||
var _byAddress = function () {
|
||||
TransactionsByAddress.get({
|
||||
address: $routeParams.addrStr,
|
||||
pageNum: pageNum
|
||||
}, function(data) {
|
||||
_paginate(data);
|
||||
});
|
||||
};
|
||||
|
||||
var _findTx = function(txid) {
|
||||
Transaction.get({
|
||||
txId: txid
|
||||
}, function(tx) {
|
||||
$rootScope.titleDetail = tx.txid.substring(0,7) + '...';
|
||||
$rootScope.flashMessage = null;
|
||||
$scope.tx = tx;
|
||||
_processTX(tx);
|
||||
$scope.txs.unshift(tx);
|
||||
}, function(e) {
|
||||
if (e.status === 400) {
|
||||
$rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId;
|
||||
}
|
||||
else if (e.status === 503) {
|
||||
$rootScope.flashMessage = 'Backend Error. ' + e.data;
|
||||
}
|
||||
else {
|
||||
$rootScope.flashMessage = 'Transaction Not Found';
|
||||
}
|
||||
|
||||
$location.path('/');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.findThis = function() {
|
||||
_findTx($routeParams.txId);
|
||||
};
|
||||
|
||||
//Initial load
|
||||
$scope.load = function(from) {
|
||||
$scope.loadedBy = from;
|
||||
$scope.loadMore();
|
||||
};
|
||||
|
||||
//Load more transactions for pagination
|
||||
$scope.loadMore = function() {
|
||||
if (pageNum < pagesTotal && !$scope.loading) {
|
||||
$scope.loading = true;
|
||||
|
||||
if ($scope.loadedBy === 'address') {
|
||||
_byAddress();
|
||||
}
|
||||
else {
|
||||
_byBlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Highlighted txout
|
||||
if ($routeParams.v_type == '>' || $routeParams.v_type == '<') {
|
||||
$scope.from_vin = $routeParams.v_type == '<' ? true : false;
|
||||
$scope.from_vout = $routeParams.v_type == '>' ? true : false;
|
||||
$scope.v_index = parseInt($routeParams.v_index);
|
||||
$scope.itemsExpanded = true;
|
||||
}
|
||||
|
||||
//Init without txs
|
||||
$scope.txs = [];
|
||||
|
||||
$scope.$on('tx', function(event, txid) {
|
||||
_findTx(txid);
|
||||
});
|
||||
|
||||
});
|
||||
@ -1,75 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var ZeroClipboard = window.ZeroClipboard;
|
||||
|
||||
angular.module('insight')
|
||||
.directive("scroll", function ($window) {
|
||||
return function(scope, element, attrs) {
|
||||
angular.element($window).bind("scroll", function() {
|
||||
if (this.pageYOffset >= 200) {
|
||||
scope.secondaryNavbar = true;
|
||||
} else {
|
||||
scope.secondaryNavbar = false;
|
||||
}
|
||||
scope.$apply();
|
||||
});
|
||||
};
|
||||
})
|
||||
.directive('whenScrolled', function($window) {
|
||||
return {
|
||||
restric: 'A',
|
||||
link: function(scope, elm, attr) {
|
||||
var pageHeight, clientHeight, scrollPos;
|
||||
$window = angular.element($window);
|
||||
|
||||
var handler = function() {
|
||||
pageHeight = window.document.documentElement.scrollHeight;
|
||||
clientHeight = window.document.documentElement.clientHeight;
|
||||
scrollPos = window.pageYOffset;
|
||||
|
||||
if (pageHeight - (scrollPos + clientHeight) === 0) {
|
||||
scope.$apply(attr.whenScrolled);
|
||||
}
|
||||
};
|
||||
|
||||
$window.on('scroll', handler);
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
return $window.off('scroll', handler);
|
||||
});
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('clipCopy', function() {
|
||||
ZeroClipboard.config({
|
||||
moviePath: '/lib/zeroclipboard/ZeroClipboard.swf',
|
||||
trustedDomains: ['*'],
|
||||
allowScriptAccess: 'always',
|
||||
forceHandCursor: true
|
||||
});
|
||||
|
||||
return {
|
||||
restric: 'A',
|
||||
scope: { clipCopy: '=clipCopy' },
|
||||
template: '<div class="tooltip fade right in"><div class="tooltip-arrow"></div><div class="tooltip-inner">Copied!</div></div>',
|
||||
link: function(scope, elm) {
|
||||
var clip = new ZeroClipboard(elm);
|
||||
|
||||
clip.on('load', function(client) {
|
||||
var onMousedown = function(client) {
|
||||
client.setText(scope.clipCopy);
|
||||
};
|
||||
|
||||
client.on('mousedown', onMousedown);
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
client.off('mousedown', onMousedown);
|
||||
});
|
||||
});
|
||||
|
||||
clip.on('noFlash wrongflash', function() {
|
||||
return elm.remove();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@ -1,9 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight')
|
||||
.filter('startFrom', function() {
|
||||
return function(input, start) {
|
||||
start = +start; //parse to int
|
||||
return input.slice(start);
|
||||
}
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.element(document).ready(function() {
|
||||
// Init the app
|
||||
// angular.bootstrap(document, ['insight']);
|
||||
});
|
||||
@ -1,23 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.address').factory('Address',
|
||||
function($resource) {
|
||||
return $resource('/api/addr/:addrStr', {
|
||||
addrStr: '@addStr'
|
||||
}, {
|
||||
get: {
|
||||
method: 'GET',
|
||||
interceptor: {
|
||||
response: function (res) {
|
||||
return res.data;
|
||||
},
|
||||
responseError: function (res) {
|
||||
if (res.status === 404) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.blocks')
|
||||
.factory('Block',
|
||||
function($resource) {
|
||||
return $resource('/api/block/:blockHash', {
|
||||
blockHash: '@blockHash'
|
||||
}, {
|
||||
get: {
|
||||
method: 'GET',
|
||||
interceptor: {
|
||||
response: function (res) {
|
||||
return res.data;
|
||||
},
|
||||
responseError: function (res) {
|
||||
if (res.status === 404) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.factory('Blocks',
|
||||
function($resource) {
|
||||
return $resource('/api/blocks');
|
||||
})
|
||||
.factory('BlockByHeight',
|
||||
function($resource) {
|
||||
return $resource('/api/block-index/:blockHeight');
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.currency').factory('Currency',
|
||||
function($resource) {
|
||||
return $resource('/api/currency');
|
||||
});
|
||||
@ -1,12 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
//Global service for global variables
|
||||
angular.module('insight.system')
|
||||
.factory('Global',[
|
||||
function() {
|
||||
}
|
||||
])
|
||||
.factory('Version',
|
||||
function($resource) {
|
||||
return $resource('/api/version');
|
||||
});
|
||||
@ -1,71 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var ScopedSocket = function(socket, $rootScope) {
|
||||
this.socket = socket;
|
||||
this.$rootScope = $rootScope;
|
||||
this.listeners = [];
|
||||
};
|
||||
|
||||
ScopedSocket.prototype.removeAllListeners = function(opts) {
|
||||
if (!opts) opts = {};
|
||||
for (var i = 0; i < this.listeners.length; i++) {
|
||||
var details = this.listeners[i];
|
||||
if (opts.skipConnect && details.event === 'connect') {
|
||||
continue;
|
||||
}
|
||||
this.socket.removeListener(details.event, details.fn);
|
||||
}
|
||||
this.listeners = [];
|
||||
};
|
||||
|
||||
ScopedSocket.prototype.on = function(event, callback) {
|
||||
var socket = this.socket;
|
||||
var $rootScope = this.$rootScope;
|
||||
|
||||
var wrapped_callback = function() {
|
||||
var args = arguments;
|
||||
$rootScope.$apply(function() {
|
||||
callback.apply(socket, args);
|
||||
});
|
||||
};
|
||||
socket.on(event, wrapped_callback);
|
||||
|
||||
this.listeners.push({
|
||||
event: event,
|
||||
fn: wrapped_callback
|
||||
});
|
||||
};
|
||||
|
||||
ScopedSocket.prototype.emit = function(event, data, callback) {
|
||||
var socket = this.socket;
|
||||
var $rootScope = this.$rootScope;
|
||||
|
||||
socket.emit(event, data, function() {
|
||||
var args = arguments;
|
||||
$rootScope.$apply(function() {
|
||||
if (callback) {
|
||||
callback.apply(socket, args);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
angular.module('insight.socket').factory('getSocket',
|
||||
function($rootScope) {
|
||||
var socket = io.connect(null, {
|
||||
'reconnect': true,
|
||||
'reconnection delay': 500,
|
||||
});
|
||||
return function(scope) {
|
||||
var scopedSocket = new ScopedSocket(socket, $rootScope);
|
||||
scope.$on('$destroy', function() {
|
||||
scopedSocket.removeAllListeners();
|
||||
});
|
||||
socket.on('connect', function() {
|
||||
scopedSocket.removeAllListeners({
|
||||
skipConnect: true
|
||||
});
|
||||
});
|
||||
return scopedSocket;
|
||||
};
|
||||
});
|
||||
@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.status')
|
||||
.factory('Status',
|
||||
function($resource) {
|
||||
return $resource('/api/status', {
|
||||
q: '@q'
|
||||
});
|
||||
})
|
||||
.factory('Sync',
|
||||
function($resource) {
|
||||
return $resource('/api/sync');
|
||||
})
|
||||
.factory('PeerSync',
|
||||
function($resource) {
|
||||
return $resource('/api/peer');
|
||||
});
|
||||
@ -1,39 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('insight.transactions')
|
||||
.factory('Transaction',
|
||||
function($resource) {
|
||||
return $resource('/api/tx/:txId', {
|
||||
txId: '@txId'
|
||||
}, {
|
||||
get: {
|
||||
method: 'GET',
|
||||
interceptor: {
|
||||
response: function (res) {
|
||||
return res.data;
|
||||
},
|
||||
responseError: function (res) {
|
||||
if (res.status === 404) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.factory('TransactionsByBlock',
|
||||
function($resource) {
|
||||
return $resource('/api/txs', {
|
||||
block: '@block'
|
||||
});
|
||||
})
|
||||
.factory('TransactionsByAddress',
|
||||
function($resource) {
|
||||
return $resource('/api/txs', {
|
||||
address: '@address'
|
||||
});
|
||||
})
|
||||
.factory('Transactions',
|
||||
function($resource) {
|
||||
return $resource('/api/txs');
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||
<div class="jumbotron">
|
||||
<h1>Ooops!</h1>
|
||||
<h2 class="text-muted">404 Page not found :(</h2>
|
||||
<p><a href="/" class="pull-right">Go to home</a></p>
|
||||
</div>
|
||||
@ -1,76 +0,0 @@
|
||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||
<section data-ng-controller="AddressController" data-ng-init="findOne()">
|
||||
<div class="secondary_navbar" scroll data-ng-class="{'hidden': !secondaryNavbar}" data-ng-show="address.addrStr">
|
||||
<div class="row">
|
||||
<div class="col-md-8 text-center">
|
||||
<span class="ellipsis txvalues txvalues-normal">
|
||||
<strong>Address</strong> {{address.addrStr}}
|
||||
<span class="btn-copy" clip-copy="address.addrStr"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<span class="txvalues txvalues-primary"><strong>Final Balance</strong> {{$root.currency.getConvertion(address.balance) || address.balance + ' BTC' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h1>Address <small data-ng-show="address.addrStr">{{$root.currency.getConvertion(address.balance) || address.balance + ' BTC'}}</small></h1>
|
||||
<div class="text-muted" data-ng-if="!address.addrStr">
|
||||
<span>Loading Address Information...</span>
|
||||
</div>
|
||||
<div data-ng-if="address.addrStr">
|
||||
<div class="well well-sm ellipsis">
|
||||
<strong>Address</strong>
|
||||
<span class="text-muted">{{address.addrStr}}</span>
|
||||
<span class="btn-copy" clip-copy="address.addrStr"></span>
|
||||
</div>
|
||||
<h2>Summary <small>confirmed</small></h2>
|
||||
<div class="ng-cloak row" data-ng-hide="!address.addrStr" data-ng-cloak>
|
||||
<div class="col-md-10">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Total Received</strong></td>
|
||||
<td class="ellipsis text-right">{{$root.currency.getConvertion(address.totalReceived) || address.totalReceived + ' BTC'}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Total Sent</strong></td>
|
||||
<td class="ellipsis text-right">{{$root.currency.getConvertion(address.totalSent) || address.totalSent + ' BTC'}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Final Balance</strong></td>
|
||||
<td class="ellipsis text-right">{{$root.currency.getConvertion(address.balance) || address.balance + ' BTC'}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>No. Transactions</strong></td>
|
||||
<td class="ellipsis text-right">{{address.txApperances}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-2 text-center">
|
||||
<qrcode size="160" data="{{address.addrStr}}"></qrcode>
|
||||
</div>
|
||||
</div>
|
||||
<div data-ng-show="address.unconfirmedTxApperances">
|
||||
<h3>Unconfirmed</h3>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="small">Unconfirmed Txs Balance</td>
|
||||
<td class="address ellipsis text-right">{{$root.currency.getConvertion(address.unconfirmedBalance)}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="small">No. Transactions</td>
|
||||
<td class="address ellipsis text-right">{{address.unconfirmedTxApperances}}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Transactions</h2>
|
||||
<div data-ng-controller="transactionsController" data-ng-init="load('address')">
|
||||
<div data-ng-include src="'/views/transaction/list.html'" when-scrolled="loadMore()"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -1,119 +0,0 @@
|
||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||
<section data-ng-controller="BlocksController" data-ng-init="findOne()">
|
||||
<div class="secondary_navbar" scroll data-ng-class="{'hidden': !secondaryNavbar}">
|
||||
<div class="row">
|
||||
<div class="col-md-2 text-right">
|
||||
<span class="ellipsis txvalues txvalues-normal">
|
||||
<a href="/block/{{block.previousblockhash}}">← Previous Block</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-md-8 text-center">
|
||||
<div class="ellipsis txvalues txvalues-normal">
|
||||
<strong>Block</strong> #{{block.height}} ·
|
||||
<strong>Hash</strong> {{block.hash}}
|
||||
<span class="btn-copy" clip-copy="block.hash"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2 text-left">
|
||||
<span class="ellipsis txvalues txvalues-normal">
|
||||
<a href="/block/{{block.nextblockhash}}">Next Block →</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h1>Block #{{block.height}}</h1>
|
||||
<div class="progress progress-striped active" data-ng-if="!block.hash">
|
||||
<div class="progress-bar progress-bar-info" style="width: 100%">
|
||||
<span>Loading Block...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row ng-cloak" data-ng-cloak data-ng-if="block.hash">
|
||||
<div class="well well-sm ellipsis">
|
||||
<strong>BlockHash</strong>
|
||||
<span class="txid text-muted">{{block.hash}}</span>
|
||||
<span class="btn-copy" clip-copy="block.hash"></span>
|
||||
</div>
|
||||
<h2>Summary</h2>
|
||||
<div class="col-md-6">
|
||||
<table class="table" style="table-layout: fixed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Number Of Transactions</strong></td>
|
||||
<td class="text-right text-muted">{{block.tx.length}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Height</strong></td>
|
||||
<td class="text-right text-muted">{{block.height}}
|
||||
<span data-ng-show="block.isMainChain" class="text-success">(Mainchain)</span>
|
||||
<span data-ng-show="!block.isMainChain" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Orphaned)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Block Reward</strong></td>
|
||||
<td class="text-right text-muted">{{$root.currency.getConvertion(block.reward) || block.reward + ' BTC'}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Timestamp</strong></td>
|
||||
<td class="text-right text-muted">{{block.time * 1000 | date:'medium'}}</td>
|
||||
</tr>
|
||||
<tr data-ng-show="block.poolInfo">
|
||||
<td><strong>Mined by</strong></td>
|
||||
<td class="text-right text-muted">
|
||||
<a href="{{block.poolInfo.url}}" target="_blank" title="{{block.poolInfo.poolName}}">{{block.poolInfo.poolName}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Merkle Root</strong></td>
|
||||
<td class="text-right text-muted">
|
||||
<div class="ellipsis">
|
||||
<span class="btn-copy" clip-copy="block.merkleroot"></span>
|
||||
<span>{{block.merkleroot}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-ng-show="block.previousblockhash">
|
||||
<td><strong>Previous Block</strong></td>
|
||||
<td class="text-right"><a href="/block/{{block.previousblockhash}}">{{block.height-1}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td> <strong> Difficulty </strong></td>
|
||||
<td class="text-right text-muted">{{block.difficulty}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <strong> Bits </strong></td>
|
||||
<td class="text-right text-muted">{{block.bits}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <strong> Size (bytes) </strong></td>
|
||||
<td class="text-right text-muted">{{block.size}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <strong> Version </strong></td>
|
||||
<td class="text-right text-muted">{{block.version}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <strong> Nonce </strong></td>
|
||||
<td class="text-right text-muted">{{block.nonce}}</td>
|
||||
</tr>
|
||||
<tr data-ng-show="block.nextblockhash">
|
||||
<td><strong>Next Block</strong></td>
|
||||
<td class="text-right"><a href="/block/{{block.nextblockhash}}">{{block.height+1}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div><!-- END OF ROW -->
|
||||
|
||||
<div data-ng-controller="transactionsController" data-ng-init="load('block')">
|
||||
<h3>Transactions</h3>
|
||||
<div data-ng-include src="'/views/transaction/list.html'" when-scrolled="loadMore()"></div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||
<section data-ng-controller="BlocksController" data-ng-init="list()">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-gray col-gray-fixed">
|
||||
<div class="block-id">
|
||||
<div class="icon-block text-center">
|
||||
<span class="glyphicon glyphicon-list"></span>
|
||||
<h3>Blocks <br> mined on:</h3>
|
||||
</div>
|
||||
</div>
|
||||
<p class="lead text-center m20v">
|
||||
{{pagination.current}} UTC
|
||||
<a href="#" class="btn btn-primary btn-xs" datepicker-popup show-button-bar="false" data-ng-click="openCalendar($event)" data-ng-model="dt" is-open="opened" data-ng-required="true"><span class="glyphicon glyphicon-calendar"></span></a>
|
||||
</p>
|
||||
<div class="m20v text-center text-muted" data-ng-if="!pagination.current">
|
||||
<span>Loading Selected Date...</span>
|
||||
</div>
|
||||
<div class="ng-cloak" data-ng-cloak data-ng-if="pagination.current">
|
||||
<p class="lead text-center m20v" data-ng-show="loading"> </p>
|
||||
<p class="text-center m20v" data-ng-show="pagination.isToday && !loading">Today</p>
|
||||
<p class="text-center m20v" data-ng-show="!pagination.isToday && !loading">{{humanSince(pagination.currentTs)}}
|
||||
<p class="text-center m20v" data-ng-show="loading"> </p>
|
||||
<div class="m50v text-center">
|
||||
<a class="btn btn-primary" href="/blocks-date/{{pagination.prev}}"><small>← {{pagination.prev}}</small></a>
|
||||
<a class="btn btn-primary" href="/blocks-date/{{pagination.next}}" data-ng-show="!pagination.isToday"><small>{{pagination.next}} →</small></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-9 col-md-offset-3">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
Blocks
|
||||
<small>by date</small>
|
||||
</h1>
|
||||
</div>
|
||||
<table class="table table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Height</th>
|
||||
<th>Timestamp</th>
|
||||
<th class="text-right">Transactions</th>
|
||||
<th class="text-right">Mined by</th>
|
||||
<th class="text-right">Size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr data-ng-show="loading">
|
||||
<td colspan="4">Waiting for blocks...</td>
|
||||
</tr>
|
||||
<tr class="fader" data-ng-repeat='b in blocks'>
|
||||
<td><a href="/block/{{b.hash}}">{{b.height}}</a></td>
|
||||
<td>{{b.time * 1000 | date:'medium'}}</td>
|
||||
<td class="text-right">{{b.txlength}}</td>
|
||||
<td class="text-right"><a href="{{b.poolInfo.url}}" title="{{b.poolInfo.poolName}}" target="_blank" data-ng-show="b.poolInfo">{{b.poolInfo.poolName}}</a></td>
|
||||
<td class="text-right">{{b.size}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="text-center text-muted" data-ng-show="!blocks.length && !loading">No blocks yet.</h2>
|
||||
</section>
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
<div class="connection-status container" data-ng-controller="ConnectionController">
|
||||
|
||||
<div class="alert alert-danger"
|
||||
data-ng-show="!serverOnline || !clienteOnline || !apiOnline"
|
||||
data-ng-init="getConnStatus()">
|
||||
|
||||
<strong>Error!</strong>
|
||||
|
||||
<p data-ng-show="!apiOnline">
|
||||
Can't connect to bitcoind to get live updates from the p2p network.
|
||||
(Tried connecting to bitcoind at {{host}}:{{port}} and failed.)
|
||||
</p>
|
||||
|
||||
<p data-ng-show="!serverOnline">
|
||||
Can't connect to insight server. Attempting to reconnect...
|
||||
</p>
|
||||
|
||||
<p data-ng-show="!clienteOnline">
|
||||
Can't connect to internet. Please, check your connection.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -1,15 +0,0 @@
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
{{currency.symbol}} <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#" data-ng-click="setCurrency('USD')" data-ng-class="{active: currency.symbol == 'USD'}">USD</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-ng-click="setCurrency('BTC')" data-ng-class="{active: currency.symbol == 'BTC'}">BTC</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-ng-click="setCurrency('mBTC')" data-ng-class="{active: currency.symbol == 'mBTC'}">mBTC</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
<div class="container" data-ng-controller="FooterController">
|
||||
<a class="insight m10v pull-right" href="/">insight <small>API v{{version}}</small></a>
|
||||
</div>
|
||||
@ -1,49 +0,0 @@
|
||||
<div class="container">
|
||||
<div data-ng-controller="HeaderController">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" data-ng-click="$root.isCollapsed = !$root.isCollapsed">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="insight navbar-brand" href="/">insight</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" collapse="$root.isCollapsed">
|
||||
<ul class="nav navbar-nav">
|
||||
<li data-ng-repeat="item in menu" ui-route="/{{item.link}}" data-ng-class="{active: $uiRoute}">
|
||||
<a href="/{{item.link}}">{{item.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form data-ng-controller="SearchController" class="navbar-form navbar-left" role="search" data-ng-submit="search()">
|
||||
<div class="form-group" data-ng-class="{'has-error': badQuery}">
|
||||
<input id="search" type="text" class="form-control" data-ng-model="q" data-ng-class="{'loading': loading}" placeholder="Search for block, transaction or address">
|
||||
</div>
|
||||
<div class="no_matching text-danger" data-ng-show="badQuery">No matching records found!</div>
|
||||
</form>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<div class="status" data-ng-controller="StatusController">
|
||||
<div data-ng-init="getSync()" class="pull-left">
|
||||
<span class="t text-danger" data-ng-show="sync.error" tooltip="{{sync.error}}" tooltip-placement="bottom">
|
||||
<span class="glyphicon glyphicon-warning-sign"></span>
|
||||
ERROR
|
||||
</span>
|
||||
<span class="t" tooltip="{{sync.syncedBlocks}} / {{sync.blockChainHeight}} synced. {{sync.skippedBlocks}} skipped" tooltip-placement="bottom" data-ng-show="sync.status==='syncing'">
|
||||
<span class="glyphicon glyphicon-refresh icon-rotate"></span>
|
||||
{{sync.status}} {{sync.syncPercentage}}%
|
||||
</span>
|
||||
<span class="t text-default" tooltip="Historic sync finished" tooltip-placement="bottom" data-ng-show="sync.status==='finished'"> Synched </span>
|
||||
</div>
|
||||
·
|
||||
<span data-ng-init="getStatus('Info')">
|
||||
<strong>Conn</strong> {{info.connections}}
|
||||
</span> ·
|
||||
<strong>Height</strong> {{totalBlocks || info.blocks}}
|
||||
</div>
|
||||
</li>
|
||||
<li class="dropdown" data-ng-controller="CurrencyController" data-ng-include src="'/views/includes/currency.html'"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,4 +0,0 @@
|
||||
<span class="text-warning" data-ng-show="!loaded && !error">Loading...</span>
|
||||
<span class="text-danger" data-ng-show="error">{{error}}</span>
|
||||
|
||||
|
||||
@ -1,80 +0,0 @@
|
||||
<div class="alert alert-danger" data-ng-show="flashMessage">
|
||||
{{$root.flashMessage}}
|
||||
</div>
|
||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||
<section data-ng-controller="IndexController" data-ng-init="index()">
|
||||
<div class="container">
|
||||
<div id="home" class="row">
|
||||
<div class="col-xs-12 col-md-8">
|
||||
<h1>Latest Blocks</h1>
|
||||
<table class="table table-hover table-striped" style="table-layout: fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Height</th>
|
||||
<th>Age</th>
|
||||
<th class="text-right"><span class="ellipsis">Transactions</span></th>
|
||||
<th class="text-right"><span class="ellipsis">Mined by</span></th>
|
||||
<th class="text-right">Size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr data-ng-show="!blocks.length"><td colspan="4">Waiting for blocks...</td></tr>
|
||||
<tr class="fader" data-ng-repeat='b in blocks'>
|
||||
<td>
|
||||
<a href="/block/{{b.hash}}">{{b.height}}</a>
|
||||
</td>
|
||||
<td><span class="ellipsis">{{humanSince(b.time)}}</span></td>
|
||||
<td class="text-right">{{b.txlength}}</td>
|
||||
<td class="text-right"><a href="{{b.poolInfo.url}}" title="{{b.poolInfo.poolName}}" target="_blank" data-ng-show="b.poolInfo">{{b.poolInfo.poolName}}</a></td>
|
||||
<td class="text-right">{{b.size}} bytes</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="btn-more">
|
||||
<a href="/blocks" class="btn btn-default">See all blocks</a>
|
||||
</div>
|
||||
|
||||
<h2>Latest Transactions</h2>
|
||||
|
||||
<table class="table table-hover table-striped" style="table-layout: fixed;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Hash</th>
|
||||
<th class="text-right">Size</th>
|
||||
<th class="text-right">Value Out</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr data-ng-show="!txs.length"><td colspan="3">Waiting for transactions...</td></tr>
|
||||
<tr class="fader" data-ng-repeat='tx in txs'>
|
||||
<td>
|
||||
<a class="ellipsis" href="/tx/{{tx.txid}}">{{tx.txid}}</a>
|
||||
</td>
|
||||
<td class="text-right"><span class="ellipsis">{{tx.size}} bytes</span></td>
|
||||
<td class="text-right"><span class="ellipsis">{{tx.valueOut}} BTC</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-4 col-gray">
|
||||
<h2> About </h2>
|
||||
<p><strong>insight</strong> is an <a href="http://insight.bitcore.io/" target="_blank">open-source Bitcoin blockchain explorer</a> with complete REST
|
||||
and websocket APIs that can be used for writing web wallets and other apps
|
||||
that need more advanced blockchain queries than provided by bitcoind RPC.
|
||||
Check out the <a href="http://github.com/bitpay/insight" target="_blank">source code</a>.</p>
|
||||
<p><strong>insight</strong> is still in development, so be sure to report any bugs and provide feedback for improvement at our <a href="https://github.com/bitpay/insight/issues" target="_blank">github issue tracker</a>.</p>
|
||||
<div id="powered" class="row">
|
||||
<div class="powered-text">
|
||||
<small class="text-muted">Powered by</small>
|
||||
</div>
|
||||
<a href="http://bitcore.io" target="_blank" class="bitcore" title="Bitcore"></a>
|
||||
<a href="http://angularjs.org" target="_blank" class="angularjs" title="AngularJS"></a>
|
||||
<a href="https://code.google.com/p/leveldb/" target="_blank" class="leveldb" title="LevelDB"></a>
|
||||
<a href="http://nodejs.org" target="_blank" class="nodejs" title="NodeJs"></a>
|
||||
</div>
|
||||
</div> <!-- END OF COL-3 -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -1 +0,0 @@
|
||||
<div class="text-center">Redirecting...</div>
|
||||
@ -1,165 +0,0 @@
|
||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||
<section>
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
Application Status
|
||||
</h1>
|
||||
</div>
|
||||
<div id="status" class="row">
|
||||
|
||||
<div class="col-xs-12 col-md-8">
|
||||
<h2>Sync Status</h2>
|
||||
<table class="table" data-ng-controller="StatusController" data-ng-init="getSync()">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Sync Progress</td>
|
||||
<td>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: {{ sync.syncPercentage}}%">
|
||||
<span data-ng-show="sync.syncPercentage>0">{{sync.syncPercentage}}% Complete</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Sync Status</td>
|
||||
<td class="text-right">
|
||||
<span data-ng-show="!sync.error">{{sync.status}}</span>
|
||||
<span class="text-danger" data-ng-show="sync.error">
|
||||
<span class="glyphicon glyphicon-warning-sign"></span>
|
||||
{{sync.error}}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Start Date</td>
|
||||
<td class="text-right"><time title="{{sync.startTs | date:'medium'}}">{{humanSince(sync.startTs)}}</time></td>
|
||||
</tr>
|
||||
<tr data-ng-show="sync.endTs">
|
||||
<td>Finish Date</td>
|
||||
<td class="text-right"><time title="{{sync.startTs | date:'medium'}}" >{{humanSince(sync.endTs)}}</time></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Initial Block Chain Height</td>
|
||||
<td class="text-right">{{sync.blockChainHeight}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Synced Blocks</td>
|
||||
<td class="text-right">{{sync.syncedBlocks}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Skipped Blocks (previously synced)</td>
|
||||
<td class="text-right">{{sync.skippedBlocks}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sync Type</td>
|
||||
<td class="text-right">{{sync.type}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Last Block</h2>
|
||||
<table class="table" style="table-layout: fixed" data-ng-controller="StatusController" data-ng-init="getStatus('LastBlockHash')">
|
||||
<thead data-ng-include src="'/views/includes/infoStatus.html'"></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Last Block Hash (Bitcoind)</td>
|
||||
<td class="text-right ellipsis"><a href="/block/{{lastblockhash}}">{{lastblockhash}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Blockchain Tip (insight)</td>
|
||||
<td class="text-right ellipsis"><a href="/block/{{syncTipHash}}">{{syncTipHash}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Transaction Output Set Information</h2>
|
||||
<div data-ng-controller="StatusController">
|
||||
<button data-ng-click="txoutLoading=1;getStatus('TxOutSetInfo')" class="btn btn-default" data-ng-show="!txoutsetinfo.height">
|
||||
Show Transaction Output data
|
||||
<span data-ng-show="txoutLoading" class="glyphicon glyphicon-refresh icon-rotate"></span>
|
||||
</button >
|
||||
|
||||
<table class="table" data-ng-show="txoutsetinfo.height" style="table-layout: fixed" >
|
||||
<thead data-ng-include src="'/views/includes/infoStatus.html'"></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Height</td>
|
||||
<td class="text-right"><a href="/block-index/{{txoutsetinfo.height}}">{{txoutsetinfo.height}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Best Block</td>
|
||||
<td class="text-right ellipsis"><a href="/block/{{txoutsetinfo.bestblock}}">{{txoutsetinfo.bestblock}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transactions</td>
|
||||
<td class="text-right"> {{txoutsetinfo.transactions}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transaction Outputs</td>
|
||||
<td class="text-right">{{txoutsetinfo.txouts}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bytes Serialized</td>
|
||||
<td class="text-right">{{txoutsetinfo.bytes_serialized}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hash Serialized</td>
|
||||
<td class="text-right ellipsis">{{txoutsetinfo.hash_serialized}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total Amount</td>
|
||||
<td class="text-right">{{txoutsetinfo.total_amount}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div> <!-- END OF COL-8 -->
|
||||
|
||||
<div class="col-xs-12 col-md-4 col-gray">
|
||||
<h2>Bitcoin node information</h2>
|
||||
<table class="table" data-ng-controller="StatusController" data-ng-init="getStatus('Info')">
|
||||
<thead data-ng-include src="'/views/includes/infoStatus.html'"></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Version</td>
|
||||
<td class="text-right">{{info.version}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Protocol version</td>
|
||||
<td class="text-right">{{info.protocolversion}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Blocks</td>
|
||||
<td class="text-right"><a href="/block-index/{{info.blocks}}">{{info.blocks}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time Offset</td>
|
||||
<td class="text-right">{{info.timeoffset}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Connections to other nodes</td>
|
||||
<td class="text-right">{{info.connections}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mining Difficulty</td>
|
||||
<td class="text-right">{{info.difficulty}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Testnet</td>
|
||||
<td class="text-right">{{info.testnet}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Proxy setting</td>
|
||||
<td class="text-right">{{info.proxy}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Info Errors</td>
|
||||
<td class="text-right">{{info.infoErrors}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div> <!-- END OF COL-GRAY -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||
<section data-ng-controller="transactionsController" data-ng-init="findThis()">
|
||||
<div class="secondary_navbar" scroll data-ng-class="{'hidden': !secondaryNavbar}">
|
||||
<div class="row">
|
||||
<div class="col-md-8 text-center">
|
||||
<span class="ellipsis txvalues txvalues-normal">
|
||||
<strong>Transaction</strong> {{tx.txid}}
|
||||
<span class="btn-copy" clip-copy="tx.txid"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<span data-ng-show="tx.confirmations" class="txvalues txvalues-success">{{tx.confirmations}} Confirmations</span>
|
||||
<span data-ng-show="!tx.confirmations" class="txvalues txvalues-danger">Unconfirmed Transaction!</span>
|
||||
<span class="txvalues txvalues-primary">{{$root.currency.getConvertion(tx.valueOut) || tx.valueOut + ' BTC' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ng-cloak" data-ng-cloak data-ng-if="tx.txid">
|
||||
<h1>Transaction
|
||||
<small data-ng-show="from_vin || from_vout">
|
||||
<span data-ng-show="from_vin">Input</span>
|
||||
<span data-ng-show="from_vout">Output</span>
|
||||
<span>{{v_index}}</span>
|
||||
</small>
|
||||
</h1>
|
||||
<div class="progress progress-striped active" data-ng-if="!tx.txid">
|
||||
<div class="progress-bar progress-bar-info" style="width: 100%">
|
||||
<span>Loading Transaction Details...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div data-ng-if="tx.txid">
|
||||
<div class="well well-sm ellipsis">
|
||||
<strong>Transaction</strong>
|
||||
<span class="txid text-muted">{{tx.txid}}</span>
|
||||
<span class="btn-copy" clip-copy="tx.txid"></span>
|
||||
</div>
|
||||
<h2>Summary</h2>
|
||||
<table class="table" style="table-layout: fixed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong> Size </strong></td>
|
||||
<td class="text-muted text-right">{{tx.size}} (bytes)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Received Time </strong></td>
|
||||
<td data-ng-show="tx.firstSeenTs" class="text-muted text-right">{{tx.firstSeenTs * 1000|date:'medium'}}</td>
|
||||
<td data-ng-show="!tx.firstSeenTs" class="text-muted text-right">N/A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Mined Time </strong></td>
|
||||
<td data-ng-show="tx.time" class="text-muted text-right">{{tx.time * 1000|date:'medium'}}</td>
|
||||
<td data-ng-show="!tx.time" class="text-muted text-right">N/A</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h2>Details</h2>
|
||||
<div class="block-tx ng-cloak" data-ng-cloak data-ng-if="tx.txid">
|
||||
<div data-ng-include src="'/views/transaction/tx.html'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
<div class="alert alert-warning" data-ng-show="!txs[0].txid && !loading">There are not transactions involving this address.</div>
|
||||
<div class="block-tx" data-ng-show="txs && txs[0].txid" data-ng-repeat="tx in txs">
|
||||
<div data-ng-include src="'/views/transaction/tx.html'"></div>
|
||||
</div>
|
||||
<div class="progress progress-striped active" data-ng-show="loading">
|
||||
<div class="progress-bar progress-bar-info" style="width: 100%">
|
||||
<span>Loading Transactions...</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,185 +0,0 @@
|
||||
<div class="line-bot row ng-cloak" data-ng-hide="!tx" data-ng-cloak>
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="ellipsis">
|
||||
<a class="btn-expand" href="#" title="Show/Hide items details" data-ng-click="itemsExpanded = !itemsExpanded">
|
||||
<span class="glyphicon glyphicon-plus-sign" data-ng-class="{'glyphicon-minus-sign': itemsExpanded}"></span>
|
||||
</a>
|
||||
<a class="txid" href="/tx/{{tx.txid}}">{{tx.txid}}</a>
|
||||
<span class="btn-copy" clip-copy="tx.txid"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 text-right">
|
||||
<div data-ng-show="tx.firstSeenTs">
|
||||
first seen at
|
||||
<time>{{tx.firstSeenTs * 1000 | date:'medium'}}</time>
|
||||
</div>
|
||||
<div data-ng-show="tx.time && !tx.firstSeenTs">
|
||||
mined at
|
||||
<time>{{tx.time * 1000 | date:'medium'}}</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row line-mid">
|
||||
<div class="col-md-5">
|
||||
<div class="row" data-ng-if="tx.isCoinBase">
|
||||
<div class="col-md-12 transaction-vin-vout" data-ng-repeat="vin in tx.vin">
|
||||
<div class="ellipsis">
|
||||
<span>No Inputs (Newly Generated Coins)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" data-ng-if="!tx.isCoinBase">
|
||||
|
||||
<!-- Simple view -->
|
||||
<div data-ng-if="!itemsExpanded" data-ng-init="currentInNoExpanded=0; sizeInNoExpanded=5">
|
||||
<div data-ng-repeat="vin in tx.vinSimple| startFrom:currentInNoExpanded*sizeInNoExpanded | limitTo:sizeInNoExpanded">
|
||||
<div class="col-md-12 transaction-vin-vout">
|
||||
<div class="pull-right btc-value" data-ng-class="{'text-danger': $root.currentAddr == vin.addr}"><p>{{$root.currency.getConvertion(vin.value) || vin.value + ' BTC'}}</p></div>
|
||||
<div class="ellipsis">
|
||||
<span data-ng-show="vin.notAddr">{{vin.addr}}</span>
|
||||
<span class="text-muted" title="Current Bitcoin Address" data-ng-show="vin.addr == $root.currentAddr">{{vin.addr}}</span>
|
||||
<a href="/address/{{vin.addr}}" data-ng-show="!vin.notAddr && vin.addr != $root.currentAddr">{{vin.addr}}</a>
|
||||
</div>
|
||||
<div data-ng-show="vin.unconfirmedInput" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Input unconfirmed)</div>
|
||||
<div data-ng-show="vin.dbError" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Incoherence in levelDB detected, please resync</div>
|
||||
<div data-ng-show="vin.doubleSpentTxID" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Double spent attempt detected. From tx:
|
||||
<a href="/tx/{{vin.doubleSpentTxID}}">{{vin.doubleSpentTxID}},{{vin.doubleSpentIndex}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="showmore_collapse text-right" data-ng-show="tx.vinSimple.length > 5" data-ng-class="{ 'hidden': itemsExpanded}">
|
||||
<a href="#" ng-hide="sizeInNoExpanded != tx.vinSimple.length" ng-click="currentInNoExpanded=0; sizeInNoExpanded=5"><small>...less</small></a>
|
||||
<a href="#" ng-hide="currentInNoExpanded >= tx.vinSimple.length/sizeInNoExpanded - 1" ng-click="currentInNoExpanded=0; sizeInNoExpanded=tx.vinSimple.length"><small>more...</small></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Full view -->
|
||||
<div data-ng-if="itemsExpanded" data-ng-init="currentInExpanded=0; sizeInExpanded=(from_vin) ? tx.vin.length : 5; fromVinCollapsed=(from_vin)">
|
||||
<a href="#" data-ng-show="(from_vin) && tx.vin.length > 1" data-ng-class="{'text-muted': fromVinCollapsed}" data-ng-click="currentInExpanded=0; sizeInExpanded=tx.vin.length;fromVinCollapsed=1"><small>show input {{ v_index }}</small></a>
|
||||
<a href="#" data-ng-show="(from_vin) && tx.vin.length > 1" data-ng-class="{'text-muted': !fromVinCollapsed}" data-ng-click="currentInExpanded=0; sizeInExpanded=tx.vin.length;fromVinCollapsed=0"><small>show all</small></a>
|
||||
<div data-ng-repeat="vin in tx.vin| startFrom:currentInExpanded*sizeInExpanded | limitTo:sizeInExpanded" data-ng-if="fromVinCollapsed ? v_index == vin.n : 1">
|
||||
<div class="col-md-12 transaction-vin-vout">
|
||||
<div class="pull-right btc-value"><p>{{$root.currency.getConvertion(vin.value) || vin.value + ' BTC'}}</p></div>
|
||||
<div class="ellipsis">
|
||||
<a class="glyphicon glyphicon-chevron-right" href="/tx/{{vin.txid}}/>/{{vin.vout}}" title="Outpoint: {{vin.txid}},{{vin.vout}}"></a>
|
||||
<span data-ng-show="vin.notAddr">{{vin.addr}}</span>
|
||||
<a href="/address/{{vin.addr}}" data-ng-show="!vin.notAddr">{{vin.addr}}</a>
|
||||
</div>
|
||||
<div data-ng-show="vin.unconfirmedInput" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Input unconfirmed)</div>
|
||||
<div data-ng-show="vin.dbError" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Incoherence in levelDB detected, please resync</div>
|
||||
<div data-ng-show="vin.doubleSpentTxID" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> Double spent attempt detected. From tx:
|
||||
<a href="/tx/{{vin.doubleSpentTxID}}">{{vin.doubleSpentTxID}},{{vin.doubleSpentIndex}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" style="word-wrap:break-word" data-ng-class="{true: 'v_highlight', false: ''}[from_vin == true && v_index == vin.n]">
|
||||
<small>
|
||||
<strong>scriptSig</strong>
|
||||
{{vin.scriptSig.asm}}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="showmore_collapse text-right" data-ng-show="tx.vin.length > 5 && !fromVinCollapsed" data-ng-class="{ 'hidden': !itemsExpanded}">
|
||||
<a href="#" ng-hide="sizeInExpanded != tx.vin.length" ng-click="currentInExpanded=0; sizeInExpanded=5"><small>...less</small></a>
|
||||
<a href="#" data-ng-class="{true: 'v_highlight_more', false: ''}[from_vin == true && v_index > 5]" ng-hide="currentInExpanded >= tx.vin.length/sizeInExpanded - 1" ng-click="currentInExpanded=0; sizeInExpanded=tx.vin.length"><small>more...</small></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1 col-xs-12">
|
||||
<div class="hidden-xs hidden-sm text-center">
|
||||
<span class="glyphicon glyphicon-chevron-right text-primary"></span>
|
||||
</div>
|
||||
<div class="hidden-md hidden-lg text-center">
|
||||
<span class="glyphicon glyphicon-chevron-down text-primary"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
|
||||
<!-- Simple view -->
|
||||
<div data-ng-if="!itemsExpanded" data-ng-init="currentOutNoExpanded=0; sizeOutNoExpanded=5">
|
||||
<div data-ng-repeat="vout in tx.voutSimple| startFrom:currentOutNoExpanded*sizeOutNoExpanded | limitTo:sizeOutNoExpanded">
|
||||
<div class="col-md-12 transaction-vin-vout">
|
||||
<div class="pull-right btc-value" data-ng-class="{'text-success': $root.currentAddr == vout.addr}">
|
||||
|
||||
<p>
|
||||
{{$root.currency.getConvertion(vout.value) || vout.value + ' BTC' }}
|
||||
<span class="text-danger" data-ng-show="vout.isSpent" tooltip="Output is spent" tooltip-placement="left">(S)</span>
|
||||
<span class="text-success" data-ng-show="!vout.isSpent" tooltip="Output is unspent" tooltip-placement="left">(U)</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="ellipsis">
|
||||
<span data-ng-show="vout.notAddr">{{vout.addr}}</span>
|
||||
<span class="text-muted" title="Current Bitcoin Address" data-ng-show="address == $root.currentAddr" data-ng-repeat="address in vout.addr.split(',')">{{vout.addr}}</span>
|
||||
<a href="/address/{{address}}" data-ng-show="!vout.notAddr && address != $root.currentAddr" data-ng-repeat="address in vout.addr.split(',')">{{address}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="showmore_collapse text-right" data-ng-show="tx.voutSimple.length > 5" data-ng-class="{ 'hidden': itemsExpanded}">
|
||||
<a href="#" ng-hide="sizeOutNoExpanded != tx.voutSimple.length" ng-click="currentOutNoExpanded=0; sizeOutNoExpanded=5"><small>...less</small></a>
|
||||
<a href="#" ng-hide="currentOutNoExpanded >= tx.voutSimple.length/sizeOutNoExpanded - 1" ng-click="currentOutNoExpanded=0; sizeOutNoExpanded=tx.voutSimple.length"><small>more...</small></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Full view -->
|
||||
<div data-ng-if="itemsExpanded" data-ng-init="currentOutExpanded=0; sizeOutExpanded=(from_vout) ? tx.vout.length : 5; fromVoutCollapsed=(from_vout)">
|
||||
<a href="#" data-ng-show="(from_vout) && tx.vout.length > 1" data-ng-class="{'text-muted': fromVoutCollapsed}" data-ng-click="currentOutExpanded=0; sizeOutExpanded=tx.vout.length;fromVoutCollapsed=1"><small>show output {{ v_index }}</small></a>
|
||||
<a href="#" data-ng-show="(from_vout) && tx.vout.length > 1" data-ng-class="{'text-muted': !fromVoutCollapsed}" data-ng-click="currentOutExpanded=0; sizeOutExpanded=tx.vout.length;fromVoutCollapsed=0"><small>show all</small></a>
|
||||
<div data-ng-repeat="vout in tx.vout| startFrom:currentOutExpanded*sizeOutExpanded | limitTo:sizeOutExpanded" data-ng-if="fromVoutCollapsed ? v_index == vout.n : 1">
|
||||
<div class="col-md-12 transaction-vin-vout">
|
||||
<div class="pull-right btc-value">
|
||||
<p>{{$root.currency.getConvertion(vout.value) || vout.value + ' BTC'}}
|
||||
<span class="text-success" data-ng-show="!vout.spentTxId" tooltip="Output is unspent" tooltip-placement="left">(U)</span>
|
||||
<a class="glyphicon glyphicon-chevron-right" data-ng-show="vout.spentTxId" href="/tx/{{vout.spentTxId}}/</{{vout.spentIndex}}" title="Spent at: {{vout.spentTxId}},{{vout.spentIndex}}"></a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="ellipsis">
|
||||
<a href="/address/{{address}}" data-ng-repeat="address in vout.scriptPubKey.addresses">{{address}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" style="word-wrap:break-word" data-ng-class="{true: 'v_highlight', false: ''}[from_vout == true && v_index == vout.n]">
|
||||
<small>
|
||||
<p>
|
||||
<strong>Type</strong>
|
||||
{{vout.scriptPubKey.type}}
|
||||
</p>
|
||||
<p>
|
||||
<strong>scriptPubKey</strong>
|
||||
{{vout.scriptPubKey.asm}}
|
||||
</p>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="showmore_collapse text-right" data-ng-show="tx.vout.length > 5 && !fromVoutCollapsed" data-ng-class="{ 'hidden': !itemsExpanded}">
|
||||
<a href="#" ng-hide="sizeOutExpanded != tx.vout.length" ng-click="currentOutExpanded=0; sizeOutExpanded=5"><small>...less</small></a>
|
||||
<a href="#" data-ng-class="{true: 'v_highlight_more', false: ''}[from_vout == true && v_index > 5]" ng-hide="currentOutExpanded >= tx.vout.length/sizeOutExpanded - 1" ng-click="currentOutExpanded=0; sizeOutExpanded=tx.vout.length"><small>more...</small></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="well well-sm bgwhite ellipsis" data-ng-if="itemsExpanded && !block.hash">
|
||||
<strong>BlockHash</strong> <a class="text-muted" href="/block/{{tx.blockhash}}">{{tx.blockhash}}</a>
|
||||
<span class="btn-copy" clip-copy="tx.blockhash"></span>
|
||||
</div>
|
||||
|
||||
<div class="line-top row ng-cloak" data-ng-hide="!tx" data-ng-cloak>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4">
|
||||
<span data-ng-show="!tx.isCoinBase && !isNaN(parseFloat(tx.fees))" class="txvalues txvalues-default">Fees: {{$root.currency.getConvertion(tx.fees) || tx.fees + 'BTC'}} </span>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-8 col-md-8 text-right">
|
||||
<span data-ng-show="tx.confirmations" class="txvalues txvalues-success">{{tx.confirmations}} Confirmations</span>
|
||||
<span data-ng-show="!tx.confirmations" class="txvalues txvalues-danger">Unconfirmed Transaction!</span>
|
||||
<span class="txvalues txvalues-primary">{{$root.currency.getConvertion(tx.valueOut) || tx.valueOut + ' BTC' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in New Issue
Block a user