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.spec.BigIntPlutusData;
import com.bloxbean.cardano.client.plutus.spec.BytesPlutusData;
import com.bloxbean.cardano.client.plutus.spec.ListPlutusData;
import com.bloxbean.cardano.client.plutus.spec.PlutusData;
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 java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
public class ValidatorUtils {
    public static String getMintOrBurnAuthTokenCode(CardanoNetwork network) {
        if (network.equals(CardanoNetwork.MAINNET)) {
            return "5901f801010032323232323232253330023232323232323232323253233300d3370e900000309919192999809980b0010992999808a99980898028008a5113370e00290008a999808980298041bac30073013375401c26600c6eb0c01cc04cdd500724411c81c0d7f845fb2cf5d23453dc63997595688973c860786503c4d47b11001616375a60240022c602800264a66601e600660206ea800452f5bded8c026eacc050c044dd500099198008009bab301430153015301530153011375401844a6660260022980103d87a800013232323253330143372200e0042a66602866e3c01c0084cdd2a4000660306e980052f5c02980103d87a80001330060060033756602a0066eb8c04c008c05c008c054004dd7180918079baa0071533300d300100613232325333010300430073758600c60246ea80344cc014dd6180318091baa00d48811c81c0d7f845fb2cf5d23453dc63997595688973c860786503c4d47b110016301430150023013001300f375400e2c6e1d200222323300100100322533301200114a0264a66602066e3cdd7180a8010020a5113300300300130150012301030113011301130113011301130113011001300100122533300d0011480004cdc02400466004004602000260106ea8004c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba201";
        }
        return "5901f801010032323232323232253330023232323232323232323253233300d3370e900000309919192999809980b0010992999808a99980898028008a5113370e00290008a999808980298041bac30073013375401c26600c6eb0c01cc04cdd500724411c11bcb8e4a79304e23bcd5e2bf628907f9b998f43902f41d1db439981001616375a60240022c602800264a66601e600660206ea800452f5bded8c026eacc050c044dd500099198008009bab301430153015301530153011375401844a6660260022980103d87a800013232323253330143372200e0042a66602866e3c01c0084cdd2a4000660306e980052f5c02980103d87a80001330060060033756602a0066eb8c04c008c05c008c054004dd7180918079baa0071533300d300100613232325333010300430073758600c60246ea80344cc014dd6180318091baa00d48811c11bcb8e4a79304e23bcd5e2bf628907f9b998f43902f41d1db4399810016301430150023013001300f375400e2c6e1d200222323300100100322533301200114a0264a66602066e3cdd7180a8010020a5113300300300130150012301030113011301130113011301130113011001300100122533300d0011480004cdc02400466004004602000260106ea8004c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba201";
    }

    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 String getUpdateStateTokenHash(CardanoNetwork network) {
        if (network.equals(CardanoNetwork.MAINNET)) {
            return "314cdf9ea60ee354ff1b87da74f15dedd4070604b2819a1d6bac3453";
        }
        return "f2f25cfcc4e1665bad2477fc1aa6e9960ae59ef1681eae28a0bfed16";
    }

    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();
    }

    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 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"));
    }
}