All files identity-proof.ts

82.85% Statements 29/35
60% Branches 15/25
87.5% Functions 7/8
81.81% Lines 27/33

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 12983x                                 1x   1x 1x 1x 1x                           2x 1x 1x 1x 1x 1x     4x   4x 1x   3x                 1x 1x     1x 1x                                             1x           1x                       1x                 2x 2x                   2x 2x      
import {
    Action,
    Authority,
    AuthorityType,
    isInstanceOf,
    Name,
    NameType,
    PermissionLevel,
    PermissionLevelType,
    PublicKey,
    Serializer,
    Signature,
    SignatureType,
    Struct,
    TimePointSec,
    TimePointType,
    Transaction,
} from '@wharfkit/antelope'
 
import {IdentityV3} from './abi'
import {ChainId, ChainIdType} from './chain-id'
import {CallbackPayload, SigningRequest, SigningRequestEncodingOptions} from './signing-request'
import * as Base64u from './base64u'
 
export type IdentityProofType =
    | IdentityProof
    | string
    | {
          chainId: ChainIdType
          scope: NameType
          expiration: TimePointType
          signer: PermissionLevelType
          signature: SignatureType
      }
 
@Struct.type('identity_proof')
export class IdentityProof extends Struct {
    @Struct.field(ChainId) chainId!: ChainId
    @Struct.field(Name) scope!: Name
    @Struct.field(TimePointSec) expiration!: TimePointSec
    @Struct.field(PermissionLevel) signer!: PermissionLevel
    @Struct.field(Signature) signature!: Signature
 
    static from(value: IdentityProofType): IdentityProof {
        Iif (isInstanceOf(value, IdentityProof)) {
            return value
        } else if (typeof value === 'string') {
            return IdentityProof.fromString(value)
        } else {
            return super.from(value) as IdentityProof
        }
    }
 
    /**
     * Create a new instance from an EOSIO authorization header string.
     * "EOSIO <base64payload>"
     */
    static fromString(string: string) {
        const parts = string.split(' ')
        Iif (parts.length !== 2 || parts[0] !== 'EOSIO') {
            throw new Error('Invalid IdentityProof string')
        }
        const data = Base64u.decode(parts[1])
        return Serializer.decode({data, type: IdentityProof})
    }
 
    /** Create a new instance from a callback payload. */
    static fromPayload(payload: CallbackPayload, options: SigningRequestEncodingOptions = {}) {
        const request = SigningRequest.from(payload.req, options)
        Iif (!(request.version >= 3 && request.isIdentity())) {
            throw new Error('Not an identity request')
        }
        return this.from({
            chainId: payload.cid || request.getChainId(),
            scope: request.getIdentityScope()!,
            expiration: payload.ex,
            signer: {actor: payload.sa, permission: payload.sp},
            signature: payload.sig,
        })
    }
 
    /**
     * Transaction this proof resolves to.
     * @internal
     */
    get transaction(): Transaction {
        const action = Action.from({
            account: '',
            name: 'identity',
            authorization: [this.signer],
            data: IdentityV3.from({scope: this.scope, permission: this.signer}),
        })
        return Transaction.from({
            ref_block_num: 0,
            ref_block_prefix: 0,
            expiration: this.expiration,
            actions: [action],
        })
    }
 
    /**
     * Recover the public key that signed this proof.
     */
    recover(): PublicKey {
        return this.signature.recoverDigest(this.transaction.signingDigest(this.chainId))
    }
 
    /**
     * Verify that given authority signed this proof.
     * @param auth The accounts signing authority.
     * @param currentTime Time to verify expiry against, if unset will use system time.
     */
    verify(auth: AuthorityType, currentTime?: TimePointType) {
        const now = TimePointSec.from(currentTime || new Date()).toMilliseconds()
        return (
            now < this.expiration.toMilliseconds() &&
            Authority.from(auth).hasPermission(this.recover())
        )
    }
 
    /**
     * Encode the proof to an `EOSIO` auth header string.
     */
    toString() {
        const data = Serializer.encode({object: this})
        return `EOSIO ${Base64u.encode(data.array, false)}`
    }
}