Initial commit
This commit is contained in:
438
spec/services/blockchain_service_spec.rb
Normal file
438
spec/services/blockchain_service_spec.rb
Normal file
@@ -0,0 +1,438 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
class FakeBlockchain < Peatio::Blockchain::Abstract
|
||||
def initialize
|
||||
@features = {cash_addr_format: false, case_sensitive: true}
|
||||
end
|
||||
|
||||
def configure(settings = {}); end
|
||||
end
|
||||
|
||||
describe BlockchainService do
|
||||
|
||||
let!(:blockchain) { create(:blockchain, 'fake-testnet') }
|
||||
let(:block_number) { 100 }
|
||||
let(:fake_adapter) { FakeBlockchain.new }
|
||||
let(:service) { BlockchainService.new(blockchain) }
|
||||
|
||||
let!(:fake_currency) { create(:currency, :fake) }
|
||||
let!(:fake_currency1) { create(:currency, :fake, id: 'fake1') }
|
||||
let!(:fake_currency2) { create(:currency, :fake, id: 'fake2') }
|
||||
let!(:wallet) { create(:wallet, :fake_deposit) }
|
||||
|
||||
let!(:member) { create(:member) }
|
||||
|
||||
let(:transaction) { Peatio::Transaction.new(hash: 'fake_txid', to_address: 'fake_address', from_addresses: ['fake_address'], amount: 5, block_number: 3, currency_id: 'fake1', txout: 4, status: 'success') }
|
||||
|
||||
let(:expected_transactions) do
|
||||
[
|
||||
{ hash: 'fake_hash1', to_address: 'fake_address', amount: 1, block_number: 2, currency_id: 'fake1', txout: 1, from_addresses: ['fake_address'], status: 'success' },
|
||||
{ hash: 'fake_hash2', to_address: 'fake_address1', amount: 2, block_number: 2, currency_id: 'fake1', txout: 2, from_addresses: ['fake_address'], status: 'success' },
|
||||
{ hash: 'fake_hash3', to_address: 'fake_address2', amount: 3, block_number: 2, currency_id: 'fake2', txout: 3, from_addresses: ['fake_address'], status: 'success' }
|
||||
].map { |t| Peatio::Transaction.new(t) }
|
||||
end
|
||||
|
||||
let(:expected_block) { Peatio::Block.new(block_number, expected_transactions) }
|
||||
|
||||
before do
|
||||
wallet.currencies << [fake_currency1, fake_currency2]
|
||||
Peatio::Blockchain.registry.expects(:[])
|
||||
.with(:fake)
|
||||
.returns(fake_adapter.class)
|
||||
.at_least_once
|
||||
|
||||
service.stubs(:latest_block_number).returns(4)
|
||||
service.adapter.stubs(:latest_block_number).never
|
||||
end
|
||||
|
||||
# Deposit context: (mock fetch_block)
|
||||
# * Single deposit in block which should be saved.
|
||||
# * Multiple deposits in single block (one saved one updated).
|
||||
# * Multiple deposits for 2 currencies in single block.
|
||||
# * Multiple deposits in single transaction (different txout).
|
||||
describe 'Filter Deposits' do
|
||||
|
||||
context 'single fake deposit was created during block processing' do
|
||||
|
||||
before do
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address')
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Deposits::Coin.where(currency: fake_currency1) }
|
||||
|
||||
it { expect(subject.exists?).to be true }
|
||||
|
||||
context 'creates deposit with correct attributes' do
|
||||
before do
|
||||
service.adapter.stubs(:fetch_block!).returns(Peatio::Block.new(block_number, [transaction]))
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
it { expect(subject.where(txid: transaction.hash,
|
||||
amount: transaction.amount,
|
||||
address: transaction.to_address,
|
||||
block_number: transaction.block_number,
|
||||
txout: transaction.txout,
|
||||
from_addresses: transaction.from_addresses).exists?).to be true }
|
||||
end
|
||||
|
||||
context 'collect deposit after processing block' do
|
||||
before do
|
||||
service.stubs(:latest_block_number).returns(100)
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
AMQP::Queue.expects(:enqueue).with(:events_processor, is_a(Hash))
|
||||
end
|
||||
|
||||
it { service.process_block(block_number) }
|
||||
end
|
||||
|
||||
context 'process data one more time' do
|
||||
before do
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
end
|
||||
|
||||
it { expect { service.process_block(block_number) }.not_to change { subject } }
|
||||
end
|
||||
end
|
||||
|
||||
context 'two fake deposits for one currency were created during block processing' do
|
||||
before do
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address')
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address1')
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Deposits::Coin.where(currency: fake_currency1) }
|
||||
|
||||
it { expect(subject.count).to eq 2 }
|
||||
|
||||
context 'one deposit was updated' do
|
||||
let!(:deposit) do
|
||||
Deposit.create!(currency: fake_currency1,
|
||||
member: member,
|
||||
amount: 5,
|
||||
address: 'fake_address',
|
||||
txid: 'fake_txid',
|
||||
block_number: 0,
|
||||
txout: 4,
|
||||
type: Deposits::Coin)
|
||||
end
|
||||
before do
|
||||
service.adapter.stubs(:fetch_block!).returns(Peatio::Block.new(block_number, [transaction]))
|
||||
service.process_block(block_number)
|
||||
end
|
||||
it { expect(Deposits::Coin.find_by(txid: transaction.hash).block_number).to eq(transaction.block_number) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'two fake deposits for two currency were created during block processing' do
|
||||
before do
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address')
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address2')
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Deposits::Coin.where(currency: [fake_currency1, fake_currency2]) }
|
||||
|
||||
it do
|
||||
expect(subject.count).to eq 2
|
||||
expect(Deposits::Coin.where(currency: fake_currency1).exists?).to be true
|
||||
expect(Deposits::Coin.where(currency: fake_currency2).exists?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'skip deposit collection fee transaction' do
|
||||
let!(:transaction) { create(:transaction, txid: 'fake_hash1') }
|
||||
before do
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address')
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Deposits::Coin.where(currency: [fake_currency1, fake_currency2]) }
|
||||
|
||||
it do
|
||||
expect(subject.count).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Withdraw context: (mock fetch_block)
|
||||
# * Single withdrawal.
|
||||
# * Multiple withdrawals for single currency.
|
||||
# * Multiple withdrawals for 2 currencies.
|
||||
describe 'Filter Withdrawals' do
|
||||
|
||||
context 'single fake withdrawal was updated during block processing' do
|
||||
|
||||
let!(:fake_account) { member.get_account(:fake1).tap { |ac| ac.update!(balance: 50, locked: 5) } }
|
||||
let!(:withdrawal) do
|
||||
Withdraw.create!(member: member,
|
||||
currency: fake_currency1,
|
||||
amount: 1,
|
||||
txid: 'fake_hash1',
|
||||
rid: 'fake_address',
|
||||
sum: 1,
|
||||
type: Withdraws::Coin,
|
||||
aasm_state: :confirming)
|
||||
end
|
||||
|
||||
before do
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
it { expect(withdrawal.reload.block_number).to eq(expected_transactions.first.block_number) }
|
||||
|
||||
context 'single withdrawal was succeed during block processing' do
|
||||
|
||||
before do
|
||||
service.stubs(:latest_block_number).returns(100)
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
it { expect(withdrawal.reload.succeed?).to be true }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'two fake withdrawals were updated during block processing' do
|
||||
|
||||
let!(:fake_account1) { member.get_account(:fake1).tap { |ac| ac.update!(balance: 50, locked: 10) } }
|
||||
let!(:withdrawals) do
|
||||
%w[fake_hash1 fake_hash2].each do |t|
|
||||
Withdraw.create!(member: member,
|
||||
currency: fake_currency1,
|
||||
amount: 1,
|
||||
txid: t,
|
||||
rid: 'fake_address',
|
||||
sum: 1,
|
||||
type: Withdraws::Coin,
|
||||
aasm_state: :confirming)
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Withdraws::Coin.where(currency: fake_currency1) }
|
||||
|
||||
it do
|
||||
expect(subject.find_by(txid: expected_transactions.first.hash).block_number).to eq(expected_transactions.first.block_number)
|
||||
expect(subject.find_by(txid: expected_transactions.second.hash).block_number).to eq(expected_transactions.second.block_number)
|
||||
end
|
||||
end
|
||||
|
||||
context 'two fake withdrawals for two currency were updated during block processing' do
|
||||
let!(:fake_account1) { member.get_account(:fake1).tap { |ac| ac.update!(balance: 50, locked: 10) } }
|
||||
let!(:fake_account2) { member.get_account(:fake2).tap { |ac| ac.update!(balance: 50, locked: 10) } }
|
||||
let!(:withdrawal1) do
|
||||
Withdraw.create!(member: member,
|
||||
currency: fake_currency1,
|
||||
amount: 1,
|
||||
txid: "fake_hash1",
|
||||
rid: 'fake_address',
|
||||
sum: 1,
|
||||
type: Withdraws::Coin,
|
||||
aasm_state: :confirming)
|
||||
end
|
||||
let!(:withdrawal2) do
|
||||
Withdraw.create!(member: member,
|
||||
currency: fake_currency2,
|
||||
amount: 1,
|
||||
txid: "fake_hash3",
|
||||
rid: 'fake_address',
|
||||
sum: 1,
|
||||
type: Withdraws::Coin,
|
||||
aasm_state: :confirming)
|
||||
end
|
||||
|
||||
before do
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Withdraws::Coin.where(currency: [fake_currency1, fake_currency2]) }
|
||||
|
||||
it do
|
||||
expect(subject.find_by(txid: expected_transactions.first.hash).block_number).to eq(expected_transactions.first.block_number)
|
||||
expect(subject.find_by(txid: expected_transactions.third.hash).block_number).to eq(expected_transactions.third.block_number)
|
||||
end
|
||||
|
||||
context 'fail withdrawal if transaction has status :fail' do
|
||||
|
||||
let!(:fake_account1) { member.get_account(:fake1).tap { |ac| ac.update!(balance: 50, locked: 10) } }
|
||||
|
||||
let!(:withdrawal) do
|
||||
Withdraw.create!(member: member,
|
||||
currency: fake_currency1,
|
||||
amount: 1,
|
||||
txid: "fake_hash",
|
||||
rid: 'fake_address',
|
||||
sum: 1,
|
||||
type: Withdraws::Coin,
|
||||
aasm_state: :confirming)
|
||||
end
|
||||
|
||||
let!(:transaction) do
|
||||
Peatio::Transaction.new(hash: 'fake_hash', to_address: 'fake_address', amount: 1, block_number: 3, currency_id: fake_currency1.id, txout: 10, status: 'failed')
|
||||
end
|
||||
|
||||
before do
|
||||
service.adapter.stubs(:fetch_block!).returns(Peatio::Block.new(block_number, [transaction]))
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Withdraws::Coin.find_by(currency: fake_currency1, txid: transaction.hash) }
|
||||
|
||||
it do
|
||||
expect(subject.failed?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'fail withdrawal if transaction has status :fail' do
|
||||
|
||||
let!(:fake_account1) { member.get_account(:fake1).tap { |ac| ac.update!(balance: 50, locked: 10) } }
|
||||
|
||||
let!(:withdrawal) do
|
||||
Withdraw.create!(member: member,
|
||||
currency: fake_currency1,
|
||||
amount: 1,
|
||||
txid: "fake_hash",
|
||||
rid: 'fake_address',
|
||||
sum: 1,
|
||||
type: Withdraws::Coin,
|
||||
aasm_state: :confirming)
|
||||
end
|
||||
|
||||
let!(:transaction) do
|
||||
Peatio::Transaction.new(hash: 'fake_hash', to_address: 'fake_address', amount: 1, block_number: 3, currency_id: fake_currency1.id, txout: 10, status: 'pending')
|
||||
end
|
||||
|
||||
let!(:failed_transaction) do
|
||||
Peatio::Transaction.new(hash: 'fake_hash', to_address: 'fake_address', amount: 1, block_number: 3, currency_id: fake_currency1.id, txout: 10, status: 'failed')
|
||||
end
|
||||
|
||||
before do
|
||||
service.adapter.stubs(:respond_to?).returns(true)
|
||||
service.adapter.stubs(:fetch_block!).returns(Peatio::Block.new(block_number, [transaction]))
|
||||
service.adapter.stubs(:fetch_transaction).with(transaction).returns(failed_transaction)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Withdraws::Coin.find_by(currency: fake_currency1, txid: transaction.hash) }
|
||||
|
||||
it do
|
||||
expect(subject.failed?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'succeed withdrawal if transaction has status :success' do
|
||||
|
||||
let!(:fake_account1) { member.get_account(:fake1).tap { |ac| ac.update!(balance: 50, locked: 10) } }
|
||||
|
||||
let!(:withdrawal) do
|
||||
Withdraw.create!(member: member,
|
||||
currency: fake_currency1,
|
||||
amount: 1,
|
||||
txid: "fake_hash",
|
||||
rid: 'fake_address',
|
||||
sum: 1,
|
||||
type: Withdraws::Coin,
|
||||
aasm_state: :confirming)
|
||||
end
|
||||
|
||||
let!(:transaction) do
|
||||
Peatio::Transaction.new(hash: 'fake_hash', to_address: 'fake_address', amount: 1, block_number: 3, currency_id: fake_currency1.id, txout: 10, status: 'pending')
|
||||
end
|
||||
|
||||
let!(:succeed_transaction) do
|
||||
Peatio::Transaction.new(hash: 'fake_hash', to_address: 'fake_address', amount: 1, block_number: 3, currency_id: fake_currency1.id, txout: 10, status: 'success')
|
||||
end
|
||||
|
||||
before do
|
||||
service.adapter.stubs(:respond_to?).returns(true)
|
||||
service.adapter.stubs(:fetch_block!).returns(Peatio::Block.new(block_number, [transaction]))
|
||||
service.stubs(:latest_block_number).returns(10)
|
||||
service.adapter.stubs(:fetch_transaction).with(transaction).returns(succeed_transaction)
|
||||
service.process_block(block_number)
|
||||
end
|
||||
|
||||
subject { Withdraws::Coin.find_by(currency: fake_currency1, txid: transaction.hash) }
|
||||
|
||||
it do
|
||||
expect(subject.succeed?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Several blocks' do
|
||||
let(:expected_transactions1) do
|
||||
[
|
||||
{ hash: 'fake_hash4', to_address: 'fake_address4', amount: 1, block_number: 3, currency_id: 'fake1', txout: 1, status: 'success' },
|
||||
{ hash: 'fake_hash5', to_address: 'fake_address4', amount: 2, block_number: 3, currency_id: 'fake1', txout: 2, status: 'success' },
|
||||
{ hash: 'fake_hash6', to_address: 'fake_address4', amount: 3, block_number: 3, currency_id: 'fake2', txout: 1, status: 'success' }
|
||||
].map { |t| Peatio::Transaction.new(t) }
|
||||
end
|
||||
|
||||
let(:expected_block1) { Peatio::Block.new(block_number, expected_transactions1) }
|
||||
|
||||
let!(:fake_account1) { member.get_account(:fake1) }
|
||||
let!(:fake_account2) { member.get_account(:fake2) }
|
||||
|
||||
before do
|
||||
service.stubs(:latest_block_number).returns(100)
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address')
|
||||
PaymentAddress.create!(member: member,
|
||||
wallet: wallet,
|
||||
address: 'fake_address2')
|
||||
service.adapter.stubs(:fetch_block!).returns(expected_block, expected_block1)
|
||||
end
|
||||
|
||||
it 'creates deposits and updates withdrawals' do
|
||||
service.process_block(block_number)
|
||||
expect(Deposits::Coin.where(currency: fake_currency1).exists?).to be true
|
||||
expect(Deposits::Coin.where(currency: fake_currency2).exists?).to be true
|
||||
Deposit.find_each { |d| d.dispatch! }
|
||||
|
||||
[fake_account1, fake_account2].map { |a| a.reload }
|
||||
withdraw1 = Withdraw.create!(member: member, currency: fake_currency1, amount: 1, txid: "fake_hash5",
|
||||
rid: 'fake_address4', sum: 1, type: Withdraws::Coin)
|
||||
withdraw1.accept!
|
||||
withdraw1.process!
|
||||
withdraw1.dispatch!
|
||||
|
||||
withdraw2 = Withdraw.create!(member: member, currency: fake_currency2, amount: 3, txid: "fake_hash6",
|
||||
rid: 'fake_address4', sum: 3, type: Withdraws::Coin)
|
||||
withdraw2.accept!
|
||||
withdraw2.process!
|
||||
withdraw2.dispatch!
|
||||
|
||||
service.process_block(block_number)
|
||||
expect(withdraw1.reload.succeed?).to be true
|
||||
expect(withdraw2.reload.succeed?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
85
spec/services/tickers_service_spec.rb
Normal file
85
spec/services/tickers_service_spec.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe TickersService, '#ticker' do
|
||||
let(:market) { Market.all.sample.id.to_sym }
|
||||
let(:service) { TickersService }
|
||||
context 'no trades executed' do
|
||||
let(:default) do
|
||||
{
|
||||
amount: '0.0',
|
||||
avg_price: '0.0',
|
||||
high: '0.0',
|
||||
last: '0.0',
|
||||
low: '0.0',
|
||||
open: '0.0',
|
||||
price_change_percent: '+0.00%',
|
||||
volume: '0.0'
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns zero tickers' do
|
||||
expect(service[:btcusd].ticker.except(:at)).to eq default
|
||||
end
|
||||
end
|
||||
|
||||
context 'single trade executed during last 24 hours' do
|
||||
after { delete_measurments('trades') }
|
||||
let!(:trade) { create(:trade, :btcusd, price: 5, amount: 2) }
|
||||
|
||||
let(:ticker) do
|
||||
{
|
||||
amount: '2.0',
|
||||
avg_price: '5.0',
|
||||
high: '5.0',
|
||||
last: '5.0',
|
||||
low: '5.0',
|
||||
open: '5.0',
|
||||
price_change_percent: '+0.00%',
|
||||
volume: '10.0'
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
trade.write_to_influx
|
||||
end
|
||||
|
||||
it 'returns trade price' do
|
||||
expect(service[:btcusd].ticker.except(:at)).to eq(ticker)
|
||||
end
|
||||
end
|
||||
|
||||
context 'multiple trades executed during last 24 hours' do
|
||||
after { delete_measurments('trades') }
|
||||
|
||||
let(:trades) do
|
||||
[
|
||||
create(:trade, :btcusd, price: 12.to_d, amount: 10.to_d),
|
||||
create(:trade, :btcusd, price: 11.to_d, amount: 17.to_d),
|
||||
create(:trade, :btcusd, price: 10.to_d, amount: 25.to_d),
|
||||
create(:trade, :btcusd, price: 9.to_d, amount: 18.to_d),
|
||||
create(:trade, :btcusd, price: 8.to_d, amount: 10.to_d)
|
||||
]
|
||||
end
|
||||
|
||||
let(:ticker) do
|
||||
{
|
||||
amount: '80.0',
|
||||
avg_price: '9.9875',
|
||||
high: '12.0',
|
||||
last: '8.0',
|
||||
low: '8.0',
|
||||
open: '12.0',
|
||||
price_change_percent: '-33.33%',
|
||||
volume: '799.0'
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
trades.map(&:write_to_influx)
|
||||
end
|
||||
|
||||
it 'returns trade price' do
|
||||
expect(service[:btcusd].ticker.except(:at)).to eq(ticker)
|
||||
end
|
||||
end
|
||||
end
|
||||
777
spec/services/wallet_service_spec.rb
Normal file
777
spec/services/wallet_service_spec.rb
Normal file
@@ -0,0 +1,777 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe WalletService do
|
||||
let!(:blockchain) { create(:blockchain, 'fake-testnet') }
|
||||
let!(:currency) { create(:currency, :fake) }
|
||||
let(:wallet) { create(:wallet, :fake_hot) }
|
||||
let(:member) { create(:member) }
|
||||
|
||||
let(:fake_wallet_adapter) { FakeWallet.new }
|
||||
let(:fake_blockchain_adapter) { FakeBlockchain.new }
|
||||
|
||||
let(:service) { WalletService.new(wallet) }
|
||||
|
||||
before do
|
||||
Peatio::Blockchain.registry.expects(:[])
|
||||
.with(:fake)
|
||||
.returns(fake_blockchain_adapter.class)
|
||||
.at_least_once
|
||||
|
||||
Peatio::Wallet.registry.expects(:[])
|
||||
.with(:fake)
|
||||
.returns(fake_wallet_adapter.class)
|
||||
.at_least_once
|
||||
|
||||
Blockchain.any_instance.stubs(:blockchain_api).returns(BlockchainService.new(blockchain))
|
||||
end
|
||||
|
||||
context :create_address! do
|
||||
let(:account) { create(:member, :level_3, :barong).get_account(currency) }
|
||||
let(:blockchain_address) do
|
||||
{ address: :fake_address,
|
||||
secret: :changeme,
|
||||
details: { uid: account.member.uid } }
|
||||
end
|
||||
|
||||
before do
|
||||
service.adapter.expects(:create_address!).returns(blockchain_address)
|
||||
end
|
||||
|
||||
it 'creates address' do
|
||||
expect(service.create_address!(account, nil)).to eq blockchain_address
|
||||
end
|
||||
end
|
||||
|
||||
context :build_withdrawal! do
|
||||
let(:withdrawal) { create(:btc_withdraw, rid: 'fake-address', amount: 100, currency: currency, member: member) }
|
||||
|
||||
let(:transaction) do
|
||||
Peatio::Transaction.new(hash: '0xfake',
|
||||
to_address: withdrawal.rid,
|
||||
amount: withdrawal.amount,
|
||||
currency_id: currency.id)
|
||||
end
|
||||
|
||||
before do
|
||||
member.get_account(currency).update!(balance: 1000)
|
||||
service.adapter.expects(:create_transaction!).returns(transaction)
|
||||
end
|
||||
|
||||
it 'sends withdrawal' do
|
||||
expect(service.build_withdrawal!(withdrawal)).to eq transaction
|
||||
end
|
||||
end
|
||||
|
||||
context :spread_between_wallets do
|
||||
|
||||
# Single wallet:
|
||||
# * Deposit fits exactly.
|
||||
# * Deposit doesn't fit.
|
||||
# Two wallets:
|
||||
# * Deposit fits to first wallet.
|
||||
# * Deposit fits to second wallet.
|
||||
# * Partial spread between first and second.
|
||||
# * Deposit doesn't fit to both wallets.
|
||||
# * Negative min_collection_amount.
|
||||
# Three wallets:
|
||||
# * Partial spread between first and second.
|
||||
# * Partial spread between first and third.
|
||||
# * Partial spread between first, second and third.
|
||||
# * Deposit doesn't fit to all wallets.
|
||||
|
||||
let(:deposit) { Deposit.new(amount: 1.2, currency_id: :fake) }
|
||||
|
||||
context 'Single wallet' do
|
||||
|
||||
context 'single wallet available' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 8.8,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'pending',
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to single wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'single wallet available + skip_deposit_collection' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 8.8,
|
||||
max_balance: 10,
|
||||
min_collection_amount: deposit.amount,
|
||||
skip_deposit_collection: true }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{:amount=>"1.2", :currency_id=>"fake", :status=>"skipped", :to_address=>"destination-wallet-1"}]
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'returns spread with skipped transaction' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
end
|
||||
end
|
||||
|
||||
context 'Single wallet is full' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 10,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'pending',
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'Two wallets' do
|
||||
|
||||
context 'Deposit fits to first wallet' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 5,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 100.0,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'pending',
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Deposit fits to second wallet' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 10,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 95,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-2',
|
||||
status: 'pending',
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Partial spread between first and second' do
|
||||
|
||||
let(:deposit) { Deposit.new(amount: 10, currency_id: :fake) }
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 5,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 90,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'pending',
|
||||
amount: '5.0',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'destination-wallet-2',
|
||||
status: 'pending',
|
||||
amount: '5.0',
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Two wallets are full' do
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 10,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 100,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-2',
|
||||
status: 'pending',
|
||||
amount: '1.2',
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'different min_collection_amount' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 10,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 100,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 2 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-2',
|
||||
status: 'pending',
|
||||
amount: '1.2',
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to single wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'tiny min_collection_amount' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 10,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 2 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 100,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 3 }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
let(:expected_spread) { [] }
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to single wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'Three wallets' do
|
||||
|
||||
context 'Partial spread between first and second' do
|
||||
|
||||
let(:deposit) { Deposit.new(amount: 10, currency_id: :fake) }
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 5,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 95,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-3',
|
||||
balance: 1001.0,
|
||||
max_balance: 1000,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'pending',
|
||||
amount: '5.0',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'destination-wallet-2',
|
||||
status: 'pending',
|
||||
amount: '5.0',
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Partial spread between first and third' do
|
||||
|
||||
let(:deposit) { Deposit.new(amount: 10, currency_id: :fake) }
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 5,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 100,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-3',
|
||||
balance: 995.0,
|
||||
max_balance: 1000,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'pending',
|
||||
amount: '5.0',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'destination-wallet-3',
|
||||
status: 'pending',
|
||||
amount: '5.0',
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Three wallets are full' do
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 10.1,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 100.0,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-3',
|
||||
balance: 1001.0,
|
||||
max_balance: 1000,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-3',
|
||||
status: 'pending',
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads everything to last wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Partial spread between first, second and third' do
|
||||
|
||||
let(:deposit) { Deposit.new(amount: 10, currency_id: :fake) }
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 7,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 97,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-3',
|
||||
balance: 995.0,
|
||||
max_balance: 1000,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'pending',
|
||||
amount: '3.0',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'destination-wallet-2',
|
||||
status: 'pending',
|
||||
amount: '3.0',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'destination-wallet-3',
|
||||
status: 'pending',
|
||||
amount: '4.0',
|
||||
currency_id: currency.id }.as_json].map(&:symbolize_keys)
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads between wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Partial spread between first, second and third + skip deposit collection option' do
|
||||
|
||||
let(:deposit) { Deposit.new(amount: 10, currency_id: :fake) }
|
||||
|
||||
let(:destination_wallets) do
|
||||
[{ address: 'destination-wallet-1',
|
||||
balance: 7,
|
||||
max_balance: 10,
|
||||
min_collection_amount: 1,
|
||||
skip_deposit_collection: true },
|
||||
{ address: 'destination-wallet-2',
|
||||
balance: 97,
|
||||
max_balance: 100,
|
||||
min_collection_amount: 1 },
|
||||
{ address: 'destination-wallet-3',
|
||||
balance: 995.0,
|
||||
max_balance: 1000,
|
||||
min_collection_amount: 1 }]
|
||||
end
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'destination-wallet-1',
|
||||
status: 'skipped',
|
||||
amount: '3.0',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'destination-wallet-2',
|
||||
status: 'pending',
|
||||
amount: '3.0',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'destination-wallet-3',
|
||||
status: 'pending',
|
||||
amount: '4.0',
|
||||
currency_id: currency.id}]
|
||||
end
|
||||
|
||||
subject { service.send(:spread_between_wallets, deposit, destination_wallets) }
|
||||
|
||||
it 'spreads between wallet' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context :spread_deposit do
|
||||
let!(:deposit_wallet) { create(:wallet, :fake_deposit) }
|
||||
let!(:hot_wallet) { create(:wallet, :fake_hot) }
|
||||
let!(:cold_wallet) { create(:wallet, :fake_cold) }
|
||||
|
||||
let(:service) { WalletService.new(deposit_wallet) }
|
||||
|
||||
let(:amount) { 2 }
|
||||
let(:deposit) { create(:deposit_btc, amount: amount, currency: currency) }
|
||||
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'fake-cold',
|
||||
status: 'pending',
|
||||
amount: '2.0',
|
||||
currency_id: currency.id }]
|
||||
end
|
||||
|
||||
subject { service.spread_deposit(deposit) }
|
||||
|
||||
context 'hot wallet is full and cold wallet balance is not available' do
|
||||
before do
|
||||
# Hot wallet balance is full and cold wallet balance is not available.
|
||||
Wallet.any_instance.stubs(:current_balance).returns(hot_wallet.max_balance, 'N/A')
|
||||
end
|
||||
|
||||
it 'spreads everything to cold wallet' do
|
||||
expect(Wallet.active.withdraw.joins(:currencies).where(currencies: { id: deposit.currency_id }).count).to eq 2
|
||||
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'hot wallet is full, warm and cold wallet balances are not available' do
|
||||
let!(:warm_wallet) { create(:wallet, :fake_warm) }
|
||||
before do
|
||||
# Hot wallet is full, warm and cold wallet balances are not available.
|
||||
Wallet.any_instance.stubs(:current_balance).returns(hot_wallet.max_balance, 'N/A', 'N/A')
|
||||
end
|
||||
|
||||
it 'skips warm wallet and spreads everything to cold wallet' do
|
||||
expect(Wallet.active.withdraw.joins(:currencies).where(currencies: { id: deposit.currency_id }).count).to eq 3
|
||||
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'there is no active wallets' do
|
||||
before { Wallet.stubs(:active).returns(Wallet.none) }
|
||||
|
||||
it 'raises an error' do
|
||||
expect{ subject }.to raise_error(StandardError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'currency price recalculation' do
|
||||
let(:deposit) { create(:deposit_btc, amount: amount, currency: currency) }
|
||||
|
||||
context 'collect to hot wallet' do
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'fake-hot',
|
||||
status: 'pending',
|
||||
amount: deposit.amount.to_s,
|
||||
currency_id: currency.id }]
|
||||
end
|
||||
|
||||
before do
|
||||
# Deposit with amount 2 and currency price 42
|
||||
hot_wallet.update!(max_balance: 100)
|
||||
deposit.currency.update!(price: 42)
|
||||
# Hot wallet balance is empty
|
||||
Wallet.any_instance.stubs(:current_balance).with(deposit.currency).returns(0)
|
||||
Currency.any_instance.unstub(:price)
|
||||
end
|
||||
|
||||
it 'skip hot wallet and collect to cold' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'collect to cold wallet' do
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'fake-cold',
|
||||
status: 'pending',
|
||||
amount: deposit.amount.to_s,
|
||||
currency_id: currency.id }]
|
||||
end
|
||||
|
||||
before do
|
||||
# Hot wallet balance is ful.
|
||||
deposit.currency.update!(price: 42)
|
||||
Wallet.any_instance.stubs(:current_balance).with(deposit.currency).returns(deposit.amount)
|
||||
Currency.any_instance.unstub(:price)
|
||||
end
|
||||
|
||||
it 'skip hot wallet and collect to cold' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'split to hot and cold wallet' do
|
||||
let(:expected_spread) do
|
||||
[{ to_address: 'fake-hot',
|
||||
status: 'pending',
|
||||
amount: '1.38095238',
|
||||
currency_id: currency.id },
|
||||
{ to_address: 'fake-cold',
|
||||
status: 'pending',
|
||||
amount: '0.61904762',
|
||||
currency_id: currency.id }]
|
||||
end
|
||||
|
||||
before do
|
||||
# Deposit with amount 2 and currency price 42
|
||||
hot_wallet.update!(max_balance: 100)
|
||||
# Hot wallet balance is full and cold wallet balance is not available.
|
||||
deposit.currency.update!(price: 42)
|
||||
Wallet.any_instance.stubs(:current_balance).with(deposit.currency).returns(deposit.amount / 2)
|
||||
Currency.any_instance.unstub(:price)
|
||||
end
|
||||
|
||||
it 'skip hot wallet and collect to cold' do
|
||||
expect(subject.map(&:as_json).map(&:symbolize_keys)).to contain_exactly(*expected_spread)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context :collect_deposit do
|
||||
let!(:deposit_wallet) { create(:wallet, :fake_deposit) }
|
||||
let!(:hot_wallet) { create(:wallet, :fake_hot) }
|
||||
let!(:cold_wallet) { create(:wallet, :fake_cold) }
|
||||
|
||||
let(:amount) { 2 }
|
||||
let(:deposit) { create(:deposit_btc, amount: amount, currency: currency) }
|
||||
|
||||
let(:fake_wallet_adapter) { FakeWallet.new }
|
||||
let(:service) { WalletService.new(deposit_wallet) }
|
||||
|
||||
context 'Spread deposit with single entry' do
|
||||
|
||||
let(:spread_deposit) do
|
||||
[Peatio::Transaction.new(to_address: 'fake-cold',
|
||||
amount: '2.0',
|
||||
currency_id: currency.id)]
|
||||
end
|
||||
|
||||
let(:transaction) do
|
||||
[Peatio::Transaction.new(hash: '0xfake',
|
||||
to_address: cold_wallet.address,
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id)]
|
||||
end
|
||||
|
||||
subject { service.collect_deposit!(deposit, spread_deposit) }
|
||||
|
||||
before do
|
||||
service.adapter.expects(:create_transaction!).returns(transaction.first)
|
||||
end
|
||||
|
||||
it 'creates single transaction' do
|
||||
expect(subject).to contain_exactly(*transaction)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
|
||||
context 'Spread deposit with two entry' do
|
||||
|
||||
let(:spread_deposit) do
|
||||
[Peatio::Transaction.new(to_address: 'fake-hot',
|
||||
amount: '2.0',
|
||||
currency_id: currency.id),
|
||||
Peatio::Transaction.new(to_address: 'fake-hot',
|
||||
amount: '2.0',
|
||||
currency_id: currency.id)]
|
||||
end
|
||||
|
||||
let(:transaction) do
|
||||
[{ hash: '0xfake',
|
||||
to_address: hot_wallet.address,
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id },
|
||||
{ hash: '0xfake1',
|
||||
to_address: cold_wallet.address,
|
||||
amount: deposit.amount,
|
||||
currency_id: currency.id }].map { |t| Peatio::Transaction.new(t)}
|
||||
end
|
||||
|
||||
subject { service.collect_deposit!(deposit, spread_deposit) }
|
||||
|
||||
before do
|
||||
service.adapter.expects(:create_transaction!).with(spread_deposit.first, subtract_fee: true).returns(transaction.first)
|
||||
service.adapter.expects(:create_transaction!).with(spread_deposit.second, subtract_fee: true).returns(transaction.second)
|
||||
end
|
||||
|
||||
it 'creates two transactions' do
|
||||
expect(subject).to contain_exactly(*transaction)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context :deposit_collection_fees do
|
||||
let!(:fee_wallet) { create(:wallet, :fake_fee) }
|
||||
let!(:deposit_wallet) { create(:wallet, :fake_deposit) }
|
||||
|
||||
let(:amount) { 2 }
|
||||
let(:deposit) { create(:deposit_btc, amount: amount, currency: currency) }
|
||||
|
||||
let(:fake_wallet_adapter) { FakeWallet.new }
|
||||
let(:service) { WalletService.new(fee_wallet) }
|
||||
|
||||
let(:spread_deposit) do
|
||||
[Peatio::Transaction.new(to_address: 'fake-cold',
|
||||
amount: '2.0',
|
||||
currency_id: currency.id)]
|
||||
end
|
||||
|
||||
let(:transactions) do
|
||||
[Peatio::Transaction.new( hash: '0xfake',
|
||||
to_address: deposit.address,
|
||||
amount: '0.01',
|
||||
currency_id: currency.id,
|
||||
options: { gas_limit: 21_000, gas_price: 10_000_000_000 })]
|
||||
end
|
||||
|
||||
subject { service.deposit_collection_fees!(deposit, spread_deposit) }
|
||||
|
||||
context 'Adapter collect fees for transaction' do
|
||||
before do
|
||||
deposit.update!(spread: spread_deposit.map(&:as_json))
|
||||
service.adapter.expects(:prepare_deposit_collection!).returns(transactions)
|
||||
end
|
||||
|
||||
it 'returns transaction' do
|
||||
expect(subject).to contain_exactly(*transactions)
|
||||
expect(subject).to all(be_a(Peatio::Transaction))
|
||||
deposit.spread.map { |s| s.key?(:options) }
|
||||
end
|
||||
end
|
||||
|
||||
context "Adapter doesn't perform any actions before collect deposit" do
|
||||
|
||||
it 'retunrs empty array' do
|
||||
expect(subject.blank?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user