All files / src utils.ts

94.2% Statements 65/69
83.33% Branches 20/24
100% Functions 7/7
93.75% Lines 60/64

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        356x 356x 3x   353x 9352x 14x     339x       9x 9x 1x   8x 6x 1x     7x     1x   1x 1x 1x 256x 256x 256x         17868x     17868x 17868x 17868x 988288x   17868x       2747x 1x   2747x     2747x 2x   2745x 2745x 2745x 2745x 418717x 418717x 3x   418714x   2742x         5x       1x             144819x 29256x   115563x 28514x       87049x 87049x 2366x   84683x 84683x 84683x 85537x 85537x 84683x   854x 854x   84683x             84683x    
import {randomBytes} from '@noble/hashes/utils.js'
import {ABISerializableObject} from './serializer/serializable'
 
export function arrayEquals(a: ArrayLike<number>, b: ArrayLike<number>) {
    const len = a.length
    if (len !== b.length) {
        return false
    }
    for (let i = 0; i < len; i++) {
        if (a[i] !== b[i]) {
            return false
        }
    }
    return true
}
 
export function arrayEquatableEquals(a: ABISerializableObject[], b: ABISerializableObject[]) {
    const len = a.length
    if (len !== b.length) {
        return false
    }
    for (let i = 0; i < len; i++) {
        if (!a[i].equals(b[i])) {
            return false
        }
    }
    return true
}
 
const hexLookup: {enc?: Array<string>; dec?: Record<string, number>} = {}
function buildHexLookup() {
    hexLookup.enc = new Array<string>(0xff)
    hexLookup.dec = {}
    for (let i = 0; i <= 0xff; ++i) {
        const b = i.toString(16).padStart(2, '0')
        hexLookup.enc[i] = b
        hexLookup.dec[b] = i
    }
}
 
export function arrayToHex(array: ArrayLike<number>) {
    Iif (!hexLookup.enc) {
        buildHexLookup()
    }
    const len = array.length
    const rv = new Array<string>(len)
    for (let i = 0; i < len; ++i) {
        rv[i] = hexLookup.enc![array[i]]
    }
    return rv.join('')
}
 
export function hexToArray(hex: string) {
    if (!hexLookup.dec) {
        buildHexLookup()
    }
    Iif (typeof hex !== 'string') {
        throw new Error('Expected string containing hex digits')
    }
    if (hex.length % 2) {
        throw new Error('Odd number of hex digits')
    }
    hex = hex.toLowerCase()
    const len = hex.length / 2
    const result = new Uint8Array(len)
    for (let i = 0; i < len; i++) {
        const b = hexLookup.dec![hex[i * 2] + hex[i * 2 + 1]]
        if (b === undefined) {
            throw new Error('Expected hex string')
        }
        result[i] = b
    }
    return result
}
 
/** Generate N random bytes, throws if a secure random source isn't available. */
export function secureRandom(length: number): Uint8Array {
    return randomBytes(length)
}
 
/** Used in isInstanceOf checks so we don't spam with warnings. */
let didWarn = false
 
/** Check if object in instance of class. */
export function isInstanceOf<T extends {new (...args: any[]): InstanceType<T>}>(
    object: any,
    someClass: T
): object is InstanceType<T> {
    if (object instanceof someClass) {
        return true
    }
    if (object == null || typeof object !== 'object') {
        return false
    }
    // not an actual instance but since bundlers can fail to dedupe stuff or
    // multiple versions can be included we check for compatibility if possible
    const className = someClass['__className'] || someClass['abiName']
    if (!className) {
        return false
    }
    let instanceClass = object.constructor
    let isAlienInstance = false
    while (instanceClass && !isAlienInstance) {
        const instanceClassName = instanceClass['__className'] || instanceClass['abiName']
        if (!instanceClassName) {
            break
        }
        isAlienInstance = className == instanceClassName
        instanceClass = Object.getPrototypeOf(instanceClass)
    }
    Iif (isAlienInstance && !didWarn) {
        // eslint-disable-next-line no-console
        console.warn(
            `Detected alien instance of ${className}, this usually means more than one version of @wharfkit/antelope has been included in your bundle.`
        )
        didWarn = true
    }
    return isAlienInstance
}