//------------------------------------------------------------------------------
/*
    This file is part of rippled: https://github.com/ripple/rippled
    Copyright (c) 2024 Ripple Labs Inc.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose  with  or without fee is hereby granted, provided that the above
    copyright notice and this permission notice appear in all copies.

    THE  SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    WITH  REGARD  TO  THIS  SOFTWARE  INCLUDING  ALL  IMPLIED  WARRANTIES  OF
    MERCHANTABILITY  AND  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    ANY  SPECIAL ,  DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    WHATSOEVER  RESULTING  FROM  LOSS  OF USE, DATA OR PROFITS, WHETHER IN AN
    ACTION  OF  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#if !defined(LEDGER_ENTRY)
#error "undefined macro: LEDGER_ENTRY"
#endif

#ifndef LEDGER_ENTRY_DUPLICATE
// The EXPAND macro is needed for Windows
// https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
#define EXPAND(x) x

// The `LEDGER_ENTRY_DUPLICATE macro is needed to avoid JSS conflicts
// Since some transactions and ledger entries have the same name (like `DepositPreauth`)
// The compiler won't accept two instances of `JSS(DepositPreauth)`
#define LEDGER_ENTRY_DUPLICATE(...) EXPAND(LEDGER_ENTRY(__VA_ARGS__))
#endif

/**
 * These objects are listed in order of increasing ledger type ID.
 * There are many gaps between these IDs.
 * You are welcome to fill them with new object types.
 */

/** A ledger object which identifies an offer to buy or sell an NFT.

    \sa keylet::nftoffer
 */
LEDGER_ENTRY(ltNFTOKEN_OFFER, 0x0037, NFTokenOffer, nft_offer, ({
    {sfOwner,                soeREQUIRED},
    {sfNFTokenID,            soeREQUIRED},
    {sfAmount,               soeREQUIRED},
    {sfOwnerNode,            soeREQUIRED},
    {sfNFTokenOfferNode,     soeREQUIRED},
    {sfDestination,          soeOPTIONAL},
    {sfExpiration,           soeOPTIONAL},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** A ledger object which describes a check.

    \sa keylet::check
 */
LEDGER_ENTRY(ltCHECK, 0x0043, Check, check, ({
    {sfAccount,              soeREQUIRED},
    {sfDestination,          soeREQUIRED},
    {sfSendMax,              soeREQUIRED},
    {sfSequence,             soeREQUIRED},
    {sfOwnerNode,            soeREQUIRED},
    {sfDestinationNode,      soeREQUIRED},
    {sfExpiration,           soeOPTIONAL},
    {sfInvoiceID,            soeOPTIONAL},
    {sfSourceTag,            soeOPTIONAL},
    {sfDestinationTag,       soeOPTIONAL},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** The ledger object which tracks the DID.

   \sa keylet::did
*/
LEDGER_ENTRY(ltDID, 0x0049, DID, did, ({
    {sfAccount,              soeREQUIRED},
    {sfDIDDocument,          soeOPTIONAL},
    {sfURI,                  soeOPTIONAL},
    {sfData,                 soeOPTIONAL},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** The ledger object which tracks the current negative UNL state.

    \note This is a singleton: only one such object exists in the ledger.

    \sa keylet::negativeUNL
 */
LEDGER_ENTRY(ltNEGATIVE_UNL, 0x004e, NegativeUNL, nunl, ({
    {sfDisabledValidators,   soeOPTIONAL},
    {sfValidatorToDisable,   soeOPTIONAL},
    {sfValidatorToReEnable,  soeOPTIONAL},
    {sfPreviousTxnID,        soeOPTIONAL},
    {sfPreviousTxnLgrSeq,    soeOPTIONAL},
}))

/** A ledger object which contains a list of NFTs

    \sa keylet::nftpage_min, keylet::nftpage_max, keylet::nftpage
 */
LEDGER_ENTRY(ltNFTOKEN_PAGE, 0x0050, NFTokenPage, nft_page, ({
    {sfPreviousPageMin,      soeOPTIONAL},
    {sfNextPageMin,          soeOPTIONAL},
    {sfNFTokens,             soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** A ledger object which contains a signer list for an account.

    \sa keylet::signers
 */
// All fields are soeREQUIRED because there is always a SignerEntries.
// If there are no SignerEntries the node is deleted.
LEDGER_ENTRY(ltSIGNER_LIST, 0x0053, SignerList, signer_list, ({
    {sfOwner,                soeOPTIONAL},
    {sfOwnerNode,            soeREQUIRED},
    {sfSignerQuorum,         soeREQUIRED},
    {sfSignerEntries,        soeREQUIRED},
    {sfSignerListID,         soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** A ledger object which describes a ticket.

    \sa keylet::ticket
 */
LEDGER_ENTRY(ltTICKET, 0x0054, Ticket, ticket, ({
    {sfAccount,              soeREQUIRED},
    {sfOwnerNode,            soeREQUIRED},
    {sfTicketSequence,       soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** A ledger object which describes an account.

    \sa keylet::account
 */
LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({
    {sfAccount,              soeREQUIRED},
    {sfSequence,             soeREQUIRED},
    {sfBalance,              soeREQUIRED},
    {sfOwnerCount,           soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
    {sfAccountTxnID,         soeOPTIONAL},
    {sfRegularKey,           soeOPTIONAL},
    {sfEmailHash,            soeOPTIONAL},
    {sfWalletLocator,        soeOPTIONAL},
    {sfWalletSize,           soeOPTIONAL},
    {sfMessageKey,           soeOPTIONAL},
    {sfTransferRate,         soeOPTIONAL},
    {sfDomain,               soeOPTIONAL},
    {sfTickSize,             soeOPTIONAL},
    {sfTicketCount,          soeOPTIONAL},
    {sfNFTokenMinter,        soeOPTIONAL},
    {sfMintedNFTokens,       soeDEFAULT},
    {sfBurnedNFTokens,       soeDEFAULT},
    {sfFirstNFTokenSequence, soeOPTIONAL},
    {sfAMMID,                soeOPTIONAL}, // pseudo-account designator
    {sfVaultID,              soeOPTIONAL}, // pseudo-account designator
}))

/** A ledger object which contains a list of object identifiers.

    \sa keylet::page, keylet::quality, keylet::book, keylet::next and
        keylet::ownerDir
 */
LEDGER_ENTRY(ltDIR_NODE, 0x0064, DirectoryNode, directory, ({
    {sfOwner,                soeOPTIONAL},  // for owner directories
    {sfTakerPaysCurrency,    soeOPTIONAL},  // order book directories
    {sfTakerPaysIssuer,      soeOPTIONAL},  // order book directories
    {sfTakerGetsCurrency,    soeOPTIONAL},  // order book directories
    {sfTakerGetsIssuer,      soeOPTIONAL},  // order book directories
    {sfExchangeRate,         soeOPTIONAL},  // order book directories
    {sfIndexes,              soeREQUIRED},
    {sfRootIndex,            soeREQUIRED},
    {sfIndexNext,            soeOPTIONAL},
    {sfIndexPrevious,        soeOPTIONAL},
    {sfNFTokenID,            soeOPTIONAL},
    {sfPreviousTxnID,        soeOPTIONAL},
    {sfPreviousTxnLgrSeq,    soeOPTIONAL},
    {sfDomainID,             soeOPTIONAL}   // order book directories
}))

/** The ledger object which lists details about amendments on the network.

    \note This is a singleton: only one such object exists in the ledger.

    \sa keylet::amendments
 */
LEDGER_ENTRY(ltAMENDMENTS, 0x0066, Amendments, amendments, ({
    {sfAmendments,           soeOPTIONAL},  // Enabled
    {sfMajorities,           soeOPTIONAL},
    {sfPreviousTxnID,        soeOPTIONAL},
    {sfPreviousTxnLgrSeq,    soeOPTIONAL},
}))

/** A ledger object that contains a list of ledger hashes.

    This type is used to store the ledger hashes which the protocol uses
    to implement skip lists that allow for efficient backwards (and, in
    theory, forward) forward iteration across large ledger ranges.

    \sa keylet::skip
 */
LEDGER_ENTRY(ltLEDGER_HASHES, 0x0068, LedgerHashes, hashes, ({
    {sfFirstLedgerSequence,  soeOPTIONAL},
    {sfLastLedgerSequence,   soeOPTIONAL},
    {sfHashes,               soeREQUIRED},
}))

/** The ledger object which lists details about sidechains.

    \sa keylet::bridge
*/
LEDGER_ENTRY(ltBRIDGE, 0x0069, Bridge, bridge, ({
    {sfAccount,                  soeREQUIRED},
    {sfSignatureReward,          soeREQUIRED},
    {sfMinAccountCreateAmount,   soeOPTIONAL},
    {sfXChainBridge,             soeREQUIRED},
    {sfXChainClaimID,            soeREQUIRED},
    {sfXChainAccountCreateCount, soeREQUIRED},
    {sfXChainAccountClaimCount,  soeREQUIRED},
    {sfOwnerNode,                soeREQUIRED},
    {sfPreviousTxnID,            soeREQUIRED},
    {sfPreviousTxnLgrSeq,        soeREQUIRED},
}))

/** A ledger object which describes an offer on the DEX.

    \sa keylet::offer
 */
LEDGER_ENTRY(ltOFFER, 0x006f, Offer, offer, ({
    {sfAccount,              soeREQUIRED},
    {sfSequence,             soeREQUIRED},
    {sfTakerPays,            soeREQUIRED},
    {sfTakerGets,            soeREQUIRED},
    {sfBookDirectory,        soeREQUIRED},
    {sfBookNode,             soeREQUIRED},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
    {sfExpiration,           soeOPTIONAL},
    {sfDomainID,             soeOPTIONAL},
    {sfAdditionalBooks,      soeOPTIONAL},
}))

/** A ledger object which describes a deposit preauthorization.

    \sa keylet::depositPreauth
 */
LEDGER_ENTRY_DUPLICATE(ltDEPOSIT_PREAUTH, 0x0070, DepositPreauth, deposit_preauth, ({
    {sfAccount,              soeREQUIRED},
    {sfAuthorize,            soeOPTIONAL},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
    {sfAuthorizeCredentials, soeOPTIONAL},
}))

/** A claim id for a cross chain transaction.

    \sa keylet::xChainClaimID
*/
LEDGER_ENTRY(ltXCHAIN_OWNED_CLAIM_ID, 0x0071, XChainOwnedClaimID, xchain_owned_claim_id, ({
    {sfAccount,                 soeREQUIRED},
    {sfXChainBridge,            soeREQUIRED},
    {sfXChainClaimID,           soeREQUIRED},
    {sfOtherChainSource,        soeREQUIRED},
    {sfXChainClaimAttestations, soeREQUIRED},
    {sfSignatureReward,         soeREQUIRED},
    {sfOwnerNode,               soeREQUIRED},
    {sfPreviousTxnID,           soeREQUIRED},
    {sfPreviousTxnLgrSeq,       soeREQUIRED},
}))

/** A ledger object which describes a bidirectional trust line.

    @note Per Vinnie Falco this should be renamed to ltTRUST_LINE

    \sa keylet::line
 */
LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, ({
    {sfBalance,              soeREQUIRED},
    {sfLowLimit,             soeREQUIRED},
    {sfHighLimit,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
    {sfLowNode,              soeOPTIONAL},
    {sfLowQualityIn,         soeOPTIONAL},
    {sfLowQualityOut,        soeOPTIONAL},
    {sfHighNode,             soeOPTIONAL},
    {sfHighQualityIn,        soeOPTIONAL},
    {sfHighQualityOut,       soeOPTIONAL},
}))

/** The ledger object which lists the network's fee settings.

    \note This is a singleton: only one such object exists in the ledger.

    \sa keylet::fees
 */
LEDGER_ENTRY(ltFEE_SETTINGS, 0x0073, FeeSettings, fee, ({
    // Old version uses raw numbers
    {sfBaseFee,                soeOPTIONAL},
    {sfReferenceFeeUnits,      soeOPTIONAL},
    {sfReserveBase,            soeOPTIONAL},
    {sfReserveIncrement,       soeOPTIONAL},
    // New version uses Amounts
    {sfBaseFeeDrops,           soeOPTIONAL},
    {sfReserveBaseDrops,       soeOPTIONAL},
    {sfReserveIncrementDrops,  soeOPTIONAL},
    {sfPreviousTxnID,          soeOPTIONAL},
    {sfPreviousTxnLgrSeq,      soeOPTIONAL},
}))

/** A claim id for a cross chain create account transaction.

    \sa keylet::xChainCreateAccountClaimID
*/
LEDGER_ENTRY(ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID, 0x0074, XChainOwnedCreateAccountClaimID, xchain_owned_create_account_claim_id, ({
    {sfAccount,                         soeREQUIRED},
    {sfXChainBridge,                    soeREQUIRED},
    {sfXChainAccountCreateCount,        soeREQUIRED},
    {sfXChainCreateAccountAttestations, soeREQUIRED},
    {sfOwnerNode,                       soeREQUIRED},
    {sfPreviousTxnID,                   soeREQUIRED},
    {sfPreviousTxnLgrSeq,               soeREQUIRED},
}))

/** A ledger object describing a single escrow.

    \sa keylet::escrow
 */
LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, ({
    {sfAccount,              soeREQUIRED},
    {sfSequence,             soeOPTIONAL},
    {sfDestination,          soeREQUIRED},
    {sfAmount,               soeREQUIRED},
    {sfCondition,            soeOPTIONAL},
    {sfCancelAfter,          soeOPTIONAL},
    {sfFinishAfter,          soeOPTIONAL},
    {sfSourceTag,            soeOPTIONAL},
    {sfDestinationTag,       soeOPTIONAL},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
    {sfDestinationNode,      soeOPTIONAL},
    {sfTransferRate,         soeOPTIONAL},
    {sfIssuerNode,           soeOPTIONAL},
}))

/** A ledger object describing a single unidirectional XRP payment channel.

    \sa keylet::payChan
 */
LEDGER_ENTRY(ltPAYCHAN, 0x0078, PayChannel, payment_channel, ({
    {sfAccount,              soeREQUIRED},
    {sfDestination,          soeREQUIRED},
    {sfSequence,             soeOPTIONAL},
    {sfAmount,               soeREQUIRED},
    {sfBalance,              soeREQUIRED},
    {sfPublicKey,            soeREQUIRED},
    {sfSettleDelay,          soeREQUIRED},
    {sfExpiration,           soeOPTIONAL},
    {sfCancelAfter,          soeOPTIONAL},
    {sfSourceTag,            soeOPTIONAL},
    {sfDestinationTag,       soeOPTIONAL},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
    {sfDestinationNode,      soeOPTIONAL},
}))

/** The ledger object which tracks the AMM.

   \sa keylet::amm
*/
LEDGER_ENTRY(ltAMM, 0x0079, AMM, amm, ({
    {sfAccount,              soeREQUIRED},
    {sfTradingFee,           soeDEFAULT},
    {sfVoteSlots,            soeOPTIONAL},
    {sfAuctionSlot,          soeOPTIONAL},
    {sfLPTokenBalance,       soeREQUIRED},
    {sfAsset,                soeREQUIRED},
    {sfAsset2,               soeREQUIRED},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeOPTIONAL},
    {sfPreviousTxnLgrSeq,    soeOPTIONAL},
}))

/** A ledger object which tracks MPTokenIssuance
    \sa keylet::mptIssuance
 */
LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, ({
    {sfIssuer,                   soeREQUIRED},
    {sfSequence,                 soeREQUIRED},
    {sfTransferFee,              soeDEFAULT},
    {sfOwnerNode,                soeREQUIRED},
    {sfAssetScale,               soeDEFAULT},
    {sfMaximumAmount,            soeOPTIONAL},
    {sfOutstandingAmount,        soeREQUIRED},
    {sfLockedAmount,             soeOPTIONAL},
    {sfMPTokenMetadata,          soeOPTIONAL},
    {sfPreviousTxnID,            soeREQUIRED},
    {sfPreviousTxnLgrSeq,        soeREQUIRED},
    {sfDomainID,                 soeOPTIONAL},
    {sfMutableFlags,             soeDEFAULT},
}))

/** A ledger object which tracks MPToken
    \sa keylet::mptoken
 */
LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, ({
    {sfAccount,                  soeREQUIRED},
    {sfMPTokenIssuanceID,        soeREQUIRED},
    {sfMPTAmount,                soeDEFAULT},
    {sfLockedAmount,             soeOPTIONAL},
    {sfOwnerNode,                soeREQUIRED},
    {sfPreviousTxnID,            soeREQUIRED},
    {sfPreviousTxnLgrSeq,        soeREQUIRED},
}))

/** A ledger object which tracks Oracle
    \sa keylet::oracle
 */
LEDGER_ENTRY(ltORACLE, 0x0080, Oracle, oracle, ({
    {sfOwner,                soeREQUIRED},
    {sfOracleDocumentID,     soeOPTIONAL},
    {sfProvider,             soeREQUIRED},
    {sfPriceDataSeries,      soeREQUIRED},
    {sfAssetClass,           soeREQUIRED},
    {sfLastUpdateTime,       soeREQUIRED},
    {sfURI,                  soeOPTIONAL},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** A ledger object which tracks Credential
    \sa keylet::credential
 */
LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, ({
    {sfSubject,              soeREQUIRED},
    {sfIssuer,               soeREQUIRED},
    {sfCredentialType,       soeREQUIRED},
    {sfExpiration,           soeOPTIONAL},
    {sfURI,                  soeOPTIONAL},
    {sfIssuerNode,           soeREQUIRED},
    {sfSubjectNode,          soeOPTIONAL},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** A ledger object which tracks PermissionedDomain
    \sa keylet::permissionedDomain
 */
LEDGER_ENTRY(ltPERMISSIONED_DOMAIN, 0x0082, PermissionedDomain, permissioned_domain, ({
    {sfOwner,               soeREQUIRED},
    {sfSequence,            soeREQUIRED},
    {sfAcceptedCredentials, soeREQUIRED},
    {sfOwnerNode,           soeREQUIRED},
    {sfPreviousTxnID,       soeREQUIRED},
    {sfPreviousTxnLgrSeq,   soeREQUIRED},
}))

/** A ledger object representing permissions an account has delegated to another account.
    \sa keylet::delegate
 */
LEDGER_ENTRY(ltDELEGATE, 0x0083, Delegate, delegate, ({
    {sfAccount,              soeREQUIRED},
    {sfAuthorize,            soeREQUIRED},
    {sfPermissions,          soeREQUIRED},
    {sfOwnerNode,            soeREQUIRED},
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
}))

/** A ledger object representing a single asset vault.
    \sa keylet::vault
 */
LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({
    {sfPreviousTxnID,        soeREQUIRED},
    {sfPreviousTxnLgrSeq,    soeREQUIRED},
    {sfSequence,             soeREQUIRED},
    {sfOwnerNode,            soeREQUIRED},
    {sfOwner,                soeREQUIRED},
    {sfAccount,              soeREQUIRED},
    {sfData,                 soeOPTIONAL},
    {sfAsset,                soeREQUIRED},
    {sfAssetsTotal,          soeREQUIRED},
    {sfAssetsAvailable,      soeREQUIRED},
    {sfAssetsMaximum,        soeDEFAULT},
    {sfLossUnrealized,       soeREQUIRED},
    {sfShareMPTID,           soeREQUIRED},
    {sfWithdrawalPolicy,     soeREQUIRED},
    {sfScale,                soeDEFAULT},
    // no SharesTotal ever (use MPTIssuance.sfOutstandingAmount)
    // no PermissionedDomainID ever (use MPTIssuance.sfDomainID)
}))

#undef EXPAND
#undef LEDGER_ENTRY_DUPLICATE
