syntax = "proto3";

package sf.substreams.v1;

option go_package = "github.com/streamingfast/substreams/pb/sf/substreams/v1;pbsubstreams";

message Modules {
  repeated Module modules = 1;
  repeated Binary binaries = 2;
}

// Binary represents some code compiled to its binary form.
message Binary {
  string type = 1;
  bytes content = 2;
}

message Module {
  string name = 1;
  oneof kind {
    KindMap kind_map = 2;
    KindStore kind_store = 3;
  };

  uint32 binary_index = 4;
  string binary_entrypoint = 5;

  repeated Input inputs = 6;
  Output output = 7;

  uint64 initial_block = 8;

  message KindMap {
    string output_type = 1;
  }

  message KindStore {
    // The `update_policy` determines the functions available to mutate the store
    // (like `set()`, `set_if_not_exists()` or `sum()`, etc..) in
    // order to ensure that parallel operations are possible and deterministic
    //
    // Say a store cumulates keys from block 0 to 1M, and a second store
    // cumulates keys from block 1M to 2M. When we want to use this
    // store as a dependency for a downstream module, we will merge the
    // two stores according to this policy.
    UpdatePolicy update_policy = 1;
    string value_type = 2;

    enum UpdatePolicy {
      UPDATE_POLICY_UNSET = 0;
      // Provides a store where you can `set()` keys, and the latest key wins
      UPDATE_POLICY_SET = 1;
      // Provides a store where you can `set_if_not_exists()` keys, and the first key wins
      UPDATE_POLICY_SET_IF_NOT_EXISTS = 2;
      // Provides a store where you can `add_*()` keys, where two stores merge by summing its values.
      UPDATE_POLICY_ADD = 3;
      // Provides a store where you can `min_*()` keys, where two stores merge by leaving the minimum value.
      UPDATE_POLICY_MIN = 4;
      // Provides a store where you can `max_*()` keys, where two stores merge by leaving the maximum value.
      UPDATE_POLICY_MAX = 5;
      // Provides a store where you can `append()` keys, where two stores merge by concatenating the bytes in order.
      UPDATE_POLICY_APPEND = 6;
    }
  }

  message Input {
    oneof input {
      Source source = 1;
      Map map = 2;
      Store store = 3;
    }

    message Source {
      string type = 1; // ex: "sf.ethereum.type.v1.Block"
    }
    message Map {
      string module_name = 1; // ex: "block_to_pairs"
    }
    message Store {
      string module_name = 1;
      Mode mode = 2;

      enum Mode {
	UNSET = 0;
	GET = 1;
	DELTAS = 2;
      }
    }
  }

  message Output {
    string type = 1;
  }
}
