vaultoro 0.1.0

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.
@@ -0,0 +1,12 @@
1
+ module Vaultoro
2
+ module BasicAPI
3
+ class Trade
4
+ include Virtus.model
5
+
6
+ attribute :transaction_id, Integer
7
+ attribute :price, Float
8
+ attribute :amount, Float
9
+ attribute :time, Time
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Vaultoro
2
+ module BasicAPI
3
+ class Transaction
4
+ include Virtus.model
5
+
6
+ attribute :time, Time
7
+ attribute :gold_amount, Float
8
+ attribute :gold_price, Float
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ module Vaultoro
2
+ module BasicAPI
3
+ class Transactions < Base
4
+ attribute :time, String # Allowed values: "hour", "day", "month"
5
+ attribute :list, Array[Transaction]
6
+
7
+ def fetch
8
+ @errors.clear
9
+
10
+ ensure_attribute_has_value :time
11
+
12
+ @errors << ":time argument must be either 'hour', 'day' or 'month'" unless ["hour", "day", "month"].include?(@time)
13
+
14
+ return false if @errors.any?
15
+
16
+ response = Client.get("/transactions/#{@time}", {})
17
+ code = response.code rescue ""
18
+
19
+ case code
20
+ when '200'
21
+ hash = JSON.parse(response.body)
22
+ @status = hash['status'].upcase
23
+
24
+ if @status == 'SUCCESS'
25
+ hash['data'].each do |transaction|
26
+ @list << Transaction.new(
27
+ time: DateTime.strptime(transaction['Time'], '%Y-%m-%dT%H:%M:%S.%L%z').to_time.utc,
28
+ gold_price: transaction['Gold_Price'].to_f,
29
+ gold_amount: transaction['Gold_Amount'].to_f
30
+ )
31
+ end
32
+ else
33
+ set_errors(response)
34
+ return false
35
+ end
36
+
37
+ return true
38
+ else
39
+ set_errors(response)
40
+ return false
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,72 @@
1
+ module Vaultoro
2
+ class Configuration
3
+ attr_writer :credentials
4
+
5
+ def api_key
6
+ Vaultoro.credentials[Vaultoro.environment][:api_key]
7
+ end
8
+
9
+ def api_key=(value)
10
+ Vaultoro.credentials[Vaultoro.environment][:api_key] = value
11
+ end
12
+
13
+ def api_secret
14
+ Vaultoro.credentials[Vaultoro.environment][:api_secret]
15
+ end
16
+
17
+ def api_secret=(value)
18
+ Vaultoro.credentials[Vaultoro.environment][:api_secret] = value
19
+ end
20
+
21
+ def api_uri
22
+ Vaultoro.credentials[Vaultoro.environment][:api_uri]
23
+ end
24
+
25
+ def api_uri=(value)
26
+ Vaultoro.credentials[Vaultoro.environment][:api_uri] = value
27
+ end
28
+
29
+ def api_version
30
+ Vaultoro.credentials[Vaultoro.environment][:api_version]
31
+ end
32
+
33
+ def api_version=(value)
34
+ Vaultoro.credentials[Vaultoro.environment][:api_version] = value
35
+ end
36
+
37
+ def credentials
38
+ @credentials ||= {
39
+ :production => {
40
+ :api_key => ENV['VAULTORO_API_KEY'],
41
+ :api_secret => ENV['VAULTORO_API_SECRET'],
42
+ :api_uri => "https://api.vaultoro.com",
43
+ :api_version => 1
44
+ },
45
+ :test => {
46
+ :api_key => "testapi",
47
+ :api_secret => "testpass",
48
+ :api_uri => "https://api.vaultoro.com",
49
+ :api_version => 1
50
+ },
51
+ :development => {
52
+ :api_key => "testapi",
53
+ :api_secret => "testpass",
54
+ :api_uri => "https://api.vaultoro.com",
55
+ :api_version => 1
56
+ }
57
+ }
58
+ end
59
+
60
+ def environment
61
+ @environment ||= :production
62
+ end
63
+
64
+ def environment=(value)
65
+ @environment = value.is_a?(String) ? value.to_sym : value
66
+ end
67
+
68
+ def environments
69
+ Vaultoro.credentials.keys
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,11 @@
1
+ module Vaultoro
2
+ module TradingAPI
3
+ class Balance
4
+ include Virtus.model
5
+
6
+ attribute :currency, String
7
+ attribute :cash, Float
8
+ attribute :reserved, Float
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ module Vaultoro
2
+ module TradingAPI
3
+ class Balances < Base
4
+ attribute :list, Array[Balance]
5
+
6
+ def fetch
7
+ @errors.clear
8
+
9
+ response = Client.get("/balance", {})
10
+ code = response.code rescue ""
11
+
12
+ case code
13
+ when '200'
14
+ hash = JSON.parse(response.body)
15
+
16
+ @status = hash['status'].upcase
17
+
18
+ if @status == 'SUCCESS'
19
+ hash['data'].each do |balance|
20
+ @list << Balance.new(
21
+ :currency => balance['currency_code'],
22
+ :cash => balance['cash'].to_f,
23
+ :reserved => balance['reserved'].to_f
24
+ )
25
+ end
26
+ else
27
+ set_errors(response)
28
+ return false
29
+ end
30
+
31
+ return true
32
+ else
33
+ set_errors(response)
34
+ return false
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,51 @@
1
+ module Vaultoro
2
+ module TradingAPI
3
+ class Buy < Base
4
+ attribute :symbol, String, default: "gld" # Allowed value: "gld"
5
+ attribute :type, String, default: "market" # Allowed values: "limit", "market"
6
+ attribute :bitcoin, Float # Size range: 0.0002-100000 (expressed in bitcoin)
7
+ attribute :gold, Float # Size range: 0.001-100000 (expressed in grams)
8
+ attribute :price, Float # Size range: 0.00002-100000 (expressed in bitcoin, ignored for market orders)
9
+ attribute :order_id, String
10
+ attribute :order_time, Time # UTC
11
+
12
+ def execute!
13
+ ensure_attribute_has_value :symbol, :type
14
+
15
+ @errors << ":bitcoin or :gold argument is required" unless @bitcoin || @gold
16
+ @errors << ":symbol argument must be 'gold'" unless @symbol == 'gold'
17
+ @errors << ":type argument must be 'limit' or 'market'" unless ['limit', 'market'].include?(@type)
18
+
19
+ return false if @errors.any?
20
+
21
+ params = {}
22
+ params.merge!(btc: @bitcoin) if @bitcoin
23
+ params.merge!(gld: @gold) if @gold
24
+ params.merge!(price: @price) if @price && @type == 'market'
25
+
26
+ response = Client.post("/buy/#{@symbol}/#{@type}", params)
27
+ code = response.code rescue ""
28
+
29
+ case code
30
+ when '200'
31
+ hash = JSON.parse(response.body)
32
+
33
+ @status = hash['status'].upcase
34
+
35
+ if @status == 'SUCCESS'
36
+ @order_id = hash['data']['Order_ID']
37
+ @order_time = DateTime.strptime(hash['data']['time'], '%Y-%m-%dT%H:%M:%S.%L%z').to_time.utc
38
+ else
39
+ set_errors(response)
40
+ return false
41
+ end
42
+
43
+ return true
44
+ else
45
+ set_errors(response)
46
+ return false
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,33 @@
1
+ module Vaultoro
2
+ module TradingAPI
3
+ class Cancel < Base
4
+ attribute :order_id, String
5
+
6
+ def execute!
7
+ ensure_attribute_has_value :order_id
8
+ return false if @errors.any?
9
+
10
+ response = Client.post("/cancel/#{@order_id}", {})
11
+ code = response.code rescue ""
12
+
13
+ case code
14
+ when '200'
15
+ hash = JSON.parse(response.body)
16
+
17
+ @status = hash['status'].upcase
18
+ @order_id = hash['data']['Order_ID']
19
+
20
+ unless @status == 'SUCCESS'
21
+ set_errors(response)
22
+ return false
23
+ end
24
+
25
+ return true
26
+ else
27
+ set_errors(response)
28
+ return false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,59 @@
1
+ require 'openssl'
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'json'
5
+
6
+ module Vaultoro
7
+ module TradingAPI
8
+ class Client
9
+ def self.get(endpoint, params = {})
10
+ begin
11
+ uri = URI.parse([Vaultoro.api_uri, "/#{Vaultoro.api_version.to_s}", endpoint].join)
12
+ params.merge!(nonce: nonce, apikey: Vaultoro.api_key)
13
+ uri.query = URI.encode_www_form(params)
14
+ http = Net::HTTP.new(uri.host, uri.port)
15
+ http.use_ssl = uri.scheme == 'https'
16
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
17
+ headers.merge!("X-Signature" => signature)
18
+ request = Net::HTTP::Get.new(uri, headers)
19
+ response = http.request(request)
20
+ rescue StandardError => error
21
+ puts "Request failed (#{error.message})"
22
+ end
23
+ end
24
+
25
+ def self.post(endpoint, params = {})
26
+ begin
27
+ uri = URI.parse([Vaultoro.api_uri, endpoint].join)
28
+ params.merge!(nonce: nonce, apikey: Vaultoro.api_key)
29
+ uri.query = URI.encode_www_form(params)
30
+ # body = URI.encode_www_form(params)
31
+ http = Net::HTTP.new(uri.host, uri.port)
32
+ http.use_ssl = uri.scheme == 'https'
33
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
34
+ headers.merge!("X-Signature" => signature)
35
+ request = Net::HTTP::Post.new(uri, headers)
36
+ request.add_field "Content-Type", "application/x-www-form-urlencoded"
37
+ # request.body = body
38
+ response = http.request(request)
39
+ rescue StandardError => error
40
+ puts "Request failed (#{error.message})"
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def headers
47
+ { 'User-Agent' => Vaultoro::VERSION::SUMMARY, 'Accept' => 'application/json' }
48
+ end
49
+
50
+ def signature(uri)
51
+ OpenSSL::HMAC.hexdigest('sha256', Vaultoro.api_secret, uri.to_s)
52
+ end
53
+
54
+ def nonce
55
+ Time.to_i
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,13 @@
1
+ module Vaultoro
2
+ module Trading
3
+ class TradingAPI
4
+ include Virtus.model
5
+
6
+ attribute :side, String
7
+ attribute :bitcoin_amount, Float
8
+ attribute :gold_amount, Float
9
+ attribute :gold_price, Float
10
+ attribute :order_id, String
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,53 @@
1
+ module Vaultoro
2
+ module TradingAPI
3
+ class Orders < Base
4
+ attribute :list, Array[Order]
5
+
6
+ def fetch
7
+ @errors.clear
8
+
9
+ response = Client.get("/orders", {})
10
+ code = response.code rescue ""
11
+
12
+ case code
13
+ when '200'
14
+ hash = JSON.parse(response.body)
15
+
16
+ @status = hash['status'].upcase
17
+
18
+ if @status == 'SUCCESS'
19
+ hash['data'].each do |orders|
20
+ orders['b'] do |buy|
21
+ @list << Order.new(
22
+ order_id: buy['Order_ID']
23
+ side: 'BUY',
24
+ bitcoin_amount: buy['BTC_Amount'].to_f,
25
+ gold_amount: buy['Gold_Amount'].to_f,
26
+ gold_price: buy['Gold_Price'].to_f
27
+ )
28
+ end
29
+
30
+ orders['s'] do |sell|
31
+ @list << Order.new(
32
+ order_id: buy['Order_ID']
33
+ side: 'SELL',
34
+ bitcoin_amount: buy['BTC_Amount'].to_f,
35
+ gold_amount: buy['Gold_Amount'].to_f,
36
+ gold_price: buy['Gold_Price'].to_f
37
+ )
38
+ end
39
+ end
40
+ else
41
+ set_errors(response)
42
+ return false
43
+ end
44
+
45
+ return true
46
+ else
47
+ set_errors(response)
48
+ return false
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ module Vaultoro
2
+ module TradingAPI
3
+ class Sell < Base
4
+ attribute :symbol, String, default: "gld" # Allowed value: "gld"
5
+ attribute :type, String, default: "market" # Allowed values: "limit", "market"
6
+ attribute :gold, Float # Size range: 0.001-100000 (expressed in grams)
7
+ attribute :price, Float # Size range: 0.00002-100000 (expressed in bitcoin, ignored for market orders)
8
+ attribute :order_id, String
9
+ attribute :order_time, Time # UTC
10
+
11
+ def execute!
12
+ ensure_attribute_has_value :gld, :symbol, :type
13
+
14
+ @errors << ":symbol argument must be 'gld'" unless @symbol == 'gld'
15
+ @errors << ":type argument must be 'limit' or 'market'" unless ['limit', 'market'].include?(@type)
16
+
17
+ return false if @errors.any?
18
+
19
+ params = {}
20
+ params.merge!(gld: @gold) if @gold
21
+ params.merge!(price: @price) if @price && @type == 'market'
22
+
23
+ response = Client.post("/sell/#{@symbol}/#{@type}", params)
24
+ code = response.code rescue ""
25
+
26
+ case code
27
+ when '200'
28
+ hash = JSON.parse(response.body)
29
+
30
+ @status = hash['status'].upcase
31
+
32
+ if @status == 'SUCCESS'
33
+ @order_id = hash['data']['Order_ID']
34
+ @order_time = DateTime.strptime(hash['data']['time'], '%Y-%m-%dT%H:%M:%S.%L%z').to_time.utc
35
+ else
36
+ set_errors(response)
37
+ return false
38
+ end
39
+
40
+ return true
41
+ else
42
+ set_errors(response)
43
+ return false
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end