diff --git a/public/js/main.min.js b/public/js/main.min.js index 86a4fb1..ff64882 100644 --- a/public/js/main.min.js +++ b/public/js/main.min.js @@ -1,2 +1,2 @@ /*! insight-bitcore 0.2.1 */ -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",[]),angular.module("insight.address").controller("AddressController",function($scope,$rootScope,$routeParams,$location,Global,Address,getSocket){$scope.global=Global;var socket=getSocket($scope),_startSocket=function(){socket.emit("subscribe",$routeParams.addrStr),socket.on($routeParams.addrStr,function(tx){$rootScope.$broadcast("tx",tx);var beep=new Audio("/sound/transaction.mp3");beep.play()})};socket.on("connect",function(){_startSocket()}),$scope.params=$routeParams,$scope.findOne=function(){$rootScope.currentAddr=$routeParams.addrStr,_startSocket(),Address.get({addrStr:$routeParams.addrStr},function(address){$rootScope.titleDetail=address.addrStr.substring(0,7)+"...",$rootScope.flashMessage=null,$scope.address=address},function(e){$rootScope.flashMessage=400===e.status?"Invalid Address: "+$routeParams.addrStr:503===e.status?"Backend Error. "+e.data:"Address Not Found",$location.path("/")})}}),angular.module("insight.blocks").controller("BlocksController",function($scope,$rootScope,$routeParams,$location,Global,Block,Blocks,BlockByHeight){$scope.global=Global,$scope.loading=!1,$routeParams.blockHeight&&BlockByHeight.get({blockHeight:$routeParams.blockHeight},function(hash){$location.path("/block/"+hash.blockHash)},function(){$rootScope.flashMessage="Bad Request",$location.path("/")});var _formatTimestamp=function(date){var yyyy=date.getUTCFullYear().toString(),mm=(date.getUTCMonth()+1).toString(),dd=date.getUTCDate().toString();return yyyy+"-"+(mm[1]?mm:"0"+mm[0])+"-"+(dd[1]?dd:"0"+dd[0])};$scope.$watch("dt",function(newValue,oldValue){newValue!==oldValue&&$location.path("/blocks-date/"+_formatTimestamp(newValue))}),$scope.openCalendar=function($event){$event.preventDefault(),$event.stopPropagation(),$scope.opened=!0},$scope.humanSince=function(time){var m=moment.unix(time).startOf("day"),b=moment().startOf("day");return m.max().from(b)},$scope.list=function(){$scope.loading=!0,$routeParams.blockDate&&($rootScope.titleDetail="on "+$routeParams.blockDate),Blocks.get({blockDate:$routeParams.blockDate},function(res){$scope.loading=!1,$scope.blocks=res.blocks,$scope.pagination=res.pagination})},$scope.findOne=function(){$scope.loading=!0,Block.get({blockHash:$routeParams.blockHash},function(block){$rootScope.titleDetail=block.height,$rootScope.flashMessage=null,$scope.loading=!1,$scope.block=block},function(e){$rootScope.flashMessage=400===e.status?"Invalid Transaction ID: "+$routeParams.txId:503===e.status?"Backend Error. "+e.data:"Block Not Found",$location.path("/")})},$scope.params=$routeParams}),angular.module("insight.connection").controller("ConnectionController",function($scope,$window,Status,getSocket,PeerSync){$scope.apiOnline=!0,$scope.serverOnline=!0,$scope.clienteOnline=!0;var socket=getSocket($scope);socket.on("connect",function(){$scope.serverOnline=!0,socket.on("disconnect",function(){$scope.serverOnline=!1})}),$scope.getConnStatus=function(){PeerSync.get({},function(peer){$scope.apiOnline=peer.connected,$scope.host=peer.host,$scope.port=peer.port},function(){$scope.apiOnline=!1})},socket.emit("subscribe","sync"),socket.on("status",function(sync){$scope.sync=sync,$scope.apiOnline="aborted"!==sync.status&&"error"!==sync.status}),$window.addEventListener("offline",function(){$scope.$apply(function(){$scope.clienteOnline=!1})},!0),$window.addEventListener("online",function(){$scope.$apply(function(){$scope.clienteOnline=!0})},!0)}),angular.module("insight.currency").controller("CurrencyController",function($scope,$rootScope,Currency){var _roundFloat=function(x,n){return parseInt(n,10)&&parseFloat(x)||(n=0),Math.round(x*Math.pow(10,n))/Math.pow(10,n)};$rootScope.currency.getConvertion=function(value){if(value=1*value,!isNaN(value)&&"undefined"!=typeof value&&null!==value){if(0===value)return"0 "+this.symbol;var response;return"USD"===this.symbol?response=_roundFloat(value*this.factor,2):"mBTC"===this.symbol?(this.factor=1e3,response=_roundFloat(value*this.factor,5)):(this.factor=1,response=value),1e-7>response&&(response=response.toFixed(8)),response+" "+this.symbol}return"value error"},$scope.setCurrency=function(currency){$rootScope.currency.symbol=currency,"USD"===currency?Currency.get({},function(res){$rootScope.currency.factor=$rootScope.currency.bitstamp=res.data.bitstamp}):$rootScope.currency.factor="mBTC"===currency?1e3:1},Currency.get({},function(res){$rootScope.currency.bitstamp=res.data.bitstamp})}),angular.module("insight.system").controller("FooterController",function($scope,Version){var _getVersion=function(){Version.get({},function(res){$scope.version=res.version})};$scope.version=_getVersion()}),angular.module("insight.system").controller("HeaderController",function($scope,$rootScope,$modal,getSocket,Global,Block){$scope.global=Global,$rootScope.currency={factor:1,bitstamp:0,symbol:"BTC"},$scope.menu=[{title:"Blocks",link:"blocks"},{title:"Status",link:"status"}],$scope.openScannerModal=function(){$modal.open({templateUrl:"scannerModal.html",controller:"ScannerController"})};var _getBlock=function(hash){Block.get({blockHash:hash},function(res){$scope.totalBlocks=res.height})},socket=getSocket($scope);socket.on("connect",function(){socket.emit("subscribe","inv"),socket.on("block",function(block){var blockHash=block.toString();_getBlock(blockHash)})}),$rootScope.isCollapsed=!0});var TRANSACTION_DISPLAYED=10,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})},socket=getSocket($scope),_startSocket=function(){socket.emit("subscribe","inv"),socket.on("tx",function(tx){$scope.txs.unshift(tx),parseInt($scope.txs.length,10)>=parseInt(TRANSACTION_DISPLAYED,10)&&($scope.txs=$scope.txs.splice(0,TRANSACTION_DISPLAYED))}),socket.on("block",function(){_getBlocks()})};socket.on("connect",function(){_startSocket()}),$scope.humanSince=function(time){var m=moment.unix(time);return m.max().fromNow()},$scope.index=function(){_getBlocks(),_startSocket()},$scope.txs=[],$scope.blocks=[]}),angular.module("insight.system").controller("ScannerController",function($scope,$rootScope,$modalInstance,Global){$scope.global=Global;var isMobile={Android:function(){return navigator.userAgent.match(/Android/i)},BlackBerry:function(){return navigator.userAgent.match(/BlackBerry/i)},iOS:function(){return navigator.userAgent.match(/iPhone|iPad|iPod/i)},Opera:function(){return navigator.userAgent.match(/Opera Mini/i)},Windows:function(){return navigator.userAgent.match(/IEMobile/i)},any:function(){return isMobile.Android()||isMobile.BlackBerry()||isMobile.iOS()||isMobile.Opera()||isMobile.Windows()}};navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia,window.URL=window.URL||window.webkitURL||window.mozURL||window.msURL,$scope.isMobile=isMobile.any(),$scope.scannerLoading=!1;var cameraInput,video,canvas,$video,context,localMediaStream,$searchInput=angular.element(document.getElementById("search")),_scan=function(evt){if($scope.isMobile){$scope.scannerLoading=!0;var files=evt.target.files;if(1===files.length&&0===files[0].type.indexOf("image/")){var file=files[0],reader=new FileReader;reader.onload=function(){return function(){var mpImg=new MegaPixImage(file);mpImg.render(canvas,{maxWidth:200,maxHeight:200,orientation:6}),setTimeout(function(){qrcode.width=canvas.width,qrcode.height=canvas.height,qrcode.imagedata=context.getImageData(0,0,qrcode.width,qrcode.height);try{qrcode.decode()}catch(e){alert(e)}},1500)}}(file),reader.readAsDataURL(file)}}else{if(localMediaStream){context.drawImage(video,0,0,300,225);try{qrcode.decode()}catch(e){}}setTimeout(_scan,500)}},_successCallback=function(stream){video.src=window.URL&&window.URL.createObjectURL(stream)||stream,localMediaStream=stream,video.play(),setTimeout(_scan,1e3)},_scanStop=function(){$scope.scannerLoading=!1,$modalInstance.close(),$scope.isMobile||(localMediaStream.stop&&localMediaStream.stop(),localMediaStream=null,video.src="")},_videoError=function(err){console.log("Video Error: "+JSON.stringify(err)),_scanStop()};qrcode.callback=function(data){_scanStop();var str=0===data.indexOf("bitcoin:")?data.substring(8):data;console.log("QR code detected: "+str),$searchInput.val(str).triggerHandler("change").triggerHandler("submit")},$scope.cancel=function(){_scanStop()},$modalInstance.opened.then(function(){$rootScope.isCollapsed=!0,setTimeout(function(){canvas=document.getElementById("qr-canvas"),context=canvas.getContext("2d"),$scope.isMobile?(cameraInput=document.getElementById("qrcode-camera"),cameraInput.addEventListener("change",_scan,!1)):(video=document.getElementById("qrcode-scanner-video"),$video=angular.element(video),canvas.width=300,canvas.height=225,context.clearRect(0,0,300,225),navigator.getUserMedia({video:!0},_successCallback,_videoError))},500)})}),angular.module("insight.search").controller("SearchController",function($scope,$routeParams,$location,$timeout,Global,Block,Transaction,Address,BlockByHeight){$scope.global=Global,$scope.loading=!1;var _badQuery=function(){$scope.badQuery=!0,$timeout(function(){$scope.badQuery=!1},2e3)},_resetSearch=function(){$scope.q="",$scope.loading=!1};$scope.search=function(){var q=$scope.q;$scope.badQuery=!1,$scope.loading=!0,Block.get({blockHash:q},function(){_resetSearch(),$location.path("block/"+q)},function(){Transaction.get({txId:q},function(){_resetSearch(),$location.path("tx/"+q)},function(){Address.get({addrStr:q},function(){_resetSearch(),$location.path("address/"+q)},function(){isFinite(q)?BlockByHeight.get({blockHeight:q},function(hash){_resetSearch(),$location.path("/block/"+hash.blockHash)},function(){_badQuery()}):($scope.loading=!1,_badQuery())})})})}}),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/1e3);return m.max().fromNow()};var _onSyncUpdate=function(sync){$scope.sync=sync},_startSocket=function(){socket.emit("subscribe","sync"),socket.on("status",function(sync){_onSyncUpdate(sync)})},socket=getSocket($scope);socket.on("connect",function(){_startSocket()}),$scope.getSync=function(){_startSocket(),Sync.get({},function(sync){_onSyncUpdate(sync)},function(e){var err="Could not get sync information"+e.toString();$scope.sync={error:err}})}}),angular.module("insight.transactions").controller("transactionsController",function($scope,$rootScope,$routeParams,$location,Global,Transaction,TransactionsByBlock,TransactionsByAddress){$scope.global=Global,$scope.loading=!1,$scope.loadedBy=null;var pageNum=0,pagesTotal=1,COIN=1e8,_aggregateItems=function(items){if(!items)return[];for(var l=items.length,ret=[],tmp={},u=0,i=0;l>i;i++){var notAddr=!1;if(items[i].scriptSig&&!items[i].addr&&(items[i].addr="Unparsed address ["+u++ +"]",items[i].notAddr=!0,notAddr=!0),items[i].scriptPubKey&&!items[i].scriptPubKey.addresses&&(items[i].scriptPubKey.addresses=["Unparsed address ["+u++ +"]"],items[i].notAddr=!0,notAddr=!0),items[i].scriptPubKey&&items[i].scriptPubKey.addresses.length>1)items[i].addr=items[i].scriptPubKey.addresses.join(","),ret.push(items[i]);else{var addr=items[i].addr||items[i].scriptPubKey&&items[i].scriptPubKey.addresses[0];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++}}return angular.forEach(tmp,function(v){v.value=v.value||parseInt(v.valueSat)/COIN,ret.push(v)}),ret},_processTX=function(tx){tx.vinSimple=_aggregateItems(tx.vin),tx.voutSimple=_aggregateItems(tx.vout)},_paginate=function(data){$scope.loading=!1,pagesTotal=data.pagesTotal,pageNum+=1,data.txs.forEach(function(tx){_processTX(tx),$scope.txs.push(tx)})},_byBlock=function(){TransactionsByBlock.get({block:$routeParams.blockHash,pageNum:pageNum},function(data){_paginate(data)})},_byAddress=function(){TransactionsByAddress.get({address:$routeParams.addrStr,pageNum:pageNum},function(data){_paginate(data)})},_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){$rootScope.flashMessage=400===e.status?"Invalid Transaction ID: "+$routeParams.txId:503===e.status?"Backend Error. "+e.data:"Transaction Not Found",$location.path("/")})};$scope.findThis=function(){_findTx($routeParams.txId)},$scope.load=function(from){$scope.loadedBy=from,$scope.loadMore()},$scope.loadMore=function(){pagesTotal>pageNum&&!$scope.loading&&($scope.loading=!0,"address"===$scope.loadedBy?_byAddress():_byBlock())},(">"==$routeParams.v_type||"<"==$routeParams.v_type)&&($scope.from_vin="<"==$routeParams.v_type?!0:!1,$scope.from_vout=">"==$routeParams.v_type?!0:!1,$scope.v_index=parseInt($routeParams.v_index),$scope.itemsExpanded=!0),$scope.txs=[],$scope.$on("tx",function(event,txid){_findTx(txid)})}),angular.module("insight.address").factory("Address",function($resource){return $resource("/api/addr/:addrStr/?noTxList=1",{addrStr:"@addStr"},{get:{method:"GET",interceptor:{response:function(res){return res.data},responseError:function(res){return 404===res.status?res:void 0}}}})}),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){return 404===res.status?res:void 0}}}})}).factory("Blocks",function($resource){return $resource("/api/blocks")}).factory("BlockByHeight",function($resource){return $resource("/api/block-index/:blockHeight")}),angular.module("insight.currency").factory("Currency",function($resource){return $resource("/api/currency")}),angular.module("insight.system").factory("Global",[function(){}]).factory("Version",function($resource){return $resource("/api/version")});var ScopedSocket=function(socket,$rootScope){this.socket=socket,this.$rootScope=$rootScope,this.listeners=[]};ScopedSocket.prototype.removeAllListeners=function(opts){opts||(opts={});for(var i=0;i=200?!0:!1,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,pageHeight-(scrollPos+clientHeight)===0&&scope.$apply(attr.whenScrolled)};$window.on("scroll",handler),scope.$on("$destroy",function(){return $window.off("scroll",handler)})}}}).directive("clipCopy",function(){return ZeroClipboard.config({moviePath:"/lib/zeroclipboard/ZeroClipboard.swf",trustedDomains:["*"],allowScriptAccess:"always",forceHandCursor:!0}),{restric:"A",scope:{clipCopy:"=clipCopy"},template:'
Copied!
',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()})}}}),angular.module("insight").filter("startFrom",function(){return function(input,start){return start=+start,input.slice(start)}}).filter("split",function(){return function(input,delimiter){var delimiter=delimiter||",";return input.split(delimiter)}}),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"})}),angular.module("insight").config(function($locationProvider){$locationProvider.html5Mode(!0),$locationProvider.hashPrefix("!")}).run(function($rootScope,$route,$location,$routeParams,$anchorScroll,ngProgress){$rootScope.$on("$routeChangeStart",function(){ngProgress.start()}),$rootScope.$on("$routeChangeSuccess",function(){ngProgress.complete(),$rootScope.titleDetail="",$rootScope.title=$route.current.title,$rootScope.isCollapsed=!0,$rootScope.currentAddr=null,$location.hash($routeParams.scrollTo),$anchorScroll()})}),angular.element(document).ready(function(){}); \ No newline at end of file +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",[]),angular.module("insight.address").controller("AddressController",function($scope,$rootScope,$routeParams,$location,Global,Address,getSocket){$scope.global=Global;var socket=getSocket($scope),_startSocket=function(){socket.emit("subscribe",$routeParams.addrStr),socket.on($routeParams.addrStr,function(tx){$rootScope.$broadcast("tx",tx);var beep=new Audio("/sound/transaction.mp3");beep.play()})};socket.on("connect",function(){_startSocket()}),$scope.params=$routeParams,$scope.findOne=function(){$rootScope.currentAddr=$routeParams.addrStr,_startSocket(),Address.get({addrStr:$routeParams.addrStr},function(address){$rootScope.titleDetail=address.addrStr.substring(0,7)+"...",$rootScope.flashMessage=null,$scope.address=address},function(e){$rootScope.flashMessage=400===e.status?"Invalid Address: "+$routeParams.addrStr:503===e.status?"Backend Error. "+e.data:"Address Not Found",$location.path("/")})}}),angular.module("insight.blocks").controller("BlocksController",function($scope,$rootScope,$routeParams,$location,Global,Block,Blocks,BlockByHeight){$scope.global=Global,$scope.loading=!1,$routeParams.blockHeight&&BlockByHeight.get({blockHeight:$routeParams.blockHeight},function(hash){$location.path("/block/"+hash.blockHash)},function(){$rootScope.flashMessage="Bad Request",$location.path("/")});var _formatTimestamp=function(date){var yyyy=date.getUTCFullYear().toString(),mm=(date.getUTCMonth()+1).toString(),dd=date.getUTCDate().toString();return yyyy+"-"+(mm[1]?mm:"0"+mm[0])+"-"+(dd[1]?dd:"0"+dd[0])};$scope.$watch("dt",function(newValue,oldValue){newValue!==oldValue&&$location.path("/blocks-date/"+_formatTimestamp(newValue))}),$scope.openCalendar=function($event){$event.preventDefault(),$event.stopPropagation(),$scope.opened=!0},$scope.humanSince=function(time){var m=moment.unix(time).startOf("day"),b=moment().startOf("day");return m.max().from(b)},$scope.list=function(){if($scope.loading=!0,$routeParams.blockDate&&($scope.detail="On "+$routeParams.blockDate),$routeParams.startTimestamp){var d=new Date(1e3*$routeParams.startTimestamp),m=d.getMinutes();10>m&&(m="0"+m),$scope.before=" before "+d.getHours()+":"+m}$rootScope.titleDetail=$scope.detail,Blocks.get({blockDate:$routeParams.blockDate,startTimestamp:$routeParams.startTimestamp},function(res){$scope.loading=!1,$scope.blocks=res.blocks,$scope.pagination=res.pagination})},$scope.findOne=function(){$scope.loading=!0,Block.get({blockHash:$routeParams.blockHash},function(block){$rootScope.titleDetail=block.height,$rootScope.flashMessage=null,$scope.loading=!1,$scope.block=block},function(e){$rootScope.flashMessage=400===e.status?"Invalid Transaction ID: "+$routeParams.txId:503===e.status?"Backend Error. "+e.data:"Block Not Found",$location.path("/")})},$scope.params=$routeParams}),angular.module("insight.connection").controller("ConnectionController",function($scope,$window,Status,getSocket,PeerSync){$scope.apiOnline=!0,$scope.serverOnline=!0,$scope.clienteOnline=!0;var socket=getSocket($scope);socket.on("connect",function(){$scope.serverOnline=!0,socket.on("disconnect",function(){$scope.serverOnline=!1})}),$scope.getConnStatus=function(){PeerSync.get({},function(peer){$scope.apiOnline=peer.connected,$scope.host=peer.host,$scope.port=peer.port},function(){$scope.apiOnline=!1})},socket.emit("subscribe","sync"),socket.on("status",function(sync){$scope.sync=sync,$scope.apiOnline="aborted"!==sync.status&&"error"!==sync.status}),$window.addEventListener("offline",function(){$scope.$apply(function(){$scope.clienteOnline=!1})},!0),$window.addEventListener("online",function(){$scope.$apply(function(){$scope.clienteOnline=!0})},!0)}),angular.module("insight.currency").controller("CurrencyController",function($scope,$rootScope,Currency){var _roundFloat=function(x,n){return parseInt(n,10)&&parseFloat(x)||(n=0),Math.round(x*Math.pow(10,n))/Math.pow(10,n)};$rootScope.currency.getConvertion=function(value){if(value=1*value,!isNaN(value)&&"undefined"!=typeof value&&null!==value){if(0===value)return"0 "+this.symbol;var response;return"USD"===this.symbol?response=_roundFloat(value*this.factor,2):"mBTC"===this.symbol?(this.factor=1e3,response=_roundFloat(value*this.factor,5)):(this.factor=1,response=value),1e-7>response&&(response=response.toFixed(8)),response+" "+this.symbol}return"value error"},$scope.setCurrency=function(currency){$rootScope.currency.symbol=currency,"USD"===currency?Currency.get({},function(res){$rootScope.currency.factor=$rootScope.currency.bitstamp=res.data.bitstamp}):$rootScope.currency.factor="mBTC"===currency?1e3:1},Currency.get({},function(res){$rootScope.currency.bitstamp=res.data.bitstamp})}),angular.module("insight.system").controller("FooterController",function($scope,Version){var _getVersion=function(){Version.get({},function(res){$scope.version=res.version})};$scope.version=_getVersion()}),angular.module("insight.system").controller("HeaderController",function($scope,$rootScope,$modal,getSocket,Global,Block){$scope.global=Global,$rootScope.currency={factor:1,bitstamp:0,symbol:"BTC"},$scope.menu=[{title:"Blocks",link:"blocks"},{title:"Status",link:"status"}],$scope.openScannerModal=function(){$modal.open({templateUrl:"scannerModal.html",controller:"ScannerController"})};var _getBlock=function(hash){Block.get({blockHash:hash},function(res){$scope.totalBlocks=res.height})},socket=getSocket($scope);socket.on("connect",function(){socket.emit("subscribe","inv"),socket.on("block",function(block){var blockHash=block.toString();_getBlock(blockHash)})}),$rootScope.isCollapsed=!0});var TRANSACTION_DISPLAYED=10,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})},socket=getSocket($scope),_startSocket=function(){socket.emit("subscribe","inv"),socket.on("tx",function(tx){$scope.txs.unshift(tx),parseInt($scope.txs.length,10)>=parseInt(TRANSACTION_DISPLAYED,10)&&($scope.txs=$scope.txs.splice(0,TRANSACTION_DISPLAYED))}),socket.on("block",function(){_getBlocks()})};socket.on("connect",function(){_startSocket()}),$scope.humanSince=function(time){var m=moment.unix(time);return m.max().fromNow()},$scope.index=function(){_getBlocks(),_startSocket()},$scope.txs=[],$scope.blocks=[]}),angular.module("insight.system").controller("ScannerController",function($scope,$rootScope,$modalInstance,Global){$scope.global=Global;var isMobile={Android:function(){return navigator.userAgent.match(/Android/i)},BlackBerry:function(){return navigator.userAgent.match(/BlackBerry/i)},iOS:function(){return navigator.userAgent.match(/iPhone|iPad|iPod/i)},Opera:function(){return navigator.userAgent.match(/Opera Mini/i)},Windows:function(){return navigator.userAgent.match(/IEMobile/i)},any:function(){return isMobile.Android()||isMobile.BlackBerry()||isMobile.iOS()||isMobile.Opera()||isMobile.Windows()}};navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia,window.URL=window.URL||window.webkitURL||window.mozURL||window.msURL,$scope.isMobile=isMobile.any(),$scope.scannerLoading=!1;var cameraInput,video,canvas,$video,context,localMediaStream,$searchInput=angular.element(document.getElementById("search")),_scan=function(evt){if($scope.isMobile){$scope.scannerLoading=!0;var files=evt.target.files;if(1===files.length&&0===files[0].type.indexOf("image/")){var file=files[0],reader=new FileReader;reader.onload=function(){return function(){var mpImg=new MegaPixImage(file);mpImg.render(canvas,{maxWidth:200,maxHeight:200,orientation:6}),setTimeout(function(){qrcode.width=canvas.width,qrcode.height=canvas.height,qrcode.imagedata=context.getImageData(0,0,qrcode.width,qrcode.height);try{qrcode.decode()}catch(e){alert(e)}},1500)}}(file),reader.readAsDataURL(file)}}else{if(localMediaStream){context.drawImage(video,0,0,300,225);try{qrcode.decode()}catch(e){}}setTimeout(_scan,500)}},_successCallback=function(stream){video.src=window.URL&&window.URL.createObjectURL(stream)||stream,localMediaStream=stream,video.play(),setTimeout(_scan,1e3)},_scanStop=function(){$scope.scannerLoading=!1,$modalInstance.close(),$scope.isMobile||(localMediaStream.stop&&localMediaStream.stop(),localMediaStream=null,video.src="")},_videoError=function(err){console.log("Video Error: "+JSON.stringify(err)),_scanStop()};qrcode.callback=function(data){_scanStop();var str=0===data.indexOf("bitcoin:")?data.substring(8):data;console.log("QR code detected: "+str),$searchInput.val(str).triggerHandler("change").triggerHandler("submit")},$scope.cancel=function(){_scanStop()},$modalInstance.opened.then(function(){$rootScope.isCollapsed=!0,setTimeout(function(){canvas=document.getElementById("qr-canvas"),context=canvas.getContext("2d"),$scope.isMobile?(cameraInput=document.getElementById("qrcode-camera"),cameraInput.addEventListener("change",_scan,!1)):(video=document.getElementById("qrcode-scanner-video"),$video=angular.element(video),canvas.width=300,canvas.height=225,context.clearRect(0,0,300,225),navigator.getUserMedia({video:!0},_successCallback,_videoError))},500)})}),angular.module("insight.search").controller("SearchController",function($scope,$routeParams,$location,$timeout,Global,Block,Transaction,Address,BlockByHeight){$scope.global=Global,$scope.loading=!1;var _badQuery=function(){$scope.badQuery=!0,$timeout(function(){$scope.badQuery=!1},2e3)},_resetSearch=function(){$scope.q="",$scope.loading=!1};$scope.search=function(){var q=$scope.q;$scope.badQuery=!1,$scope.loading=!0,Block.get({blockHash:q},function(){_resetSearch(),$location.path("block/"+q)},function(){Transaction.get({txId:q},function(){_resetSearch(),$location.path("tx/"+q)},function(){Address.get({addrStr:q},function(){_resetSearch(),$location.path("address/"+q)},function(){isFinite(q)?BlockByHeight.get({blockHeight:q},function(hash){_resetSearch(),$location.path("/block/"+hash.blockHash)},function(){_badQuery()}):($scope.loading=!1,_badQuery())})})})}}),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/1e3);return m.max().fromNow()};var _onSyncUpdate=function(sync){$scope.sync=sync},_startSocket=function(){socket.emit("subscribe","sync"),socket.on("status",function(sync){_onSyncUpdate(sync)})},socket=getSocket($scope);socket.on("connect",function(){_startSocket()}),$scope.getSync=function(){_startSocket(),Sync.get({},function(sync){_onSyncUpdate(sync)},function(e){var err="Could not get sync information"+e.toString();$scope.sync={error:err}})}}),angular.module("insight.transactions").controller("transactionsController",function($scope,$rootScope,$routeParams,$location,Global,Transaction,TransactionsByBlock,TransactionsByAddress){$scope.global=Global,$scope.loading=!1,$scope.loadedBy=null;var pageNum=0,pagesTotal=1,COIN=1e8,_aggregateItems=function(items){if(!items)return[];for(var l=items.length,ret=[],tmp={},u=0,i=0;l>i;i++){var notAddr=!1;if(items[i].scriptSig&&!items[i].addr&&(items[i].addr="Unparsed address ["+u++ +"]",items[i].notAddr=!0,notAddr=!0),items[i].scriptPubKey&&!items[i].scriptPubKey.addresses&&(items[i].scriptPubKey.addresses=["Unparsed address ["+u++ +"]"],items[i].notAddr=!0,notAddr=!0),items[i].scriptPubKey&&items[i].scriptPubKey.addresses.length>1)items[i].addr=items[i].scriptPubKey.addresses.join(","),ret.push(items[i]);else{var addr=items[i].addr||items[i].scriptPubKey&&items[i].scriptPubKey.addresses[0];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++}}return angular.forEach(tmp,function(v){v.value=v.value||parseInt(v.valueSat)/COIN,ret.push(v)}),ret},_processTX=function(tx){tx.vinSimple=_aggregateItems(tx.vin),tx.voutSimple=_aggregateItems(tx.vout)},_paginate=function(data){$scope.loading=!1,pagesTotal=data.pagesTotal,pageNum+=1,data.txs.forEach(function(tx){_processTX(tx),$scope.txs.push(tx)})},_byBlock=function(){TransactionsByBlock.get({block:$routeParams.blockHash,pageNum:pageNum},function(data){_paginate(data)})},_byAddress=function(){TransactionsByAddress.get({address:$routeParams.addrStr,pageNum:pageNum},function(data){_paginate(data)})},_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){$rootScope.flashMessage=400===e.status?"Invalid Transaction ID: "+$routeParams.txId:503===e.status?"Backend Error. "+e.data:"Transaction Not Found",$location.path("/")})};$scope.findThis=function(){_findTx($routeParams.txId)},$scope.load=function(from){$scope.loadedBy=from,$scope.loadMore()},$scope.loadMore=function(){pagesTotal>pageNum&&!$scope.loading&&($scope.loading=!0,"address"===$scope.loadedBy?_byAddress():_byBlock())},(">"==$routeParams.v_type||"<"==$routeParams.v_type)&&($scope.from_vin="<"==$routeParams.v_type?!0:!1,$scope.from_vout=">"==$routeParams.v_type?!0:!1,$scope.v_index=parseInt($routeParams.v_index),$scope.itemsExpanded=!0),$scope.txs=[],$scope.$on("tx",function(event,txid){_findTx(txid)})}),angular.module("insight.address").factory("Address",function($resource){return $resource("/api/addr/:addrStr/?noTxList=1",{addrStr:"@addStr"},{get:{method:"GET",interceptor:{response:function(res){return res.data},responseError:function(res){return 404===res.status?res:void 0}}}})}),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){return 404===res.status?res:void 0}}}})}).factory("Blocks",function($resource){return $resource("/api/blocks")}).factory("BlockByHeight",function($resource){return $resource("/api/block-index/:blockHeight")}),angular.module("insight.currency").factory("Currency",function($resource){return $resource("/api/currency")}),angular.module("insight.system").factory("Global",[function(){}]).factory("Version",function($resource){return $resource("/api/version")});var ScopedSocket=function(socket,$rootScope){this.socket=socket,this.$rootScope=$rootScope,this.listeners=[]};ScopedSocket.prototype.removeAllListeners=function(opts){opts||(opts={});for(var i=0;i=200?!0:!1,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,pageHeight-(scrollPos+clientHeight)===0&&scope.$apply(attr.whenScrolled)};$window.on("scroll",handler),scope.$on("$destroy",function(){return $window.off("scroll",handler)})}}}).directive("clipCopy",function(){return ZeroClipboard.config({moviePath:"/lib/zeroclipboard/ZeroClipboard.swf",trustedDomains:["*"],allowScriptAccess:"always",forceHandCursor:!0}),{restric:"A",scope:{clipCopy:"=clipCopy"},template:'
Copied!
',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()})}}}),angular.module("insight").filter("startFrom",function(){return function(input,start){return start=+start,input.slice(start)}}).filter("split",function(){return function(input,delimiter){var delimiter=delimiter||",";return input.split(delimiter)}}),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/:startTimestamp?",{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"})}),angular.module("insight").config(function($locationProvider){$locationProvider.html5Mode(!0),$locationProvider.hashPrefix("!")}).run(function($rootScope,$route,$location,$routeParams,$anchorScroll,ngProgress){$rootScope.$on("$routeChangeStart",function(){ngProgress.start()}),$rootScope.$on("$routeChangeSuccess",function(){ngProgress.complete(),$rootScope.titleDetail="",$rootScope.title=$route.current.title,$rootScope.isCollapsed=!0,$rootScope.currentAddr=null,$location.hash($routeParams.scrollTo),$anchorScroll()})}),angular.element(document).ready(function(){}); \ No newline at end of file diff --git a/public/src/js/config.js b/public/src/js/config.js index 4131cd7..3af0b02 100644 --- a/public/src/js/config.js +++ b/public/src/js/config.js @@ -23,7 +23,7 @@ angular.module('insight').config(function($routeProvider) { templateUrl: '/views/block_list.html', title: 'Bitcoin Blocks solved Today' }). - when('/blocks-date/:blockDate', { + when('/blocks-date/:blockDate/:startTimestamp?', { templateUrl: '/views/block_list.html', title: 'Bitcoin Blocks solved ' }). diff --git a/public/src/js/controllers/blocks.js b/public/src/js/controllers/blocks.js index b96d576..4660672 100644 --- a/public/src/js/controllers/blocks.js +++ b/public/src/js/controllers/blocks.js @@ -49,11 +49,21 @@ angular.module('insight.blocks').controller('BlocksController', $scope.loading = true; if ($routeParams.blockDate) { - $rootScope.titleDetail = 'on ' + $routeParams.blockDate; + $scope.detail = 'On ' + $routeParams.blockDate; } + if ($routeParams.startTimestamp) { + var d=new Date($routeParams.startTimestamp*1000); + var m=d.getMinutes(); + if (m<10) m = '0' + m; + $scope.before = ' before ' + d.getHours() + ':' + m; + } + + $rootScope.titleDetail = $scope.detail; + Blocks.get({ - blockDate: $routeParams.blockDate + blockDate: $routeParams.blockDate, + startTimestamp: $routeParams.startTimestamp }, function(res) { $scope.loading = false; $scope.blocks = res.blocks; diff --git a/public/views/block_list.html b/public/views/block_list.html index b7c3378..5675e5b 100644 --- a/public/views/block_list.html +++ b/public/views/block_list.html @@ -30,7 +30,7 @@ @@ -56,6 +56,10 @@
+
+ Lastest block from date + Older blocks from this date +

No blocks yet.