// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

syntax = "proto3";

package sui.rpc.v2;

import "google/protobuf/field_mask.proto";
import "sui/rpc/v2/bcs.proto";
import "sui/rpc/v2/object.proto";

service StateService {
  rpc ListDynamicFields(ListDynamicFieldsRequest) returns (ListDynamicFieldsResponse);
  rpc ListOwnedObjects(ListOwnedObjectsRequest) returns (ListOwnedObjectsResponse);
  rpc GetCoinInfo(GetCoinInfoRequest) returns (GetCoinInfoResponse);
  rpc GetBalance(GetBalanceRequest) returns (GetBalanceResponse);
  rpc ListBalances(ListBalancesRequest) returns (ListBalancesResponse);
}

// Request message for `NodeService.GetCoinInfo`.
message GetCoinInfoRequest {
  // The coin type to request information about
  optional string coin_type = 1;
}

// Response message for `NodeService.GetCoinInfo`.
message GetCoinInfoResponse {
  // Required. The coin type.
  optional string coin_type = 1;

  // This field will be populated with information about this coin
  // type's `0x2::coin::CoinMetadata` if it exists and has not been wrapped.
  optional CoinMetadata metadata = 2;

  // This field will be populated with information about this coin
  // type's `0x2::coin::TreasuryCap` if it exists and has not been wrapped.
  optional CoinTreasury treasury = 3;

  // If this coin type is a regulated coin, this field will be
  // populated with information either from its Currency object
  // in the CoinRegistry, or from its `0x2::coin::RegulatedCoinMetadata`
  // object for coins that have not been migrated to the CoinRegistry
  //
  // If this coin is not known to be regulated, only the
  // coin_regulated_state field will be populated.
  optional RegulatedCoinMetadata regulated_metadata = 4;
}

// Metadata for a coin type
message CoinMetadata {
  // Information about the state of the coin's MetadataCap
  enum MetadataCapState {
    // Indicates the state of the MetadataCap is unknown.
    // Set when the coin has not been migrated to the CoinRegistry.
    METADATA_CAP_STATE_UNKNOWN = 0;
    // Indicates the MetadataCap has been claimed.
    CLAIMED = 1;
    // Indicates the MetadataCap has not been claimed.
    UNCLAIMED = 2;
    // Indicates the MetadataCap has been deleted.
    DELETED = 3;
  }

  // ObjectId of the `0x2::coin::CoinMetadata` object or
  // 0x2::sui::coin_registry::Currency object (when registered with CoinRegistry).
  optional string id = 1;
  // Number of decimal places to coin uses.
  optional uint32 decimals = 2;
  // Name for the token
  optional string name = 3;
  // Symbol for the token
  optional string symbol = 4;
  // Description of the token
  optional string description = 5;
  // URL for the token logo
  optional string icon_url = 6;
  // The MetadataCap ID if it has been claimed for this coin type.
  // This capability allows updating the coin's metadata fields.
  // Only populated when metadata is from CoinRegistry.
  optional string metadata_cap_id = 7;
  // State of the MetadataCap for this coin type.
  optional MetadataCapState metadata_cap_state = 8;
}

// Information about a coin type's `0x2::coin::TreasuryCap` and its total available supply
message CoinTreasury {
  // Supply state of a coin, matching the Move SupplyState enum
  enum SupplyState {
    // Supply is unknown or TreasuryCap still exists (minting still possible)
    SUPPLY_STATE_UNKNOWN = 0;
    // Supply is fixed (TreasuryCap consumed, no more minting possible)
    FIXED = 1;
    // Supply can only decrease (burning allowed, minting not allowed)
    BURN_ONLY = 2;
  }
  // ObjectId of the `0x2::coin::TreasuryCap` object.
  optional string id = 1;
  // Total available supply for this coin type.
  optional uint64 total_supply = 2;
  // Supply state indicating if the supply is fixed or can still be minted
  optional SupplyState supply_state = 3;
}

// Information about a regulated coin, which indicates that it makes use of the transfer deny list.
message RegulatedCoinMetadata {
  // Indicates the state of the regulation of the coin.
  enum CoinRegulatedState {
    // Indicates the regulation state of the coin is unknown.
    // This is set when a coin has not been migrated to the
    // coin registry and has no `0x2::coin::RegulatedCoinMetadata`
    // object.
    COIN_REGULATED_STATE_UNKNOWN = 0;
    // Indicates a coin is regulated. RegulatedCoinMetadata will be populated.
    REGULATED = 1;
    // Indicates a coin is unregulated.
    UNREGULATED = 2;
  }

  // ObjectId of the `0x2::coin::RegulatedCoinMetadata` object.
  // Only present for coins that have not been migrated to CoinRegistry.
  optional string id = 1;
  // The ID of the coin's `CoinMetadata` or `CoinData` object.
  optional string coin_metadata_object = 2;
  // The ID of the coin's `DenyCap` object.
  optional string deny_cap_object = 3;
  // Whether the coin can be globally paused
  optional bool allow_global_pause = 4;
  // Variant of the regulated coin metadata
  optional uint32 variant = 5;
  // Indicates the coin's regulated state.
  optional CoinRegulatedState coin_regulated_state = 6;
}

// Request message for `LiveDataService.GetBalance`.
message GetBalanceRequest {
  // Required. The owner's Sui address.
  optional string owner = 1;

  // Required. The type names for the coin (e.g., 0x2::sui::SUI).
  optional string coin_type = 2;
}

// Response message for `LiveDataService.GetBalance`.
// Return the total coin balance for one coin type, owned by the address owner.
message GetBalanceResponse {
  // The balance information for the requested coin type.
  optional Balance balance = 1;
}

// Request message for `LiveDataService.ListBalances`.
message ListBalancesRequest {
  // Required. The owner's Sui address.
  optional string owner = 1;

  // The maximum number of balance entries to return. The service may return fewer than this value.
  // If unspecified, at most `50` entries will be returned.
  // The maximum value is `1000`; values above `1000` will be coerced to `1000`.
  optional uint32 page_size = 2;

  // A page token, received from a previous `ListBalances` call.
  // Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to `ListBalances` must
  // match the call that provided the page token.
  optional bytes page_token = 3;
}

// Response message for `LiveDataService.ListBalances`.
// Return the total coin balance for all coin types, owned by the address owner.
message ListBalancesResponse {
  // The list of coin types and their respective balances.
  repeated Balance balances = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  optional bytes next_page_token = 2;
}

// Balance information for a specific coin type.
message Balance {
  // The type of the coin (e.g., 0x2::sui::SUI).
  optional string coin_type = 1;

  // The total balance of `coin_type` in its smallest unit.
  // This is the sum of all spendable amounts of `coin_type` (`address_balance`
  // and `coin_balance`).
  optional uint64 balance = 3;

  // The balance of `Balance<T>` in this address's Address Balance.
  optional uint64 address_balance = 4;

  // The balance of all `Coin<T>` objects owned by this address.
  optional uint64 coin_balance = 5;
}

// Request message for `NodeService.ListDynamicFields`
message ListDynamicFieldsRequest {
  // Required. The `UID` of the parent, which owns the collections of dynamic fields.
  optional string parent = 1;

  // The maximum number of dynamic fields to return. The service may return fewer than this value.
  // If unspecified, at most `50` entries will be returned.
  // The maximum value is `1000`; values above `1000` will be coerced to `1000`.
  optional uint32 page_size = 2;

  // A page token, received from a previous `ListDynamicFields` call.
  // Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to `ListDynamicFields` must
  // match the call that provided the page token.
  optional bytes page_token = 3;

  // Mask specifying which fields to read.
  // If no mask is specified, defaults to `parent,field_id`.
  optional google.protobuf.FieldMask read_mask = 4;
}

// Response message for `NodeService.ListDynamicFields`
message ListDynamicFieldsResponse {
  // Page of dynamic fields owned by the specified parent.
  repeated DynamicField dynamic_fields = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  optional bytes next_page_token = 2;
}

message DynamicField {
  enum DynamicFieldKind {
    DYNAMIC_FIELD_KIND_UNKNOWN = 0;
    FIELD = 1;
    OBJECT = 2;
  }

  optional DynamicFieldKind kind = 1;

  // ObjectId of this dynamic field's parent.
  optional string parent = 2;

  // ObjectId of this dynamic field.
  optional string field_id = 3;

  // The field object itself
  optional Object field_object = 4;

  // The dynamic field's "name"
  optional Bcs name = 5;

  // The dynamic field's "value"
  optional Bcs value = 6;

  // The type of the dynamic field "value".
  //
  // If this is a dynamic object field then this is the type of the object
  // itself (which is a child of this field), otherwise this is the type of the
  // value of this field.
  optional string value_type = 7;

  // The ObjectId of the child object when a child is a dynamic
  // object field.
  //
  // The presence or absence of this field can be used to determine if a child
  // is a dynamic field or a dynamic child object
  optional string child_id = 8;

  // The object itself when a child is a dynamic object field.
  optional Object child_object = 9;
}

message ListOwnedObjectsRequest {
  // Required. The address of the account that owns the objects.
  optional string owner = 1;

  // The maximum number of entries return. The service may return fewer than this value.
  // If unspecified, at most `50` entries will be returned.
  // The maximum value is `1000`; values above `1000` will be coerced to `1000`.
  optional uint32 page_size = 2;

  // A page token, received from a previous `ListOwnedObjects` call.
  // Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to `ListOwnedObjects` must
  // match the call that provided the page token.
  optional bytes page_token = 3;

  // Mask specifying which fields to read.
  // If no mask is specified, defaults to `object_id,version,object_type`.
  optional google.protobuf.FieldMask read_mask = 4;

  // Optional type filter to limit the types of objects listed.
  //
  // Providing an object type with no type params will return objects of that
  // type with any type parameter, e.g. `0x2::coin::Coin` will return all
  // `Coin<T>` objects regardless of the type parameter `T`. Providing a type
  // with a type param will restrict the returned objects to only those objects
  // that match the provided type parameters, e.g.
  // `0x2::coin::Coin<0x2::sui::SUI>` will only return `Coin<SUI>` objects.
  optional string object_type = 5;
}

message ListOwnedObjectsResponse {
  // Page of dynamic fields owned by the specified parent.
  repeated Object objects = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  optional bytes next_page_token = 2;
}
