import { assembleBytecodeBCH, disassembleBytecodeBCH, base58AddressToLockingBytecode, cashAddressToLockingBytecode, binToHex, hexToBin, isHex, } from '@bitauth/libauth'; /** * Script Entity. */ export class Script { public readonly bytes: Uint8Array; /** * Construct a new Script * * @param bytes {Uint8Array} The raw bytes of the Script. */ constructor(bytes: Uint8Array) { this.bytes = bytes; } /** * Create a Script Entity from the given Assembly String. * * @param asm {string} String of assembly code. * * @throws {Error} If script cannot be decoded. * * @returns {Script} The created Script Entity. */ public static fromASM(asm: string): Script { // Attempt to convert the given ASM to bytecode. const assembleResult = assembleBytecodeBCH(asm); // If a string is returned, this indicates an error... if (typeof assembleResult === 'string') { throw new Error(assembleResult); } // If the success flag is not marked, this indicates an error... if (!assembleResult.success) { throw new Error('Could not assemble bytecode from assembly.'); } // Return new Script Entity from the assembled bytecode. return new Script(assembleResult.bytecode); } /** * Create a Script Entity from the given bytes (as hexadecimal string). * * @param hex {string} Raw script bytes encoded as hexadecimal. * * @throws {Error} If script cannot be decoded. * * @returns {Script} The created Script Entity. */ public static fromHex(hex: string): Script { // Ensure that the given string is hex. if (!isHex(hex)) { throw new Error(`The given string (${hex}) is not valid hexadecimal.`); } // Conver the given hex to binary (Uint8Array). const scriptBin = hexToBin(hex); // Return new Script entity constructed from the binary. return new Script(scriptBin); } /** * Create a Script Entity from the given CashAddr. * * @param cashAddr {string} The Address in CashAddr format. * * @throws {Error} If address cannot be decoded. * * @returns {Script} The created Script Entity. */ public static fromCashAddr(cashAddr: string): Script { const decodeResult = cashAddressToLockingBytecode(cashAddr); if (typeof decodeResult === 'string') { throw new Error(decodeResult); } return new Script(decodeResult.bytecode); } /** * Create a Script Entity from the given Legacy Address. * * @param legacyAddress {string} The Address in Legacy format. * * @throws {Error} If address cannot be decoded. * * @returns {Script} The created Script Entity. */ public static fromLegacyAddress(legacyAddress: string): Script { const decodeResult = base58AddressToLockingBytecode(legacyAddress); if (typeof decodeResult === 'string') { throw new Error(decodeResult); } return new Script(decodeResult.bytecode); } /** * Convert this script to a human-readable string of assembly. * * @returns {string} Human-readable assembly. */ public toASM(joinWith = '\n'): string { const disassembledBytecode = disassembleBytecodeBCH(this.bytes); if (joinWith) { return disassembledBytecode.split(' ').join(joinWith); } return disassembledBytecode; } /** * Get the raw bytecode for this script. * * @returns {Uint8Array} The compiled bytes. */ public toBytes(): Uint8Array { return this.bytes; } /** * Get the raw bytecode for this script as a hex string. * * @returns {string} The compiled bytes as a hex string. */ public toHex(): string { return binToHex(this.bytes); } }