fyb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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