syntax = "proto3";
package accounting;
option go_package = "github.com/nspcc-dev/neofs-proto/accounting";

import "decimal/decimal.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";

option (gogoproto.stable_marshaler_all) = true;

message Account {
    // OwnerID is a wallet address
    bytes OwnerID                 = 1 [(gogoproto.customtype) = "OwnerID",  (gogoproto.nullable) = false];
    // Address is identifier of accounting record
    string Address                = 2;
    // ParentAddress is identifier of parent accounting record
    string ParentAddress          = 3;
    // ActiveFunds is amount of active (non locked) funds for account
    decimal.Decimal ActiveFunds   = 4;
    // Lifetime is time until account is valid (used for lock accounts)
    Lifetime Lifetime             = 5 [(gogoproto.nullable) = false];
    // LockTarget is the purpose of lock funds (it might be withdraw or payment for storage)
    LockTarget LockTarget         = 6;
    // LockAccounts contains child accounts with locked funds
    repeated Account LockAccounts = 7;
}

// LockTarget must be one of two options
message LockTarget {
    oneof Target {
        // WithdrawTarget used when user requested withdraw
        WithdrawTarget WithdrawTarget = 1;
        // ContainerCreateTarget used when user requested creation of container
        ContainerCreateTarget ContainerCreateTarget = 2;
    }
}

message Balances {
    // Accounts contains multiple account snapshots
    repeated Account Accounts = 1 [(gogoproto.nullable) = false];
}

message PayIO {
    // BlockID contains id of the NEO block where withdraw or deposit
    // call was invoked
    uint64 BlockID = 1;
    // Transactions contains all transactions that founded in block
    // and used for PayIO
    repeated Tx Transactions = 2 [(gogoproto.nullable) = false];
}

message Lifetime {
    // Unit can be Unlimited, based on NeoFS epoch or Neo block
    enum Unit {
        Unlimited = 0;
        NeoFSEpoch = 1;
        NeoBlock = 2;
    }

    // Unit describes how lifetime is measured in account
    Unit unit = 1 [(gogoproto.customname) = "Unit"];
    // Value describes how long lifetime will be valid
    int64 Value = 2;
}

message Tx {
    // Type can be withdrawal, payIO or inner
    enum Type {
        Unknown  = 0;
        Withdraw = 1;
        PayIO    = 2;
        Inner    = 3;
    }

    // Type describes target of transaction
    Type type              = 1 [(gogoproto.customname) = "Type"];
    // From describes sender of funds
    string From            = 2;
    // To describes receiver of funds
    string To              = 3;
    // Amount describes amount of funds
    decimal.Decimal Amount = 4;
    // PublicKeys contains public key of sender
    bytes PublicKeys       = 5;
}

message Settlement {
    message Receiver {
        // To is the address of funds recipient 
        string To              = 1;
        // Amount is the amount of funds that will be sent
        decimal.Decimal Amount = 2;
    }

    message Container {
        // CID is container identifier
        bytes CID            = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
        // SGIDs is a set of storage groups that successfully passed the audit
        repeated bytes SGIDs = 2 [(gogoproto.customtype) = "SGID", (gogoproto.nullable) = false];
    }

    message Tx {
        // From is the address of the sender of funds
        string From                 = 1;
        // Container that successfully had passed the audit
        Container Container         = 2 [(gogoproto.nullable) = false];
        // Receivers is a set of addresses of funds recipients
        repeated Receiver Receivers = 3 [(gogoproto.nullable) = false];
    }

    // Epoch contains an epoch when settlement was accepted
    uint64 Epoch             = 1;
    // Transactions is a set of transactions
    repeated Tx Transactions = 2;
}

message ContainerCreateTarget {
    // CID is container identifier
    bytes CID = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
}

message WithdrawTarget {
    // Cheque is a string representation of cheque id
    string Cheque = 1;
}