peatio 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/.simplecov +17 -0
- data/.travis.yml +5 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +56 -5
- data/README.md +0 -1
- data/Rakefile +1 -1
- data/bin/peatio +12 -0
- data/lib/peatio/command/amqp.rb +9 -0
- data/lib/peatio/command/base.rb +11 -0
- data/lib/peatio/command/db.rb +20 -0
- data/lib/peatio/command/inject.rb +11 -0
- data/lib/peatio/command/root.rb +14 -0
- data/lib/peatio/command/service.rb +17 -0
- data/lib/peatio/executor.rb +64 -0
- data/lib/peatio/injectors/peatio_events.rb +190 -0
- data/lib/peatio/logger.rb +37 -0
- data/lib/peatio/mq/client.rb +24 -0
- data/lib/peatio/mq/events.rb +65 -0
- data/lib/peatio/ranger.rb +31 -0
- data/lib/peatio/sql/client.rb +19 -0
- data/lib/peatio/sql/schema.rb +72 -0
- data/lib/peatio/version.rb +1 -1
- data/lib/peatio.rb +14 -4
- data/peatio.gemspec +23 -11
- metadata +160 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3697d323f43f4c9387766cae5aeb0a77acb29d47f933f84f95fa68ad95a4cf97
|
4
|
+
data.tar.gz: f345354fdaa1eb1660394c7d2373ced0d34aa80e09a336cf4541fd6ce58a5511
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc2e62d12ef1bf3b58cbc378fe1af25dfc0fcd6a79270eff490bde22cf5deff4b9674d44e786be4fe943d699bb5ac16e062ba45a6d6b2a822a73c32213a6b182
|
7
|
+
data.tar.gz: 18d134f48a68fcbdfb2598d5dd7da95c844668ec1c550fcd9535e1193631f83f2ace108a96257cb392e22c4b9cf17d99d160f465f8eac3bf144900c3dce0d16f
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.simplecov
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
require 'simplecov-json'
|
3
|
+
|
4
|
+
SimpleCov.start do
|
5
|
+
add_filter '/spec/'
|
6
|
+
end
|
7
|
+
|
8
|
+
SimpleCov.formatters = [
|
9
|
+
SimpleCov::Formatter::HTMLFormatter,
|
10
|
+
SimpleCov::Formatter::JSONFormatter,
|
11
|
+
]
|
12
|
+
|
13
|
+
# save to CircleCI's artifacts directory if we're on CircleCI
|
14
|
+
if ENV['CIRCLE_ARTIFACTS']
|
15
|
+
dir = File.join(ENV['CIRCLE_ARTIFACTS'], "coverage")
|
16
|
+
SimpleCov.coverage_dir(dir)
|
17
|
+
end
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,18 +1,43 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
peatio (0.
|
4
|
+
peatio (0.2.0)
|
5
|
+
amqp
|
6
|
+
clamp
|
7
|
+
em-websocket
|
8
|
+
eventmachine
|
9
|
+
mysql2
|
5
10
|
|
6
11
|
GEM
|
7
12
|
remote: https://rubygems.org/
|
8
13
|
specs:
|
14
|
+
amq-protocol (2.3.0)
|
15
|
+
amqp (1.8.0)
|
16
|
+
amq-protocol (>= 2.2.0)
|
17
|
+
eventmachine
|
18
|
+
ast (2.4.0)
|
19
|
+
clamp (1.3.0)
|
9
20
|
diff-lcs (1.3)
|
21
|
+
docile (1.3.1)
|
22
|
+
em-websocket (0.5.1)
|
23
|
+
eventmachine (>= 0.12.9)
|
24
|
+
http_parser.rb (~> 0.6.0)
|
25
|
+
eventmachine (1.2.7)
|
26
|
+
http_parser.rb (0.6.0)
|
27
|
+
jaro_winkler (1.5.1)
|
28
|
+
json (2.1.0)
|
29
|
+
mysql2 (0.5.2)
|
30
|
+
parallel (1.12.1)
|
31
|
+
parser (2.5.1.0)
|
32
|
+
ast (~> 2.4.0)
|
33
|
+
powerpack (0.1.2)
|
34
|
+
rainbow (3.0.0)
|
10
35
|
rake (10.5.0)
|
11
36
|
rspec (3.7.0)
|
12
37
|
rspec-core (~> 3.7.0)
|
13
38
|
rspec-expectations (~> 3.7.0)
|
14
39
|
rspec-mocks (~> 3.7.0)
|
15
|
-
rspec-core (3.7.
|
40
|
+
rspec-core (3.7.1)
|
16
41
|
rspec-support (~> 3.7.0)
|
17
42
|
rspec-expectations (3.7.0)
|
18
43
|
diff-lcs (>= 1.2.0, < 2.0)
|
@@ -20,16 +45,42 @@ GEM
|
|
20
45
|
rspec-mocks (3.7.0)
|
21
46
|
diff-lcs (>= 1.2.0, < 2.0)
|
22
47
|
rspec-support (~> 3.7.0)
|
23
|
-
rspec-support (3.7.
|
48
|
+
rspec-support (3.7.1)
|
49
|
+
rspec_junit_formatter (0.4.1)
|
50
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
51
|
+
rubocop (0.57.2)
|
52
|
+
jaro_winkler (~> 1.5.1)
|
53
|
+
parallel (~> 1.10)
|
54
|
+
parser (>= 2.5)
|
55
|
+
powerpack (~> 0.1)
|
56
|
+
rainbow (>= 2.2.2, < 4.0)
|
57
|
+
ruby-progressbar (~> 1.7)
|
58
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
59
|
+
rubocop-github (0.10.0)
|
60
|
+
rubocop (~> 0.51)
|
61
|
+
ruby-progressbar (1.9.0)
|
62
|
+
simplecov (0.16.1)
|
63
|
+
docile (~> 1.1)
|
64
|
+
json (>= 1.8, < 3)
|
65
|
+
simplecov-html (~> 0.10.0)
|
66
|
+
simplecov-html (0.10.2)
|
67
|
+
simplecov-json (0.2)
|
68
|
+
json
|
69
|
+
simplecov
|
70
|
+
unicode-display_width (1.4.0)
|
24
71
|
|
25
72
|
PLATFORMS
|
26
73
|
ruby
|
27
74
|
|
28
75
|
DEPENDENCIES
|
29
|
-
bundler (~> 1.
|
76
|
+
bundler (~> 1.16)
|
30
77
|
peatio!
|
31
78
|
rake (~> 10.0)
|
32
79
|
rspec (~> 3.0)
|
80
|
+
rspec_junit_formatter
|
81
|
+
rubocop-github
|
82
|
+
simplecov
|
83
|
+
simplecov-json
|
33
84
|
|
34
85
|
BUNDLED WITH
|
35
|
-
1.
|
86
|
+
1.16.3
|
data/README.md
CHANGED
data/Rakefile
CHANGED
data/bin/peatio
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- RUBY -*-
|
3
|
+
|
4
|
+
PEATIO_CORE = ENV["PEATIO_CORE"] || File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
5
|
+
$: << File.join(PEATIO_CORE, "lib")
|
6
|
+
|
7
|
+
require "clamp"
|
8
|
+
|
9
|
+
require "peatio"
|
10
|
+
require "peatio/command/root"
|
11
|
+
|
12
|
+
Peatio::Root.run
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Peatio::Command::DB
|
2
|
+
class Create < Peatio::Command::Base
|
3
|
+
def execute
|
4
|
+
client = Peatio::Sql::Client.new
|
5
|
+
database_name = client.config.delete(:database)
|
6
|
+
Peatio::Sql::Schema.new(client.connect).create_database(database_name)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Migrate < Peatio::Command::Base
|
11
|
+
def execute
|
12
|
+
Peatio::Sql::Schema.new(sql_client).create_tables
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Root < Peatio::Command::Base
|
17
|
+
subcommand "create", "Create database", Peatio::Command::DB::Create
|
18
|
+
subcommand "migrate", "Create tables", Peatio::Command::DB::Migrate
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Peatio::Command
|
2
|
+
class Inject < Peatio::Command::Base
|
3
|
+
class PeatioEvents < Peatio::Command::Base
|
4
|
+
def execute
|
5
|
+
Peatio::Injectors::PeatioEvents.new.run!
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
subcommand "peatio_events", "Inject peatio events in mq", PeatioEvents
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "peatio/command/base"
|
2
|
+
require "peatio/command/service"
|
3
|
+
require "peatio/command/db"
|
4
|
+
require "peatio/command/amqp"
|
5
|
+
require "peatio/command/inject"
|
6
|
+
|
7
|
+
module Peatio
|
8
|
+
class Root < Command::Base
|
9
|
+
subcommand "amqp", "AMQP related sub-commands", Peatio::Command::AMQP::Root
|
10
|
+
subcommand "db", "Database related sub-commands", Peatio::Command::DB::Root
|
11
|
+
subcommand "service", "Services management related sub-commands", Peatio::Command::Service::Root
|
12
|
+
subcommand "inject", "Data injectors", Peatio::Command::Inject
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Peatio::Command::Service
|
2
|
+
|
3
|
+
class Start < Peatio::Command::Base
|
4
|
+
class Ranger < Peatio::Command::Base
|
5
|
+
def execute
|
6
|
+
::Peatio::Ranger.run!
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
subcommand "ranger", "Start ranger process", Ranger
|
11
|
+
end
|
12
|
+
|
13
|
+
class Root < Peatio::Command::Base
|
14
|
+
subcommand "start", "Start a service", Start
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "mysql2"
|
2
|
+
require "benchmark"
|
3
|
+
|
4
|
+
client = Mysql2::Client.new(
|
5
|
+
host: "172.19.0.3",
|
6
|
+
username: "root",
|
7
|
+
password: "changeme",
|
8
|
+
port: 3306,
|
9
|
+
database: "peatio_development")
|
10
|
+
|
11
|
+
queries = [
|
12
|
+
"INSERT INTO `trades` (`ask_id`, `ask_member_id`, `bid_id`, `bid_member_id`, `price`, `volume`, `funds`, `market_id`, `trend`, `created_at`, `updated_at`) VALUES (18711, 81, 18708, 82, 0.99999999, 50.0, 49.9999995, 'eurusd', 0, NOW(), NOW())",
|
13
|
+
"UPDATE `accounts` SET `accounts`.`locked` = 3571.09999702 WHERE `accounts`.`id` = 164",
|
14
|
+
"UPDATE `accounts` SET `accounts`.`balance` = 999995119.5335 WHERE `accounts`.`id` = 163",
|
15
|
+
"UPDATE `accounts` SET `accounts`.`locked` = 4257.0 WHERE `accounts`.`id` = 161",
|
16
|
+
"UPDATE `accounts` SET `accounts`.`balance` = 999995825.720262199325 WHERE `accounts`.`id` = 162",
|
17
|
+
"UPDATE `orders` SET `volume` = 20.0, `locked` = 19.9999998, `funds_received` = 53.0, `trades_count` = 2, `updated_at` = '2018-06-25 23:44:37' WHERE `orders`.`id` = 18708",
|
18
|
+
"UPDATE `orders` SET `volume` = 0.0, `locked` = 0.0, `funds_received` = 78.59999924, `trades_count` = 2, `state` = 200, `updated_at` = '2018-06-25 23:44:37' WHERE `orders`.`id` = 18711"
|
19
|
+
]
|
20
|
+
|
21
|
+
puts Benchmark.measure {
|
22
|
+
1_000.times {
|
23
|
+
|
24
|
+
client.query("begin")
|
25
|
+
begin
|
26
|
+
|
27
|
+
100.times {
|
28
|
+
queries.each do |q|
|
29
|
+
client.query q
|
30
|
+
end
|
31
|
+
}
|
32
|
+
|
33
|
+
rescue Mysql2::Error => e
|
34
|
+
puts "+++++++ DB ERROR - ROLLING BACK ++++++++"
|
35
|
+
puts e
|
36
|
+
client.query("rollback")
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
client.query("commit") #commit the changes to the DB
|
40
|
+
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
client.close
|
45
|
+
|
46
|
+
__END__
|
47
|
+
|
48
|
+
require 'mysql2/em'
|
49
|
+
|
50
|
+
EM.run do
|
51
|
+
client = Mysql2::EM::Client.new(
|
52
|
+
:host => '172.19.0.3',
|
53
|
+
:username => 'root',
|
54
|
+
:password => 'changeme',
|
55
|
+
:port => 3306,
|
56
|
+
:database => 'peatio_development')
|
57
|
+
|
58
|
+
|
59
|
+
defer1 = client.query "SELECT sleep(3) as first_query"
|
60
|
+
defer1.callback do |result|
|
61
|
+
puts "Result: #{result.to_a.inspect}"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module Peatio::Injectors
|
2
|
+
class PeatioEvents
|
3
|
+
attr_accessor :market, :seller_uid, :buyer_uid, :logger
|
4
|
+
|
5
|
+
def run!
|
6
|
+
require "time"
|
7
|
+
@logger = Peatio::Logger.logger
|
8
|
+
@market = "eurusd"
|
9
|
+
@seller_uid = 21
|
10
|
+
@buyer_uid = 42
|
11
|
+
@messages = create_messages
|
12
|
+
@exchange_name = "peatio.events.market"
|
13
|
+
|
14
|
+
EventMachine.run do
|
15
|
+
Peatio::MQ::Client.new
|
16
|
+
AMQP::Exchange.new(Peatio::MQ::Client.channel, :topic, @exchange_name) do |exchange, declare_ok|
|
17
|
+
logger.info "Exchange #{exchange.name} is ready to go"
|
18
|
+
next_message(exchange)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def next_message(exchange)
|
24
|
+
if message = @messages.shift
|
25
|
+
event_name, data = message
|
26
|
+
serialized_data = JSON.dump(data)
|
27
|
+
exchange.publish(serialized_data, routing_key: event_name) do
|
28
|
+
logger.debug { "event #{event_name} sent with data: #{serialized_data}" }
|
29
|
+
next_message(exchange)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
Peatio::MQ::Client.disconnect { EventMachine.stop }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_messages
|
37
|
+
[
|
38
|
+
order_created,
|
39
|
+
order_canceled,
|
40
|
+
order_completed,
|
41
|
+
order_updated,
|
42
|
+
trade_completed,
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
def created_at
|
47
|
+
Time.now - 600
|
48
|
+
end
|
49
|
+
|
50
|
+
def updated_at
|
51
|
+
Time.now
|
52
|
+
end
|
53
|
+
alias :completed_at :updated_at
|
54
|
+
alias :canceled_at :updated_at
|
55
|
+
|
56
|
+
def order_created
|
57
|
+
[
|
58
|
+
"#{market}.order_created",
|
59
|
+
{
|
60
|
+
market: "#{market}",
|
61
|
+
type: "buy",
|
62
|
+
trader_uid: buyer_uid,
|
63
|
+
income_unit: "btc",
|
64
|
+
income_fee_type: "relative",
|
65
|
+
income_fee_value: "0.0015",
|
66
|
+
outcome_unit: "usd",
|
67
|
+
outcome_fee_type: "relative",
|
68
|
+
outcome_fee_value: "0.0",
|
69
|
+
initial_income_amount: "14.0",
|
70
|
+
current_income_amount: "14.0",
|
71
|
+
initial_outcome_amount: "0.42",
|
72
|
+
current_outcome_amount: "0.42",
|
73
|
+
strategy: "limit",
|
74
|
+
price: "0.03",
|
75
|
+
state: "open",
|
76
|
+
trades_count: 0,
|
77
|
+
created_at: created_at.iso8601
|
78
|
+
}
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
def order_canceled
|
83
|
+
[
|
84
|
+
"#{market}.order_canceled",
|
85
|
+
{
|
86
|
+
market: "#{market}",
|
87
|
+
type: "sell",
|
88
|
+
trader_uid: seller_uid,
|
89
|
+
income_unit: "usd",
|
90
|
+
income_fee_type: "relative",
|
91
|
+
income_fee_value: "0.0015",
|
92
|
+
outcome_unit: "btc",
|
93
|
+
outcome_fee_type: "relative",
|
94
|
+
outcome_fee_value: "0.0",
|
95
|
+
initial_income_amount: "3.0",
|
96
|
+
current_income_amount: "3.0",
|
97
|
+
initial_outcome_amount: "100.0",
|
98
|
+
current_outcome_amount: "100.0",
|
99
|
+
strategy: "limit",
|
100
|
+
price: "0.03",
|
101
|
+
state: "canceled",
|
102
|
+
trades_count: 0,
|
103
|
+
created_at: created_at.iso8601,
|
104
|
+
canceled_at: canceled_at.iso8601
|
105
|
+
}
|
106
|
+
]
|
107
|
+
end
|
108
|
+
|
109
|
+
def order_completed
|
110
|
+
[
|
111
|
+
"#{market}.order_completed", {
|
112
|
+
market: "#{market}",
|
113
|
+
type: "sell",
|
114
|
+
trader_uid: seller_uid,
|
115
|
+
income_unit: "usd",
|
116
|
+
income_fee_type: "relative",
|
117
|
+
income_fee_value: "0.0015",
|
118
|
+
outcome_unit: "btc",
|
119
|
+
outcome_fee_type: "relative",
|
120
|
+
outcome_fee_value: "0.0",
|
121
|
+
initial_income_amount: "3.0",
|
122
|
+
current_income_amount: "0.0",
|
123
|
+
previous_income_amount: "3.0",
|
124
|
+
initial_outcome_amount: "100.0",
|
125
|
+
current_outcome_amount: "0.0",
|
126
|
+
previous_outcome_amount: "100.0",
|
127
|
+
strategy: "limit",
|
128
|
+
price: "0.03",
|
129
|
+
state: "completed",
|
130
|
+
trades_count: 1,
|
131
|
+
created_at: created_at.iso8601,
|
132
|
+
completed_at: completed_at.iso8601
|
133
|
+
}
|
134
|
+
]
|
135
|
+
end
|
136
|
+
|
137
|
+
def order_updated
|
138
|
+
[
|
139
|
+
"#{market}.order_updated", {
|
140
|
+
market: "#{market}",
|
141
|
+
type: "sell",
|
142
|
+
trader_uid: seller_uid,
|
143
|
+
income_unit: "usd",
|
144
|
+
income_fee_type: "relative",
|
145
|
+
income_fee_value: "0.0015",
|
146
|
+
outcome_unit: "btc",
|
147
|
+
outcome_fee_type: "relative",
|
148
|
+
outcome_fee_value: "0.0",
|
149
|
+
initial_income_amount: "3.0",
|
150
|
+
current_income_amount: "2.4",
|
151
|
+
previous_income_amount: "3.0",
|
152
|
+
initial_outcome_amount: "100.0",
|
153
|
+
current_outcome_amount: "80.0",
|
154
|
+
previous_outcome_amount: "100.0",
|
155
|
+
strategy: "limit",
|
156
|
+
price: "0.03",
|
157
|
+
state: "open",
|
158
|
+
trades_count: 1,
|
159
|
+
created_at: created_at.iso8601,
|
160
|
+
updated_at: updated_at.iso8601
|
161
|
+
}
|
162
|
+
]
|
163
|
+
end
|
164
|
+
|
165
|
+
def trade_completed
|
166
|
+
[
|
167
|
+
"#{market}.trade_completed", {
|
168
|
+
market: "#{market}",
|
169
|
+
price: "0.03",
|
170
|
+
buyer_uid: buyer_uid,
|
171
|
+
buyer_income_unit: "btc",
|
172
|
+
buyer_income_amount: "14.0",
|
173
|
+
buyer_income_fee: "0.021",
|
174
|
+
buyer_outcome_unit: "usd",
|
175
|
+
buyer_outcome_amount: "0.42",
|
176
|
+
buyer_outcome_fee: "0.0",
|
177
|
+
seller_uid: seller_uid,
|
178
|
+
seller_income_unit: "usd",
|
179
|
+
seller_income_amount: "0.42",
|
180
|
+
seller_income_fee: "0.00063",
|
181
|
+
seller_outcome_unit: "btc",
|
182
|
+
seller_outcome_amount: "14.0",
|
183
|
+
seller_outcome_fee: "0.0",
|
184
|
+
completed_at: completed_at.iso8601
|
185
|
+
}
|
186
|
+
]
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Peatio
|
2
|
+
class Logger
|
3
|
+
class << self
|
4
|
+
def logger
|
5
|
+
@logger ||= ::Logger.new(STDERR, level: level)
|
6
|
+
end
|
7
|
+
|
8
|
+
def level
|
9
|
+
(ENV["LOG_LEVEL"] || "debug").downcase.to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def debug(progname = nil, &block)
|
13
|
+
logger.debug(progname, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def info(progname = nil, &block)
|
17
|
+
logger.info(progname, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def warn(progname = nil, &block)
|
21
|
+
logger.warn(progname, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def error(progname = nil, &block)
|
25
|
+
logger.error(progname, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def fatal(progname = nil, &block)
|
29
|
+
logger.fatal(progname, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def unknown(progname = nil, &block)
|
33
|
+
logger.unknown(progname, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Peatio::MQ
|
2
|
+
class Client
|
3
|
+
class << self
|
4
|
+
attr_reader :channel, :connection
|
5
|
+
|
6
|
+
def new
|
7
|
+
options = {
|
8
|
+
host: ENV["RABBITMQ_HOST"] || "0.0.0.0",
|
9
|
+
port: ENV["RABBITMQ_PORT"] || "5672",
|
10
|
+
username: ENV["RABBITMQ_USER"],
|
11
|
+
password: ENV["RABBITMQ_PASSWORD"],
|
12
|
+
}
|
13
|
+
@connection = AMQP.connect(options)
|
14
|
+
@channel = AMQP::Channel.new(@connection)
|
15
|
+
end
|
16
|
+
|
17
|
+
def disconnect
|
18
|
+
connection.close do
|
19
|
+
yield
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Peatio::MQ::Events
|
2
|
+
def self.subscribe!
|
3
|
+
ranger = RangerEvents.new
|
4
|
+
ranger.subscribe
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.start!
|
8
|
+
end
|
9
|
+
|
10
|
+
class SocketHandler
|
11
|
+
attr_accessor :event
|
12
|
+
|
13
|
+
@@all = []
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def all
|
17
|
+
@@all
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(socket, event)
|
22
|
+
@socket = socket
|
23
|
+
@event = event
|
24
|
+
@@all << self
|
25
|
+
end
|
26
|
+
|
27
|
+
def send_payload(message)
|
28
|
+
@socket.send message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class RangerEvents
|
33
|
+
attr_accessor :exchange_name
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
@exchange_name = "peatio.events.market"
|
37
|
+
end
|
38
|
+
|
39
|
+
def subscribe
|
40
|
+
require "socket"
|
41
|
+
|
42
|
+
exchange = Peatio::MQ::Client.channel.topic(@exchange_name)
|
43
|
+
|
44
|
+
suffix = "#{Socket.gethostname.split(/-/).last}#{Random.rand(10_000)}"
|
45
|
+
|
46
|
+
queue_name = "#{@topic_name}.ranger.#{suffix}"
|
47
|
+
|
48
|
+
Peatio::MQ::Client.channel
|
49
|
+
.queue(queue_name, durable: false, auto_delete: true)
|
50
|
+
.bind(exchange, routing_key: "#").subscribe do |metadata, payload|
|
51
|
+
|
52
|
+
Peatio::Logger.debug { "event received: #{payload}" }
|
53
|
+
|
54
|
+
event = metadata.routing_key
|
55
|
+
|
56
|
+
SocketHandler.all.each do |handler|
|
57
|
+
if event == handler.event
|
58
|
+
handler.send_payload payload
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Peatio::Ranger
|
2
|
+
def run!
|
3
|
+
logger = Peatio::Logger.logger
|
4
|
+
port = 8081
|
5
|
+
logger.info "Starting the server on port #{port}"
|
6
|
+
|
7
|
+
EM.run do
|
8
|
+
Peatio::MQ::Client.new
|
9
|
+
Peatio::MQ::Events.subscribe!
|
10
|
+
|
11
|
+
EM::WebSocket.start(host: "0.0.0.0", port: port) do |ws|
|
12
|
+
ws.onopen do |id|
|
13
|
+
logger.info "ranger: WebSocket connection openned"
|
14
|
+
|
15
|
+
ws.instance_variable_set(
|
16
|
+
:@connection_handler,
|
17
|
+
Peatio::MQ::Events::SocketHandler.new(ws, "eurusd.order_created")
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
ws.onclose { logger.info "ranger: WebSocket connection closed" }
|
22
|
+
|
23
|
+
ws.onerror { |e|
|
24
|
+
puts "ranger: WebSocket Error: #{e.message}"
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module_function :run!
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Peatio::Sql
|
2
|
+
class Client
|
3
|
+
attr_accessor :client, :config
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@config = {
|
7
|
+
host: ENV["DATABASE_HOST"] || "localhost",
|
8
|
+
username: ENV["DATABASE_USER"] || "root",
|
9
|
+
password: ENV["DATABASE_PASS"] || "",
|
10
|
+
port: ENV["DATABASE_PORT"] || "3306",
|
11
|
+
database: ENV["DATABASE_NAME"] || "peatio_development",
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def connect
|
16
|
+
@client = Mysql2::Client.new(config)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Peatio::Sql
|
2
|
+
class Schema
|
3
|
+
attr_accessor :client
|
4
|
+
|
5
|
+
def initialize(sql_client)
|
6
|
+
@client = sql_client
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_database(name)
|
10
|
+
client.query("CREATE DATABASE IF NOT EXISTS `#{ name }`;")
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_tables(options = {})
|
14
|
+
statements = []
|
15
|
+
statements << "DROP TABLE IF EXISTS `operations`;" if options[:drop_if_exists]
|
16
|
+
statements << <<-EOF
|
17
|
+
CREATE TABLE IF NOT EXISTS `operations` (
|
18
|
+
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
19
|
+
code TINYINT UNSIGNED NOT NULL,
|
20
|
+
account_id INT UNSIGNED NOT NULL,
|
21
|
+
reference INT UNSIGNED NOT NULL,
|
22
|
+
debit DECIMAL(32, 16) NOT NULL,
|
23
|
+
credit DECIMAL(32, 16) NOT NULL,
|
24
|
+
created_at DATETIME NOT NULL,
|
25
|
+
updated_at DATETIME NOT NULL,
|
26
|
+
PRIMARY KEY (id),
|
27
|
+
INDEX `balance_key` (account_id, debit, credit)
|
28
|
+
) ENGINE = InnoDB;
|
29
|
+
EOF
|
30
|
+
|
31
|
+
statements << "DROP TABLE IF EXISTS `orders`;" if options[:drop_if_exists]
|
32
|
+
statements << <<EOF
|
33
|
+
CREATE TABLE IF NOT EXISTS`orders` (
|
34
|
+
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
35
|
+
`uid` INT(11) UNSIGNED NOT NULL,
|
36
|
+
`bid` VARCHAR(5) NOT NULL,
|
37
|
+
`ask` VARCHAR(5) NOT NULL,
|
38
|
+
`market` VARCHAR(10) NOT NULL,
|
39
|
+
`price` DECIMAL(32,16) DEFAULT NULL,
|
40
|
+
`volume` DECIMAL(32,16) NOT NULL,
|
41
|
+
`fee` DECIMAL(32,16) NOT NULL DEFAULT '0.0000000000000000',
|
42
|
+
`type` TINYINT UNSIGNED NOT NULL,
|
43
|
+
`state` TINYINT UNSIGNED NOT NULL,
|
44
|
+
`created_at` DATETIME NOT NULL,
|
45
|
+
`updated_at` DATETIME NOT NULL,
|
46
|
+
PRIMARY KEY (`id`)
|
47
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
48
|
+
EOF
|
49
|
+
|
50
|
+
statements << "DROP TABLE IF EXISTS `trades`;" if options[:drop_if_exists]
|
51
|
+
statements << <<EOF
|
52
|
+
CREATE TABLE IF NOT EXISTS `trades` (
|
53
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
54
|
+
`market` varchar(10) NOT NULL,
|
55
|
+
`volume` decimal(32,16) NOT NULL,
|
56
|
+
`price` decimal(32,16) NOT NULL,
|
57
|
+
`ask_id` int(11) NOT NULL,
|
58
|
+
`bid_id` int(11) NOT NULL,
|
59
|
+
`ask_uid` int(11) NOT NULL,
|
60
|
+
`bid_uid` int(11) NOT NULL,
|
61
|
+
`created_at` datetime NOT NULL,
|
62
|
+
`updated_at` datetime NOT NULL,
|
63
|
+
PRIMARY KEY (`id`)
|
64
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
65
|
+
EOF
|
66
|
+
statements.each do |statement|
|
67
|
+
puts statement
|
68
|
+
client.query(statement)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/peatio/version.rb
CHANGED
data/lib/peatio.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
|
-
require "
|
1
|
+
require "logger"
|
2
|
+
require "json"
|
3
|
+
require "mysql2"
|
4
|
+
require "amqp"
|
5
|
+
require "eventmachine"
|
6
|
+
require "em-websocket"
|
2
7
|
|
3
|
-
|
4
|
-
|
5
|
-
|
8
|
+
require "peatio/logger"
|
9
|
+
require "peatio/version"
|
10
|
+
require "peatio/sql/client"
|
11
|
+
require "peatio/sql/schema"
|
12
|
+
require "peatio/mq/client"
|
13
|
+
require "peatio/mq/events"
|
14
|
+
require "peatio/ranger"
|
15
|
+
require "peatio/injectors/peatio_events"
|
data/peatio.gemspec
CHANGED
@@ -1,26 +1,38 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path(
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "peatio/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "peatio"
|
8
8
|
spec.version = Peatio::VERSION
|
9
|
-
spec.authors = ["Louis
|
9
|
+
spec.authors = ["Louis B.", "Camille M."]
|
10
10
|
spec.email = ["lbellet@heliostech.fr"]
|
11
11
|
|
12
|
-
spec.summary = %q{Peatio
|
13
|
-
spec.description = %q{Peatio gem contains
|
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
14
|
spec.homepage = "https://www.peatio.tech"
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
21
|
end
|
19
|
-
spec.bindir = "
|
20
|
-
spec.executables = spec.files.grep(%r{^
|
22
|
+
spec.bindir = "bin"
|
23
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
24
|
spec.require_paths = ["lib"]
|
22
25
|
|
23
|
-
spec.
|
26
|
+
spec.add_dependency "clamp"
|
27
|
+
spec.add_dependency "amqp"
|
28
|
+
spec.add_dependency "eventmachine"
|
29
|
+
spec.add_dependency "em-websocket"
|
30
|
+
spec.add_dependency "mysql2"
|
31
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
24
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
33
|
spec.add_development_dependency "rspec", "~> 3.0"
|
34
|
+
spec.add_development_dependency "simplecov"
|
35
|
+
spec.add_development_dependency "simplecov-json"
|
36
|
+
spec.add_development_dependency "rspec_junit_formatter"
|
37
|
+
spec.add_development_dependency "rubocop-github"
|
26
38
|
end
|
metadata
CHANGED
@@ -1,29 +1,100 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: peatio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Louis
|
7
|
+
- Louis B.
|
8
|
+
- Camille M.
|
8
9
|
autorequire:
|
9
|
-
bindir:
|
10
|
+
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2018-08-09 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: clamp
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: amqp
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: eventmachine
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: em-websocket
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: mysql2
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
13
84
|
- !ruby/object:Gem::Dependency
|
14
85
|
name: bundler
|
15
86
|
requirement: !ruby/object:Gem::Requirement
|
16
87
|
requirements:
|
17
88
|
- - "~>"
|
18
89
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
90
|
+
version: '1.16'
|
20
91
|
type: :development
|
21
92
|
prerelease: false
|
22
93
|
version_requirements: !ruby/object:Gem::Requirement
|
23
94
|
requirements:
|
24
95
|
- - "~>"
|
25
96
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
97
|
+
version: '1.16'
|
27
98
|
- !ruby/object:Gem::Dependency
|
28
99
|
name: rake
|
29
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,20 +123,99 @@ dependencies:
|
|
52
123
|
- - "~>"
|
53
124
|
- !ruby/object:Gem::Version
|
54
125
|
version: '3.0'
|
55
|
-
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: simplecov
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: simplecov-json
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: rspec_junit_formatter
|
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: rubocop-github
|
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
|
+
description: Peatio gem contains microservices and command line tools
|
56
183
|
email:
|
57
184
|
- lbellet@heliostech.fr
|
58
|
-
executables:
|
185
|
+
executables:
|
186
|
+
- console
|
187
|
+
- peatio
|
188
|
+
- setup
|
59
189
|
extensions: []
|
60
190
|
extra_rdoc_files: []
|
61
191
|
files:
|
192
|
+
- ".gitignore"
|
193
|
+
- ".rspec"
|
194
|
+
- ".rubocop.yml"
|
195
|
+
- ".simplecov"
|
196
|
+
- ".travis.yml"
|
62
197
|
- Gemfile
|
63
198
|
- Gemfile.lock
|
64
199
|
- README.md
|
65
200
|
- Rakefile
|
66
201
|
- bin/console
|
202
|
+
- bin/peatio
|
67
203
|
- bin/setup
|
68
204
|
- lib/peatio.rb
|
205
|
+
- lib/peatio/command/amqp.rb
|
206
|
+
- lib/peatio/command/base.rb
|
207
|
+
- lib/peatio/command/db.rb
|
208
|
+
- lib/peatio/command/inject.rb
|
209
|
+
- lib/peatio/command/root.rb
|
210
|
+
- lib/peatio/command/service.rb
|
211
|
+
- lib/peatio/executor.rb
|
212
|
+
- lib/peatio/injectors/peatio_events.rb
|
213
|
+
- lib/peatio/logger.rb
|
214
|
+
- lib/peatio/mq/client.rb
|
215
|
+
- lib/peatio/mq/events.rb
|
216
|
+
- lib/peatio/ranger.rb
|
217
|
+
- lib/peatio/sql/client.rb
|
218
|
+
- lib/peatio/sql/schema.rb
|
69
219
|
- lib/peatio/version.rb
|
70
220
|
- peatio.gemspec
|
71
221
|
homepage: https://www.peatio.tech
|
@@ -87,8 +237,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
237
|
version: '0'
|
88
238
|
requirements: []
|
89
239
|
rubyforge_project:
|
90
|
-
rubygems_version: 2.
|
240
|
+
rubygems_version: 2.7.3
|
91
241
|
signing_key:
|
92
242
|
specification_version: 4
|
93
|
-
summary: Peatio
|
243
|
+
summary: Peatio is a gem for running critical core services
|
94
244
|
test_files: []
|