All files / src/powerup abstract.ts

98.48% Statements 65/66
76.47% Branches 13/17
100% Functions 10/10
98.46% Lines 64/65

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141130x                   1x   1x     62x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x   62x 62x           5x         7x         16x         15x 15x 15x 15x         15x 15x 15x 15x       15x 15x 15x   15x         3x       3x 3x     3x       3x       3x         15x   15x 15x   15x 15x 15x       15x           15x   15x 3x   15x         17x 17x 17x 17x 17x 17x 17x 17x 17x 17x   17x      
import {
    Asset,
    Float64,
    Int64,
    Struct,
    TimePointSec,
    UInt128,
    UInt32,
    UInt64,
    UInt8,
} from '@wharfkit/antelope'
 
import {intToBigDecimal} from '..'
import {PowerUpStateOptions} from './options'
 
export abstract class PowerUpStateResource extends Struct {
    @Struct.field('uint8') version!: UInt8
    @Struct.field('int64') weight!: Int64
    @Struct.field('int64') weight_ratio!: Int64
    @Struct.field('int64') assumed_stake_weight!: Int64
    @Struct.field('int64') initial_weight_ratio!: Int64
    @Struct.field('int64') target_weight_ratio!: Int64
    @Struct.field('time_point_sec') initial_timestamp!: TimePointSec
    @Struct.field('time_point_sec') target_timestamp!: TimePointSec
    @Struct.field('float64') exponent!: Float64
    @Struct.field('uint32') decay_secs!: UInt32
    @Struct.field('asset') min_price!: Asset
    @Struct.field('asset') max_price!: Asset
    @Struct.field('int64') utilization!: Int64
    @Struct.field('int64') adjusted_utilization!: Int64
    @Struct.field('time_point_sec') utilization_timestamp!: TimePointSec
 
    readonly default_block_cpu_limit: UInt64 = UInt64.from(200000)
    readonly default_block_net_limit: UInt64 = UInt64.from(1048576000)
 
    abstract per_day(options?: PowerUpStateOptions): number
 
    // Get the current number of allocated units (shift from REX -> PowerUp)
    public get allocated(): number {
        return 1 - Number(this.weight_ratio.dividing(this.target_weight_ratio)) / 100
    }
 
    // Get the current percentage of reserved units
    public get reserved(): Int64 {
        return this.utilization.dividing(this.weight)
    }
 
    // Get the symbol definition for the token
    public get symbol() {
        return this.min_price.symbol
    }
 
    // Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L358
    utilization_increase(frac: UInt128) {
        const base = intToBigDecimal(frac)
        const weight = intToBigDecimal(this.weight)
        const multiplier = intToBigDecimal(Math.pow(10, 15))
        return UInt128.from(base.multiply(weight).divide(multiplier, 15).ceil().getValue())
    }
 
    // Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L284-L298
    price_function(utilization: Int64): number {
        const {weight} = this
        let price = this.min_price.value
        const new_exponent = Number(this.exponent) - 1.0
        Iif (new_exponent <= 0.0) {
            return this.max_price.value
        } else {
            // const util_weight = utilization.dividing(weight)
            const util_weight = intToBigDecimal(utilization).divide(intToBigDecimal(weight), 18)
            const difference = this.max_price.value - this.min_price.value
            price += difference * Math.pow(Number(util_weight.getValue()), new_exponent)
        }
        return price
    }
 
    // Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L274-L280
    price_integral_delta(start_utilization: Int64, end_utilization: Int64): number {
        const difference = Asset.fromUnits(
            this.max_price.units.subtracting(this.min_price.units),
            this.symbol
        )
        const coefficient = difference.value / this.exponent.value
        const start_u = Number(
            intToBigDecimal(start_utilization).divide(intToBigDecimal(this.weight), 18).getValue()
        )
        const end_u = Number(
            intToBigDecimal(end_utilization).divide(intToBigDecimal(this.weight), 18).getValue()
        )
        const delta =
            this.min_price.value * end_u -
            this.min_price.value * start_u +
            coefficient * Math.pow(end_u, this.exponent.value) -
            coefficient * Math.pow(start_u, this.exponent.value)
        return delta
    }
 
    // Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L262-L315
    fee(utilization_increase: UInt128, adjusted_utilization: Int64) {
        const {utilization, weight} = this
 
        let start_utilization = Int64.from(utilization)
        const end_utilization = start_utilization.adding(utilization_increase)
 
        let fee = 0
        if (start_utilization.lt(adjusted_utilization)) {
            const min = Math.min(
                Number(utilization_increase),
                Number(adjusted_utilization.subtracting(start_utilization))
            )
            fee += Number(
                intToBigDecimal(this.price_function(adjusted_utilization) * min)
                    .divide(intToBigDecimal(weight), 18)
                    .getValue()
            )
 
            start_utilization = adjusted_utilization
        }
        if (start_utilization.lt(end_utilization)) {
            fee += this.price_integral_delta(start_utilization, end_utilization)
        }
        return fee
    }
 
    // Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L105-L117
    determine_adjusted_utilization(options?: PowerUpStateOptions) {
        const {decay_secs, utilization, utilization_timestamp} = this
        let {adjusted_utilization} = this
        if (utilization.lt(adjusted_utilization)) {
            const ts = options && options.timestamp ? options.timestamp : new Date()
            const now = TimePointSec.from(ts).toMilliseconds() / 1000
            const utilization_ts = utilization_timestamp.toMilliseconds() / 1000
            const diff = adjusted_utilization.subtracting(utilization).toNumber()
            let delta: number = diff * Math.exp(-(now - utilization_ts) / Number(decay_secs))
            delta = Math.min(Math.max(delta, 0), diff)
            adjusted_utilization = utilization.adding(delta)
        }
        return adjusted_utilization
    }
}