All files / src/chain time.ts

93.61% Statements 44/47
100% Branches 10/10
88.88% Functions 24/27
93.61% Lines 44/47

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 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177                                      1x         115x 44x   71x   1x   70x 3x   67x 59x     8x           59x 59x 1x   58x           3x                 38x 38x       6x 6x               12x       11x           1x     45x       2x       2x         49x 49x       4x       14x           1x     19x       6x       4x         29x 29x       6x       19x         1x     6x               1x         7x 7x       2x       3x      
import {ABIDecoder} from '../serializer/decoder'
import {ABIEncoder} from '../serializer/encoder'
import {ABISerializableObject} from '../serializer/serializable'
import {isInstanceOf} from '../utils'
 
import {AnyInt, Int64, Int64Type, UInt32, UInt32Type, UInt64} from '../'
 
export type TimePointType = TimePoint | TimePointSec | string | Date | AnyInt
 
interface TimePointConstructor {
    from(value: TimePointType): TimePointBase
    fromInteger(value: AnyInt): TimePointBase
    fromDate(value: Date): TimePointBase
    fromString(value: string): TimePointBase
    fromMilliseconds(value: number): TimePointBase
    new (...args: any[]): TimePointBase
}
 
class TimePointBase implements ABISerializableObject {
    static abiName = '__time_point_base'
 
    static from<T extends TimePointConstructor>(this: T, value: TimePointType): InstanceType<T>
    static from(value: TimePointType): unknown
    static from(this: TimePointConstructor, value: TimePointType) {
        if (isInstanceOf(value, this)) {
            return value
        }
        if (isInstanceOf(value, TimePointBase)) {
            // converting between types
            return this.fromMilliseconds(value.toMilliseconds())
        }
        if (isInstanceOf(value, Date)) {
            return this.fromDate(value)
        }
        if (typeof value === 'string') {
            return this.fromString(value)
        }
 
        return this.fromInteger(value)
    }
 
    static fromString<T extends TimePointConstructor>(this: T, string: string): InstanceType<T>
    static fromString(string: string): unknown
    static fromString(this: TimePointConstructor, string: string) {
        const value = Date.parse(string + 'Z')
        if (!Number.isFinite(value)) {
            throw new Error('Invalid date string')
        }
        return this.fromMilliseconds(value)
    }
 
    static fromDate<T extends TimePointConstructor>(this: T, date: Date): InstanceType<T>
    static fromDate(date: Date): unknown
    static fromDate(this: TimePointConstructor, date: Date) {
        return this.fromMilliseconds(date.getTime())
    }
 
    static abiDefault<T extends TimePointConstructor>(this: T): InstanceType<T>
    static abiDefault(): unknown {
        return this.from(0)
    }
 
    toABI(encoder: ABIEncoder) {
        const self = this as any
        self.value.toABI(encoder)
    }
 
    equals(other: TimePointType) {
        const self = this.constructor as TimePointConstructor
        return this.toMilliseconds() === self.from(other).toMilliseconds()
    }
 
    toMilliseconds(): number {
        throw new Error('Not implemented')
    }
 
    toDate() {
        return new Date(this.toMilliseconds())
    }
 
    toJSON() {
        return this.toString()
    }
}
 
/** Timestamp with microsecond accuracy. */
export class TimePoint extends TimePointBase {
    static abiName = 'time_point'
 
    static fromMilliseconds(ms: number) {
        return new this(Int64.from(Math.round(ms * 1000)))
    }
 
    static fromInteger(value: Int64Type) {
        return new this(Int64.from(value))
    }
 
    static fromABI(decoder: ABIDecoder) {
        return new this(Int64.fromABI(decoder))
    }
 
    value: Int64
    constructor(value: Int64) {
        super()
        this.value = value
    }
 
    toString() {
        return this.toDate().toISOString().slice(0, -1)
    }
 
    toMilliseconds() {
        return Number(this.value.dividing(1000, 'round'))
    }
}
 
/** Timestamp with second accuracy. */
export class TimePointSec extends TimePointBase {
    static abiName = 'time_point_sec'
 
    static fromMilliseconds(ms: number) {
        return new this(UInt32.from(Math.round(ms / 1000)))
    }
 
    static fromInteger(value: UInt32Type) {
        return new this(UInt32.from(value))
    }
 
    static fromABI(decoder: ABIDecoder) {
        return new this(UInt32.fromABI(decoder))
    }
 
    value: UInt32
    constructor(value: UInt32) {
        super()
        this.value = value
    }
 
    toString() {
        return this.toDate().toISOString().slice(0, -5)
    }
 
    toMilliseconds() {
        return Number(this.value.cast(UInt64).multiplying(1000))
    }
}
 
export class BlockTimestamp extends TimePointBase {
    static abiName = 'block_timestamp_type'
 
    static fromMilliseconds(ms: number) {
        return new this(UInt32.from(Math.round((ms - 946684800000) / 500)))
    }
 
    static fromInteger(value: UInt32Type) {
        return new this(UInt32.from(value))
    }
 
    static fromABI(decoder: ABIDecoder) {
        return new this(UInt32.fromABI(decoder))
    }
 
    value: UInt32
    constructor(value: UInt32) {
        super()
        this.value = value
    }
 
    toString() {
        return this.toDate().toISOString().slice(0, -1)
    }
 
    toMilliseconds() {
        return Number(this.value.cast(UInt64).multiplying(500).adding(946684800000))
    }
}