UNPKG

@node-dlc/messaging

Version:
308 lines 13.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ContractInfoV1 = exports.ContractInfoV0 = exports.DisjointContractInfo = exports.SingleContractInfo = exports.ContractInfo = void 0; const bufio_1 = require("@node-dlc/bufio"); const MessageType_1 = require("../MessageType"); const ContractDescriptor_1 = require("./ContractDescriptor"); const DlcMessage_1 = require("./DlcMessage"); const OracleInfo_1 = require("./OracleInfo"); class ContractInfo extends DlcMessage_1.DlcMessage { static deserialize(buf) { const reader = new bufio_1.BufferReader(buf); const typeId = Number(reader.readBigSize()); switch (typeId) { case MessageType_1.ContractInfoType.Single: return SingleContractInfo.deserialize(buf); case MessageType_1.ContractInfoType.Disjoint: return DisjointContractInfo.deserialize(buf); default: throw new Error(`Contract info type must be Single (0) or Disjoint (1), got ${typeId}`); } } /** * Creates a ContractInfo from JSON data (e.g., from test vectors) * @param json JSON object representing contract info */ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any static fromJSON(json) { if (!json) { throw new Error('contractInfo is required'); } // Check if it's a single contract info or disjoint contract info if (json.singleContractInfo || json.single_contract_info) { return SingleContractInfo.fromJSON(json.singleContractInfo || json.single_contract_info); } else if (json.disjointContractInfo || json.disjoint_contract_info) { return DisjointContractInfo.fromJSON(json.disjointContractInfo || json.disjoint_contract_info); } else { throw new Error('contractInfo must have either singleContractInfo or disjointContractInfo'); } } // Method to get total collateral (for compatibility) getTotalCollateral() { return this.totalCollateral; } } exports.ContractInfo = ContractInfo; /** * SingleContractInfo contains information about a contract's outcomes, * their corresponding payouts, and the oracles to be used. * This corresponds to the previous ContractInfoV0. */ class SingleContractInfo extends ContractInfo { constructor() { super(...arguments); /** * The type for single_contract_info message - using MessageType for IDlcMessage compatibility */ this.type = MessageType_1.MessageType.SingleContractInfo; /** * The contract info type for new format */ this.contractInfoType = MessageType_1.ContractInfoType.Single; } /** * Creates a SingleContractInfo from JSON data * @param json JSON object representing single contract info */ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any static fromJSON(json) { const instance = new SingleContractInfo(); instance.totalCollateral = BigInt(json.totalCollateral || json.total_collateral || 0); // Handle nested contractInfo structure (test vectors have double nesting) const contractInfoData = json.contractInfo || json.contract_info || json; // Parse contract descriptor using proper fromJSON method instance.contractDescriptor = ContractDescriptor_1.ContractDescriptor.fromJSON(contractInfoData.contractDescriptor || contractInfoData.contract_descriptor); // Parse oracle info using proper fromJSON method instance.oracleInfo = OracleInfo_1.OracleInfo.fromJSON(contractInfoData.oracleInfo || contractInfoData.oracle_info); return instance; } /** * Deserializes a single_contract_info message * @param buf */ static deserialize(buf) { const instance = new SingleContractInfo(); const reader = new bufio_1.BufferReader(buf); reader.readBigSize(); // read type (0) instance.totalCollateral = reader.readUInt64BE(); // Read contract descriptor as sibling type (starts with its own type prefix) instance.contractDescriptor = ContractDescriptor_1.ContractDescriptor.deserialize(Buffer.from(reader.buffer.subarray(reader.position))); // Skip past the contract descriptor we just read const descLength = instance.contractDescriptor.serialize().length; reader.position += descLength; // Read oracle info with rust-dlc format - discriminator + body const oracleType = Number(reader.readBigSize()); if (oracleType === 0) { // Single oracle instance.oracleInfo = OracleInfo_1.SingleOracleInfo.deserializeBody(Buffer.from(reader.buffer.subarray(reader.position))); } else if (oracleType === 1) { // Multi oracle instance.oracleInfo = OracleInfo_1.MultiOracleInfo.deserializeBody(Buffer.from(reader.buffer.subarray(reader.position))); } else { throw new Error(`Unknown oracle info type: ${oracleType}`); } return instance; } // Compatibility property get length() { return BigInt(this.serialize().length); } /** * Validates correctness of all fields in the message * @throws Will throw an error if validation fails */ validate() { if (this.totalCollateral <= 0) { throw new Error('totalCollateral must be greater than 0'); } this.oracleInfo.validate(); // TODO: Add contract descriptor validation once available // this.contractDescriptor.validate(); } /** * Converts single_contract_info to JSON */ toJSON() { // Return enum variant format for Rust compatibility return { singleContractInfo: { totalCollateral: Number(this.totalCollateral), contractInfo: { contractDescriptor: this.contractDescriptor.toJSON(), oracleInfo: this.oracleInfo.toJSON(), }, }, }; } /** * Serializes the single_contract_info message into a Buffer */ serialize() { const writer = new bufio_1.BufferWriter(); writer.writeBigSize(this.contractInfoType); writer.writeUInt64BE(this.totalCollateral); writer.writeBytes(this.contractDescriptor.serialize()); // Use serializeBody() to match rust-dlc behavior - don't add extra TLV wrapper if (this.oracleInfo instanceof OracleInfo_1.SingleOracleInfo) { writer.writeBigSize(0); // Single oracle discriminator writer.writeBytes(this.oracleInfo.serializeBody()); } else { writer.writeBigSize(1); // Multi oracle discriminator writer.writeBytes(this.oracleInfo.serializeBody()); } return writer.toBuffer(); } } exports.SingleContractInfo = SingleContractInfo; SingleContractInfo.contractInfoType = MessageType_1.ContractInfoType.Single; SingleContractInfo.type = MessageType_1.MessageType.SingleContractInfo; /** * DisjointContractInfo contains information about multiple disjoint contract events. * This corresponds to the previous ContractInfoV1. */ class DisjointContractInfo extends ContractInfo { constructor() { super(...arguments); /** * The type for disjoint_contract_info message - using MessageType for IDlcMessage compatibility */ this.type = MessageType_1.MessageType.DisjointContractInfo; /** * The contract info type for new format */ this.contractInfoType = MessageType_1.ContractInfoType.Disjoint; this.contractOraclePairs = []; } /** * Creates a DisjointContractInfo from JSON data * @param json JSON object representing disjoint contract info */ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any static fromJSON(json) { const instance = new DisjointContractInfo(); instance.totalCollateral = BigInt(json.totalCollateral || json.total_collateral || 0); // Parse contract infos array const contractInfosData = json.contractInfos || json.contract_infos || []; instance.contractOraclePairs = contractInfosData.map( // eslint-disable-next-line @typescript-eslint/no-explicit-any (contractInfoData) => ({ contractDescriptor: ContractDescriptor_1.ContractDescriptor.fromJSON(contractInfoData.contractDescriptor || contractInfoData.contract_descriptor), oracleInfo: OracleInfo_1.OracleInfo.fromJSON(contractInfoData.oracleInfo || contractInfoData.oracle_info), })); return instance; } /** * Deserializes a disjoint_contract_info message * @param buf */ static deserialize(buf) { const instance = new DisjointContractInfo(); const reader = new bufio_1.BufferReader(buf); reader.readBigSize(); // read type (1) instance.totalCollateral = reader.readUInt64BE(); const numDisjointEvents = Number(reader.readBigSize()); for (let i = 0; i < numDisjointEvents; i++) { // Read contract descriptor as sibling type (starts with its own type prefix) const contractDescriptor = ContractDescriptor_1.ContractDescriptor.deserialize(Buffer.from(reader.buffer.subarray(reader.position))); // Skip past the contract descriptor we just read const descLength = contractDescriptor.serialize().length; reader.position += descLength; // Read oracle info with rust-dlc format - discriminator + body (same as SingleContractInfo) const oracleType = Number(reader.readBigSize()); let oracleInfo; if (oracleType === 0) { // Single oracle oracleInfo = OracleInfo_1.SingleOracleInfo.deserializeBody(Buffer.from(reader.buffer.subarray(reader.position))); } else if (oracleType === 1) { // Multi oracle oracleInfo = OracleInfo_1.MultiOracleInfo.deserializeBody(Buffer.from(reader.buffer.subarray(reader.position))); } else { throw new Error(`Unknown oracle info type: ${oracleType}`); } // Skip past the oracle info we just read const oracleInfoLength = oracleInfo.serializeBody().length; reader.position += oracleInfoLength; instance.contractOraclePairs.push({ contractDescriptor, oracleInfo }); } return instance; } // Compatibility property get length() { return BigInt(this.serialize().length); } /** * Validates correctness of all fields in the message * @throws Will throw an error if validation fails */ validate() { if (this.totalCollateral <= 0) { throw new Error('totalCollateral must be greater than 0'); } if (this.contractOraclePairs.length === 0) { throw new Error('contractOraclePairs cannot be empty'); } this.contractOraclePairs.forEach((pair, index) => { try { pair.oracleInfo.validate(); // TODO: Add contract descriptor validation once available // pair.contractDescriptor.validate(); } catch (error) { throw new Error(`Validation failed for contract oracle pair ${index}: ${error.message}`); } }); } /** * Converts disjoint_contract_info to JSON */ toJSON() { // Return enum variant format for Rust compatibility return { disjointContractInfo: { totalCollateral: Number(this.totalCollateral), contractInfos: this.contractOraclePairs.map((pair) => ({ contractDescriptor: pair.contractDescriptor.toJSON(), oracleInfo: pair.oracleInfo.toJSON(), })), }, }; } /** * Serializes the disjoint_contract_info message into a Buffer */ serialize() { const writer = new bufio_1.BufferWriter(); writer.writeBigSize(this.contractInfoType); writer.writeUInt64BE(this.totalCollateral); writer.writeBigSize(this.contractOraclePairs.length); for (const pair of this.contractOraclePairs) { writer.writeBytes(pair.contractDescriptor.serialize()); // Write oracle info with discriminator like SingleContractInfo does if (pair.oracleInfo instanceof OracleInfo_1.SingleOracleInfo) { writer.writeBigSize(0); // Single oracle discriminator writer.writeBytes(pair.oracleInfo.serializeBody()); } else { writer.writeBigSize(1); // Multi oracle discriminator writer.writeBytes(pair.oracleInfo.serializeBody()); } } return writer.toBuffer(); } } exports.DisjointContractInfo = DisjointContractInfo; DisjointContractInfo.contractInfoType = MessageType_1.ContractInfoType.Disjoint; DisjointContractInfo.type = MessageType_1.MessageType.DisjointContractInfo; // Legacy support - keeping old class names as aliases (both value and type exports) exports.ContractInfoV0 = SingleContractInfo; exports.ContractInfoV1 = DisjointContractInfo; //# sourceMappingURL=ContractInfo.js.map