peatio-jruby 2.6.2
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 +7 -0
- data/.drone.yml +29 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +148 -0
- data/.simplecov +17 -0
- data/.tool-versions +1 -0
- data/.travis.yml +18 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +198 -0
- data/README.md +47 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/peatio +12 -0
- data/bin/setup +8 -0
- data/lib/peatio.rb +52 -0
- data/lib/peatio/adapter_registry.rb +25 -0
- data/lib/peatio/auth/error.rb +18 -0
- data/lib/peatio/auth/jwt_authenticator.rb +127 -0
- data/lib/peatio/block.rb +29 -0
- data/lib/peatio/blockchain/abstract.rb +161 -0
- data/lib/peatio/blockchain/error.rb +37 -0
- data/lib/peatio/blockchain/registry.rb +16 -0
- data/lib/peatio/command/base.rb +11 -0
- data/lib/peatio/command/db.rb +20 -0
- data/lib/peatio/command/inject.rb +13 -0
- data/lib/peatio/command/root.rb +14 -0
- data/lib/peatio/command/security.rb +29 -0
- data/lib/peatio/command/service.rb +40 -0
- data/lib/peatio/error.rb +18 -0
- data/lib/peatio/executor.rb +64 -0
- data/lib/peatio/injectors/peatio_events.rb +240 -0
- data/lib/peatio/logger.rb +39 -0
- data/lib/peatio/metrics/server.rb +15 -0
- data/lib/peatio/mq/client.rb +51 -0
- data/lib/peatio/ranger/connection.rb +117 -0
- data/lib/peatio/ranger/events.rb +11 -0
- data/lib/peatio/ranger/router.rb +234 -0
- data/lib/peatio/ranger/web_socket.rb +68 -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/transaction.rb +122 -0
- data/lib/peatio/upstream/base.rb +116 -0
- data/lib/peatio/upstream/registry.rb +14 -0
- data/lib/peatio/version.rb +3 -0
- data/lib/peatio/wallet/abstract.rb +189 -0
- data/lib/peatio/wallet/error.rb +37 -0
- data/lib/peatio/wallet/registry.rb +16 -0
- data/peatio.gemspec +59 -0
- metadata +480 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
module Peatio
|
2
|
+
module Blockchain
|
3
|
+
Error = Class.new(StandardError)
|
4
|
+
|
5
|
+
class ClientError < Error
|
6
|
+
|
7
|
+
attr_reader :wrapped_ex
|
8
|
+
|
9
|
+
def initialize(ex_or_string)
|
10
|
+
@wrapped_ex = nil
|
11
|
+
|
12
|
+
if ex_or_string.respond_to?(:backtrace)
|
13
|
+
super(ex_or_string.message)
|
14
|
+
@wrapped_exception = ex_or_string
|
15
|
+
else
|
16
|
+
super(ex_or_string.to_s)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class MissingSettingError < Error
|
22
|
+
def initialize(key)
|
23
|
+
super "#{key.capitalize} setting is missing"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class UnavailableAddressBalanceError < Error
|
28
|
+
def initialize(address)
|
29
|
+
@address = address
|
30
|
+
end
|
31
|
+
|
32
|
+
def message
|
33
|
+
"Unable to load #{@address} balance"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -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,13 @@
|
|
1
|
+
module Peatio::Command
|
2
|
+
class Inject < Peatio::Command::Base
|
3
|
+
class PeatioEvents < Peatio::Command::Base
|
4
|
+
option ["-e", "--exchange"], "NAME", "exchange name to inject messages to", default: "peatio.events.ranger"
|
5
|
+
def execute
|
6
|
+
Peatio::Logger.logger.level = :debug
|
7
|
+
Peatio::Injectors::PeatioEvents.new.run!(exchange)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
subcommand "peatio_events", "Inject peatio events in mq", PeatioEvents
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "peatio/command/base"
|
2
|
+
require "peatio/command/service"
|
3
|
+
require "peatio/command/db"
|
4
|
+
require "peatio/command/inject"
|
5
|
+
require "peatio/command/security"
|
6
|
+
|
7
|
+
module Peatio
|
8
|
+
class Root < Command::Base
|
9
|
+
subcommand "db", "Database related sub-commands", Peatio::Command::DB::Root
|
10
|
+
subcommand "service", "Services management related sub-commands", Peatio::Command::Service::Root
|
11
|
+
subcommand "inject", "Data injectors", Peatio::Command::Inject
|
12
|
+
subcommand "security", "Security management related sub-commands", Peatio::Command::Security
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
rescue IOError => e
|
21
|
+
abort("Failed saving files")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
subcommand "keygen", "Generate a public private rsa key pair", KeyGenerator
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Peatio::Command::Service
|
4
|
+
class Start < Peatio::Command::Base
|
5
|
+
class Ranger < Peatio::Command::Base
|
6
|
+
option ["-e", "--exchange"], "NAME", "exchange name to inject messages to", default: "peatio.events.ranger"
|
7
|
+
option "--[no-]stats", :flag, "display periodically connections statistics", default: true
|
8
|
+
option "--stats-period", "SECONDS", "period of displaying stats in seconds", default: 30
|
9
|
+
def execute
|
10
|
+
raise ArgumentError, "JWT_PUBLIC_KEY was not specified." if ENV["JWT_PUBLIC_KEY"].to_s.empty?
|
11
|
+
|
12
|
+
key_decoded = Base64.urlsafe_decode64(ENV["JWT_PUBLIC_KEY"])
|
13
|
+
|
14
|
+
jwt_public_key = OpenSSL::PKey.read(key_decoded)
|
15
|
+
if jwt_public_key.private?
|
16
|
+
raise ArgumentError, "JWT_PUBLIC_KEY was set to private key, however it should be public."
|
17
|
+
end
|
18
|
+
|
19
|
+
raise "stats period missing" if stats? && !stats_period
|
20
|
+
|
21
|
+
Prometheus::Client.config.data_store = Prometheus::Client::DataStores::SingleThreaded.new()
|
22
|
+
registry = Prometheus::Client.registry
|
23
|
+
|
24
|
+
opts = {
|
25
|
+
display_stats: stats?,
|
26
|
+
stats_period: stats_period.to_f,
|
27
|
+
metrics_port: 8082,
|
28
|
+
registry: registry
|
29
|
+
}
|
30
|
+
::Peatio::Ranger.run!(jwt_public_key, exchange, opts)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
subcommand "ranger", "Start ranger process", Ranger
|
35
|
+
end
|
36
|
+
|
37
|
+
class Root < Peatio::Command::Base
|
38
|
+
subcommand "start", "Start a service", Start
|
39
|
+
end
|
40
|
+
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,240 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Peatio::Injectors
|
4
|
+
class PeatioEvents
|
5
|
+
attr_accessor :market, :market_name, :base_unit, :quote_unit, :seller_uid, :buyer_uid, :logger
|
6
|
+
|
7
|
+
def run!(exchange_name)
|
8
|
+
require "time"
|
9
|
+
@logger = Peatio::Logger.logger
|
10
|
+
@market = "eurusd"
|
11
|
+
@market_name = "EUR/USD"
|
12
|
+
@base_unit = "eur"
|
13
|
+
@quote_unit = "usd"
|
14
|
+
@seller_uid = 21
|
15
|
+
@buyer_uid = 42
|
16
|
+
@messages = create_messages
|
17
|
+
@opts = {
|
18
|
+
ex_name: exchange_name
|
19
|
+
}
|
20
|
+
EventMachine.run do
|
21
|
+
inject_message()
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def inject_message()
|
26
|
+
if message = @messages.shift
|
27
|
+
type, id, event, data = message
|
28
|
+
Peatio::Ranger::Events.publish(type, id, event, data, @opts)
|
29
|
+
EM.next_tick do
|
30
|
+
inject_message()
|
31
|
+
end
|
32
|
+
else
|
33
|
+
Peatio::MQ::Client.disconnect
|
34
|
+
EventMachine.stop
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_messages
|
39
|
+
[
|
40
|
+
public_tickers,
|
41
|
+
public_orderbook,
|
42
|
+
private_order,
|
43
|
+
private_trade_user1,
|
44
|
+
private_trade_user2,
|
45
|
+
public_trade,
|
46
|
+
public_orderbook_increment1,
|
47
|
+
public_orderbook_snapshot1,
|
48
|
+
public_orderbook_increment2,
|
49
|
+
public_orderbook_increment3,
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
def created_at
|
54
|
+
Time.now - 600
|
55
|
+
end
|
56
|
+
|
57
|
+
def updated_at
|
58
|
+
Time.now
|
59
|
+
end
|
60
|
+
|
61
|
+
alias completed_at updated_at
|
62
|
+
alias canceled_at updated_at
|
63
|
+
|
64
|
+
def public_orderbook
|
65
|
+
[
|
66
|
+
"public",
|
67
|
+
market,
|
68
|
+
"update",
|
69
|
+
{
|
70
|
+
"asks": [
|
71
|
+
["1020.0", "0.005"],
|
72
|
+
["1026.0", "0.03"]
|
73
|
+
],
|
74
|
+
"bids": [
|
75
|
+
["1000.0", "0.25"],
|
76
|
+
["999.0", "0.005"],
|
77
|
+
["994.0", "0.005"],
|
78
|
+
["1.0", "11.0"]
|
79
|
+
]
|
80
|
+
}
|
81
|
+
]
|
82
|
+
end
|
83
|
+
|
84
|
+
def public_orderbook_snapshot1
|
85
|
+
[
|
86
|
+
"public",
|
87
|
+
market,
|
88
|
+
"ob-snap",
|
89
|
+
{
|
90
|
+
"asks": [
|
91
|
+
["1020.0", "0.005"],
|
92
|
+
["1026.0", "0.03"]
|
93
|
+
],
|
94
|
+
"bids": [
|
95
|
+
["1000.0", "0.25"],
|
96
|
+
["999.0", "0.005"],
|
97
|
+
["994.0", "0.005"],
|
98
|
+
["1.0", "11.0"]
|
99
|
+
]
|
100
|
+
}
|
101
|
+
]
|
102
|
+
end
|
103
|
+
|
104
|
+
def public_orderbook_increment1
|
105
|
+
[
|
106
|
+
"public",
|
107
|
+
market,
|
108
|
+
"ob-inc",
|
109
|
+
{
|
110
|
+
"asks": [
|
111
|
+
["1020.0", "0.015"],
|
112
|
+
],
|
113
|
+
}
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
def public_orderbook_increment2
|
118
|
+
[
|
119
|
+
"public",
|
120
|
+
market,
|
121
|
+
"ob-inc",
|
122
|
+
{
|
123
|
+
"bids": [
|
124
|
+
["1000.0", "0"],
|
125
|
+
],
|
126
|
+
}
|
127
|
+
]
|
128
|
+
end
|
129
|
+
|
130
|
+
def public_orderbook_increment3
|
131
|
+
[
|
132
|
+
"public",
|
133
|
+
market,
|
134
|
+
"ob-inc",
|
135
|
+
{
|
136
|
+
"bids": [
|
137
|
+
["999.0", "0.001"],
|
138
|
+
],
|
139
|
+
}
|
140
|
+
]
|
141
|
+
end
|
142
|
+
|
143
|
+
def public_tickers
|
144
|
+
[
|
145
|
+
"public",
|
146
|
+
"global",
|
147
|
+
"tickers",
|
148
|
+
{
|
149
|
+
market => {
|
150
|
+
"name": market_name,
|
151
|
+
"base_unit": base_unit,
|
152
|
+
"quote_unit": quote_unit,
|
153
|
+
"low": "1000.0",
|
154
|
+
"high": "10000.0",
|
155
|
+
"last": "1000.0",
|
156
|
+
"open": 1000.0,
|
157
|
+
"volume": "0.0",
|
158
|
+
"sell": "1020.0",
|
159
|
+
"buy": "1000.0",
|
160
|
+
"at": Time.now.to_i
|
161
|
+
}
|
162
|
+
}
|
163
|
+
]
|
164
|
+
end
|
165
|
+
|
166
|
+
def private_order
|
167
|
+
[
|
168
|
+
"private",
|
169
|
+
"IDABC0000001",
|
170
|
+
"order",
|
171
|
+
{
|
172
|
+
"id": 22,
|
173
|
+
"at": created_at.to_i,
|
174
|
+
"market": market,
|
175
|
+
"kind": "bid",
|
176
|
+
"price": "1026.0",
|
177
|
+
"state": "wait",
|
178
|
+
"volume": "0.001",
|
179
|
+
"origin_volume": "0.001"
|
180
|
+
}
|
181
|
+
]
|
182
|
+
end
|
183
|
+
|
184
|
+
def private_trade_user1
|
185
|
+
[
|
186
|
+
"private",
|
187
|
+
"IDABC0000001",
|
188
|
+
"trade",
|
189
|
+
{
|
190
|
+
"id": 7,
|
191
|
+
"kind": "ask",
|
192
|
+
"at": created_at.to_i,
|
193
|
+
"price": "1020.0",
|
194
|
+
"volume": "0.001",
|
195
|
+
"ask_id": 15,
|
196
|
+
"bid_id": 22,
|
197
|
+
"market": market
|
198
|
+
}
|
199
|
+
]
|
200
|
+
end
|
201
|
+
|
202
|
+
def private_trade_user2
|
203
|
+
[
|
204
|
+
"private",
|
205
|
+
"IDABC0000002",
|
206
|
+
"trade",
|
207
|
+
{
|
208
|
+
"id": 7,
|
209
|
+
"kind": "bid",
|
210
|
+
"at": created_at.to_i,
|
211
|
+
"price": "1020.0",
|
212
|
+
"volume": "0.001",
|
213
|
+
"ask_id": 15,
|
214
|
+
"bid_id": 22,
|
215
|
+
"market": market
|
216
|
+
}
|
217
|
+
]
|
218
|
+
end
|
219
|
+
|
220
|
+
def public_trade
|
221
|
+
[
|
222
|
+
"public",
|
223
|
+
market,
|
224
|
+
"trades",
|
225
|
+
{
|
226
|
+
"trades": [
|
227
|
+
{
|
228
|
+
"tid": 7,
|
229
|
+
"taker_type": "buy",
|
230
|
+
"date": created_at.to_i,
|
231
|
+
"price": "1020.0",
|
232
|
+
"amount":
|
233
|
+
"0.001"
|
234
|
+
}
|
235
|
+
]
|
236
|
+
}
|
237
|
+
]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|