import {ed25519} from "@noble/curves/ed25519"; import BufferReader from "./buffer_reader.js"; import BufferWriter from "./buffer_writer.js"; class Advert { static ADV_TYPE_NONE = 0; static ADV_TYPE_CHAT = 1; static ADV_TYPE_REPEATER = 2; static ADV_TYPE_ROOM = 3; static ADV_LATLON_MASK = 0x10; static ADV_BATTERY_MASK = 0x20; static ADV_TEMPERATURE_MASK = 0x40; static ADV_NAME_MASK = 0x80; constructor(publicKey, timestamp, signature, appData) { this.publicKey = publicKey; this.timestamp = timestamp; this.signature = signature; this.appData = appData; this.parsed = this.parseAppData(); } static fromBytes(bytes) { // read bytes const bufferReader = new BufferReader(bytes); const publicKey = bufferReader.readBytes(32); const timestamp = bufferReader.readUInt32LE(); const signature = bufferReader.readBytes(64); const appData = bufferReader.readRemainingBytes(); return new Advert(publicKey, timestamp, signature, appData); } getFlags() { return this.appData[0]; } getTypeString() { const flags = this.getFlags(); if(flags & Advert.ADV_TYPE_NONE) return "ADV_TYPE_NONE"; if(flags & Advert.ADV_TYPE_CHAT) return "ADV_TYPE_CHAT"; if(flags & Advert.ADV_TYPE_REPEATER) return "ADV_TYPE_REPEATER"; if(flags & Advert.ADV_TYPE_ROOM) return "ADV_TYPE_ROOM"; return null; } isVerified() { // build signed data const bufferWriter = new BufferWriter(); bufferWriter.writeBytes(this.publicKey); bufferWriter.writeUInt32LE(this.timestamp); bufferWriter.writeBytes(this.appData); // verify signature return ed25519.verify(this.signature, bufferWriter.toBytes(), this.publicKey); } parseAppData() { // read app data const bufferReader = new BufferReader(this.appData); const flags = bufferReader.readByte(); // parse lat lon var lat = null; var lon = null; if(flags & Advert.ADV_LATLON_MASK){ lat = bufferReader.readInt32LE(); lon = bufferReader.readInt32LE(); } // parse name (remainder of app data) var name = null; if(flags & Advert.ADV_NAME_MASK){ name = bufferReader.readString(); } return { type: this.getTypeString(), lat: lat, lon: lon, name: name, }; } } export default Advert;