syntax = "proto3";

package ark.v1;

import "meshapi/gateway/annotations.proto";
import "ark/v1/types.proto";

service ArkService {
  // GetInfo returns information and parameters of the server.
  rpc GetInfo(GetInfoRequest) returns (GetInfoResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/info"
    };
  }

  // RegisterIntent allows to register a new intent that will be eventually selected by the server
  // for a particular batch.
  // The client should provide a BIP-322 message with the intent information, and the server should
  // respond with an intent id.
  rpc RegisterIntent(RegisterIntentRequest) returns (RegisterIntentResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/registerIntent"
      body: "*"
    };
  };

  // EstimateIntentFee allows to estimate the fees for a given intent.
  // The client should provide a BIP-322 message with the same data as the register intent message,
  // and the server should respond with the estimated fees in satoshis.
  rpc EstimateIntentFee(EstimateIntentFeeRequest) returns (EstimateIntentFeeResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/estimateFee"
      body: "*"
    };
  }
  
  // DeleteIntent removes a previously registered intent from the server.
  // The client should provide the BIP-322 signature and message including any of the vtxos used in
  // the registered intent to prove its ownership.
  // The server should delete the intent and return success.
  rpc DeleteIntent(DeleteIntentRequest) returns (DeleteIntentResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/deleteIntent"
      body: "*"
    };
  }

  // ConfirmRegistration allows a client that has been selected for the next batch to confirm its
  // participation by revealing the intent id.
  rpc ConfirmRegistration(ConfirmRegistrationRequest) returns (ConfirmRegistrationResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/ack"
      body: "*"
    };
  };
  
  // SubmitTreeNonces allows a cosigner to submit the tree nonces for the musig2 session of a given
  // batch.
  // The client should provide the batch id, the cosigner public key, and the tree nonces.
  // The server should verify the cosigner public key and the nonces, and store them for later
  // aggregation once nonces from all clients are collected.
  rpc SubmitTreeNonces(SubmitTreeNoncesRequest) returns (SubmitTreeNoncesResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/tree/submitNonces"
      body: "*"
    };
  }
  
  // SubmitTreeSignatures allows a cosigner to submit the tree signatures for the musig2 session of
  // a given batch.
  // The client should provide the batch id, the cosigner public key, and the tree signatures.
  // The server should verify the cosigner public key and the signatures, and store them for later
  // aggregation once signatures from all clients are collected.
  rpc SubmitTreeSignatures(SubmitTreeSignaturesRequest) returns (SubmitTreeSignaturesResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/tree/submitSignatures"
      body: "*"
    };
  }
  
  // SubmitSignedForfeitTxs allows a client to submit signed forfeit transactions and/or signed
  // commitment transaction (in case of onboarding).
  // The server should verify the signed txs and return success.
  rpc SubmitSignedForfeitTxs(SubmitSignedForfeitTxsRequest) returns (SubmitSignedForfeitTxsResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/submitForfeitTxs"
      body: "*"
    };
  };
  
  // GetEventStream is a server-side streaming RPC that allows clients to receive a stream of
  // events related to batch processing.
  // Clients should use this stream as soon as they are ready to join a batch and can listen for
  // various events such as batch start, batch finalization, and other related activities.
  // The server pushes these events to the client in real-time as soon as its ready to move to the
  // next phase of the batch processing. Upon creation of the stream, the event StreamStartedEvent
  // is immediately sent, which passes along the stream id, to be used by the client for future
  // calls to UpdateStreamTopics.
  rpc GetEventStream(GetEventStreamRequest) returns (stream GetEventStreamResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/batch/events"
      stream: {
        disable_chunked_transfer: true
        disable_websockets: true
      }
    };
  };

  // UpdateStreamTopics allows a client to modify the topics of their event stream. They can add,
  // remove, or specify a list of topics, providing them control over the events received on the
  // event stream. 
  rpc UpdateStreamTopics(UpdateStreamTopicsRequest) returns (UpdateStreamTopicsResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/batch/updateTopics"
      body: "*"
    };
  }

  // SubmitTx is the first leg of the process of spending vtxos offchain and allows a client to
  // submit a signed Ark transaction and the unsigned checkpoint transactions.
  // The server should verify the signed transactions and return the fully signed Ark tx and the
  // signed checkpoint txs.
  rpc SubmitTx(SubmitTxRequest) returns (SubmitTxResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/tx/submit"
      body: "*"
    };
  }

  // FinalizeTx is the last lef of the process of spending vtxos offchain and allows a client to
  // submit the fully signed checkpoint txs for the provided Ark txid .
  // The server verifies the signed checkpoint transactions and returns success if everything is
  // valid.
  rpc FinalizeTx(FinalizeTxRequest) returns (FinalizeTxResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/tx/finalize"
      body: "*"
    };
  }

  // GetPendingTx returns not finalized transaction(s) for a given set of inputs.
  // the client should provide a BIP322 proof of ownership of the inputs
  rpc GetPendingTx(GetPendingTxRequest) returns (GetPendingTxResponse) {
    option (meshapi.gateway.http) = {
      post: "/v1/tx/pending"
      body: "*"
    };
  }

  // GetTransactionsStream is a server-side streaming RPC that allows clients to receive
  // notifications in real-time about any commitment tx or ark tx processed and finalized by the
  // server.
  // NOTE: the stream doesn't have history support, therefore returns only txs from the moment it's
  // opened until it's closed.
  rpc GetTransactionsStream(GetTransactionsStreamRequest) returns (stream GetTransactionsStreamResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/txs"
      stream: {
        disable_chunked_transfer: true
        disable_websockets: true
      }
    };
  }

  rpc GetIntent(GetIntentRequest) returns (GetIntentResponse) {
    option (meshapi.gateway.http) = {
      get: "/v1/intent"
      additional_bindings {
        post: "/v1/intent"
        body: "*"
      }
    };
  }
}

message GetInfoRequest {}
message GetInfoResponse {
  string version = 1;
  string signer_pubkey = 2;
  string forfeit_pubkey = 3;
  string forfeit_address = 4;
  string checkpoint_tapscript = 5;
  string network = 6;
  int64 session_duration = 7;
  int64 unilateral_exit_delay = 8;
  int64 boarding_exit_delay = 9;
  int64 utxo_min_amount = 10;
  int64 utxo_max_amount = 11; // -1 means no limit (default), 0 means boarding not allowed
  int64 vtxo_min_amount = 12; 
  int64 vtxo_max_amount = 13; // -1 means no limit (default)
  int64 dust = 14;
  FeeInfo fees = 15;
  ScheduledSession scheduled_session = 16;
  repeated DeprecatedSigner deprecated_signers = 17;
  map<string, string> service_status = 18;
  string digest = 19;
  int64 max_tx_weight = 20;
  int64 max_op_return_outputs = 21;
}

message RegisterIntentRequest {
  // an intent proof that embeds the outpoints to be spent and new ones to be created, as well as the
  // proof of funds.
  Intent intent = 1;
}
message RegisterIntentResponse {
  string intent_id = 1;
}

message EstimateIntentFeeRequest {
  Intent intent = 1;
}
message EstimateIntentFeeResponse {
  int64 fee = 1;
}

message DeleteIntentRequest {
  // an intent proof that includes any of the inputs of the intent to be deleted to prove the
  // ownership of that intent.
  Intent intent = 1;
}
message DeleteIntentResponse {}

message ConfirmRegistrationRequest {
  string intent_id = 1;
}
message ConfirmRegistrationResponse {}

message SubmitTreeNoncesRequest {
  string batch_id = 1;
  string pubkey = 2;
  map<string, string> tree_nonces = 3;
}
message SubmitTreeNoncesResponse {}

message SubmitTreeSignaturesRequest {
  string batch_id = 1;
  string pubkey = 2;
  map<string, string> tree_signatures = 3;
}
message SubmitTreeSignaturesResponse {}

message SubmitSignedForfeitTxsRequest {
  // Forfeit txs signed by the user.
  repeated string signed_forfeit_txs = 1;
  // The user has to sign also the commitment tx if he registered a boarding UTXO.
  string signed_commitment_tx = 2;
}
message SubmitSignedForfeitTxsResponse {}

message GetEventStreamRequest {
  repeated string topics = 1;
}
message GetEventStreamResponse {
  oneof event {
    BatchStartedEvent batch_started = 1;
    BatchFinalizationEvent batch_finalization = 2;
    BatchFinalizedEvent batch_finalized = 3;
    BatchFailedEvent batch_failed = 4;
    TreeSigningStartedEvent tree_signing_started = 5;
    TreeNoncesAggregatedEvent tree_nonces_aggregated = 6;
    TreeTxEvent tree_tx = 7;
    TreeSignatureEvent tree_signature = 8;
    TreeNoncesEvent tree_nonces = 9;
    Heartbeat heartbeat = 10;
    StreamStartedEvent stream_started = 11;
  }
}

message ModifyTopics {
  repeated string add_topics = 1;
  repeated string remove_topics = 2;
}

message OverwriteTopics {
  repeated string topics = 1;
}

// Adding and removing topics can both be supplied in the same request,
// allowing for simultaneous changes.
// overwrite_topics will take precedence, and if set, then the add/remove
// topics are ignored. The stream_id is required.
message UpdateStreamTopicsRequest {
  string stream_id = 1;

  oneof topics_change {
    ModifyTopics modify = 2;
    OverwriteTopics overwrite = 3;
  }
}

message UpdateStreamTopicsResponse {
  repeated string topics_added = 1;
  repeated string topics_removed = 2;
  repeated string all_topics = 3;
}

message SubmitTxRequest {
  string signed_ark_tx = 1;
  repeated string checkpoint_txs = 2;
}
message SubmitTxResponse {
  string ark_txid = 1;
  string final_ark_tx = 2;
  repeated string signed_checkpoint_txs = 3;
}

message FinalizeTxRequest {
  string ark_txid = 1;
  repeated string final_checkpoint_txs = 2;
}
message FinalizeTxResponse {}

message GetPendingTxRequest {
  oneof identifier {
    Intent intent = 1;
  }
}
message GetPendingTxResponse {
  repeated PendingTx pending_txs = 1;
}

message GetTransactionsStreamRequest {}
message GetTransactionsStreamResponse {
  oneof data {
    TxNotification commitment_tx = 1;
    TxNotification ark_tx = 2;
    Heartbeat heartbeat = 3;
    TxNotification sweep_tx = 4;
  }
}

message GetIntentRequest {
  oneof filter {
    string txid = 1;
    Intent intent = 2;
  }
}

// The repeated intents field is always populated with the matching results.
// The singular intent field is only set for backward compatibility when the
// request uses the txid filter, in which case it mirrors intents[0].
message GetIntentResponse {
  Intent intent = 1;
  repeated Intent intents = 2;
}