// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

syntax = "proto3";

package aptos.extractor.v1;

option go_package = "github.com/streamingfast/firehose-aptos/types/pb/aptos/extractor/v1;pbaptos";

import "aptos/util/timestamp/timestamp.proto";

// A block on Aptos holds transactions in chronological order (ordered by a transactions monotonically increasing `version` field)
// All blocks start with a `BlockMetadataTransaction`, and are followed by zero or more transactions.
// The next `BlockMetadataTransaction` denotes the end of the current block, and the start of the next one.
//
// The Block `height` is a strictly monotonically increasing count of the number of blocks,
// and there will never be a gap in the numbers. It is also a unique identifier: there will never be two blocks with
// the same `height`.
//
// The Genesis Transaction (version 0) is contained within the first block, which has a height of `0`
message Block {
  // Timestamp represents the timestamp of the `BlockMetadataTransaction` (or `GenesisTransaction` for the genesis block)
  // and every transaction in the `transactions` will have the same `timestamp` as the block.
  aptos.util.timestamp.Timestamp timestamp = 1;

  // Height represents the block number and ultimately, is the count of `BlockMetadataTransaction` that happened on the chain.
  uint64 height = 2;

  // Transactions holds all transactions that happened in the Block, which is transactions that happened starting with (and including)
  // a `BlockMetadataTransaction`, and every other transaction up to (but excluding) the next `BlockMetadataTransaction`.
  repeated Transaction transactions = 3;

  // Chain ID informs us which chain we're trying to index, this is important to ensure that we're not mixing chains within a single pipeline.
  uint32 chain_id = 4;
}

// Transaction as it happened on the chain, there are 4 types of transactions:
// - User Transaction: a user initiated transaction to interact with the chain
// - Block Metadata Transaction: transactions generated by the chain to group together transactions forming a "block"
// - State Checkpoint Transaction: transactions generated by the chain so when validator agreed on a particular global state
// - Genesis Transaction: the first transaction of the chain, with all core contract and validator information baked in
message Transaction {
  aptos.util.timestamp.Timestamp timestamp = 1;
  uint64 version = 2;
  TransactionInfo info = 3;
  uint64 epoch = 4;
  uint64 block_height = 5;

  enum TransactionType {
    GENESIS = 0;
    BLOCK_METADATA = 1;
    STATE_CHECKPOINT = 2;
    USER = 3;
  }

  TransactionType type = 6;

  oneof txn_data {
    BlockMetadataTransaction block_metadata = 7;
    GenesisTransaction genesis = 8;
    StateCheckpointTransaction state_checkpoint = 9;
    UserTransaction user = 10;
  }
}

// TransactionTrimmed is a real Transaction with most of the fields removed so that
// we can easily decode only the few fields that we have interest in in certain situations.
message TransactionTrimmed {
  aptos.util.timestamp.Timestamp timestamp = 1;
  uint64 version = 2;
}

message BlockMetadataTransaction {
  string id = 1;
  uint64 round = 2;
  repeated Event events = 3;
  bytes previous_block_votes_bitvec = 4;
  string proposer = 5;
  repeated uint32 failed_proposer_indices = 6;
}

message GenesisTransaction {
  WriteSet payload = 1;
  repeated Event events = 2;
}

message StateCheckpointTransaction {
}

message UserTransaction {
  UserTransactionRequest request = 1;
  repeated Event events = 2;
}

message Event {
  EventKey key = 1;
  uint64 sequence_number = 2;
  MoveType type = 3;
  string type_str = 5;
  string data = 4;
}

message TransactionInfo {
  bytes hash = 1;
  bytes state_change_hash = 2;
  bytes event_root_hash = 3;
  optional bytes state_checkpoint_hash = 4;
  uint64 gas_used = 5;
  bool success = 6;
  string vm_status = 7;
  bytes accumulator_root_hash = 8;
  repeated WriteSetChange changes = 9;
}

message EventKey {
  uint64 creation_number = 1;
  string account_address = 2;
}

message UserTransactionRequest {
  string sender = 1;
  uint64 sequence_number = 2;
  uint64 max_gas_amount = 3;
  uint64 gas_unit_price = 4;
  aptos.util.timestamp.Timestamp expiration_timestamp_secs = 5;
  TransactionPayload payload = 6;
  Signature signature = 7;
}

message WriteSet {

  enum WriteSetType {
    SCRIPT_WRITE_SET = 0;
    DIRECT_WRITE_SET = 1;
  }

  WriteSetType write_set_type = 1;
  oneof write_set {
    ScriptWriteSet script_write_set = 2;
    DirectWriteSet direct_write_set = 3;
  }
}

message ScriptWriteSet {
  string execute_as = 1;
  ScriptPayload script = 2;
}

message DirectWriteSet {
  repeated WriteSetChange write_set_change = 1;
  repeated Event events = 2;
}

message WriteSetChange {

  enum Type {
    DELETE_MODULE = 0;
    DELETE_RESOURCE = 1;
    DELETE_TABLE_ITEM = 2;
    WRITE_MODULE = 3;
    WRITE_RESOURCE = 4;
    WRITE_TABLE_ITEM = 5;
  }

  Type type = 1;

  oneof change {
    DeleteModule delete_module = 2;
    DeleteResource delete_resource = 3;
    DeleteTableItem delete_table_item = 4;
    WriteModule write_module = 5;
    WriteResource write_resource = 6;
    WriteTableItem write_table_item = 7;
  }
}

message DeleteModule {
  string address = 1;
  bytes state_key_hash = 2;
  MoveModuleId module = 3;
}

message DeleteResource {
  string address = 1;
  bytes state_key_hash = 2;
  MoveStructTag type = 3;
  string type_str = 4;
}

message DeleteTableItem {
  bytes state_key_hash = 1;
  string handle = 2;
  string key = 3;
  DeleteTableData data = 4;
}

message DeleteTableData {
  string key = 1;
  string key_type = 2;
}

message WriteModule {
  string address = 1;
  bytes state_key_hash = 2;
  MoveModuleBytecode data = 3;
}

message WriteResource {
  string address = 1;
  bytes state_key_hash = 2;
  MoveStructTag type = 3;
  string type_str = 4;
  string data = 5;
}

message WriteTableData {
  string key = 1;
  string key_type = 2;
  string value = 3;
  string value_type = 4;
}

message WriteTableItem {
  bytes state_key_hash = 1;
  string handle = 2;
  string key = 3;
  WriteTableData data = 4;
}

message TransactionPayload {
  enum Type {
    ENTRY_FUNCTION_PAYLOAD = 0;
    SCRIPT_PAYLOAD = 1;
    MODULE_BUNDLE_PAYLOAD = 2;
  }

  Type type = 1;

  oneof payload {
    EntryFunctionPayload entry_function_payload = 2;
    ScriptPayload script_payload = 3;
    ModuleBundlePayload module_bundle_payload = 4;
    WriteSetPayload write_set_payload = 5;
  }
}

message EntryFunctionPayload {
  EntryFunctionId function = 1;
  repeated MoveType type_arguments = 2;
  repeated string arguments = 3;
}

message MoveScriptBytecode {
  bytes bytecode = 1;
  MoveFunction abi = 2;
}

message ScriptPayload {
  MoveScriptBytecode code = 1;
  repeated MoveType type_arguments = 2;
  repeated string arguments = 3;
}

message ModuleBundlePayload {
  repeated MoveModuleBytecode modules = 1;
}

message MoveModuleBytecode {
  bytes bytecode = 1;
  MoveModule abi = 2;
}

message MoveModule {
  string address = 1;
  string name = 2;
  repeated MoveModuleId friends = 3;
  repeated MoveFunction exposed_functions = 4;
  repeated MoveStruct structs = 5;
}
message MoveFunction {
  enum Visibility {
    PRIVATE = 0;
    PUBLIC = 1;
    FRIEND = 2;
  }
  string name = 1;
  MoveFunction.Visibility visibility = 2;
  bool is_entry = 3;
  repeated MoveFunctionGenericTypeParam generic_type_params = 4;
  repeated MoveType params = 5;
  repeated MoveType return = 6;
}

message MoveStruct {
  string name = 1;
  bool is_native = 2;
  repeated MoveAbility abilities = 3;
  repeated MoveStructGenericTypeParam generic_type_params = 4;
  repeated MoveStructField fields = 5;
}

message MoveStructGenericTypeParam{
  repeated MoveAbility constraints = 1;
  bool is_phantom = 2;
}

message MoveStructField {
  string name = 1;
  MoveType type = 2;
}

message MoveFunctionGenericTypeParam {
  repeated MoveAbility constraints = 1;
}

enum MoveTypes {
  Bool = 0;
  U8 = 1;
  U64 = 2;
  U128 = 3;
  Address = 4;
  Signer = 5;
  Vector = 6; // { items: Box<MoveType> },
  Struct = 7; //(MoveStructTag),
  GenericTypeParam = 8; // { index: u16 },
  Reference = 9; // { mutable: bool, to: Box<MoveType> },
  Unparsable = 10; //(String),
}

message MoveType{

  message ReferenceType {
    bool mutable = 1;
    MoveType to = 2;
  }

  MoveTypes type = 1;
  oneof content {
    MoveType vector = 3;
    MoveStructTag struct = 4;
    uint32 generic_type_param_index = 5;
    ReferenceType reference = 6;
    string unparsable = 7;
  }
}

enum MoveAbility {
  COPY = 0;
  DROP = 1;
  STORE = 2;
  KEY = 3;
}

message WriteSetPayload {
  WriteSet write_set = 1;
}

message EntryFunctionId {
  MoveModuleId module = 1;
  string name = 2;
}

message MoveModuleId {
  string address = 1;
  string name = 2;
}

message MoveStructTag {
  string address = 1;
  string module = 2;
  string name = 3;
  repeated MoveType generic_type_params = 4;
}

message Signature {

  enum Type {
    ED25519 = 0;
    MULTI_ED25519 = 1;
    MULTI_AGENT = 2;
  }

  Type type = 1;
  oneof signature {
    Ed25519Signature ed25519 = 2;
    MultiEd25519Signature multi_ed25519 = 3;
    MultiAgentSignature multi_agent = 4;
  }
}

message Ed25519Signature {
  bytes public_key = 1;
  bytes signature = 2;
}

message MultiEd25519Signature {
  repeated bytes public_keys = 1;
  repeated bytes signatures = 2;
  uint32 threshold = 3;
  repeated uint32 public_key_indices = 4;
}

message MultiAgentSignature {
  AccountSignature sender = 1;
  repeated string secondary_signer_addresses = 2;
  repeated AccountSignature secondary_signers = 3;
}

message AccountSignature {
  enum Type {
    ED25519 = 0;
    MULTI_ED25519 = 1;
  }

  Type type = 1;
  oneof signature {
    Ed25519Signature ed25519 = 2;
    MultiEd25519Signature multi_ed25519 = 3;
  }
}
