remitano 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +13 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +127 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +115 -0
  9. data/Rakefile +51 -0
  10. data/bin/remitano +20 -0
  11. data/lib/remitano.rb +2 -0
  12. data/lib/remitano/client.rb +98 -0
  13. data/lib/remitano/client/action_confirmations.rb +29 -0
  14. data/lib/remitano/client/coin_accounts.rb +9 -0
  15. data/lib/remitano/client/coin_collection.rb +18 -0
  16. data/lib/remitano/client/coin_withdrawals.rb +24 -0
  17. data/lib/remitano/client/collection.rb +29 -0
  18. data/lib/remitano/client/fiat_accounts.rb +9 -0
  19. data/lib/remitano/client/fiat_collection.rb +18 -0
  20. data/lib/remitano/client/helper.rb +14 -0
  21. data/lib/remitano/client/merchant_charges.rb +24 -0
  22. data/lib/remitano/client/merchant_withdrawals.rb +38 -0
  23. data/lib/remitano/client/net.rb +100 -0
  24. data/lib/remitano/client/offers.rb +21 -0
  25. data/lib/remitano/client/orders.rb +26 -0
  26. data/lib/remitano/client/public/offers.rb +18 -0
  27. data/lib/remitano/client/public/price_ladders.rb +7 -0
  28. data/lib/remitano/client/public/rates.rb +12 -0
  29. data/lib/remitano/client/trades.rb +37 -0
  30. data/lib/remitano/version.rb +3 -0
  31. data/remitano.gemspec +40 -0
  32. data/spec/client/merchant_charges_spec.rb +66 -0
  33. data/spec/client/merchant_withdrawals_spec.rb +111 -0
  34. data/spec/coin_accounts_spec.rb +11 -0
  35. data/spec/fiat_accounts_spec.rb +11 -0
  36. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_create/invalid_params/raises_error.yml +51 -0
  37. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_create/valid_params/returns_created_charge.yml +53 -0
  38. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_get/object_exists/returns_charge_data.yml +48 -0
  39. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_get/object_not_found/raises_error.yml +46 -0
  40. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_create/invalid_params/raises_error.yml +52 -0
  41. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_create/valid_params/auto_confirms_withdrawal_with_htop_and_returns_created_withdrawal.yml +296 -0
  42. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_get/object_exists/returns_withdrawal_data.yml +48 -0
  43. data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_get/object_not_found/raises_error.yml +46 -0
  44. data/spec/fixtures/vcr_cassettes/remitano/coin_accounts/me.yml +52 -0
  45. data/spec/fixtures/vcr_cassettes/remitano/fiat_accounts/me.yml +52 -0
  46. data/spec/fixtures/vcr_cassettes/remitano/my_offers/sell.yml +47 -0
  47. data/spec/fixtures/vcr_cassettes/remitano/offers/update.yml +94 -0
  48. data/spec/fixtures/vcr_cassettes/remitano/orders/cancel.yml +54 -0
  49. data/spec/fixtures/vcr_cassettes/remitano/orders/create.yml +54 -0
  50. data/spec/fixtures/vcr_cassettes/remitano/orders/open.yml +54 -0
  51. data/spec/fixtures/vcr_cassettes/remitano/price_ladders/sell.yml +48 -0
  52. data/spec/fixtures/vcr_cassettes/remitano/rates.yml +44 -0
  53. data/spec/fixtures/vcr_cassettes/remitano/trades/active.yml +46 -0
  54. data/spec/fixtures/vcr_cassettes/remitano/trades/completed.yml +46 -0
  55. data/spec/fixtures/vcr_cassettes/remitano/trades/release.yml +144 -0
  56. data/spec/offers_spec.rb +18 -0
  57. data/spec/orders_spec.rb +29 -0
  58. data/spec/public/price_ladders_spec.rb +11 -0
  59. data/spec/public/rates_spec.rb +10 -0
  60. data/spec/spec_helper.rb +25 -0
  61. data/spec/support/crendentials.rb +12 -0
  62. data/spec/support/request_usec.rb +5 -0
  63. data/spec/support/vcr.rb +22 -0
  64. data/spec/trades_spec.rb +39 -0
  65. metadata +329 -0
@@ -0,0 +1,29 @@
1
+ require_relative "collection"
2
+
3
+ module Remitano
4
+ class Client::ActionConfirmations < Client::Collection
5
+ attr_accessor :config
6
+
7
+ def initialize(config:)
8
+ @config = config
9
+ end
10
+
11
+ def confirm!(id)
12
+ config.net.post("/action_confirmations/#{id}/confirm", token: config.authenticator_token).execute
13
+ end
14
+
15
+ def confirm_by_hotp!(id, otp_counter)
16
+ otp = config.hotp(otp_counter)
17
+ config.net.post("/action_confirmations/#{id}/confirm", token: otp).execute
18
+ end
19
+
20
+ def confirm_if_neccessary!(response)
21
+ if response.is_action_confirmation && response.status != "confirmed"
22
+ puts "Submitting token"
23
+ confirm!(response.id)
24
+ else
25
+ response
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "coin_collection"
2
+
3
+ module Remitano
4
+ class Client::CoinAccounts < Client::CoinCollection
5
+ def me
6
+ config.net.get("/coin_accounts/me?coin_currency=#{coin}").execute
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "collection"
2
+
3
+ module Remitano
4
+ class Client::CoinCollection < Client::Collection
5
+ attr_reader :config, :coin
6
+
7
+ def initialize(coin, config:)
8
+ @coin = coin
9
+ super(config: config)
10
+ end
11
+
12
+ class << self
13
+ def of_coin(coin, config:)
14
+ new(coin, config: config)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "coin_collection"
2
+
3
+ module Remitano
4
+ class Client::CoinWithdrawals < Client::CoinCollection
5
+ def my_withdrawals
6
+ config.net.get("/coin_withdrawals?coin_currency=#{coin}").execute
7
+ end
8
+
9
+ def cancel(id)
10
+ config.net.post("/coin_withdrawals/#{id}/cancel").execute
11
+ end
12
+
13
+ def withdraw(coin_address:, coin_amount:, destination_tag: nil)
14
+ params = {
15
+ coin_address: coin_address,
16
+ coin_currency: coin,
17
+ coin_amount: coin_amount,
18
+ destination_tag: destination_tag,
19
+ }
20
+ response = config.net.post("/coin_withdrawals", coin_withdrawal: params).execute
21
+ config.action_confirmations.confirm_if_neccessary!(response)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module Remitano
2
+ class Client::Collection
3
+ attr_accessor :path, :resource_name
4
+ attr_accessor :config
5
+
6
+ def initialize(config:)
7
+ @config = config
8
+ name = self.class.name.underscore.split("/").last
9
+ self.resource_name = name.singularize
10
+ self.path = "/#{name}"
11
+ end
12
+
13
+ def all
14
+ config.net.new(config: config).get(self.path).execute
15
+ end
16
+
17
+ def create(params = {})
18
+ config.net.new(config: config).post(self.path, { self.resource_name => params }).execute
19
+ end
20
+
21
+ def get(id)
22
+ config.net.new(config: config).get("#{self.path}/#{id}").execute
23
+ end
24
+
25
+ def update(id, params = {})
26
+ config.net.new(config: config).patch("#{self.path}/#{id}", { self.resource_name => params }).execute
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "fiat_collection"
2
+
3
+ module Remitano
4
+ class Client::FiatAccounts < Client::FiatCollection
5
+ def me
6
+ config.net.get("/fiat_accounts/me?currency=#{currency}").execute
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "collection"
2
+
3
+ module Remitano
4
+ class Client::FiatCollection < Client::Collection
5
+ attr_reader :config, :currency
6
+
7
+ def initialize(currency, config:)
8
+ @currency = currency
9
+ super(config: config)
10
+ end
11
+
12
+ class << self
13
+ def of_currency(currency, config:)
14
+ new(currency, config: config)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module Remitano
2
+ module Client::Helper
3
+ def self.parse_json(str)
4
+ json = JSON.parse(str)
5
+ if json.is_a? Array
6
+ json.map do |hash|
7
+ Hashie::Mash[hash]
8
+ end
9
+ else
10
+ Hashie::Mash[json]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Remitano
4
+ class Client::MerchantCharges
5
+ attr_reader :config
6
+
7
+ def initialize(config:)
8
+ @config = config
9
+ end
10
+
11
+ def get(id)
12
+ config.net.get("/merchant/merchant_deposit_requests/#{id}").execute
13
+ end
14
+
15
+ def create(coin_currency:, coin_amount:, cancelled_or_completed_callback_url:)
16
+ config.net.post(
17
+ "/merchant/merchant_deposit_requests",
18
+ coin_currency: coin_currency,
19
+ coin_amount: coin_amount,
20
+ cancelled_or_completed_callback_url: cancelled_or_completed_callback_url
21
+ ).execute
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Remitano
4
+ class Client::MerchantWithdrawals
5
+ attr_reader :config
6
+
7
+ def initialize(config:)
8
+ @config = config
9
+ end
10
+
11
+ def get(id)
12
+ config.net.get("/merchant/merchant_withdrawal_requests/#{id}").execute
13
+ end
14
+
15
+ def create(
16
+ merchant_withdrawal_ref:, coin_currency:, coin_amount:, receiver_pay_fee:, cancelled_or_completed_callback_url:,
17
+ coin_address: nil, destination_tag: nil, remitano_username: nil, remitano_phone_number: nil
18
+ )
19
+ withdrawal = config.net.post(
20
+ "/merchant/merchant_withdrawal_requests",
21
+ merchant_withdrawal_ref: merchant_withdrawal_ref,
22
+ coin_currency: coin_currency,
23
+ coin_amount: coin_amount,
24
+ receiver_pay_fee: receiver_pay_fee,
25
+ cancelled_or_completed_callback_url: cancelled_or_completed_callback_url,
26
+ coin_address: coin_address,
27
+ destination_tag: destination_tag,
28
+ remitano_username: remitano_username,
29
+ remitano_phone_number: remitano_phone_number
30
+ ).execute
31
+ if (action_confirmation_id = withdrawal["action_confirmation_id"]).present?
32
+ config.action_confirmations.confirm_by_hotp!(action_confirmation_id, withdrawal["otp_counter"])
33
+ end
34
+
35
+ withdrawal
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,100 @@
1
+ require 'api-auth'
2
+
3
+ module Remitano
4
+ class Client::Request
5
+ class RequestError < StandardError; end
6
+
7
+ def initialize(request)
8
+ @request = request
9
+ end
10
+
11
+ def execute
12
+ @request.execute do |res, req, result|
13
+ if result.code =~ /^2\d\d$/
14
+ return Remitano::Client::Helper.parse_json(res)
15
+ else
16
+ raise RequestError.new("Error #{result.code} #{res}")
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ class Client::Net
23
+ attr_reader :config
24
+
25
+ def initialize(config:)
26
+ @config = config
27
+ end
28
+
29
+ def self.to_uri(path)
30
+ return "#{server}/api/v1#{path}"
31
+ end
32
+
33
+ def self.server
34
+ @server ||= (ENV['REMITANO_SERVER'] || "https://api.remitano.com")
35
+ end
36
+
37
+ def self.public_get(path, params = {})
38
+ options = {
39
+ :url => self.to_uri(path),
40
+ :method => :get,
41
+ :timeout => 20,
42
+ :headers => {
43
+ :params => params,
44
+ :lang => "vi"
45
+ }
46
+ }
47
+ req = RestClient::Request.new(options)
48
+ req.headers['Content-Type'] = 'application/json'
49
+ Remitano::Client::Request.new(req)
50
+ end
51
+
52
+ def get(path, params={})
53
+ request = new_request(:get, path, params)
54
+ sign_request(request)
55
+ end
56
+
57
+ def post(path, params={})
58
+ request = new_request(:post, path, params)
59
+ sign_request(request)
60
+ end
61
+
62
+ def patch(path, params={})
63
+ request = new_request(:put, path, params)
64
+ sign_request(request)
65
+ end
66
+
67
+ def delete(path, params={})
68
+ request = new_request(:delete, path, params)
69
+ sign_request(request)
70
+ end
71
+
72
+ def new_request(method, path, params={})
73
+ p [:new_request, method, path] if config.verbose
74
+
75
+ options = {
76
+ :method => method,
77
+ :timeout => 20
78
+ }
79
+
80
+ usec = Time.now.usec
81
+ if method == :get
82
+ path += (path.include?("?") ? "&" : "?")
83
+ path += "usec=#{usec}"
84
+ else
85
+ params[:usec] = usec
86
+ options[:payload] = params.to_json
87
+ end
88
+
89
+ options[:url] = self.class.to_uri(path)
90
+
91
+ RestClient::Request.new(options)
92
+ end
93
+
94
+ def sign_request(req)
95
+ req.headers['Content-Type'] = 'application/json'
96
+ ApiAuth.sign!(req, config.key, config.secret)
97
+ Remitano::Client::Request.new(req)
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,21 @@
1
+ require_relative "coin_collection"
2
+ module Remitano
3
+ class Client::Offers < Client::CoinCollection
4
+ def my_offers(side)
5
+ config.net.get("/offers/my_offers?offer_type=#{side}&coin_currency=#{coin}").execute.offers
6
+ end
7
+
8
+ def update(offer_id, params)
9
+ response = config.net.patch("/offers/#{offer_id}?coin_currency=#{coin}", params).execute
10
+ config.action_confirmations.confirm_if_neccessary!(response)
11
+ end
12
+
13
+ def enable(offer_id)
14
+ config.net.patch("/offers/#{offer_id}/enable?coin_currency=#{coin}").execute
15
+ end
16
+
17
+ def disable(offer_id)
18
+ config.net.patch("/offers/#{offer_id}/disable?coin_currency=#{coin}").execute
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require_relative "coin_collection"
2
+
3
+ module Remitano
4
+ class Client::Orders
5
+ attr_reader :config
6
+
7
+ def initialize(config:)
8
+ @config = config
9
+ end
10
+
11
+ def open(pair, **params)
12
+ config.net.get("/orders/open?pair=#{pair}&#{params.to_query}").execute
13
+ end
14
+
15
+ def cancel(id)
16
+ config.net.post("/orders/#{id}/cancel").execute
17
+ end
18
+
19
+ def create(pair:, side:, price:, amount:)
20
+ config.net.post(
21
+ "/orders",
22
+ pair: pair, side: side, price: price, amount: amount
23
+ ).execute
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "../collection"
2
+ module Remitano
3
+ class Client::PublicOffers < Remitano::Client::Collection
4
+ def offers(params = {} )
5
+ Remitano::Client::Net.public_get("/offers", params).execute.offers
6
+ end
7
+
8
+ def buy_offers(params = {})
9
+ params[:offer_type] = "buy"
10
+ offers(params)
11
+ end
12
+
13
+ def sell_offers(params = {})
14
+ params[:offer_type] = "sell"
15
+ offers(params)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module Remitano
2
+ class Client::PriceLadders
3
+ def fetch(pair)
4
+ Remitano::Client::Net.public_get("/price_ladders/#{pair}").execute
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "../collection"
2
+ module Remitano
3
+ class Client::Rates
4
+ def ads
5
+ Remitano::Client::Net.public_get("/rates/ads").execute
6
+ end
7
+
8
+ def exchange
9
+ Remitano::Client::Net.public_get("/rates/exchange").execute
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,37 @@
1
+ require_relative "coin_collection"
2
+ module Remitano
3
+ class Client::Trades < Client::CoinCollection
4
+ def active(buy_or_sell, page: nil)
5
+ options = { trade_type: buy_or_sell, trade_status: "active", coin_currency: coin }
6
+ (options[:page] = page) if page
7
+ config.net.get("/trades?#{options.to_query}").execute
8
+ end
9
+
10
+ def completed(buy_or_sell, page: nil)
11
+ options = { trade_type: buy_or_sell, trade_status: "completed", coin_currency: coin }
12
+ (options[:page] = page) if page
13
+ config.net.get("/trades?#{options.to_query}").execute
14
+ end
15
+
16
+ def release(trade_ref)
17
+ response = config.net.post("/trades/#{trade_ref}/release").execute
18
+ config.action_confirmations.confirm_if_neccessary!(response)
19
+ end
20
+
21
+ def dispute(trade_ref)
22
+ config.net.post("/trades/#{trade_ref}/dispute").execute
23
+ end
24
+
25
+ def mark_as_paid(trade_ref)
26
+ config.net.post("/trades/#{trade_ref}/mark_as_paid").execute
27
+ end
28
+
29
+ def get(id)
30
+ config.net.get("/trades/#{id}").execute.trade
31
+ end
32
+
33
+ def cancel(id)
34
+ config.net.post("/trades/#{id}/cancel").execute
35
+ end
36
+ end
37
+ end