bitx 0.0.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +92 -5
- data/Rakefile +7 -0
- data/bitx.gemspec +7 -4
- data/lib/bitx.rb +42 -54
- data/lib/bitx_connection.rb +0 -0
- data/lib/private_api.rb +289 -0
- data/lib/public_api.rb +77 -0
- data/lib/version.rb +9 -0
- data/test/balance_test.rb +58 -0
- data/test/order_test.rb +116 -0
- data/test/public_test.rb +224 -0
- data/test/quotes_test.rb +163 -0
- data/test/receive_address_test.rb +101 -0
- data/test/send_test.rb +40 -0
- data/test/withdrawal_test.rb +108 -0
- metadata +39 -5
data/lib/public_api.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
module PublicApi
|
2
|
+
|
3
|
+
def ticker(pair)
|
4
|
+
t = self.get('/api/1/ticker', {pair: pair})
|
5
|
+
{
|
6
|
+
pair: pair,
|
7
|
+
timestamp: Time.at(t['timestamp'].to_i/1000),
|
8
|
+
ask: BigDecimal(t['ask']),
|
9
|
+
bid: BigDecimal(t['bid']),
|
10
|
+
last: BigDecimal(t['last_trade']),
|
11
|
+
volume: t['rolling_24_hour_volume']
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def tickers
|
16
|
+
tickers = []
|
17
|
+
self.get('/api/1/tickers')['tickers'].each do |t|
|
18
|
+
tickers << {
|
19
|
+
pair: t['pair'],
|
20
|
+
timestamp: Time.at(t['timestamp'].to_i/1000),
|
21
|
+
ask: BigDecimal(t['ask']),
|
22
|
+
bid: BigDecimal(t['bid']),
|
23
|
+
last: BigDecimal(t['last_trade']),
|
24
|
+
volume: t['rolling_24_hour_volume']
|
25
|
+
}
|
26
|
+
end
|
27
|
+
tickers
|
28
|
+
end
|
29
|
+
|
30
|
+
def orderbook(pair)
|
31
|
+
t = self.get('/api/1/orderbook', {pair: pair})
|
32
|
+
|
33
|
+
bids = []
|
34
|
+
t['bids'].each do |o|
|
35
|
+
bids << {
|
36
|
+
price: BigDecimal(o['price']),
|
37
|
+
volume: BigDecimal(o['volume'])
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
asks = []
|
42
|
+
t['asks'].each do |o|
|
43
|
+
asks << {
|
44
|
+
price: BigDecimal(o['price']),
|
45
|
+
volume: BigDecimal(o['volume'])
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
{bids: bids, asks: asks, timestamp: Time.at(t['timestamp'].to_i/1000)}
|
50
|
+
end
|
51
|
+
|
52
|
+
def trades(pair)
|
53
|
+
t = self.get('/api/1/trades', {pair: pair})
|
54
|
+
trades = []
|
55
|
+
t['trades'].each do |trade|
|
56
|
+
trades << {
|
57
|
+
timestamp: Time.at(trade['timestamp'].to_i/1000),
|
58
|
+
price: BigDecimal(trade['price']),
|
59
|
+
volume: BigDecimal(trade['volume'])
|
60
|
+
}
|
61
|
+
end
|
62
|
+
trades
|
63
|
+
end
|
64
|
+
|
65
|
+
def get(url, params=nil)
|
66
|
+
r = self.conn.get(url, params)
|
67
|
+
if r.status != 200
|
68
|
+
raise ::BitX::Error.new("BitX error: #{r.status}")
|
69
|
+
end
|
70
|
+
t = JSON.parse r.body
|
71
|
+
if t['error']
|
72
|
+
raise ::BitX::Error.new('BitX error: ' + t['error'])
|
73
|
+
end
|
74
|
+
t
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "minitest/pride"
|
2
|
+
require "minitest/autorun"
|
3
|
+
require_relative "../lib/bitx.rb"
|
4
|
+
|
5
|
+
module BalanceStubs
|
6
|
+
def self.conn
|
7
|
+
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
8
|
+
|
9
|
+
stub.get('/api/1/balance') {[ 200, {},
|
10
|
+
'{
|
11
|
+
"balance": [
|
12
|
+
{
|
13
|
+
"account_id": "1224342323",
|
14
|
+
"asset": "XBT",
|
15
|
+
"balance": "1.012423",
|
16
|
+
"reserved": "0.01",
|
17
|
+
"unconfirmed": "0.421"
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"account_id": "2997473",
|
21
|
+
"asset": "ZAR",
|
22
|
+
"balance": "1000.00",
|
23
|
+
"reserved": "0.00",
|
24
|
+
"unconfirmed": "0.00"
|
25
|
+
}
|
26
|
+
]
|
27
|
+
}']}
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
Faraday.new do |faraday|
|
32
|
+
faraday.adapter :test, stubs
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class TestBalance < Minitest::Test
|
38
|
+
|
39
|
+
def test_balance
|
40
|
+
BitX.set_conn(BalanceStubs.conn)
|
41
|
+
|
42
|
+
r = BitX.balance
|
43
|
+
assert_equal r.first[:reserved], 0.01
|
44
|
+
assert_equal r.first[:available], r.first[:balance] - r.first[:reserved]
|
45
|
+
assert_equal r.first[:unconfirmed], 0.421
|
46
|
+
assert_equal r.first[:asset], 'XBT'
|
47
|
+
assert_equal r.last[:account_id], '2997473'
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_connection_balance
|
51
|
+
r = BitX::Connection.new(BalanceStubs.conn).balance
|
52
|
+
assert_equal r.first[:reserved], 0.01
|
53
|
+
assert_equal r.first[:available], r.first[:balance] - r.first[:reserved]
|
54
|
+
assert_equal r.first[:unconfirmed], 0.421
|
55
|
+
assert_equal r.first[:asset], 'XBT'
|
56
|
+
assert_equal r.last[:account_id], '2997473'
|
57
|
+
end
|
58
|
+
end
|
data/test/order_test.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require "minitest/pride"
|
2
|
+
require "minitest/autorun"
|
3
|
+
require_relative "../lib/bitx.rb"
|
4
|
+
|
5
|
+
module OrderStubs
|
6
|
+
def self.conn
|
7
|
+
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
8
|
+
|
9
|
+
stub.get('/api/1/listorders?pair=XBTZAR') {[ 200, {},
|
10
|
+
'{
|
11
|
+
"orders": [
|
12
|
+
{
|
13
|
+
"fee_counter": "0.00",
|
14
|
+
"order_id": "BXMC2CJ7HNB88U4",
|
15
|
+
"creation_timestamp": 1367849297609,
|
16
|
+
"counter": "0.00",
|
17
|
+
"limit_volume": "0.80",
|
18
|
+
"limit_price": "1000.00",
|
19
|
+
"state": "PENDING",
|
20
|
+
"base": "0.00",
|
21
|
+
"fee_base": "0.00",
|
22
|
+
"type": "ASK",
|
23
|
+
"expiration_timestamp": 1367935697609
|
24
|
+
}
|
25
|
+
]
|
26
|
+
}']}
|
27
|
+
|
28
|
+
|
29
|
+
stub.post('/api/1/postorder', {pair:'XBTZAR', type: 'BID', volume: '0.1', price: '1000.0'}) {[ 200, {},
|
30
|
+
'{
|
31
|
+
"order_id": "BXRANDOMORDERID23"
|
32
|
+
}']}
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
stub.get('/api/1/orders/BXHW6PFRRXKFSB4') {[ 200, {},
|
37
|
+
'{
|
38
|
+
"order_id": "BXHW6PFRRXKFSB4",
|
39
|
+
"creation_timestamp": 1402866878367,
|
40
|
+
"expiration_timestamp": 0,
|
41
|
+
"type": "ASK",
|
42
|
+
"state": "PENDING",
|
43
|
+
"limit_price": "6500.00",
|
44
|
+
"limit_volume": "0.02",
|
45
|
+
"base": "0.00",
|
46
|
+
"counter": "0.00",
|
47
|
+
"fee_base":"0.00",
|
48
|
+
"fee_counter":"0.00"
|
49
|
+
}']}
|
50
|
+
|
51
|
+
stub.post('/api/1/stoporder', {order_id: 'BXMC2CJ7HNB88U4'}) {[ 200, {},
|
52
|
+
'{
|
53
|
+
"success": true
|
54
|
+
}']}
|
55
|
+
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
Faraday.new do |faraday|
|
60
|
+
faraday.adapter :test, stubs
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class TestOrders < Minitest::Test
|
66
|
+
|
67
|
+
def setup_module
|
68
|
+
BitX.set_conn(OrderStubs.conn)
|
69
|
+
end
|
70
|
+
def setup_connection
|
71
|
+
BitX::Connection.new(OrderStubs.conn)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_connection_list
|
75
|
+
r = setup_connection.list_orders('XBTZAR')
|
76
|
+
assert_equal r.size, 1
|
77
|
+
end
|
78
|
+
def test_list
|
79
|
+
setup_module
|
80
|
+
r = BitX.list_orders('XBTZAR')
|
81
|
+
assert_equal r.size, 1
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def test_connection_post_order
|
86
|
+
r = setup_connection.post_order('BID', 0.1, 1000, 'XBTZAR')
|
87
|
+
assert_equal r[:order_id], 'BXRANDOMORDERID23'
|
88
|
+
end
|
89
|
+
def test_post_order
|
90
|
+
setup_module
|
91
|
+
r = BitX.post_order('BID', 0.1, 1000, 'XBTZAR')
|
92
|
+
assert_equal r[:order_id], 'BXRANDOMORDERID23'
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_connection_get_order
|
96
|
+
r = setup_connection.get_order('BXHW6PFRRXKFSB4')
|
97
|
+
assert_equal r[:order_id], 'BXHW6PFRRXKFSB4'
|
98
|
+
end
|
99
|
+
def test_get_order
|
100
|
+
setup_module
|
101
|
+
r = BitX.get_order('BXHW6PFRRXKFSB4')
|
102
|
+
assert_equal r[:order_id], 'BXHW6PFRRXKFSB4'
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_connection_stop_order
|
106
|
+
r = setup_connection.stop_order('BXMC2CJ7HNB88U4')
|
107
|
+
assert_equal r[:success], true
|
108
|
+
end
|
109
|
+
def test_stop_order
|
110
|
+
setup_module
|
111
|
+
r = BitX.stop_order('BXMC2CJ7HNB88U4')
|
112
|
+
assert_equal r[:success], true
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
end
|
data/test/public_test.rb
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
require_relative "../lib/bitx.rb"
|
2
|
+
|
3
|
+
module PublicStubs
|
4
|
+
|
5
|
+
def self.conn
|
6
|
+
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
7
|
+
# ticker
|
8
|
+
stub.get('/api/1/ticker?pair=XBTZAR') {[200, {}, '{
|
9
|
+
"ask": "1050.00",
|
10
|
+
"timestamp": 1366224386716,
|
11
|
+
"bid": "924.00",
|
12
|
+
"rolling_24_hour_volume": "12.52",
|
13
|
+
"last_trade": "950.00"
|
14
|
+
}']}
|
15
|
+
stub.get('/api/1/ticker?pair=XBTXRP') {[200, {}, '{
|
16
|
+
"error": "Invalid currency pair.",
|
17
|
+
"error_code": "ErrInvalidPair"
|
18
|
+
}']}
|
19
|
+
stub.get('/api/1/ticker?pair=xbtzar') {[200, {}, '{
|
20
|
+
"error": "Invalid currency pair.",
|
21
|
+
"error_code": "ErrInvalidPair"
|
22
|
+
}']}
|
23
|
+
stub.get('/api/1/ticker?pair=ZARXBT') {[200, {}, '{
|
24
|
+
"error": "Invalid currency pair.",
|
25
|
+
"error_code": "ErrInvalidPair"
|
26
|
+
}']}
|
27
|
+
|
28
|
+
|
29
|
+
# tickers
|
30
|
+
stub.get('/api/1/tickers') {[200, {}, '{
|
31
|
+
"tickers": [
|
32
|
+
{
|
33
|
+
"timestamp": 1405413955793,
|
34
|
+
"bid": "6801.00",
|
35
|
+
"ask": "6900.00",
|
36
|
+
"last_trade": "6900.00",
|
37
|
+
"rolling_24_hour_volume": "12.455579",
|
38
|
+
"pair":"XBTZAR"
|
39
|
+
},
|
40
|
+
{
|
41
|
+
"timestamp": 1405413955337,
|
42
|
+
"bid": "5000.00",
|
43
|
+
"ask":"6968.00",
|
44
|
+
"last_trade": "6830.00",
|
45
|
+
"rolling_24_hour_volume": "0.00",
|
46
|
+
"pair":"XBTNAD"
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}']}
|
50
|
+
|
51
|
+
# orderbook
|
52
|
+
stub.get('/api/1/orderbook?pair=XBTZAR') {[200, {}, '{
|
53
|
+
"asks": [
|
54
|
+
{
|
55
|
+
"volume": "0.10",
|
56
|
+
"price": "1180.00"
|
57
|
+
},
|
58
|
+
{
|
59
|
+
"volume": "0.15",
|
60
|
+
"price": "2000.00"
|
61
|
+
}
|
62
|
+
],
|
63
|
+
"bids": [
|
64
|
+
{
|
65
|
+
"volume": "0.10",
|
66
|
+
"price": "1100.00"
|
67
|
+
},
|
68
|
+
{
|
69
|
+
"volume": "0.10",
|
70
|
+
"price": "1000.00"
|
71
|
+
},
|
72
|
+
{
|
73
|
+
"volume": "0.10",
|
74
|
+
"price": "900.00"
|
75
|
+
}
|
76
|
+
],
|
77
|
+
"timestamp": 1366305398592,
|
78
|
+
"currency": "ZAR"
|
79
|
+
|
80
|
+
}']}
|
81
|
+
|
82
|
+
# trades
|
83
|
+
stub.get('/api/1/trades?pair=XBTZAR') {[200, {}, '{
|
84
|
+
"trades": [
|
85
|
+
{
|
86
|
+
"volume": "0.10",
|
87
|
+
"timestamp": 1366052621774,
|
88
|
+
"price": "1000.00"
|
89
|
+
},
|
90
|
+
{
|
91
|
+
"volume": "1.20",
|
92
|
+
"timestamp": 1366052620770,
|
93
|
+
"price": "1020.50"
|
94
|
+
}
|
95
|
+
]
|
96
|
+
}']}
|
97
|
+
end
|
98
|
+
|
99
|
+
Faraday.new do |faraday|
|
100
|
+
faraday.adapter :test, stubs
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
require "minitest/pride"
|
110
|
+
require "minitest/autorun"
|
111
|
+
|
112
|
+
class TestPublic < Minitest::Test
|
113
|
+
|
114
|
+
def setup_module
|
115
|
+
BitX.set_conn(PublicStubs.conn)
|
116
|
+
end
|
117
|
+
|
118
|
+
def setup_connection
|
119
|
+
BitX::Connection.new(PublicStubs.conn)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_ticker
|
123
|
+
setup_module
|
124
|
+
ticker = BitX.ticker('XBTZAR')
|
125
|
+
assert_equal ticker[:volume], '12.52'
|
126
|
+
|
127
|
+
err = assert_raises(BitX::Error) {
|
128
|
+
BitX.ticker('XBTXRP')
|
129
|
+
}
|
130
|
+
assert_equal err.message, 'BitX error: Invalid currency pair.'
|
131
|
+
|
132
|
+
err = assert_raises(BitX::Error) {
|
133
|
+
BitX.ticker('xbtzar')
|
134
|
+
}
|
135
|
+
assert_equal err.message, 'BitX error: Invalid currency pair.'
|
136
|
+
|
137
|
+
err = assert_raises(BitX::Error) {
|
138
|
+
BitX.ticker('ZARXBT')
|
139
|
+
}
|
140
|
+
assert_equal err.message, 'BitX error: Invalid currency pair.'
|
141
|
+
end
|
142
|
+
def test_connection_ticker
|
143
|
+
cnx = setup_connection
|
144
|
+
ticker = cnx.ticker('XBTZAR')
|
145
|
+
assert_equal ticker[:volume], '12.52'
|
146
|
+
|
147
|
+
err = assert_raises(BitX::Error) {
|
148
|
+
cnx.ticker('XBTXRP')
|
149
|
+
}
|
150
|
+
assert_equal err.message, 'BitX error: Invalid currency pair.'
|
151
|
+
|
152
|
+
err = assert_raises(BitX::Error) {
|
153
|
+
cnx.ticker('xbtzar')
|
154
|
+
}
|
155
|
+
assert_equal err.message, 'BitX error: Invalid currency pair.'
|
156
|
+
|
157
|
+
err = assert_raises(BitX::Error) {
|
158
|
+
cnx.ticker('ZARXBT')
|
159
|
+
}
|
160
|
+
assert_equal err.message, 'BitX error: Invalid currency pair.'
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_tickers
|
164
|
+
setup_module
|
165
|
+
tickers = BitX.tickers
|
166
|
+
assert_equal tickers.size, 2
|
167
|
+
assert_equal tickers.first[:pair], 'XBTZAR'
|
168
|
+
assert_equal tickers.first[:ask], 6900.00
|
169
|
+
assert_equal tickers.first[:volume], "12.455579"
|
170
|
+
|
171
|
+
assert_equal tickers.last[:volume], "0.00"
|
172
|
+
assert_equal tickers.last[:bid], 5000
|
173
|
+
end
|
174
|
+
def test_connection_tickers
|
175
|
+
tickers = setup_connection.tickers
|
176
|
+
assert_equal tickers.size, 2
|
177
|
+
assert_equal tickers.first[:pair], 'XBTZAR'
|
178
|
+
assert_equal tickers.first[:ask], 6900.00
|
179
|
+
assert_equal tickers.first[:volume], "12.455579"
|
180
|
+
|
181
|
+
assert_equal tickers.last[:volume], "0.00"
|
182
|
+
assert_equal tickers.last[:bid], 5000
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_orderbook
|
186
|
+
setup_module
|
187
|
+
ob = BitX.orderbook('XBTZAR')
|
188
|
+
assert_equal ob[:bids].size, 3
|
189
|
+
assert_equal ob[:bids].first[:price], 1100
|
190
|
+
|
191
|
+
assert_equal ob[:asks].size, 2
|
192
|
+
assert_equal ob[:asks].last[:volume], 0.15
|
193
|
+
assert_equal ob[:timestamp], Time.at(1366305398)
|
194
|
+
end
|
195
|
+
def test_connection_orderbook
|
196
|
+
ob = setup_connection.orderbook('XBTZAR')
|
197
|
+
assert_equal ob[:bids].size, 3
|
198
|
+
assert_equal ob[:bids].first[:price], 1100
|
199
|
+
|
200
|
+
assert_equal ob[:asks].size, 2
|
201
|
+
assert_equal ob[:asks].last[:volume], 0.15
|
202
|
+
assert_equal ob[:timestamp], Time.at(1366305398)
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_trades
|
206
|
+
setup_module
|
207
|
+
trades = BitX.trades('XBTZAR')
|
208
|
+
assert_equal trades.size, 2
|
209
|
+
assert_equal trades.first[:timestamp], Time.at(1366052621)
|
210
|
+
assert_equal trades.last[:volume], 1.2
|
211
|
+
assert_equal trades.last[:price], 1020.5
|
212
|
+
assert_operator trades.first[:timestamp], :>=, trades.last[:timestamp]
|
213
|
+
end
|
214
|
+
def test_connection_trades
|
215
|
+
setup_module
|
216
|
+
trades = setup_connection.trades('XBTZAR')
|
217
|
+
assert_equal trades.size, 2
|
218
|
+
assert_equal trades.first[:timestamp], Time.at(1366052621)
|
219
|
+
assert_equal trades.last[:volume], 1.2
|
220
|
+
assert_equal trades.last[:price], 1020.5
|
221
|
+
assert_operator trades.first[:timestamp], :>=, trades.last[:timestamp]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|