import type { ReadStream , WriteStream } from "@iota/util.js" ; import bigInt from "big-integer" ; import { INDEXATION_PAYLOAD_TYPE } from "../models/IIndexationPayload" ; import type { IMessage } from "../models/IMessage" ; import { MILESTONE_PAYLOAD_TYPE } from "../models/IMilestonePayload" ; import { RECEIPT_PAYLOAD_TYPE } from "../models/IReceiptPayload" ; import { TRANSACTION_PAYLOAD_TYPE } from "../models/ITransactionPayload" ; import { TREASURY_TRANSACTION_PAYLOAD_TYPE } from "../models/ITreasuryTransactionPayload" ; import { BYTE_SIZE , MESSAGE_ID_LENGTH , UINT64_SIZE } from "./common" ; import { deserializePayload , MIN_PAYLOAD_LENGTH , serializePayload } from "./payload" ; /**
 * The minimum length of a message binary representation.
 */ const MIN_MESSAGE_LENGTH = UINT64_SIZE + BYTE_SIZE + MESSAGE_ID_LENGTH + MIN_PAYLOAD_LENGTH + UINT64_SIZE ; /**
 * The maximum length of a message.
 */ export const MAX_MESSAGE_LENGTH = 32768 ; /**
 * The maximum number of parents.
 */ export const MAX_NUMBER_PARENTS = 8 ; /**
 * The minimum number of parents.
 */ export const MIN_NUMBER_PARENTS = 1 ; param readStream returns export function deserializeMessage ( readStream ) { if ( ! readStream . hasRemaining ( MIN_MESSAGE_LENGTH ) ) { throw new Error ( `Message data is ${ readStream . length ( ) } in length which is less than the minimimum size required of ${ MIN_MESSAGE_LENGTH }` ) ; } const networkId = readStream . readUInt64 ( "message.networkId" ) ; const numParents = readStream . readByte ( "message.numParents" ) ; const parents = [ ] ; for ( let i = 0 ; i < numParents ; i ++ ) { const parentMessageId = readStream . readFixedHex ( `message.parentMessageId${ i }` , MESSAGE_ID_LENGTH ) ; parents . push ( parentMessageId ) ; } const payload = deserializePayload ( readStream ) ; if ( payload && ( payload . type === RECEIPT_PAYLOAD_TYPE || payload . type === TREASURY_TRANSACTION_PAYLOAD_TYPE ) ) { throw new Error ( "Messages can not contain receipt or treasury transaction payloads" ) ; } const nonce = readStream . readUInt64 ( "message.nonce" ) ; const unused = readStream . unused ( ) ; if ( unused !== 0 ) { throw new Error ( `Message data length ${ readStream . length ( ) } has unused data ${ unused }` ) ; } return { networkId : networkId . toString ( 10 ) , parentMessageIds : parents , payload , nonce : nonce . toString ( 10 ) } ; } param writeStream param object export function serializeMessage ( writeStream , object ) { writeStream . writeUInt64 ( "message.networkId" , bigInt ( object . networkId ?? "0" ) ) ; const numParents = object . parentMessageIds ?. length ?? 0 ; writeStream . writeByte ( "message.numParents" , numParents ) ; if ( object . parentMessageIds ) { if ( numParents > MAX_NUMBER_PARENTS ) { throw new Error ( `A maximum of ${ MAX_NUMBER_PARENTS } parents is allowed, you provided ${ numParents }` ) ; } if ( new Set ( object . parentMessageIds ) . size !== numParents ) { throw new Error ( "The message parents must be unique" ) ; } const sorted = object . parentMessageIds . slice ( ) . sort ( ) ; for ( let i = 0 ; i < numParents ; i ++ ) { if ( sorted [ i ] !== object . parentMessageIds [ i ] ) { throw new Error ( "The message parents must be lexographically sorted" ) ; } writeStream . writeFixedHex ( `message.parentMessageId${ i + 1 }` , MESSAGE_ID_LENGTH , object . parentMessageIds [ i ] ) ; } } if ( object . payload && object . payload . type !== TRANSACTION_PAYLOAD_TYPE && object . payload . type !== INDEXATION_PAYLOAD_TYPE && object . payload . type !== MILESTONE_PAYLOAD_TYPE ) { throw new Error ( "Messages can only contain transaction, indexation or milestone payloads" ) ; } serializePayload ( writeStream , object . payload ) ; writeStream . writeUInt64 ( "message.nonce" , bigInt ( object . nonce ?? "0" ) ) ; }