All files / src/chain authority.ts

94.28% Statements 33/35
85.71% Branches 6/7
90.9% Functions 10/11
96.66% Lines 29/30

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                              2x     2x 1x 1x       2x 1x 1x       2x 1x 1x                         2x 1x 1x 1x 1x     24x     24x           24x 24x         3x         3x         9x 5x                   5x 5x 5x               24x 24x 24x      
import {
    PermissionLevel,
    PermissionLevelType,
    PublicKey,
    PublicKeyType,
    Struct,
    TypeAlias,
    UInt16,
    UInt16Type,
    UInt32,
    UInt32Type,
} from '../'
import {isInstanceOf} from '../utils'
 
@TypeAlias('weight_type')
export class Weight extends UInt16 {}
 
@Struct.type('key_weight')
export class KeyWeight extends Struct {
    @Struct.field(PublicKey) key!: PublicKey
    @Struct.field(Weight) weight!: Weight
}
 
@Struct.type('permission_level_weight')
export class PermissionLevelWeight extends Struct {
    @Struct.field(PermissionLevel) permission!: PermissionLevel
    @Struct.field(Weight) weight!: Weight
}
 
@Struct.type('wait_weight')
export class WaitWeight extends Struct {
    @Struct.field(UInt32) wait_sec!: UInt32
    @Struct.field(Weight) weight!: Weight
}
 
export type AuthorityType =
    | Authority
    | {
          threshold: UInt32Type
          keys?: {key: PublicKeyType; weight: UInt16Type}[]
          accounts?: {permission: PermissionLevelType; weight: UInt16Type}[]
          waits?: {wait_sec: UInt32Type; weight: UInt16Type}[]
      }
 
@Struct.type('authority')
export class Authority extends Struct {
    @Struct.field(UInt32) threshold!: UInt32
    @Struct.field(KeyWeight, {array: true}) keys!: KeyWeight[]
    @Struct.field(PermissionLevelWeight, {array: true}) accounts!: PermissionLevelWeight[]
    @Struct.field(WaitWeight, {array: true}) waits!: WaitWeight[]
 
    static from(value: AuthorityType): Authority {
        Iif (isInstanceOf(value, Authority)) {
            return value
        }
        const rv = super.from({
            keys: [],
            accounts: [],
            waits: [],
            ...value,
        }) as Authority
        rv.sort()
        return rv
    }
 
    /** Total weight of all waits. */
    get waitThreshold(): number {
        return this.waits.reduce((val, wait) => val + wait.weight.toNumber(), 0)
    }
 
    /** Weight a key needs to sign for this authority. */
    get keyThreshold(): number {
        return this.threshold.toNumber() - this.waitThreshold
    }
 
    /** Return the weight for given public key, or zero if it is not included in this authority. */
    keyWeight(publicKey: PublicKeyType): number {
        const weight = this.keys.find(({key}) => key.equals(publicKey))
        return weight ? weight.weight.toNumber() : 0
    }
 
    /**
     * Check if given public key has permission in this authority,
     * @attention Does not take indirect permissions for the key via account weights into account.
     * @param publicKey The key to check.
     * @param includePartial Whether to consider auths where the key is included but can't be reached alone (e.g. multisig).
     */
    hasPermission(publicKey: PublicKeyType, includePartial = false): boolean {
        const threshold = includePartial ? 1 : this.keyThreshold
        const weight = this.keyWeight(publicKey)
        return weight >= threshold
    }
 
    /**
     * Sorts the authority weights in place, should be called before including the authority in a `updateauth` action or it might be rejected.
     */
    sort() {
        // This hack satisfies the constraints that authority weights, see: https://github.com/wharfkit/antelope/issues/8
        this.keys.sort((a, b) => String(a.key).localeCompare(String(b.key)))
        this.accounts.sort((a, b) => String(a.permission).localeCompare(String(b.permission)))
        this.waits.sort((a, b) => String(a.wait_sec).localeCompare(String(b.wait_sec)))
    }
}