Class: Istox::OrderBookProrate

Inherits:
Object
  • Object
show all
Defined in:
lib/istox/helpers/order_book_prorate.rb

Class Method Summary collapse

Class Method Details

.allocation(token_price:, min_investment:, bid_block:, invest_step:, hard_cap:, investments:) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/istox/helpers/order_book_prorate.rb', line 4

def allocation(token_price:, min_investment:, bid_block:,
               invest_step:, hard_cap:, investments:)

  # sort by id asc
  interests = investments.sort do |a, b|
    a[:id] <=> b[:id]
  end
  total_interests = 0

  max_allowed_investor = Istox::FMath.round_down(::Istox::FMath.div(hard_cap, min_investment), 0).to_i

  interests.each_with_index.map do |interest, i|
    total_interests = ::Istox::FMath.add(total_interests, interest[:fiat_amount]) if i < max_allowed_investor
  end

  # only need to handle when oversubscribe
  if total_interests.to_d > hard_cap.to_s.to_d

    # prorate the interests
    interests = interests.each_with_index.map do |interest, i|
      investment = if i < max_allowed_investor
                     result = ::Istox::FMath.round_down(::Istox::FMath.mul(::Istox::FMath.div(interest[:fiat_amount], total_interests),
                                                                           hard_cap), 0)
                     result = result.to_d - result.to_d.modulo(invest_step.to_s.to_d)

                     result = min_investment.to_d if result < min_investment.to_d

                     result
                   else
                     ::BigDecimal.new('0').to_s
                   end

      {
        id: interest[:id],
        investment: investment.to_s
      }
    end

    new_total_interests = '0'
    interests.each do |interest|
      new_total_interests = ::Istox::FMath.add(new_total_interests, interest[:investment])
    end

    # need to do adjustment if summation of new rounded values still larger than
    if new_total_interests.to_d > hard_cap.to_s.to_d
      total_deducting = ::Istox::FMath.sub(new_total_interests, hard_cap)
      interests.reverse_each do |interest|
        next unless interest[:investment].to_d > min_investment.to_d

        deductable = ::Istox::FMath.sub(interest[:investment], min_investment)

        if deductable.to_d > total_deducting.to_d
          interest[:investment] = ::Istox::FMath.sub(interest[:investment], total_deducting)
          total_deducting = 0
        else
          interest[:investment] = ::Istox::FMath.sub(interest[:investment], deductable)
          total_deducting = ::Istox::FMath.sub(total_deducting, deductable)
        end
      end
    end

    final_interests = interests

  else
    final_interests = interests.each_with_index.map do |interest, i|
      {
        id: interest[:id],
        investment: i < max_allowed_investor ? ::BigDecimal.new(interest[:fiat_amount].to_s).to_s : ::BigDecimal.new('0').to_s
      }
    end
  end

  {
    cutoff_price: token_price.to_s,
    interests: final_interests
  }
end