import { Buffer } from "buffer/"; export function fromHex(hex: string): Buffer { return Buffer.from(hex, "hex"); } export function getScriptType(bytes: Buffer): string | null { if (isP2pk(bytes)) { return "P2PK"; } else if (isP2pkh(bytes)) { return "P2PKH"; } else if (isP2sh(bytes)) { return "P2SH"; } else if (isReturn(bytes)) { return "OP_RETURN"; } else { return null; } } export function takeScriptMessage(asmInput: string[]): string | null { try { let input = ""; for (let i = 0; i < asmInput.length; i++) { const asm = asmInput[i]; if (asm.startsWith("OP_PUSHBYTES_")) { input += asmInput[i + 1]; i++; } } if (input) { return Buffer.from(input, "hex").toString("ascii").trim(); } else { return null; } } catch (e) { return null; } } export function hexToAsm(bytes: Buffer) { const out = []; // adapted from https://gist.github.com/rsbondi/674ec5ac823a244b889773be57304f85 for (let i = 0; i < bytes.length; i++) { const byte = bytes[i]; if (byte >= 0x52 && byte <= 0x60) { out.push((byte - 0x50).toString(16)); continue; } if (byte >= 0x02 && byte <= 0x4b) { out.push("OP_PUSHBYTES_" + byte); out.push(bytes.slice(i + 1, i + 1 + byte).toString("hex")); i += byte; continue; } out.push(Operation[byte] || byte.toString(16)); } return out; } export function briefHexToAsm(hex: Buffer) { const asm = hexToAsm(hex); const OP_RETURN = Operation[Operation.OP_RETURN]; for (const op of asm) { if (op === OP_RETURN) { return [OP_RETURN]; } } return asm; } function isP2sh(bytes: Buffer): boolean { return ( bytes.length === 23 && bytes[0] == Operation["OP_HASH160"] && bytes[1] == 0x14 && // Operation["OP_PUSHBYTES_20"] bytes[22] == Operation["OP_EQUAL"] ); } function isP2pkh(bytes: Buffer): boolean { return ( bytes.length == 25 && bytes[0] == Operation["OP_DUP"] && bytes[1] == Operation["OP_HASH160"] && bytes[2] == 0x14 && // Operation["OP_PUSHBYTES_20"] bytes[23] == Operation["OP_EQUALVERIFY"] && bytes[24] == Operation["OP_CHECKSIG"] ); } function isP2pk(bytes: Buffer): boolean { if (bytes.length == 67) { return ( bytes[0] == 0x41 && // Operation["OP_PUSHBYTES_65"] bytes[66] == Operation["OP_CHECKSIG"] ); } else if (bytes.length == 35) { return ( bytes[0] == 0x21 && // Operation["OP_PUSHBYTES_33"] bytes[34] == Operation["OP_CHECKSIG"] ); } else { return false; } } function isReturn(bytes: Buffer): boolean { return bytes.includes(Operation["OP_RETURN"]); } enum Operation { OP_FALSE = 0x00, OP_PUSHDATA1 = 0x4c, OP_PUSHDATA2 = 0x4d, OP_PUSHDATA4 = 0x4e, OP_1NEGATE = 0x4f, OP_RESERVED = 0x50, OP_TRUE = 0x51, OP_2 = 0x52, OP_3 = 0x53, OP_4 = 0x54, OP_5 = 0x55, OP_6 = 0x56, OP_7 = 0x57, OP_8 = 0x58, OP_9 = 0x59, OP_10 = 0x5a, OP_11 = 0x5b, OP_12 = 0x5c, OP_13 = 0x5d, OP_14 = 0x5e, OP_15 = 0x5f, OP_16 = 0x60, OP_NOP = 0x61, OP_VER = 0x62, OP_IF = 0x63, OP_NOTIF = 0x64, OP_VERIF = 0x65, OP_VERNOTIF = 0x66, OP_ELSE = 0x67, OP_ENDIF = 0x68, OP_VERIFY = 0x69, OP_RETURN = 0x6a, OP_TOALTSTACK = 0x6b, OP_FROMALTSTACK = 0x6c, OP_2DROP = 0x6d, OP_2DUP = 0x6e, OP_3DUP = 0x6f, OP_2OVER = 0x70, OP_2ROT = 0x71, OP_2SWAP = 0x72, OP_IFDUP = 0x73, OP_DEPTH = 0x74, OP_DROP = 0x75, OP_DUP = 0x76, OP_NIP = 0x77, OP_OVER = 0x78, OP_PICK = 0x79, OP_ROLL = 0x7a, OP_ROT = 0x7b, OP_SWAP = 0x7c, OP_TUCK = 0x7d, OP_CAT = 0x7e, OP_SUBSTR = 0x7f, OP_LEFT = 0x80, OP_RIGHT = 0x81, OP_SIZE = 0x82, OP_INVERT = 0x83, OP_AND = 0x84, OP_OR = 0x85, OP_XOR = 0x86, OP_EQUAL = 0x87, OP_EQUALVERIFY = 0x88, OP_RESERVED1 = 0x89, OP_RESERVED2 = 0x8a, OP_1ADD = 0x8b, OP_1SUB = 0x8c, OP_2MUL = 0x8d, OP_2DIV = 0x8e, OP_NEGATE = 0x8f, OP_ABS = 0x90, OP_NOT = 0x91, OP_0NOTEQUAL = 0x92, OP_ADD = 0x93, OP_SUB = 0x94, OP_MUL = 0x95, OP_DIV = 0x96, OP_MOD = 0x97, OP_LSHIFT = 0x98, OP_RSHIFT = 0x99, OP_BOOLAND = 0x9a, OP_BOOLOR = 0x9b, OP_NUMEQUAL = 0x9c, OP_NUMEQUALVERIFY = 0x9d, OP_NUMNOTEQUAL = 0x9e, OP_LESSTHAN = 0x9f, OP_GREATERTHAN = 0xa0, OP_LESSTHANOREQUAL = 0xa1, OP_GREATERTHANOREQUAL = 0xa2, OP_MIN = 0xa3, OP_MAX = 0xa4, OP_WITHIN = 0xa5, OP_RIPEMD160 = 0xa6, OP_SHA1 = 0xa7, OP_SHA256 = 0xa8, OP_HASH160 = 0xa9, OP_HASH256 = 0xaa, OP_CODESEPARATOR = 0xab, OP_CHECKSIG = 0xac, OP_CHECKSIGVERIFY = 0xad, OP_CHECKMULTISIG = 0xae, OP_CHECKMULTISIGVERIFY = 0xaf, OP_NOP1 = 0xb0, OP_CHECKLOCKTIMEVERIFY = 0xb1, OP_CHECKSEQUENCEVERIFY = 0xb2, OP_NOP4 = 0xb3, OP_NOP5 = 0xb4, OP_NOP6 = 0xb5, OP_NOP7 = 0xb6, OP_NOP8 = 0xb7, OP_NOP9 = 0xb8, OP_NOP10 = 0xb9, OP_PUBKEYHASH = 0xfd, OP_PUBKEY = 0xfe, OP_INVALIDOPCODE = 0xff, }