straight 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +5 -1
  4. data/README.md +20 -10
  5. data/VERSION +1 -1
  6. data/lib/straight.rb +10 -1
  7. data/lib/straight/blockchain_adapter.rb +2 -13
  8. data/lib/straight/blockchain_adapters/biteasy_adapter.rb +74 -0
  9. data/lib/straight/blockchain_adapters/blockchain_info_adapter.rb +37 -17
  10. data/lib/straight/blockchain_adapters/mycelium_adapter.rb +144 -0
  11. data/lib/straight/exchange_rate_adapter.rb +20 -1
  12. data/lib/straight/exchange_rate_adapters/average_rate_adapter.rb +54 -0
  13. data/lib/straight/exchange_rate_adapters/bitpay_adapter.rb +5 -2
  14. data/lib/straight/exchange_rate_adapters/bitstamp_adapter.rb +2 -1
  15. data/lib/straight/exchange_rate_adapters/btce_adapter.rb +18 -0
  16. data/lib/straight/exchange_rate_adapters/coinbase_adapter.rb +2 -4
  17. data/lib/straight/exchange_rate_adapters/kraken_adapter.rb +18 -0
  18. data/lib/straight/exchange_rate_adapters/localbitcoins_adapter.rb +17 -0
  19. data/lib/straight/exchange_rate_adapters/okcoin_adapter.rb +18 -0
  20. data/lib/straight/gateway.rb +20 -9
  21. data/lib/straight/order.rb +46 -13
  22. data/spec/lib/blockchain_adapters/{helloblock_io_spec.rb → biteasy_adapter_spec.rb} +23 -18
  23. data/spec/lib/blockchain_adapters/{blockchain_info_spec.rb → blockchain_info_adapter_spec.rb} +8 -3
  24. data/spec/lib/blockchain_adapters/mycelium_adapter_spec.rb +54 -0
  25. data/spec/lib/exchange_rate_adapter_spec.rb +6 -1
  26. data/spec/lib/exchange_rate_adapters/average_rate_adapter_spec.rb +43 -0
  27. data/spec/lib/exchange_rate_adapters/bitpay_adapter_spec.rb +14 -1
  28. data/spec/lib/exchange_rate_adapters/bitstamp_adapter_spec.rb +14 -1
  29. data/spec/lib/exchange_rate_adapters/btce_adapter_spec.rb +27 -0
  30. data/spec/lib/exchange_rate_adapters/coinbase_adapter_spec.rb +14 -1
  31. data/spec/lib/exchange_rate_adapters/kraken_adapter_spec.rb +27 -0
  32. data/spec/lib/exchange_rate_adapters/localbitcoins_adapter_spec.rb +27 -0
  33. data/spec/lib/exchange_rate_adapters/okcoin_adapter_spec.rb +27 -0
  34. data/spec/lib/gateway_spec.rb +23 -5
  35. data/spec/lib/order_spec.rb +18 -2
  36. data/straight.gemspec +95 -0
  37. metadata +33 -6
  38. data/lib/straight/blockchain_adapters/helloblock_io_adapter.rb +0 -53
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Straight::Blockchain::MyceliumAdapter do
4
+
5
+ subject(:adapter) { Straight::Blockchain::MyceliumAdapter.mainnet_adapter }
6
+
7
+ it "fetches all transactions for the current address" do
8
+ address = "3B1QZ8FpAaHBgkSB5gFt76ag5AW9VeP8xp"
9
+ expect(adapter).to receive(:straighten_transaction).with(anything, address: address).at_least(:once)
10
+ expect(adapter.fetch_transactions_for(address)).not_to be_empty
11
+ end
12
+
13
+ it "fetches the balance for a given address" do
14
+ address = "1NX8bgWdPq2NahtTbTUAAdsTwpMpvt7nLy"
15
+ expect(adapter.fetch_balance_for(address)).to be_kind_of(Integer)
16
+ end
17
+
18
+ it "fetches a single transaction" do
19
+ tid = 'ae0d040f48d75fdc46d9035236a1782164857d6f0cca1f864640281115898560'
20
+ expect(adapter.fetch_transaction(tid)[:total_amount]).to eq(832947)
21
+ end
22
+
23
+ it "calculates the number of confirmations for each transaction" do
24
+ tid = 'ae0d040f48d75fdc46d9035236a1782164857d6f0cca1f864640281115898560'
25
+ expect(adapter.fetch_transaction(tid)[:confirmations]).to be > 0
26
+ end
27
+
28
+ it "gets a transaction id among other data" do
29
+ tid = 'ae0d040f48d75fdc46d9035236a1782164857d6f0cca1f864640281115898560'
30
+ expect(adapter.fetch_transaction(tid)[:tid]).to eq(tid)
31
+ end
32
+
33
+ it "caches blockchain.info latestblock requests" do
34
+ latest_block_response = double('Blockchain info latest block response')
35
+ expect(latest_block_response).to receive(:body).and_return('{ "height": 1 }')
36
+ expect(HTTParty).to receive(:get).with("https://blockchain.info/latestblock", timeout: 4, verify: false).once.and_return(latest_block_response)
37
+ adapter.send(:calculate_confirmations, 1, force_latest_block_reload: true)
38
+ adapter.send(:calculate_confirmations, 1)
39
+ adapter.send(:calculate_confirmations, 1)
40
+ adapter.send(:calculate_confirmations, 1)
41
+ adapter.send(:calculate_confirmations, 1)
42
+ end
43
+
44
+ it "raises an exception when something goes wrong with fetching datd" do
45
+ expect( -> { adapter.send(:api_request, "/a-404-request") }).to raise_error(Straight::Blockchain::Adapter::RequestError)
46
+ end
47
+
48
+ it "uses the same Singleton instance" do
49
+ a = Straight::Blockchain::MyceliumAdapter.mainnet_adapter
50
+ b = Straight::Blockchain::MyceliumAdapter.mainnet_adapter
51
+ expect(a).to eq(b)
52
+ end
53
+
54
+ end
@@ -7,7 +7,7 @@ RSpec.describe Straight::ExchangeRate::Adapter do
7
7
  end
8
8
 
9
9
  before(:each) do
10
- @exchange_adapter = Straight::ExchangeRate::Adapter.new
10
+ @exchange_adapter = Straight::ExchangeRate::Adapter.instance
11
11
  end
12
12
 
13
13
  describe "converting currencies" do
@@ -47,4 +47,9 @@ RSpec.describe Straight::ExchangeRate::Adapter do
47
47
  @exchange_adapter.rate_for('USD')
48
48
  end
49
49
 
50
+ it "raises exception if rate is nil" do
51
+ rate = nil
52
+ expect( -> { @exchange_adapter.rate_to_f(rate) }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
53
+ end
54
+
50
55
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Straight::ExchangeRate::AverageRateAdapter do
4
+
5
+ before(:each) do
6
+ @average_rates_adapter = Straight::ExchangeRate::AverageRateAdapter.instance(
7
+ Straight::ExchangeRate::BitstampAdapter,
8
+ Straight::ExchangeRate::BitpayAdapter.instance,
9
+ )
10
+ end
11
+
12
+ it "calculates average rate" do
13
+ json_response_bistamp = '{"high": "232.89", "last": "100", "timestamp": "1423457015", "bid": "224.00", "vwap": "224.57", "volume": "14810.41127494", "low": "217.28", "ask": "224.13"}'
14
+ json_response_bitpay = '[{"code":"USD","name":"US Dollar","rate":200},{"code":"EUR","name":"Eurozone Euro","rate":197.179544}]'
15
+ uri_mock = double('uri mock')
16
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_bistamp, json_response_bitpay)
17
+ allow(URI).to receive(:parse).and_return(uri_mock)
18
+ expect(@average_rates_adapter.rate_for('USD')).to eq 150
19
+ end
20
+
21
+ it "fetches rates for all adapters" do
22
+ expect(@average_rates_adapter.fetch_rates!).not_to be_empty
23
+ end
24
+
25
+ it 'raises error if all adapters failed to fetch rates' do
26
+ adapter_mocks = [double('adapter_1'), double('adapter_2')]
27
+ adapter_mocks.each do |adapter|
28
+ expect(adapter).to receive(:fetch_rates!).and_raise(Straight::ExchangeRate::Adapter::FetchingFailed)
29
+ end
30
+ average_rates_adapter = Straight::ExchangeRate::AverageRateAdapter.instance(*adapter_mocks)
31
+ expect( -> { average_rates_adapter.fetch_rates! }).to raise_error(Straight::ExchangeRate::Adapter::FetchingFailed)
32
+ end
33
+
34
+ it "raises exception if all adapters fail to get rates" do
35
+ expect( -> { @average_rates_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
36
+ end
37
+
38
+ it "raises exception if unallowed method is called" do # fetch_rates! is not to be used in AverageRateAdapter itself
39
+ expect( -> { @average_rates_adapter.get_rate_value_from_hash(nil, 'nothing') }).to raise_error("This method is not supposed to be used in #{@average_rates_adapter.class}.")
40
+ expect( -> { @average_rates_adapter.rate_to_f(nil) }).to raise_error("This method is not supposed to be used in #{@average_rates_adapter.class}.")
41
+ end
42
+
43
+ end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  RSpec.describe Straight::ExchangeRate::BitpayAdapter do
4
4
 
5
5
  before(:each) do
6
- @exchange_adapter = Straight::ExchangeRate::BitpayAdapter.new
6
+ @exchange_adapter = Straight::ExchangeRate::BitpayAdapter.instance
7
7
  end
8
8
 
9
9
  it "finds the rate for currency code" do
@@ -11,4 +11,17 @@ RSpec.describe Straight::ExchangeRate::BitpayAdapter do
11
11
  expect( -> { @exchange_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
12
12
  end
13
13
 
14
+ it "raises exception if rate is nil" do
15
+ json_response_1 = '[{},{}]'
16
+ json_response_2 = '[{"code":"USD","name":"US Dollar","rat":223.59},{"code":"EUR","name":"Eurozone Euro","rate":197.179544}]'
17
+ json_response_3 = '[{"code":"USD","name":"US Dollar","rate":null},{"code":"EUR","name":"Eurozone Euro","rate":197.179544}]'
18
+ uri_mock = double('uri mock')
19
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_1, json_response_2, json_response_3)
20
+ allow(URI).to receive(:parse).and_return(uri_mock)
21
+ 3.times do
22
+ @exchange_adapter.fetch_rates!
23
+ expect( -> { @exchange_adapter.rate_for('USD') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
24
+ end
25
+ end
26
+
14
27
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  RSpec.describe Straight::ExchangeRate::BitstampAdapter do
4
4
 
5
5
  before(:each) do
6
- @exchange_adapter = Straight::ExchangeRate::BitstampAdapter.new
6
+ @exchange_adapter = Straight::ExchangeRate::BitstampAdapter.instance
7
7
  end
8
8
 
9
9
  it "finds the rate for currency code" do
@@ -11,4 +11,17 @@ RSpec.describe Straight::ExchangeRate::BitstampAdapter do
11
11
  expect( -> { @exchange_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
12
12
  end
13
13
 
14
+ it "raises exception if rate is nil" do
15
+ json_response_1 = '{}'
16
+ json_response_2 = '{"high": "232.89", "list": "224.13", "timestamp": "1423457015", "bid": "224.00", "vwap": "224.57", "volume": "14810.41127494", "low": "217.28", "ask": "224.13"}'
17
+ json_response_3 = '{"high": "232.89", "last": null, "timestamp": "1423457015", "bid": "224.00", "vwap": "224.57", "volume": "14810.41127494", "low": "217.28", "ask": "224.13"}'
18
+ uri_mock = double('uri mock')
19
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_1, json_response_2, json_response_3)
20
+ allow(URI).to receive(:parse).and_return(uri_mock)
21
+ 3.times do
22
+ @exchange_adapter.fetch_rates!
23
+ expect( -> { @exchange_adapter.rate_for('USD') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
24
+ end
25
+ end
26
+
14
27
  end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Straight::ExchangeRate::BtceAdapter do
4
+
5
+ before(:each) do
6
+ @exchange_adapter = Straight::ExchangeRate::BtceAdapter.instance
7
+ end
8
+
9
+ it "finds the rate for currency code" do
10
+ expect(@exchange_adapter.rate_for('USD')).to be_kind_of(Float)
11
+ expect( -> { @exchange_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
12
+ end
13
+
14
+ it "rases exception if rate is nil" do
15
+ json_response_1 = '{"ticker":{}}'
16
+ json_response_2 = '{"ticker":{"high":235,"low":215.89999,"avg":225.449995,"vol":2848293.72397,"vol_cur":12657.55799,"bambo":221.444,"buy":221.629,"sell":220.98,"updated":1422678812,"server_time":1422678813}}'
17
+ json_response_3 = '{"ticker":{"high":235,"low":215.89999,"avg":225.449995,"vol":2848293.72397,"vol_cur":12657.55799,"last":null,"buy":221.629,"sell":220.98,"updated":1422678812,"server_time":1422678813}}'
18
+ uri_mock = double('uri mock')
19
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_1, json_response_2, json_response_3)
20
+ allow(URI).to receive(:parse).and_return(uri_mock)
21
+ 3.times do
22
+ @exchange_adapter.fetch_rates!
23
+ expect( -> { @exchange_adapter.rate_for('USD') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
24
+ end
25
+ end
26
+
27
+ end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  RSpec.describe Straight::ExchangeRate::CoinbaseAdapter do
4
4
 
5
5
  before(:each) do
6
- @exchange_adapter = Straight::ExchangeRate::CoinbaseAdapter.new
6
+ @exchange_adapter = Straight::ExchangeRate::CoinbaseAdapter.instance
7
7
  end
8
8
 
9
9
  it "finds the rate for currency code" do
@@ -11,4 +11,17 @@ RSpec.describe Straight::ExchangeRate::CoinbaseAdapter do
11
11
  expect( -> { @exchange_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
12
12
  end
13
13
 
14
+ it "raises exception if rate is nil" do
15
+ json_response_1 = '{}'
16
+ json_response_2 = '{"btc_to_urd":"224.41","usd_to_xpf":"105.461721","bsd_to_btc":"0.004456"}'
17
+ json_response_3 = '{"btc_to_usd":null,"usd_to_xpf":"105.461721","bsd_to_btc":"0.004456"}'
18
+ uri_mock = double('uri mock')
19
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_1, json_response_2, json_response_3)
20
+ allow(URI).to receive(:parse).and_return(uri_mock)
21
+ 3.times do
22
+ @exchange_adapter.fetch_rates!
23
+ expect( -> { @exchange_adapter.rate_for('USD') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
24
+ end
25
+ end
26
+
14
27
  end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Straight::ExchangeRate::KrakenAdapter do
4
+
5
+ before(:each) do
6
+ @exchange_adapter = Straight::ExchangeRate::KrakenAdapter.instance
7
+ end
8
+
9
+ it "finds the rate for currency code" do
10
+ expect(@exchange_adapter.rate_for('USD')).to be_kind_of(Float)
11
+ expect( -> { @exchange_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
12
+ end
13
+
14
+ it "raises exception if rate is nil" do
15
+ json_response_1 = '{"error":[],"result":{}}'
16
+ json_response_2 = '{"error":[],"result":{"XXBTZUSD":{"a":["244.95495","1"],"b":["227.88761","1"],"abc":["228.20494","0.10000000"],"v":["5.18645337","24.04033530"],"p":["234.92296","234.41356"],"t":[45,74],"l":["228.20494","228.20494"],"h":["239.36069","239.36069"],"o":"231.82976"}}}'
17
+ json_response_3 = '{"error":[],"result":{"XXBTZUSD":{"a":["244.95495","1"],"b":["227.88761","1"],"c":[null,"0.10000000"],"v":["5.18645337","24.04033530"],"p":["234.92296","234.41356"],"t":[45,74],"l":["228.20494","228.20494"],"h":["239.36069","239.36069"],"o":"231.82976"}}}'
18
+ uri_mock = double('uri mock')
19
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_1, json_response_2, json_response_3)
20
+ allow(URI).to receive(:parse).and_return(uri_mock)
21
+ 3.times do
22
+ @exchange_adapter.fetch_rates!
23
+ expect( -> { @exchange_adapter.rate_for('USD') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Straight::ExchangeRate::LocalbitcoinsAdapter do
4
+
5
+ before(:each) do
6
+ @exchange_adapter = Straight::ExchangeRate::LocalbitcoinsAdapter.instance
7
+ end
8
+
9
+ it "finds the rate for currency code" do
10
+ expect(@exchange_adapter.rate_for('USD')).to be_kind_of(Float)
11
+ expect( -> { @exchange_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
12
+ end
13
+
14
+ it "rases exception if rate is nil" do
15
+ json_response_1 = '{"USD": {}}'
16
+ json_response_2 = '{"USD": {"volume_btc": "2277.85", "rates": {"bambo": "263.78"}, "avg_1h": 287.6003904801631, "avg_24h": 253.58144543993674, "avg_12h": 252.29202866050034}}'
17
+ json_response_3 = '{"USD": {"volume_btc": "2277.85", "rates": {"last": null}, "avg_1h": 287.6003904801631, "avg_24h": 253.58144543993674, "avg_12h": 252.29202866050034}}'
18
+ uri_mock = double('uri mock')
19
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_1, json_response_2, json_response_3)
20
+ allow(URI).to receive(:parse).and_return(uri_mock)
21
+ 3.times do
22
+ @exchange_adapter.fetch_rates!
23
+ expect( -> { @exchange_adapter.rate_for('USD') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Straight::ExchangeRate::OkcoinAdapter do
4
+
5
+ before(:each) do
6
+ @exchange_adapter = Straight::ExchangeRate::OkcoinAdapter.instance
7
+ end
8
+
9
+ it "finds the rate for currency code" do
10
+ expect(@exchange_adapter.rate_for('USD')).to be_kind_of(Float)
11
+ expect( -> { @exchange_adapter.rate_for('FEDcoin') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
12
+ end
13
+
14
+ it "rases exception if rate is nil" do
15
+ json_response_1 = '{"date":"1422679981","ticker":{}}'
16
+ json_response_2 = '{"date":"1422679981","ticker":{"buy":"227.27","high":"243.55","bambo":"226.89","low":"226.0","sell":"227.74","vol":"16065.2085"}}'
17
+ json_response_3 = '{"date":"1422679981","ticker":{"buy":"227.27","high":"243.55","last":null,"low":"226.0","sell":"227.74","vol":"16065.2085"}}'
18
+ uri_mock = double('uri mock')
19
+ allow(uri_mock).to receive(:read).with(read_timeout: 4).and_return(json_response_1, json_response_2, json_response_3)
20
+ allow(URI).to receive(:parse).and_return(uri_mock)
21
+ 3.times do
22
+ @exchange_adapter.fetch_rates!
23
+ expect( -> { @exchange_adapter.rate_for('USD') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported)
24
+ end
25
+ end
26
+
27
+ end
@@ -12,6 +12,20 @@ RSpec.describe Straight::Gateway do
12
12
  @gateway.order_callbacks = []
13
13
  end
14
14
 
15
+ it "shares exchange rate adapter(s) instances between all/multiple gateway instances" do
16
+ gateway_2 = Straight::Gateway.new.tap do |g|
17
+ g.pubkey = "pubkey"
18
+ g.order_class = "Straight::Order"
19
+ g.blockchain_adapters = [@mock_adapter]
20
+ g.status_check_schedule = Straight::Gateway::DEFAULT_STATUS_CHECK_SCHEDULE
21
+ g.order_callbacks = []
22
+ end
23
+ # Checking if exchange rate adapters are the same objects for both gateways
24
+ @gateway.instance_variable_get(:@exchange_rate_adapters).each_with_index do |adapter, i|
25
+ expect(gateway_2.instance_variable_get(:@exchange_rate_adapters)[i]).to be adapter
26
+ end
27
+ end
28
+
15
29
  it "passes methods on to the available adapter" do
16
30
  @gateway.instance_variable_set('@blockchain_adapters', [@mock_adapter])
17
31
  expect(@mock_adapter).to receive(:fetch_transaction).once
@@ -27,8 +41,8 @@ RSpec.describe Straight::Gateway do
27
41
  end
28
42
 
29
43
  it "creates new orders and addresses for them" do
30
- @gateway.pubkey = MoneyTree::Master.new.to_serialized_address
31
- expected_address = MoneyTree::Node.from_serialized_address(@gateway.pubkey).node_for_path("1").to_address
44
+ @gateway.pubkey = 'xpub661MyMwAqRbcFhUeRviyfia1NdfX4BAv5zCsZ6HqsprRjdBDK8vwh3kfcnTvqNbmi5S1yZ5qL9ugZTyVqtyTZxccKZzMVMCQMhARycvBZvx'
45
+ expected_address = '1NEvrcxS3REbJgup8rMA4QvMFFSdWTLvM'
32
46
  expect(@gateway.order_for_keychain_id(amount: 1, keychain_id: 1).address).to eq(expected_address)
33
47
  end
34
48
 
@@ -47,15 +61,15 @@ RSpec.describe Straight::Gateway do
47
61
  describe "exchange rate calculation" do
48
62
 
49
63
  it "sets order amount in satoshis calculated from another currency" do
50
- adapter = Straight::ExchangeRate::BitpayAdapter.new
64
+ adapter = Straight::ExchangeRate::BitpayAdapter.instance
51
65
  allow(adapter).to receive(:rate_for).and_return(450.5412)
52
66
  @gateway.exchange_rate_adapters = [adapter]
53
67
  expect(@gateway.amount_from_exchange_rate(2252.706, currency: 'USD')).to eq(500000000)
54
68
  end
55
69
 
56
70
  it "tries various exchange adapters until one of them actually returns an exchange rate" do
57
- adapter1 = Straight::ExchangeRate::BitpayAdapter.new
58
- adapter2 = Straight::ExchangeRate::BitpayAdapter.new
71
+ adapter1 = Straight::ExchangeRate::BitpayAdapter.instance
72
+ adapter2 = Straight::ExchangeRate::BitpayAdapter.instance
59
73
  allow(adapter1).to receive(:rate_for).and_return( -> { raise "connection problem" })
60
74
  allow(adapter2).to receive(:rate_for).and_return(450.5412)
61
75
  @gateway.exchange_rate_adapters = [adapter1, adapter2]
@@ -70,6 +84,10 @@ RSpec.describe Straight::Gateway do
70
84
  expect(@gateway.amount_from_exchange_rate('0.5', currency: 'BTC', btc_denomination: :btc)).to eq(50000000)
71
85
  end
72
86
 
87
+ it "simply fetches current exchange rate for 1 BTC" do
88
+ expect(@gateway.current_exchange_rate('USD')).not_to be_nil
89
+ end
90
+
73
91
  end
74
92
 
75
93
  end
@@ -26,9 +26,9 @@ RSpec.describe Straight::Order do
26
26
  allow(@gateway).to receive(:fetch_transactions_for).with('address').and_return([])
27
27
  allow(@gateway).to receive(:status_check_schedule).and_return(Straight::Gateway::DEFAULT_STATUS_CHECK_SCHEDULE)
28
28
  [10, 20, 40, 80, 160, 320, 640].each do |i|
29
- expect(@order).to receive(:sleep).with(i).exactly(6).times
29
+ expect(@order).to receive(:sleep).with(i).exactly(20).times
30
30
  end
31
- @order.check_status_on_schedule
31
+ @order.start_periodic_status_check(duration: 25400)
32
32
  end
33
33
 
34
34
  it "gets the last transaction for the current address, caches the request" do
@@ -53,6 +53,12 @@ RSpec.describe Straight::Order do
53
53
  expect(@order.to_json).to eq('{"status":1,"amount":10,"address":"address","tid":null}')
54
54
  end
55
55
 
56
+ it "returns amount in btc as a string" do
57
+ @order.amount = 1
58
+ expect(@order.amount_in_btc).to eq(0.00000001)
59
+ expect(@order.amount_in_btc(as: :string)).to eq('0.00000001')
60
+ end
61
+
56
62
  describe "assigning statuses" do
57
63
 
58
64
  before(:each) do
@@ -65,6 +71,11 @@ RSpec.describe Straight::Order do
65
71
  @order.status
66
72
  end
67
73
 
74
+ it "sets status to :new upon order creation" do
75
+ expect(@order.instance_variable_get(:@status)).to eq(0)
76
+ expect(@order.instance_variable_get(:@old_status)).to eq(nil)
77
+ end
78
+
68
79
  it "sets status to :new if no transaction issued" do
69
80
  expect(@order).to receive(:transaction).at_most(3).times.and_return(nil)
70
81
  expect(@order.status(reload: true)).to eq(0)
@@ -107,6 +118,11 @@ RSpec.describe Straight::Order do
107
118
  expect(@order.instance_variable_get(:@original_status_setter_called)).to be_truthy
108
119
  end
109
120
 
121
+ it "saves the old status in the old_status property" do
122
+ @order.status = 2
123
+ expect(@order.old_status).to eq(0)
124
+ end
125
+
110
126
  end
111
127
 
112
128
  end
data/straight.gemspec ADDED
@@ -0,0 +1,95 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: straight 0.2.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "straight"
9
+ s.version = "0.2.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Roman Snitko"]
14
+ s.date = "2015-05-05"
15
+ s.description = "An engine for the Straight payment gateway software. Requires no state to be saved (that is, no storage or DB). Its responsibilities only include processing data coming from an actual gateway."
16
+ s.email = "roman.snitko@gmail.com"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "LICENSE.txt",
27
+ "README.md",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "lib/straight.rb",
31
+ "lib/straight/blockchain_adapter.rb",
32
+ "lib/straight/blockchain_adapters/biteasy_adapter.rb",
33
+ "lib/straight/blockchain_adapters/blockchain_info_adapter.rb",
34
+ "lib/straight/blockchain_adapters/mycelium_adapter.rb",
35
+ "lib/straight/exchange_rate_adapter.rb",
36
+ "lib/straight/exchange_rate_adapters/average_rate_adapter.rb",
37
+ "lib/straight/exchange_rate_adapters/bitpay_adapter.rb",
38
+ "lib/straight/exchange_rate_adapters/bitstamp_adapter.rb",
39
+ "lib/straight/exchange_rate_adapters/btce_adapter.rb",
40
+ "lib/straight/exchange_rate_adapters/coinbase_adapter.rb",
41
+ "lib/straight/exchange_rate_adapters/kraken_adapter.rb",
42
+ "lib/straight/exchange_rate_adapters/localbitcoins_adapter.rb",
43
+ "lib/straight/exchange_rate_adapters/okcoin_adapter.rb",
44
+ "lib/straight/gateway.rb",
45
+ "lib/straight/order.rb",
46
+ "spec/lib/blockchain_adapters/biteasy_adapter_spec.rb",
47
+ "spec/lib/blockchain_adapters/blockchain_info_adapter_spec.rb",
48
+ "spec/lib/blockchain_adapters/mycelium_adapter_spec.rb",
49
+ "spec/lib/exchange_rate_adapter_spec.rb",
50
+ "spec/lib/exchange_rate_adapters/average_rate_adapter_spec.rb",
51
+ "spec/lib/exchange_rate_adapters/bitpay_adapter_spec.rb",
52
+ "spec/lib/exchange_rate_adapters/bitstamp_adapter_spec.rb",
53
+ "spec/lib/exchange_rate_adapters/btce_adapter_spec.rb",
54
+ "spec/lib/exchange_rate_adapters/coinbase_adapter_spec.rb",
55
+ "spec/lib/exchange_rate_adapters/kraken_adapter_spec.rb",
56
+ "spec/lib/exchange_rate_adapters/localbitcoins_adapter_spec.rb",
57
+ "spec/lib/exchange_rate_adapters/okcoin_adapter_spec.rb",
58
+ "spec/lib/gateway_spec.rb",
59
+ "spec/lib/order_spec.rb",
60
+ "spec/spec_helper.rb",
61
+ "straight.gemspec"
62
+ ]
63
+ s.homepage = "http://github.com/snitko/straight"
64
+ s.licenses = ["MIT"]
65
+ s.rubygems_version = "2.4.5"
66
+ s.summary = "An engine for the Straight payment gateway software"
67
+
68
+ if s.respond_to? :specification_version then
69
+ s.specification_version = 4
70
+
71
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
72
+ s.add_runtime_dependency(%q<money-tree>, [">= 0"])
73
+ s.add_runtime_dependency(%q<satoshi-unit>, [">= 0"])
74
+ s.add_runtime_dependency(%q<httparty>, [">= 0"])
75
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
76
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
77
+ s.add_development_dependency(%q<github_api>, ["= 0.11.3"])
78
+ else
79
+ s.add_dependency(%q<money-tree>, [">= 0"])
80
+ s.add_dependency(%q<satoshi-unit>, [">= 0"])
81
+ s.add_dependency(%q<httparty>, [">= 0"])
82
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
83
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
84
+ s.add_dependency(%q<github_api>, ["= 0.11.3"])
85
+ end
86
+ else
87
+ s.add_dependency(%q<money-tree>, [">= 0"])
88
+ s.add_dependency(%q<satoshi-unit>, [">= 0"])
89
+ s.add_dependency(%q<httparty>, [">= 0"])
90
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
91
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
92
+ s.add_dependency(%q<github_api>, ["= 0.11.3"])
93
+ end
94
+ end
95
+