fyb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db2d4ceddaf476cfaaa7a41d973295bf705fa4dd
4
+ data.tar.gz: f116183fc3a61ed1e457a027ae752e060a112b74
5
+ SHA512:
6
+ metadata.gz: 0a550671244a3ad68ff13a314096dd70348ca98f284f9da31a5c9cb5cdb059d157f5d7dae0de973e466565ef1fedf6dfe51fbc8d99a42ad883d0ba6ecf9317b5
7
+ data.tar.gz: b52c2eb729b74f7c8c731d56742d9fcdc3dfd9c4d2ce2a7a850739944f8ea2e15aff98888ce1dc411f28d9798aeb48e4476c1e2c133bcc1379a8b6ce3995a5d4
data/.gitignore ADDED
@@ -0,0 +1,45 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+
24
+ ## Documentation cache and generated files:
25
+ /.yardoc/
26
+ /_yardoc/
27
+ /doc/
28
+ /rdoc/
29
+ /html/
30
+
31
+ ## Environment normalisation:
32
+ /.bundle/
33
+ /lib/bundler/man/
34
+
35
+ # for a library or gem, you might want to ignore these files since the code is
36
+ # intended to run in multiple environments; otherwise, check them in:
37
+ # Gemfile.lock
38
+ # .ruby-version
39
+ # .ruby-gemset
40
+
41
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
42
+ .rvmrc
43
+
44
+ \#*#
45
+ .#*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ LineLength:
2
+ Max: 120
3
+
4
+ AllCops:
5
+ Excludes:
6
+ - spec/spec_helper.rb
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fyb.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Henrik Lundberg
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Fyb
2
+
3
+ FYB API v1 implementation.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'fyb'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install fyb
18
+
19
+ ## Usage
20
+
21
+ Use the command-line binary to get the current bid/ask price.
22
+
23
+ ```
24
+ $ fyb
25
+ Bid: 3690.54 Ask: 3870.21
26
+
27
+ $ fyb --sek
28
+ Bid: 3690.54 Ask: 3870.21
29
+
30
+ $ fyb --sgd
31
+ Bid: 3690.54 Ask: 3870.21 # the api currently returns the wrong currency
32
+ ```
33
+
34
+ Please look in the source code for documentation or generate rdocs.
35
+
36
+ A short example follows:
37
+
38
+ ```ruby
39
+ require 'rubygems'
40
+ require 'fyb'
41
+
42
+ puts Fyb.ask # default currency is SEK
43
+ puts Fyb.bid
44
+
45
+ # To use the private API you need to authorize
46
+ Fyb::Configuration.configure do |config|
47
+ config.currency = :sek # or :sgd
48
+ config.key = 'FYBSE-API-KEY'
49
+ config.sig = 'FYBSE-API-SECRET'
50
+ end
51
+
52
+ Fyb.test # => returns true if authorized
53
+
54
+ # you can either place an order by doing
55
+ order = Fyb.sell! 0.11, Fyb.bid # creates an Order object and performs it
56
+ # you can also use the market price
57
+ order = Fyb.buy! 0.11, :market
58
+
59
+ order.cancel! if order.pending?
60
+
61
+ # or by creating the order and then performing it on your own
62
+ order = Fyb::Order.new 0.11, Fyb.ask, :buy
63
+ order.perform.cancel!
64
+ ```
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it ( http://github.com/Velfolt/fyb/fork )
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require 'rdoc'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", :rerdoc => "rdoc:force")
8
+
9
+ task :default => :spec
data/bin/fyb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'optparse'
7
+ require 'fyb'
8
+
9
+ opt_parser = OptionParser.new do |opt|
10
+ opt.banner = 'Usage: fyb [OPTIONS]'
11
+
12
+ opt.on('-s', '--sek', 'swedish crown') do
13
+ Fyb::Configuration.currency = :sek
14
+ end
15
+
16
+ opt.on('-g', '--sgd', 'singapore dollar') do
17
+ Fyb::Configuration.currency = :sgd
18
+ end
19
+
20
+ opt.on('-h', '--help', 'help') do
21
+ puts opt_parser
22
+ end
23
+ end
24
+
25
+ opt_parser.parse!
26
+
27
+ puts "Bid: #{Fyb.bid.money} Ask: #{Fyb.ask.money}"
data/fyb.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fyb/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fyb"
8
+ spec.version = Fyb::VERSION
9
+ spec.authors = ["Henrik Lundberg"]
10
+ spec.email = ["velfolt@gmail.com"]
11
+ spec.summary = %q{FYB v1 API implementation}
12
+ spec.description = %q{FYB v1 API implementation for easy access}
13
+ spec.homepage = "https://github.com/Velfolt/fyb"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_runtime_dependency 'weary', '~> 1.1.3'
25
+ spec.add_runtime_dependency 'ruby-hmac', '~> 0.4.0'
26
+ spec.add_runtime_dependency 'json'
27
+ spec.add_runtime_dependency 'promise'
28
+ end
@@ -0,0 +1,40 @@
1
+ module Fyb
2
+ module API
3
+ # ==== The private API
4
+ #
5
+ # You can use this directly instead of Fyb::Client if you want.
6
+ #
7
+ # ==== Examples
8
+ #
9
+ # body = Fyb.private.test.perform.parse
10
+ #
11
+ # order = Fyb.private.placeorder(:qty => 1.5, :price => 100, 'B').perform.parse
12
+ class Private < Weary::Client
13
+ use Middleware::Timestamper
14
+ use Middleware::Authorize
15
+ use Middleware::Parser
16
+
17
+ domain Fyb::Configuration.domain
18
+ headers 'Content-Type' => 'application/x-www-form-urlencoded'
19
+
20
+ # This is a hack to let the RACK middleware add a timestamp.
21
+ optional :timestamp
22
+
23
+ post :test, 'test'
24
+ post :getaccinfo, 'getaccinfo'
25
+ post :getpendingorders, 'getpendingorders'
26
+
27
+ post :getorderhistory, 'getorderhistory' do |resource|
28
+ resource.required :limit
29
+ end
30
+
31
+ post :cancelpendingorder, 'cancelpendingorder' do |resource|
32
+ resource.required :orderNo
33
+ end
34
+
35
+ post :placeorder, 'placeorder' do |resource|
36
+ resource.required :qty, :price, :type
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,23 @@
1
+ module Fyb
2
+ module API
3
+ # ==== The public API
4
+ #
5
+ # You can access the API directly instead of using Fyb::Client.
6
+ #
7
+ # = Examples
8
+ #
9
+ # ticker = Fyb.public.ticker.perform.parse
10
+ # ticker['ask']
11
+ class Public < Weary::Client
12
+ use Middleware::Parser
13
+
14
+ domain Fyb::Configuration.domain
15
+
16
+ get :ticker, 'ticker.json'
17
+ get :orderbook, 'orderbook.json'
18
+ get :trades, 'trades.json' do |resource|
19
+ resource.optional :since
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/fyb/client.rb ADDED
@@ -0,0 +1,84 @@
1
+ module Fyb
2
+ # Client class containing all the methods needed to buy and sell btc.
3
+ class Client
4
+ # Returns the current ask price.
5
+ def ask
6
+ BigDecimal Fyb.public.ticker.perform.parse['ask'], 2
7
+ end
8
+
9
+ # Returns the current bid price.
10
+ def bid
11
+ BigDecimal Fyb.public.ticker.perform.parse['bid'], 2
12
+ end
13
+
14
+ # Returns a couple of the last asks and bids.
15
+ def orderbook
16
+ Fyb.public.orderbook.perform.parse
17
+ end
18
+
19
+ # Returns trades.
20
+ #
21
+ # Fyb.trades
22
+ # Fyb.trades Time.now.to_i
23
+ #
24
+ # * +tid+ tradeid to begin history from
25
+ def trades(tid = nil)
26
+ params = { since: tid } unless tid.nil?
27
+ params ||= {}
28
+
29
+ plain_orders = Fyb.public.trades(params).perform.parse
30
+
31
+ return [] if plain_orders.empty?
32
+
33
+ plain_orders.map do |data|
34
+ Order.new data['amount'], data['price'], :undefined, data['tid']
35
+ end
36
+ end
37
+
38
+ # Returns true if the authorization key and signature was correct.
39
+ def test
40
+ data = Fyb.private.test.perform.parse
41
+ data['msg'] == 'success'
42
+ end
43
+
44
+ # Creates and performs a buy order.
45
+ #
46
+ # Returns the order.
47
+ def buy!(qty, price)
48
+ order = Fyb::Order.new qty, price, :buy
49
+ order.perform
50
+ end
51
+
52
+ # Creates and performs a sell order.
53
+ #
54
+ # Returns the order.
55
+ def sell!(qty, price)
56
+ order = Fyb::Order.new qty, price, :sell
57
+ order.perform
58
+ end
59
+
60
+ # Returns your currenct balance and the currency you have configured.
61
+ def balance
62
+ wallet = Fyb.private.getaccinfo.perform.parse
63
+ btc_label = 'btcBal'
64
+ money_label = Fyb::Configuration.currency.to_s + 'Bal'
65
+
66
+ btc = BigDecimal.new wallet[btc_label]
67
+ real_money = BigDecimal.new wallet[money_label]
68
+
69
+ { :btc => btc, Fyb::Configuration.currency => real_money }
70
+ end
71
+
72
+ # Returns your order history.
73
+ def order_history(limit = 10)
74
+ plain_orders = Fyb.private.getorderhistory(limit: limit).perform.parse
75
+ error = plain_orders['error']
76
+
77
+ fail Exception, error unless error == 0
78
+
79
+ plain_orders['orders'].map do |data|
80
+ Order.new data['qty'], data['price'], data['type'] == 'B' ? :buy : :sell, data['ticket']
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,37 @@
1
+ module Fyb
2
+ # Configuration class that sets the default values if needed. Call this using:
3
+ #
4
+ # Fyb::Configuration.configure do |config|
5
+ # config.currency = :sek
6
+ # config.key = 'your-fyb-key'
7
+ # config.sig = 'your-fyb-secret'
8
+ # end
9
+ module Configuration
10
+ module_function
11
+
12
+ class << self
13
+ attr_accessor :key, :sig, :currency
14
+
15
+ APIS = {
16
+ sek: 'https://www.fybse.se/api/SEK/',
17
+ sgd: 'https://www.fybsg.com/api/SGD/',
18
+ test: 'https://fyb.apiary.io/'
19
+ }
20
+
21
+ def currency
22
+ @currency ||= :sek
23
+ @currency
24
+ end
25
+
26
+ def domain
27
+ return APIS[:sek] if currency.nil?
28
+
29
+ APIS[currency]
30
+ end
31
+
32
+ def configure
33
+ yield self
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ require 'hmac-sha1'
2
+
3
+ module Fyb
4
+ module Middleware
5
+ # Adds the key and secret signature to the weary request
6
+ class Authorize
7
+ def initialize(app)
8
+ @app = app
9
+
10
+ @key = Fyb::Configuration.key
11
+ @sig = Fyb::Configuration.sig
12
+ end
13
+
14
+ def call(env)
15
+ env.update 'HTTP_SIG' => generate_signature(env), 'HTTP_KEY' => @key
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ def generate_signature(env)
21
+ body = env['weary.request'].body.string
22
+
23
+ hmac = HMAC::SHA1.new(@sig)
24
+ hmac.update(body)
25
+ hmac.hexdigest
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ module Fyb
2
+ module Middleware
3
+ # Correct the Content-Type of the replies from Fyb
4
+ class Parser
5
+ include Rack::Utils
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ status, headers, response = @app.call(env)
13
+
14
+ headers = HeaderHash.new(headers)
15
+
16
+ if headers.key?('Content-Type') && headers['Content-Type'].include?('text/html; charset=utf-8')
17
+ headers['Content-Type'] = [headers['Content-Type'][0].gsub('text/html', 'application/json')]
18
+ end
19
+
20
+ [status, headers, response]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ module Fyb
2
+ module Middleware
3
+ # Add timestamp to the request
4
+ class Timestamper
5
+ include Rack::Utils
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ body = env['weary.request'].body
13
+
14
+ timestamp = "timestamp=#{Time.now.to_i}"
15
+ timestamp = '&' + timestamp if body.length > 0
16
+
17
+ env['rack.input'].write(body.string)
18
+ env['rack.input'].write(timestamp)
19
+ env['rack.input'].rewind
20
+
21
+ @app.call(env)
22
+ end
23
+ end
24
+ end
25
+ end
data/lib/fyb/order.rb ADDED
@@ -0,0 +1,80 @@
1
+ module Fyb
2
+ # Handles a Fyb order.
3
+ #
4
+ # order = Order.new 1, :market, :buy
5
+ # order.perform
6
+ #
7
+ # or
8
+ #
9
+ # order = Order.new 1, 1234, :sell
10
+ # order.perform
11
+ class Order
12
+ attr_reader :qty, :price, :type, :order_id, :timestamp
13
+
14
+ FEE = BigDecimal '0.008'
15
+ ORDER_TYPES = { buy: 'B', sell: 'S', undefined: nil }
16
+
17
+ def initialize(qty, price, type, order_id = nil)
18
+ fail ArgumentError, 'type must be :buy or :sell' unless ORDER_TYPES.keys.member? type
19
+
20
+ @qty = BigDecimal(qty, 8)
21
+ @price = BigDecimal(price, 2) unless price == :market
22
+ @price ||= price
23
+ @type = ORDER_TYPES[type]
24
+ @order_id = order_id
25
+ end
26
+
27
+ def qty_after_fee
28
+ @qty * (BigDecimal(1) - FEE)
29
+ end
30
+
31
+ def money_after_fee
32
+ price = @price
33
+ price = @type == 'B' ? Fyb.ask : Fyb.bid if price == :market
34
+
35
+ qty_after_fee.in_money(price)
36
+ end
37
+
38
+ def perform
39
+ return self unless @order_id.nil? || @type.nil?
40
+
41
+ future do
42
+ @price = @type == 'B' ? Fyb.ask : Fyb.bid if @price == :market
43
+
44
+ body = Fyb.private.placeorder(qty: @qty.btc, price: @price.money, type: @type).perform.parse
45
+ error = body['error']
46
+ fail Exception, error unless error == 0
47
+
48
+ @order_id = body['pending_oid'].to_i
49
+
50
+ self
51
+ end
52
+ end
53
+
54
+ def cancel!
55
+ return false if @order_id.nil?
56
+
57
+ body = Fyb.private.cancelpendingorder(orderNo: @order_id).perform.parse
58
+ error = body['error']
59
+ fail Exception, error unless error == 0
60
+
61
+ true
62
+ end
63
+
64
+ def pending?
65
+ return false if @order_id.nil?
66
+
67
+ body = Fyb.private.getpendingorders.perform.parse
68
+ error = body['error']
69
+ fail Exception, error unless error == 0
70
+
71
+ return false if body['orders'].nil?
72
+
73
+ body['orders'].each do |order|
74
+ return true if order['ticket'] == @order_id
75
+ end
76
+
77
+ false
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,20 @@
1
+ # Utility functions for BigDecimal
2
+ class BigDecimal
3
+ # Returns a rounded to 8 string
4
+ def btc
5
+ round(8).to_s('F')
6
+ end
7
+
8
+ # Returns a rounded to 2 string
9
+ def money
10
+ round(2).to_s('F')
11
+ end
12
+
13
+ # Returns a BigDecimal with the bitcoin amount converted into real currency
14
+ def in_money(price)
15
+ price = Fyb.ask if price == :ask
16
+ price = Fyb.bid if price == :bid
17
+
18
+ self * BigDecimal(price)
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ #:nodoc:
2
+ module Fyb
3
+ VERSION = '0.0.1'
4
+ end
data/lib/fyb.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'weary'
2
+ require 'json'
3
+ require 'future'
4
+ require 'stringio'
5
+ require 'bigdecimal'
6
+
7
+ require 'fyb/version'
8
+ require 'fyb/client'
9
+ require 'fyb/configuration'
10
+ require 'fyb/order'
11
+ require 'fyb/middleware/authorize'
12
+ require 'fyb/middleware/parser'
13
+ require 'fyb/middleware/timestamper'
14
+ require 'fyb/api/public'
15
+ require 'fyb/api/private'
16
+ require 'fyb/util/bigdecimal'
17
+
18
+ # Fyb is an implementation of the FYB v1 API.
19
+ module Fyb
20
+ module_function
21
+
22
+ class << self
23
+ def public
24
+ @public ||= API::Public.new
25
+ @public
26
+ end
27
+
28
+ def private
29
+ @private ||= API::Private.new
30
+ @private
31
+ end
32
+
33
+ def client
34
+ @client ||= Fyb::Client.new
35
+ @client
36
+ end
37
+
38
+ def method_missing(method, *args, &block)
39
+ client.send(method, *args, &block)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fyb::Client do
4
+ let(:client) { Fyb::Client.new }
5
+
6
+ context 'ticker' do
7
+ before { Fyb.stub_chain(:public, :ticker, :perform).and_return JsonData.ticker }
8
+
9
+ describe '#ask' do
10
+ subject { client.ask }
11
+
12
+ it { should eq 3500 }
13
+ end
14
+
15
+ describe '#bid' do
16
+ subject { client.bid }
17
+
18
+ it { should eq 3600 }
19
+ end
20
+ end
21
+
22
+ describe '#orderbook' do
23
+ before { Fyb.stub_chain(:public, :orderbook, :perform).and_return JsonData.orderbook }
24
+ subject { client.orderbook }
25
+
26
+ it { should include 'asks' }
27
+ it { should include 'bids' }
28
+ end
29
+
30
+ describe '#trades' do
31
+ before { Fyb.stub_chain(:public, :trades, :perform).and_return JsonData.trades }
32
+ subject { client.trades }
33
+
34
+ context 'with since' do
35
+ subject { client.trades Time.now.to_i - 100 }
36
+ end
37
+
38
+ context 'without since' do
39
+ it { should be_an_instance_of Array }
40
+ end
41
+ end
42
+
43
+ describe '#test' do
44
+ subject { client.test }
45
+
46
+ context 'when successful authorization' do
47
+ before { Fyb.stub_chain(:private, :test, :perform).and_return JsonData.test_success }
48
+
49
+ it { should be_true }
50
+ end
51
+
52
+ context 'when failed authorization' do
53
+ before { Fyb.stub_chain(:private, :test, :perform).and_return JsonData.test_fail }
54
+
55
+ it { should be_false }
56
+ end
57
+ end
58
+
59
+ context 'order' do
60
+ before { Fyb.stub_chain(:private, :placeorder, :perform).and_return JsonData.order }
61
+
62
+ context 'buy! returns order' do
63
+ subject { client.buy!(0.11, 1234) }
64
+
65
+ it { should be_an_instance_of Fyb::Order }
66
+ end
67
+
68
+ context 'sell! returns order' do
69
+ subject { client.sell!(0.11, 1234) }
70
+
71
+ it { should be_an_instance_of Fyb::Order }
72
+ end
73
+ end
74
+
75
+ describe '#balance' do
76
+ before { Fyb.stub_chain(:private, :getaccinfo, :perform).and_return JsonData.getaccinfo_sek }
77
+ subject { client.balance }
78
+
79
+ it { should include :btc }
80
+
81
+ context 'currency = :sek' do
82
+ before { Fyb::Configuration.currency = :sek }
83
+
84
+ it { should include :sek }
85
+ end
86
+
87
+ context 'currency = :sgd' do
88
+ before do
89
+ Fyb.stub_chain(:private, :getaccinfo, :perform).and_return JsonData.getaccinfo_sgd
90
+ Fyb::Configuration.currency = :sgd
91
+ end
92
+
93
+ it { should include :sgd }
94
+ end
95
+ end
96
+
97
+ describe '#order_history' do
98
+ before { Fyb.stub_chain(:private, :getorderhistory, :perform).and_return JsonData.getorderhistory }
99
+ subject { client.order_history }
100
+
101
+ it { should be_an_instance_of Array }
102
+ end
103
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fyb::Configuration do
4
+ describe '.configure' do
5
+ context 'default settings' do
6
+ before { Fyb::Configuration.currency = nil }
7
+ its(:currency) { should eq :sek }
8
+ end
9
+
10
+ context 'explicit settings' do
11
+ before do
12
+ Fyb::Configuration.configure do |config|
13
+ config.key = 'testkey'
14
+ config.sig = 'testsig'
15
+ config.currency = :test
16
+ end
17
+ end
18
+
19
+ its(:key) { should eq 'testkey' }
20
+ its(:sig) { should eq 'testsig' }
21
+ its(:currency) { should eq :test }
22
+ end
23
+ end
24
+
25
+ describe '.domain' do
26
+ subject { Fyb::Configuration.domain }
27
+
28
+ context ':sek' do
29
+ before { Fyb::Configuration.currency = :sek }
30
+
31
+ it { should eq 'https://www.fybse.se/api/SEK/' }
32
+ end
33
+
34
+ context ':sgd' do
35
+ before { Fyb::Configuration.currency = :sgd }
36
+
37
+ it { should eq 'https://www.fybsg.com/api/SGD/' }
38
+ end
39
+
40
+ context ':test' do
41
+ before { Fyb::Configuration.currency = :test }
42
+
43
+ it { should eq 'https://fyb.apiary.io/' }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fyb::Order do
4
+ before { Fyb.stub_chain(:private, :placeorder, :perform).and_return JsonData.order }
5
+ let(:order) { Fyb::Order.new 0.11, 100, :buy }
6
+
7
+ describe '#qty_after_fee' do
8
+ subject { order.qty_after_fee }
9
+
10
+ it { should eq BigDecimal('0.10912') }
11
+ end
12
+
13
+ describe '#money_after_fee' do
14
+ subject { order.money_after_fee }
15
+
16
+ it { should eq BigDecimal('10.912') }
17
+ end
18
+
19
+ describe '#perform' do
20
+ subject { order.perform }
21
+
22
+ its(:order_id) { should eq 28 }
23
+ end
24
+
25
+ describe '#cancel!' do
26
+ before { Fyb.stub_chain(:private, :cancelpendingorder, :perform).and_return JsonData.cancelpendingorder }
27
+ subject { order.cancel! }
28
+
29
+ context 'pending' do
30
+ subject { order.perform }
31
+
32
+ it { should be_true }
33
+ end
34
+
35
+ context 'not pending' do
36
+ it { should be_false }
37
+ end
38
+ end
39
+
40
+ describe '#pending?' do
41
+ before { Fyb.stub_chain(:private, :getpendingorders, :perform).and_return JsonData.getpendingorders }
42
+
43
+ context 'has order_id' do
44
+ subject { order.perform.pending? }
45
+ it { should be_true }
46
+ end
47
+
48
+ context 'not pending' do
49
+ subject { order.pending? }
50
+ it { should be_false }
51
+ end
52
+ end
53
+ end
data/spec/fyb_spec.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fyb do
4
+ describe 'version' do
5
+ subject { Fyb::VERSION }
6
+
7
+ it { should_not be_nil }
8
+ end
9
+
10
+ describe BigDecimal do
11
+ describe '#btc' do
12
+ subject { BigDecimal('.11111111').btc }
13
+
14
+ it { should eq '0.11111111' }
15
+ end
16
+
17
+ describe '#money' do
18
+ subject { BigDecimal('3500').money }
19
+
20
+ it { should eq '3500.0' }
21
+ end
22
+
23
+ describe '#in_money' do
24
+ subject { BigDecimal('2.0').in_money(1000) }
25
+
26
+ it { should eq BigDecimal('2000') }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,70 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'fyb'
3
+
4
+ def response(rawJson)
5
+ Weary::Response.new(rawJson,
6
+ 200,
7
+ 'Content-Type' => 'application/json')
8
+ end
9
+
10
+ def verify(object)
11
+ RSpec::Mocks.proxy_for(object).verify
12
+ end
13
+
14
+ def reset(object)
15
+ RSpec::Mocks.proxy_for(object).reset
16
+ end
17
+
18
+ RSpec.configure do |config|
19
+ config.expect_with :rspec do |c|
20
+ c.syntax = :expect
21
+ end
22
+ end
23
+
24
+ class JsonData
25
+ class << self
26
+ def ticker
27
+ response('{"ask":3500.00,"bid":3600.00}')
28
+ end
29
+
30
+ def orderbook
31
+ response('{"asks":[["1194.90","0.50000000"],["1195.00","0.17295600"],["1198.80","1.25000000"]],"bids":[["1127.00","1.03075421"],["1126.10","2.00000000"],["1106.00","0.50000000"],["1105.50","1.24000000"]]}')
32
+ end
33
+
34
+ def test_success
35
+ response('{"error":0,"msg":"success"}')
36
+ end
37
+
38
+ def test_fail
39
+ response('{"error":0,"msg":"unsuccessful"}')
40
+ end
41
+
42
+ def order
43
+ response('{"error":0, "msg":"", "pending_oid":"28"}')
44
+ end
45
+
46
+ def cancelpendingorder
47
+ response('{"error":0}')
48
+ end
49
+
50
+ def getpendingorders
51
+ response('{"error":0,"orders":[{"date":1387099682,"price":"5.00","qty":"0.99000000","ticket":28,"type":"S"},{"date":1386932631,"price":"2.00","qty":"0.99000000","ticket":5,"type":"B"},{"date":1386099367,"price":"1.00","qty":"1.00000000","ticket":4,"type":"B"}]}')
52
+ end
53
+
54
+ def trades
55
+ response('[{"amount":"1.00000000","date":1386935056,"price":"1161.00","tid":27350},{"amount":"0.18000000","date":1386937603,"price":"1161.00","tid":27372},{"amount":"0.01651380","date":1386937959,"price":"1127.00","tid":27379}]')
56
+ end
57
+
58
+ def getaccinfo_sgd
59
+ response('{"accNo":1234,"btcBal":"23.00000000","btcDeposit":"1FkrHkVAFg5Jn3s2njdnWFcbizMYbb423W","email":"goondoo@hotmail.com","error":0,"sgdBal":"57.50"}')
60
+ end
61
+
62
+ def getaccinfo_sek
63
+ response('{"accNo":1234,"btcBal":"23.00000000","btcDeposit":"1FkrHkVAFg5Jn3s2njdnWFcbizMYbb423W","email":"goondoo@hotmail.com","error":0,"sekBal":"57.50"}')
64
+ end
65
+
66
+ def getorderhistory
67
+ response('{"error":0,"orders":[{"date_created":1387971414,"date_executed":1387971414,"price":"S$3.00","qty":"2.00000000BTC","status":"A","ticket":11,"type":"B"},{"date_created":1387971314,"date_executed":1387971414,"price":"S$3.00","qty":"2.00000000BTC","status":"F","ticket":6,"type":"S"},{"date_created":1387971414,"date_executed":1387971414,"price":"S$5.00","qty":"1.00000000BTC","status":"A","ticket":12,"type":"B"},{"date_created":1387971306,"date_executed":1387971414,"price":"S$5.00","qty":"1.00000000BTC","status":"F","ticket":5,"type":"S"},{"date_created":1387971398,"date_executed":1387971398,"price":"S$2.50","qty":"1.00000000BTC","status":"F","ticket":10,"type":"B"},{"date_created":1387971335,"date_executed":1387971398,"price":"S$2.50","qty":"1.00000000BTC","status":"F","ticket":8,"type":"S"}]}')
68
+ end
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fyb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Henrik Lundberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: weary
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: ruby-hmac
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.4.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.4.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: json
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: promise
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: FYB v1 API implementation for easy access
112
+ email:
113
+ - velfolt@gmail.com
114
+ executables:
115
+ - fyb
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - ".rubocop.yml"
122
+ - ".travis.yml"
123
+ - Gemfile
124
+ - LICENSE.txt
125
+ - README.md
126
+ - Rakefile
127
+ - bin/fyb
128
+ - fyb.gemspec
129
+ - lib/fyb.rb
130
+ - lib/fyb/api/private.rb
131
+ - lib/fyb/api/public.rb
132
+ - lib/fyb/client.rb
133
+ - lib/fyb/configuration.rb
134
+ - lib/fyb/middleware/authorize.rb
135
+ - lib/fyb/middleware/parser.rb
136
+ - lib/fyb/middleware/timestamper.rb
137
+ - lib/fyb/order.rb
138
+ - lib/fyb/util/bigdecimal.rb
139
+ - lib/fyb/version.rb
140
+ - spec/fyb/client_spec.rb
141
+ - spec/fyb/configuration_spec.rb
142
+ - spec/fyb/order_spec.rb
143
+ - spec/fyb_spec.rb
144
+ - spec/spec_helper.rb
145
+ homepage: https://github.com/Velfolt/fyb
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.2.0
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: FYB v1 API implementation
169
+ test_files:
170
+ - spec/fyb/client_spec.rb
171
+ - spec/fyb/configuration_spec.rb
172
+ - spec/fyb/order_spec.rb
173
+ - spec/fyb_spec.rb
174
+ - spec/spec_helper.rb