syntax = "proto3";
package forge_abi;

import "google/protobuf/any.proto";
import "vendor.proto";
import "enum.proto";
import "type.proto";
import "state.proto";
import "trace_type.proto";

// Request / Response message definition

// create_tx(itx, wallet, token)
message RequestCreateTx {
  google.protobuf.Any itx = 1;
  string from = 2;
  uint64 nonce = 3;
  WalletInfo wallet = 4;
  string token = 5;
}

message ResponseCreateTx {
  StatusCode code = 1;
  Transaction tx = 2;
}

// multisig(tx, wallet, token)
message RequestMultisig {
  Transaction tx = 1;
  // extra data for multisig
  google.protobuf.Any data = 2;
  WalletInfo wallet = 3;
  string token = 4;
}

message ResponseMultisig {
  StatusCode code = 1;
  Transaction tx = 2;
}

// send_tx(tx, wallet, token, commit \\ false)
message RequestSendTx {
  Transaction tx = 1;
  WalletInfo wallet = 2;
  string token = 3;
  bool commit = 4;
}

message ResponseSendTx {
  StatusCode code = 1;
  string hash = 2;
}

// get_tx(hash)
message RequestGetTx { string hash = 1; }

message ResponseGetTx {
  StatusCode code = 1;
  TransactionInfo info = 2;
}

// get_block(height)
message RequestGetBlock { uint64 height = 1; }

message ResponseGetBlock {
  StatusCode code = 1;
  BlockInfo block = 2;
}

message RequestGetBlocks {
  PageInput paging = 1;
  RangeFilter height_filter = 2;
  bool empty_excluded = 3;
}

message ResponseGetBlocks {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated BlockInfoSimple blocks = 3;
}

// create_wallet(moniker, passphrase): create an account locally
message RequestCreateWallet {
  string passphrase = 1;
  WalletType type = 2;
  string moniker = 3;
}

message ResponseCreateWallet {
  StatusCode code = 1;
  string token = 2;
  WalletInfo wallet = 3;
}

// load_wallet(address, passphrase): load account to memory with given
// passphrase
message RequestLoadWallet {
  string address = 1;
  string passphrase = 2;
}

message ResponseLoadWallet {
  StatusCode code = 1;
  string token = 2;
  WalletInfo wallet = 3;
}

// recover_wallet(data, passphrase): recover to a keystore with given
// passphrase. data could be seed words or bytes of secret key.
message RequestRecoverWallet {
  bytes data = 1;
  WalletType type = 2;
  string passphrase = 3;
  string moniker = 4;
}

message ResponseRecoverWallet {
  StatusCode code = 1;
  string token = 2;
  WalletInfo wallet = 3;
}

// list_wallet(): list accounts stored in this node
message RequestListWallet {}

message ResponseListWallet {
  StatusCode code = 1;
  string address = 2;
}

// remove_wallet(hash): remove account by hash for this node
message RequestRemoveWallet { string address = 1; }

message ResponseRemoveWallet { StatusCode code = 1; }

message RequestDeclareNode { bool validator = 1; }

message ResponseDeclareNode {
  StatusCode code = 1;
  WalletInfo wallet = 3;
}

// get_account_state(address, key): retrieve the current state from a list of
// wallet addresses, return the value of the key. If key is omitted, return
// entire account states
message RequestGetAccountState {
  string address = 1;
  repeated string keys = 2;
  uint64 height = 3;
}

message ResponseGetAccountState {
  StatusCode code = 1;
  AccountState state = 2;
}

message RequestGetAssetState {
  string address = 1;
  repeated string keys = 2;
  uint64 height = 3;
}

message ResponseGetAssetState {
  StatusCode code = 1;
  AssetState state = 2;
}

message RequestGetProtocolState {
  string address = 1;
  repeated string keys = 2;
  uint64 height = 3;
}

message ResponseGetProtocolState {
  StatusCode code = 1;
  ProtocolState state = 2;
}

message RequestGetStakeState {
  string address = 1;
  repeated string keys = 2;
  uint64 height = 3;
}

message ResponseGetStakeState {
  StatusCode code = 1;
  StakeState state = 2;
}

// get_forge_state(key): retrieve Forge state by key. If key is omitted, return
// entire Forge state
message RequestGetForgeState {
  repeated string keys = 1;
  uint64 height = 3;
}

message ResponseGetForgeState {
  StatusCode code = 1;
  ForgeState state = 2;
}

message RequestGetTetherState {
  string address = 1;
  repeated string keys = 2;
  uint64 height = 3;
}

message ResponseGetTetherState {
  StatusCode code = 1;
  TetherState state = 2;
}

// store_file(chunk): store a piece of data into ipfs, return its hash address
message RequestStoreFile { bytes chunk = 1; }

message ResponseStoreFile {
  StatusCode code = 1;
  string hash = 2;
}

// load_file(hash): load a hash address from ipfs and return the file content
message RequestLoadFile { string hash = 1; }

message ResponseLoadFile {
  StatusCode code = 1;
  bytes chunk = 2;
}

// pin_file(hash): pin a hash address into ipfs, return ok if success
message RequestPinFile { string hash = 1; }

message ResponsePinFile { StatusCode code = 1; }

// get_chain_info(): retrieve the current chain information
message RequestGetChainInfo {}

message ResponseGetChainInfo {
  StatusCode code = 1;
  ChainInfo info = 2;
}

// get_node_info(): retrieve the current node information
message RequestGetNodeInfo {}

message ResponseGetNodeInfo {
  StatusCode code = 1;
  NodeInfo info = 2;
}

// search(term): retrieve related transactions by a search term (prefix match)
message RequestSearch {
  string key = 1;
  string value = 2;
}

message ResponseSearch {
  StatusCode code = 1;
  repeated TransactionInfo txs = 2;
}

message RequestGetUnconfirmedTxs { PageInput paging = 1; }

message ResponseGetUnconfirmedTxs {
  StatusCode code = 1;
  PageInfo page = 2;
  UnconfirmedTxs unconfirmed_txs = 3;
}

message RequestGetNetInfo {}

message ResponseGetNetInfo {
  StatusCode code = 1;
  NetInfo net_info = 2;
}

message RequestGetValidatorsInfo {}

message ResponseGetValidatorsInfo {
  StatusCode code = 1;
  ValidatorsInfo validators_info = 2;
}

// event subscription

// filter could be: value.header.height > 10086 and value.byzantine_validators
// != []
message RequestSubscribe {
  string topic = 1;
  string filter = 2;
}

message ResponseSubscribe {
  StatusCode code = 1;
  oneof value {
    string topic = 2;
    Transaction transfer = 3;
    Transaction account_migrate = 4;
    Transaction confirm = 5;
    Transaction create_asset = 6;
    Transaction exchange = 7;
    Transaction revoke = 8;

    abci_vendor.RequestBeginBlock begin_block = 16;
    abci_vendor.RequestEndBlock end_block = 17;

    Transaction declare = 19;
    Transaction update_asset = 20;
    Transaction consensus_upgrade = 21;
    Transaction declare_file = 22;
    Transaction sys_upgrade = 23;
    Transaction stake = 24;

    AccountState account_state = 129;
    AssetState asset_state = 130;
    ForgeState forge_state = 131;
    StakeState stake_state = 132;
    ProtocolState protocol_state = 133;
  }
}

message RequestUnsubscribe { string topic = 1; }

message ResponseUnsubscribe { StatusCode code = 1; }

// get config
message RequestGetConfig {}
message ResponseGetConfig {
  StatusCode code = 1;
  string config = 2;
}

message ByDay {
  string start_date = 1;
  string end_date = 2;
}

message ByHour { string date = 1; }

message RequestGetForgeStats {
  oneof value {
    ByDay day_info = 1;
    ByHour date = 2;
  }
}

message ResponseGetForgeStats {
  StatusCode code = 1;
  ForgeStats forge_stats = 2;
}

message RequestListTransactions {
  PageInput paging = 1;
  TimeFilter time_filter = 2;
  AddressFilter address_filter = 3;
  TypeFilter type_filter = 4;
  ValidityFilter validity_filter = 5;
}

message ResponseListTransactions {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated IndexedTransaction transactions = 3;
}

message RequestListAssets {
  PageInput paging = 1;
  string owner_address = 2;
}

message ResponseListAssets {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated IndexedAssetState assets = 3;
}

message RequestListStakes {
  PageInput paging = 1;
  AddressFilter address_filter = 2;
}

message ResponseListStakes {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated IndexedStakeState stakes = 3;
}

message RequestListAccount { string owner_address = 1; }

message ResponseListAccount {
  StatusCode code = 1;
  IndexedAccountState account = 2;
}

message RequestListTopAccounts { PageInput paging = 1; }

message ResponseListTopAccounts {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated IndexedAccountState accounts = 3;
}

message RequestListAssetTransactions {
  PageInput paging = 1;
  string address = 2;
}

message ResponseListAssetTransactions {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated IndexedTransaction transactions = 3;
}

message RequestListBlocks {
  PageInput paging = 1;
  string proposer = 2;
  TimeFilter time_filter = 3;
  RangeFilter height_filter = 4;
  RangeFilter num_txs_filter = 5;
  RangeFilter num_invalid_txs_filter = 6;
}

message ResponseListBlocks {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated IndexedBlock blocks = 3;
}

message RequestListTethers {
  PageInput paging = 1;
  string depositor = 2;
  string withdrawer = 3;
  string custodian = 4;
  bool  available = 5;
}

message ResponseListTethers {
  StatusCode code = 1;
  PageInfo page = 2;
  repeated TetherState tethers = 3;
}

message RequestGetHealthStatus {}

message ResponseGetHealthStatus {
  StatusCode code = 1;
  HealthStatus health_status = 2;
}
