Skip to content

Commit 0aa52a5

Browse files
committed
blockchain initial commit
0 parents  commit 0aa52a5

10 files changed

+451
-0
lines changed

LICENSE

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2014 Alf
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+

address.go

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package blockchain
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
type Address struct {
9+
Hash160 string `json:"hash160"`
10+
Address string `json:"address"`
11+
NTx int `json:"n_tx"`
12+
TotalReceived int `json:"total_received"`
13+
TotalSent int `json:"total_sent"`
14+
FinalBalance int `json:"final_balance"`
15+
Txs []*Tx `json:"txs"`
16+
}
17+
18+
type MultiAddr struct {
19+
Addresses []*Address `json:"addresses"`
20+
Txs []*Tx `json:"txs"`
21+
}
22+
23+
type Tx struct {
24+
Result int `json:"result"`
25+
Ver int `json:"ver"`
26+
Size int `json:"size"`
27+
Inputs []*Inputs `json:"inputs"`
28+
Time int `json:"time"`
29+
BlockHeight int `json:"block_height"`
30+
TxIndex int `json:"tx_index"`
31+
VinSz int `json:"vin_sz"`
32+
Hash string `json:"hash"`
33+
VoutSz int `json:"vout_sz"`
34+
RelayedBy string `json:"relayed_by"`
35+
Out []*Out `json:"out"`
36+
}
37+
38+
type Inputs struct {
39+
Sequence int `json:"sequence"`
40+
Script string `json:"script"`
41+
PrevOut *PrevOut `json:"prev_out"`
42+
}
43+
44+
type PrevOut struct {
45+
Spent bool `json:"spent"`
46+
TxIndex int `json:"tx_index"`
47+
Type int `json:"type"`
48+
Addr string `json:"addr"`
49+
Value int `json:"value"`
50+
N int `json:"n"`
51+
Script string `json:"script"`
52+
}
53+
54+
type Out struct {
55+
Spent bool `json:"spent"`
56+
TxIndex int `json:"tx_index"`
57+
Type int `json:"type"`
58+
Addr string `json:"addr"`
59+
Value int `json:"value"`
60+
N int `json:"n"`
61+
Script string `json:"script"`
62+
}
63+
64+
func (c *Client) GetAddress(address string) (*Address, error) {
65+
rsp := &Address{}
66+
var path = "/address/" + address
67+
e := c.loadResponse(path, rsp, true)
68+
69+
if e != nil {
70+
fmt.Print(e)
71+
}
72+
return rsp, e
73+
}
74+
75+
func (c *Client) GetAddresses(addresses []string) (*MultiAddr, error) {
76+
rsp := &MultiAddr{}
77+
var path = "/multiaddr?active=" + strings.Join(addresses, "|")
78+
e := c.loadResponse(path, rsp, false)
79+
80+
if e != nil {
81+
fmt.Print(e)
82+
}
83+
return rsp, e
84+
}

address_test.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package blockchain
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestGetAddress(t *testing.T) {
9+
fmt.Println("===== TESTING ADDRESS =====")
10+
11+
c, e := New()
12+
resp, e := c.GetAddress("162FjqU7RYdojnejCDe6zrPDUpaLcv9Hhq")
13+
if e != nil {
14+
fmt.Print(e)
15+
}
16+
17+
fmt.Println(resp.Hash160)
18+
fmt.Println(resp.Address)
19+
fmt.Println(resp.NTx)
20+
fmt.Println(resp.TotalReceived)
21+
fmt.Println(resp.TotalSent)
22+
fmt.Println(resp.FinalBalance)
23+
24+
for i := range resp.Txs {
25+
fmt.Println(resp.Txs[i].Result)
26+
27+
for j := range resp.Txs[i].Inputs {
28+
fmt.Println(resp.Txs[i].Inputs[j].Sequence)
29+
fmt.Println(resp.Txs[i].Inputs[j].PrevOut.Spent)
30+
}
31+
}
32+
}
33+
34+
func TestGetAddresses(t *testing.T) {
35+
fmt.Println("===== TESTING ADDRESSES =====")
36+
37+
c, e := New()
38+
if e != nil {
39+
fmt.Print(e)
40+
}
41+
42+
addresses := []string{
43+
"162FjqU7RYdojnejCDe6zrPDUpaLcv9Hhq",
44+
"1K3Vs8tPu2YkAoWmrkjUQVJuxr7wgPP3Wf"}
45+
46+
resp, _ := c.GetAddresses(addresses)
47+
for i := range resp.Addresses {
48+
fmt.Println(resp.Addresses[i].Address)
49+
50+
for j := range resp.Txs[i].Inputs {
51+
fmt.Println(resp.Txs[i].Inputs[j].Sequence)
52+
fmt.Println(resp.Txs[i].Inputs[j].PrevOut.Spent)
53+
}
54+
}
55+
}

block.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package blockchain
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type Block struct {
8+
Hash string `json:"hash"`
9+
Ver int `json:"ver"`
10+
PrevBlock string `json:"prev_block"`
11+
MrklRoot string `json:"mrkl_root"`
12+
Time int `json:"time"`
13+
Bits int `json:"bits"`
14+
Nonce int `json:"nonce"`
15+
NTx int `json:"n_tx"`
16+
Size int `json:"size"`
17+
BlockIndex int `json:"block_index"`
18+
MainChain bool `json:"main_chain"`
19+
Height int `json:"height"`
20+
ReceivedTime int `json:"recieved_time"`
21+
RelayedBy string `json:"relayed_by"`
22+
Tx []*Tx `json:"tx"`
23+
TxIndexes []int `json:"txIndexes"`
24+
}
25+
26+
type BlockHeight struct {
27+
Blocks []*Block `json:"blocks"`
28+
}
29+
30+
func (c *Client) GetBlock(block string) (*Block, error) {
31+
rsp := &Block{}
32+
var path = "/rawblock/" + block
33+
e := c.loadResponse(path, rsp, true)
34+
35+
if e != nil {
36+
fmt.Print(e)
37+
}
38+
return rsp, e
39+
}
40+
41+
func (c *Client) GetBlockHeight(blockHeight string) (*BlockHeight, error) {
42+
rsp := &BlockHeight{}
43+
var path = "/block-height/" + blockHeight
44+
e := c.loadResponse(path, rsp, true)
45+
46+
if e != nil {
47+
fmt.Print(e)
48+
}
49+
return rsp, e
50+
}
51+
52+
func (c *Client) GetLatestBlock() (*Block, error) {
53+
rsp := &Block{}
54+
var path = "/latestblock"
55+
e := c.loadResponse(path, rsp, false)
56+
57+
if e != nil {
58+
fmt.Print(e)
59+
}
60+
return rsp, e
61+
}

block_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package blockchain
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestGetBlock(t *testing.T) {
9+
fmt.Println("===== TESTING BLOCK =====")
10+
11+
c, e := New()
12+
resp, e := c.GetBlock("0000000000000bae09a7a393a8acded75aa67e46cb81f7acaa5ad94f9eacd103")
13+
if e != nil {
14+
fmt.Print(e)
15+
}
16+
17+
fmt.Println(resp.Hash)
18+
19+
for i := range resp.Tx {
20+
21+
for j := range resp.Tx[i].Inputs {
22+
fmt.Println(resp.Tx[i].Inputs[j].Sequence)
23+
}
24+
}
25+
}
26+
27+
func TestGetBlockHeight(t *testing.T) {
28+
fmt.Println("===== TESTING BLOCK HEIGHT =====")
29+
30+
c, e := New()
31+
resp, e := c.GetBlockHeight("160778")
32+
if e != nil {
33+
fmt.Print(e)
34+
}
35+
36+
for i := range resp.Blocks {
37+
fmt.Println(resp.Blocks[i].Hash)
38+
fmt.Println(resp.Blocks[i].Time)
39+
}
40+
}
41+
42+
func TestGetLatestBlock(t *testing.T) {
43+
fmt.Println("===== TESTING LATEST BLOCK =====")
44+
45+
c, e := New()
46+
resp, e := c.GetLatestBlock()
47+
if e != nil {
48+
fmt.Print(e)
49+
}
50+
51+
fmt.Println(resp.Hash)
52+
fmt.Println(resp.Height)
53+
54+
for _, v := range resp.TxIndexes {
55+
fmt.Println(v)
56+
}
57+
}

chart.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package blockchain
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type Chart struct {
8+
Values []*Value `json:"values"`
9+
}
10+
11+
type Value struct {
12+
X int `json:"x"`
13+
Y int `json:"y"`
14+
}
15+
16+
func (c *Client) GetChart(chartType string) (*Chart, error) {
17+
rsp := &Chart{}
18+
var path = "/charts/" + chartType
19+
e := c.loadResponse(path, rsp, true)
20+
21+
if e != nil {
22+
fmt.Print(e)
23+
}
24+
return rsp, e
25+
}

chart_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package blockchain
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestGetChart(t *testing.T) {
9+
fmt.Println("===== TESTING CHART =====")
10+
11+
c, e := New()
12+
resp, e := c.GetChart("total-bitcoins")
13+
if e != nil {
14+
fmt.Print(e)
15+
}
16+
17+
for i := range resp.Values {
18+
fmt.Println(resp.Values[i].X)
19+
}
20+
}

client.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package blockchain
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"net/http"
8+
)
9+
10+
const (
11+
API_ROOT = "https://blockchain.info/"
12+
)
13+
14+
type Client struct {
15+
*http.Client
16+
}
17+
18+
func (c *Client) loadResponse(path string, i interface{}, formatJson bool) error {
19+
full_path := API_ROOT + path
20+
if formatJson {
21+
full_path = API_ROOT + path + "/?format=json"
22+
}
23+
24+
fmt.Println("querying..." + full_path)
25+
rsp, e := c.Get(full_path)
26+
if e != nil {
27+
return e
28+
}
29+
30+
defer rsp.Body.Close()
31+
32+
b, e := ioutil.ReadAll(rsp.Body)
33+
if e != nil {
34+
return e
35+
}
36+
if rsp.Status[0] != '2' {
37+
return fmt.Errorf("expected status 2xx, got %s: %s", rsp.Status, string(b))
38+
}
39+
40+
return json.Unmarshal(b, &i)
41+
}
42+
43+
func New() (*Client, error) {
44+
return &Client{Client: &http.Client{}}, nil
45+
}

0 commit comments

Comments
 (0)