UNPKG

trezor-link

Version:
108 lines (92 loc) 3 kB
/* @flow */ "use strict"; // Helper module for converting Trezor's raw input to // ProtoBuf's message and from there to regular JSON to trezor.js import * as ProtoBuf from "protobufjs-old-fixed-webpack"; const ByteBuffer = ProtoBuf.ByteBuffer; const Long = ProtoBuf.Long; import {Messages} from "./messages.js"; export class MessageDecoder { // Builders, generated by reading config messages: Messages; // message type number type: number; // raw data to push to Trezor data: ArrayBuffer; constructor(messages: Messages, type: number, data: ArrayBuffer) { this.type = type; this.data = data; this.messages = messages; } // Returns an info about this message, // which includes the constructor object and a name _messageInfo() : MessageInfo { const r = this.messages.messagesByType[this.type]; if (r == null) { throw new Error(`Method type not found - ${this.type}`); } return new MessageInfo(r.constructor, r.name); } // Returns the name of the message messageName() : string { return this._messageInfo().name; } // Returns the actual decoded message, as a ProtoBuf.js object _decodedMessage() : ProtoBuf.Builder.Message { const constructor = this._messageInfo().messageConstructor; return constructor.decode(this.data); } // Returns the message decoded to JSON, that could be handed back // to trezor.js decodedJSON() : Object { const decoded = this._decodedMessage(); const converted = messageToJSON(decoded); return JSON.parse(JSON.stringify(converted)); } } class MessageInfo { messageConstructor: ProtoBuf.Builder.Message; name: string; constructor(messageConstructor: ProtoBuf.Builder.Message, name: string) { this.messageConstructor = messageConstructor; this.name = name; } } // Converts any ProtoBuf message to JSON in Trezor.js-friendly format function messageToJSON(message: ProtoBuf.Builder.Message) : Object { const res = {}; const meta = message.$type; for (const key in message) { const value = message[key]; if (typeof value === `function`) { // ignoring } else if (value instanceof ByteBuffer) { const hex = value.toHex(); res[key] = hex; } else if (value instanceof Long) { const num = value.toNumber(); res[key] = num; } else if (Array.isArray(value)) { const decodedArr = value.map((i) => { if (typeof i === `object`) { return messageToJSON(i); } else { return i; } }); res[key] = decodedArr; } else if (value instanceof ProtoBuf.Builder.Message) { res[key] = messageToJSON(value); } else if (meta._fieldsByName[key].type.name === `enum`) { if (value == null) { res[key] = null; } else { const enumValues = meta._fieldsByName[key].resolvedType.getChildren(); res[key] = enumValues.find(e => e.id === value).name; } } else { res[key] = value; } } return res; }