syntax = "proto3";

import "taprootassets.proto";

package mintrpc;

option go_package = "github.com/lightninglabs/taproot-assets/taprpc/mintrpc";

service Mint {
    /* tapcli: `assets mint`
    MintAsset will attempt to mint the set of assets (async by default to
    ensure proper batching) specified in the request. The pending batch is
    returned that shows the other pending assets that are part of the next
    batch. This call will block until the operation succeeds (asset is staged
    in the batch) or fails.
    */
    rpc MintAsset (MintAssetRequest) returns (MintAssetResponse);

    /* tapcli `assets mint fund`
    FundBatch will attempt to fund the current pending batch with a genesis
    input, or create a new funded batch if no batch exists yet. This RPC is only
    needed if a custom witness is needed to finalize the batch. Otherwise,
    FinalizeBatch can be called directly.
    */
    rpc FundBatch (FundBatchRequest) returns (FundBatchResponse);

    /* tapcli `assets mint seal`
    SealBatch will attempt to seal the current pending batch by creating and
    validating asset group witness for all assets in the batch. If a witness
    is not provided, a signature will be derived to serve as the witness. This
    RPC is only needed if any assets in the batch have a custom asset group key
    that require an external signer. Otherwise, FinalizeBatch can be called
    directly.
    */
    rpc SealBatch (SealBatchRequest) returns (SealBatchResponse);

    /* tapcli: `assets mint finalize`
    FinalizeBatch will attempt to finalize the current pending batch.
    */
    rpc FinalizeBatch (FinalizeBatchRequest) returns (FinalizeBatchResponse);

    /* tapcli: `assets mint cancel`
    CancelBatch will attempt to cancel the current pending batch.
    */
    rpc CancelBatch (CancelBatchRequest) returns (CancelBatchResponse);

    /* tapcli: `assets mint batches`
    ListBatches lists the set of batches submitted to the daemon, including
    pending and cancelled batches.
    */
    rpc ListBatches (ListBatchRequest) returns (ListBatchResponse);

    /* tapcli: `events mint`
    SubscribeMintEvents allows a caller to subscribe to mint events for asset
    creation batches.
    */
    rpc SubscribeMintEvents (SubscribeMintEventsRequest)
        returns (stream MintEvent);
}

message PendingAsset {
    // The version of asset to mint.
    taprpc.AssetVersion asset_version = 1;

    // The type of the asset to be created.
    taprpc.AssetType asset_type = 2;

    // The name, or "tag" of the asset. This will affect the final asset ID.
    string name = 3;

    /*
    A blob that resents metadata related to the asset. This will affect the
    final asset ID.
    */
    taprpc.AssetMeta asset_meta = 4;

    /*
    The total amount of units of the new asset that should be created. If the
    AssetType is Collectible, then this field cannot be set.
    */
    uint64 amount = 5;

    /*
    If true, then the asset will be created with a new group key, which allows
    for future asset issuance.
    */
    bool new_grouped_asset = 6;

    // The specific existing group key this asset should be minted with.
    bytes group_key = 7;

    /*
    The name of the asset in the batch that will anchor a new asset group.
    This asset will be minted with the same group key as the anchor asset.
    */
    string group_anchor = 8;

    /*
    The optional key that will be used as the internal key for an asset group
    created with this asset.
    */
    taprpc.KeyDescriptor group_internal_key = 9;

    /*
    The optional root of a tapscript tree that will be used when constructing a
    new asset group key. This enables future issuance authorized with a script
    witness.
    */
    bytes group_tapscript_root = 10;

    /*
    The optional script key to use for the new asset. If no script key is given,
    a BIP-86 key will be derived from the underlying wallet.
    */
    taprpc.ScriptKey script_key = 11;
}

message UnsealedAsset {
    // The pending asset with an unsealed asset group.
    PendingAsset asset = 1;

    // The group key request for the asset.
    taprpc.GroupKeyRequest group_key_request = 2;

    // The group virtual transaction for the asset.
    taprpc.GroupVirtualTx group_virtual_tx = 3;
}

message MintAsset {
    // The version of asset to mint.
    taprpc.AssetVersion asset_version = 1;

    // The type of the asset to be created.
    taprpc.AssetType asset_type = 2;

    // The name, or "tag" of the asset. This will affect the final asset ID.
    string name = 3;

    /*
    A blob that resents metadata related to the asset. This will affect the
    final asset ID.
    */
    taprpc.AssetMeta asset_meta = 4;

    /*
    The total amount of units of the new asset that should be created. If the
    AssetType is Collectible, then this field cannot be set.
    */
    uint64 amount = 5;

    /*
    If true, then the asset will be created with a group key, which allows for
    future asset issuance.
    */
    bool new_grouped_asset = 6;

    /*
    If true, then a group key or group anchor can be set to mint this asset into
    an existing asset group.
    */
    bool grouped_asset = 7;

    // The specific existing group key this asset should be minted with.
    bytes group_key = 8;

    /*
    The name of the asset in the batch that will anchor a new asset group.
    This asset will be minted with the same group key as the anchor asset.
    */
    string group_anchor = 9;

    /*
    The optional key that will be used as the internal key for an asset group
    created with this asset.
    */
    taprpc.KeyDescriptor group_internal_key = 10;

    /*
    The optional root of a tapscript tree that will be used when constructing a
    new asset group key. This enables future issuance authorized with a script
    witness.
    */
    bytes group_tapscript_root = 11;

    /*
    The optional script key to use for the new asset. If no script key is given,
    a BIP-86 key will be derived from the underlying wallet.
    */
    taprpc.ScriptKey script_key = 12;

    /*
    Decimal display dictates the number of decimal places to shift the amount to
    the left converting from Taproot Asset integer representation to a
    UX-recognizable fractional quantity.

    For example, if the decimal_display value is 2 and there's 100 of those
    assets, then a wallet would display the amount as "1.00". This field is
    intended as information for wallets that display balances and has no impact
    on the behavior of the daemon or any other part of the protocol. This value
    is encoded in the MetaData field as a JSON field, therefore it is only
    compatible with assets that have a JSON MetaData field.
    */
    uint32 decimal_display = 13;
}

message MintAssetRequest {
    /*
    The asset to be minted.
    */
    MintAsset asset = 1;

    /*
    If true, then the assets currently in the batch won't be returned in the
    response. This is mainly to avoid a lot of data being transmitted and
    possibly printed on the command line in the case of a very large batch.
    */
    bool short_response = 2;
}

message MintAssetResponse {
    // The pending batch the asset was added to.
    MintingBatch pending_batch = 1;
}

message MintingBatch {
    /*
    A public key serialized in compressed format that can be used to uniquely
    identify a pending minting batch. Responses that share the same key will be
    batched into the same minting transaction.
    */
    bytes batch_key = 1;

    /*
    The transaction ID of the batch. Only populated if the batch has been
    committed.
    */
    string batch_txid = 2;

    // The state of the batch.
    BatchState state = 3;

    // The assets that are part of the batch.
    repeated PendingAsset assets = 4;

    // The time the batch was created as a Unix timestamp (in seconds).
    int64 created_at = 5;

    // The current height of the block chain at the time of the batch creation.
    uint32 height_hint = 6;

    // The genesis transaction as a PSBT packet. Only populated if the batch has
    // been committed.
    bytes batch_psbt = 7;
}

message VerboseBatch {
    // The minting batch, without any assets.
    MintingBatch batch = 1;

    // The assets that are part of the batch.
    repeated UnsealedAsset unsealed_assets = 2;
}

enum BatchState {
    BATCH_STATE_UNKNOWN = 0;
    BATCH_STATE_PENDING = 1;
    BATCH_STATE_FROZEN = 2;
    BATCH_STATE_COMMITTED = 3;
    BATCH_STATE_BROADCAST = 4;
    BATCH_STATE_CONFIRMED = 5;
    BATCH_STATE_FINALIZED = 6;
    BATCH_STATE_SEEDLING_CANCELLED = 7;
    BATCH_STATE_SPROUT_CANCELLED = 8;
}

message FundBatchRequest {
    /*
    If true, then the assets currently in the batch won't be returned in the
    response. This is mainly to avoid a lot of data being transmitted and
    possibly printed on the command line in the case of a very large batch.
    */
    bool short_response = 1;

    // The optional fee rate to use for the minting transaction, in sat/kw.
    uint32 fee_rate = 2;

    /*
    The optional tapscript sibling that will be used when deriving the genesis
    output for the batch. This sibling is a tapscript tree, which allows the
    minter to encumber future transfers of assets in the batch with Tapscript.
    */
    oneof batch_sibling {
        /*
        An ordered list of TapLeafs, which will be used to construct a
        Tapscript tree.
        */
        taprpc.TapscriptFullTree full_tree = 3;

        // A TapBranch that represents a Tapscript tree managed externally.
        taprpc.TapBranch branch = 4;
    }
}

message FundBatchResponse {
    // The funded batch.
    MintingBatch batch = 1;
}

message SealBatchRequest {
    /*
    If true, then the assets currently in the batch won't be returned in the
    response. This is mainly to avoid a lot of data being transmitted and
    possibly printed on the command line in the case of a very large batch.
    */
    bool short_response = 1;

    // The assetID, witness pairs that authorize asset membership in a group.
    repeated taprpc.GroupWitness group_witnesses = 2;
}

message SealBatchResponse {
    // The sealed batch.
    MintingBatch batch = 1;
}

message FinalizeBatchRequest {
    /*
    If true, then the assets currently in the batch won't be returned in the
    response. This is mainly to avoid a lot of data being transmitted and
    possibly printed on the command line in the case of a very large batch.
    */
    bool short_response = 1;

    // The optional fee rate to use for the minting transaction, in sat/kw.
    uint32 fee_rate = 2;

    /*
    The optional tapscript sibling that will be used when deriving the genesis
    output for the batch. This sibling is a tapscript tree, which allows the
    minter to encumber future transfers of assets in the batch with Tapscript.
    */
    oneof batch_sibling {
        /*
        An ordered list of TapLeafs, which will be used to construct a
        Tapscript tree.
        */
        taprpc.TapscriptFullTree full_tree = 3;

        // A TapBranch that represents a Tapscript tree managed externally.
        taprpc.TapBranch branch = 4;
    }
}

message FinalizeBatchResponse {
    // The finalized batch.
    MintingBatch batch = 1;
}

message CancelBatchRequest {
}

message CancelBatchResponse {
    // The internal public key of the batch.
    bytes batch_key = 1;
}

message ListBatchRequest {
    // The optional batch key of the batch to list.
    oneof filter {
        // The optional batch key of the batch to list, specified as raw bytes
        // (gRPC only).
        bytes batch_key = 1;

        // The optional batch key of the batch to list, specified as a hex
        // encoded string (use this for REST).
        string batch_key_str = 2;
    }

    // If true, pending asset group information will be shown for the pending
    // batch.
    bool verbose = 3;
}

message ListBatchResponse {
    repeated VerboseBatch batches = 1;
}

message SubscribeMintEventsRequest {
    /*
    If true, then the assets currently in the batch won't be returned in the
    event's batch. This is mainly to avoid a lot of data being transmitted and
    possibly printed on the command line in the case of a very large batch.
    */
    bool short_response = 1;
}

message MintEvent {
    // Execute timestamp (Unix timestamp in microseconds).
    int64 timestamp = 1;

    // The last state of the batch that was successfully executed. If error
    // below is set, then the batch_state is the state that lead to the error
    // during its execution.
    BatchState batch_state = 2;

    // The batch that the event is for.
    MintingBatch batch = 3;

    // An optional error, indicating that executing the batch_state failed.
    string error = 4;
}
