diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.html b/frontend/src/app/components/transactions-list/transactions-list.component.html index 7c65c0981..8290c2422 100644 --- a/frontend/src/app/components/transactions-list/transactions-list.component.html +++ b/frontend/src/app/components/transactions-list/transactions-list.component.html @@ -69,7 +69,7 @@ ScriptSig (ASM) - {{ vin.scriptsig_asm }} + ScriptSig (HEX) @@ -82,11 +82,11 @@ P2SH redeem script - {{ vin.inner_redeemscript_asm }} + P2WSH witness script - {{ vin.inner_witnessscript_asm }} + nSequence @@ -94,7 +94,7 @@ Previous output script - {{ vin.prevout.scriptpubkey_asm }} {{ vin.prevout.scriptpubkey_type ? ('(' + vin.prevout.scriptpubkey_type + ')') : '' }} + {{ vin.prevout.scriptpubkey_type ? ('(' + vin.prevout.scriptpubkey_type + ')') : '' }}" @@ -165,7 +165,7 @@ scriptPubKey (ASM) - {{ vout.scriptpubkey_asm }} + scriptPubKey (HEX) diff --git a/frontend/src/app/shared/pipes/asm-styler/asm-styler.pipe.spec.ts b/frontend/src/app/shared/pipes/asm-styler/asm-styler.pipe.spec.ts new file mode 100644 index 000000000..8e7d28265 --- /dev/null +++ b/frontend/src/app/shared/pipes/asm-styler/asm-styler.pipe.spec.ts @@ -0,0 +1,8 @@ +import { AsmStylerPipe } from './asm-styler.pipe'; + +describe('OpcodesStylerPipe', () => { + it('create an instance', () => { + const pipe = new AsmStylerPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/shared/pipes/asm-styler/asm-styler.pipe.ts b/frontend/src/app/shared/pipes/asm-styler/asm-styler.pipe.ts new file mode 100644 index 000000000..14626a1de --- /dev/null +++ b/frontend/src/app/shared/pipes/asm-styler/asm-styler.pipe.ts @@ -0,0 +1,316 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'asmStyler' +}) +export class AsmStylerPipe implements PipeTransform { + + transform(asm: string): string { + const instructions = asm.split('OP_'); + let out = ''; + for (const instruction of instructions) { + if (instruction === '') { + continue; + } + out += this.addStyling(instruction); + } + return out; + } + + addStyling(instruction: string): string { + const opcode = instruction.split(' ')[0]; + let style = ''; + switch (opcode) { + case '0': + case 'FALSE': + case 'PUSHBYTES_1': + case 'PUSHBYTES_2': + case 'PUSHBYTES_3': + case 'PUSHBYTES_4': + case 'PUSHBYTES_5': + case 'PUSHBYTES_6': + case 'PUSHBYTES_7': + case 'PUSHBYTES_8': + case 'PUSHBYTES_9': + case 'PUSHBYTES_10': + case 'PUSHBYTES_11': + case 'PUSHBYTES_12': + case 'PUSHBYTES_13': + case 'PUSHBYTES_14': + case 'PUSHBYTES_15': + case 'PUSHBYTES_16': + case 'PUSHBYTES_17': + case 'PUSHBYTES_18': + case 'PUSHBYTES_19': + case 'PUSHBYTES_20': + case 'PUSHBYTES_21': + case 'PUSHBYTES_22': + case 'PUSHBYTES_23': + case 'PUSHBYTES_24': + case 'PUSHBYTES_25': + case 'PUSHBYTES_26': + case 'PUSHBYTES_27': + case 'PUSHBYTES_28': + case 'PUSHBYTES_29': + case 'PUSHBYTES_30': + case 'PUSHBYTES_31': + case 'PUSHBYTES_32': + case 'PUSHBYTES_33': + case 'PUSHBYTES_34': + case 'PUSHBYTES_35': + case 'PUSHBYTES_36': + case 'PUSHBYTES_37': + case 'PUSHBYTES_38': + case 'PUSHBYTES_39': + case 'PUSHBYTES_40': + case 'PUSHBYTES_41': + case 'PUSHBYTES_42': + case 'PUSHBYTES_43': + case 'PUSHBYTES_44': + case 'PUSHBYTES_45': + case 'PUSHBYTES_46': + case 'PUSHBYTES_47': + case 'PUSHBYTES_48': + case 'PUSHBYTES_49': + case 'PUSHBYTES_50': + case 'PUSHBYTES_51': + case 'PUSHBYTES_52': + case 'PUSHBYTES_53': + case 'PUSHBYTES_54': + case 'PUSHBYTES_55': + case 'PUSHBYTES_56': + case 'PUSHBYTES_57': + case 'PUSHBYTES_58': + case 'PUSHBYTES_59': + case 'PUSHBYTES_60': + case 'PUSHBYTES_61': + case 'PUSHBYTES_62': + case 'PUSHBYTES_63': + case 'PUSHBYTES_64': + case 'PUSHBYTES_65': + case 'PUSHBYTES_66': + case 'PUSHBYTES_67': + case 'PUSHBYTES_68': + case 'PUSHBYTES_69': + case 'PUSHBYTES_70': + case 'PUSHBYTES_71': + case 'PUSHBYTES_72': + case 'PUSHBYTES_73': + case 'PUSHBYTES_74': + case 'PUSHBYTES_75': + case 'PUSHDATA1': + case 'PUSHDATA2': + case 'PUSHDATA4': + case 'PUSHNUM_NEG1': + case 'TRUE': + case 'PUSHNUM_1': + case 'PUSHNUM_2': + case 'PUSHNUM_3': + case 'PUSHNUM_4': + case 'PUSHNUM_5': + case 'PUSHNUM_6': + case 'PUSHNUM_7': + case 'PUSHNUM_8': + case 'PUSHNUM_9': + case 'PUSHNUM_10': + case 'PUSHNUM_11': + case 'PUSHNUM_12': + case 'PUSHNUM_13': + case 'PUSHNUM_14': + case 'PUSHNUM_15': + case 'PUSHNUM_16': + style = 'constants'; + break; + + case 'NOP': + case 'IF': + case 'NOTIF': + case 'ELSE': + case 'ENDIF': + case 'VERIFY': + case 'RETURN': + case 'RETURN_186': + case 'RETURN_187': + case 'RETURN_188': + case 'RETURN_189': + case 'RETURN_190': + case 'RETURN_191': + case 'RETURN_192': + case 'RETURN_193': + case 'RETURN_194': + case 'RETURN_195': + case 'RETURN_196': + case 'RETURN_197': + case 'RETURN_198': + case 'RETURN_199': + case 'RETURN_200': + case 'RETURN_201': + case 'RETURN_202': + case 'RETURN_203': + case 'RETURN_204': + case 'RETURN_205': + case 'RETURN_206': + case 'RETURN_207': + case 'RETURN_208': + case 'RETURN_209': + case 'RETURN_210': + case 'RETURN_211': + case 'RETURN_212': + case 'RETURN_213': + case 'RETURN_214': + case 'RETURN_215': + case 'RETURN_216': + case 'RETURN_217': + case 'RETURN_218': + case 'RETURN_219': + case 'RETURN_220': + case 'RETURN_221': + case 'RETURN_222': + case 'RETURN_223': + case 'RETURN_224': + case 'RETURN_225': + case 'RETURN_226': + case 'RETURN_227': + case 'RETURN_228': + case 'RETURN_229': + case 'RETURN_230': + case 'RETURN_231': + case 'RETURN_232': + case 'RETURN_233': + case 'RETURN_234': + case 'RETURN_235': + case 'RETURN_236': + case 'RETURN_237': + case 'RETURN_238': + case 'RETURN_239': + case 'RETURN_240': + case 'RETURN_241': + case 'RETURN_242': + case 'RETURN_243': + case 'RETURN_244': + case 'RETURN_245': + case 'RETURN_246': + case 'RETURN_247': + case 'RETURN_248': + case 'RETURN_249': + case 'RETURN_250': + case 'RETURN_251': + case 'RETURN_252': + case 'RETURN_253': + case 'RETURN_254': + case 'RETURN_255': + style = 'control'; + break; + + case 'TOALTSTACK': + case 'FROMALTSTACK': + case 'IFDUP': + case 'DEPTH': + case 'DROP': + case 'DUP': + case 'NIP': + case 'OVER': + case 'PICK': + case 'ROLL': + case 'ROT': + case 'SWAP': + case 'TUCK': + case '2DROP': + case '2DUP': + case '3DUP': + case '2OVER': + case '2ROT': + case '2SWAP': + style = 'stack'; + break; + + case 'CAT': + case 'SUBSTR': + case 'LEFT': + case 'RIGHT': + case 'SIZE': + style = 'splice'; + break; + + case 'INVERT': + case 'AND': + case 'OR': + case 'XOR': + case 'EQUAL': + case 'EQUALVERIFY': + style = 'logic'; + break; + + case '1ADD': + case '1SUB': + case '2MUL': + case '2DIV': + case 'NEGATE': + case 'ABS': + case 'NOT': + case '0NOTEQUAL': + case 'ADD': + case 'SUB': + case 'MUL': + case 'DIV': + case 'MOD': + case 'LSHIFT': + case 'RSHIFT': + case 'BOOLAND': + case 'BOOLOR': + case 'NUMEQUAL': + case 'NUMEQUALVERIFY': + case 'NUMNOTEQUAL': + case 'LESSTHAN': + case 'GREATERTHAN': + case 'LESSTHANOREQUAL': + case 'MIN': + case 'MAX': + case 'WITHIN': + style = 'arithmetic'; + break; + + case 'RIPEMD160': + case 'SHA1': + case 'SHA256': + case 'HASH160': + case 'HASH256': + case 'CODESEPARATOR': + case 'CHECKSIG': + case 'CHECKSIGVERIFY': + case 'CHECKMULTISIG': + case 'CHCEKMULTISIGVERIFY': + style = 'crypto'; + break; + + case 'CHECKLOCKTIMEVERIFY': + case 'CHECKSEQUENCEVERIFY': + style = 'locktime'; + break; + + case 'RESERVED': + case 'VER': + case 'VERIF': + case 'VERNOTIF': + case 'RESERVED1': + case 'RESERVED2': + case 'NOP1': + case 'NOP4': + case 'NOP5': + case 'NOP6': + case 'NOP7': + case 'NOP8': + case 'NOP9': + case 'NOP10': + style = 'reserved'; + break; + } + + let args = instruction.substr(instruction.indexOf(' ') + 1); + if (args === opcode) { + args = ''; + } + return `OP_${opcode} ${args}
`; + } + +} diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index b5b5e138b..f9f0c4a4d 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -4,6 +4,7 @@ import { VbytesPipe } from './pipes/bytes-pipe/vbytes.pipe'; import { ShortenStringPipe } from './pipes/shorten-string-pipe/shorten-string.pipe'; import { CeilPipe } from './pipes/math-ceil/math-ceil.pipe'; import { Hex2asciiPipe } from './pipes/hex2ascii/hex2ascii.pipe'; +import { AsmStylerPipe } from './pipes/asm-styler/asm-styler.pipe'; import { RelativeUrlPipe } from './pipes/relative-url/relative-url.pipe'; import { ScriptpubkeyTypePipe } from './pipes/scriptpubkey-type-pipe/scriptpubkey-type.pipe'; import { BytesPipe } from './pipes/bytes-pipe/bytes.pipe'; @@ -28,6 +29,7 @@ import { ReactiveFormsModule } from '@angular/forms'; ScriptpubkeyTypePipe, RelativeUrlPipe, Hex2asciiPipe, + AsmStylerPipe, BytesPipe, VbytesPipe, WuBytesPipe, @@ -63,6 +65,7 @@ import { ReactiveFormsModule } from '@angular/forms'; ScriptpubkeyTypePipe, RelativeUrlPipe, Hex2asciiPipe, + AsmStylerPipe, BytesPipe, VbytesPipe, WuBytesPipe, diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index ac02e49bf..0c243d722 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -429,3 +429,41 @@ h1, h2, h3 { th { white-space: nowrap; } + +// ASM opcode colors + +.constants { + color: #ff8c00 +} + +.control { + color: #87ceeb +} + +.stack { + color: #ffa500 +} + +.splice { + color: #46b5e2 +} + +.logic { + color: #46b5e2 +} + +.arithmetic { + color: #cae8d0 +} + +.crypto { + color: #b22222 +} + +.locktime { + color: #ff8c00 +} + +.reserved { + color: #ff8c00 +}