/**
 * # Account.
 * This is a single account within the Hedera network. An Account is the
 * primary entity representing ownership of assets tracked on the ledger.
 * Account Allowances are also described here, and these represent permission
 * granted to an account to transfer assets owned by a different account which
 * granted the "allowance". Allowances specify the assets and amounts which may
 * be transferred.
 *
 * ### Keywords
 * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
 * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
 * document are to be interpreted as described in
 * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
 * [RFC8174](https://www.ietf.org/rfc/rfc8174).
 */
syntax = "proto3";

package proto;

// SPDX-License-Identifier: Apache-2.0
import "services_basic_types.proto";

option java_package = "com.hederahashgraph.api.proto.java";
// <<<pbj.java_package = "com.hedera.hapi.node.state.token">>> This comment is special code for setting PBJ Compiler java package
option java_multiple_files = true;

/**
 * A single Account in the Hedera distributed ledger.
 *
 * Each Account SHALL have a unique three-part identifier, a Key, and one
 * or more token balances.<br/>
 * Each Account SHALL have an alias, which has multiple forms, and MAY be set automatically.<br/>
 * Several additional items SHALL be associated with the Account to enable
 * full functionality.<br/>
 * Assets SHALL be represented as linked-lists with only the "head" item
 * referenced directly in the Account, and the remaining items SHALL be
 * accessible via the token relation or unique tokens maps.<br/>
 * Accounts, as most items in the network, SHALL have an expiration time,
 * recorded as seconds since the epoch, and MUST be "renewed" for a small fee
 * at expiration. This helps to reduce the amount of inactive accounts retained
 * in state.<br/>
 * Another account MAY be designated to pay any renewal fees and automatically
 * renew an account for (by default) 30-90 days at a time as a means to
 * optionally ensure important accounts remain active.<br/>
 * Accounts MAY participate in securing the network by "staking" the account
 * balances to a particular network node, and receive a portion of network
 * fees as a reward. An account MAY optionally decline these rewards but still
 * stake its balances.<br/>
 * An account MAY optionally require that inbound transfer transactions be
 * signed by that account as receiver
 * (in addition to the sender's signature).<br/>
 * As with all network entities, Account ID SHALL be represented as
 * shard.realm.X.<br/>
 * Alias and contractId SHALL be additional identifiers used to connect accounts
 * to transactions before the account is fully enabled,
 * or in EVM contracts.<br/>
 *
 * ---
 *
 * #### Alias
 * There is considerable complexity with `alias` (aka `evm_address`) for
 * Accounts. Much of this comes from the existence of a "hidden" alias for
 * almost all accounts, and the reuse of the alias field for both EVM reference
 * and "automatic" account creation.
 *
 * For the purposes of this specification, we will use the following terms for
 * clarity.
 *   - `key_alias` is the account public key as a protobuf serialized message
 *     and used for auto-creation and subsequent lookup. This is only valid if
 *     the account key is a
 *     single `primitive` key, either ED25519 or ECDSA_SECP256K1.
 *   - `evm_address` exists for every account and is one of
 *      - `contract_address`, which is the 20 byte EVM contract address per
 *        EIP-1014
 *      - `evm_key_address`, which is the keccak-256 hash of a ECDSA_SECP256K1
 *        `primitive` key.
 *         - This is for accounts lazy-created from EVM public keys, when the
 *           corresponding ECDSA_SECP256K1 public key is presented in a
 *           transaction signed by the private key for that public key, the
 *           account is created that key assigned, and the protobuf-serialized
 *           form is set as the account alias.
 *      - `long_zero`, is a synthetic 20 byte address inferred for "normally"
 *        created accounts. It is constructed from the "standard" AccountID as
 *        follows.
 *         - 4 byte big-endian shard number
 *         - 8 byte big-endian realm number
 *         - 8 byte big-endian entity number
 *
 * The `alias` field in the `Account` message SHALL contain one of four values
 * for any given account.
 *   - The `key_alias`, if the account was created by transferring HBAR to the
 *     account referenced by `key_alias`.
 *   - The `evm_key_address` if the account was created from an EVM public key
 *   - The `contract_address` if the account belongs to an EVM contract
 *   - Not-Set/null/Bytes.EMPTY (collectively `null`) if the account was
 *     created normally
 *
 * If the `alias` field of an `Account` is any form of `null`, then the account
 * MAY be referenced by `alias` in an `AccountID` by using the `long_zero`
 * address for the account. This "hidden default" alias SHALL NOT be stored,
 * but is synthesized by the node software as needed, and may be synthesized by
 * an EVM contract or client software as well.
 *
 * An AccountID in a transaction MAY reference an `Account` with
 * `shard`.`realm`.`alias`.<br/>
 * If the account `alias` field is set for an Account, that value SHALL be the
 * account alias.<br/>
 * If the account `alias` field is not set for an Account, the `long_zero`
 * alias SHALL be the account alias.
 */
message Account {
    /**
     * The unique ID of this account.
     * <p>
     * An account ID, when assigned to this field, SHALL be of
     * the form `shard.realm.number`.<br/>
     * Transactions MAY reference the account by alias, but the account itself
     * MUST always have a purely numeric identifier. This numeric ID is the
     * value used to reference the account in query responses, transaction
     * receipts, transaction records, and the block stream.
     */
    AccountID account_id = 1;

    /**
     * An account EVM alias.
     * <p>
     * This is a value used in some contexts to reference an account when the
     * numeric account identifier is not available.<br/>
     * This field, when set to a non-default value, is immutable and
     * SHALL NOT be changed.
     */
    bytes alias = 2;

    /**
     * The key to be used to sign transactions from this account, if any.
     * <p>
     * This key SHALL NOT be set for hollow accounts until the account
     * is finalized.<br/>
     * This key SHALL be set on all other accounts, except for certain
     * immutable accounts (0.0.800 and 0.0.801) necessary for network function
     * and otherwise secured by the governing council.
     */
    Key key = 3;

    /**
     * The current expiration time of this account, in seconds since the epoch.
     * <p>
     * For this purpose, `epoch` SHALL be the UNIX epoch
     * with 0 at `1970-01-01T00:00:00.000Z`.<br/>
     * This account SHALL be due standard renewal fees when the network
     * consensus time exceeds this time.<br/>
     * If rent and expiration are enabled for the network, and automatic
     * renewal is enabled for this account, renewal fees SHALL be charged
     * after this time, and, if charged, the expiration time SHALL be
     * extended for another renewal period.<br/>
     * This account MAY be expired and removed from state at any point
     * after this time if not renewed.<br/>
     * An account holder MAY extend this time by submitting an account
     * update transaction to modify expiration time, subject to the current
     * maximum expiration time for the network.
     */
    int64 expiration_second = 4;

    /**
     * The HBAR balance of this account, in tinybar (10<sup>-8</sup> HBAR).
     * <p>
     * This value is a signed integer for efficiency, but MUST always
     * be a whole number.
     */
    int64 tinybar_balance = 5;

    /**
     * A short description of this account.
     * <p>
     * This value, if set, MUST NOT exceed `transaction.maxMemoUtf8Bytes`
     * (default 100) bytes when encoded as UTF-8.
     */
    string memo = 6;

    /**
     * A boolean indicating that this account is deleted.
     */
    bool deleted = 7;

    /**
     * The amount of HBAR staked to this account by others.
     */
    int64 staked_to_me = 8;

    /**
     * If this account stakes to another account, this value SHALL be set to
     * the time when the current period for staking and reward
     * calculations began.
     */
    int64 stake_period_start = 9;

    // Below comment is NOT included in generated documentation
    /**
     * ID of the account or node to which this account is staking, if any.
     * <p>
     * if not set this field MAY be interpreted as staked_account_id
     * with value `0.0.0`.
     */
    oneof staked_id {
        /**
         * An identifier for the account to which this account is
         * staking its balances as a proxy.
         * <p>
         * If this account is not currently staking its balances, then this
         * field, if set, SHALL be the sentinel value of `0.0.0`.
         */
        AccountID staked_account_id = 10;

        /**
         * An identifier for the node this account is staked to.
         * <p>
         * If this account is not currently staking its balances, then this
         * field, if set, SHALL be the sentinel value of `-1`.
         * Wallet software SHOULD surface staking issues to users and provide a
         * simple mechanism to update staking to a new node ID in the event the
         * prior staked node ID ceases to be valid.
         * <p>
         * <blockquote>Note: node IDs do fluctuate as node operators change.
         * The Account owner MUST submit a new transaction to change this value
         * if the current node ID changes or ceases to operate as a node. An
         * account with an invalid `staked_node_id` SHALL NOT participate in
         * staking until the `staked_node_id` is updated to a valid node ID.
         * </blockquote>
         */
        int64 staked_node_id = 11;
    }

    /**
     * A boolean indicating that this account has chosen to decline rewards for
     * staking its balances.
     * <p>
     * This account MAY still stake its balances, but SHALL NOT receive reward
     * payments for doing so.
     */
    bool decline_reward = 12;

    /**
     * A boolean indicating that the account requires a receiver signature for
     * inbound token transfer transactions.
     * <p>
     * If this value is `true` then a transaction to transfer tokens to this
     * account SHALL NOT succeed unless this account has signed the transfer
     * transaction.
     */
    bool receiver_sig_required = 13;

    /**
     * A token ID at the head of the linked list for this account from the
     * token relations map.<br/>
     * The token relations are connected by including the "next" and "previous"
     * TokenID in each TokenRelation message. The "head" item in that list is
     * found by looking up the TokenRelation with this Account's account_id and
     * this head_token_id. Each subsequent item in the list is found via
     * similar lookup with both an AccountID and a TokenID.
     */
    TokenID head_token_id = 14;

    /**
     * A NftID at the head of the linked list for this account from
     * the unique tokens map.<br/>
     * The unique token relations are connected by including the "next" and
     * "previous" NftID in each Nft message. The "head" item in that list is
     * found by looking up the Nft with ID matching this head_nft_id. Each
     * subsequent item in the list is found via similar lookup with the next
     * or previous NftID.
     */
    NftID head_nft_id = 15;

    /**
     * A serial number in the NftID at the head of the linked list for this
     * account from unique tokens map.
     * <p>
     * This MUST match the `serial_number` field of `head_nft_id`.
     */
    int64 head_nft_serial_number = 16;

    /**
     * A number of non-fungible tokens (NTFs) owned by the account.
     */
    int64 number_owned_nfts = 17;

    /**
     * A maximum for the number of tokens that can be automatically
     * associated with this account.
     * <p>
     * If this is less than or equal to `used_auto_associations` (or 0), then
     * this account MUST manually associate with a token before transacting in
     * that token.<br/>
     * This value may also be `-1` to indicate no limit.<br/>
     * This value MUST NOT be less than `-1`.
     */
    int32 max_auto_associations = 18;

    /**
     * A count of used auto-association slots.
     * <p>
     * If this is greater than, or equal to, the current value of
     * `max_auto_associations`, then this account MUST manually associate with
     * a new token before transacting in that token.
     */
    int32 used_auto_associations = 19;

    /**
     * A count of tokens associated with this account.
     * <p>
     * This value determines a portion of the renewal fee for this account.
     */
    int32 number_associations = 20;

    /**
     * A boolean indicating that this account is owned by a smart contract.
     */
    bool smart_contract = 21;

    /**
     * A count of tokens with a positive balance associated with this account.
     * <p>
     * If the account has a positive balance in any token,
     * it SHALL NOT be deleted.
     */
    int32 number_positive_balances = 22;

    /**
     * A nonce of this account for Ethereum interoperability.
     */
    int64 ethereum_nonce = 23;

    /**
     * An amount of HBAR staked by this account at the start of
     * the last reward period.
     */
    int64 stake_at_start_of_last_rewarded_period = 24;

    /**
     * An account identifier for automatic renewal.<br/>
     * This is the identifier of another account, in the same shard and
     * realm as this account, that has signed a transaction allowing the
     * network to use its balance, if needed, to automatically extend this
     * account's expiration time during automatic renewal processing.
     * <p>
     * If this is set, and this account lack sufficient HBAR balance to pay
     * renewal fees when due, then the network SHALL deduct the necessary fees
     * from the designated auto renew account, if that account has sufficient
     * balance.
     */
    AccountID auto_renew_account_id = 25;

    /**
     * A count of the number of seconds to extend this account's expiration.
     * <p>
     * The network SHALL extend the account's expiration by this number of
     * seconds, if funds are available, upon automatic renewal.<br/>
     * This SHALL NOT apply if the account is already deleted
     * upon expiration.<br/>
     * If this is not provided in an allowed range on account creation, the
     * transaction SHALL fail with INVALID_AUTO_RENEWAL_PERIOD. The default
     * values for the minimum period and maximum period are currently 30 days
     * and 90 days, respectively.
     */
    int64 auto_renew_seconds = 26;

    /**
     * A count of smart contract key-value pairs.<br/>
     * If this account is a smart-contract, this is the number of key-value
     * pairs stored on the contract.
     * <p>
     * If this account is not a smart contract, this field
     * SHALL NOT be used.<br/>
     * This value SHALL determine a portion of the storage rental
     *fees for the contract.
     */
    int32 contract_kv_pairs_number = 27;

    /**
     * A list of crypto (HBAR) allowances approved by this account.
     * <p>
     * If this is not empty, each allowance SHALL permit a specified "spender"
     * account to spend this account's HBAR balance, up to a designated
     * limit.<br/>
     * This field SHALL permit spending only HBAR balance, not other tokens the
     * account may hold. Allowances for other tokens SHALL be listed in the
     * `token_allowances` field or the `approve_for_all_nft_allowances` field.
     */
    repeated AccountCryptoAllowance crypto_allowances = 28;

    /**
     * A list of non-fungible token (NFT) allowances approved by this account.
     * <p>
     * If this is not empty, each allowance permits a specified "spender"
     * account to transfer _all_ of this account's non-fungible tokens from a
     * particular collection.<br/>
     * Allowances for a specific serial number MUST be directly associated with
     * that specific non-fungible token, rather than the holding account.
     */
    repeated AccountApprovalForAllAllowance approve_for_all_nft_allowances = 29;

    /**
     * A list of fungible token allowances approved by this account.
     * <p>
     * If this is not empty, each allowance permits a specified "spender" to
     * spend this account's fungible tokens, of the designated type, up to a
     * designated limit.
     */
    repeated AccountFungibleTokenAllowance token_allowances = 30;

    /**
     * A count of tokens for which this account is the treasury account.
     * <p>
     * Each native token is initially created with all tokens held by its
     * treasury, and the owner of that account (which may be a smart contract)
     * determines how those tokens are distributed.
     */
    uint32 number_treasury_titles = 31;

    /**
     * A flag indicating that the account is expired and pending removal.
     * <p>
     * When the network checks for entity expiration, it SHALL set this flag if
     * the account expiration time has past and the account has no HBAR
     * sufficient to pay current renewal fees.<br/>
     * If the account has an auto-renew account set with an HBAR balance that
     * could pay for an auto-renewal, then this flag SHALL NOT be set. This
     * ensures the account is not encumbered during the time between expiration
     * and when the auto-renewal processing renews the account.
     */
    bool expired_and_pending_removal = 32;

    /**
     * A contract storage key.<br/>
     * This is the first key in the doubly-linked list of this
     * contract's storage mappings.
     * <p>
     * This value SHALL be empty if the account is not a contract or the
     * contract has no storage mappings.
     */
    bytes first_contract_storage_key = 33;

    /**
     * A pending airdrop ID.<br/>
     * This is the head of the linked list for this account from the
     * account airdrops map.<br/>
     * <p>
     * The account airdrops SHALL be connected by including the "next" and
     * "previous" `PendingAirdropID` in each `AccountAirdrop` message.<br/>
     * This value SHALL NOT be empty if this account is "sender" for any
     * pending airdrop, and SHALL be empty otherwise.
     */
    PendingAirdropId head_pending_airdrop_id = 34;

    /**
     * A number of pending airdrops.
     * <p>
     * This count SHALL be used to calculate rent _without_ walking the linked
     * list of pending airdrops associated to this account via the
     * `head_pending_airdrop_id` field.<br/>
     * This value MUST be updated for every airdrop, clam, or cancel transaction
     * that designates this account as a receiver.<br/>
     * This number MUST always match the count of entries in the "list"
     * identified by `head_pending_airdrop_id`.
     */
    uint64 number_pending_airdrops = 35;

    /**
     * The number of hooks currently in use on this account.
     */
    uint64 number_hooks_in_use = 36;

    /**
     * If the account has more than zero hooks in use, the id of the first hook in its
     * doubly-linked list of hooks.
     */
    int64 first_hook_id = 37;

    /**
     * The number of storage slots in use by this account's lambdas.
     */
    uint64 number_lambda_storage_slots = 38;
}

/**
 * Permission granted by one account (the "funding" account) to another account
 * (the "spender" account) that allows the spender to transfer all serial
 * numbers of a specific non-fungible token (NFT) collection owned by the
 * funding account.<br/>
 * This is a broad permission, as it does not matter how many NFTs of the
 * specified collection the funding account owns, the spender MAY dispose of
 * any or all of them with this allowance.<br/>
 * Each token type (typically a collection of NFTs) SHALL require a separate
 * allowance.<br/>
 * Allowances for a specific serial number MUST be directly associated with
 * that specific non-fungible token, rather than the holding account.
 *
 * An allowance SHALL NOT transfer any tokens directly, it only permits
 * transactions signed only by the spender account to transfer any non-fungible
 * tokens of the specified type owned by the funding account.
 */
message AccountApprovalForAllAllowance {
    /**
     * The identifier for the token associated with this allowance.
     * <p>
     * This token MUST be a non-fungible/unique token.
     */
    TokenID token_id = 1;

    /**
     * The identifier for the spending account associated with this allowance.
     * <p>
     * This account SHALL be permitted to sign transactions to spend tokens of
     * the associated token type from the funding/allowing account.
     */
    AccountID spender_id = 2;
}

/**
 * Permission granted by one account (the "funding" account) to another account
 * (the "spender" account) that allows the spender to spend a specified amount
 * of a specific non-HBAR fungible token from the balance owned by the funding
 * account.
 *
 * An allowance SHALL NOT transfer any tokens directly, it only permits
 * transactions signed only by the spender account to transfer tokens of the
 * specified type, up to the amount specified, from the funding account.
 *
 * Once the specified amount is spent, the allowance SHALL be consumed and a
 * new allowance SHALL be required before that spending account may spend
 * additional tokens from the funding account.
 */
message AccountFungibleTokenAllowance {
    /**
     * The identifier for the token associated with this allowance.
     * <p>
     * This token MUST be a fungible/common token.
     */
    TokenID token_id = 1;

    /**
     * The identifier for the spending account associated with this allowance.
     * <p>
     * This account SHALL be permitted to sign transactions to spend tokens of
     * the associated token type from the funding/allowing account.<br/>
     * This permission SHALL be limited to no more than the specified `amount`.
     */
    AccountID spender_id = 2;

    /*
     * The maximum amount that the spender account may transfer within the
     * scope of this allowance.
     * <p>
     * This allowance SHALL be consumed if any combination of transfers
     * authorized via this allowance meet this value in total.<br/>
     * This value MUST be specified in the smallest units of the relevant token
     * (i.e. 10<sup>-decimals</sup> whole tokens).
     */
    int64 amount = 3;
}

/**
 * Permission granted by one account (the "funding" account) to another account
 * (the "spender" account) that allows the spender to spend a specified amount
 * of HBAR owned by the funding account.
 *
 * An allowance SHALL NOT transfer any HBAR directly, it only permits
 * transactions signed only by the spender account to transfer HBAR, up to the
 * amount specified, from the funding account.
 *
 * Once the specified amount is spent, the allowance SHALL be consumed and a
 * new allowance SHALL be required before that spending account may spend
 * additional HBAR from the funding account.
 */
message AccountCryptoAllowance {
    /**
     * The identifier for the spending account associated with this allowance.
     * <p>
     * This account SHALL be permitted to sign transactions to spend HBAR from
     * the funding/allowing account.<br/>
     * This permission SHALL be limited to no more than the specified `amount`.
     */
    AccountID spender_id = 1;

    /*
     * The maximum amount that the spender account may transfer within the
     * scope of this allowance.
     * <p>
     * This allowance SHALL be consumed if any combination of transfers
     * authorized via this allowance meet this value in total.<br/>
     * This value MUST be specified in tinybar (i.e. 10<sup>-8</sup> HBAR).
     */
    int64 amount = 2;
}
