import { cborBackend } from "cbor-rpc"; import { DatumOption, PlutusData } from "./plutus"; import { HexString, RawValue, Value, valuetoObject } from "./value"; import { Address, Credential, RawAddress, ShelleyAddress, StakeCredential, parseAddressBytes, } from "../serialization/address"; import { Script, ScriptJSON } from "./plutusScript"; import { Tag } from "cbor-rpc/lib/cbor-x"; import { RawTxId, UtxoId } from "../types"; import { Buffer } from "buffer"; type RawPostAlonzoOutput = Map; type RawPreBabbageOutput = [RawAddress, RawValue, Buffer?]; type RawOutput = RawPostAlonzoOutput | RawPreBabbageOutput; export type TxInput = { txHash: Buffer; index: number; }; export class Output { address!: Address; value!: Value; datum?: DatumOption; datumHash?: Buffer; referenceScript?: Script; static fromCborObject(obj: RawOutput): Output { throw new Error("Method 'fromCborObject' must be implemented in derived classes"); } contains(address?: Address, value?: Value, datum?: DatumOption, datumHash?: Buffer, referenceScript?: Script) { if (address && this.address.equals(address)) { return true; } if (value && this.value.equals(value)) { return true; } if (datum && this.datum == datum) { return true; } if (datumHash && this.datumHash == datumHash) { return true; } // TODO: this is the wrong way to compare reference script if (referenceScript && this.referenceScript == referenceScript) { return true; } return false; } } export class PostAlonzoOutput extends Output { constructor(address: Address, value: Value, datum?: DatumOption, referenceScript?: Script) { super(); this.address = address; this.value = value; this.datum = datum; this.referenceScript = referenceScript; } static override fromCborObject(obj: RawPostAlonzoOutput): PostAlonzoOutput { const address = parseAddressBytes(obj.get(0)); const value = Value.fromCborObject(obj.get(1)); const datum = obj.get(2) ? obj.get(2)[0] == 0 ? (obj.get(2)[0] as HexString) : PlutusData.fromBytes((obj.get(2)[1] as Tag).value) : undefined; const referenceScript = obj.get(3) ? Script.fromRawScript({ tag: 24, value: obj.get(3).value }) : undefined; return new PostAlonzoOutput(address, value, datum, referenceScript); } } export class PreBabbageOutput extends Output { declare address: Address; declare value: Value; declare datum?: any; constructor(address: Address, value: Value, datum?: any) { super(); this.address = address; this.value = value; this.datum = datum; } static override fromCborObject(obj: RawPreBabbageOutput): PreBabbageOutput { const address = parseAddressBytes(obj[0]); const value = Value.fromCborObject(obj[1]); const datum = obj[2]?.toString("hex"); return new PreBabbageOutput(address, value, datum); } } export function parseOutputBytes(rawBytes: Buffer): Output { const obj: RawPreBabbageOutput | RawPostAlonzoOutput = cborBackend.decode(rawBytes); if (Array.isArray(obj)) { return PreBabbageOutput.fromCborObject(obj); } else { return PostAlonzoOutput.fromCborObject(obj); } } Output.fromCborObject = function (obj: RawOutput): Output { if (Array.isArray(obj)) { return PreBabbageOutput.fromCborObject(obj); } else if (typeof obj == "object") { return PostAlonzoOutput.fromCborObject(obj); } else { throw new Error("Unknown Output type"); } }; export function parseOutputs(rawOutputs: RawOutput[]): Output[] { const outputs: Output[] = []; rawOutputs.forEach((rawOutput) => { outputs.push(Output.fromCborObject(rawOutput)); }); return outputs; } export class UTxO { txIn: TxInput; txOut: Output; constructor(txIn: TxInput, txOut: Output) { this.txIn = txIn; this.txOut = txOut; } static fromBytes(bytes:Buffer): UTxO{ return this.fromCborObject(cborBackend.decode(bytes)) } static fromCborObject(cborObject:[RawTxId,RawOutput]){ return new UTxO(UtxoId.fromCborObject(cborObject[0]),Output.fromCborObject(cborObject[1])); } static fromHexString(bytes:HexString){ return this.fromBytes(Buffer.from(bytes,'hex')) } toBytes(): Buffer { if (!this.txOut.datum && !this.txOut.datumHash && !this.txOut.referenceScript) { return encodeBasicUtxo(this.txIn, this.txOut.address, this.txOut.value); } else { return encodeFullUtxo( this.txIn, this.txOut.address, this.txOut.value, this.txOut.datumHash, this.txOut.datum, this.txOut.referenceScript ); } } toHex(): string { return this.toBytes().toString("hex"); } } const encodeBasicUtxo = (txin: TxInput, address: Address, value: Value) => cborBackend.encode([ [Buffer.from(txin.txHash), BigInt(txin.index)], [address.toBytes(), value.toCborObject()], ]); const encodeFullUtxo = ( txin: TxInput, address: Address, value: Value, datumHash?: Buffer, inlineDatum?: DatumOption, script?: Script ) => { const utxoMap = new Map(); utxoMap.set(0, address.toBytes()); utxoMap.set(1, value.toCborObject()); if (datumHash) utxoMap.set(2, datumHash); if (inlineDatum) utxoMap.set( 2, inlineDatum instanceof PlutusData ? cborBackend.decode(inlineDatum.toInlineDatumBytes()) : cborBackend.decode(PlutusData.fromHex(inlineDatum).toInlineDatumBytes()) ); if (script) { utxoMap.set(3, cborBackend.decode(script.toBytes())); } return cborBackend.encode([[txin.txHash, BigInt(txin.index)], utxoMap]); }; // const postAlonzoOutputHex = // "82A4005839005D4F58F5D89DB08086D4CB0D933E2ECCB38C0148586F0758B88B486FDD8F5D45A1954E0AECF1DBCAB8A2F723652F67ED5FB06C8EC27E42CC01821A01047F26A2581C34E6054E3E74ECF4A9B6EB4E34A865F6B0B5FEE85E6A9BFBA0D2D025A848366B546F6B656E7319157C43414243194D9043444546194DB9434E47451903E844526F6F6D0449536967546F6B656E731907CF46546F6B656E311902FE46546F6B656E3218BD581CEFF7E215E355546CD0A59F0307638264CB98B88C8DCBBB36CAD29818A14850726F706F73616C01028201D81843D8798003D818590DF68203590DF1590DEE010100332323232323232323232323232323232323232323232323232323232323232323223223323232322932323255333573466E1D2000002118019BAE357420021155333573466E1D200200211804980A1ABA10019980E10009ABA1357440021155333573466E1D200400211803980D9ABA100108AA999AB9A3370E900300108C004DD69ABA10019919192A999AB9A3370E900000108C034C078D5D0800CCC07DD69ABA1357440021155333573466E1D200200211809980F1ABA10019980FBAD357426AE8800422AA666AE68CDC3A400800423003301E357420033015357426AE8800422AA666AE68CDC3A400C004226500B301F35742005301635742003375A6AE84D5D10008D5D100088AA999AB9A3370E900400108C024C078D5D0800CDD69ABA1357440021155333573466E1D200A0021180A980F1ABA100108AA999AB9A3370E900600108C044C078D5D0800CDD69ABA1357440021155333573466E1D200E002118029BAE35742003375C6AE84D5D100084554CCD5CD19B87480400084600E6EB8D5D0800CDD69ABA1357440021155333573466E1D201200211800980F1ABA1001980F1ABA1357440021155333573466E1D201400211807980F1ABA1001089812249035054310035573C0046AAE74004DD51ABA1357440021155333573466E1D2008002118059919192A999AB9A3370E900000108C004C078D5D080084554CCD5CD19B874800800846006603C6AE8400422AA666AE68CDC3A400800423005375C6AE84004226048921035054310035573C0046AAE74004DD51ABA100108AA999AB9A3370E900500108C014DD69ABA10019919192A999AB9A3370E900000108994004DD69ABA1002980F9ABA10019919192A999AB9A3370E900000108994024CC0900A0D5D08014D5D0800CCC091D71ABA1357440023574400222AA666AE68CDC3A400400423001330230273574200332323255333573466E1D2000002118009BAD35742003375A6AE84D5D1000844C0AD241035054310035573C0046AAE74004DD51ABA1357440021155333573466E1D20040021180599980F0113AD357420033302375C6AE84D5D100084554CCD5CD19B87480180084600E6604604E6AE8400422AA666AE68CDC3A401000422646500D3302502935742007330260243574200533302002475A6AE840072646464AA666AE68CDC3A400000423001375A6AE840066EB4D5D09ABA2001089816A481035054310035573C0046AAE74004DD51ABA13574400322330290020010D5D10009ABA20011155333573466E1D200A00211802998118139ABA10019919192A999AB9A3370E900000108998133AE357420022260569201035054310035573C0046AAE74004DD51ABA1357440021155333573466E1D200C002118010898142481035054310035573C0046AAE74004DD51ABA135744002357440022260489201035054310035573C0046AAE74004DD51ABA1357440021130214901035054310035573C0046AAE74004DD51ABA1357446AE89401644D23232323232593012801C004C034C09401292010444433032006007001333573466E1D200233010001006800400A92103443034004CA0070015900190C0023002524104444330340060070015900190ACC800C88880091801484CA000603E003218012300252401044443303100600018029981512CCC800C88880112290029400A50010011213302D0080018C0080044526898122481035054350019980CBAE5018357426AE88D5D10011980F00B1ABA100150065004302A22590018C00A442AA666AE68CDC3A40046601F2005222200300288C00400822600800291349A4644646464646464646464B2B26031003800AC980318161802802484C8CCC05E400644444002003900191111001166400644440048B484C09000642C8C00949104444330350060008AC9803804C84C064CA007001333573466E1D200233018302F00100A800400A921044443303600600700159330322333573466E1D20023301990019111001802E0010020018C00A442B2003159900291110012300290994000C09C0064300248860045240104444330310060001981892CCC800C88880112290029400A50010011213303400B0018C008007180023002452689815249035054350019812BAE357426AE88D5D11ABA2357446AE88D5D10011981200E1ABA1001500C33022018357426AE894030C0C08964006200D2218018014C010004302F22590018C00A442AA666AE68CDC3A4004660292005222200300308C004008226008002302E22590018C00A442AA666AE68CDC3A40046602732005220014888800C00A230010020898020009666564C00C0062D221590018801488589111002245200528014A0020022420031628029815112C800C60012213259593301B900391001001A300190039100091801243003001801220023004001400426603001C6AE8540084D5D11ABA25001135573C6EA8D5D0A80089AAB9E37540024C604444B20031801488564CC04801400A30008980200086040444644AA666AE68CDC3A4000008230001159590038C002443002460051333005593002001899B810044800A2008590038980D24903505439009108008004604644B20031801488554CCD5CD19B8F590058980E24810350543800910801000846000226008002223302122590018A40012219002912A999AB9A3371E00400E22601200222600C006001180F112C800C52000910C801488CDC000098030018460046006002603844B2003180048856400A2600800318010603644B200318004886007200522590028C0022602C0024C010004232323255333573466E1D2000002118009BAE35742002115325333573466E1D20020031180298009ABA100208AA999AB9A3370E900200188C00CDD71ABA100298009ABA1357440041130144910350543100232323255333573466E1D20000021180098089ABA100108AA999AB9A3370E900100108C0084554CCD5CD19B87480100084600822602E9201035054310035573C0046AAE74004DD50009AAB9E00235573A0026EA80048C8C8C954CCD5CD19B874800000846002600A6AE84006600C6AE84D5D1000844C049241035054310035573C0046AAE74004DD500091919192A999AB9A3370E900000108C004DD71ABA10019BAD357426AE880042260229201035054310035573C0046AAE74004DD500091919192A999AB9A3370E90000010899194004C02CD5D0801CCCC021D728039ABA10029919192A999AB9A3370E900000108C0004554CCD5CD19B87480080084600A6EB8D5D080084554CCD5CD19B8748010008460066AE8400422602A921035054310035573C0046AAE74004DD51ABA100199806BAE357426AE880046AE88004D5D1000889808249035054310035573C0046AAE74004DD5000899800BAE75A4464460046EAC004C05C88CCCD55CF800940008CA007001300635573A003300535573C00298021ABA20031ABA100280011480148A400E44AA666AE68CDC780200108999AB9A3370E00600300080108C008232323255333573466E1D20000021132323280099805BAD35742009300835742007375C6AE8400A66016EB8D5D0800CDD69ABA135744002357440026AE88004D5D10008898062481035054310035573C0046AAE74004DD500091919192A999AB9A3370E900000108C004C014D5D0800CCC0188C8C8C954CCD5CD19B87480000084600260126AE8400422AA666AE68CDC3A40040042265003375A6AE8400A6EB4D5D0800CDD69ABA1357440023574400222601E9201035054310035573C0046AAE74004DD50009ABA13574400211300B491035054310035573C0046AAE74004DD500091919192A999AB9A3370E900000108C004DD71ABA100108AA999AB9A3370E900100108C00CDD71ABA1001089805249035054310035573C0046AAE74004DD5000911919192A999AB9A3370E900100108C0084554CCD5CD19B874800000846002600A6AE84004226014921035054310035573C0046AAE74004DD5000919118011BAC00130102233335573E0025000280198021ABA100298019ABA20024000C03888954CCD5CD19B874800000444C01924103505433001155333573466E200052000113300333702900000119B814800000444CA00266E1000C00666E1000800466008004002601A444AA666AE68CDC3A400000222004226600600266E180080048C8C8C954CCD5CD19B8748000008460026EB8D5D0800CDD69ABA1357440021130054901035054310035573C0046AAE74004DD5000919319AB9C0018001805112C800C6001221801C80148800930040010C02489640063000910C00E400A4400298020008601044B200318004884E400A4444460206014666A01601A00800230040011803912C800C6001221801C80148A002005900191805800C88CCD402402C0080064601800226008002099111191919806112C800C400E443003002980200086004008600A6600C5200323223002007300D22590018C002443200522593300C0020078C00A2600C0060004601444B2003180048860072005228008014CC040896400630050034886400A44B26601E0040111801803C00513006003000E4C010004300622590018C002443003900291400400B0010011300400108C88C008004C01889640063000910992C9803001C600600700144004600800222333573466E3C008006001002300322590018C002443003900291400400B001001130040010C00889640063000910C00E400A45001002C0140044C010004300122590018C002443003900291400400A6600E44B20031800488600720052280080164006466E0120000019119B80002001919B80480000044C010004001260080021191800800918011198010010009999A89100111400400A002212900280092212056D95081EFA6C0842A174E8A6BFBFF454F69B833D4814C903B61B3C3A3FAD28C00480101825839005D4F58F5D89DB08086D4CB0D933E2ECCB38C0148586F0758B88B486FDD8F5D45A1954E0AECF1DBCAB8A2F723652F67ED5FB06C8EC27E42CC821B0000000340EAB042A2581CA48A63CA4083B142057F7F62599AB1E7CA73D3BA6DB800E25C1E6E83A14850726F706F73616C05581CF123088056B0F07927AC7D23CC22F9BC03E4B2FDF0F2E2DF605B58CAA14850726F706F73616C05"; // const toCbor = cborBackend.decode(Buffer.from(postAlonzoOutputHex, "hex")); // toCbor.forEach((decodedCbor: RawOutput) => { // console.log(Output.fromCborObject(decodedCbor)); // });