# generated by datamodel-codegen:
#   filename:  https://cardanosolutions.github.io/kupo/api/nightly.yaml
#   timestamp: 2025-01-07T02:57:18+00:00

from __future__ import annotations

from enum import Enum
from typing import Dict, List, Optional, Union

from pydantic import BaseModel, ConfigDict, Field, RootModel, conint, constr


class AddressShelley(RootModel[str]):
    root: str = Field(..., title="Shelley")


class AddressStake(RootModel[str]):
    root: str = Field(..., title="Stake")


class AddressBootstrap(RootModel[str]):
    root: str = Field(..., title="Bootstrap")


class AddressCredentials(RootModel[str]):
    root: str = Field(
        ...,
        description=(
            "```\n  ┏━━━━━━━━━━━━┓ ╭───╮ ┏━━━━━━━━━━━━┓\n╾─┫ CREDENTIAL ┣─┤ / ├─┫"
            " CREDENTIAL ┣─╼\n  ┗━━━━━━━━━━━━┛ ╰───╯ ┗━━━━━━━━━━━━┛\n```\n\nOne or two"
            " address credentials, separated by a `/`. The left-side identifies the"
            " payment\npart of the address, and the right-side identifies the"
            " delegation part. Both are optional\nan can be instead a wildcard"
            " (`*`).\n\nExamples:\n-"
            " `addr_vk1x7da0l25j04my8sej5ntrgdn38wmshxhplxdfjskn07ufavsgtkqn5hljl/*`\n-"
            " `*/script1cda3khwqv60360rp5m7akt50m6ttapacs8rqhn5w342z7r35m37`\n-"
            " `dca1e44765b9f80c8b18105e17de90d4a07e4d5a83de533e53fee32e0502d17e/*`\n-"
            " `*/4fc6bb0c93780ad706425d9f7dc1d3c5e3ddbf29ba8486dce904a5fc`\n- `*/*`\n"
        ),
        examples=[
            "addr_vk1x7da0l25j04my8sej5ntrgdn38wmshxhplxdfjskn07ufavsgtkqn5hljl/*",
            "*/script1cda3khwqv60360rp5m7akt50m6ttapacs8rqhn5w342z7r35m37",
            "dca1e44765b9f80c8b18105e17de90d4a07e4d5a83de533e53fee32e0502d17e/*",
            "*/4fc6bb0c93780ad706425d9f7dc1d3c5e3ddbf29ba8486dce904a5fc",
            "*/*",
        ],
        title="Credentials",
    )


class BadRequest(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    hint: Optional[str] = Field(None, description="Some hint about what went wrong.")


class Datum(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    datum: str = Field(
        ...,
        description="A serialized Plutus' Data (datum or redeemer).",
        examples=["d87980"],
    )


class DatumType(Enum):
    """
    Categorize the type of datum in the output:

    - `hash`: means that the output only contains a reference to the datum;
    - `inline`: means that the ouput originally contained a full inline datum.

    In both cases however, Kupo returns only a `datum_hash`, and full datums
    can be retrieved via the [`GET /datums/{datum-hash}`](#tag/Datums/paths/~1datums~1{datum-hash}/get)
    endpoint.

    This field is only present when `datum_hash` is not `null`.

    """

    hash = "hash"
    inline = "inline"


class Deleted(BaseModel):
    deleted: conint(ge=0) = Field(
        ..., description="Number of entities effectively deleted."
    )


class Limit(Enum):
    """
    Specify the server behavior when rolling back out of the _safe
    zone_. As mentioned in the user manual, when running Kupo with
    `--prune-utxo` enabled, the server gets rid of spent UTxOs, but it
    only does so after a certain time. That time is exactly `129600`
    slots (or 36h on Mainnet/Testnet). This is because the core
    protocol cannot roll back further than this particular depth and it
    is the point after which it is 100% safe to remove data from the
    database.

    However, this endpoint allows you to break this invariant and
    rollback to points that are even older in the past. As a
    consequence, while syncing, the index may be in a somewhat
    inconsistent state because some inputs spent at a later time may
    not have been recovered during the rollback. This may be surprising
    if you're expecting to see and query those transient inputs after
    rolling back.

    By default, you won't be allowed to rollback beyond the safe zone.
    If, however, you know what you're doing, you're kindly asked to
    pass `unsafe_allow_beyond_safe_zone` as a token of acknowledgment.
    Passing `within_safe_zone` has no effects other than the default.

    Note that, once synchronized again, the index will always be in the
    expected state and problems reflecting reality only occurs _while
    catching up_, after a long rollback.

    """

    unsafe_allow_beyond_safe_zone = "unsafe_allow_beyond_safe_zone"
    within_safe_zone = "within_safe_zone"


class MetadatumInt(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    value: int = Field(
        ...,
        description=(
            'An integer or arbitrary size.\n\nExample:\n\n```json\n{ "int": 42 }\n```\n'
        ),
        alias="int",
    )


class MetadatumString(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    string: constr(max_length=64) = Field(
        ...,
        description=(
            "A text string, which is at most 64 bytes.\n\nExample:\n\n```json\n{"
            ' "string": "kupo!" }\n```\n'
        ),
    )


class MetadatumBytes(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    bytes: constr(max_length=128) = Field(
        ...,
        description=(
            "A base16 byte string, which is at most 64 bytes\n\nExample:\n\n```json\n{"
            ' "bytes": "6b75706f21" }\n```\n'
        ),
    )


class Language(Enum):
    """
    The type of script. `native` refers to pre-Alonzo scripts made of the native DSL to combine keys.
    """

    native = "native"
    plutus_v1 = "plutus:v1"
    plutus_v2 = "plutus:v2"
    plutus_v3 = "plutus:v3"


class Script(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    language: Language = Field(
        ...,
        description=(
            "The type of script. `native` refers to pre-Alonzo scripts made of the"
            " native DSL to combine keys."
        ),
    )
    script: str = Field(
        ...,
        description="A serialized script (native or Plutus).",
        examples=["4d01000033222220051200120011"],
    )


class Value(BaseModel):
    """
    A (multi-asset) value of a transaction's output.
    """

    model_config = ConfigDict(
        extra="forbid",
    )
    coins: int = Field(..., description="A quantity of Lovelace.", examples=[42])
    assets: Optional[Dict[str, int]] = Field(
        None,
        description="A _key:value_ map of asset identifier → quantity.",
        examples=[
            {
                "1220099e5e430475c219518179efc7e6c8289db028904834025d5b086": 231,
                "289db028904834025d5b085d5b08661220099e5e430475c2195181796.08661220099e": 1,
            }
        ],
    )


class Wildcard(Enum):
    field_ = "*"


class CreatedAt(BaseModel):
    """
    Block reference at which this transaction was included in the ledger.
    """

    model_config = ConfigDict(
        extra="forbid",
    )
    slot_no: conint(ge=0) = Field(
        ..., description="An absolut slot number.", examples=[51540727]
    )
    header_hash: constr(min_length=64, max_length=64) = Field(
        ...,
        description="A blake2b-256 hash digest of a block header.",
        examples=["9d09...31bf"],
    )


class ConnectionStatus(Enum):
    """
    Condition of the connection with the underlying node.
    """

    connected = "connected"
    disconnected = "disconnected"


class Indexes(Enum):
    """
    Behaviour surrounding the database query indexes.
    """

    deferred = "deferred"
    installed = "installed"


class Configuration(BaseModel):
    """
    A summary of hand-picked configuration parameters.
    """

    model_config = ConfigDict(
        extra="forbid",
    )
    indexes: Indexes = Field(
        ..., description="Behaviour surrounding the database query indexes."
    )


class Health(BaseModel):
    """
    An overview of the server & connection status. Note that, when `most_recent_checkpoint` and `most_recent_node_tip` are equal, the index is fully synchronized.
    """

    model_config = ConfigDict(
        extra="forbid",
    )
    connection_status: ConnectionStatus = Field(
        ..., description="Condition of the connection with the underlying node."
    )
    most_recent_checkpoint: Optional[conint(ge=0)] = None
    most_recent_node_tip: Optional[conint(ge=0)] = None
    configuration: Configuration = Field(
        ..., description="A summary of hand-picked configuration parameters."
    )
    version: str = Field(..., description="Current software version.")


class HealthPrometheus(RootModel[str]):
    root: str = Field(
        ...,
        description=(
            "A key-value export compatible with Prometheus.\n\n- `connected` and"
            " `disconnected` (from `connection_status`) are encoded as `1.0` and `0.0`"
            " respectively.\n- `installed` and `deferred` (from"
            " `configuration.indexes`) are encoded as `1.0` and `0.0` respectively.\n-"
            " `version` is not present in the Prometheus metrics.\n"
        ),
        examples={
            "response": {
                "value": (
                    "# TYPE kupo_connection_status gauge\nkupo_connection_status "
                    " 1.0\n\n# TYPE kupo_most_recent_checkpoint"
                    " counter\nkupo_most_recent_checkpoint  294998\n\n# TYPE"
                    " kupo_most_recent_node_tip counter\nkupo_most_recent_node_tip "
                    " 71753381\n\n# TYPE kupo_configuration_indexes"
                    " gauge\nkupo_configuration_indexes  1.0\n"
                )
            }
        },
    )


class RollbackTo(BaseModel):
    """
    A mandatory point to rollback the synchronization to.
    Note that the synchronization will therefore begin starting from the point **immediately after** the provided point!

    > <sup><strong>NOTE (1)</strong></sup> <br/>
    > If you need to query ancestors from any given known point, see [`GET /checkpoints/{slot-no}`](#operation/getCheckpointBySlot)

    > <sup><strong>NOTE (2)</strong></sup> <br/>
    > The `header_hash` is **optional**! However if provided, Kupo will check that it rolls back exactly to the specified point by comparing header hashes.
    > If it's omitted, Kupo will rollback to the given slot number or, any closest ancestor if no point is found at the given slot.

    """

    slot_no: conint(ge=0) = Field(
        ..., description="An absolut slot number.", examples=[51540727]
    )
    header_hash: Optional[constr(min_length=64, max_length=64)] = Field(
        None,
        description="A blake2b-256 hash digest of a block header.",
        examples=["9d09...31bf"],
    )


class ForcedRollback(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    rollback_to: RollbackTo = Field(
        ...,
        description=(
            "A mandatory point to rollback the synchronization to.\nNote that the"
            " synchronization will therefore begin starting from the point"
            " **immediately after** the provided point!\n\n> <sup><strong>NOTE"
            " (1)</strong></sup> <br/>\n> If you need to query ancestors from any given"
            " known point, see [`GET"
            " /checkpoints/{slot-no}`](#operation/getCheckpointBySlot)\n\n>"
            " <sup><strong>NOTE (2)</strong></sup> <br/>\n> The `header_hash` is"
            " **optional**! However if provided, Kupo will check that it rolls back"
            " exactly to the specified point by comparing header hashes.\n> If it's"
            " omitted, Kupo will rollback to the given slot number or, any closest"
            " ancestor if no point is found at the given slot.\n"
        ),
    )
    limit: Optional[Limit] = Field(
        "within_safe_zone",
        description=(
            "Specify the server behavior when rolling back out of the _safe\nzone_. As"
            " mentioned in the user manual, when running Kupo with\n`--prune-utxo`"
            " enabled, the server gets rid of spent UTxOs, but it\nonly does so after a"
            " certain time. That time is exactly `129600`\nslots (or 36h on"
            " Mainnet/Testnet). This is because the core\nprotocol cannot roll back"
            " further than this particular depth and it\nis the point after which it is"
            " 100% safe to remove data from the\ndatabase.\n\nHowever, this endpoint"
            " allows you to break this invariant and\nrollback to points that are even"
            " older in the past. As a\nconsequence, while syncing, the index may be in"
            " a somewhat\ninconsistent state because some inputs spent at a later time"
            " may\nnot have been recovered during the rollback. This may be"
            " surprising\nif you're expecting to see and query those transient inputs"
            " after\nrolling back.\n\nBy default, you won't be allowed to rollback"
            " beyond the safe zone.\nIf, however, you know what you're doing, you're"
            " kindly asked to\npass `unsafe_allow_beyond_safe_zone` as a token of"
            " acknowledgment.\nPassing `within_safe_zone` has no effects other than the"
            " default.\n\nNote that, once synchronized again, the index will always be"
            " in the\nexpected state and problems reflecting reality only occurs"
            " _while\ncatching up_, after a long rollback.\n"
        ),
    )


class Pattern(
    RootModel[
        Union[
            Wildcard,
            str,
            constr(pattern=r"[0-9a-f]{56}\.(.*|[0-9a-f]{2,64})"),
            constr(pattern=r"(.*|[0-9]+)@[0-9a-f]{64}"),
        ]
    ]
):
    root: Union[
        Wildcard,
        str,
        constr(pattern=r"[0-9a-f]{56}\.(.*|[0-9a-f]{2,64})"),
        constr(pattern=r"(.*|[0-9]+)@[0-9a-f]{64}"),
    ] = Field(
        ...,
        description=(
            "A matching pattern for addresses, assets or transactions.\n\nSee"
            " [Patterns](#section/Patterns) for more details.\n"
        ),
    )


class Point(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    slot_no: conint(ge=0) = Field(
        ..., description="An absolut slot number.", examples=[51540727]
    )
    header_hash: constr(min_length=64, max_length=64) = Field(
        ...,
        description="A blake2b-256 hash digest of a block header.",
        examples=["9d09...31bf"],
    )


class SpentAt(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    slot_no: conint(ge=0) = Field(
        ..., description="An absolut slot number.", examples=[51540727]
    )
    header_hash: constr(min_length=64, max_length=64) = Field(
        ...,
        description="A blake2b-256 hash digest of a block header.",
        examples=["9d09...31bf"],
    )
    transaction_id: Optional[constr(min_length=64, max_length=64)] = None
    input_index: Optional[conint(ge=0)] = None
    redeemer: Optional[str] = None


class Match(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    transaction_index: conint(ge=0) = Field(
        ...,
        description="The index of the transaction within the block including it.",
        examples=[14],
    )
    transaction_id: constr(min_length=64, max_length=64) = Field(
        ...,
        description="A blake2b-256 hash digest of a transaction body.",
        examples=["35d8...4e09"],
    )
    output_index: conint(ge=0) = Field(
        ...,
        description="The index of the output within the transaction carrying it.",
        examples=[2],
    )
    address: str = Field(..., description="A Cardano address, in any era.")
    value: Value
    datum_hash: Optional[constr(min_length=64, max_length=64)] = Field(
        ..., description="A blake2b-256 hash digest of a Plutus' datum, if any."
    )
    datum: Optional[str] = Field(
        None,
        description=(
            "The resolved datum, if available. The field is only and always present"
            " (yet may be `null`) if `?resolve_hashes` was set."
        ),
    )
    datum_type: Optional[DatumType] = None
    script_hash: Optional[constr(min_length=56, max_length=56)] = Field(
        ...,
        description="A blake2b-224 hash digest of a Native or Plutus script, if any.",
    )
    script: Optional[Script] = Field(
        None,
        description=(
            "The resolved script, if available. The field is only and always present"
            " (yet may be `null`) if `?resolve_hashes` was set."
        ),
    )
    created_at: CreatedAt = Field(
        ...,
        description=(
            "Block reference at which this transaction was included in the ledger."
        ),
        title="Point",
    )
    spent_at: Optional[SpentAt] = Field(
        ...,
        description=(
            "Block reference at which this transaction input was spent, if any."
        ),
    )


class Metadata(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    hash: constr(min_length=64, max_length=64) = Field(
        ...,
        description="A blake2b-256 hash digest of the raw serialized data",
        examples=["cd6a5d31bf9d309706b92ad83402e682fdab9fc889b1b63565ee3de14e09dedf"],
    )
    raw: str = Field(
        ...,
        description=(
            "A [CBOR](https://www.rfc-editor.org/rfc/rfc8949.html)-encoded binary"
            " payload."
        ),
    )
    schema_: Dict[
        str,
        Union[
            MetadatumInt, MetadatumString, MetadatumBytes, MetadatumList, MetadatumMap
        ],
    ] = Field(
        ...,
        alias="schema",
        description=(
            "A high-level description of the raw data. The top-level object is an"
            " object where all keys are integers (possibly negative) and points to"
            " objects representing one of 5 primitives:\n\n- int\n- string\n- bytes\n-"
            " list\n- map\n\nThis schema is meant to give a faithful representation of"
            " the underlying [CBOR](https://www.rfc-editor.org/rfc/rfc8949.html)"
            " encoding, which is slightly more expressive than pure JSON (e.g. keys of"
            " maps can be arbitrary CBOR objects).\n\nThis is why it is generally not"
            " possible to ensure a 1:1 conversion between low-level CBOR and JSON, and"
            " why this intermediate representation is necessary to safely represent"
            " **any** metadata object.\n"
        ),
        examples=[
            {
                "64": {"string": "some text"},
                "32": {"int": 42},
                "16": {
                    "map": [
                        {
                            "k": {"string": "numbers"},
                            "v": {
                                "list": [{"int": 1}, {"int": 2}, {"int": 4}, {"int": 8}]
                            },
                        },
                        {
                            "k": {"string": "alphabet"},
                            "v": {
                                "map": [
                                    {"k": {"string": "A"}, "v": {"int": 65}},
                                    {"k": {"string": "B"}, "v": {"int": 66}},
                                    {"k": {"string": "C"}, "v": {"int": 67}},
                                ]
                            },
                        },
                    ]
                },
                "-8": {"bytes": "48656c6c6f2c2043617264616e6f21"},
            }
        ],
    )


class MetadatumList(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    list: List[
        Union[
            MetadatumInt, MetadatumString, MetadatumBytes, MetadatumList, MetadatumMap
        ]
    ] = Field(
        ...,
        description=(
            "A (possibly heterogeneous) list of metadatum\n\nExample:\n\n```json\n{\n "
            ' "list": [\n    {\n      "int": 14\n    },\n    {\n      "list": [\n      '
            '  { "string": "kupo!" },\n        { "bytes": "6b75706f21" }\n      ]\n   '
            " }\n  ]\n}\n```\n"
        ),
    )


class MapItem(BaseModel):
    k: Union[MetadatumInt, MetadatumString, MetadatumBytes, MetadatumList, MetadatumMap]
    v: Union[MetadatumInt, MetadatumString, MetadatumBytes, MetadatumList, MetadatumMap]


class MetadatumMap(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    map: List[MapItem] = Field(
        ...,
        description=(
            "A list of key:value objects. Both keys and values can be any sort"
            ' metadatum.\n\nExample:\n\n```json\n{\n  "map": [\n    {\n      "k": {'
            ' "int": 14 },\n      "v": {\n        "list": [\n          { "string":'
            ' "kupo!" },\n          { "bytes": "6b75706f21" }\n        ]\n      }\n   '
            " }\n  ]\n}\n```\n"
        ),
    )


Metadata.model_rebuild()
