|
1 | 1 |
|
2 | 2 | http = require 'http'
|
3 | 3 | assert = require 'assert'
|
| 4 | +async = require 'async' |
4 | 5 | {readData} = require './util'
|
5 | 6 |
|
6 | 7 |
|
7 |
| -exports.get_address_info = (address, callback) -> |
| 8 | +exports.get_unspent_outpoints = (address, callback) -> |
| 9 | + |
8 | 10 | http.get {host:"blockexplorer.com", port:80, path:"/address/#{address}"}, (res) ->
|
9 | 11 | 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 |
15 | 47 |
|
16 | 48 |
|
17 |
| -scrape_address_outpoints = (html) -> |
18 |
| - outpoints = [] |
| 49 | +scrape_address_ledger = (html) -> |
19 | 50 |
|
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 |
21 | 55 | assert.ok trs
|
22 | 56 |
|
23 | 57 | 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] |
45 | 88 |
|
0 commit comments