ValidatorUtils.java

/*
 * UVerify Backend
 * Copyright (C) 2025 Fabian Bormann
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package io.uverify.backend.util;

import com.bloxbean.cardano.client.api.exception.ApiException;
import com.bloxbean.cardano.client.api.model.Result;
import com.bloxbean.cardano.client.api.model.Utxo;
import com.bloxbean.cardano.client.backend.api.BackendService;
import com.bloxbean.cardano.client.backend.model.TxContentOutputAmount;
import com.bloxbean.cardano.client.backend.model.TxContentUtxo;
import com.bloxbean.cardano.client.backend.model.TxContentUtxoOutputs;
import com.bloxbean.cardano.client.plutus.blueprint.PlutusBlueprintUtil;
import com.bloxbean.cardano.client.plutus.blueprint.model.PlutusVersion;
import com.bloxbean.cardano.client.plutus.spec.*;
import com.bloxbean.cardano.client.transaction.spec.TransactionOutput;
import com.bloxbean.cardano.client.util.HexUtil;
import com.bloxbean.cardano.yaci.store.common.domain.AddressUtxo;
import com.bloxbean.cardano.yaci.store.common.domain.Amt;
import io.uverify.backend.enums.CardanoNetwork;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import scalus.bloxbean.ScalusScriptUtils;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
public class ValidatorUtils {
    public static String getProxyStateTokenName(String txHash, int outputIndex) {
        // Convert hex string to bytes
        byte[] txHashBytes;
        try {
            txHashBytes = Hex.decodeHex(txHash.toCharArray());
        } catch (java.lang.Exception exception) {
            log.error(exception.getMessage());
            return "";
        }
        // Convert outputIndex to string and then to bytes
        String outputIndexString = String.valueOf(outputIndex);
        byte[] outputIndexBytes = outputIndexString.getBytes(StandardCharsets.UTF_8);

        // Combine both byte arrays
        byte[] messageBuffer = new byte[txHashBytes.length + outputIndexBytes.length];
        System.arraycopy(txHashBytes, 0, messageBuffer, 0, txHashBytes.length);
        System.arraycopy(outputIndexBytes, 0, messageBuffer, txHashBytes.length, outputIndexBytes.length);

        // Calculate SHA3-256 hash and return as hex string
        return DigestUtils.sha3_256Hex(messageBuffer);
    }

    public static String validatorToScriptHash(PlutusScript script) {
        try {
            return HexUtil.encodeHexString(script.getScriptHash());
        } catch (Exception e) {
            log.error("Error computing policy id: " + e.getMessage());
            return null;
        }
    }

    public static PlutusScript getUVerifyProxyContract() {
        String compiledCode = "590a11010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a488888889660033001300337540132232330010010032259800800c528456600266e3cdd71805000801c528c4cc008008c02c0050052010912cc004006297ae089980398021804000998010011804800a00c911919800800801912cc00400629422b30013375e601400200714a3133002002300b001401480426e1d200091191919800800802112cc00400600713233225980099b910070028acc004cdc78038014400600c804a26600a00a601e0088048dd718040009bab3009001300b0014024297adef6c609b874800a6e9520009112cc004cdc48012400110018cc00400e66e10009201499b8b3370066e14009201448180005003200891111919800800802912cc004006200b13259800800c4cc010c03400801a26600a601a004660060060028058c03400500a48c01cc0200052222222222298009809005cc04402e446601800400330090099192cc004cdc3a4008601e6ea8006264b3001300a3010375400313232332259800980c801c40162c80b0dd7180b0009bae301600230160013011375400316403c602660206ea80062c8070c048c04cc04cc03cdd5000c888c020c8cc88cc008008004896600200300389919912cc004cdc8803801456600266e3c01c00a20030064055133005005301b00440546eb8c050004dd6980a800980b800a02a3300a00400314800244646600200200644b30010018a60103d87a80008992cc004c010006260126602a00297ae0899801801980b80120223015001404d300300391192cc004c0280062b3001301137540070028b20248acc004c0200062b3001301137540070028b20248b201e403c601e6ea800922222222233223232980091b93337146eb8c07cc070dd50009b98373266004601e60386ea800522100980f006cc068dd50022444b30013017001899198048018991919194c004c09cc09c0066eacc09800660100549112cc004c07cc094dd500544c8c9660026042604e6ea80062b30013302232330010013758605801444b30010018a5eb82266058605a60546ea8c0b4004cc008008c0b800502b017c566002603e646600200200644b30010018a40011337009001198010011817000a0568acc004cc896600200514a11329800992cc004c094c0acdd5000c4dd6981618179bab302f302c375400314800102a1817000cdd798171817800cdd5801a444b30010018acc004c00801a26600a0069000452820588992cc004cdd79817000a6010140008acc004cc018010dd6981798191bab302f001898019ba630330028a5040b51598009980300224001130030078a5040b48168c0c400502f0ca60020030079119817801198179ba60014bd7020022225980080144cc005300103d87a80004bd6f7b63044ca60026eb8c0b40066eacc0b800660640069112cc004cdc8a441000038acc004cdc7a441000038998029813998199ba60024bd70000c4cc015300103d87a800000640bd19800803c006446600e0046606a66ec0dd48029ba6004001401c81786060004817229422942294102f1ba63302a337606ea4028dd31981519bb0375200698010101004bd6f7b63025eb7bdb1808928c566002646600200200644b30010018a508acc00660026eacc074c0a8dd51816800c03200a80ba2946266004004605c002814102b44cc060dd61815981618160029bae301b30283754602c605660506ea800629410264528204c8a50409914a081322c81316600200314c0103d87a80008980e998149815000a5eb8102819198008009bac302a0062259800800c52f5c11332259800992cc004c088c0a8dd5000c4cdc78069bae302e302b375400314a08148c0b4c0a8dd5181698151baa00289981600119802002000c4cc01001000502818158009816000a0528992cc004c080c098dd5000c56600330013302332330010013302000400a2259800800c52f5c113302b3028302c00133002002302d00140a80054a14a2812a266042602c6eacc0a8010cdd2a4004660526054604e6ea8c054c068c09cdd5181518139baa0014bd704528204a8b204a330123758605200c5300137566034604e6ea8c068c09cdd5000c02600480a10240c098c098004c094004c090004c07cdd50081bae3021301e375400f159800980a800c4c8cc88cc02c0144c8cc88c8c8cc8966002603e604e6ea800626644b300130233029375401d13259800981218151baa001899912cc004cc07401cdd7181018169baa0018acc004cdc79bae3020302d37540046eb8c080c0b4dd5000c528c4cc07401cdd7181018169baa00240ad14a08158c064c0b8c0acdd5000980c8044590291980b1bac302d006298009bab301e302b375400300380120308992cc004c090c0a8dd5000c566003300198009bab301e302b37540110038012030a50a5140a5133025301a3756605c00c66e9520023302d302e302b37546032603c60566ea8c0b8c0acdd5000a5eb8229410294590291980b1bac302d008298009bab301e302b3754603c60566ea800600700240608140dd7181598141baa001300d02f8b204c37586052605460540026052604c6ea8c0a4c098dd500198149814981498148009814001181300099198008009bac30260022259800800c5a264b30013375e6050604a6ea800401a26030604a6ea800626600600660520048118c09c00502518109baa012302200130223023001301e375400f16407080e0600200244464b30010038991919911980480119b8a48901280059800800c4cdc52441035b5d2900006899b8a489035b5f20009800800ccdc52441025d2900006914c00402a00530070014029229800805400a002805101520445980099b880014803a266e0120f2010018acc004cdc4000a41000513370066e01208014001480362c80e901d1bac301f002375a603a0026466ec0dd4180e8009ba7301e001375400713259800800c4cdc52441027b7d00003899b8a489037b5f20003232330010010032259800800c400e264b30010018994c00402a6044003337149101023a200098008054c08c00600a805100a181280144ca6002015302200199b8a489023a200098008054c08c006600e66008008004805100a181280120463025001408866e29220102207d00003407c6eac00e264b3001001899b8a489025b5d00003899b8a489035b5f20009800800ccdc52441015d00003914c00401e0053004001401d229800803c00a0028039012203e3758007133005375a0060051323371491102682700329800800ccdc01b8d0024800666e292210127000044004444b3001337100049000440062646645300100699b800054800666e2ccdc00012cc004cdc4001240291481822903720443371666e000056600266e2000520148a40c11481b9022002200c33706002901019b8600148080cdc7002001203e375c0068110dc5245022c2000301a301b0092232330010010032259800980a000c4cdc524410130000038acc004cdc4000a40011337149101012d0033002002337029000000c4cc018cdc2000a402866e2ccdc019b85001480512060003406480c88a4d1365640041";
        return PlutusBlueprintUtil.getPlutusScriptFromCompiledCode(compiledCode, PlutusVersion.v3);
    }


    public static PlutusScript getUVerifyStateContract() {
        String compiledCode = "5913060101002229800aba2aba1aba0aab9faab9eaab9dab9a9bae0039bae002488888888966003300130053754015370e90034dc3a4001370e90022444464653001300a3754003300e00698070012444b30013006003899912cc004c024c03cdd5001c4c8c8c966002602e005133223322598009808000c566002602e6ea800e0051640611598009802000c566002602e6ea800e0051640611598009807800c566002602e6ea800e0051640611598009808800c566002602e6ea800e00516406115980099b87480200062b3001301737540070028b20308b202a405480a9015202a1330060032259800801466002602e6ea802e6e9520009180d980e000c88c8c8cc004004010896600200300389919912cc004cdc8803801456600266e3c01c00a20030064075133005005302300440746eb8c070004dd5980e800980f800a03a14bd6f7b63048c06cc070c070c070c070c070c070c070c070c070c070006460366038603860380032301b301c301c0019180d980e180e180e180e180e180e000c8c06cc070c070c070c07000644646600200200644b30010018a508acc004c00cc0780062946266004004603e00280c901c4dc0240052301b301c301c301c301c301c301c301c001911919800800801912cc00400629422b30013371e6eb8c07800400e2946266004004603e00280c901c48cdc4240006e340064b30010018a518a5040652301b301c301c301c301c301c301c301c301c001912cc004c048c060dd500144c8c8c8c8c8c8c8c8c8c8ca600264b300130250018acc004cdc4a4008604800316898091812000a0468b204c3754604e003375c604e017375c604e015375a604e013375a604e011375a604e00d375a604e00b375c604e009375a604e007375c604e00491111111112cc004c0c802e26603e6eb0c0c404489660020050188991801181a8019bae303300240c51640bc30270013026001302500130240013023001302200130210013020001301f001301e0013019375400516405d2301b301c301c301c301c301c001488888888888888888a6002605a025375860580252232330010010032259800800c5300103d87a80008992cc004c0100062602c6606000297ae089980180198190012058303000140b922323259800980d000c4c9660026036605a6ea8c054c0b8dd5180a98171baa005899b88001004899b8900100440b06eb4c0c0c0b4dd50014566002604a00314a114a2815902b18159baa001302e302b3754602460566ea800a44b30010018a40011300a33002002302f00140b12233008002001912cc0040062900044c028cc008008c0bc00502c4888c8cc88cc008008004896600200300389919912cc004cdc8803801456600266e3c01c00a200300640c1133005005303600440c06eb8c0bc004dd698180009819000a06033013004003148001222222229800981a8044dd6181a0044cc01801c8cdd7981a98191baa303530323754603260646ea8004cdd2a4004660686ea40bd2f5c130040049112cc0066002601e0054a14a281922b300132330010010032259800800c528c56600264b30013013375c6074606e6ea80062b30013013375c6034606e6ea80062660120086eb8c068c0dcdd5000c528206a8a5040d46072003133002002303a0018a5040d081ba266e3c00cdc9194c004006007489004004444b30010028800c66002007303b00299b8a0013232323371466e28cdc51bae303d00337306e64dd7181e8011bae303d001329800800cdd6181f181f80152201004004444b30010028800c66002007304100299b8a00137306e64dd71820001200640f8607a0026078002606e6ea8c0e800900320708a5040c914a08192600400522230219800801c00a002802122222229800981e181e003cdd6181d803d660026062606e6ea8016294629410364896600260666eb4c078c0e8dd5000c528c56600260666eb4c074c0e8dd5000c528c566003300130333370c60326eb4c070c0e8dd50009bad301e303a37540034a14a281c22946264660020026eb0c070c0ecdd5001112cc00400629462b3001323301d00525980099baf3025303e37540026e98c966002607000314bd6f7b63044c8c8cc0040052f5bded8c044b300100189982219bb04c01014000374c00697adef6c608994c004dd71821000cdd59821800cc11c0092225980099b904890000389982419bb04c01014000374c00e00b15980099b8f4890000389982419bb04c01014000374c00e003133048337606ea400cdd300119803003000a08841103045001410c646600200297adef6c602259800800c4cc10ccdd8261014000375000697adef6c608994c004dd71820800cdd69821000cc1180092225980099b904890000389982399bb04c01014000375000e00b15980099b8f4890000389982399bb04c01014000375000e003133047337606ea400cdd400119803003000a086410c3044001410881e8cdc19bad3021303e375400a60146eb0c07cc0f8dd5002c4cdd79820981f1baa3041303e3754002604c660806ea40092f5c114a081e0dd7181f800c4cc008008c100006294103a207a40e081c1038244446645300130410029bac30413042002cc0056600200314a314a081fa94294503c2444b300159800cc00400694294503f4528c56600200319800918151982219ba548008cc110dd4800a5eb80cc11130103d87a80004bd704c100dd5182218209baa034911919800800801112cc00400629422b300133017004375c609000314a31330020023049001410c82324b30010018a6103d87a800089815198221822800a5eb81043489660020031480022604466004004608e00282212222233225980099b874802001a2b300130413047375400513259800982098241baa0018992cc004c10cc124dd5000c4c8c8c8c8c8c8c8ca60026eb4c1540066eb8c15401e6eb4c15401a6eb4c1540166eb0c1540126eb4c15400e6eb4c154009222222259800982e80444cc128dd6182e007912cc00400a26609800a44b30010028992cc004c15cc174dd5000c5660026096602e04315980099b8f00b375c60c260bc6ea800626603603e97ae1011e581c11bcb8e4a79304e23bcd5e2bf628907f9b998f43902f41d1db43998100811e581c81c0d7f845fb2cf5d23453dc63997595688973c860786503c4d47b1100452820b88a5041711641706032646600200204244b30010018a5eb822660c260bc60c40026600400460c60028302264600460c40066eb8c18000905e44c8c008c18000cdd7182f00120b88b20b4182a800982a0009829800982900098288009828000982780098251baa0018b2090304c3049375400316411c60966098609860906ea8c12cc120dd500145904644cc89660026088011159800982198249baa0048992cc004c10cc128dd5000c4c8cc0940044c966002608c60986ea8006264b30013046304d3754003132330060011323259800982518281baa001899912cc004cdc3980600b19b800010028acc004c10000a2b3001337120029001456600266e3cdd7182b18299baa003375c60ac60a66ea80222b3001323303402a2323371e6e48cdc51bae30590019800a50a4009375a60b260b4002bc9001982a9baa3058305537540026eb8c158c14cdd5004456600266e24c074dd6181d18299baa046375a605a60a66ea80222b300198009bae3031305337540113758607460a66ea811a02880f22b300159800acc004dd6182b18299baa0058a518a50415114a3133030375860ac60a66ea8014dd7181d18299baa0084145159800acc004cdc79bae303a305337540106eb8c0e8c14cdd500444cdd7991919181f1982c182c8019982c182c8011982c181c982b1baa00833058303a30563754010660b0606e60ac6ea8020cc160c0b8c158dd50041982c1ba8337006eb4c0e0c158dd500424002660b060b2002660b0606860ac6ea8020cc160c0f4c158dd5004182d182d182d000982c982c982c982c982c982c800982c00098299baa0080088a5041451598009980c00d00445660026604e606260a66ea811cdd6981598299baa00889981280a1bae303a3053375401114a0828a2941051452820a28a50414514a0828a2941051452820a28a50414514a0828a2941051452820a2301d002301d33009014480062c8278c030004cc01c04920023051304e37540031641306060609a6ea8c0d0c134dd5182818269baa0018b20963302101a25980099baf3050304d37546068609a6ea8004c03012a3300137566068609a6ea8c0d0c134dd5000c12a6eb8c140c144c144c144c144c144c144c144c144c144c134dd5001202c8a50412c609c60966ea80062c8248c134c138c138c128dd5182698251baa0048b20908992cc004c110026264b30013045304b37540031323259800982398269baa0018992cc004c11cc138dd5000c4c8cc01c00456600266e3cdd7181b98281baa0010048acc004c01802a26601a02297ae111e581c11bcb8e4a79304e23bcd5e2bf628907f9b998f43902f41d1db43998100811e581c81c0d7f845fb2cf5d23453dc63997595688973c860786503c4d47b11004528209c8a50413860a4609e6ea80062c8268c0c4c138dd5181a98271baa3051304e3754003164130660440464607730013756606a609c6ea8c0d4c138dd5000c12e00480f0dd7182798261baa0018b209430073300300e480062b3001303800989919912cc004c11cc134dd5000c4c8c9660026092609e6ea8006264b30013049305037540031323302b00115980099b87300b0150068acc004cc09004cdd7181c98291baa0018acc004cdc78021bae305530523754003159800cc004c0fcc144dd5181b98291baa001a50a51414115980098169bac30393052375408b159800981f80344c0200322941050452820a08a50414114a082822941050452820a030543051375400316413c606660a06ea8c0dcc140dd5182998281baa0018b209c330240252303d98009bab303730503754606e60a06ea800609b00240806eb8c144c138dd5000c5904c180c0009804000998018072400314a0824904912cc004c110c128dd5000c5284528a092412044646600200200644b30010018a5eb822653001375c6098003375a609a003305100248896600266e1c01c00a2660a46ea400ccc01801800626600c00c0028270609e00282688966002608660926ea800a264646464646464653001375a60aa003375c60aa00f375a60aa00d375a60aa00b375860aa009375a60aa007375a60aa00491111112cc004c1740222660946eb0c17003c896600200513304c00522598008014052264600460c40066eb8c18000905e44c8c008c18000cdd7182f00120b88b20b4182a800982a0009829800982900098288009828000982780098251baa0028b209041186603601a4b30013375e6094608e6ea8004c0181122b300132330010013302e3756605e60906ea8008114896600200314a11323259800998020021827801c528c4c0e0dd698258012092375c6092002609800282523300198009bab302e30473754003044821a020a50a51411514a0822a29410451800800a294103f207e8acc006600200f4a14a281fa29462b30010078acc004c0e8c100dd500744c966002607460826ea800626644b3001303d00188024566002606200310048acc004c0f000626603a00426464b3001303f304537540031323259800982018239baa001899198110008acc004cc06c028dd7181818249baa0078acc004c0d8c04c0162b300198009bab3030304937540070469bae304c3049375400e80922b30015980099b8848000dd6981598249baa00789980e8059bad30213049375400f14a0823a2b300159800cc004c0d8c120dd5181718249baa007a50a51411d13375e646464646464606e660a260a400c660a260a400a660a260a4008660a260a4006660a260a4004660a260a4002660a26ea0cdc01bad3031304f375401a900099828981698279baa007305330533053001305200130510013050001304f001304e0013049375400e00314a0823a2b30013300e0100018acc004cdc498099bac3030304937540786eb4c08cc124dd5000c660026eb8c09cc124dd5000cdd6181818249baa03c80520288a50411d14a0823a29410474528208e8a50411d14a0823a2941047182598241baa0018b208c302a304737540026092608c6ea80062c82216600200314c103d87a800089816998239824000a5eb810461919800800806112cc004006297ae0899912cc004c966002606c60906ea8006266e3c118dd7182618249baa0018a50411c609660906ea8c12cc120dd500144cc128008cc0100100062660080080028230c124004c1280050474528208441088210c114c108dd500098209baa30453042375406b164100604860826ea8c0a0c104dd5182218209baa00e8b207e8a5040fc81fa294103f0c100c100c100010cc088dd5981f80201c844c9660026022602e6ea800626464653001375c603c003301f0019bae301e0039b99375c603c00491112cc004c08c00e2660206eb0c08800c89660020051300b302500c899180118130019b99375c604800481122c8100603c002603a00260306ea80062c80b0c068009018180a1baa001370e9001180b001c590141bac30150013015001301037540071640386022601c6ea801088c8cc00400400c88cc00c004c00800a2b30013008003899192cc004c024c03cdd51809980a0014528c5900e1bad3012001300e37540091640308060601a601c002601a0088a4d13656400c1";
        return PlutusBlueprintUtil.getPlutusScriptFromCompiledCode(compiledCode, PlutusVersion.v3);
    }

    public static PlutusScript getLibraryContract() {
        String compiledCode = "589f010100229800aba2aba1aab9faab9eaab9dab9a9bae002488888896600264646644b30013370e900118039baa0018994c004c02c006601660180032259800800c528456600266e3cdd718068008044528c4cc008008c03800500920184888cc004004dd618071807980798079807980798079807980798061baa300e00818041baa0018b200c300800130083009001300800130043754011149a26cac80101";
        return PlutusBlueprintUtil.getPlutusScriptFromCompiledCode(compiledCode, PlutusVersion.v3);
    }

    public static PlutusScript getLibraryContract(byte[] paymentCredential) {
        PlutusScript plainScript = getLibraryContract();

        String parameterizedScript = ScalusScriptUtils.applyParamsToScript(plainScript.getCborHex(),
                BytesPlutusData.of(paymentCredential));
        return PlutusV3Script.builder().cborHex(parameterizedScript).build();
    }

    public static PlutusScript getUVerifyStateContract(String scriptHash, String proxyTokenName) {
        PlutusScript plainScript = getUVerifyStateContract();

        String parameterizedScript = ScalusScriptUtils.applyParamsToScript(plainScript.getCborHex(),
                BytesPlutusData.of(HexUtil.decodeHexString(scriptHash)),
                BytesPlutusData.of(HexUtil.decodeHexString(proxyTokenName)));
        return PlutusV3Script.builder().cborHex(parameterizedScript).build();
    }

    public static PlutusScript getUVerifyStateContract(String txHash, int outputIndex) {
        PlutusScript proxyContract = getUverifyProxyContract(txHash, outputIndex);
        String proxyScriptHash = validatorToScriptHash(proxyContract);

        if (proxyScriptHash == null) {
            throw new IllegalArgumentException("Script hash of proxy contract is null");
        }

        String proxyTokenName = getProxyStateTokenName(txHash, outputIndex);

        PlutusScript plainScript = getUVerifyStateContract();

        String parameterizedScript = ScalusScriptUtils.applyParamsToScript(plainScript.getCborHex(),
                BytesPlutusData.of(HexUtil.decodeHexString(proxyScriptHash)),
                BytesPlutusData.of(HexUtil.decodeHexString(proxyTokenName)));
        return PlutusV3Script.builder().cborHex(parameterizedScript).build();
    }

    // ── Tokenizable Certificate ───────────────────────────────────────────────

    private static PlutusScript getTokenizableCertificateBaseContract() {
        String compiledCode = "591132010100229800aba2aba1aba0aab9faab9eaab9dab9a48888889660033001300337540112232330010010032259800800c528456600266e3cdd71805000801c528c4cc008008c02c00500520109ba5480024446466446600400400244b3001001801c4c8cc896600266e4401c00a2b30013371e00e0051001803201489980280298080022014375c60120026eb4c028004c03000500a191919800800803112cc00400600713233225980099b910090028acc004cdc78048014400600c805a26600a00a60220088058dd718050009bab300b001300d001402c297adef6c601480024600e6010003370e90014dc52450354434e009ba54800a44646600200200644b30010018a508acc004c00cc02800629462660040046016002802900848c01cc020c020c0200064464660020020064466006002600400523007300830080019b87480026e1d20049baf4c103d87980009b884800122222222222222229800980b8084c05804244646600200200644b30010018a60103d87a80008992cc004c010006260266603400297ae0899801801980e001202c301a00140612232598009803800c4c8c96600260380050048b2032375c6034002602c6ea800e2b3001300e0018acc004c058dd5001c00a2c80ba2c80a1014180a1baa00291192cc004c01c0062b3001301637540070028b202e8acc004c0380062b3001301637540070028b202e8b2028405060286ea800a4464b30013007001899192cc004c07000a0091640646eb8c068004c058dd5001c566002601c0031323259800980e00140122c80c8dd7180d000980b1baa0038acc004c01800626464b3001301c0028024590191bae301a0013016375400716405080a1014180a1baa002488888a6002603800d301c301d0069111980380192cc004c05660026eacc058c074dd5000c00e602800480ba266ebcc080c074dd51810180e9baa00130133301f375200697ae08a50406d22598009806180d1baa0028991919194c004c0880066eb8c0880126eb8c08800922259800981300244cc054dd61812803112cc00400a26601c00a01513230023029003375c604e004812a2c811860440026042002604000260366ea800a2c80c92222332259800980800144c8cc02001c4c8c8c8c8ca60026eb0c0a00066eacc0a0c0a400644464b3001301a3028375400313259800980d98149baa00189919192cc004c0c400a2646644b300130210028acc004c0c0dd5001c0062c818a2b300130280028acc004c0c0dd5001c0062c818a2b300130200028acc004c0c0dd5001c0062c818a2b30013370e9003001456600260606ea800e0031640c515980099b874802000a2b3001303037540070018b20628b205c40b8817102e205c302d375400226604200444b30010028998129bac30293030375400e466e3cdd7181a18189baa00100a8992cc004c088c0c0dd5000c4c8c8ca60026eb8c0dc0066070003375c606e00737326eb8c0dc009222259800981e001c4cc0acdd6181d801912cc00400a26016607c0191323002303f00337326eb8c0f400903b4590390c0dc004c0d8004c0c4dd5000c5902f1819801206230300038b205c3758605e002605e00260546ea80062c8140c0b0c0a4dd5000c59027191919800800802912cc0040062980103d87a80008992cc004cdd78021815800c4c09ccc0b8c0b00052f5c1133003003303000240a8605c0028160cdd2a400866054603c660546ea40092f5c097ae098121baa00c9bac30280059bac30280049bac30280039bab302800248888888966002603c00b198009bae3030302d37540293302200423375e6062605c6ea80040d2604b3001001807522010354434e00409d3301800225980098134c004dd5981398171baa001807d2210354434e0040a113375e6062605c6ea8c0c4c0b8dd50009812198181ba900f4bd704528205848888c966002604660626ea800a264b300130233032375400313259800981298199baa00189919192cc004c0ec00a26466044002266038004264b3001302a30383754003132598009815181c9baa0018992cc004c0ccc0e8dd5000c4c8c8c8c8ca60026086003375c6086007375c60860049112cc004c11c012266446605e00226605c00a2b30010178acc00405a2b30010148acc004c0ccdc680c45660033001598009bac303e3045375401f14a314a082329429450434566002660820406eb8c0dcc114dd5007c56600266ebc038c100cc11cdd480c25eb822b30013371e00403115980099baf0014c103d87a80008acc004c0da6002033026801a07e8acc004c0d00163300101f9bae30483045375401f018407914a0821a2941043452820868a50410d14a0821a2941043452820868a50410d14a0821a294104345282086375c608c010608c00f1641103043001304200130410013040001303b37540031640e4607a60746ea80062c81c0c0acc0e4dd5181e181c9baa0018b206e9800806c06601680e8c0e800e2c81c0c0e4004c0e4004c0d0dd5000c59032181b18199baa0018b2062302430323754606a60646ea800a2c8180c0a6600200b012981400220564566002604a00b13322980099198008009bac30293030375400444b30010018a508acc004cc0b4030dd7181a000c528c4cc008008c0d400502f2064cc0040266eb8c0c8c0bcdd5000c0090084c09e600200701098130012052cc004012021002405091112cc004c090c0c8dd5000c4c966002604860666ea8006264b3001302d30343754003132323232329800981e800cdd7181e801cdd7181e8012444b300130410048991981418208040998138020acc004c0b0dc6808c56600201f159800807456600201b1598009817cc00404a03f00240e115980099b8f00101189816802452820788a5040f114a081e2294103c452820788a5040f06eb8c1000222c81f0607a002607800260760026074002606a6ea80062c8198c0dcc0d0dd5000c59032181298199baa3036303337540031640c4375c6060605a6ea8050cc03c00c03a26464b30013020302e375400313259800981018179baa0018992cc004c0a4c0c0dd5000c4c8c8c8c8ca60026072003375c6072007375c60720049112cc004c0f401226466048607a010266046008264b30013033303a3754003130339800807c07200681aa26644b300130359800808c07a66e2922104000de1400000540dd159800981acc00404603d00140dd13303201225980099baf3041303e37546082607c6ea8004c0d0cc100dd4801a5eb822606d30013756606e607c6ea800603f00240e114a081e2294103b45282076375c607c60766ea8004cdc524504000643b00000340e4605c60746ea8cc07004006cdd7181e00445903a0c0e4004c0e0004c0dc004c0d8004c0c4dd5000c5902f181998181baa0018b205c3021302f37546050605e6ea8c0c8c0bcdd5000c5902d1980c80292cc004c09e60026eacc0a0c0bcdd5181418179baa0018084c09800902944cdd7981918179baa3032302f37546050605e6ea8004c094cc0c4dd480825eb82294102d1bae3030302d3754028815902b0c0a0c0a0c0a0c0a0004c09cc09c004c098004c094004c080dd50061bae3022301f375400b159800980b80144c8cc88cc0280244c8c8c8ca60026eacc0a40066eb0c0a4c0a8c0a8c0a8c0a8006660226eb0c0a40108cdd7981518139baa0010079bac30290039bac302900248888966002603860546ea800e264b30013024302b37540031332259800980f800c5a2b300130260018992cc004c080c0b8dd5007466002604f3001009801cc0980050294c0c8c0bcdd50074896600266e400080062980103d87980008acc004cdc7801000c530103d87a80008a6103d87b800040bc817922259800981198189baa0028994c004c0d8006606c606e0039800804c01e91010040609112cc004c09cc0d4dd5000c4c966002604e606c6ea8006264b3001302930373754003132323259800981f80144c8cc0980044cc0800084c966002605c60786ea8006264b3001302e303d375400313259800981b981f1baa001899191919194c004c11c0066eb8c11c00e6eb8c11c00922259800982580244cc88cc0cc0044cc0c8014566002b300130413048375402d14a3130383301801b375c609860926ea8059047456600203515980099baf00e30443304b375203697ae08acc004cdd780780ac4cdd780080b4528208e8a50411d14a0823a29410471bae304a008304a0078b20901823800982300098228009822000981f9baa0018b207a3041303e37540031640f0605e607a6ea8c100c0f4dd5000c5903b4c00404a02100e4084607c0071640f0607a002607a00260706ea80062c81b0c0e8c0dcdd5000c590351814181b1baa3039303637540031640d0303237540051323322323298009bae303a001981d181d800e600201b00b801a038981d0024dd7181d001244444b3001302d303b3754007132598009816981e1baa0018992cc004c0d8c0f4dd5000c4c8c8c8c8ca6002608c003375c608c007375c608c0049112cc004c128012266446606400226606200a264b3001303a3048375400313259800981d18249baa0018992cc004c10cc128dd5000c4c8c8c8c8ca600260a6003375c60a6007375c60a60049112cc004c15c012266446607e00226607c00a2b300159800982219812010813c566002609a60a86ea806e2946260886604804e6eb8c160c154dd500da0a68a50414d159800813456600266e3c03c0862b30013375e01c60a0660ae6ea409d2f5c115980099b8f01101a8acc004cdc780800f456600266ebc048076266ebc00406e2941053452820a68a50414d14a0829a2941053452820a68a50414c6eb8c158020c15801e2c82a060a600260a400260a200260a000260966ea80062c8248c134c128dd5000c59048181d98249baa304c3049375400316411d300101e80e406902d1bae304900830490078b208e1823000982280098220009821800981f1baa0018b20783040303d37540031640ec605c60786ea8c0fcc0f0dd5001c5903a0c0e8004c0e4008c0dc004dd7181b00098191baa00240c08b205a375c6062605c6ea8056264b30013020302e375401d13259800981418179baa0018991919194c004dd7181b800cc0dcc0e0007300100a80440190194dd7181b8024c0dc00e6eb8c0dc009222222598009815981c9baa0048992cc004c0acc0e8dd5000c4c966002606860766ea800626464646465300130440019bae30440039bae30440024889660026090009133223303000113302f0051325980099b8f0100198acc004c0d804a2b30013035371a033159800998218100074566002607f300102180dc00504145660026607803a4b30013375e609660906ea8c12cc120dd50009821998251ba900f4bd7044c10260026eacc104c120dd5000c07200482122941046456600266e3c00c0422b30013375e00401f15980099b8f00500e8acc004cdc7802009c4cdd7803260103d87a80008a50411514a0822a29410454528208a8a50411514a0822a29410454528208a8a50411514a0822966002607c608a6ea8c0e8c118dd51981400e80d4404a266e29220104000de1400001241106eb8c11c020c11c01e2c8228608800260860026084002608200260786ea80062c81d0c0f8c0ecdd5000c590391816181d1baa303d303a37540091640e0303700130360013035001303037540031640b86064605e6ea803a2c8168dd7181898171baa01540b08160dd7181798161baa001302b37540271640a8605c60566ea8c0b8c0acdd5181218159baa302e302b37540071640a430293029001302800130270013022375401c604600260466048002603e6ea80162c80e901d180e1baa0032232598009808980f9baa0018992cc004c044c080dd5000c4c966002602660426ea80062646464b3001302900289980798140018998048008800c590261813800981380098111baa0018b204030243021375400316407c602460406ea8c064c080dd5181198101baa0018b203c3300a002259800980c4c004dd5980c98101baa301930203754003002a4410354434e00406913375e604660406ea8c08cc080dd5180c98101baa001301633022375200497ae08a504078229344d95900101";
        return PlutusBlueprintUtil.getPlutusScriptFromCompiledCode(compiledCode, PlutusVersion.v3);
    }

    /**
     * Returns the tokenizable-certificate Plutus V3 script parameterized with the
     * given one-shot {@code init_utxo: OutputReference}.
     */
    public static PlutusScript getTokenizableCertificateContract(String txHash, int outputIndex) {
        PlutusScript plainScript = getTokenizableCertificateBaseContract();
        PlutusData outputReference = ConstrPlutusData.of(0,
                BytesPlutusData.of(HexUtil.decodeHexString(txHash)),
                BigIntPlutusData.of(outputIndex));
        String parameterizedScript = ScalusScriptUtils.applyParamsToScript(plainScript.getCborHex(), outputReference);
        return PlutusV3Script.builder().cborHex(parameterizedScript).build();
    }

    // ── Fractionized Certificate ──────────────────────────────────────────────

    /**
     * Returns the base (un-parameterized) fractionized-certificate Plutus V3 script.
     */
    private static PlutusScript getFractionizedCertificateBaseContract() {
        String compiledCode = "591298010100229800aba2aba1aba0aab9faab9eaab9dab9a48888889660033001300337540112232330010010032259800800c528456600260066eb8c028006294626600400460160028029008488c8cc00400400c896600200314a115980099b8f375c601400200714a3133002002300b001401480424b30010018a518a504015374a90004888c8cc88cc008008004896600200300389919912cc004cdc8803801456600266e3c01c00a20030064029133005005301000440286eb8c024004dd698050009806000a0143232330010010062259800800c00e2646644b30013372201200515980099b8f0090028800c01900b44cc014014c04401100b1bae300a00137566016002601a002805852f5bded8c02900048c01cc0200066e1d20029b8a4890346524e009ba54800a44646600200200644660060026004005370e9000488c8cc00400400c896600200314a115980098019805000c528c4cc008008c02c00500520109180398041804000cdc3a4009375e98103d87980009b8848001222222222222222229800980c008cc05c04644646600200200644b30010018a6103d87a80008992cc004c010006260246603600297ae0899801801980e801202e301b001406522598009804180a9baa002899191919912cc004c07c00e26601c6eb0c0780108966002005008899180118110019bae302000240791640706eb8c070004dd7180e001980e000980d800980b1baa0028b202891192cc004c0240062b3001301737540070028b20308acc004c0340062b3001301737540070028b20308b202a4054602a6ea800a4464b30013009001899192cc004c07400a0091640686eb8c06c004c05cdd5001c566002601a003159800980b9baa003801459018459015202a301537540052232598009804800c4c8c966002603a0050048b2034375c6036002602e6ea800e2b3001300d001899192cc004c07400a0091640686eb8c06c004c05cdd5001c566002600c003132323298009bad301d0019bae301d0039bae301d00248896600260420090088b203c180e800980e000980b9baa0038b202a405480a8c054dd500124444444653001301b375400322233009003259800980b4c004dd5980b98101baa001801cc05400901844cdd7981198101baa3023302037540026028660446ea400d2f5c114a080f2603e0109112cc004c04400e2646600c004264646464653001375860500033756605060520032223259800980d98141baa0018992cc004c070c0a4dd5000c4c8c8c96600260620051323322598009811001456600260606ea800e0031640c51598009813001456600260606ea800e0031640c5159800980f801456600260606ea800e0031640c515980099b874801800a2b3001303037540070018b20628acc004cdc3a401000515980098181baa003800c5903145902e205c40b8817102e18169baa001133021002225980080144cc084dd6181398181baa00723371e6eb8c0d0c0c4dd500080544c966002604660606ea800626464653001375c606e00330380019bae30370039b99375c606e00491112cc004c0f000e2660566eb0c0ec00c89660020051300b303e00c8991801181f8019b99375c607a00481da2c81c8606e002606c00260626ea80062c8178c0cc0090311818001c5902e1bac302f001302f001302a37540031640a0605860526ea80062c8138c8c8cc004004014896600200314c0103d87a80008992cc004cdd78021815800c4c094cc0b8c0b00052f5c1133003003303000240a8605c0028160cdd2a4008660546038660546ea40092f5c097ae098121baa0079bac30280059bac30280039bab30280024888888966002603c009198009bae302f302c375401d3301d00323375e6060605a6ea80040ce60453001001806d22010346524e004091330160022598009811cc004dd5981218169baa00180752210346524e00409513375e6060605a6ea8c0c0c0b4dd50009810998179ba900e4bd704528205648888c966002604660606ea800a264b300130213031375400313259800981298191baa00189919192cc004c0e800a2646603c002266040004264b3001302a30373754003132598009814181c1baa0018992cc004c0c0c0e4dd5000c4c8c8c8c8c8c8ca60026088003375a608800b375a608800937586088007375c6088004911112cc004c12801a266446605e00226607600844b30010028998190048acc0040762b300101c8acc00406a2b30013037371a03d159800cc004c110dd6182098251baa015a50a514121159800998228129bae303a304a375402b15980099baf01430433304c375203c97ae08acc004cdc780200f456600266ebc00d300103d87a80008acc004c0dc0222b30013370e00e011159800981c004c66002049375c609a60946ea805603c811a2941048452820908a50412114a082422941048452820908a50412114a082422941048452820908a50412114a082422646004609e0066eb8c13400904b1bae304900c304900b8b208e18220009821800982100098208009820000981f800981d1baa0018b2070303c303937540031640dc605060706ea8c0ecc0e0dd5000c590364c00403603100b406860720071640dc6070002607000260666ea80062c8188c0d4c0c8dd5000c59030181098189baa3034303137540051640bc604d3001005808cc09401102822b30013022004899914c004cc0a8dd6181298171baa00123302a00a001cc0040226eb8c0c4c0b8dd5000c0090074c092600200700f9811801204ccc00401201f002404491112cc004c090c0c4dd5000c4c966002604460646ea8006264b3001302a303337540031323232323232329800981f000cdd6981f002cdd6981f0024dd6181f001cdd7181f001244444b3001304400689919814182200609981a001912cc00400a2660560102b30013030371a02f15980080ac566002029159800809c56600266e3c00c05e2b300130300078acc004cdc3803003c4c0c40222941041452820828a50410514a0820a2941041452820828a50410513230023048003375c608c0048220dd718218064590410c0f8004c0f4004c0f0004c0ec004c0e8004c0e4004c0d0dd5000c59032181b18199baa0018b2062302230323754606a60646ea80062c81806eb8c0bcc0b0dd5007192cc004c07cc0b0dd5000c4c966002603a605a6ea8006264b30013021302e3754003132323259800981b00144cc064c0d400c4cc06c00440062c8198c0d0004c0d0004c0bcdd5000c5902d181898171baa0018b2058301d302d37546048605a6ea8c0c0c0b4dd5000c5902b1980b1bac302f00b2598009811cc004dd5981218169baa3024302d375400300ea450346524e00409513375e6060605a6ea8c0c0c0b4dd5181218169baa00130213302f375201c97ae08a5040ad13232332259800981118179baa0028992cc004c080c0c0dd5000c4c966002605060626ea80062646464646464653001303c0019bad303c0059bad303c0049bac303c0039bae303c00248888966002608400d13233026304200c133032003225980080144cc0a4020566002605c02515980099b89012006899b87980080b408a00881c804a294103f4528207e899180118230019bae304400241086eb8c1040322c81f860780026076002607400260720026070002606e00260646ea80062c8180c0d0c0c4dd5000c5902f181018181baa302730303754606660606ea800a2c8170cc060014966002604b30013756604c605e6ea8c098c0bcdd5000c0426048004813a266ebcc0c8c0bcdd5181918179baa3026302f37540026046660626ea40412f5c114a08168dd69818981918190011bae3030001302c375401c815102a0c0a0c0a0c0a0c0a0004c09cc09c004c098004c094004c080dd50059bae3022301f3754009159800980a801c4c8cc88cc0200104c8ca60026eb0c09c0066eb0c09cc0a0c0a0c0a0c0a0c0a0c0a00066601c6eb0c09c0088cdd7981418129baa0010054889660026032604c6ea8006264b3001301e302737540031332259800980e000c5a2b300130200018992cc004c074c0a8dd5005466002604330013756605c605e605e605e605e60566ea805a0073020001408d302e302b3754015225980099b900020018a6103d87980008acc004cdc7801000c530103d87a80008a6103d87b800040ac815922259800981018169baa0028994c004c0c8006606460660039800805c01e91010040489112cc004c090c0c4dd5000c4c966002604460646ea8006264b3001302630333754003132323259800981d80144c8cc07c0044cc0840084c966002605660706ea8006264b3001302930393754003132598009818981d1baa0018991919191919194c004c1140066eb4c1140166eb4c1140126eb0c11400e6eb8c1140092222259800982580344cc88cc0c00044cc0f00108966002005133033009159800acc004c104c128dd500e4528c4c0e4cc078084dd7182718259baa01c4125159800810456600266ebc050c110cc134dd4810a5eb822b30013375e02a03713375e00603914a0824a2941049452820928a50412513230023050003375c609c0048260dd718250061825005c590480c114004c110004c10c004c108004c104004c100004c0ecdd5000c59039181e981d1baa0018b2070302930393754607860726ea80062c81ba60020290108072036303a0038b207030390013039001303437540031640c8606c60666ea80062c8188c088c0c8dd5181a98191baa0018b206018171baa0028991991191919194c004dd7181c000cc0e0c0e40073001011806c0150184c0e001a6eb4c0e00126eb4c0e000e6eb0c0e00092222222598009817181d9baa0058992cc004c0b0c0f0dd5000c4c9660026068607a6ea8006264646464646465300130480019bad30480059bad30480049bac30480039bae304800248888966002609c00d133223303300113303f004225980080144cc0d80244c9660026082609c6ea8006264b3001303f304f375400313259800982398281baa0018991919191919194c004c16c0066eb4c16c0166eb4c16c0126eb0c16c00e6eb8c16c0092222259800983080344cc88cc1180044cc1480108966002005133049009159800acc004c13ccc0d00c40de2b300130573060375405314a31304f33034037375c60c860c26ea80a505f452820be8acc0040da2b30013371e02e06315980099baf016305a33063375206e97ae08acc004cdc380d814456600266e1c06809e2b30013375e6e9c064dd3813456600266e3c0600b22b30013375e03805713375e00605314a082fa294105f452820be8a50417d14a082fa294105f452820be8a50417d14a082fa264600460cc0066eb8c1900090621bae306000c306000b8b20bc182d800982d000982c800982c000982b800982b00098289baa0018b209e305330503754003164138607e609e6ea8c148c13cdd5000c5904d4c0040aa04d02440c513230023053003375c60a20048278dd718268061826805c5904b0c120004c11c004c118004c114004c110004c10c004c0f8dd5000c5903c1820181e9baa0018b2076302c303c3754607e60786ea80162c81d06070002606e002606c002606a00460660026eb8c0c8004c0b8dd500120584590291bae302d302a37540191323298009bae302f0019bad302f30300019bae302f0024889660026042605c6ea803a264b30013026302f37540031323232323322332298009bae303b002981d981e001566002605400314c0103d87a80008a6103d879800040d9980080a404201480da6eb8c0ec022607600f375a607600d37586076008911111112cc004c0c8c0fcdd5002c4c966002606060806ea8006264b300130383041375400313232323232323298009826000cdd69826002cdd698260024dd61826001cdd71826001244444b30013052006899911981b800899821802112cc00400a2660740122b30013371e02c049159800982000cc566002607e6e340922b3001303f0258acc004cdc481280ec566002b3001304c0138a51899827009919b8f00102741411598009982681681345660026608605c4b30013375e60ac60a66ea8c158c14cdd500098261982a9ba90274bd7044cdc3cc004dd5982518299baa001815c06d04b013452820a28acc004cdc780200b456600266ebc00c0562b30013370e01002915980099b8700701b8acc004cdd79ba7006374e02715980099b8f00501a899baf0090188a50414114a082822941050452820a08a50414114a082822941050452820a08a50414114a082822941050452820a08a50414114a08282264600460ae0066eb8c1540090531bae305100c305100b8b209e18260009825800982500098248009824000982380098211baa0018b20803044304137540031640fc606060806ea8c10cc100dd5002c5903e0c0e8008cdc0800804981c0009bad3037001303700130360013035001303037540031640b86064605e6ea803a2c8168605e00260546ea80310282050375c605660506ea8004c09cdd5005459026181518139baa302a30273754603c604e6ea8c0a8c09cdd5000c590250c09cc09c004c088dd5006981180098119812000980f9baa0048b203a4074301e301f007229344d9590011";
        return PlutusBlueprintUtil.getPlutusScriptFromCompiledCode(compiledCode, PlutusVersion.v3);
    }

    /**
     * Returns the fractionized-certificate Plutus V3 script parameterized with the
     * given one-shot {@code init_utxo: OutputReference}.
     */
    public static PlutusScript getFractionizedCertificateContract(String txHash, int outputIndex) {
        PlutusScript plainScript = getFractionizedCertificateBaseContract();
        PlutusData outputReference = ConstrPlutusData.of(0,
                BytesPlutusData.of(HexUtil.decodeHexString(txHash)),
                BigIntPlutusData.of(outputIndex));
        String parameterizedScript = ScalusScriptUtils.applyParamsToScript(plainScript.getCborHex(), outputReference);
        return PlutusV3Script.builder().cborHex(parameterizedScript).build();
    }

    // ─────────────────────────────────────────────────────────────────────────

    public static PlutusScript getUverifyProxyContract(Utxo utxo) {
        return getUverifyProxyContract(utxo.getTxHash(), utxo.getOutputIndex());
    }

    public static PlutusScript getUverifyProxyContract(String txHash, int outputIndex) {
        PlutusScript plainScript = getUVerifyProxyContract();

        PlutusData outputReference = ConstrPlutusData.of(0,
                BytesPlutusData.of(HexUtil.decodeHexString(txHash)),
                BigIntPlutusData.of(outputIndex));


        String parameterizedScript = ScalusScriptUtils.applyParamsToScript(plainScript.getCborHex(), outputReference);
        return PlutusV3Script.builder().cborHex(parameterizedScript).build();
    }

    public static String getMintOrBurnAuthTokenHash(CardanoNetwork network) {
        if (network.equals(CardanoNetwork.MAINNET)) {
            return "a8172157733dd50ef6f0f8d38e361745037f0a79c1f5da9b1d8079ff";
        }
        return "d3c25617941168e238038f1cf6542229b919bbd6fd2b8292ce176203";
    }

    public static String getMintStateTokenCode(CardanoNetwork network) {
        if (network.equals(CardanoNetwork.MAINNET)) {
            return "590b9301010032323232323232253330023232323232533233008300130093754004264646464646464a666024602a004264646464646464646464a666032601a012264646464646464646464646464646464646464646464a66605e60466030002264a666060605260626ea80044c94ccc0c4c094c0740184c94ccc0c8c0acc0ccdd500089919299981a19b8748010c0d4dd5000899299981a9817181b1baa00113232323232323232323232323232323232323232533304c304f00213302b01322533304e00213302d0092253330500021533304d304133302837566064609e6ea8c0c8c13cdd500da451ca8172157733dd50ef6f0f8d38e361745037f0a79c1f5da9b1d8079ff00375c606a609e6ea806454ccc134cdd7981898279baa3031304f37546064609e6ea806ccdd2a4004660a298011e581ca8172157733dd50ef6f0f8d38e361745037f0a79c1f5da9b1d8079ff004bd70099299982729998271823981b8008a5113303400101e132533304f3043303b001132533305030493051375400226464a6660a466e1d200430533754002264a6660a6609860a86ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc1b8c1c40084cc13402c894ccc1c00084cc13c01c894ccc1c800854ccc1bccdc781f9bae30543071375403a2a6660de60c66660946eacc150c1c4dd500f83381f8a99983799baf30533071375460a660e26ea807ccdd2a4004660e6609260e26ea80752f5c02a6660de664464a6660e460cc60e66ea80044c94ccc1ccc19cc1d0dd5182c183a9baa305830753754008266e2000400c4cdc48008019bad3077307437540022940c154c1ccdd5182b18399baa0023048307137540d86eb4c120c1c4dd500e8a999837a99983799b8f375c60a860e26ea80740fc54ccc1bccdc79bae30573071375403a6eb8c150c1c4dd501d8a99983799b8f375c609260e26ea8074dd7182498389baa03b1533306f3370e6eb4c190c1c4dd500e9bad3064307137540762a6660de66e1cdd6982698389baa01d375a609a60e26ea80ec54ccc1bccdd7982718389baa01d304e307137540762a6660de66e1cdd6982418389baa01d375a609060e26ea80ec54ccc1bccdc39bad304f3071375403a6eb4c140c1c4dd501d8a99983799b8f375c60e860ea60ea60ea60ea60ea60ea60ea60ea60ea60ea60ea60e26ea8074dd7182b98389baa03b13370e6eb4c158c1c4dd500e99b80375a60ac60e26ea80ed200114a029405280a5014a029405280a5014a02a6660de66e24c16cdd6182818389baa01d375a609e60e26ea807454ccc1bcc8cc004004dd6182898391baa01e22533307400114a2264a6660e464a6660e660ac6eb8c15cc1d4dd50008a999839982b1bae305b307537540022660b26eb0c168c1d4dd50381bae305b307537540022940528183b8010998018018008a5030770011533306f533306f3068375a609a60e26ea80745288a99983798341bad30643071375403a294454ccc1bcccc1bcc1a0cdc3182e9bad30563071375403a6eb4c134c1c4dd500ea504a229444c8cc004004dd6182798391baa01e22533307400114a2264a6660e464660a008c4a6660e866ebcc164c1d8dd50009ba6325333075306e00114bd6f7b6300991919800800a5eb7bdb180894ccc1ec0044cc1f0cdd82601014000374c00697adef6c60132323232533307c3372091010000213308001337609801014000374c00e00a2a6660f866e3d2210000213308001337609801014000374c00e0062661000266ec0dd48011ba600133006006003375660fa0066eb8c1ec008c1fc008c1f4004c8cc0040052f5bded8c044a6660f40022660f666ec13001014000375000697adef6c60132323232533307b3372091010000213307f337609801014000375000e00a2a6660f666e3d2210000213307f337609801014000375000e0062660fe66ec0dd48011ba800133006006003375a60f80066eb8c1e8008c1f8008c1f0004cdc19bad30693076375404460ba6eb0c14cc1d8dd5011099baf30583076375460b060ec6ea8004c1accc1e0dd480125eb805281bae307700213300300300114a060ee0022646609a08e464646466e3cdc919b8a0023337929412004001005375a60f060f20046eb8c1dc004c1ccdd5182a98399baa001375c60a660e26ea80745280a5014a029405280a5014a029404c94ccc1c0c1a4c1c4dd500089919191919191919299983d983f00109982d00091299983e8010980618400080689918011840808019b99375c60fe0042c6eb0c1f0004c1f0008dd7183d000983d0011b99375c60f000260f00046eb8c1d8004c1c8dd50008b183a0010991801183a0019bae307200216375c60de00260de0046eb4c1b4004c1b4008dd6183580098358011bad30690013069002375a60ce00260ce0046eb0c194004c194008dd6983180098318011bad30610013061002375c60be00260be0046eb8c174004c174008dd7182d800982d8011bae3059001305537540022c60ae60a86ea800458c0e4c14cdd5000982a98291baa00116302b001163303d021233304f3375e606e60a26ea800530103d87980004a094458dd6181898279baa019161613230023054003375c60a4004264600460a40066eb8c14000858dd6982680098268011bad304b001304b002375a609200260920046eb0c11c004c11c008dd6982280098228011bad30430013043002375c608200260820046eb8c0fc004c0fc008dd7181e800981e8011bac303b001303737540022c6072606c6ea800458c06cc0d4dd5180c181a9baa0013037303437540022c601a00c2c6eb8c0d4c0c8dd50008b180d0008b1bac30333034303430343034303430340023758606400260640046eb0c0c0004c0c0008dd6181700098151baa0252302d302e302e302e302e302e302e302e0012302c302d302d302d001222325333029301d302a37540022900009bad302e302b375400264a666052603a60546ea80045300103d87a8000132330010013756605e60586ea8008894ccc0b8004530103d87a8000132323232533302f337220100042a66605e66e3c0200084c098cc0ccdd4000a5eb80530103d87a8000133006006003375a60600066eb8c0b8008c0c8008c0c0004cc07800c00894ccc0a0004530103d87a80001301c33029302a0014bd701119198008008019129998150008a5013253330283004302d00214a2266006006002605a00246050605260526052605260520024604e6050605060506050605060500024604c604e604e604e604e604e604e604e604e604e604e0024604a604c604c604c604c604c604c604c604c604c00244646600200200644660060026004004466e212000371a0024604400246042604400244646600200200644a66604200229404c94ccc07ccdc79bae302400200414a226600600600260480024603e604060406040604060406040604060400022a66603266e1d200100913232533301b301430073300a37586040004466603866ebcc010c078dd5000a60103d87980004a094454ccc06cc03cc0100044c94ccc070c054c074dd5000899b8f00d375c6042603c6ea800458c0180045858dd6180f981018101810181018101810000980f980f980d9baa016162301e301f301f001300100122533301b0011480004c018cc008008c07800494ccc0640045300103d87a80001300d3301a301b0014bd70180080091299980c0008a4000260066600400460360026e01200222323300100100322533301800114bd7009919299980b980280109980d80119802002000899802002000980e001180d0009bad3012002375c60200022c602600264a66601c6004601e6ea800452f5bded8c026eacc04cc040dd5000998019bab3002300f375401400a6e1d200223011301230123012301200122323300100100322533301100114c103d87a800013232323253330123372200e0042a66602466e3c01c0084c024cc058dd3000a5eb80530103d87a8000133006006003375660260066eb8c044008c054008c04c004dd2a40006eb8c034c028dd50011b874800058c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba21";
        }
        return "590b9301010032323232323232253330023232323232533233008300130093754004264646464646464a666024602a004264646464646464646464a666032601a012264646464646464646464646464646464646464646464a66605e60466030002264a666060605260626ea80044c94ccc0c4c094c0740184c94ccc0c8c0acc0ccdd500089919299981a19b8748010c0d4dd5000899299981a9817181b1baa00113232323232323232323232323232323232323232533304c304f00213302b01322533304e00213302d0092253330500021533304d304133302837566064609e6ea8c0c8c13cdd500da451cd3c25617941168e238038f1cf6542229b919bbd6fd2b8292ce17620300375c606a609e6ea806454ccc134cdd7981898279baa3031304f37546064609e6ea806ccdd2a4004660a298011e581cd3c25617941168e238038f1cf6542229b919bbd6fd2b8292ce176203004bd70099299982729998271823981b8008a5113303400101e132533304f3043303b001132533305030493051375400226464a6660a466e1d200430533754002264a6660a6609860a86ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc1b8c1c40084cc13402c894ccc1c00084cc13c01c894ccc1c800854ccc1bccdc781f9bae30543071375403a2a6660de60c66660946eacc150c1c4dd500f83381f8a99983799baf30533071375460a660e26ea807ccdd2a4004660e6609260e26ea80752f5c02a6660de664464a6660e460cc60e66ea80044c94ccc1ccc19cc1d0dd5182c183a9baa305830753754008266e2000400c4cdc48008019bad3077307437540022940c154c1ccdd5182b18399baa0023048307137540d86eb4c120c1c4dd500e8a999837a99983799b8f375c60a860e26ea80740fc54ccc1bccdc79bae30573071375403a6eb8c150c1c4dd501d8a99983799b8f375c609260e26ea8074dd7182498389baa03b1533306f3370e6eb4c190c1c4dd500e9bad3064307137540762a6660de66e1cdd6982698389baa01d375a609a60e26ea80ec54ccc1bccdd7982718389baa01d304e307137540762a6660de66e1cdd6982418389baa01d375a609060e26ea80ec54ccc1bccdc39bad304f3071375403a6eb4c140c1c4dd501d8a99983799b8f375c60e860ea60ea60ea60ea60ea60ea60ea60ea60ea60ea60ea60e26ea8074dd7182b98389baa03b13370e6eb4c158c1c4dd500e99b80375a60ac60e26ea80ed200114a029405280a5014a029405280a5014a02a6660de66e24c16cdd6182818389baa01d375a609e60e26ea807454ccc1bcc8cc004004dd6182898391baa01e22533307400114a2264a6660e464a6660e660ac6eb8c15cc1d4dd50008a999839982b1bae305b307537540022660b26eb0c168c1d4dd50381bae305b307537540022940528183b8010998018018008a5030770011533306f533306f3068375a609a60e26ea80745288a99983798341bad30643071375403a294454ccc1bcccc1bcc1a0cdc3182e9bad30563071375403a6eb4c134c1c4dd500ea504a229444c8cc004004dd6182798391baa01e22533307400114a2264a6660e464660a008c4a6660e866ebcc164c1d8dd50009ba6325333075306e00114bd6f7b6300991919800800a5eb7bdb180894ccc1ec0044cc1f0cdd82601014000374c00697adef6c60132323232533307c3372091010000213308001337609801014000374c00e00a2a6660f866e3d2210000213308001337609801014000374c00e0062661000266ec0dd48011ba600133006006003375660fa0066eb8c1ec008c1fc008c1f4004c8cc0040052f5bded8c044a6660f40022660f666ec13001014000375000697adef6c60132323232533307b3372091010000213307f337609801014000375000e00a2a6660f666e3d2210000213307f337609801014000375000e0062660fe66ec0dd48011ba800133006006003375a60f80066eb8c1e8008c1f8008c1f0004cdc19bad30693076375404460ba6eb0c14cc1d8dd5011099baf30583076375460b060ec6ea8004c1accc1e0dd480125eb805281bae307700213300300300114a060ee0022646609a08e464646466e3cdc919b8a0023337929412004001005375a60f060f20046eb8c1dc004c1ccdd5182a98399baa001375c60a660e26ea80745280a5014a029405280a5014a029404c94ccc1c0c1a4c1c4dd500089919191919191919299983d983f00109982d00091299983e8010980618400080689918011840808019b99375c60fe0042c6eb0c1f0004c1f0008dd7183d000983d0011b99375c60f000260f00046eb8c1d8004c1c8dd50008b183a0010991801183a0019bae307200216375c60de00260de0046eb4c1b4004c1b4008dd6183580098358011bad30690013069002375a60ce00260ce0046eb0c194004c194008dd6983180098318011bad30610013061002375c60be00260be0046eb8c174004c174008dd7182d800982d8011bae3059001305537540022c60ae60a86ea800458c0e4c14cdd5000982a98291baa00116302b001163303d021233304f3375e606e60a26ea800530103d87980004a094458dd6181898279baa019161613230023054003375c60a4004264600460a40066eb8c14000858dd6982680098268011bad304b001304b002375a609200260920046eb0c11c004c11c008dd6982280098228011bad30430013043002375c608200260820046eb8c0fc004c0fc008dd7181e800981e8011bac303b001303737540022c6072606c6ea800458c06cc0d4dd5180c181a9baa0013037303437540022c601a00c2c6eb8c0d4c0c8dd50008b180d0008b1bac30333034303430343034303430340023758606400260640046eb0c0c0004c0c0008dd6181700098151baa0252302d302e302e302e302e302e302e302e0012302c302d302d302d001222325333029301d302a37540022900009bad302e302b375400264a666052603a60546ea80045300103d87a8000132330010013756605e60586ea8008894ccc0b8004530103d87a8000132323232533302f337220100042a66605e66e3c0200084c098cc0ccdd4000a5eb80530103d87a8000133006006003375a60600066eb8c0b8008c0c8008c0c0004cc07800c00894ccc0a0004530103d87a80001301c33029302a0014bd701119198008008019129998150008a5013253330283004302d00214a2266006006002605a00246050605260526052605260520024604e6050605060506050605060500024604c604e604e604e604e604e604e604e604e604e604e0024604a604c604c604c604c604c604c604c604c604c00244646600200200644660060026004004466e212000371a0024604400246042604400244646600200200644a66604200229404c94ccc07ccdc79bae302400200414a226600600600260480024603e604060406040604060406040604060400022a66603266e1d200100913232533301b301430073300a37586040004466603866ebcc010c078dd5000a60103d87980004a094454ccc06cc03cc0100044c94ccc070c054c074dd5000899b8f00d375c6042603c6ea800458c0180045858dd6180f981018101810181018101810000980f980f980d9baa016162301e301f301f001300100122533301b0011480004c018cc008008c07800494ccc0640045300103d87a80001300d3301a301b0014bd70180080091299980c0008a4000260066600400460360026e01200222323300100100322533301800114bd7009919299980b980280109980d80119802002000899802002000980e001180d0009bad3012002375c60200022c602600264a66601c6004601e6ea800452f5bded8c026eacc04cc040dd5000998019bab3002300f375401400a6e1d200223011301230123012301200122323300100100322533301100114c103d87a800013232323253330123372200e0042a66602466e3c01c0084c024cc058dd3000a5eb80530103d87a8000133006006003375660260066eb8c044008c054008c04c004dd2a40006eb8c034c028dd50011b874800058c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba21";
    }

    public static String getMintStateTokenHash(CardanoNetwork network) {
        if (network.equals(CardanoNetwork.MAINNET)) {
            return "1919c122cba719a9bf760e4e463bbcf8a3d46327569cdb5edd8b7d0e";
        }
        return "6b3a786359bfb307baa3be8cc4fa9872c219c42b76226a4f97d90a62";
    }

    public static String getUpdateStateTokenCode(CardanoNetwork network) {
        if (network.equals(CardanoNetwork.MAINNET)) {
            return "590b3a01010032323232323232253330023232323232533233008300130093754004264646646464646464646464646464646464646464646464646464646446464a66604e600e60506ea80044c8c94ccc0a4cdc3a400860546ea80044c8cc02400454ccc0a8c08cc060dd6181018161baa0271533302a3375e60106eb0c080c0b0dd5013980919817180f98161baa0014bd700a99981518119998039bab301f302c3754603e60586ea800d2211c1919c122cba719a9bf760e4e463bbcf8a3d46327569cdb5edd8b7d0e00375c603e60586ea80044c8c94ccc0b0c0940044c8c94ccc0b8c038c0bcdd50008992999817981418088028992999818180818189baa00113253330313375e604860666ea8004c090c0ccdd5181318199baa00313253330323370e900218199baa0011323301200115333033302c33301037566050606a6ea800d22011c1919c122cba719a9bf760e4e463bbcf8a3d46327569cdb5edd8b7d0e00375c6050606a6ea80284c8c94ccc0d4c94ccc0d8cdc4240006eb4c0b0c0e0dd500689919299981c1818981c9baa00113253330393032303a3754605c60766ea8c0b8c0ecdd5002099b880010031337120020066eb4c0f4c0e8dd50008a50302a30393754605860726ea8008dd6980d181c1baa00d14a06032606e6ea80c854ccc0d400854ccc0d400454ccc0d4cdc4980b9bac301a303737540066eb4c06cc0dcdd5001899198008009bac301b3038375400844a66607400229444c94ccc0e0c94ccc0e4c0acdd71816181d9baa00115333039302b375c605a60766ea80044c8c8cc004004dd61818981e9baa03822533303f00114a0264a66607a66e3cdd718210010020a511330030030013042001375c605a60766ea80045280a50303d00213300300300114a0607a00229405280a5014a0a66606860286eb4c07cc0d8dd50010a51153330343014375a603c606c6ea80085288a99981a19981a180a19b863024375a6054606c6ea8008dd6980f981b1baa0024a0944528899198008009bac30213037375400644a66607200229444c94ccc0dcc8c8cc004004034894ccc0f4004528099299981d99299981e19baf3031303e37540026e98c94ccc0f4c07400452f5bded8c0264646600200297adef6c60225333043001133044337609801014000374c00697adef6c60132323232533304433720910100002133048337609801014000374c00e00a2a66608866e3d22100002133048337609801014000374c00e00626609066ec0dd48011ba6001330060060033756608a0066eb8c10c008c11c008c114004c8cc0040052f5bded8c044a66608400226608666ec13001014000375000697adef6c60132323232533304333720910100002133047337609801014000375000e00a2a66608666e3d22100002133047337609801014000375000e00626608e66ec0dd48011ba800133006006003375a60880066eb8c108008c118008c110004cdc19bad3026303e375401460546eb0c0a0c0f8dd5005099baf302f303e3754605e607c6ea8004c090cc100dd4802a5eb8052818200010a511330030030013040001375c60780042660060060022940c0f00054ccc0cccdc79bae3026303537540026eb8c098c0d4dd50050a99981999b8f375c6050606a6ea8004dd71814181a9baa00a153330333371e6eb8c09cc0d4dd50009bae3027303537540142a66606666e3cdd7180e181a9baa001375c6038606a6ea802854ccc0cccdc39bad301d303537540026eb4c074c0d4dd50050a99981999b87375a603c606a6ea8004dd6980f181a9baa00a153330333375e603e606a6ea8004c07cc0d4dd50050a99981999b87375a602e606a6ea8004dd6980b981a9baa00a153330333370e6eb4c064c0d4dd50009bad3019303537540142a66606666e3cdd71810181a9baa001375c6040606a6ea80284cdc39bad30293035375400266e00dd69814981a9baa00a480045280a5014a029405280a5014a029405280a50163037303437540022c604a60666ea800458c0d4c0c8dd50008b29998190028a60103d87a8000130173303330340054bd700b181998181baa001163300e37586040605e6ea80a8024dd618189819181918171baa0291533302c300c0011533302c300c300e0021533302c3025301a37586044605c6ea80a44c94ccc0b4c034c0b8dd500089919192999819981b001099299981899b87375a606600490008a99981899b8f00100413371e6eb8c098c0ccdd50040020a5014a06eb8c0c400458c0d0004c94ccc0bcc0a0c0c0dd50008a5eb7bdb1804dd5981a18189baa001330153756603060606ea80ad22011c1919c122cba719a9bf760e4e463bbcf8a3d46327569cdb5edd8b7d0e00375c6064605e6ea800458c028dd6181118171baa0291614a02c646600200200e44a6660600022900009991299981798141998061bab30243031375400491011c1919c122cba719a9bf760e4e463bbcf8a3d46327569cdb5edd8b7d0e00375c604860626ea80184c07c0044004c0c8004cc008008c0cc004c8cc004004018894ccc0bc00452f5c026464a66605c66605c66ebcc088c0c0dd500126103d87980004a09444cc0c8008cc0100100044cc010010004c0cc008c0c4004585858c0b8c0acdd50008b180e18151baa301d302a3754002605860526ea800458cc01cdd6180c98141baa0230023758605460566056604e6ea8088888c94ccc09cc080c0a0dd50008a400026eb4c0b0c0a4dd5000992999813981018141baa00114c103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a8000132323232533302d337220100042a66605a66e3c0200084c054cc0c4dd4000a5eb80530103d87a8000133006006003375a605c0066eb8c0b0008c0c0008c0b8004cc03400c00894ccc098004530103d87a80001300b3302730280014bd70112999811980198121baa0021323232323232323232323232323232323232323232323232533303e304100213302c00b22533304000213302e0072253330420021501d132533304030203041375400226464646464646464a666096609c00426607200244a66609a0042601860a001a264600460a20066e64dd718278010b1bac304c001304c002375c609400260940046e64dd7182400098240011bae3046001304237540022c6088004264600460880066eb8c10800858dd7181f800981f8011bad303d001303d0023758607600260760046eb4c0e4004c0e4008dd6981b800981b8011bac30350013035002375a606600260660046eb4c0c4004c0c4008dd7181780098178011bae302d001302d002375c605600260560046eb8c0a4004c094dd50010b1b874800088c8cc00400400c894ccc098004530103d87a80001323253330253375e6030604e6ea80080144c034cc0a40092f5c026600800800260540046050002600200244a6660440022900009807998010011812800918111811981198119811981198119811800918109811181118111811181118111811181118110009181018109810981098109810981098109810981098108009119198008008019129998100008a6103d87a800013232323253330213372200e0042a66604266e3c01c0084c024cc094dd3000a5eb80530103d87a8000133006006003375660440066eb8c080008c090008c088004dd2a40004603a603c603c603c00246038603a603a603a603a0024603660386038603860386038002460346036603660366036603660360024603260346034603460346034603460346034603460346034002600200244a66602c002290000980199801001180c8009b804800888c8cc00400400c88cc00c004c0080088cdc4240006e340048c04c0048c048c04cc04c0048c044c0480048c040c044c044c044c044c044c044c044c044004c03c008c038c03c004c028dd50011b874800858c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba21";
        }
        return "590b3a01010032323232323232253330023232323232533233008300130093754004264646646464646464646464646464646464646464646464646464646446464a66604e600e60506ea80044c8c94ccc0a4cdc3a400860546ea80044c8cc02400454ccc0a8c08cc060dd6181018161baa0271533302a3375e60106eb0c080c0b0dd5013980919817180f98161baa0014bd700a99981518119998039bab301f302c3754603e60586ea800d2211c6b3a786359bfb307baa3be8cc4fa9872c219c42b76226a4f97d90a6200375c603e60586ea80044c8c94ccc0b0c0940044c8c94ccc0b8c038c0bcdd50008992999817981418088028992999818180818189baa00113253330313375e604860666ea8004c090c0ccdd5181318199baa00313253330323370e900218199baa0011323301200115333033302c33301037566050606a6ea800d22011c6b3a786359bfb307baa3be8cc4fa9872c219c42b76226a4f97d90a6200375c6050606a6ea80284c8c94ccc0d4c94ccc0d8cdc4240006eb4c0b0c0e0dd500689919299981c1818981c9baa00113253330393032303a3754605c60766ea8c0b8c0ecdd5002099b880010031337120020066eb4c0f4c0e8dd50008a50302a30393754605860726ea8008dd6980d181c1baa00d14a06032606e6ea80c854ccc0d400854ccc0d400454ccc0d4cdc4980b9bac301a303737540066eb4c06cc0dcdd5001899198008009bac301b3038375400844a66607400229444c94ccc0e0c94ccc0e4c0acdd71816181d9baa00115333039302b375c605a60766ea80044c8c8cc004004dd61818981e9baa03822533303f00114a0264a66607a66e3cdd718210010020a511330030030013042001375c605a60766ea80045280a50303d00213300300300114a0607a00229405280a5014a0a66606860286eb4c07cc0d8dd50010a51153330343014375a603c606c6ea80085288a99981a19981a180a19b863024375a6054606c6ea8008dd6980f981b1baa0024a0944528899198008009bac30213037375400644a66607200229444c94ccc0dcc8c8cc004004034894ccc0f4004528099299981d99299981e19baf3031303e37540026e98c94ccc0f4c07400452f5bded8c0264646600200297adef6c60225333043001133044337609801014000374c00697adef6c60132323232533304433720910100002133048337609801014000374c00e00a2a66608866e3d22100002133048337609801014000374c00e00626609066ec0dd48011ba6001330060060033756608a0066eb8c10c008c11c008c114004c8cc0040052f5bded8c044a66608400226608666ec13001014000375000697adef6c60132323232533304333720910100002133047337609801014000375000e00a2a66608666e3d22100002133047337609801014000375000e00626608e66ec0dd48011ba800133006006003375a60880066eb8c108008c118008c110004cdc19bad3026303e375401460546eb0c0a0c0f8dd5005099baf302f303e3754605e607c6ea8004c090cc100dd4802a5eb8052818200010a511330030030013040001375c60780042660060060022940c0f00054ccc0cccdc79bae3026303537540026eb8c098c0d4dd50050a99981999b8f375c6050606a6ea8004dd71814181a9baa00a153330333371e6eb8c09cc0d4dd50009bae3027303537540142a66606666e3cdd7180e181a9baa001375c6038606a6ea802854ccc0cccdc39bad301d303537540026eb4c074c0d4dd50050a99981999b87375a603c606a6ea8004dd6980f181a9baa00a153330333375e603e606a6ea8004c07cc0d4dd50050a99981999b87375a602e606a6ea8004dd6980b981a9baa00a153330333370e6eb4c064c0d4dd50009bad3019303537540142a66606666e3cdd71810181a9baa001375c6040606a6ea80284cdc39bad30293035375400266e00dd69814981a9baa00a480045280a5014a029405280a5014a029405280a50163037303437540022c604a60666ea800458c0d4c0c8dd50008b29998190028a60103d87a8000130173303330340054bd700b181998181baa001163300e37586040605e6ea80a8024dd618189819181918171baa0291533302c300c0011533302c300c300e0021533302c3025301a37586044605c6ea80a44c94ccc0b4c034c0b8dd500089919192999819981b001099299981899b87375a606600490008a99981899b8f00100413371e6eb8c098c0ccdd50040020a5014a06eb8c0c400458c0d0004c94ccc0bcc0a0c0c0dd50008a5eb7bdb1804dd5981a18189baa001330153756603060606ea80ad22011c6b3a786359bfb307baa3be8cc4fa9872c219c42b76226a4f97d90a6200375c6064605e6ea800458c028dd6181118171baa0291614a02c646600200200e44a6660600022900009991299981798141998061bab30243031375400491011c6b3a786359bfb307baa3be8cc4fa9872c219c42b76226a4f97d90a6200375c604860626ea80184c07c0044004c0c8004cc008008c0cc004c8cc004004018894ccc0bc00452f5c026464a66605c66605c66ebcc088c0c0dd500126103d87980004a09444cc0c8008cc0100100044cc010010004c0cc008c0c4004585858c0b8c0acdd50008b180e18151baa301d302a3754002605860526ea800458cc01cdd6180c98141baa0230023758605460566056604e6ea8088888c94ccc09cc080c0a0dd50008a400026eb4c0b0c0a4dd5000992999813981018141baa00114c103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a8000132323232533302d337220100042a66605a66e3c0200084c054cc0c4dd4000a5eb80530103d87a8000133006006003375a605c0066eb8c0b0008c0c0008c0b8004cc03400c00894ccc098004530103d87a80001300b3302730280014bd70112999811980198121baa0021323232323232323232323232323232323232323232323232533303e304100213302c00b22533304000213302e0072253330420021501d132533304030203041375400226464646464646464a666096609c00426607200244a66609a0042601860a001a264600460a20066e64dd718278010b1bac304c001304c002375c609400260940046e64dd7182400098240011bae3046001304237540022c6088004264600460880066eb8c10800858dd7181f800981f8011bad303d001303d0023758607600260760046eb4c0e4004c0e4008dd6981b800981b8011bac30350013035002375a606600260660046eb4c0c4004c0c4008dd7181780098178011bae302d001302d002375c605600260560046eb8c0a4004c094dd50010b1b874800088c8cc00400400c894ccc098004530103d87a80001323253330253375e6030604e6ea80080144c034cc0a40092f5c026600800800260540046050002600200244a6660440022900009807998010011812800918111811981198119811981198119811800918109811181118111811181118111811181118110009181018109810981098109810981098109810981098108009119198008008019129998100008a6103d87a800013232323253330213372200e0042a66604266e3c01c0084c024cc094dd3000a5eb80530103d87a8000133006006003375660440066eb8c080008c090008c088004dd2a40004603a603c603c603c00246038603a603a603a603a0024603660386038603860386038002460346036603660366036603660360024603260346034603460346034603460346034603460346034002600200244a66602c002290000980199801001180c8009b804800888c8cc00400400c88cc00c004c0080088cdc4240006e340048c04c0048c048c04cc04c0048c044c0480048c040c044c044c044c044c044c044c044c044004c03c008c038c03c004c028dd50011b874800858c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba21";
    }

    public static Optional<Utxo> getUtxoByTransactionAndUnit(String transactionHash, String unit, BackendService backendService) {
        Result<TxContentUtxo> transactionUtxos;
        try {
            transactionUtxos = backendService.getTransactionService().getTransactionUtxos(transactionHash);
        } catch (ApiException e) {
            log.error("Error getting transaction utxos: {}", e.getMessage());
            return Optional.empty();
        }

        if (transactionUtxos.isSuccessful()) {
            for (TxContentUtxoOutputs output : transactionUtxos.getValue().getOutputs()) {
                Optional<TxContentOutputAmount> outputWithUnit = output.getAmount().stream().filter(amount -> amount.getUnit().equals(unit)).findFirst();
                if (outputWithUnit.isPresent()) {
                    return Optional.of(output.toUtxos(transactionHash));
                }
            }
        } else {
            log.error("Error getting transaction utxos: {}", transactionUtxos.getResponse());
        }

        return Optional.empty();
    }

    /**
     * Returns the current (unspent) UTxO at {@code scriptAddress} that contains {@code unit}.
     * <p>
     * Unlike {@link #getUtxoByTransactionAndUnit}, this queries the live UTxO set so it will
     * never return an output that has already been consumed by a previous transaction.
     */
    public static Optional<Utxo> getCurrentUtxoByUnit(String scriptAddress, String unit, BackendService backendService) {
        try {
            Result<List<Utxo>> result = backendService.getUtxoService().getUtxos(scriptAddress, unit, 1, 1);
            if (result.isSuccessful() && !result.getValue().isEmpty()) {
                return Optional.of(result.getValue().get(0));
            }
            log.error("No current UTxO found for unit {} at {}: {}", unit, scriptAddress, result.getResponse());
        } catch (ApiException e) {
            log.error("Error fetching current UTxO by unit {} at {}: {}", unit, scriptAddress, e.getMessage());
        }
        return Optional.empty();
    }

    public static String extractStringFromPlutusData(PlutusData plutusData) {
        return new String(((BytesPlutusData) plutusData).getValue());
    }

    public static String extractByteArrayFromPlutusData(PlutusData plutusData) {
        return HexUtil.encodeHexString(((BytesPlutusData) plutusData).getValue());
    }

    public static List<byte[]> extractListFromPlutusData(PlutusData plutusData) {
        return ((ListPlutusData) plutusData).getPlutusDataList().stream()
                .map(item -> ((BytesPlutusData) item).getValue())
                .collect(Collectors.toList());
    }

    public static Integer extractIntegerFromPlutusData(PlutusData plutusData) {
        return ((BigIntPlutusData) plutusData).getValue().intValue();
    }

    public static Boolean extractBooleanFromPlutusData(PlutusData plutusData) {
        return ((ConstrPlutusData) plutusData).getAlternative() == 1;
    }

    public static Long extractLongFromPlutusData(PlutusData plutusData) {
        return ((BigIntPlutusData) plutusData).getValue().longValue();
    }

    public static boolean includesStateToken(TransactionOutput output) {
        return output.getValue().getMultiAssets().stream().anyMatch(
                asset -> asset.getPolicyId() != null && asset.getPolicyId().equalsIgnoreCase(getMintStateTokenHash(CardanoNetwork.MAINNET))
                        || asset.getPolicyId().equalsIgnoreCase(getMintStateTokenHash(CardanoNetwork.PREPROD))
        );
    }

    public static boolean includesStateToken(AddressUtxo addressUtxo, CardanoNetwork network) {
        return addressUtxo.getAmounts().stream()
                .anyMatch(asset -> asset.getPolicyId() != null && asset.getPolicyId().equals(ValidatorUtils.getMintStateTokenHash(network)));

    }

    public static boolean includesBootstrapToken(AddressUtxo addressUtxo, CardanoNetwork network) {
        return addressUtxo.getAmounts().stream()
                .anyMatch(asset -> asset.getPolicyId() != null && asset.getPolicyId().equals(ValidatorUtils.getMintOrBurnAuthTokenHash(network)));
    }

    public static boolean isMintingTransaction(AddressUtxo addressUtxo, String policyId) {
        return addressUtxo.getAmounts().stream()
                .anyMatch(input -> input.getPolicyId() != null && input.getPolicyId().equals(policyId) &&
                        input.getQuantity().equals(BigInteger.ONE));
    }

    public static boolean isBurningTransaction(AddressUtxo addressUtxo, String policyId) {
        return addressUtxo.getAmounts().stream()
                .anyMatch(input -> input.getPolicyId() != null && input.getPolicyId().equals(policyId) &&
                        input.getQuantity().equals(BigInteger.valueOf(-1)));
    }

    public static String getBootstrapTokenName(AddressUtxo addressUtxo, CardanoNetwork network) {
        return addressUtxo.getAmounts().stream()
                .filter(input -> input.getPolicyId() != null && input.getPolicyId().equals(getMintOrBurnAuthTokenHash(network)))
                .findFirst()
                .map(Amt::getAssetName)
                .orElseThrow(() -> new IllegalArgumentException("Bootstrap token not found"));
    }
}