Files
Dena/spec/api/v2/management/beneficiaries_spec.rb
2026-08-13 19:50:53 +03:30

375 lines
11 KiB
Ruby

# encoding: UTF-8
# frozen_string_literal: true
describe API::V2::Management::Beneficiaries, type: :request do
before do
defaults_for_management_api_v1_security_configuration!
management_api_v1_security_configuration.merge! \
scopes: {
read_beneficiaries: { permitted_signers: %i[alex jeff], mandatory_signers: %i[alex] },
write_beneficiaries: { permitted_signers: %i[alex jeff], mandatory_signers: %i[alex] }
}
end
describe 'beneficiary list' do
def request
post_json '/api/v2/management/beneficiaries/list', multisig_jwt_management_api_v1({ data: beneficiary_data }, *signers)
end
let(:signers) { %i[alex jeff] }
let(:member) { create(:member, :level_3) }
let(:beneficiary_data) do
{
uid: member.uid,
}
end
let!(:pending_beneficiaries_for_member) do
create_list(:beneficiary, 2, member: member, state: :pending)
end
let!(:active_beneficiaries_for_member) do
create_list(:beneficiary, 3, member: member, state: :active)
end
let!(:archived_beneficiaries_for_member) do
create_list(:beneficiary, 2, member: member, state: :archived)
end
let!(:other_member_beneficiaries) do
create_list(:beneficiary, 5)
end
context 'missing required params' do
it do
beneficiary_data.except!(:uid)
request
expect(response.status).to eq 422
expect(JSON.parse(response.body)['error']).to match(/uid is missing/i)
end
end
context 'without currency and state' do
it do
request
expect(response.status).to eq 200
total_for_member = pending_beneficiaries_for_member.count + active_beneficiaries_for_member.count
expect(response_body.size).to eq total_for_member
end
end
context 'non-existing currency' do
it do
beneficiary_data.merge!(currency: :uah)
request
expect(response.status).to eq 422
expect(response.body).to match(/management.currency.doesnt_exist/i)
end
end
context 'existing currency' do
let!(:btc_beneficiaries_for_member) do
create_list(:beneficiary, 3, member: member)
end
it do
beneficiary_data.merge!(currency: :btc)
request
expect(response.status).to eq 200
expect(response_body.all? { |b| b['currency'] == 'btc' }).to be_truthy
end
context 'fiat currency' do
let!(:usd_beneficiary_for_member) { create(:beneficiary, currency: Currency.find('usd'), member: member) }
it do
beneficiary_data.merge!(currency: :usd)
request
expect(response.status).to eq 200
expect(response_body.all? { |b| b['currency'] == 'usd' }).to be_truthy
expect(usd_beneficiary_for_member.id).to eq response_body.first['id']
expect(usd_beneficiary_for_member.data[:account_number]).to eq response_body.first['data']['account_number']
end
end
end
context 'invalid state' do
it do
beneficiary_data.merge!(state: :invalid)
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.invalid_state/i)
end
end
context 'existing state' do
it do
beneficiary_data.merge!(state: :pending)
request
expect(response.status).to eq 200
expect(response_body.all? { |b| b['state'] == 'pending' }).to be_truthy
end
end
context 'both currency and state' do
let!(:active_btc_beneficiaries_for_member) do
create_list(:beneficiary, 3, member: member, state: :active)
end
it do
beneficiary_data.merge!(currency: :btc, state: :active)
request
expect(response.status).to eq 200
expect(response_body.all? { |b| b['currency'] == 'btc' && b['state'] == 'active' }).to be_truthy
end
end
end
describe 'create beneficiary' do
def request
post_json '/api/v2/management/beneficiaries', multisig_jwt_management_api_v1({ data: beneficiary_data }, *signers)
end
let(:signers) { %i[alex jeff] }
let(:member) { create(:member, :level_3) }
let(:beneficiary_data) do
{
currency: :btc,
name: 'Personal Bitcoin wallet',
description: 'Multisignature Bitcoin Wallet',
uid: member.uid,
state: 'active',
data: {
address: Faker::Blockchain::Bitcoin.address
}
}
end
context 'invalid params' do
context 'missing required params' do
%i[currency name data uid].each do |rp|
context rp do
it do
beneficiary_data.except!(rp)
request
expect(response.status).to eq 422
expect(JSON.parse(response.body)['error']).to match(/#{rp} is missing/i)
end
end
end
end
context 'currency doesn\'t exist' do
it do
beneficiary_data.merge!(currency: :uah)
request
expect(response.status).to eq 422
expect(response.body).to match(/management.currency.doesnt_exist/i)
end
end
context 'name is too long' do
it do
beneficiary_data.merge!(name: Faker::Lorem.sentence(500))
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.too_long_name/i)
end
end
context 'invalid state' do
it do
beneficiary_data.merge!(state: 'test')
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.invalid_state/i)
end
end
context 'description is too long' do
it do
beneficiary_data.merge!(description: Faker::Lorem.sentence(500))
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.too_long_description/i)
end
end
context 'data has invalid type' do
it do
beneficiary_data.merge!(data: 'data')
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.non_json_data/i)
end
end
context 'crypto beneficiary' do
context 'nil address in data' do
it do
beneficiary_data[:data][:address] = nil
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.missing_address_in_data/i)
end
end
context 'data without address' do
it do
beneficiary_data[:data].delete(:address)
beneficiary_data[:data][:memo] = :memo
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.missing_address_in_data/i)
end
end
context 'disabled withdrawal for currency' do
let(:currency) { Currency.find(:btc) }
before do
currency.update(withdrawal_enabled: false)
end
it do
request
expect(response.status).to eq 422
expect(response.body).to match(/management.currency.withdrawal_disabled/i)
end
end
context 'invalid character in address' do
before do
beneficiary_data[:data][:address] = "'" + Faker::Blockchain::Bitcoin.address
end
it do
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.failed_to_create/i)
end
end
context 'duplicated address' do
context 'same currency' do
before do
create(:beneficiary,
member: member,
currency_id: beneficiary_data[:currency],
data: {address: beneficiary_data.dig(:data, :address)})
end
it do
request
expect(response.status).to eq 422
expect(response.body).to match(/management.beneficiary.duplicate_address/i)
end
end
context 'different currencies' do
before do
create(:beneficiary,
member: member,
currency_id: :eth,
data: {address: beneficiary_data.dig(:data, :address)})
end
it do
request
expect(response.status).to eq 201
end
end
context 'truncates spaces in address' do
let(:address) { Faker::Blockchain::Bitcoin.address }
before do
beneficiary_data[:data][:address] = " " + address + " "
end
it do
request
expect(response.status).to eq 201
result = JSON.parse(response.body)
expect(Beneficiary.find(result['id']).data['address']).to eq(address)
end
end
end
context 'destination tag in address' do
before do
beneficiary_data[:data][:address] = Faker::Blockchain::Bitcoin.address + "?dt=4"
end
it do
request
expect(response.status).to eq 201
result = JSON.parse(response.body)
expect(Beneficiary.find(result['id']).data['address']).to eq(beneficiary_data[:data][:address])
end
end
context 'fiat beneficiary' do
let(:beneficiary_data) do
{
currency: :usd,
uid: member.uid,
name: Faker::Bank.name,
description: Faker::Company.catch_phrase,
data: generate(:fiat_beneficiary_data)
}
end
context 'nil address in data' do
it do
beneficiary_data[:data].except!(:address)
request
expect(response.status).to eq 201
expect(response_body['data']).to eq beneficiary_data[:data].with_indifferent_access
end
end
context 'nil data' do
it do
beneficiary_data[:data] = nil
request
expect(response.status).to eq 422
expect(JSON.parse(response.body)['error']).to match(/data is empty/i)
end
end
context 'duplicated address' do
context 'same currency' do
before do
create(:beneficiary,
member: member,
currency_id: beneficiary_data[:currency],
data: beneficiary_data[:data])
end
it do
request
expect(response.status).to eq 201
end
end
end
end
end
end
context 'valid params' do
it 'creates beneficiary for member' do
expect do
request
end.to change{ member.beneficiaries.count }.by(1)
end
it 'creates beneficiary with active state' do
request
expect(response.status).to eq 201
id = response_body['id']
expect(Beneficiary.find_by!(id: id).state).to eq 'active'
expect(Beneficiary.find_by!(id: id).data).to eq response_body['data']
end
end
end
end