syntax = "proto3";

package ark.v1;

import "meshapi/gateway/annotations.proto";

service IndexerService {
  // GetCommitmentTx returns information about a specific commitment transaction identified by the
  // provided txid.
  rpc GetCommitmentTx(GetCommitmentTxRequest) returns (GetCommitmentTxResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/commitmentTx/{txid}"
    };
  };

  // GetForfeitTxs returns the list of forfeit transactions that were submitted for the provided
  // commitment transaction.
  // The response may include pagination information if the results span multiple pages.
  rpc GetForfeitTxs(GetForfeitTxsRequest) returns (GetForfeitTxsResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/commitmentTx/{txid}/forfeitTxs"
    };
  };
  
  // GetConnectors returns the tree of connectors for the provided commitment transaction.
  // The response includes a list of connector txs with details on the tree posistion and may
  // include pagination information if the results span multiple pages.
  rpc GetConnectors(GetConnectorsRequest) returns (GetConnectorsResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/commitmentTx/{txid}/connectors"
    };
  };

  // GetVtxoTree returns the vtxo tree for the provided batch outpoint.
  // The response includes a list of txs with details on the tree posistion and may
  // include pagination information if the results span multiple pages.
  rpc GetVtxoTree(GetVtxoTreeRequest) returns (GetVtxoTreeResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/batch/{batch_outpoint.txid}/{batch_outpoint.vout}/tree"
    };
  };

  // GetVtxoTreeLeaves returns the list of leaves (vtxo outpoints) of the tree(s) for the
  // provided batch outpoint.
  // The response may be paginated if the results span multiple pages.
  rpc GetVtxoTreeLeaves(GetVtxoTreeLeavesRequest) returns (GetVtxoTreeLeavesResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/batch/{batch_outpoint.txid}/{batch_outpoint.vout}/tree/leaves"
    };
  };

  // GetVtxos returns the list of vtxos based on the provided filter. Vtxos can be retrieved either
  // by addresses or by outpoints, and optionally filtered by spendable or spent only.
  // The response may be paginated if the results span multiple pages.
  rpc GetVtxos(GetVtxosRequest) returns (GetVtxosResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/vtxos"
    };
  };
  
  // GetVtxoChain returns the the chain of ark txs that starts from spending any vtxo leaf and ends
  // with the creation of the provided vtxo outpoint.
  // The response may be paginated if the results span multiple pages.
  rpc GetVtxoChain(GetVtxoChainRequest) returns (GetVtxoChainResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/vtxo/{outpoint.txid}/{outpoint.vout}/chain"
    };
  }

  // GetVirtualTxs returns the virtual transactions in hex format for the specified txids.
  // The response may be paginated if the results span multiple pages.
  rpc GetVirtualTxs(GetVirtualTxsRequest) returns (GetVirtualTxsResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/virtualTx/{txids}"
    };
  }

  // GetAsset returns the asset information and metadata for the specified asset ID.
  rpc GetAsset(GetAssetRequest) returns (GetAssetResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/asset/{asset_id}"
    };
  }

  // GetBatchSweepTransactions returns the list of transaction (txid) that swept a given batch
  // output.
  // In most cases the list contains only one txid, meaning that all the amount locked for a
  // vtxo tree has been claimed back.
  // If any of the leaves of the tree have been unrolled onchain before the expiration, the
  // list will contain many txids instead.
  // In a binary tree with 4 or more leaves, 1 unroll causes the server to broadcast 3 txs to sweep
  // the whole rest of tree for example.
  // If a whole vtxo tree has been unrolled onchain, the list of txids for that batch output is
  // empty.
  rpc GetBatchSweepTransactions(GetBatchSweepTransactionsRequest) returns (GetBatchSweepTransactionsResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/batch/{batch_outpoint.txid}/{batch_outpoint.vout}/sweepTxs"
    };
  }

  // SubscribeForScripts allows to subscribe for tx notifications related to the provided vtxo
  // scripts. It can also be used to update an existing subscribtion by adding new scripts to it.
  rpc SubscribeForScripts(SubscribeForScriptsRequest) returns (SubscribeForScriptsResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/indexer/script/subscribe"
      body: "*"
    };
  };

  // UnsubscribeForScripts allows to remove scripts from an existing subscription.
  rpc UnsubscribeForScripts(UnsubscribeForScriptsRequest) returns (UnsubscribeForScriptsResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/indexer/script/unsubscribe"
      body: "*"
    };
  };

  
  // GetSubscription is a server-side streaming RPC which allows clients to receive real-time
  // notifications on transactions related to the subscribed vtxo scripts.
  // The subscription can be created or updated by using the SubscribeForScripts and 
  // UnsubscribeForScripts RPCs.
  rpc GetSubscription(GetSubscriptionRequest) returns (stream GetSubscriptionResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/indexer/script/subscription/{subscription_id}"
      stream: {
        disable_chunked_transfer: true
        disable_websockets: true
      }
    };
  };
}

message GetCommitmentTxRequest {
  string txid = 1;
}
message GetCommitmentTxResponse {
  int64 started_at = 1;
  int64 ended_at = 2;
  map<uint32, IndexerBatch> batches = 3;
  uint64 total_input_amount = 4;
  int32 total_input_vtxos = 5;
  uint64 total_output_amount = 6;
  int32 total_output_vtxos = 7;
}

message GetForfeitTxsRequest {
  string txid = 1;
  IndexerPageRequest page = 2;
}
message GetForfeitTxsResponse {
  repeated string txids = 1;
  IndexerPageResponse page = 2;
}

message GetConnectorsRequest {
  string txid = 1;
  IndexerPageRequest page = 2;
}
message GetConnectorsResponse {
  repeated IndexerNode connectors = 1;
  IndexerPageResponse page = 2;
}

message GetVtxoTreeRequest {
  IndexerOutpoint batch_outpoint = 1;
  IndexerPageRequest page = 2;
}
message GetVtxoTreeResponse {
  repeated IndexerNode vtxo_tree = 1;
  IndexerPageResponse page = 2;
}

message GetVtxoTreeLeavesRequest {
  IndexerOutpoint batch_outpoint = 1;
  IndexerPageRequest page = 2;
}
message GetVtxoTreeLeavesResponse {
  repeated IndexerOutpoint leaves = 1;
  IndexerPageResponse page = 2;
}

message GetVtxosRequest {
  // Either specify a list of vtxo scripts.
  repeated string scripts = 1;
  // Or specify a list of vtxo outpoints. The 2 filters are mutually exclusive.
  repeated string outpoints = 2;
  // Retrieve only spendable vtxos
  bool spendable_only = 3;
  // Retrieve only spent vtxos.
  bool spent_only = 4;
  // Retrieve only recoverable vtxos (notes, subdust or swept vtxos).
  // The 3 filters are mutually exclusive,
  bool recoverable_only = 5;
  IndexerPageRequest page = 6;
  // Include only spent vtxos that are not finalized.
  bool pending_only = 7;
  // Include only vtxos with last update after the given unix time in milliseconds.
  // A value of 0 means no lower bound.
  int64 after = 8;
  // Include only vtxos with last update before the given unix time in milliseconds,
  // greater value than the after when specified. A value of 0 means no upper bound.
  int64 before = 9; 
}
message GetVtxosResponse {
  repeated IndexerVtxo vtxos = 1;
  IndexerPageResponse page = 2;
}

message GetVtxoChainRequest {
  IndexerOutpoint outpoint = 1;
  IndexerPageRequest page = 2;
}
message GetVtxoChainResponse {
  repeated IndexerChain chain = 1;
  IndexerPageResponse page = 2;
}

message GetVirtualTxsRequest {
  repeated string txids = 1;
  IndexerPageRequest page = 2;
}

message GetVirtualTxsResponse {
  repeated string txs = 1;
  IndexerPageResponse page = 2;
}

message GetAssetRequest {
  string asset_id = 1;
}

message GetAssetResponse {
  string asset_id = 1;
  string supply = 2;
  string metadata = 3;
  string control_asset = 4;
}

message AssetMetadata {
  string key = 1;
  string value = 2;
}

message GetBatchSweepTransactionsRequest {
  IndexerOutpoint batch_outpoint = 1;

}
message GetBatchSweepTransactionsResponse {
  repeated string swept_by = 1;
}

message IndexerBatch {
  uint64 total_output_amount = 1;
  int32 total_output_vtxos = 2;
  int64 expires_at = 3;
  bool swept = 4;
}

message IndexerOutpoint {
  string txid = 1;
  uint32 vout = 2;
}

message IndexerNode {
  string txid = 1;
  map<uint32, string> children = 2; // vout -> txid
}

message IndexerVtxo {
  IndexerOutpoint outpoint = 1;
  int64 created_at = 2;
  int64 expires_at = 3;
  uint64 amount = 4;
  string script = 5;
  bool is_preconfirmed = 6;
  bool is_swept = 7;
  bool is_unrolled = 8;
  bool is_spent = 9;
  string spent_by = 10;
  repeated string commitment_txids = 11;
  string settled_by = 12;
  string ark_txid = 13;
  repeated IndexerAsset assets = 14;
}

message IndexerAsset {
  string asset_id = 1;
  uint64 amount = 2;
}

message IndexerChain {
  string txid = 1;
  int64 expires_at = 2;
  IndexerChainedTxType type = 3;
  // txids of the transactions in the chain used as input of the current tx
  repeated string spends = 4;
}

message IndexerTxHistoryRecord {
  oneof key {
    string commitment_txid = 1;
    string virtual_txid = 2;
  }
  IndexerTxType type = 3;
  uint64 amount = 4;
  int64 created_at = 5;
  bool is_settled = 6;
  string settled_by = 7;
}

enum IndexerTxType {
  INDEXER_TX_TYPE_UNSPECIFIED = 0;
  INDEXER_TX_TYPE_RECEIVED = 1;
  INDEXER_TX_TYPE_SENT = 2;
}

enum IndexerChainedTxType {
  INDEXER_CHAINED_TX_TYPE_UNSPECIFIED = 0;
  INDEXER_CHAINED_TX_TYPE_COMMITMENT = 1;
  INDEXER_CHAINED_TX_TYPE_ARK = 2;
  INDEXER_CHAINED_TX_TYPE_TREE = 3;
  INDEXER_CHAINED_TX_TYPE_CHECKPOINT = 4;
}

message IndexerPageRequest {
  int32 size = 1;
  int32 index = 2;
}

message IndexerPageResponse {
  int32 current = 1;
  int32 next = 2;
  int32 total = 3;
}

message SubscribeForScriptsRequest {
  repeated string scripts = 1;
  // If set, update an existing subscription
  string subscription_id = 2;
}

message SubscribeForScriptsResponse {
  string subscription_id = 1;
}

message UnsubscribeForScriptsRequest {
  string subscription_id = 1;
  // If empty, unsubscribe all scripts
  repeated string scripts = 2; 
}

message UnsubscribeForScriptsResponse {}


message GetSubscriptionRequest {
  string subscription_id = 1;
}

message GetSubscriptionResponse {
  oneof data {
    IndexerHeartbeat heartbeat = 1;
    IndexerSubscriptionEvent event = 2;
  }
}

message IndexerTxData {
  string txid = 1;
  string tx = 2;
}

message IndexerHeartbeat {
}

message IndexerSubscriptionEvent {
  string txid = 1;
  repeated string scripts = 2;
  repeated IndexerVtxo new_vtxos = 3;
  repeated IndexerVtxo spent_vtxos = 4;
  string tx = 5;
  map<string, IndexerTxData> checkpoint_txs = 6;
  repeated IndexerVtxo swept_vtxos = 7;
}