peatio 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +31 -15
- data/lib/peatio.rb +13 -9
- data/lib/peatio/auth/error.rb +19 -0
- data/lib/peatio/auth/jwt_authenticator.rb +127 -0
- data/lib/peatio/command/service.rb +12 -3
- data/lib/peatio/error.rb +27 -0
- data/lib/peatio/injectors/peatio_events.rb +133 -114
- data/lib/peatio/mq/client.rb +13 -7
- data/lib/peatio/mq/events.rb +73 -16
- data/lib/peatio/ranger.rb +90 -15
- data/lib/peatio/version.rb +1 -1
- data/peatio.gemspec +15 -11
- metadata +75 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0654fc5cd21783e8e22ca88db407d01f1c268032f09b347dfed2f49ca3aae8e
|
|
4
|
+
data.tar.gz: 3346353884ce7fd78c47d8b6f8bad7f2a3d360a4366ba1b1f635e8eb750b87ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d5d538caf05569e94c3f812d5f15cfa49a5cbcfa0d23c1ccbc2f76a3c66fbb56c8c4f0e83e61dba96c1550bdc9b7a816bd7c3093e5b0e50b6fc0f5cce47f34e7
|
|
7
|
+
data.tar.gz: 9a5304ac15012c2488aadb4990bc62c331bb7e7f0f8cbd3f044ad3dd7ae1a0cc51f524f062b0abd46f7df31a8003486bcd70b0d0d2b9690547ecc4b8bfb0916e
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -3,9 +3,11 @@ PATH
|
|
|
3
3
|
specs:
|
|
4
4
|
peatio (0.2.0)
|
|
5
5
|
amqp
|
|
6
|
+
bunny
|
|
6
7
|
clamp
|
|
7
8
|
em-websocket
|
|
8
9
|
eventmachine
|
|
10
|
+
jwt
|
|
9
11
|
mysql2
|
|
10
12
|
|
|
11
13
|
GEM
|
|
@@ -16,49 +18,59 @@ GEM
|
|
|
16
18
|
amq-protocol (>= 2.2.0)
|
|
17
19
|
eventmachine
|
|
18
20
|
ast (2.4.0)
|
|
21
|
+
bunny (2.11.0)
|
|
22
|
+
amq-protocol (~> 2.3.0)
|
|
23
|
+
bunny-mock (1.7.0)
|
|
24
|
+
bunny (>= 1.7)
|
|
19
25
|
clamp (1.3.0)
|
|
20
26
|
diff-lcs (1.3)
|
|
21
27
|
docile (1.3.1)
|
|
28
|
+
em-spec (0.2.7)
|
|
29
|
+
eventmachine
|
|
22
30
|
em-websocket (0.5.1)
|
|
23
31
|
eventmachine (>= 0.12.9)
|
|
24
32
|
http_parser.rb (~> 0.6.0)
|
|
33
|
+
em-websocket-client (0.1.2)
|
|
34
|
+
eventmachine
|
|
35
|
+
websocket
|
|
25
36
|
eventmachine (1.2.7)
|
|
26
37
|
http_parser.rb (0.6.0)
|
|
27
38
|
jaro_winkler (1.5.1)
|
|
28
39
|
json (2.1.0)
|
|
40
|
+
jwt (2.1.0)
|
|
29
41
|
mysql2 (0.5.2)
|
|
30
42
|
parallel (1.12.1)
|
|
31
|
-
parser (2.5.1.
|
|
43
|
+
parser (2.5.1.2)
|
|
32
44
|
ast (~> 2.4.0)
|
|
33
45
|
powerpack (0.1.2)
|
|
34
46
|
rainbow (3.0.0)
|
|
35
47
|
rake (10.5.0)
|
|
36
|
-
rspec (3.
|
|
37
|
-
rspec-core (~> 3.
|
|
38
|
-
rspec-expectations (~> 3.
|
|
39
|
-
rspec-mocks (~> 3.
|
|
40
|
-
rspec-core (3.
|
|
41
|
-
rspec-support (~> 3.
|
|
42
|
-
rspec-expectations (3.
|
|
48
|
+
rspec (3.8.0)
|
|
49
|
+
rspec-core (~> 3.8.0)
|
|
50
|
+
rspec-expectations (~> 3.8.0)
|
|
51
|
+
rspec-mocks (~> 3.8.0)
|
|
52
|
+
rspec-core (3.8.0)
|
|
53
|
+
rspec-support (~> 3.8.0)
|
|
54
|
+
rspec-expectations (3.8.1)
|
|
43
55
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
44
|
-
rspec-support (~> 3.
|
|
45
|
-
rspec-mocks (3.
|
|
56
|
+
rspec-support (~> 3.8.0)
|
|
57
|
+
rspec-mocks (3.8.0)
|
|
46
58
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
47
|
-
rspec-support (~> 3.
|
|
48
|
-
rspec-support (3.
|
|
59
|
+
rspec-support (~> 3.8.0)
|
|
60
|
+
rspec-support (3.8.0)
|
|
49
61
|
rspec_junit_formatter (0.4.1)
|
|
50
62
|
rspec-core (>= 2, < 4, != 2.12.0)
|
|
51
|
-
rubocop (0.
|
|
63
|
+
rubocop (0.58.2)
|
|
52
64
|
jaro_winkler (~> 1.5.1)
|
|
53
65
|
parallel (~> 1.10)
|
|
54
|
-
parser (>= 2.5)
|
|
66
|
+
parser (>= 2.5, != 2.5.1.1)
|
|
55
67
|
powerpack (~> 0.1)
|
|
56
68
|
rainbow (>= 2.2.2, < 4.0)
|
|
57
69
|
ruby-progressbar (~> 1.7)
|
|
58
70
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
59
71
|
rubocop-github (0.10.0)
|
|
60
72
|
rubocop (~> 0.51)
|
|
61
|
-
ruby-progressbar (1.
|
|
73
|
+
ruby-progressbar (1.10.0)
|
|
62
74
|
simplecov (0.16.1)
|
|
63
75
|
docile (~> 1.1)
|
|
64
76
|
json (>= 1.8, < 3)
|
|
@@ -68,12 +80,16 @@ GEM
|
|
|
68
80
|
json
|
|
69
81
|
simplecov
|
|
70
82
|
unicode-display_width (1.4.0)
|
|
83
|
+
websocket (1.2.8)
|
|
71
84
|
|
|
72
85
|
PLATFORMS
|
|
73
86
|
ruby
|
|
74
87
|
|
|
75
88
|
DEPENDENCIES
|
|
76
89
|
bundler (~> 1.16)
|
|
90
|
+
bunny-mock
|
|
91
|
+
em-spec
|
|
92
|
+
em-websocket-client
|
|
77
93
|
peatio!
|
|
78
94
|
rake (~> 10.0)
|
|
79
95
|
rspec (~> 3.0)
|
data/lib/peatio.rb
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
require "logger"
|
|
2
2
|
require "json"
|
|
3
3
|
require "mysql2"
|
|
4
|
-
require "
|
|
4
|
+
require "bunny"
|
|
5
5
|
require "eventmachine"
|
|
6
6
|
require "em-websocket"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
module Peatio
|
|
9
|
+
require_relative "peatio/error"
|
|
10
|
+
require_relative "peatio/logger"
|
|
11
|
+
require_relative "peatio/version"
|
|
12
|
+
require_relative "peatio/sql/client"
|
|
13
|
+
require_relative "peatio/sql/schema"
|
|
14
|
+
require_relative "peatio/mq/client"
|
|
15
|
+
require_relative "peatio/mq/events"
|
|
16
|
+
require_relative "peatio/ranger"
|
|
17
|
+
require_relative "peatio/injectors/peatio_events"
|
|
18
|
+
require_relative "peatio/auth/jwt_authenticator"
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Peatio::Auth
|
|
2
|
+
# Error repesent all errors that can be returned from Auth module.
|
|
3
|
+
class Error < Peatio::Error
|
|
4
|
+
# @return [String, JWT::*] Reason store underlying reason for given error.
|
|
5
|
+
#
|
|
6
|
+
# @see https://github.com/jwt/ruby-jwt/blob/master/lib/jwt/error.rb List of JWT::* errors.
|
|
7
|
+
attr_reader :reason
|
|
8
|
+
|
|
9
|
+
def initialize(reason = nil)
|
|
10
|
+
@reason = reason
|
|
11
|
+
|
|
12
|
+
super(
|
|
13
|
+
code: 2001,
|
|
14
|
+
text: "Authorization failed: #{reason}",
|
|
15
|
+
status: 401,
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require "jwt"
|
|
2
|
+
|
|
3
|
+
require_relative "error"
|
|
4
|
+
|
|
5
|
+
module Peatio::Auth
|
|
6
|
+
# JWTAuthenticator used to authenticate user using JWT.
|
|
7
|
+
#
|
|
8
|
+
# It allows configuration of JWT verification through following ENV
|
|
9
|
+
# variables (all optional):
|
|
10
|
+
# * JWT_ISSUER
|
|
11
|
+
# * JWT_AUDIENCE
|
|
12
|
+
# * JWT_ALGORITHM (default: RS256)
|
|
13
|
+
# * JWT_DEFAULT_LEEWAY
|
|
14
|
+
# * JWT_ISSUED_AT_LEEWAY
|
|
15
|
+
# * JWT_EXPIRATION_LEEWAY
|
|
16
|
+
# * JWT_NOT_BEFORE_LEEWAY
|
|
17
|
+
#
|
|
18
|
+
# @see https://github.com/jwt/ruby-jwt JWT validation parameters.
|
|
19
|
+
#
|
|
20
|
+
# @example Token validation
|
|
21
|
+
# rsa_private = OpenSSL::PKey::RSA.generate(2048)
|
|
22
|
+
# rsa_public = rsa_private.public_key
|
|
23
|
+
#
|
|
24
|
+
# payload = {
|
|
25
|
+
# iat: Time.now.to_i,
|
|
26
|
+
# exp: (Time.now + 60).to_i,
|
|
27
|
+
# sub: "session",
|
|
28
|
+
# iss: "barong",
|
|
29
|
+
# aud: [
|
|
30
|
+
# "peatio",
|
|
31
|
+
# "barong",
|
|
32
|
+
# ],
|
|
33
|
+
# jti: "BEF5617B7B2762DDE61702F5",
|
|
34
|
+
# uid: "TEST123",
|
|
35
|
+
# email: "user@example.com",
|
|
36
|
+
# role: "admin",
|
|
37
|
+
# level: 4,
|
|
38
|
+
# state: "active",
|
|
39
|
+
# }
|
|
40
|
+
#
|
|
41
|
+
# token = JWT.encode(payload, rsa_private, "RS256")
|
|
42
|
+
#
|
|
43
|
+
# auth = Peatio::Auth::JWTAuthenticator.new(rsa_public)
|
|
44
|
+
# auth.authenticate!("Bearer #{token}")
|
|
45
|
+
class JWTAuthenticator
|
|
46
|
+
@@verify_options = {
|
|
47
|
+
verify_expiration: true,
|
|
48
|
+
verify_not_before: true,
|
|
49
|
+
iss: ENV["JWT_ISSUER"],
|
|
50
|
+
verify_iss: !ENV["JWT_ISSUER"].nil?,
|
|
51
|
+
verify_iat: true,
|
|
52
|
+
verify_jti: true,
|
|
53
|
+
aud: ENV["JWT_AUDIENCE"].to_s.split(",").reject(&:empty?),
|
|
54
|
+
verify_aud: !ENV["JWT_AUDIENCE"].nil?,
|
|
55
|
+
sub: "session",
|
|
56
|
+
verify_sub: true,
|
|
57
|
+
algorithms: [ENV["JWT_ALGORITHM"] || "RS256"],
|
|
58
|
+
leeway: ENV["JWT_DEFAULT_LEEWAY"].yield_self { |n| n.to_i unless n.nil? },
|
|
59
|
+
iat_leeway: ENV["JWT_ISSUED_AT_LEEWAY"].yield_self { |n| n.to_i unless n.nil? },
|
|
60
|
+
exp_leeway: ENV["JWT_EXPIRATION_LEEWAY"].yield_self { |n| n.to_i unless n.nil? },
|
|
61
|
+
nbf_leeway: ENV["JWT_NOT_BEFORE_LEEWAY"].yield_self { |n| n.to_i unless n.nil? },
|
|
62
|
+
}.compact
|
|
63
|
+
|
|
64
|
+
@@encode_options = {
|
|
65
|
+
algorithm: @@verify_options[:algorithms].first,
|
|
66
|
+
}.compact
|
|
67
|
+
|
|
68
|
+
# Creates new authenticator with given public key.
|
|
69
|
+
#
|
|
70
|
+
# @param public_key [OpenSSL::PKey::PKey] Public key object to verify
|
|
71
|
+
# signature.
|
|
72
|
+
# @param private_key [OpenSSL::PKey::PKey] Optional private key that used
|
|
73
|
+
# only to encode new tokens.
|
|
74
|
+
def initialize(public_key, private_key = nil)
|
|
75
|
+
@public_key = public_key
|
|
76
|
+
@private_key = private_key
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Decodes and verifies JWT.
|
|
80
|
+
# Returns payload from JWT or raises an exception
|
|
81
|
+
#
|
|
82
|
+
# @param token [String] Token string. Must start from <tt>"Bearer "</tt>.
|
|
83
|
+
# @return [Hash] Payload Hash from JWT without any changes.
|
|
84
|
+
#
|
|
85
|
+
# @raise [Peatio::Auth::Error] If token is invalid or can't be verified.
|
|
86
|
+
def authenticate!(token)
|
|
87
|
+
token_type, token_value = token.to_s.split(" ")
|
|
88
|
+
|
|
89
|
+
unless token_type == "Bearer"
|
|
90
|
+
raise(Peatio::Auth::Error, "Token type is not provided or invalid.")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
decode_and_verify_token(token_value)
|
|
94
|
+
rescue => error
|
|
95
|
+
case error
|
|
96
|
+
when Peatio::Auth::Error
|
|
97
|
+
raise(error)
|
|
98
|
+
else
|
|
99
|
+
raise(Peatio::Auth::Error, e.inspect)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Encodes given payload and produces JWT.
|
|
104
|
+
#
|
|
105
|
+
# @param payload [String, Hash] Payload to encode.
|
|
106
|
+
# @return [String] JWT token string.
|
|
107
|
+
#
|
|
108
|
+
# @raise [ArgumentError] If no private key was passed to constructor.
|
|
109
|
+
def encode(payload)
|
|
110
|
+
raise(::ArgumentError, "No private key given.") if @private_key.nil?
|
|
111
|
+
|
|
112
|
+
JWT.encode(payload, @private_key, @@encode_options[:algorithm])
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def decode_and_verify_token(token)
|
|
118
|
+
payload, header = JWT.decode(token, @public_key, true, @@verify_options)
|
|
119
|
+
|
|
120
|
+
payload.keys.each { |k| payload[k.to_sym] = payload.delete(k) }
|
|
121
|
+
|
|
122
|
+
payload
|
|
123
|
+
rescue JWT::DecodeError => e
|
|
124
|
+
raise(Peatio::Auth::Error, "Failed to decode and verify JWT: #{e.inspect}.")
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
module Peatio::Command::Service
|
|
2
|
-
|
|
3
2
|
class Start < Peatio::Command::Base
|
|
4
3
|
class Ranger < Peatio::Command::Base
|
|
5
4
|
def execute
|
|
6
|
-
|
|
5
|
+
if ENV["JWT_PUBLIC_KEY"].nil?
|
|
6
|
+
raise ArgumentError, "JWT_PUBLIC_KEY was not specified."
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
key_decoded = Base64.urlsafe_decode64(ENV["JWT_PUBLIC_KEY"])
|
|
10
|
+
|
|
11
|
+
jwt_public_key = OpenSSL::PKey.read(key_decoded)
|
|
12
|
+
if jwt_public_key.private?
|
|
13
|
+
raise ArgumentError, "JWT_PUBLIC_KEY was set to private key, however it should be public."
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
::Peatio::Ranger.run!(jwt_public_key)
|
|
7
17
|
end
|
|
8
18
|
end
|
|
9
19
|
|
|
@@ -13,5 +23,4 @@ module Peatio::Command::Service
|
|
|
13
23
|
class Root < Peatio::Command::Base
|
|
14
24
|
subcommand "start", "Start a service", Start
|
|
15
25
|
end
|
|
16
|
-
|
|
17
26
|
end
|
data/lib/peatio/error.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class Peatio::Error < ::StandardError
|
|
2
|
+
@@default_code = 2000
|
|
3
|
+
@@default_status = 400
|
|
4
|
+
|
|
5
|
+
attr :code, :text
|
|
6
|
+
|
|
7
|
+
def initialize(opts = {})
|
|
8
|
+
@code = opts[:code] || @@default_code
|
|
9
|
+
@text = opts[:text] || ""
|
|
10
|
+
|
|
11
|
+
@status = opts[:status] || @@default_status
|
|
12
|
+
@message = {error: {code: @code, message: @text}}
|
|
13
|
+
|
|
14
|
+
if @text != ""
|
|
15
|
+
super("#{@code}: #{text}")
|
|
16
|
+
else
|
|
17
|
+
super("#{@code}")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def inspect
|
|
22
|
+
message = @text
|
|
23
|
+
message += " (#{@reason})" unless @reason.nil?
|
|
24
|
+
|
|
25
|
+
%[#<#{self.class.name}: #{message}>]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -13,21 +13,18 @@ module Peatio::Injectors
|
|
|
13
13
|
|
|
14
14
|
EventMachine.run do
|
|
15
15
|
Peatio::MQ::Client.new
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
end
|
|
16
|
+
Peatio::MQ::Client.connect!
|
|
17
|
+
Peatio::MQ::Client.create_channel!
|
|
18
|
+
inject_message
|
|
20
19
|
end
|
|
21
20
|
end
|
|
22
21
|
|
|
23
|
-
def
|
|
22
|
+
def inject_message
|
|
24
23
|
if message = @messages.shift
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
next_message(exchange)
|
|
30
|
-
end
|
|
24
|
+
type, id, event, data = message
|
|
25
|
+
Peatio::MQ::Events.publish(type, id, event, data) {
|
|
26
|
+
inject_message
|
|
27
|
+
}
|
|
31
28
|
else
|
|
32
29
|
Peatio::MQ::Client.disconnect { EventMachine.stop }
|
|
33
30
|
end
|
|
@@ -35,6 +32,7 @@ module Peatio::Injectors
|
|
|
35
32
|
|
|
36
33
|
def create_messages
|
|
37
34
|
[
|
|
35
|
+
private_trade,
|
|
38
36
|
order_created,
|
|
39
37
|
order_canceled,
|
|
40
38
|
order_completed,
|
|
@@ -50,141 +48,162 @@ module Peatio::Injectors
|
|
|
50
48
|
def updated_at
|
|
51
49
|
Time.now
|
|
52
50
|
end
|
|
51
|
+
|
|
53
52
|
alias :completed_at :updated_at
|
|
54
|
-
alias :canceled_at
|
|
53
|
+
alias :canceled_at :updated_at
|
|
54
|
+
|
|
55
|
+
def private_trade
|
|
56
|
+
[
|
|
57
|
+
"private",
|
|
58
|
+
"debug_user",
|
|
59
|
+
"trade",
|
|
60
|
+
{
|
|
61
|
+
trade: "some-data",
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
end
|
|
55
65
|
|
|
56
66
|
def order_created
|
|
57
67
|
[
|
|
58
|
-
"
|
|
68
|
+
"public",
|
|
69
|
+
market,
|
|
70
|
+
"order_created",
|
|
59
71
|
{
|
|
60
|
-
market:
|
|
61
|
-
type:
|
|
62
|
-
trader_uid:
|
|
63
|
-
income_unit:
|
|
64
|
-
income_fee_type:
|
|
65
|
-
income_fee_value:
|
|
66
|
-
outcome_unit:
|
|
67
|
-
outcome_fee_type:
|
|
68
|
-
outcome_fee_value:
|
|
69
|
-
initial_income_amount:
|
|
70
|
-
current_income_amount:
|
|
72
|
+
market: "#{market}",
|
|
73
|
+
type: "buy",
|
|
74
|
+
trader_uid: buyer_uid,
|
|
75
|
+
income_unit: "btc",
|
|
76
|
+
income_fee_type: "relative",
|
|
77
|
+
income_fee_value: "0.0015",
|
|
78
|
+
outcome_unit: "usd",
|
|
79
|
+
outcome_fee_type: "relative",
|
|
80
|
+
outcome_fee_value: "0.0",
|
|
81
|
+
initial_income_amount: "14.0",
|
|
82
|
+
current_income_amount: "14.0",
|
|
71
83
|
initial_outcome_amount: "0.42",
|
|
72
84
|
current_outcome_amount: "0.42",
|
|
73
|
-
strategy:
|
|
74
|
-
price:
|
|
75
|
-
state:
|
|
76
|
-
trades_count:
|
|
77
|
-
created_at:
|
|
78
|
-
}
|
|
85
|
+
strategy: "limit",
|
|
86
|
+
price: "0.03",
|
|
87
|
+
state: "open",
|
|
88
|
+
trades_count: 0,
|
|
89
|
+
created_at: created_at.iso8601,
|
|
90
|
+
},
|
|
79
91
|
]
|
|
80
92
|
end
|
|
81
93
|
|
|
82
94
|
def order_canceled
|
|
83
95
|
[
|
|
84
|
-
"
|
|
96
|
+
"public",
|
|
97
|
+
market,
|
|
98
|
+
"order_canceled",
|
|
85
99
|
{
|
|
86
|
-
market:
|
|
87
|
-
type:
|
|
88
|
-
trader_uid:
|
|
89
|
-
income_unit:
|
|
90
|
-
income_fee_type:
|
|
91
|
-
income_fee_value:
|
|
92
|
-
outcome_unit:
|
|
93
|
-
outcome_fee_type:
|
|
94
|
-
outcome_fee_value:
|
|
95
|
-
initial_income_amount:
|
|
96
|
-
current_income_amount:
|
|
97
|
-
initial_outcome_amount:
|
|
98
|
-
current_outcome_amount:
|
|
99
|
-
strategy:
|
|
100
|
-
price:
|
|
101
|
-
state:
|
|
102
|
-
trades_count:
|
|
103
|
-
created_at:
|
|
104
|
-
canceled_at:
|
|
105
|
-
}
|
|
100
|
+
market: "#{market}",
|
|
101
|
+
type: "sell",
|
|
102
|
+
trader_uid: seller_uid,
|
|
103
|
+
income_unit: "usd",
|
|
104
|
+
income_fee_type: "relative",
|
|
105
|
+
income_fee_value: "0.0015",
|
|
106
|
+
outcome_unit: "btc",
|
|
107
|
+
outcome_fee_type: "relative",
|
|
108
|
+
outcome_fee_value: "0.0",
|
|
109
|
+
initial_income_amount: "3.0",
|
|
110
|
+
current_income_amount: "3.0",
|
|
111
|
+
initial_outcome_amount: "100.0",
|
|
112
|
+
current_outcome_amount: "100.0",
|
|
113
|
+
strategy: "limit",
|
|
114
|
+
price: "0.03",
|
|
115
|
+
state: "canceled",
|
|
116
|
+
trades_count: 0,
|
|
117
|
+
created_at: created_at.iso8601,
|
|
118
|
+
canceled_at: canceled_at.iso8601,
|
|
119
|
+
},
|
|
106
120
|
]
|
|
107
121
|
end
|
|
108
122
|
|
|
109
123
|
def order_completed
|
|
110
124
|
[
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
"public",
|
|
126
|
+
market,
|
|
127
|
+
"order_completed", {
|
|
128
|
+
market: "#{market}",
|
|
129
|
+
type: "sell",
|
|
130
|
+
trader_uid: seller_uid,
|
|
131
|
+
income_unit: "usd",
|
|
132
|
+
income_fee_type: "relative",
|
|
133
|
+
income_fee_value: "0.0015",
|
|
134
|
+
outcome_unit: "btc",
|
|
135
|
+
outcome_fee_type: "relative",
|
|
136
|
+
outcome_fee_value: "0.0",
|
|
137
|
+
initial_income_amount: "3.0",
|
|
138
|
+
current_income_amount: "0.0",
|
|
139
|
+
previous_income_amount: "3.0",
|
|
140
|
+
initial_outcome_amount: "100.0",
|
|
141
|
+
current_outcome_amount: "0.0",
|
|
126
142
|
previous_outcome_amount: "100.0",
|
|
127
|
-
strategy:
|
|
128
|
-
price:
|
|
129
|
-
state:
|
|
130
|
-
trades_count:
|
|
131
|
-
created_at:
|
|
132
|
-
completed_at:
|
|
133
|
-
}
|
|
143
|
+
strategy: "limit",
|
|
144
|
+
price: "0.03",
|
|
145
|
+
state: "completed",
|
|
146
|
+
trades_count: 1,
|
|
147
|
+
created_at: created_at.iso8601,
|
|
148
|
+
completed_at: completed_at.iso8601,
|
|
149
|
+
},
|
|
134
150
|
]
|
|
135
151
|
end
|
|
136
152
|
|
|
137
153
|
def order_updated
|
|
138
154
|
[
|
|
139
|
-
"
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
155
|
+
"public",
|
|
156
|
+
market,
|
|
157
|
+
"order_updated", {
|
|
158
|
+
market: "#{market}",
|
|
159
|
+
type: "sell",
|
|
160
|
+
trader_uid: seller_uid,
|
|
161
|
+
income_unit: "usd",
|
|
162
|
+
income_fee_type: "relative",
|
|
163
|
+
income_fee_value: "0.0015",
|
|
164
|
+
outcome_unit: "btc",
|
|
165
|
+
outcome_fee_type: "relative",
|
|
166
|
+
outcome_fee_value: "0.0",
|
|
167
|
+
initial_income_amount: "3.0",
|
|
168
|
+
current_income_amount: "2.4",
|
|
169
|
+
previous_income_amount: "3.0",
|
|
170
|
+
initial_outcome_amount: "100.0",
|
|
171
|
+
current_outcome_amount: "80.0",
|
|
154
172
|
previous_outcome_amount: "100.0",
|
|
155
|
-
strategy:
|
|
156
|
-
price:
|
|
157
|
-
state:
|
|
158
|
-
trades_count:
|
|
159
|
-
created_at:
|
|
160
|
-
updated_at:
|
|
161
|
-
}
|
|
173
|
+
strategy: "limit",
|
|
174
|
+
price: "0.03",
|
|
175
|
+
state: "open",
|
|
176
|
+
trades_count: 1,
|
|
177
|
+
created_at: created_at.iso8601,
|
|
178
|
+
updated_at: updated_at.iso8601,
|
|
179
|
+
},
|
|
162
180
|
]
|
|
163
181
|
end
|
|
164
182
|
|
|
165
183
|
def trade_completed
|
|
166
184
|
[
|
|
167
|
-
"
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
185
|
+
"public",
|
|
186
|
+
market,
|
|
187
|
+
"trade_completed", {
|
|
188
|
+
market: "#{market}",
|
|
189
|
+
price: "0.03",
|
|
190
|
+
buyer_uid: buyer_uid,
|
|
191
|
+
buyer_income_unit: "btc",
|
|
192
|
+
buyer_income_amount: "14.0",
|
|
193
|
+
buyer_income_fee: "0.021",
|
|
194
|
+
buyer_outcome_unit: "usd",
|
|
195
|
+
buyer_outcome_amount: "0.42",
|
|
196
|
+
buyer_outcome_fee: "0.0",
|
|
197
|
+
seller_uid: seller_uid,
|
|
198
|
+
seller_income_unit: "usd",
|
|
199
|
+
seller_income_amount: "0.42",
|
|
200
|
+
seller_income_fee: "0.00063",
|
|
201
|
+
seller_outcome_unit: "btc",
|
|
182
202
|
seller_outcome_amount: "14.0",
|
|
183
|
-
seller_outcome_fee:
|
|
184
|
-
completed_at:
|
|
185
|
-
}
|
|
203
|
+
seller_outcome_fee: "0.0",
|
|
204
|
+
completed_at: completed_at.iso8601,
|
|
205
|
+
},
|
|
186
206
|
]
|
|
187
207
|
end
|
|
188
|
-
|
|
189
208
|
end
|
|
190
209
|
end
|
data/lib/peatio/mq/client.rb
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
module Peatio::MQ
|
|
2
2
|
class Client
|
|
3
3
|
class << self
|
|
4
|
-
|
|
4
|
+
attr_accessor :channel, :connection
|
|
5
5
|
|
|
6
6
|
def new
|
|
7
|
-
options = {
|
|
7
|
+
@options = {
|
|
8
8
|
host: ENV["RABBITMQ_HOST"] || "0.0.0.0",
|
|
9
9
|
port: ENV["RABBITMQ_PORT"] || "5672",
|
|
10
10
|
username: ENV["RABBITMQ_USER"],
|
|
11
11
|
password: ENV["RABBITMQ_PASSWORD"],
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def connect!
|
|
16
|
+
@connection = Bunny.new(@options)
|
|
17
|
+
@connection.start
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create_channel!
|
|
21
|
+
@channel = @connection.create_channel
|
|
15
22
|
end
|
|
16
23
|
|
|
17
24
|
def disconnect
|
|
18
|
-
connection.close
|
|
19
|
-
|
|
20
|
-
end
|
|
25
|
+
@connection.close
|
|
26
|
+
yield if block_given?
|
|
21
27
|
end
|
|
22
28
|
end
|
|
23
29
|
end
|
data/lib/peatio/mq/events.rb
CHANGED
|
@@ -1,26 +1,47 @@
|
|
|
1
|
+
require "socket"
|
|
2
|
+
|
|
1
3
|
module Peatio::MQ::Events
|
|
2
4
|
def self.subscribe!
|
|
3
5
|
ranger = RangerEvents.new
|
|
4
6
|
ranger.subscribe
|
|
5
7
|
end
|
|
6
8
|
|
|
7
|
-
def self.
|
|
9
|
+
def self.publish(type, id, event, payload)
|
|
10
|
+
@@client ||= begin
|
|
11
|
+
ranger = RangerEvents.new
|
|
12
|
+
ranger.connect!
|
|
13
|
+
ranger
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@@client.publish(type, id, event, payload) do
|
|
17
|
+
yield if block_given?
|
|
18
|
+
end
|
|
8
19
|
end
|
|
9
20
|
|
|
10
|
-
class
|
|
11
|
-
attr_accessor :
|
|
21
|
+
class Client
|
|
22
|
+
attr_accessor :streams, :authorized, :user
|
|
12
23
|
|
|
13
24
|
@@all = []
|
|
14
25
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
def self.all
|
|
27
|
+
@@all
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.user(user)
|
|
31
|
+
@@all.each do |handler|
|
|
32
|
+
if handler.user == user
|
|
33
|
+
yield handler
|
|
34
|
+
end
|
|
18
35
|
end
|
|
19
36
|
end
|
|
20
37
|
|
|
21
|
-
def initialize(socket,
|
|
38
|
+
def initialize(socket, streams)
|
|
22
39
|
@socket = socket
|
|
23
|
-
@
|
|
40
|
+
@streams = streams
|
|
41
|
+
|
|
42
|
+
@user = ""
|
|
43
|
+
@authorized = false
|
|
44
|
+
|
|
24
45
|
@@all << self
|
|
25
46
|
end
|
|
26
47
|
|
|
@@ -36,9 +57,22 @@ module Peatio::MQ::Events
|
|
|
36
57
|
@exchange_name = "peatio.events.market"
|
|
37
58
|
end
|
|
38
59
|
|
|
39
|
-
def
|
|
40
|
-
|
|
60
|
+
def connect!
|
|
61
|
+
@exchange = Peatio::MQ::Client.channel.topic(@exchange_name)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def publish(type, id, event, payload)
|
|
65
|
+
routing_key = [type, id, event].join(".")
|
|
66
|
+
serialized_data = JSON.dump(payload)
|
|
67
|
+
|
|
68
|
+
@exchange.publish(serialized_data, routing_key: routing_key)
|
|
69
|
+
|
|
70
|
+
Peatio::Logger::debug { "published event to #{routing_key} " }
|
|
41
71
|
|
|
72
|
+
yield if block_given?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def subscribe
|
|
42
76
|
exchange = Peatio::MQ::Client.channel.topic(@exchange_name)
|
|
43
77
|
|
|
44
78
|
suffix = "#{Socket.gethostname.split(/-/).last}#{Random.rand(10_000)}"
|
|
@@ -47,19 +81,42 @@ module Peatio::MQ::Events
|
|
|
47
81
|
|
|
48
82
|
Peatio::MQ::Client.channel
|
|
49
83
|
.queue(queue_name, durable: false, auto_delete: true)
|
|
50
|
-
.bind(exchange, routing_key: "#").subscribe do |metadata, payload|
|
|
84
|
+
.bind(exchange, routing_key: "#").subscribe do |delivery_info, metadata, payload|
|
|
85
|
+
|
|
86
|
+
# type@id@event
|
|
87
|
+
# type can be public|private
|
|
88
|
+
# id can be user id or market
|
|
89
|
+
# event can be anything like order_completed or just trade
|
|
51
90
|
|
|
52
|
-
|
|
91
|
+
routing_key = delivery_info.routing_key
|
|
92
|
+
if routing_key.count(".") != 2
|
|
93
|
+
Peatio::Logger::error do
|
|
94
|
+
"got invalid routing key from amqp: #{routing_key}"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
next
|
|
98
|
+
end
|
|
53
99
|
|
|
54
|
-
event =
|
|
100
|
+
type, id, event = routing_key.split(".")
|
|
55
101
|
|
|
56
|
-
|
|
57
|
-
|
|
102
|
+
if type == "private"
|
|
103
|
+
Client.user(id) do |client|
|
|
104
|
+
if client.streams.include?(event)
|
|
105
|
+
client.send_payload payload
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
next
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
stream = [id, event].join(".")
|
|
113
|
+
|
|
114
|
+
Client.all.each do |handler|
|
|
115
|
+
if handler.streams.include?(stream)
|
|
58
116
|
handler.send_payload payload
|
|
59
117
|
end
|
|
60
118
|
end
|
|
61
119
|
end
|
|
62
120
|
end
|
|
63
121
|
end
|
|
64
|
-
|
|
65
122
|
end
|
data/lib/peatio/ranger.rb
CHANGED
|
@@ -1,31 +1,106 @@
|
|
|
1
1
|
module Peatio::Ranger
|
|
2
|
-
|
|
2
|
+
class Connection
|
|
3
|
+
def initialize(authenticator, socket, logger)
|
|
4
|
+
@authenticator = authenticator
|
|
5
|
+
@socket = socket
|
|
6
|
+
@logger = logger
|
|
7
|
+
@streams = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def send(method, data)
|
|
11
|
+
payload = JSON.dump(method => data)
|
|
12
|
+
@logger.debug { payload }
|
|
13
|
+
@socket.send payload
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def handle(msg)
|
|
17
|
+
authorized = false
|
|
18
|
+
begin
|
|
19
|
+
data = JSON.parse(msg)
|
|
20
|
+
|
|
21
|
+
token = data["jwt"]
|
|
22
|
+
|
|
23
|
+
payload = @authenticator.authenticate!(token)
|
|
24
|
+
|
|
25
|
+
authorized = true
|
|
26
|
+
rescue JSON::ParserError
|
|
27
|
+
rescue => error
|
|
28
|
+
@logger.error error.message
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if !authorized
|
|
32
|
+
send :error, message: "Authentication failed."
|
|
33
|
+
return
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
@client.user = payload[:uid]
|
|
37
|
+
@client.authorized = true
|
|
38
|
+
|
|
39
|
+
@logger.info "ranger: user #{@client.user} authenticated #{@streams}"
|
|
40
|
+
|
|
41
|
+
send :success, message: "Authenticated."
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def handshake(handshake)
|
|
45
|
+
query = URI::decode_www_form(handshake.query_string)
|
|
46
|
+
|
|
47
|
+
@streams = query.map do |item|
|
|
48
|
+
if item.first == "stream"
|
|
49
|
+
item.last
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
@logger.info "ranger: WebSocket connection openned, streams: #{@streams}"
|
|
54
|
+
|
|
55
|
+
@client = Peatio::MQ::Events::Client.new(
|
|
56
|
+
@socket, @streams,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@socket.instance_variable_set(:@connection_handler, @client)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.run!(jwt_public_key)
|
|
64
|
+
host = ENV["RANGER_HOST"] || "0.0.0.0"
|
|
65
|
+
port = ENV["RANGER_PORT"] || "8081"
|
|
66
|
+
|
|
67
|
+
authenticator = Peatio::Auth::JWTAuthenticator.new(jwt_public_key)
|
|
68
|
+
|
|
3
69
|
logger = Peatio::Logger.logger
|
|
4
|
-
port = 8081
|
|
5
70
|
logger.info "Starting the server on port #{port}"
|
|
6
71
|
|
|
7
72
|
EM.run do
|
|
8
73
|
Peatio::MQ::Client.new
|
|
74
|
+
Peatio::MQ::Client.connect!
|
|
75
|
+
Peatio::MQ::Client.create_channel!
|
|
76
|
+
|
|
9
77
|
Peatio::MQ::Events.subscribe!
|
|
10
78
|
|
|
11
|
-
EM::WebSocket.start(
|
|
12
|
-
|
|
13
|
-
|
|
79
|
+
EM::WebSocket.start(
|
|
80
|
+
host: host,
|
|
81
|
+
port: port,
|
|
82
|
+
secure: true,
|
|
83
|
+
) do |socket|
|
|
84
|
+
connection = Connection.new(authenticator, socket, logger)
|
|
85
|
+
|
|
86
|
+
socket.onopen do |handshake|
|
|
87
|
+
connection.handshake(handshake)
|
|
88
|
+
end
|
|
14
89
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Peatio::MQ::Events::SocketHandler.new(ws, "eurusd.order_created")
|
|
18
|
-
)
|
|
90
|
+
socket.onmessage do |msg|
|
|
91
|
+
connection.handle(msg)
|
|
19
92
|
end
|
|
20
93
|
|
|
21
|
-
|
|
94
|
+
socket.onclose do
|
|
95
|
+
logger.info "ranger: WebSocket connection closed"
|
|
96
|
+
end
|
|
22
97
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
98
|
+
socket.onerror do |e|
|
|
99
|
+
logger.error "ranger: WebSocket Error: #{e.message}"
|
|
100
|
+
end
|
|
26
101
|
end
|
|
102
|
+
|
|
103
|
+
yield if block_given?
|
|
27
104
|
end
|
|
28
105
|
end
|
|
29
|
-
|
|
30
|
-
module_function :run!
|
|
31
106
|
end
|
data/lib/peatio/version.rb
CHANGED
data/peatio.gemspec
CHANGED
|
@@ -4,23 +4,22 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
require "peatio/version"
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name
|
|
8
|
-
spec.version
|
|
9
|
-
spec.authors
|
|
10
|
-
spec.email
|
|
11
|
-
|
|
12
|
-
spec.summary = %q{Peatio is a gem for running critical core services}
|
|
13
|
-
spec.description = %q{Peatio gem contains microservices and command line tools}
|
|
14
|
-
spec.homepage = "https://www.peatio.tech"
|
|
7
|
+
spec.name = "peatio"
|
|
8
|
+
spec.version = Peatio::VERSION
|
|
9
|
+
spec.authors = ["Louis B.", "Camille M."]
|
|
10
|
+
spec.email = ["lbellet@heliostech.fr"]
|
|
15
11
|
|
|
12
|
+
spec.summary = %q{Peatio is a gem for running critical core services}
|
|
13
|
+
spec.description = %q{Peatio gem contains microservices and command line tools}
|
|
14
|
+
spec.homepage = "https://www.peatio.tech"
|
|
16
15
|
|
|
17
16
|
# Specify which files should be added to the gem when it is released.
|
|
18
17
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
19
|
-
spec.files
|
|
18
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
|
20
19
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
21
20
|
end
|
|
22
|
-
spec.bindir
|
|
23
|
-
spec.executables
|
|
21
|
+
spec.bindir = "bin"
|
|
22
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
24
23
|
spec.require_paths = ["lib"]
|
|
25
24
|
|
|
26
25
|
spec.add_dependency "clamp"
|
|
@@ -28,9 +27,14 @@ Gem::Specification.new do |spec|
|
|
|
28
27
|
spec.add_dependency "eventmachine"
|
|
29
28
|
spec.add_dependency "em-websocket"
|
|
30
29
|
spec.add_dependency "mysql2"
|
|
30
|
+
spec.add_dependency "jwt"
|
|
31
|
+
spec.add_dependency "bunny"
|
|
31
32
|
spec.add_development_dependency "bundler", "~> 1.16"
|
|
32
33
|
spec.add_development_dependency "rake", "~> 10.0"
|
|
33
34
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
35
|
+
spec.add_development_dependency "em-spec"
|
|
36
|
+
spec.add_development_dependency "em-websocket-client"
|
|
37
|
+
spec.add_development_dependency "bunny-mock"
|
|
34
38
|
spec.add_development_dependency "simplecov"
|
|
35
39
|
spec.add_development_dependency "simplecov-json"
|
|
36
40
|
spec.add_development_dependency "rspec_junit_formatter"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: peatio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Louis B.
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2018-08-
|
|
12
|
+
date: 2018-08-17 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: clamp
|
|
@@ -81,6 +81,34 @@ dependencies:
|
|
|
81
81
|
- - ">="
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
83
|
version: '0'
|
|
84
|
+
- !ruby/object:Gem::Dependency
|
|
85
|
+
name: jwt
|
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - ">="
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '0'
|
|
91
|
+
type: :runtime
|
|
92
|
+
prerelease: false
|
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - ">="
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '0'
|
|
98
|
+
- !ruby/object:Gem::Dependency
|
|
99
|
+
name: bunny
|
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
type: :runtime
|
|
106
|
+
prerelease: false
|
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '0'
|
|
84
112
|
- !ruby/object:Gem::Dependency
|
|
85
113
|
name: bundler
|
|
86
114
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -123,6 +151,48 @@ dependencies:
|
|
|
123
151
|
- - "~>"
|
|
124
152
|
- !ruby/object:Gem::Version
|
|
125
153
|
version: '3.0'
|
|
154
|
+
- !ruby/object:Gem::Dependency
|
|
155
|
+
name: em-spec
|
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
|
157
|
+
requirements:
|
|
158
|
+
- - ">="
|
|
159
|
+
- !ruby/object:Gem::Version
|
|
160
|
+
version: '0'
|
|
161
|
+
type: :development
|
|
162
|
+
prerelease: false
|
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
164
|
+
requirements:
|
|
165
|
+
- - ">="
|
|
166
|
+
- !ruby/object:Gem::Version
|
|
167
|
+
version: '0'
|
|
168
|
+
- !ruby/object:Gem::Dependency
|
|
169
|
+
name: em-websocket-client
|
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
|
171
|
+
requirements:
|
|
172
|
+
- - ">="
|
|
173
|
+
- !ruby/object:Gem::Version
|
|
174
|
+
version: '0'
|
|
175
|
+
type: :development
|
|
176
|
+
prerelease: false
|
|
177
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
178
|
+
requirements:
|
|
179
|
+
- - ">="
|
|
180
|
+
- !ruby/object:Gem::Version
|
|
181
|
+
version: '0'
|
|
182
|
+
- !ruby/object:Gem::Dependency
|
|
183
|
+
name: bunny-mock
|
|
184
|
+
requirement: !ruby/object:Gem::Requirement
|
|
185
|
+
requirements:
|
|
186
|
+
- - ">="
|
|
187
|
+
- !ruby/object:Gem::Version
|
|
188
|
+
version: '0'
|
|
189
|
+
type: :development
|
|
190
|
+
prerelease: false
|
|
191
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
192
|
+
requirements:
|
|
193
|
+
- - ">="
|
|
194
|
+
- !ruby/object:Gem::Version
|
|
195
|
+
version: '0'
|
|
126
196
|
- !ruby/object:Gem::Dependency
|
|
127
197
|
name: simplecov
|
|
128
198
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -202,12 +272,15 @@ files:
|
|
|
202
272
|
- bin/peatio
|
|
203
273
|
- bin/setup
|
|
204
274
|
- lib/peatio.rb
|
|
275
|
+
- lib/peatio/auth/error.rb
|
|
276
|
+
- lib/peatio/auth/jwt_authenticator.rb
|
|
205
277
|
- lib/peatio/command/amqp.rb
|
|
206
278
|
- lib/peatio/command/base.rb
|
|
207
279
|
- lib/peatio/command/db.rb
|
|
208
280
|
- lib/peatio/command/inject.rb
|
|
209
281
|
- lib/peatio/command/root.rb
|
|
210
282
|
- lib/peatio/command/service.rb
|
|
283
|
+
- lib/peatio/error.rb
|
|
211
284
|
- lib/peatio/executor.rb
|
|
212
285
|
- lib/peatio/injectors/peatio_events.rb
|
|
213
286
|
- lib/peatio/logger.rb
|