Initial commit
This commit is contained in:
9
lib/tasks/accounts.rake
Normal file
9
lib/tasks/accounts.rake
Normal file
@@ -0,0 +1,9 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :accounts do
|
||||
desc 'Create missing accounts for existing members.'
|
||||
task touch: :environment do
|
||||
Member.find_each(&:touch_accounts)
|
||||
end
|
||||
end
|
||||
67
lib/tasks/api_becnhmark.rake
Normal file
67
lib/tasks/api_becnhmark.rake
Normal file
@@ -0,0 +1,67 @@
|
||||
require 'faraday'
|
||||
require 'thread/pool'
|
||||
require 'progress_bar'
|
||||
require "#{Rails.root}/lib/api_bench.rb"
|
||||
|
||||
yml_data = YAML.load_file("#{Rails.root}/config/bench/api_bench.yml")
|
||||
namespace :api_benchmark do
|
||||
desc 'create random request for order creation and do trading'
|
||||
task :random_fire do
|
||||
bar = ProgressBar.new(yml_data.dig('order_count'), :percentage, :bar, :elapsed, :eta, :rate)
|
||||
|
||||
pool = Thread.pool(5)
|
||||
creator = ApiBench.new
|
||||
start_time = Time.now
|
||||
yml_data.dig('order_count').times do |_i|
|
||||
pool.process do
|
||||
price = rand(1000..1500)
|
||||
side = price.odd? ? 'sell' : 'buy'
|
||||
creator.create_order(yml_data.dig('base_url'),
|
||||
'btcusd',
|
||||
side,
|
||||
rand.round(2),
|
||||
yml_data.dig('server_token'),
|
||||
'limit',
|
||||
price)
|
||||
bar.increment!
|
||||
end
|
||||
end
|
||||
pool.shutdown
|
||||
puts 'elapsed_time:'
|
||||
puts Time.now - start_time
|
||||
end
|
||||
|
||||
|
||||
desc 'create one big sell request for support a lot of small buy order for trading'
|
||||
task :direct_fire do
|
||||
bar = ProgressBar.new(yml_data.dig('order_count'), :percentage, :bar, :elapsed, :eta, :rate)
|
||||
|
||||
pool = Thread.pool(5)
|
||||
creator = ApiBench.new
|
||||
creator.create_order(yml_data.dig('base_url'),
|
||||
'btcusd',
|
||||
'sell',
|
||||
yml_data.dig('order_count'),
|
||||
yml_data.dig('server_token'),
|
||||
'limit',
|
||||
1000)
|
||||
# sleep(1)
|
||||
start_time = Time.now
|
||||
yml_data.dig('order_count').times do |_i|
|
||||
pool.process do
|
||||
price = rand(1001..1500)
|
||||
creator.create_order(yml_data.dig('base_url'),
|
||||
'btcusd',
|
||||
'buy',
|
||||
1,
|
||||
yml_data.dig('server_token'),
|
||||
'limit',
|
||||
price)
|
||||
bar.increment!
|
||||
end
|
||||
end
|
||||
pool.shutdown
|
||||
puts 'elapsed_time:'
|
||||
puts Time.now - start_time
|
||||
end
|
||||
end
|
||||
54
lib/tasks/auto_annotate_models.rake
Normal file
54
lib/tasks/auto_annotate_models.rake
Normal file
@@ -0,0 +1,54 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
# NOTE: only doing this in development as some production environments (Heroku)
|
||||
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
|
||||
# NOTE: to have a dev-mode tool do its thing in production.
|
||||
if Rails.env.development? && defined?(Annotate)
|
||||
task :set_annotation_options do
|
||||
# You can override any of these by setting an environment variable of the
|
||||
# same name.
|
||||
Annotate.set_defaults \
|
||||
'routes' => 'false',
|
||||
'position_in_routes' => 'before',
|
||||
'position_in_class' => 'after',
|
||||
'position_in_test' => 'before',
|
||||
'position_in_fixture' => 'before',
|
||||
'position_in_factory' => 'before',
|
||||
'position_in_serializer' => 'before',
|
||||
'show_foreign_keys' => 'true',
|
||||
'show_complete_foreign_keys' => 'true',
|
||||
'show_indexes' => 'true',
|
||||
'simple_indexes' => 'false',
|
||||
'model_dir' => 'app/models',
|
||||
'root_dir' => '',
|
||||
'include_version' => 'true',
|
||||
'require' => '',
|
||||
'exclude_tests' => 'true',
|
||||
'exclude_fixtures' => 'true',
|
||||
'exclude_factories' => 'true',
|
||||
'exclude_serializers' => 'true',
|
||||
'exclude_scaffolds' => 'true',
|
||||
'exclude_controllers' => 'true',
|
||||
'exclude_helpers' => 'true',
|
||||
'exclude_sti_subclasses' => 'false',
|
||||
'ignore_model_sub_dir' => 'false',
|
||||
'ignore_columns' => nil,
|
||||
'ignore_routes' => nil,
|
||||
'ignore_unknown_models' => 'false',
|
||||
'hide_limit_column_types' => '',
|
||||
'hide_default_column_types' => '',
|
||||
'skip_on_db_migrate' => 'false',
|
||||
'format_bare' => 'true',
|
||||
'format_rdoc' => 'false',
|
||||
'format_markdown' => 'false',
|
||||
'sort' => 'false',
|
||||
'force' => 'false',
|
||||
'trace' => 'false',
|
||||
'wrapper_open' => nil,
|
||||
'wrapper_close' => nil,
|
||||
'with_comment' => true
|
||||
end
|
||||
|
||||
Annotate.load_tasks
|
||||
end
|
||||
32
lib/tasks/barong.rake
Normal file
32
lib/tasks/barong.rake
Normal file
@@ -0,0 +1,32 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :barong do
|
||||
desc 'Refresh access level for Barong members.'
|
||||
task levels: :environment do
|
||||
url = "https://#{ENV.fetch('BARONG_DOMAIN')}/api/account"
|
||||
t = Authentication.arel_table
|
||||
Authentication
|
||||
.where(provider: :barong)
|
||||
.where(t[:token].is_not_blank)
|
||||
.where(t[:member_id].is_not_blank)
|
||||
.includes(:member)
|
||||
.order(updated_at: :asc)
|
||||
.limit(1000)
|
||||
.each do |auth|
|
||||
next if auth.token.blank? || auth.member.blank?
|
||||
|
||||
profile = JSON.parse(Faraday.get(url, nil, 'Authorization' => "Bearer #{auth.token}").assert_success!.body)
|
||||
current_level = auth.member.level
|
||||
new_level = profile.fetch('level')
|
||||
|
||||
unless current_level == new_level
|
||||
auth.member.update!(level: new_level)
|
||||
auth.touch
|
||||
Rails.logger.info { "#{auth.member.email}: #{current_level} >> #{new_level}." }
|
||||
end
|
||||
rescue => e
|
||||
report_exception(e)
|
||||
end
|
||||
end
|
||||
end
|
||||
140
lib/tasks/bench.rake
Normal file
140
lib/tasks/bench.rake
Normal file
@@ -0,0 +1,140 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# TODO: Add descriptions.
|
||||
# TODO: Don't sleep in case of last bench.
|
||||
# TODO: Remove legacy benchmarks.
|
||||
namespace :bench do
|
||||
|
||||
namespace :matching do
|
||||
|
||||
desc 'Matching with amqp messages'
|
||||
task :amqp, [:config_load_path] => [:environment] do |_t, args|
|
||||
args.with_defaults(:config_load_path => 'config/bench/matching.yml')
|
||||
|
||||
benches =
|
||||
YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
.map(&:deep_symbolize_keys)
|
||||
.each_with_object([]) do |config, memo|
|
||||
Kernel.pp config
|
||||
|
||||
matching = Bench::Matching::AMQP.new(config)
|
||||
matching.run!
|
||||
memo << matching
|
||||
matching.save_report
|
||||
Kernel.puts "Sleep before next bench"
|
||||
sleep 5
|
||||
end
|
||||
|
||||
benches.each {|b| Kernel.pp b.result}
|
||||
end
|
||||
|
||||
desc 'Matching without amqp messages'
|
||||
task :direct, [:config_load_path] => [:environment] do |_t, args|
|
||||
args.with_defaults(:config_load_path => 'config/bench/matching.yml')
|
||||
|
||||
benches =
|
||||
YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
.map(&:deep_symbolize_keys)
|
||||
.each_with_object([]) do |config, memo|
|
||||
Kernel.pp config
|
||||
|
||||
matching = Bench::Matching::Direct.new(config)
|
||||
matching.run!
|
||||
memo << matching
|
||||
matching.save_report
|
||||
Kernel.puts "Sleep before next bench"
|
||||
sleep 5
|
||||
end
|
||||
|
||||
benches.each {|b| Kernel.pp b.result}
|
||||
end
|
||||
end
|
||||
|
||||
namespace :trade_execution do
|
||||
|
||||
desc 'Trade Execution with amqp messages'
|
||||
task :amqp, [:config_load_path] => [:environment] do |_t, args|
|
||||
args.with_defaults(:config_load_path => 'config/bench/trade_execution.yml')
|
||||
benches =
|
||||
YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
.map(&:deep_symbolize_keys)
|
||||
.each_with_object([]) do |config, memo|
|
||||
Kernel.pp config
|
||||
trade_execution = ::Bench::TradeExecution::AMQP.new(config)
|
||||
trade_execution.run!
|
||||
memo << trade_execution
|
||||
trade_execution.save_report
|
||||
Kernel.puts "Sleep before next bench"
|
||||
sleep 5
|
||||
end
|
||||
|
||||
benches.each {|b| Kernel.pp b.result}
|
||||
end
|
||||
|
||||
desc 'Trade execution without amqp messages'
|
||||
task :direct, [:config_load_path] => [:environment] do |_t, args|
|
||||
args.with_defaults(:config_load_path => 'config/bench/trade_execution.yml')
|
||||
|
||||
benches =
|
||||
YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
.map(&:deep_symbolize_keys)
|
||||
.each_with_object([]) do |config, memo|
|
||||
Kernel.pp config
|
||||
|
||||
trade_execution = ::Bench::TradeExecution::Direct.new(config)
|
||||
trade_execution.run!
|
||||
memo << trade_execution
|
||||
trade_execution.save_report
|
||||
Kernel.puts "Sleep before next bench"
|
||||
sleep 5
|
||||
end
|
||||
|
||||
benches.each {|b| Kernel.pp b.result}
|
||||
end
|
||||
end
|
||||
|
||||
namespace :order_processing do
|
||||
|
||||
desc 'Order Processing with amqp messages'
|
||||
task :amqp, [:config_load_path] => [:environment] do |_t, args|
|
||||
args.with_defaults(:config_load_path => 'config/bench/order_processing.yml')
|
||||
|
||||
benches =
|
||||
YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
.map(&:deep_symbolize_keys)
|
||||
.each_with_object([]) do |config, memo|
|
||||
Kernel.pp config
|
||||
|
||||
order_processing = ::Bench::OrderProcessing::AMQP.new(config)
|
||||
order_processing.run!
|
||||
memo << order_processing
|
||||
order_processing.save_report
|
||||
Kernel.puts "Sleep before next bench"
|
||||
sleep 5
|
||||
end
|
||||
|
||||
benches.each {|b| Kernel.pp b.result}
|
||||
end
|
||||
|
||||
desc 'Order Processing without amqp messages'
|
||||
task :direct, [:config_load_path] => [:environment] do |_t, args|
|
||||
args.with_defaults(:config_load_path => 'config/bench/order_processing.yml')
|
||||
|
||||
benches =
|
||||
YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
.map(&:deep_symbolize_keys)
|
||||
.each_with_object([]) do |config, memo|
|
||||
Kernel.pp config
|
||||
|
||||
order_processing = Bench::OrderProcessing::Direct.new(config)
|
||||
order_processing.run!
|
||||
memo << order_processing
|
||||
order_processing.save_report
|
||||
Kernel.puts "Sleep before next bench"
|
||||
sleep 5
|
||||
end
|
||||
|
||||
benches.each { |b| Kernel.pp b.result }
|
||||
end
|
||||
end
|
||||
end
|
||||
72
lib/tasks/benchmark.rake
Normal file
72
lib/tasks/benchmark.rake
Normal file
@@ -0,0 +1,72 @@
|
||||
namespace :benchmark do
|
||||
|
||||
desc "In memory matching engine benchmark"
|
||||
task :matching => %w(environment) do
|
||||
max_round = round(2)
|
||||
puts "\n>> Setup environment (num=#{num} round=#{max_round})"
|
||||
Dir[Rails.root.join('tmp', 'matching_result_*')].each {|f| FileUtils.rm(f) }
|
||||
|
||||
Benchmark::Matching.new(label, num, max_round).run
|
||||
end
|
||||
|
||||
desc "Trade execution benchmark"
|
||||
task :execution => %w(environment) do
|
||||
max_round = round(2)
|
||||
puts "\n>> Setup environment (executor=#{executor} num=#{num} round=#{max_round})"
|
||||
Dir[Rails.root.join('tmp', 'matching_result_*')].each {|f| FileUtils.rm(f) }
|
||||
|
||||
Benchmark::Execution.new(label, num, max_round, executor).run
|
||||
end
|
||||
|
||||
desc "Run integration benchmark"
|
||||
task :integration => %w(environment) do
|
||||
puts "Integration Benchmark (num: #{num(400)})\n"
|
||||
|
||||
Benchmark::Integration.new(num).run
|
||||
end
|
||||
|
||||
desc "Profiling"
|
||||
task :profiling, [:type]=> %w(environment) do |task, args|
|
||||
|
||||
case args[:type]
|
||||
|
||||
when 'matching'
|
||||
puts "\n>> Setup environment (num=#{num} round=#{round})"
|
||||
Dir[Rails.root.join('tmp', 'profiling_matching_result_*')].each {|f| FileUtils.rm(f) }
|
||||
file_path = Rails.root.join('tmp', "profiling_matching_result_#{Time.now.to_i}")
|
||||
|
||||
File.open(file_path, 'w') { |file| file.puts "\n>> Setup environment (num=#{num} round=#{round})" }
|
||||
|
||||
Benchmark::Profiling.matching(label, num, round, file_path)
|
||||
|
||||
when 'execution'
|
||||
puts "\n>> Setup environment (executor=#{executor} num=#{num} round=#{round})"
|
||||
Dir[Rails.root.join('tmp', 'profiling_execution_result_*')].each {|f| FileUtils.rm(f) }
|
||||
|
||||
file_path = Rails.root.join('tmp', "profiling_execution_result_#{Time.now.to_i}")
|
||||
File.open(file_path, 'w') { |file| file.puts "\n>> Setup environment (executor=#{executor} num=#{num} round=#{round})" }
|
||||
|
||||
Benchmark::Profiling.execution(label, num, round, executor, file_path)
|
||||
|
||||
else
|
||||
puts "\n>> Wrong parameter!"
|
||||
end
|
||||
end
|
||||
|
||||
def num
|
||||
ENV['NUM'] ? ENV['NUM'].to_i : 100
|
||||
end
|
||||
|
||||
def round r = 1
|
||||
ENV['ROUND'] ? ENV['ROUND'].to_i : r
|
||||
end
|
||||
|
||||
def label
|
||||
ENV['LABEL'] || Time.now.to_i
|
||||
end
|
||||
|
||||
def executor
|
||||
ENV['EXECUTOR'] ? ENV['EXECUTOR'].to_i : 6
|
||||
end
|
||||
end
|
||||
|
||||
12
lib/tasks/billoner_members.rake
Normal file
12
lib/tasks/billoner_members.rake
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace :billionaire do
|
||||
desc 'make your memberes billionaires'
|
||||
task :by_email, %i[market members] => [:environment] do |_t, args|
|
||||
include ::Bench::Helpers
|
||||
memberes_array = args[:members].split(' ')
|
||||
memberes = ::Member.where(email: memberes_array)
|
||||
raise 'members if empty' if memberes.empty? || args[:members].blank?
|
||||
|
||||
@currencies = ::Currency.where(id: args[:market].split('-').map(&:squish).reject(&:blank?))
|
||||
memberes.map(&method(:become_billionaire))
|
||||
end
|
||||
end
|
||||
11
lib/tasks/bitgo_webhooks.rake
Normal file
11
lib/tasks/bitgo_webhooks.rake
Normal file
@@ -0,0 +1,11 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :bitgo do
|
||||
desc 'Add a webhook that will result in an HTTP callback at the specified URL from BitGo when events are triggered.'
|
||||
task :webhooks, [:url] => [:environment] do
|
||||
Wallet.deposit.active.where(gateway: :bitgo).each do |w|
|
||||
w.service.register_webhooks!(args[:url])
|
||||
end
|
||||
end
|
||||
end
|
||||
11
lib/tasks/clear.rake
Normal file
11
lib/tasks/clear.rake
Normal file
@@ -0,0 +1,11 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :clear do
|
||||
desc 'Clear database from accounting information.'
|
||||
task accounting: :environment do
|
||||
table_names = %w[accounts adjustments assets beneficiaries deposits expenses
|
||||
liabilities orders payment_addresses revenues trades transfers triggers withdraws]
|
||||
table_names.each { |name| ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{name}") }
|
||||
end
|
||||
end
|
||||
42
lib/tasks/create_user_barong.rake
Normal file
42
lib/tasks/create_user_barong.rake
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace :bench do
|
||||
namespace :barong_session do
|
||||
desc 'create user and create barong session'
|
||||
|
||||
task :create => [:environment] do
|
||||
members = Bench::Barong_session::Sessions.new(trader: 10)
|
||||
members.run!
|
||||
end
|
||||
|
||||
task :session_create => [:environment] do
|
||||
config = YAML.load_file("#{Rails.root}/config/application.yml")
|
||||
session_file = "#{Rails.root}/public/sessions.csv"
|
||||
file = "#{Rails.root}/public/user_data.csv"
|
||||
result = []
|
||||
CSV.foreach(file) do |row|
|
||||
Kernel.pp row[0]
|
||||
url = "#{config["development"]["LOG_IN_URL"]}"
|
||||
url_balance = "#{config["development"]["BALANCE_URL"]}"
|
||||
resp = Faraday.post(url) do |req|
|
||||
req.params['email'] = row[0]
|
||||
req.params['password'] = "#{config["development"]["SIGN_UP_PASSWORD"]}"
|
||||
Kernel.puts "#{req.params["email"]} tried to log in"
|
||||
end
|
||||
balance = Faraday.get(url_balance) do |req|
|
||||
req.headers['Cookie'] = resp.headers["set-cookie"].split(';')[0]
|
||||
end
|
||||
Kernel.pp balance.body
|
||||
result << resp.headers["set-cookie"].split(';')[0]
|
||||
|
||||
end
|
||||
CSV.open(session_file, 'w+', write_headers: true) do |csv|
|
||||
result.each do |res|
|
||||
csv << [res]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
42
lib/tasks/distribution.rake
Normal file
42
lib/tasks/distribution.rake
Normal file
@@ -0,0 +1,42 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'csv'
|
||||
|
||||
namespace :distribution do
|
||||
# Detailed instruction https://github.com/rubykube/peatio/blob/master/docs/tasks/distribution.md
|
||||
# Required fields for distribution:
|
||||
# - uid
|
||||
# - currency_id
|
||||
# - amount
|
||||
#
|
||||
# Usage:
|
||||
# For distribution process: -> bundle exec rake distribution:process['file_name.csv']
|
||||
|
||||
desc 'Distribution process'
|
||||
task :process, [:config_load_path] => [:environment] do |_, args|
|
||||
csv_table = File.read(Rails.root.join(args[:config_load_path]))
|
||||
count = 0
|
||||
errors_count = 0
|
||||
CSV.parse(csv_table, headers: true, quote_empty: false).each do |row|
|
||||
row = row.to_h.compact.symbolize_keys!
|
||||
uid = row[:uid]
|
||||
currency_id = row[:currency_id]
|
||||
amount = row[:amount].to_d
|
||||
member = Member.find_by_uid!(uid)
|
||||
currency = Currency.find(currency_id)
|
||||
account = member.get_account(currency)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
Operations::Asset.credit!(currency: currency, amount: amount, reference_type: 'Distribution')
|
||||
Operations::Liability.credit!(kind: :main, currency: currency, member_id: member.id, amount: amount, reference_type: 'Distribution')
|
||||
account.update!(balance: account.balance + amount)
|
||||
end
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, uid: row[:uid] }
|
||||
::Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
Kernel.puts "Distributions processed #{count}"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
end
|
||||
138
lib/tasks/export.rake
Normal file
138
lib/tasks/export.rake
Normal file
@@ -0,0 +1,138 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'yaml'
|
||||
require 'csv'
|
||||
require 'peatio/export'
|
||||
|
||||
namespace :export do
|
||||
desc 'Export all configs to yaml files.'
|
||||
task configs: :environment do
|
||||
Rake::Task['export:blockchains'].invoke
|
||||
Rake::Task['export:currencies'].invoke
|
||||
Rake::Task['export:markets'].invoke
|
||||
Rake::Task['export:wallets'].invoke
|
||||
Rake::Task['export:engines'].invoke
|
||||
Rake::Task['export:trading_fees'].invoke
|
||||
end
|
||||
|
||||
desc 'Export blockchains config to yaml file.'
|
||||
task :blockchains, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'config/seed/blockchains.yml')
|
||||
File.write(args.export_path, Peatio::Export.new.export_blockchains.to_yaml)
|
||||
end
|
||||
|
||||
desc 'Export currencies config to yaml file.'
|
||||
task :currencies, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'config/seed/currencies_backup.yml')
|
||||
File.write(args.export_path, Peatio::Export.new.export_currencies.to_yaml)
|
||||
end
|
||||
|
||||
desc 'Export markets config to yaml file.'
|
||||
task :markets, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'config/seed/markets_backup.yml')
|
||||
File.write(args.export_path, Peatio::Export.new.export_markets.to_yaml)
|
||||
end
|
||||
|
||||
desc 'Export wallets config to yaml file.'
|
||||
task :wallets, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'config/seed/wallets_backup.yml')
|
||||
File.write(args.export_path, Peatio::Export.new.export_wallets.to_yaml)
|
||||
end
|
||||
|
||||
desc 'Export trading fees config to yaml file.'
|
||||
task :trading_fees, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'config/seed/trading_fees_backup.yml')
|
||||
File.write(args.export_path, Peatio::Export.new.export_trading_fees.to_yaml)
|
||||
end
|
||||
|
||||
desc 'Export engines to yaml file.'
|
||||
task :engines, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'config/seed/engines_backup.yml')
|
||||
File.write(args.export_path, Peatio::Export.new.export_engines.to_yaml)
|
||||
end
|
||||
|
||||
desc 'Export all members to csv file.'
|
||||
task :users, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'exported_users.csv')
|
||||
count = 0
|
||||
errors_count = 0
|
||||
begin
|
||||
CSV.open(args.export_path, 'w') do |csv|
|
||||
csv << %w[uid email level role state]
|
||||
Member.find_each do |member|
|
||||
csv << [member.uid, member.email, member.level, member.role, member.state]
|
||||
count += 1
|
||||
end
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, email: member.email, uid: member.uid }
|
||||
::Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
end
|
||||
Kernel.puts "Exported #{count} members"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
desc 'Export accounts to csv file.'
|
||||
task :accounts, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'exported_accounts.csv')
|
||||
count = 0
|
||||
errors_count = 0
|
||||
begin
|
||||
CSV.open(args.export_path, 'w') do |csv|
|
||||
csv << %w[uid currency_id main_balance locked_balance]
|
||||
Account.find_each do |account|
|
||||
if account.balance.positive? || account.locked.positive?
|
||||
csv << [account.member.uid, account.currency_id, account.balance, account.locked]
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, uid: account.member.uid, currency_id: account.currency_id }
|
||||
::Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
end
|
||||
Kernel.puts "Exported #{count} accounts"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
desc 'Export addresses to csv file.'
|
||||
task :addresses, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'exported_addresses.csv')
|
||||
count = 0
|
||||
errors_count = 0
|
||||
begin
|
||||
CSV.open(args.export_path, 'w') do |csv|
|
||||
csv << %w[uid wallet_name address secret details]
|
||||
PaymentAddress.find_each do |address|
|
||||
wallet = Wallet.find(address.wallet_id)
|
||||
# We save wallet name instead of id because id can change after export/import migration
|
||||
csv << [address.member.uid, wallet.name, address.address, address.secret, address.details]
|
||||
count += 1
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, uid: address.member.uid, wallet_name: address.wallet.name }
|
||||
::Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
Kernel.puts "Exported #{count} addresses"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
desc 'Export configs(blockchains, currencies, wallets, markets, engines) from the database'
|
||||
task :configs, [:export_path] => [:environment] do |_, args|
|
||||
args.with_defaults(export_path: 'export_configs.yaml')
|
||||
ex = Peatio::Export.new
|
||||
File.write(args.export_path, {
|
||||
'accounts' => ex.export_accounts,
|
||||
'blockchains' => ex.export_blockchains,
|
||||
'currencies' => ex.export_currencies,
|
||||
'markets' => ex.export_markets,
|
||||
'wallets' => ex.export_wallets,
|
||||
'trading_fees' => ex.export_trading_fees,
|
||||
'engines' => ex.export_engines
|
||||
}.to_yaml)
|
||||
end
|
||||
end
|
||||
37
lib/tasks/failures.rake
Normal file
37
lib/tasks/failures.rake
Normal file
@@ -0,0 +1,37 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :failures do
|
||||
desc 'Fetch Trade Execution Errors'
|
||||
task trade_errors: :environment do
|
||||
|
||||
conn = Bunny.new AMQP::Config.connect
|
||||
conn.start
|
||||
|
||||
ch = conn.create_channel
|
||||
|
||||
q = ch.queue("peatio.trades.errors")
|
||||
puts "****** Fetching Queue Messages ******"
|
||||
count = q.message_count
|
||||
puts "****** Total Messages in queue = #{count} ******"
|
||||
errors = []
|
||||
until count == 0
|
||||
_delivery_info, _metadata, payload = q.pop
|
||||
payload = JSON.parse(payload).symbolize_keys!
|
||||
err_obj = payload.slice(:code, :message)
|
||||
if err = errors.find{|k| k[:code] == err_obj.fetch(:code)}
|
||||
err[:count] += 1
|
||||
else
|
||||
errors << {code: err_obj.fetch(:code), count: 1 }
|
||||
end
|
||||
count -= 1
|
||||
end
|
||||
|
||||
errors.each do |error|
|
||||
puts "****** Error Code: #{error[:code]} Count = #{error[:count]} ******"
|
||||
end
|
||||
puts "****** purging queue *******"
|
||||
q.purge
|
||||
|
||||
end
|
||||
end
|
||||
26
lib/tasks/fetch.rake
Normal file
26
lib/tasks/fetch.rake
Normal file
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :fetch do
|
||||
desc 'Fetch currency price'
|
||||
task :price, %i[quote external_currencies_service] => [:environment] do |_, args|
|
||||
# TODO
|
||||
# Add ability to take price from platform market
|
||||
Currency.find_in_batches(batch_size: 50) do |group|
|
||||
group.each do |record|
|
||||
url = args.external_currencies_service || ENV['EXTERNAL_CURRENCIES_SERVICE']
|
||||
raise 'There is no external currencies service configured' unless url.present?
|
||||
|
||||
# API call to external currencies service to get current currency price
|
||||
response = Faraday.get(url, { code: record.code, quote: args.quote })
|
||||
response_body = JSON.parse(response.body)
|
||||
|
||||
next unless response_body['current_price'].present?
|
||||
|
||||
::Rails.logger.info { "Updating currency #{record.code} with price #{response_body["current_price"]}" }
|
||||
record.update!(price: response_body['current_price'])
|
||||
rescue Faraday::Error, StandardError => e
|
||||
::Rails.logger.error e.inspect
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
196
lib/tasks/import.rake
Normal file
196
lib/tasks/import.rake
Normal file
@@ -0,0 +1,196 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'csv'
|
||||
require 'peatio/import'
|
||||
|
||||
namespace :import do
|
||||
# Detailed instruction https://github.com/rubykube/peatio/blob/master/docs/tasks/import.md
|
||||
# Required fields for import users:
|
||||
# - uid
|
||||
# - email
|
||||
#
|
||||
# Usage:
|
||||
# For import users: -> bundle exec rake import:users['file_name.csv']
|
||||
|
||||
desc 'Load members from csv file.'
|
||||
task :users, [:config_load_path] => [:environment] do |_, args|
|
||||
csv_table = File.read(Rails.root.join(args[:config_load_path]))
|
||||
count = 0
|
||||
errors_count = 0
|
||||
CSV.parse(csv_table, headers: true, quote_empty: false).each do |row|
|
||||
row = row.to_h.compact.symbolize_keys!
|
||||
defaults = { level: 0, role: 'member', state: 'active' }
|
||||
permitted_attr = %i[uid email level role state]
|
||||
Member.create!(row.slice(*permitted_attr).reverse_merge(defaults))
|
||||
count += 1
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, email: row[:email], uid: row[:uid] }
|
||||
Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
Kernel.puts "Created #{count} members"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
# Required fields for import accounts balances:
|
||||
# - uid
|
||||
# - currency_id
|
||||
#
|
||||
# Make sure that you create required currency
|
||||
# Usage:
|
||||
# For import account balances: -> bundle exec rake import:accounts['file_name.csv']
|
||||
|
||||
desc 'Load accounts balances from csv file.'
|
||||
task :accounts, %i[config_load_path balance_check] => [:environment] do |_, args|
|
||||
args.with_defaults(:config_load_path => 'exported_accounts.csv', :balance_check => false)
|
||||
csv_table = File.read(Rails.root.join(args[:config_load_path]))
|
||||
count = 0
|
||||
errors_count = 0
|
||||
CSV.parse(csv_table, headers: true).each do |row|
|
||||
row = row.to_h.compact.symbolize_keys!
|
||||
uid = row[:uid]
|
||||
member = Member.find_by_uid!(uid)
|
||||
currency = Currency.find(row[:currency_id])
|
||||
account = Account.find_or_create_by!(member: member, currency: currency)
|
||||
main_balance = row[:main_balance].to_d
|
||||
locked_balance = row[:locked_balance].to_d
|
||||
next if args[:balance_check] == 'true' && main_balance <= 0 && locked_balance <= 0
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
Operations::Asset.credit!(currency: currency, amount: main_balance + locked_balance)
|
||||
Operations::Liability.credit!(kind: :main, currency: currency, member_id: member.id, amount: main_balance)
|
||||
Operations::Liability.credit!(kind: :locked, currency: currency, member_id: member.id, amount: locked_balance)
|
||||
account.update!(balance: main_balance, locked: locked_balance)
|
||||
count += 1
|
||||
end
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, uid: row[:uid] }
|
||||
Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
Kernel.puts "Accounts created #{count}"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
desc 'Load addresses from csv file. Export file from Peatio version >= 2.6.0'
|
||||
task :addresses, [:config_load_path] => [:environment] do |_, args|
|
||||
args.with_defaults(:config_load_path => 'exported_addresses.csv')
|
||||
csv_table = File.read(Rails.root.join(args[:config_load_path]))
|
||||
count = 0
|
||||
errors_count = 0
|
||||
CSV.parse(csv_table, headers: true).each do |row|
|
||||
row = row.to_h.compact.symbolize_keys!
|
||||
uid = row[:uid]
|
||||
member = Member.find_by_uid!(uid)
|
||||
wallet = Wallet.find_by(name: row[:wallet_name])
|
||||
PaymentAddress.create(member_id: member.id, wallet_id: wallet.id, address: row[:address], secret: row[:secret], details: row[:details])
|
||||
count += 1
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, uid: row[:uid], currency_id: currency_id[:currency_id] }
|
||||
Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
Kernel.puts "Addresses created #{count}"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
desc 'Load addresses from csv file. Export file from Peatio version < 2.6.0'
|
||||
task :addresses_legacy, [:config_load_path] => [:environment] do |_, args|
|
||||
args.with_defaults(:config_load_path => 'exported_addresses.csv')
|
||||
csv_table = File.read(Rails.root.join(args[:config_load_path]))
|
||||
count = 0
|
||||
errors_count = 0
|
||||
CSV.parse(csv_table, headers: true).each do |row|
|
||||
row = row.to_h.compact.symbolize_keys!
|
||||
uid = row[:uid]
|
||||
member = Member.find_by_uid!(uid)
|
||||
wallet = Wallet.deposit_wallet(row[:currency_id])
|
||||
PaymentAddress.create(member_id: member.id, wallet_id: wallet.id, address: row[:address], secret: row[:secret], details: row[:details])
|
||||
count += 1
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, uid: row[:uid], currency_id: currency_id[:currency_id] }
|
||||
Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
Kernel.puts "Addresses created #{count}"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
desc 'Load whitelisted smart contracts from CSV'
|
||||
task :whitelisted_smart_contracts, [:config_load_path] => [:environment] do |_, args|
|
||||
args.with_defaults(:config_load_path => 'exported_whitelisted_smart_contracts.csv')
|
||||
csv_table = File.read(Rails.root.join(args[:config_load_path]))
|
||||
count = 0
|
||||
errors_count = 0
|
||||
CSV.parse(csv_table, headers: true, quote_empty: false).each do |row|
|
||||
row = row.to_h.compact.symbolize_keys!
|
||||
address = row[:address]
|
||||
blockchain_key = row[:blockchain_key]
|
||||
description = row[:description]
|
||||
next if address.blank? || blockchain_key.blank? || ::Blockchain.pluck(:key).exclude?(blockchain_key)
|
||||
|
||||
::WhitelistedSmartContract.create!(description: description, address: address,
|
||||
blockchain_key: blockchain_key, state: 'active')
|
||||
count += 1
|
||||
rescue StandardError => e
|
||||
message = { error: e.message, uid: row[:uid], currency_id: currency_id[:currency_id] }
|
||||
Rails.logger.error message
|
||||
errors_count += 1
|
||||
end
|
||||
Kernel.puts "whitelisted contracts created #{count}"
|
||||
Kernel.puts "Errored #{errors_count}"
|
||||
end
|
||||
|
||||
desc 'Import configs(accounts, blockchains, currencies, wallets, trading_fees, markets, engines, whitelisted_smart_contracts) to the database'
|
||||
task :configs, [:config_load_path] => :environment do |_, args|
|
||||
args.with_defaults(config_load_path: 'import_configs.yaml')
|
||||
|
||||
import_data = YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
Peatio::Import.new(import_data).load_all
|
||||
end
|
||||
|
||||
desc 'Load local trades to the Influx. By default, it will load trades starting from the last id in Influx'
|
||||
task :trade_to_influx, [:full_load] => :environment do |_, args|
|
||||
args.with_defaults(full_load: 'false')
|
||||
if args.full_load == 'false'
|
||||
ids = []
|
||||
Peatio::InfluxDB.config[:host].each do |host|
|
||||
client = Peatio::InfluxDB.client(host: [host])
|
||||
client.query('SELECT id from trades ORDER BY desc limit 1') do |_name, _tags, points|
|
||||
ids << points.map(&:deep_symbolize_keys!).first[:id]
|
||||
end
|
||||
end
|
||||
last_id = ids.max
|
||||
Trade.where('id > ?', last_id.to_i).find_in_batches do |batch|
|
||||
process_trades_batch(batch)
|
||||
end
|
||||
elsif args.full_load == 'true'
|
||||
Trade.find_in_batches do |batch|
|
||||
process_trades_batch(batch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def process_trades_batch(batch)
|
||||
batch.each_with_index do |trade, index|
|
||||
# We will convert created_at to ms and update it with index to make sure that we have unique
|
||||
# timestamps for each trade because influxdb use timestamp as unique identifier.
|
||||
influx_data = trade.influx_data.merge(timestamp: trade.created_at.to_i * 1000 + index)
|
||||
Peatio::InfluxDB.client(keyshard: trade.market_id).write_point('trades', influx_data, "ms")
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Build candles for all trades in influx'
|
||||
task influx_build_candles: :environment do
|
||||
prev_from = 'trades'
|
||||
Peatio::InfluxDB.config[:host].each do |host|
|
||||
client = Peatio::InfluxDB.client(host: [host])
|
||||
client.query('SELECT FIRST(price) AS open, max(price) AS high, min(price) AS low, last(price) AS close, sum(amount) AS volume INTO candles_1m FROM trades GROUP BY time(1m), market')
|
||||
prev_from = 'candles_1m'
|
||||
KLineService::HUMANIZED_POINT_PERIODS.except(1).each do |_, v|
|
||||
client.query("SELECT FIRST(open) as open, MAX(high) as high, MIN(low) as low, LAST(close) as close, SUM(volume) as volume INTO candles_#{v} FROM #{prev_from} GROUP BY time(#{v}), market")
|
||||
prev_from = "candles_#{v}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
61
lib/tasks/init_order.rake
Normal file
61
lib/tasks/init_order.rake
Normal file
@@ -0,0 +1,61 @@
|
||||
namespace :init_order do
|
||||
desc 'initalizing orders for testing'
|
||||
task :fire, %i[order_count member_count] => [:environment] do |_t, args|
|
||||
include ::Bench::Helpers
|
||||
raise 'please set config' if args[:order_count].blank? || args[:member_count].blank?
|
||||
|
||||
my_config = { injector: 'dummy', number: args[:order_count].to_i, step: 100, markets: 'btcusd',
|
||||
currencies: 'btc,usd', min_volume: 0.001, max_volume: 0.005 }
|
||||
|
||||
memberes = ::Bench::Factories.create_list(:member, args[:member_count].to_i)
|
||||
@currencies = ::Currency.where(id: my_config[:currencies].split(',').map(&:squish).reject(&:blank?))
|
||||
raise 'check currencies' unless @currencies.present?
|
||||
raise 'check members' unless memberes.present?
|
||||
|
||||
memberes.map(&method(:become_billionaire))
|
||||
|
||||
buy_config = my_config.merge({ min_price: 19_000, max_price: 20_000 })
|
||||
buy_injector = ::Bench::Injectors.initialize_injector(buy_config)
|
||||
(1..my_config[:number]).each do |_i|
|
||||
my_create_order(buy_injector.construct_order(memberes, 'OrderBid'))
|
||||
end
|
||||
|
||||
sell_config = my_config.merge({ min_price: 50_000, max_price: 51_000 })
|
||||
sell_injector = ::Bench::Injectors.initialize_injector(sell_config)
|
||||
(1..my_config[:number]).each do |_i|
|
||||
my_create_order(sell_injector.construct_order(memberes, 'OrderAsk'))
|
||||
end
|
||||
end
|
||||
|
||||
task :fire_token => [:environment] do
|
||||
raise 'secretFile is not existed' unless File.exist?("#{Rails.root}/config/secrets/rsa-key")
|
||||
|
||||
secret_file = File.read("#{Rails.root}/config/secrets/rsa-key")
|
||||
puts secret_file
|
||||
raise 'secretFile is not existed' unless File.exist?("#{Rails.root}/config/secrets/rsa-key.pub")
|
||||
|
||||
public_file = File.read("#{Rails.root}/config/secrets/rsa-key.pub")
|
||||
puts public_file
|
||||
|
||||
token_file = "#{Rails.root}/public/member_jwt_token.csv"
|
||||
JWT_ALGORITHM = 'RS256'
|
||||
ENCODED_PRIVATE_KEY = Base64.urlsafe_encode64(secret_file)
|
||||
ENCODED_PUBLIC_KEY = Base64.urlsafe_encode64(public_file)
|
||||
result = []
|
||||
Member.all.each do |member|
|
||||
payload = { uid: member.uid, email: member.email, level: member.level,
|
||||
role: member.role, state: "active", aud: "peatio", sub: "session",
|
||||
jti: SecureRandom.uuid }
|
||||
token = JWT.encode(payload, OpenSSL::PKey.read(Base64.urlsafe_decode64(ENCODED_PRIVATE_KEY)), JWT_ALGORITHM)
|
||||
puts [member.uid, member.email, token]
|
||||
result << [member.uid.to_s, member.email.to_s, token.to_s]
|
||||
end
|
||||
|
||||
CSV.open(token_file, 'w', write_headers: true) do |csv|
|
||||
result.each do |res|
|
||||
csv << res
|
||||
end
|
||||
puts 'FINISHED'
|
||||
end
|
||||
end
|
||||
end
|
||||
93
lib/tasks/job.rake
Normal file
93
lib/tasks/job.rake
Normal file
@@ -0,0 +1,93 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace :job do
|
||||
namespace :order do
|
||||
desc 'Close orders older than ORDER_MAX_AGE.'
|
||||
task close: :environment do
|
||||
Job.execute('close_orders') do
|
||||
order_max_age = ENV.fetch('ORDER_MAX_AGE', 2_419_200).to_i
|
||||
|
||||
# Cancel orders that older than max_order_age
|
||||
orders = Order.where('created_at < ? AND state = ?', Time.now - order_max_age, 100)
|
||||
orders.each do |o|
|
||||
Order.cancel(o.id)
|
||||
end
|
||||
|
||||
{ pointer: Time.now.to_s(:db), counter: orders.count }
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Archive and delete old cancelled orders without trades to the archive database.'
|
||||
task archive: :environment do
|
||||
Job.execute('archive_orders') do
|
||||
time = Time.now
|
||||
# default batch 1000
|
||||
count = Order.where(state: :cancel, trades_count: 0).where('updated_at < ?', time - 1.week).count
|
||||
Order.where(state: :cancel, trades_count: 0).where('updated_at < ?', time - 1.week).find_in_batches do |batch|
|
||||
ActiveRecord::Base.establish_connection(:archive_db)
|
||||
batch.each do |o|
|
||||
Order.new(o.attributes).save!(validate: false)
|
||||
end
|
||||
ActiveRecord::Base.establish_connection
|
||||
batch.each do |o|
|
||||
o.delete
|
||||
end
|
||||
end
|
||||
{ pointer: time, counter: count }
|
||||
end
|
||||
end
|
||||
|
||||
def order_insert
|
||||
'INSERT INTO orders (id, uuid, remote_id, bid, ask, market_id, price, ' \
|
||||
'volume, origin_volume, maker_fee, taker_fee, state, type, member_id, ord_type, ' \
|
||||
'locked, origin_locked, funds_received, trades_count, created_at, updated_at) VALUES ' \
|
||||
end
|
||||
|
||||
def order_values(order)
|
||||
order['remote_id'] = order['remote_id'].nil? ? 'NULL' : order['remote_id']
|
||||
order['uuid'] = UUID::Type.new.quoted_id(order['uuid'])
|
||||
"(#{order['id']}, #{order['uuid']}, #{order['remote_id']}, " \
|
||||
"'#{order['bid']}', '#{order['ask']}', '#{order['market_id']}', " \
|
||||
"#{order['price']}, #{order['volume']}, #{order['origin_volume']}, " \
|
||||
"#{order['maker_fee']}, #{order['taker_fee']}, #{order['state']}, " \
|
||||
"'#{order['type']}', #{order['member_id']}, '#{order['ord_type']}', " \
|
||||
"#{order['locked']}, #{order['origin_locked']}, #{order['funds_received']}, " \
|
||||
"#{order['trades_count']}, '#{order['created_at']}', '#{order['updated_at']}')"
|
||||
end
|
||||
end
|
||||
|
||||
namespace :liabilities do
|
||||
desc 'Compact liabilities using Stored Procedure'
|
||||
task :compact_orders, %i[min_time max_time] => [:environment] do |_, args|
|
||||
Job.execute('compact_orders') do
|
||||
# Connection to the main database
|
||||
main_db = if Rails.configuration.database_adapter.downcase == 'PostgreSQL'.downcase
|
||||
ActiveRecord::Base.connection.raw_connection
|
||||
else
|
||||
Mysql2::Client.new(sql_config(ENV.fetch('RAILS_ENV', 'development')))
|
||||
end
|
||||
# Execute Stored Procedure for Liabilities compacting
|
||||
# Example:
|
||||
# Current date: "2020-07-30 16:39:15"
|
||||
# min_time: "2020-07-23 00:00:00"
|
||||
# max_time: "2020-07-24 00:00:00"
|
||||
# Compact liabilities beetwen: "2020-07-23 00:00:00" and "2020-07-24 00:00:00"
|
||||
args.with_defaults(min_time: (Time.now - 1.week).beginning_of_day.to_s(:db),
|
||||
max_time: (Time.now - 6.day).beginning_of_day.to_s(:db))
|
||||
result = if Rails.configuration.database_adapter.downcase == 'PostgreSQL'.downcase
|
||||
main_db.query("select * from compact_orders('#{args.min_time}'::date, '#{args.max_time}'::date);")
|
||||
else
|
||||
main_db.query("call compact_orders('#{args.min_time}', '#{args.max_time}');")
|
||||
end
|
||||
result.first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def sql_config(namespace)
|
||||
yaml = ::Pathname.new('config/database.yml')
|
||||
return {} unless yaml.exist?
|
||||
|
||||
::SafeYAML.load(::ERB.new(yaml.read).result)[namespace]
|
||||
end
|
||||
end
|
||||
37
lib/tasks/release.rake
Normal file
37
lib/tasks/release.rake
Normal file
@@ -0,0 +1,37 @@
|
||||
require 'bump'
|
||||
|
||||
def bot_username
|
||||
ENV.fetch('BOT_USERNAME', 'kite-bot')
|
||||
end
|
||||
|
||||
def repository_slug
|
||||
ENV.fetch('REPOSITORY_SLUG', 'openware/peatio')
|
||||
end
|
||||
|
||||
namespace 'release' do
|
||||
|
||||
desc 'Bump the version of the application'
|
||||
task :travis do
|
||||
unless ENV['TRAVIS_BRANCH'] == 'master' || ENV['TRAVIS_BRANCH'].match?(/^[0-9]+-[0-9]+-stable$/)
|
||||
Kernel.abort 'Bumping version aborted: GitHub pull request detected.'
|
||||
end
|
||||
|
||||
if ENV['TRAVIS_PULL_REQUEST'] != 'false'
|
||||
Kernel.abort 'Bumping version aborted: GitHub pull request detected.'
|
||||
end
|
||||
|
||||
unless ENV['TRAVIS_TAG'].to_s.empty?
|
||||
Kernel.abort 'Bumping version aborted: the build has been triggered by Git tag.'
|
||||
end
|
||||
|
||||
sh %(git config --global user.name 'OpenWare')
|
||||
sh %(git config --global user.email 'support@openware.com')
|
||||
sh %(git remote add authenticated-origin https://#{bot_username}:#{ENV.fetch('GITHUB_API_KEY')}@github.com/#{repository_slug})
|
||||
next_version = Bump::Bump.next_version('patch')
|
||||
sh %(V='#{next_version}' bin/gendocs)
|
||||
sh %(git add -A)
|
||||
Bump::Bump.run('patch', commit_message: '[skip ci]', tag: false)
|
||||
sh %(git tag #{Bump::Bump.current})
|
||||
sh %(git push --tags authenticated-origin HEAD:#{ENV.fetch('TRAVIS_BRANCH')})
|
||||
end
|
||||
end
|
||||
17
lib/tasks/revert.rake
Normal file
17
lib/tasks/revert.rake
Normal file
@@ -0,0 +1,17 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Usage
|
||||
# for revert all trading activity for particular user:
|
||||
# $> bundle exec rake revert:trading_activity["admin@barong.io"]
|
||||
namespace :revert do
|
||||
desc 'Revert user trade activity.'
|
||||
task :trading_activity, [:member_email] => [:environment] do |_, args|
|
||||
|
||||
member = Member.find_by(email: args[:member_email])
|
||||
|
||||
# For each trade create revert Liabilities, Revenues and update User balances
|
||||
# TODO: Add ability to revert particular trades.
|
||||
member.revert_trading_activity!(member.trades.order(id: :desc))
|
||||
end
|
||||
end
|
||||
143
lib/tasks/seed.rake
Normal file
143
lib/tasks/seed.rake
Normal file
@@ -0,0 +1,143 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
require 'yaml'
|
||||
|
||||
namespace :seed do
|
||||
desc 'Adds missing accounts to database defined at config/seed/accounts.yml.'
|
||||
task accounts: :environment do
|
||||
Operations::Account.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/accounts.yml')).each do |hash|
|
||||
next if Operations::Account.exists?(code: hash.fetch('code'))
|
||||
Operations::Account.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Deprecate seed tasks in favour of import:configs
|
||||
desc 'Adds missing currencies to database defined at config/seed/currencies.yml.'
|
||||
task currencies: :environment do
|
||||
Currency.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/currencies.yml')).each do |hash|
|
||||
next if Currency.exists?(id: hash.fetch('id'))
|
||||
Currency.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds missing blockchains to database defined at config/seed/blockchains.yml.'
|
||||
task blockchains: :environment do
|
||||
Blockchain.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/blockchains.yml')).each do |hash|
|
||||
next if Blockchain.exists?(key: hash.fetch('key'))
|
||||
Blockchain.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds missing engines to database defined at config/seed/engines.yml.'
|
||||
task engines: :environment do
|
||||
Engine.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/engines.yml')).each do |hash|
|
||||
next if Engine.exists?(name: hash.fetch('name'))
|
||||
Engine.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds missing markets to database defined at config/seed/markets.yml.'
|
||||
task markets: :environment do
|
||||
Market.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/markets.yml'))
|
||||
.map(&:symbolize_keys)
|
||||
.each do |hash|
|
||||
next if Market.exists?(id: hash.fetch(:id))
|
||||
# For compatibility with old markets.yml
|
||||
# If state is not defined set it from enabled.
|
||||
enabled = hash.delete(:enabled)
|
||||
hash[:state] ||= enabled ? :enabled : :disabled
|
||||
|
||||
# For compatibility with old markets.yml we keep legacy-new keys mapping.
|
||||
# New key value has higher priority than legacy.
|
||||
legacy_keys_mappings = { ask_unit: :base_unit,
|
||||
bid_unit: :quote_unit,
|
||||
ask_precision: :amount_precision,
|
||||
bid_precision: :price_precision,
|
||||
min_ask_price: :min_price,
|
||||
max_bid_price: :max_price,
|
||||
min_ask_amount: :min_amount,
|
||||
min_bid_amount: :min_amount }
|
||||
|
||||
legacy_keys_mappings.each do |old_key, new_key|
|
||||
legacy_key_value = hash.delete(old_key)
|
||||
hash[new_key] ||= legacy_key_value
|
||||
end
|
||||
|
||||
# Select engine with provided name
|
||||
engine = Engine.find_by(name: hash[:engine_name])
|
||||
if engine.present?
|
||||
hash.delete :engine_name
|
||||
hash[:engine_id] = engine.id
|
||||
Market.create!(hash)
|
||||
else
|
||||
Rails.logger.error "Engine doesn't exist"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds missing wallets to database defined at config/seed/wallets.yml.'
|
||||
task wallets: :environment do
|
||||
Wallet.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/wallets.yml')).each do |hash|
|
||||
next if Wallet.exists?(name: hash.fetch('name'))
|
||||
if hash['currency_ids'].is_a?(String)
|
||||
hash['currency_ids'] = hash['currency_ids'].split(',')
|
||||
end
|
||||
Wallet.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds missing trading_fees to database defined at config/seed/trading_fees.yml.'
|
||||
task trading_fees: :environment do
|
||||
TradingFee.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/trading_fees.yml')).each do |hash|
|
||||
next if TradingFee.exists?(market_id: hash.fetch('market_id'), group: hash.fetch('group'))
|
||||
TradingFee.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds missing whitelisted_smart_contracts to database defined at config/seed/whitelisted_smart_contracts.yml.'
|
||||
task whitelisted_smart_contracts: :environment do
|
||||
WhitelistedSmartContract.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/whitelisted_smart_contracts.yml')).each do |hash|
|
||||
next if WhitelistedSmartContract.exists?(address: hash.fetch('address'), blockchain_key: hash.fetch('blockchain_key'))
|
||||
|
||||
WhitelistedSmartContract.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds missing member for test'
|
||||
task members: :environment do
|
||||
Member.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/members.yml')).each do |hash|
|
||||
next if Member.exists?(id: hash.fetch('id'))
|
||||
|
||||
Member.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Adds deposit limits'
|
||||
task deposit_limits: :environment do
|
||||
::DepositLimit.transaction do
|
||||
YAML.load_file(Rails.root.join('config/seed/deposit_limit.yml')).each do |hash|
|
||||
next if ::DepositLimit.exists?(id: hash.fetch('id'))
|
||||
|
||||
::DepositLimit.create!(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
10
lib/tasks/trade_taker_type.rake
Normal file
10
lib/tasks/trade_taker_type.rake
Normal file
@@ -0,0 +1,10 @@
|
||||
desc 'Select and update taker_type base on taker_order'
|
||||
task assign_taker_type: :environment do
|
||||
Trade.where(taker_type: '').find_in_batches do |batch|
|
||||
ActiveRecord::Base.transaction do
|
||||
batch.each do |t|
|
||||
t.update_attribute(:taker_type, t.taker_order.side) if t.taker_order.present?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
lib/tasks/trading_fee_test.rake
Normal file
20
lib/tasks/trading_fee_test.rake
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace :trading_fee_test do
|
||||
|
||||
task :amqp, [:config_load_path] => [:environment] do |_t, args|
|
||||
args.with_defaults(:config_load_path => 'config/bench/trade_execution.yml')
|
||||
benches =
|
||||
YAML.load_file(Rails.root.join(args[:config_load_path]))
|
||||
.map(&:deep_symbolize_keys)
|
||||
.each_with_object([]) do |config, memo|
|
||||
Kernel.pp config
|
||||
trade_execution = ::Bench::TradeExecution::AMQP.new(config)
|
||||
trade_execution.run_fee!
|
||||
memo << trade_execution
|
||||
trade_execution.save_report
|
||||
Kernel.puts "Sleep before next bench"
|
||||
sleep 5
|
||||
end
|
||||
|
||||
benches.each {|b| Kernel.pp b.result}
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user