syntax = "proto3";
package provenance.ledger.v1;

option go_package          = "github.com/provenance-io/provenance/x/ledger/types";
option java_package        = "io.provenance.ledger.v1";
option java_multiple_files = true;

import "cosmos/msg/v1/msg.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "provenance/ledger/v1/ledger.proto";
import "provenance/ledger/v1/ledger_settlement.proto";

// Msg defines the ledger module Msg service.
service Msg {
  option (cosmos.msg.v1.service) = true;

  // CreateLedger creates a new NFT ledger.
  rpc CreateLedger(MsgCreateLedgerRequest) returns (MsgCreateLedgerResponse);

  // UpdateStatus updates the Status of a ledger.
  rpc UpdateStatus(MsgUpdateStatusRequest) returns (MsgUpdateStatusResponse);

  // UpdateInterestRate updates the interest rate of a ledger.
  rpc UpdateInterestRate(MsgUpdateInterestRateRequest) returns (MsgUpdateInterestRateResponse);

  // UpdatePayment updates the payment amount, next payment date, and payment frequency of a ledger.
  rpc UpdatePayment(MsgUpdatePaymentRequest) returns (MsgUpdatePaymentResponse);

  // UpdateMaturityDate updates the maturity date of a ledger.
  rpc UpdateMaturityDate(MsgUpdateMaturityDateRequest) returns (MsgUpdateMaturityDateResponse);

  // Append adds an entry to a ledger.
  rpc Append(MsgAppendRequest) returns (MsgAppendResponse);

  // UpdateBalances updates the balances for a ledger entry, allowing for retroactive adjustments to be applied.
  rpc UpdateBalances(MsgUpdateBalancesRequest) returns (MsgUpdateBalancesResponse);

  // TransferFundsWithSettlement processes multiple fund transfers with manual settlement instructions.
  rpc TransferFundsWithSettlement(MsgTransferFundsWithSettlementRequest)
      returns (MsgTransferFundsWithSettlementResponse);

  // Destroy deletes a ledger and its ledger entries.
  rpc Destroy(MsgDestroyRequest) returns (MsgDestroyResponse);

  // CreateLedgerClass creates a new ledger class.
  rpc CreateLedgerClass(MsgCreateLedgerClassRequest) returns (MsgCreateLedgerClassResponse);

  // AddLedgerClassStatusType adds a status type to a ledger class.
  rpc AddLedgerClassStatusType(MsgAddLedgerClassStatusTypeRequest) returns (MsgAddLedgerClassStatusTypeResponse);

  // AddLedgerClassEntryType adds an entry type to a ledger class.
  rpc AddLedgerClassEntryType(MsgAddLedgerClassEntryTypeRequest) returns (MsgAddLedgerClassEntryTypeResponse);

  // AddLedgerClassBucketType adds a bucket type to a ledger class.
  rpc AddLedgerClassBucketType(MsgAddLedgerClassBucketTypeRequest) returns (MsgAddLedgerClassBucketTypeResponse);

  // BulkCreate creates ledgers and entries in bulk.
  // Each ledger in this will cost one MsgCreateLedgerRequest.
  rpc BulkCreate(MsgBulkCreateRequest) returns (MsgBulkCreateResponse);
}

// MsgCreateLedgerRequest represents a request to create a new ledger.
message MsgCreateLedgerRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // The ledger to create.
  Ledger ledger = 1;
  // The signer address that can create ledgers.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgCreateLedgerResponse represents the response from creating a ledger.
message MsgCreateLedgerResponse {}

// MsgUpdateStatusRequest represents a request to update the status of a ledger.
message MsgUpdateStatusRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger key of the ledger whose status is being updated.
  LedgerKey key = 1;

  // The signer that is updating the status.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // The new status type id of the ledger.
  int32 status_type_id = 3;
}

// MsgUpdateStatusResponse represents the response from updating a ledger status.
message MsgUpdateStatusResponse {}

// MsgUpdateInterestRateRequest represents a request to update the interest rate configuration of a ledger.
message MsgUpdateInterestRateRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger key of the ledger whose interest rate is being updated.
  LedgerKey key = 1;

  // The signer that is updating the interest rate.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // The new interest rate of the ledger.
  // This field is NOT optional. If not provided (or provided as zero),
  // then the ledger's interest_rate field will be updated to be zero.
  int32 interest_rate = 3;

  // The new interest day count convention of the ledger.
  // This field is optional. If not provided (or set to unspecified),
  // the interest day count convention will not be updated.
  DayCountConvention interest_day_count_convention = 4;

  // The new interest accrual method of the ledger.
  // This field is optional. If not provided (or set to unspecified),
  // the interest accrual method will not be updated.
  InterestAccrualMethod interest_accrual_method = 5;
}

// MsgUpdateInterestRateResponse represents the response from updating a ledger interest rate.
message MsgUpdateInterestRateResponse {}

// MsgUpdatePaymentRequest represents a request to update payment configuration of a ledger.
message MsgUpdatePaymentRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger key of the ledger whose payment is being updated.
  LedgerKey key = 1;

  // The signer that is updating the payment.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // The new next payment amount of the ledger.
  // The units of this field are defined by the denom field in this ledger's class.
  // This field is NOT optional. If you don't provide a value (or provide it as zero),
  // then the ledger's next_pmt_amt field will be updated to be zero.
  string next_pmt_amt = 3 [
    (cosmos_proto.scalar)  = "cosmos.Int",
    (gogoproto.customtype) = "cosmossdk.io/math.Int",
    (gogoproto.nullable)   = false,
    (gogoproto.jsontag)    = "nextPmtAmt,omitempty"
  ];

  // The new next payment date in days since epoch.
  // This field is not optional and cannot be zero.
  int32 next_pmt_date = 4;

  // The new payment frequency of the ledger.
  // This field is optional. If set to unspecified, it will be ignored and the payment_frequency will not be changed.
  PaymentFrequency payment_frequency = 5;
}

// MsgUpdatePaymentResponse represents the response from updating a ledger payment configuration.
message MsgUpdatePaymentResponse {}

// MsgUpdateMaturityDateRequest represents a request to update the maturity date of a ledger.
message MsgUpdateMaturityDateRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger key of the ledger whose maturity date is being updated.
  LedgerKey key = 1;

  // The signer that is updating the maturity date.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // The new maturity date in days since epoch.
  int32 maturity_date = 3;
}

// MsgUpdateMaturityDateResponse represents the response from updating a ledger maturity date.
message MsgUpdateMaturityDateResponse {}

// MsgAppendRequest represents a request to append entries to a ledger.
message MsgAppendRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger key of the ledger whose entries are being appended.
  LedgerKey key = 1;

  // The entries to append to the ledger.
  repeated LedgerEntry entries = 2;

  // The signer that is appending the entries.
  string signer = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgAppendResponse represents the response from appending entries to a ledger.
message MsgAppendResponse {}

// MsgUpdateBalancesRequest represents a request to update balances for a ledger entry.
message MsgUpdateBalancesRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger key of the ledger whose balances are being updated.
  LedgerKey key = 1;

  // The signer that is updating the balances.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // The correlation id of the ledger entry.
  string correlation_id = 3;

  // The total amount of the ledger entry.
  // The units of this field are defined by the denom field in this ledger's class.
  string total_amt = 4 [
    (cosmos_proto.scalar)  = "cosmos.Int",
    (gogoproto.customtype) = "cosmossdk.io/math.Int",
    (gogoproto.nullable)   = false,
    (gogoproto.jsontag)    = "totalAmt,omitempty"
  ];

  // Applied amounts represent how the entry affects different buckets.
  repeated LedgerBucketAmount applied_amounts = 5;

  // Bucket balances represent the current state of funds in each bucket.
  repeated BucketBalance balance_amounts = 6;
}

// MsgUpdateBalancesResponse represents the response from updating ledger balances.
message MsgUpdateBalancesResponse {}

// MsgTransferFundsWithSettlementRequest represents a request to transfer funds with settlement instructions.
message MsgTransferFundsWithSettlementRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // The signer that is transferring the funds.
  string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // The transfers to be made.
  repeated FundTransferWithSettlement transfers = 2;
}

// MsgTransferFundsWithSettlementResponse represents the response from transferring funds with settlement.
message MsgTransferFundsWithSettlementResponse {}

// MsgDestroyRequest represents a request to destroy a ledger.
message MsgDestroyRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger key of the ledger to destroy.
  LedgerKey key = 1;

  // The signer that is destroying the ledger.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgDestroyResponse represents the response from destroying a ledger.
message MsgDestroyResponse {}

// MsgCreateLedgerClassRequest represents a request to create a new ledger class.
message MsgCreateLedgerClassRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // The ledger class to create.
  LedgerClass ledger_class = 1;

  // The signer that is creating the ledger class.
  string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgCreateLedgerClassResponse represents the response from creating a ledger class.
message MsgCreateLedgerClassResponse {}

// MsgAddLedgerClassStatusTypeRequest represents a request to add a status type to a ledger class.
message MsgAddLedgerClassStatusTypeRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger class id to add the status type to.
  string ledger_class_id = 1;

  // The status type to add to the ledger class.
  LedgerClassStatusType status_type = 2;

  // The signer that is adding the status type.
  string signer = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgAddLedgerClassStatusTypeResponse represents the response from adding a status type.
message MsgAddLedgerClassStatusTypeResponse {}

// MsgAddLedgerClassEntryTypeRequest represents a request to add an entry type to a ledger class.
message MsgAddLedgerClassEntryTypeRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger class id to add the entry type to.
  string ledger_class_id = 1;

  // The entry type to add to the ledger class.
  LedgerClassEntryType entry_type = 2;

  // The signer that is adding the entry type.
  string signer = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgAddLedgerClassEntryTypeResponse represents the response from adding an entry type.
message MsgAddLedgerClassEntryTypeResponse {}

// MsgAddLedgerClassBucketTypeRequest represents a request to add a bucket type to a ledger class.
message MsgAddLedgerClassBucketTypeRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // Ledger class id to add the bucket type to.
  string ledger_class_id = 1;

  // The bucket type to add to the ledger class.
  LedgerClassBucketType bucket_type = 2;

  // The signer that is adding the bucket type.
  string signer = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgAddLedgerClassBucketTypeResponse represents the response from adding a bucket type.
message MsgAddLedgerClassBucketTypeResponse {}

// MsgBulkCreateRequest represents a request to bulk create ledgers and entries.
message MsgBulkCreateRequest {
  option (cosmos.msg.v1.signer) = "signer";

  // The signer that is bulk importing the ledger data.
  string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

  // The genesis state to bulk import.
  repeated LedgerAndEntries ledger_and_entries = 2;
}

// MsgBulkCreateResponse represents the response from bulk creating ledgers and entries.
message MsgBulkCreateResponse {}
