// Copyright (c) 2019 IoTeX
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

// To compile the proto, run:
//      protoc -I. -I ./../types --go_out=plugins=grpc:$GOPATH/src *.proto
syntax = "proto3";
package iotexapi;
option go_package = "github.com/iotexproject/iotex-proto/golang/iotexapi";
option java_multiple_files = true;
option java_package = "com.github.iotexproject.grpc.api";

import "proto/types/action.proto";
import "proto/types/blockchain.proto";
import "proto/types/node.proto";
import "proto/types/election.proto";
import "proto/types/transaction_log.proto";
import "google/protobuf/timestamp.proto";

service APIService {
  // get the address detail of an address
  rpc GetAccount(GetAccountRequest) returns (GetAccountResponse) {}

  // get action(s) by:
  // 1. start index and action count
  // 2. action hash
  // 3. address with start index and action count
  // 4. get unconfirmed actions by address with start index and action count
  // 5. block hash with start index and action count
  rpc GetActions(GetActionsRequest) returns (GetActionsResponse) {}

  // get block metadata(s) by:
  // 1. start index and block count
  // 2. block hash
  rpc GetBlockMetas(GetBlockMetasRequest) returns (GetBlockMetasResponse) {}

  // get chain metadata
  rpc GetChainMeta(GetChainMetaRequest) returns (GetChainMetaResponse) {}

  // get server version
  rpc GetServerMeta(GetServerMetaRequest) returns (GetServerMetaResponse) {}

  // sendAction
  rpc SendAction(SendActionRequest) returns (SendActionResponse) {}

  // get receipt by action Hash
  rpc GetReceiptByAction(GetReceiptByActionRequest) returns (GetReceiptByActionResponse) {}

  // TODO: read contract
  rpc ReadContract(ReadContractRequest) returns (ReadContractResponse) {}

  // suggest gas price
  rpc SuggestGasPrice(SuggestGasPriceRequest) returns (SuggestGasPriceResponse) {}

  // estimate gas for action, to be deprecated
  rpc EstimateGasForAction(EstimateGasForActionRequest) returns (EstimateGasForActionResponse) {}

  // estimate gas for action and transfer not sealed
  rpc EstimateActionGasConsumption(EstimateActionGasConsumptionRequest) returns (EstimateActionGasConsumptionResponse) {}

  // read state from blockchain
  rpc ReadState(ReadStateRequest) returns (ReadStateResponse) {}

  // get epoch metadata
  rpc GetEpochMeta(GetEpochMetaRequest) returns (GetEpochMetaResponse) {}

  // get raw blocks data
  rpc GetRawBlocks(GetRawBlocksRequest) returns (GetRawBlocksResponse) {}

  // get logs filtered by contract address and topics
  rpc GetLogs(GetLogsRequest) returns (GetLogsResponse) {}

  rpc GetTransactionLogByActionHash(GetTransactionLogByActionHashRequest) returns (GetTransactionLogByActionHashResponse) {}

  rpc GetTransactionLogByBlockHeight(GetTransactionLogByBlockHeightRequest) returns (GetTransactionLogByBlockHeightResponse) {}

  /*
   * below are streaming APIs
   */

  // get block info in stream
  rpc StreamBlocks(StreamBlocksRequest) returns (stream StreamBlocksResponse) {}

  // get logs filtered by contract address and topics in stream
  rpc StreamLogs(StreamLogsRequest) returns (stream StreamLogsResponse) {}

  // get actions from act pool
  rpc GetActPoolActions(GetActPoolActionsRequest) returns (GetActPoolActionsResponse) {}

  // Deprecated
  rpc GetEvmTransfersByActionHash(GetEvmTransfersByActionHashRequest) returns (GetEvmTransfersByActionHashResponse) {}

  // Deprecated
  rpc GetEvmTransfersByBlockHeight(GetEvmTransfersByBlockHeightRequest) returns (GetEvmTransfersByBlockHeightResponse) {}

  // Deprecated
  rpc GetElectionBuckets(GetElectionBucketsRequest) returns (GetElectionBucketsResponse) {}

  rpc ReadContractStorage(ReadContractStorageRequest) returns (ReadContractStorageResponse) {}

  rpc TraceTransactionStructLogs(TraceTransactionStructLogsRequest) returns (TraceTransactionStructLogsResponse) {}
}

// experiment
service TransactionLogService {
  rpc GetTransactionLogByActionHash(GetTransactionLogByActionHashRequest) returns (GetTransactionLogByActionHashResponse) {}

  rpc GetTransactionLogByBlockHeight(GetTransactionLogByBlockHeightRequest) returns (GetTransactionLogByBlockHeightResponse) {}
}

message Bucket {
  // hex string
  string voter = 1;
  string votes = 2;
  string weightedVotes = 3;
  // human readable duration
  string remainingDuration = 4;
}

message GetAccountRequest {
  string address = 1;
}

message GetAccountResponse {
  iotextypes.AccountMeta accountMeta = 1;
  iotextypes.BlockIdentifier blockIdentifier = 2;
}

message GetActionsRequest {
  oneof lookup {
    GetActionsByIndexRequest byIndex = 1;
    GetActionByHashRequest byHash = 2;
    GetActionsByAddressRequest byAddr = 3;
    GetUnconfirmedActionsByAddressRequest unconfirmedByAddr = 4;
    GetActionsByBlockRequest byBlk = 5;
  }
}

message GetActionsByIndexRequest {
  uint64 start = 1;
  uint64 count = 2;
}

message GetActionByHashRequest {
  string actionHash = 1;
  bool checkPending = 2;
}

message GetActionsByAddressRequest {
  string address = 1;
  uint64 start = 2;
  uint64 count = 3;
}

message GetUnconfirmedActionsByAddressRequest {
  string address = 1;
  uint64 start = 2;
  uint64 count = 3;
}

message GetActionsByBlockRequest {
  string blkHash = 1;
  uint64 start = 2;
  uint64 count = 3;
}

message ActionInfo {
  iotextypes.Action action = 1;
  string actHash = 2;
  string blkHash = 3;
  google.protobuf.Timestamp timestamp = 4;
  uint64 blkHeight = 5;
  string sender = 6;
  string gasFee = 7;
  uint32 index = 8;
}

message ReceiptInfo {
  iotextypes.Receipt receipt = 1;
  string blkHash = 2;
}

message BlockProducerInfo {
  string address = 1;
  string votes = 2;
  bool active = 3;
  uint64 production = 4;
}

message BlockInfo {
  iotextypes.Block block = 1;
  repeated iotextypes.Receipt receipts = 2;
  iotextypes.TransactionLogs transactionLogs = 3;
}

message GetActionsResponse {
  uint64 total = 2;
  repeated ActionInfo actionInfo = 1;
}

message GetBlockMetasRequest {
  oneof lookup {
    GetBlockMetasByIndexRequest byIndex = 1;
    GetBlockMetaByHashRequest byHash = 2;
  }
}

message GetBlockMetasByIndexRequest {
  uint64 start = 1;
  uint64 count = 2;
}

message GetBlockMetaByHashRequest {
  string blkHash = 1;
}

message GetBlockMetasResponse {
  uint64 total = 2;
  repeated iotextypes.BlockMeta blkMetas = 1;
}

message GetChainMetaRequest {}

message GetChainMetaResponse {
  iotextypes.ChainMeta chainMeta = 1;
  string syncStage = 2; // sync stage
}

message GetServerMetaRequest  {}

message GetServerMetaResponse  {
  iotextypes.ServerMeta serverMeta = 1;
}

message SendActionRequest {
  iotextypes.Action action = 1;
}

message SendSignedActionBytesRequest {
  string signedActionBytes = 1;
}

message SendActionResponse {
  string actionHash = 1;
}

message GetReceiptByActionRequest {
  string actionHash = 1;
}

message GetReceiptByActionResponse {
  ReceiptInfo receiptInfo = 1;
}

message ReadContractRequest {
  iotextypes.Execution execution = 1;
  string callerAddress = 2;
  uint64 gasLimit = 3;
  string gasPrice = 4;
}

message ReadContractResponse {
  string data = 1;
  iotextypes.Receipt receipt = 2;
}

message SuggestGasPriceRequest {}

message SuggestGasPriceResponse {
  uint64 gasPrice = 1;
}

// To be deprecated
message EstimateGasForActionRequest {
  iotextypes.Action action = 1;
}

message EstimateActionGasConsumptionRequest {
  oneof action {
    iotextypes.Transfer transfer = 1;
    iotextypes.Execution execution = 2;
    // Native staking
    iotextypes.StakeCreate stakeCreate = 40;
    iotextypes.StakeReclaim stakeUnstake = 41;
    iotextypes.StakeReclaim stakeWithdraw = 42;
    iotextypes.StakeAddDeposit stakeAddDeposit = 43;
    iotextypes.StakeRestake stakeRestake = 44;
    iotextypes.StakeChangeCandidate stakeChangeCandidate = 45;
    iotextypes.StakeTransferOwnership stakeTransferOwnership = 46;
    iotextypes.CandidateRegister candidateRegister = 47;
    iotextypes.CandidateBasicInfo candidateUpdate = 48;
    iotextypes.CandidateActivate candidateActivate = 49;
    iotextypes.CandidateEndorsement candidateEndorsement = 51;
    iotextypes.CandidateTransferOwnership candidateTransferOwnership = 52;
    iotextypes.StakeMigrate stakeMigrate = 53;
  }
  string callerAddress = 100;
  string gasPrice = 101;
}

message EstimateActionGasConsumptionResponse {
  uint64 gas = 1;
}

message EstimateGasForActionResponse {
  uint64 gas = 1;
}

message ReadStateRequest {
  bytes protocolID = 1;
  bytes methodName = 2;
  repeated bytes arguments = 3;
  string height = 4; // optional, if not present, read from tip height
}

message ReadStateResponse {
  bytes data = 1;
  iotextypes.BlockIdentifier blockIdentifier = 2;
}

message GetEpochMetaRequest {
  uint64 epochNumber = 1;
}

message GetEpochMetaResponse {
  iotextypes.EpochData epochData = 1;
  uint64 totalBlocks = 2;
  repeated BlockProducerInfo blockProducersInfo = 3;
}

message GetRawBlocksRequest {
  uint64 startHeight = 1;
  uint64 count = 2;
  bool withReceipts = 3;
  bool withTransactionLogs = 4;
}

message GetRawBlocksResponse {
  repeated BlockInfo blocks = 1;
}

message GetLogsByBlock {
  bytes blockHash = 1;
}

message GetLogsByRange {
  uint64 fromBlock = 1;
  uint64 toBlock = 2;
  uint64 paginationSize = 3;
}

message Topics {
    repeated bytes topic = 1;
}

message LogsFilter {
  repeated string address = 1;
  repeated Topics topics = 2;
}

message GetLogsRequest {
  LogsFilter filter = 1;
  oneof lookup {
    GetLogsByBlock byBlock = 2;
    GetLogsByRange byRange = 3;
  }
}

message GetLogsResponse {
  repeated iotextypes.Log logs = 1;
}

message GetTransactionLogByActionHashRequest {
  string actionHash = 1;
}

message GetTransactionLogByActionHashResponse {
  iotextypes.TransactionLog transactionLog = 1;
}

message GetTransactionLogByBlockHeightRequest {
  uint64 blockHeight = 1;
}

message GetTransactionLogByBlockHeightResponse {
  iotextypes.TransactionLogs transactionLogs = 1;
  iotextypes.BlockIdentifier blockIdentifier = 2;
}

/*
 * below are streaming APIs
 */
message StreamBlocksRequest {}

message StreamBlocksResponse {
    BlockInfo block = 1;
    iotextypes.BlockIdentifier blockIdentifier = 2;
}

message StreamLogsRequest {
    LogsFilter filter = 1;
}

message StreamLogsResponse {
    iotextypes.Log log = 1;
}

message GetActPoolActionsRequest {
  repeated string actionHashes = 1;  // if this field is absent, get all actions from actpool
}

message GetActPoolActionsResponse {
  repeated iotextypes.Action actions = 1;
}

 /*
  * election APIs
  */
message GetElectionBucketsRequest{
  uint64 epochNum = 1;
}

message GetElectionBucketsResponse{
  repeated iotextypes.ElectionBucket buckets = 1;
}

// Deprecated
message GetEvmTransfersByActionHashRequest {
  string actionHash = 1;
}

// Deprecated
message GetEvmTransfersByActionHashResponse {
  iotextypes.ActionEvmTransfer actionEvmTransfers = 1;
}

// Deprecated
message GetEvmTransfersByBlockHeightRequest {
  uint64 blockHeight = 1;
}

// Deprecated
message GetEvmTransfersByBlockHeightResponse {
  iotextypes.BlockEvmTransfer blockEvmTransfers = 1;
}

message ReadContractStorageRequest {
  string contract = 1;
  bytes key = 2;
}

message ReadContractStorageResponse {
  bytes data = 1;
}

message TraceTransactionStructLogsRequest {
  string actionHash = 1;
}

message TraceTransactionStructLogsResponse {
  repeated iotextypes.TransactionStructLog  structLogs = 1;
}
