peatio1.9 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/.simplecov +17 -0
- data/.travis.yml +17 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +107 -0
- data/README.md +35 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/peatio +12 -0
- data/bin/setup +8 -0
- data/lib/peatio.rb +20 -0
- data/lib/peatio/auth/error.rb +18 -0
- data/lib/peatio/auth/jwt_authenticator.rb +127 -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 +16 -0
- data/lib/peatio/command/security.rb +30 -0
- data/lib/peatio/command/service.rb +26 -0
- data/lib/peatio/error.rb +18 -0
- data/lib/peatio/executor.rb +64 -0
- data/lib/peatio/injectors/peatio_events.rb +209 -0
- data/lib/peatio/logger.rb +37 -0
- data/lib/peatio/mq/client.rb +30 -0
- data/lib/peatio/mq/events.rb +128 -0
- data/lib/peatio/ranger.rb +106 -0
- data/lib/peatio/security/key_generator.rb +26 -0
- data/lib/peatio/sql/client.rb +19 -0
- data/lib/peatio/sql/schema.rb +72 -0
- data/lib/peatio/version.rb +3 -0
- data/peatio1.9.gemspec +44 -0
- metadata +331 -0
@@ -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,16 @@
|
|
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
|
+
require "peatio/command/security"
|
7
|
+
|
8
|
+
module Peatio
|
9
|
+
class Root < Command::Base
|
10
|
+
subcommand "amqp", "AMQP related sub-commands", Peatio::Command::AMQP::Root
|
11
|
+
subcommand "db", "Database related sub-commands", Peatio::Command::DB::Root
|
12
|
+
subcommand "service", "Services management related sub-commands", Peatio::Command::Service::Root
|
13
|
+
subcommand "inject", "Data injectors", Peatio::Command::Inject
|
14
|
+
subcommand "security", "Security management related sub-commands", Peatio::Command::Security
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Peatio::Command
|
4
|
+
class Security < Peatio::Command::Base
|
5
|
+
class KeyGenerator < Peatio::Command::Base
|
6
|
+
option "--print", :flag, "print on screen"
|
7
|
+
option "--path", "FOLDER", "save keypair into folder", default: "secrets"
|
8
|
+
|
9
|
+
def execute
|
10
|
+
keypair = Peatio::Security::KeyGenerator.new
|
11
|
+
|
12
|
+
if print?
|
13
|
+
puts keypair.private, keypair.public
|
14
|
+
puts "-----BASE64 ENCODED-----"
|
15
|
+
puts Base64.urlsafe_encode64(keypair.public)
|
16
|
+
else
|
17
|
+
begin
|
18
|
+
keypair.save(path)
|
19
|
+
puts "Files saved in #{File.join(path, 'rsa-key')}"
|
20
|
+
|
21
|
+
rescue IOError => e
|
22
|
+
abort('Failed saving files')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
subcommand "keygen", "Generate a public private rsa key pair", KeyGenerator
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Peatio::Command::Service
|
2
|
+
class Start < Peatio::Command::Base
|
3
|
+
class Ranger < Peatio::Command::Base
|
4
|
+
def execute
|
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)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
subcommand "ranger", "Start ranger process", Ranger
|
21
|
+
end
|
22
|
+
|
23
|
+
class Root < Peatio::Command::Base
|
24
|
+
subcommand "start", "Start a service", Start
|
25
|
+
end
|
26
|
+
end
|
data/lib/peatio/error.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class Peatio::Error < ::StandardError
|
2
|
+
@@default_code = 2000
|
3
|
+
|
4
|
+
attr :code, :text
|
5
|
+
|
6
|
+
def initialize(opts = {})
|
7
|
+
@code = opts[:code] || @@default_code
|
8
|
+
@text = opts[:text] || ""
|
9
|
+
|
10
|
+
@message = {error: {code: @code, message: @text}}
|
11
|
+
|
12
|
+
if @text != ""
|
13
|
+
super("#{@code}: #{text}")
|
14
|
+
else
|
15
|
+
super("#{@code}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
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,209 @@
|
|
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
|
+
Peatio::MQ::Client.connect!
|
17
|
+
Peatio::MQ::Client.create_channel!
|
18
|
+
inject_message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def inject_message
|
23
|
+
if message = @messages.shift
|
24
|
+
type, id, event, data = message
|
25
|
+
Peatio::MQ::Events.publish(type, id, event, data) {
|
26
|
+
inject_message
|
27
|
+
}
|
28
|
+
else
|
29
|
+
Peatio::MQ::Client.disconnect { EventMachine.stop }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_messages
|
34
|
+
[
|
35
|
+
private_trade,
|
36
|
+
order_created,
|
37
|
+
order_canceled,
|
38
|
+
order_completed,
|
39
|
+
order_updated,
|
40
|
+
trade_completed,
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
def created_at
|
45
|
+
Time.now - 600
|
46
|
+
end
|
47
|
+
|
48
|
+
def updated_at
|
49
|
+
Time.now
|
50
|
+
end
|
51
|
+
|
52
|
+
alias :completed_at :updated_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
|
65
|
+
|
66
|
+
def order_created
|
67
|
+
[
|
68
|
+
"public",
|
69
|
+
market,
|
70
|
+
"order_created",
|
71
|
+
{
|
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",
|
83
|
+
initial_outcome_amount: "0.42",
|
84
|
+
current_outcome_amount: "0.42",
|
85
|
+
strategy: "limit",
|
86
|
+
price: "0.03",
|
87
|
+
state: "open",
|
88
|
+
trades_count: 0,
|
89
|
+
created_at: created_at.iso8601,
|
90
|
+
},
|
91
|
+
]
|
92
|
+
end
|
93
|
+
|
94
|
+
def order_canceled
|
95
|
+
[
|
96
|
+
"public",
|
97
|
+
market,
|
98
|
+
"order_canceled",
|
99
|
+
{
|
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
|
+
},
|
120
|
+
]
|
121
|
+
end
|
122
|
+
|
123
|
+
def order_completed
|
124
|
+
[
|
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",
|
142
|
+
previous_outcome_amount: "100.0",
|
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
|
+
},
|
150
|
+
]
|
151
|
+
end
|
152
|
+
|
153
|
+
def order_updated
|
154
|
+
[
|
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",
|
172
|
+
previous_outcome_amount: "100.0",
|
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
|
+
},
|
180
|
+
]
|
181
|
+
end
|
182
|
+
|
183
|
+
def trade_completed
|
184
|
+
[
|
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",
|
202
|
+
seller_outcome_amount: "14.0",
|
203
|
+
seller_outcome_fee: "0.0",
|
204
|
+
completed_at: completed_at.iso8601,
|
205
|
+
},
|
206
|
+
]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
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
|