Skip to content

Commit 79b263a

Browse files
committed
/api/unspent-outpoints.js
1 parent 1d59c99 commit 79b263a

File tree

3 files changed

+95
-41
lines changed

3 files changed

+95
-41
lines changed

app.coffee

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11

22
url = require 'url'
33
async = require 'async'
4-
{get_address_info} = require './scrape-blockexplorer'
4+
{get_unspent_outpoints} = require './scrape-blockexplorer'
55
{BitcoinNode} = require './bitcoin-node'
66

77

8+
CONNECT_TO_BITCOIND = true
89

9-
bitcoin_node = new BitcoinNode
10+
11+
if CONNECT_TO_BITCOIND
12+
bitcoin_node = new BitcoinNode
1013

1114

1215

@@ -20,14 +23,20 @@ api = (req, res, next) ->
2023

2124
module.exports = (app) ->
2225

23-
app.get '/api/check-addresses.js', api, (req, res, next) ->
26+
app.get '/api/unspent-outpoints.js', api, (req, res, next) ->
2427
addrs = req.x.addresses.split ','
25-
async.map addrs, get_address_info, (err, results) ->
28+
async.map addrs, get_unspent_outpoints, (err, results) ->
29+
unspent_outpoints = []
30+
for arr in results
31+
for x in arr
32+
unspent_outpoints.push x
2633
res.api {
27-
addresses: results
34+
unspent_outpoints: unspent_outpoints
2835
}
2936

30-
app.post '/api/publish-tx.js', api, (req, res, next) ->
31-
tx = new Buffer req.body.tx64, 'base64'
32-
bitcoin_node.publishTX_via_tx tx, () ->
33-
res.api {}
37+
if CONNECT_TO_BITCOIND
38+
app.post '/api/publish-tx.js', api, (req, res, next) ->
39+
tx = new Buffer req.body.tx64, 'base64'
40+
console.log require('hexy').hexy tx
41+
bitcoin_node.publishTX_via_tx tx, () ->
42+
res.api {}

bitcoin-node.coffee

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ net = require 'net'
44
{readData} = require './util'
55

66

7+
78
exports.BitcoinNode = class BitcoinNode
89

910
publishTX_via_tx: (data, callback) ->
10-
@conn.write msg pack_message 'tx', data
11+
@conn.write pack_message 'tx', data
12+
callback()
1113

1214
publishTX_via_inv: (data, callback) ->
1315
k = inv_for_tx(data).toString('base64')
@@ -24,7 +26,7 @@ exports.BitcoinNode = class BitcoinNode
2426
console.log "Bitcoin message: #{name}"
2527

2628
p.on 'version', (m) =>
27-
if m >= 209
29+
if m.version >= 209
2830
@conn.write pack_message 'verack', {}
2931

3032
p.on 'getdata', (m) =>

scrape-blockexplorer.coffee

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,88 @@
11

22
http = require 'http'
33
assert = require 'assert'
4+
async = require 'async'
45
{readData} = require './util'
56

67

7-
exports.get_address_info = (address, callback) ->
8+
exports.get_unspent_outpoints = (address, callback) ->
9+
810
http.get {host:"blockexplorer.com", port:80, path:"/address/#{address}"}, (res) ->
911
readData res, (data) ->
10-
html = data.toString('utf-8')
11-
callback null, {
12-
address: address
13-
outpoints: scrape_address_outpoints(html)
14-
}
12+
[received, sent_transactions] = scrape_address_ledger data.toString 'utf-8'
13+
14+
async.map sent_transactions, tx_input_outpoints, (err, results) ->
15+
16+
# Set of received outpoints
17+
set = {}
18+
for row in received
19+
set[row.outpoint] = row
20+
21+
# Setminus the spent ones
22+
for outpoints in results
23+
for outpoint in outpoints
24+
delete set[outpoint]
25+
26+
unspent_outpoints = []
27+
for own k, v of set
28+
unspent_outpoints.push v
29+
30+
callback null, unspent_outpoints
31+
32+
33+
tx_input_outpoints = (tx_hash, cb) ->
34+
http.get {host:"blockexplorer.com", port:80, path:"/tx/#{tx_hash}"}, (res) ->
35+
readData res, (data) ->
36+
html = data.toString 'utf-8'
37+
38+
rg = /<td><a name="i[0-9]+" href="\/tx\/([0-9a-fA-F]+)#o([0-9]+)"/g
39+
r = /<td><a name="i[0-9]+" href="\/tx\/([0-9a-fA-F]+)#o([0-9]+)"/
40+
41+
outpoints = []
42+
for text in html.match rg
43+
m = text.match r
44+
outpoints.push "#{m[1]}:#{m[2]}"
45+
46+
cb null, outpoints
1547

1648

17-
scrape_address_outpoints = (html) ->
18-
outpoints = []
49+
scrape_address_ledger = (html) ->
1950

20-
trs = html.match(/<tr>(.|\n)*?Received: Address(.|\n)*?<\/tr>/g)
51+
received = []
52+
sent_transactions_set = {}
53+
54+
trs = html.match /<tr>(.|[\r\n])*?<\/tr>/g
2155
assert.ok trs
2256

2357
for tr in trs
24-
25-
m = tr.match /href="\/tx\/([a-zA-Z0-9]+)#o([0-9]+)"/
26-
assert.ok m
27-
hash = m[1]
28-
n = parseInt m[2], 10
29-
30-
m = tr.match(/Block ([0-9]+)<\/a>/)
31-
assert.ok m
32-
block_number = parseInt m[1], 10
33-
34-
m = tr.match /<td>([0-9.]+)<\/td>\n<td>Received/
35-
assert.ok m
36-
value_str = m[1]
37-
38-
outpoints.push {
39-
hash: hash
40-
n: n
41-
block_number: block_number
42-
value_str: value_str
43-
}
44-
outpoints
58+
amount_match = tr.match /<td>([0-9.]+)<\/td>[ \t\r\n]*<td>(Received|Sent)/
59+
if amount_match
60+
61+
m = tr.match /href="\/tx\/([a-zA-Z0-9]+)#.([0-9]+)"/
62+
assert.ok m, 'hash, n'
63+
hash = m[1]
64+
n = parseInt m[2], 10
65+
66+
m = tr.match /Block ([0-9]+)<\/a>/
67+
assert.ok m, 'block_number'
68+
block_number = parseInt m[1], 10
69+
70+
value_str = amount_match[1]
71+
72+
if tr.match /Received/
73+
received.push {
74+
hash: hash
75+
n: n
76+
outpoint: "#{hash}:#{n}"
77+
block_number: block_number
78+
value_str: value_str
79+
}
80+
else
81+
sent_transactions_set[hash] = true
82+
83+
sent_transactions = []
84+
for own k of sent_transactions_set
85+
sent_transactions.push k
86+
87+
return [received, sent_transactions]
4588

0 commit comments

Comments
 (0)