import * as base58 from 'base-58' ; import * as cryptoJS from 'crypto-js' ; import { ADDR_VERSION } from '../consts' ; import { ERROR_CODE } from '../error' ; import opcode from '../transaction/opcode' ; import { comparePublicKeys , programFromPubKey , pushBigInt } from '../transaction/program' ; import { pushHexString } from '../transaction/program' ; import { ab2hexstring , hash160 , num2hexstring , sha256 , StringReader } from '../utils' ; import { reverseHex } from './../utils' ; import { PublicKey } from './PublicKey' ; /**
 * Representation of Address.
 *
 * There are 4 types of address:
 * 1. Public key based
 * 2. Multi public key based (m, n)
 * 3. Contract based
 * 4. ONT ID based
 *
 * The value is stored as base58 or hex encoded, therefore always use
 * toBase58() or serialize() according to requirements.
 */ export class Address { static deserialize ( sr ) { return new Address ( sr . read ( 20 ) ) ; } param publicKey static fromPubKey ( publicKey ) { const program = programFromPubKey ( publicKey ) ; const programHash = hash160 ( program ) ; return new Address ( programHash ) ; } param ontid static fromOntid ( ontid ) { const address = ontid . substr ( 8 ) ; return new Address ( address ) ; } param vmCode static fromVmCode ( vmCode ) { const programHash = hash160 ( vmCode ) ; return new Address ( programHash ) ; } param m param publicKeys static fromMultiPubKeys ( m , publicKeys ) { const n = publicKeys . length ; if ( m <= 0 || m > n || n > 24 ) { throw ERROR_CODE . INVALID_PARAMS ; } publicKeys . sort ( comparePublicKeys ) ; let result = '' ; result += pushBigInt ( m ) ; for ( const s of publicKeys ) { result += pushHexString ( s . serializeHex ( ) ) ; } result += pushBigInt ( n ) ; result += num2hexstring ( opcode . CHECKMULTISIG ) ; const programHash = hash160 ( result ) ; return new Address ( programHash ) ; } /**
     * Deterministicaly generates ONT ID from this public key.
     */ static generateOntid ( publicKey ) { const address = Address . fromPubKey ( publicKey ) ; const ontid = 'did:ont:' + address . toBase58 ( ) ; return ontid ; } /**
     * Base58 or Hex encoded address
     */ value : string ; constructor ( value ) { if ( value . length === 40 || value . length === 34 ) { this . value = value ; } else { throw ERROR_CODE . INVALID_PARAMS ; } } /**
     * Gets Base58 encoded representation of the address.
     */ toBase58 ( ) { if ( this . value . length === 34 ) { return this . value ; } else { return hexToBase58 ( this . value ) ; } } /**
     * Gets Hex encoded representation of the address.
     */ toHexString ( ) { let val ; if ( this . value . length === 40 ) { val = this . value ; } else { val = base58ToHex ( this . value ) ; } return reverseHex ( val ) ; } serialize ( ) { if ( this . value . length === 40 ) { return this . value ; } else { return base58ToHex ( this . value ) ; } } /**
     * Computes the salt from address for decrypt.
     */ getB58Checksum ( ) { const address = this . toBase58 ( ) ; const hash = cryptoJS . SHA256 ( address ) . toString ( ) ; const hash2 = sha256 ( hash ) ; return hash2 . slice ( 0 , 8 ) ; } } param programhash function hexToBase58 ( hexEncoded ) { const data = ADDR_VERSION + hexEncoded ; const hash = sha256 ( data ) ; const hash2 = sha256 ( hash ) ; const checksum = hash2 . slice ( 0 , 8 ) ; const datas = data + checksum ; return base58 . encode ( new Buffer ( datas , 'hex' ) ) ; } function base58ToHex ( base58Encoded ) { const decoded = base58 . decode ( base58Encoded ) ; const hexEncoded = ab2hexstring ( decoded ) . substr ( 2 , 40 ) ; if ( base58Encoded !== hexToBase58 ( hexEncoded ) ) { throw new Error ( '[addressToU160] decode encoded verify failed' ) ; } return hexEncoded ; }