diff --git a/README.md b/README.md index f9b12b9..025aa2c 100644 --- a/README.md +++ b/README.md @@ -103,22 +103,30 @@ $ npm install -g bower A REST API is provided at /api. The entry points are: -### Blocks +### Block ``` /api/block/[:hash] /api/block/00000000a967199a2fad0877433c93df785a8d8ce062e5f9b451cd1397bdbf62 ``` -### Transactions +### Transaction ``` /api/tx/[:txid] /api/tx/525de308971eabd941b139f46c7198b5af9479325c2395db7f2fb5ae8562556c ``` -### Addresses +### Addresse ``` /api/addr/[:addr] /api/addr/mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5 ``` - +### Transactions by Block +``` + /api/txs/?block=HASH + /api/txs/?block=00000000fa6cf7367e50ad14eb0ca4737131f256fc4c5841fd3c3f140140e6b6 +``` +### Transactions by Address +``` + /api/txs/?address=ADDR + /api/txs/?address=mmhmMNfBiZZ37g1tgg2t8DDbNoEdqKVxAL ## Web Socket API The web socket API is served using [socket.io](http://socket.io) at: diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js index caa66f1..8146d04 100644 --- a/app/controllers/transactions.js +++ b/app/controllers/transactions.js @@ -2,6 +2,9 @@ var Transaction = require('../models/Transaction'); +var Block = require('../models/Block'); +var Address = require('../models/Address'); +var async = require('async'); //, _ = require('lodash'); @@ -38,3 +41,50 @@ exports.show = function(req, res) { } }; +var getTransaction = function(txid, cb) { + Transaction.fromIdWithInfo(txid, function(err, tx) { + if (err) { + console.log(err); + return cb(err); + } + return cb(null, tx.info); + }); +}; + +exports.transactions = function(req, res, next) { + var bId = req.query.block; + var aId = req.query.address; + + if (bId) { + Block.fromHashWithInfo(bId, function(err, block) { + if (err && !block) { + console.log(err); + res.status(404).send('Not found'); + return next(); + } + + async.mapSeries(block.info.tx, getTransaction, + function(err, results) { + res.jsonp(results); + }); + }); + } + else { + var a = Address.new(aId); + + a.update(function(err) { + if (err && !a.totalReceivedSat) { + console.log(err); + res.status(404).send('Invalid address'); + return next(); + } + + async.mapSeries(a.transactions, getTransaction, + function(err, results) { + res.jsonp(results); + }); + }); + + } +}; + diff --git a/config/routes.js b/config/routes.js index 45bc4ad..51a3413 100644 --- a/config/routes.js +++ b/config/routes.js @@ -14,11 +14,14 @@ module.exports = function(app) { app.get('/api/block/:blockHash', blocks.show); app.param('blockHash', blocks.block); + // Transaction routes var transactions = require('../app/controllers/transactions'); app.get('/api/tx/:txid', transactions.show); - app.param('txid', transactions.transaction); + app.get('/api/txs', transactions.transactions); + + // Address routes var addresses = require('../app/controllers/addresses'); app.get('/api/addr/:addr', addresses.show); app.param('addr', addresses.address); diff --git a/public/js/controllers/address.js b/public/js/controllers/address.js index 7c859db..bc894a3 100644 --- a/public/js/controllers/address.js +++ b/public/js/controllers/address.js @@ -1,22 +1,6 @@ 'use strict'; angular.module('mystery.address').controller('AddressController', ['$scope', '$routeParams', '$location', 'Global', 'Address', function ($scope, $routeParams, $location, Global, Address) { -/* - $scope.address = '1JmTTDcksW7A6GN7JnxuXkMAXsVN9zmgm1'; - $scope.hash160 = '77ad7d08aaa9cf489ea4e468eaeb892b85f71e27'; - $scope.transactions = [ - { - hash: '49a1d01759690476dbeec4a8efd969c09c6d4269ea2d88f4d9d4f098f021413c', - time: 1234123445, - amount: 0.3 - }, - { - hash: 'cce948b422a4d485900fb82e64458720eb89f545af3f07ddf7d18660f9f881e9', - time: 1234123445, - amount: 0.1 - } - ]; -*/ $scope.global = Global; $scope.findOne = function() { @@ -27,4 +11,5 @@ angular.module('mystery.address').controller('AddressController', ['$scope', '$r }); }; + $scope.params = $routeParams; }]); diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js index d9dd958..d9277eb 100644 --- a/public/js/controllers/blocks.js +++ b/public/js/controllers/blocks.js @@ -20,4 +20,5 @@ angular.module('mystery.blocks').controller('BlocksController', ['$scope', '$rou }); }; + $scope.params = $routeParams; }]); diff --git a/public/js/controllers/transactions.js b/public/js/controllers/transactions.js index 53aaf92..10d5f9f 100644 --- a/public/js/controllers/transactions.js +++ b/public/js/controllers/transactions.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('mystery.transactions').controller('transactionsController', ['$scope', '$routeParams', '$location', 'Global', 'Transaction', function ($scope, $routeParams, $location, Global, Transaction) { +angular.module('mystery.transactions').controller('transactionsController', ['$scope', '$routeParams', '$location', 'Global', 'Transaction', 'TransactionsByBlock', 'TransactionsByAddress', function ($scope, $routeParams, $location, Global, Transaction, TransactionsByBlock, TransactionsByAddress) { $scope.global = Global; $scope.findOne = function() { @@ -10,5 +10,23 @@ angular.module('mystery.transactions').controller('transactionsController', ['$s $scope.tx = tx; }); }; + + $scope.byBlock = function(bId) { + TransactionsByBlock.query({ + block: bId + }, function(txs) { + $scope.txs = txs; + }); + }; + + $scope.byAddress = function(aId) { + TransactionsByAddress.query({ + address: aId + }, function(txs) { + $scope.txs = txs; + }); + }; + + }]); diff --git a/public/js/services/transactions.js b/public/js/services/transactions.js index bc7ee29..d245dbf 100644 --- a/public/js/services/transactions.js +++ b/public/js/services/transactions.js @@ -20,3 +20,15 @@ angular.module('mystery.transactions').factory('Transaction', ['$resource', func }); }]); +angular.module('mystery.transactions').factory('TransactionsByBlock', ['$resource', function($resource) { + return $resource('/api/txs', { + block: '@block' + }); +}]); + +angular.module('mystery.transactions').factory('TransactionsByAddress', ['$resource', function($resource) { + return $resource('/api/txs', { + address: '@address' + }); +}]); + diff --git a/public/views/address.html b/public/views/address.html index f6bb95b..bcafe33 100644 --- a/public/views/address.html +++ b/public/views/address.html @@ -5,12 +5,13 @@ Addresses are identifiers which you use to send bitcoins to another person. -
- - +
+
+
+ - + @@ -29,32 +30,35 @@ - -
Address{{address.addrStr}}{{address.addrStr}}
Total Received{{address.txApperances}}
+ + +
+
+ +
-
- -
-
-

- Transactions - transactions this address relates to -

+
+

Transactions Transactions contained within this block

- + + - - - - - + + + + + + + + +
Transaction Hash DatetimeTransacted amountFeeTransacted Amount
{{transaction}}----
Loading...
{{tx.txid}}{{tx.time * 1000 | date:'medium'}}{{tx.feeds}}{{tx.valueOut}}
diff --git a/public/views/block.html b/public/views/block.html index 68fb1dd..b843503 100644 --- a/public/views/block.html +++ b/public/views/block.html @@ -16,18 +16,6 @@ Number Of Transactions {{block.tx.length}} - - Output Total - -- - - - Estimated Transaction Volume - -- - - - Transaction Fees - -- - Height {{block.height}} @@ -36,10 +24,6 @@ Timestamp {{block.time * 1000 | date:'medium'}} - - Relayed By - -- - Difficulty {{block.difficulty}} @@ -96,17 +80,28 @@
-

Transactions Transactions contained within this block

- - - - +
+

Transactions Transactions contained within this block

+
Hash
+ + + + + + + + + + + - - - - - - -
Transaction HashDatetimeFeeTransacted Amount
Loading...
{{tx}}
+ + {{tx.txid}} + {{tx.time * 1000 | date:'medium'}} + {{tx.feeds}} + {{tx.valueOut}} + + + + diff --git a/public/views/transaction.html b/public/views/transaction.html index cadce85..b0cc422 100644 --- a/public/views/transaction.html +++ b/public/views/transaction.html @@ -23,13 +23,18 @@
- No Inputs (Newly Generated isCoinBasens) +
  @@ -82,8 +87,8 @@ {{tx.time * 1000|date:'medium'}} - Reward From Block - Need height to show (it links to block page) + Block + Block