remitano 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +13 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +127 -0
- data/LICENSE.txt +20 -0
- data/README.md +115 -0
- data/Rakefile +51 -0
- data/bin/remitano +20 -0
- data/lib/remitano.rb +2 -0
- data/lib/remitano/client.rb +98 -0
- data/lib/remitano/client/action_confirmations.rb +29 -0
- data/lib/remitano/client/coin_accounts.rb +9 -0
- data/lib/remitano/client/coin_collection.rb +18 -0
- data/lib/remitano/client/coin_withdrawals.rb +24 -0
- data/lib/remitano/client/collection.rb +29 -0
- data/lib/remitano/client/fiat_accounts.rb +9 -0
- data/lib/remitano/client/fiat_collection.rb +18 -0
- data/lib/remitano/client/helper.rb +14 -0
- data/lib/remitano/client/merchant_charges.rb +24 -0
- data/lib/remitano/client/merchant_withdrawals.rb +38 -0
- data/lib/remitano/client/net.rb +100 -0
- data/lib/remitano/client/offers.rb +21 -0
- data/lib/remitano/client/orders.rb +26 -0
- data/lib/remitano/client/public/offers.rb +18 -0
- data/lib/remitano/client/public/price_ladders.rb +7 -0
- data/lib/remitano/client/public/rates.rb +12 -0
- data/lib/remitano/client/trades.rb +37 -0
- data/lib/remitano/version.rb +3 -0
- data/remitano.gemspec +40 -0
- data/spec/client/merchant_charges_spec.rb +66 -0
- data/spec/client/merchant_withdrawals_spec.rb +111 -0
- data/spec/coin_accounts_spec.rb +11 -0
- data/spec/fiat_accounts_spec.rb +11 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_create/invalid_params/raises_error.yml +51 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_create/valid_params/returns_created_charge.yml +53 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_get/object_exists/returns_charge_data.yml +48 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_charges/_get/object_not_found/raises_error.yml +46 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_create/invalid_params/raises_error.yml +52 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_create/valid_params/auto_confirms_withdrawal_with_htop_and_returns_created_withdrawal.yml +296 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_get/object_exists/returns_withdrawal_data.yml +48 -0
- data/spec/fixtures/vcr_cassettes/Remitano_Client_merchant_withdrawals/_get/object_not_found/raises_error.yml +46 -0
- data/spec/fixtures/vcr_cassettes/remitano/coin_accounts/me.yml +52 -0
- data/spec/fixtures/vcr_cassettes/remitano/fiat_accounts/me.yml +52 -0
- data/spec/fixtures/vcr_cassettes/remitano/my_offers/sell.yml +47 -0
- data/spec/fixtures/vcr_cassettes/remitano/offers/update.yml +94 -0
- data/spec/fixtures/vcr_cassettes/remitano/orders/cancel.yml +54 -0
- data/spec/fixtures/vcr_cassettes/remitano/orders/create.yml +54 -0
- data/spec/fixtures/vcr_cassettes/remitano/orders/open.yml +54 -0
- data/spec/fixtures/vcr_cassettes/remitano/price_ladders/sell.yml +48 -0
- data/spec/fixtures/vcr_cassettes/remitano/rates.yml +44 -0
- data/spec/fixtures/vcr_cassettes/remitano/trades/active.yml +46 -0
- data/spec/fixtures/vcr_cassettes/remitano/trades/completed.yml +46 -0
- data/spec/fixtures/vcr_cassettes/remitano/trades/release.yml +144 -0
- data/spec/offers_spec.rb +18 -0
- data/spec/orders_spec.rb +29 -0
- data/spec/public/price_ladders_spec.rb +11 -0
- data/spec/public/rates_spec.rb +10 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/crendentials.rb +12 -0
- data/spec/support/request_usec.rb +5 -0
- data/spec/support/vcr.rb +22 -0
- data/spec/trades_spec.rb +39 -0
- 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,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,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,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,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
|