Skip to content

feat: Add code generator for transactions and ledger entries#6443

Draft
a1q123456 wants to merge 2 commits intodevelopfrom
a1q123456/add-code-generator
Draft

feat: Add code generator for transactions and ledger entries#6443
a1q123456 wants to merge 2 commits intodevelopfrom
a1q123456/add-code-generator

Conversation

@a1q123456
Copy link
Collaborator

@a1q123456 a1q123456 commented Feb 26, 2026

High Level Overview of Change

This PR adds code generators to generate type wrappers for transactions and ledger entries. The generators are python scripts and we generate code during configuration. The generated files are ignored by git but are put under xrpl.protocol_autogen. This approach provides 2 benefits:

  1. It's friendly to IDEs and humans
  2. We always get the latest generated code after we modify transactions.macro, ledger_entries.macro, or sfields.macro

Context of Change

                auto testTx = transactions::AMMBidBuilder::create()
                    .setBidMin(XRP(100))
                    .setBidMax(XRP(110))
                    .build();

                auto ammObj = ledger_entries::AMMBuilder::create()
                                  .setAsset(xrpIssue())
                                  .setAsset2(xrpIssue())
                                  .build(uint256{});

                auto ammObj2 = ledger_entries::AMMBuilder::create(ammObj.getSle())
                                  .setAsset(xrpIssue())
                                  .setAsset2(xrpIssue())
                                  .build(uint256{});
#pragma once

#include <xrpl/protocol/LedgerEntryBase.h>
#include <xrpl/protocol/LedgerEntryBuilderBase.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>

namespace xrpl::ledger_entries {

// Forward declaration
class AccountRootBuilder;

/**
 * Ledger Entry: AccountRoot
 * Type: ltACCOUNT_ROOT (0x0061)
 * RPC Name: account
 *
 * Immutable wrapper around SLE providing type-safe field access.
 * Use AccountRootBuilder to construct new ledger entries.
 */
class AccountRoot : public LedgerEntryBase
{
public:
    static constexpr LedgerEntryType entryType = ltACCOUNT_ROOT;

    /**
     * Construct a AccountRoot ledger entry wrapper from an existing SLE object.
     * @throws std::runtime_error if the ledger entry type doesn't match.
     */
    explicit AccountRoot(SLE const& sle)
        : LedgerEntryBase(sle)
    {
        // Verify ledger entry type
        if (sle.getType() != entryType)
        {
            throw std::runtime_error("Invalid ledger entry type for AccountRoot");
        }
    }

    // Ledger entry-specific field getters

    /**
     * Get sfAccount (soeREQUIRED)
     */
    [[nodiscard]]
    SF_ACCOUNT::type::value_type
    getAccount() const
    {
        return this->sle_.at(sfAccount);
    }

    /**
     * Get sfSequence (soeREQUIRED)
     */
    [[nodiscard]]
    SF_UINT32::type::value_type
    getSequence() const
    {
        return this->sle_.at(sfSequence);
    }

    /**
     * Get sfBalance (soeREQUIRED)
     */
    [[nodiscard]]
    SF_AMOUNT::type::value_type
    getBalance() const
    {
        return this->sle_.at(sfBalance);
    }

    /**
     * Get sfOwnerCount (soeREQUIRED)
     */
    [[nodiscard]]
    SF_UINT32::type::value_type
    getOwnerCount() const
    {
        return this->sle_.at(sfOwnerCount);
    }

    /**
     * Get sfPreviousTxnID (soeREQUIRED)
     */
    [[nodiscard]]
    SF_UINT256::type::value_type
    getPreviousTxnID() const
    {
        return this->sle_.at(sfPreviousTxnID);
    }

    /**
     * Get sfPreviousTxnLgrSeq (soeREQUIRED)
     */
    [[nodiscard]]
    SF_UINT32::type::value_type
    getPreviousTxnLgrSeq() const
    {
        return this->sle_.at(sfPreviousTxnLgrSeq);
    }

    /**
     * Get sfAccountTxnID (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT256::type::value_type>
    getAccountTxnID() const
    {
        if (hasAccountTxnID())
            return this->sle_.at(sfAccountTxnID);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasAccountTxnID() const
    {
        return this->sle_.isFieldPresent(sfAccountTxnID);
    }

    /**
     * Get sfRegularKey (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_ACCOUNT::type::value_type>
    getRegularKey() const
    {
        if (hasRegularKey())
            return this->sle_.at(sfRegularKey);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasRegularKey() const
    {
        return this->sle_.isFieldPresent(sfRegularKey);
    }

    /**
     * Get sfEmailHash (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT128::type::value_type>
    getEmailHash() const
    {
        if (hasEmailHash())
            return this->sle_.at(sfEmailHash);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasEmailHash() const
    {
        return this->sle_.isFieldPresent(sfEmailHash);
    }

    /**
     * Get sfWalletLocator (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT256::type::value_type>
    getWalletLocator() const
    {
        if (hasWalletLocator())
            return this->sle_.at(sfWalletLocator);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasWalletLocator() const
    {
        return this->sle_.isFieldPresent(sfWalletLocator);
    }

    /**
     * Get sfWalletSize (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT32::type::value_type>
    getWalletSize() const
    {
        if (hasWalletSize())
            return this->sle_.at(sfWalletSize);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasWalletSize() const
    {
        return this->sle_.isFieldPresent(sfWalletSize);
    }

    /**
     * Get sfMessageKey (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_VL::type::value_type>
    getMessageKey() const
    {
        if (hasMessageKey())
            return this->sle_.at(sfMessageKey);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasMessageKey() const
    {
        return this->sle_.isFieldPresent(sfMessageKey);
    }

    /**
     * Get sfTransferRate (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT32::type::value_type>
    getTransferRate() const
    {
        if (hasTransferRate())
            return this->sle_.at(sfTransferRate);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasTransferRate() const
    {
        return this->sle_.isFieldPresent(sfTransferRate);
    }

    /**
     * Get sfDomain (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_VL::type::value_type>
    getDomain() const
    {
        if (hasDomain())
            return this->sle_.at(sfDomain);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasDomain() const
    {
        return this->sle_.isFieldPresent(sfDomain);
    }

    /**
     * Get sfTickSize (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT8::type::value_type>
    getTickSize() const
    {
        if (hasTickSize())
            return this->sle_.at(sfTickSize);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasTickSize() const
    {
        return this->sle_.isFieldPresent(sfTickSize);
    }

    /**
     * Get sfTicketCount (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT32::type::value_type>
    getTicketCount() const
    {
        if (hasTicketCount())
            return this->sle_.at(sfTicketCount);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasTicketCount() const
    {
        return this->sle_.isFieldPresent(sfTicketCount);
    }

    /**
     * Get sfNFTokenMinter (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_ACCOUNT::type::value_type>
    getNFTokenMinter() const
    {
        if (hasNFTokenMinter())
            return this->sle_.at(sfNFTokenMinter);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasNFTokenMinter() const
    {
        return this->sle_.isFieldPresent(sfNFTokenMinter);
    }

    /**
     * Get sfMintedNFTokens (soeDEFAULT)
     */
    [[nodiscard]]
    std::optional<SF_UINT32::type::value_type>
    getMintedNFTokens() const
    {
        if (hasMintedNFTokens())
            return this->sle_.at(sfMintedNFTokens);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasMintedNFTokens() const
    {
        return this->sle_.isFieldPresent(sfMintedNFTokens);
    }

    /**
     * Get sfBurnedNFTokens (soeDEFAULT)
     */
    [[nodiscard]]
    std::optional<SF_UINT32::type::value_type>
    getBurnedNFTokens() const
    {
        if (hasBurnedNFTokens())
            return this->sle_.at(sfBurnedNFTokens);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasBurnedNFTokens() const
    {
        return this->sle_.isFieldPresent(sfBurnedNFTokens);
    }

    /**
     * Get sfFirstNFTokenSequence (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT32::type::value_type>
    getFirstNFTokenSequence() const
    {
        if (hasFirstNFTokenSequence())
            return this->sle_.at(sfFirstNFTokenSequence);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasFirstNFTokenSequence() const
    {
        return this->sle_.isFieldPresent(sfFirstNFTokenSequence);
    }

    /**
     * Get sfAMMID (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT256::type::value_type>
    getAMMID() const
    {
        if (hasAMMID())
            return this->sle_.at(sfAMMID);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasAMMID() const
    {
        return this->sle_.isFieldPresent(sfAMMID);
    }

    /**
     * Get sfVaultID (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT256::type::value_type>
    getVaultID() const
    {
        if (hasVaultID())
            return this->sle_.at(sfVaultID);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasVaultID() const
    {
        return this->sle_.isFieldPresent(sfVaultID);
    }

    /**
     * Get sfLoanBrokerID (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_UINT256::type::value_type>
    getLoanBrokerID() const
    {
        if (hasLoanBrokerID())
            return this->sle_.at(sfLoanBrokerID);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasLoanBrokerID() const
    {
        return this->sle_.isFieldPresent(sfLoanBrokerID);
    }
};

/**
 * Builder for AccountRoot ledger entries.
 * Provides a fluent interface for constructing ledger entries with method chaining.
 * Uses Json::Value internally for flexible ledger entry construction.
 * Inherits common field setters from LedgerEntryBuilderBase.
 */
class AccountRootBuilder : public LedgerEntryBuilderBase<AccountRootBuilder>
{
public:
    AccountRootBuilder()
    {
        // Initialize with ledger entry type
        object_[sfLedgerEntryType] = ltACCOUNT_ROOT;
    }

    AccountRootBuilder(SLE const& sle)
    {
        if (object_[sfLedgerEntryType] != ltACCOUNT_ROOT)
        {
            throw std::runtime_error("Invalid ledger entry type for AccountRoot");
        }
        object_ = sle;
    }

    // Ledger entry-specific field setters

    /**
     * Set sfAccount (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setAccount(SF_ACCOUNT::type::value_type const& value)
    {
        object_[sfAccount] = value;
        return *this;
    }

    /**
     * Set sfSequence (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setSequence(SF_UINT32::type::value_type const& value)
    {
        object_[sfSequence] = value;
        return *this;
    }

    /**
     * Set sfBalance (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setBalance(SF_AMOUNT::type::value_type const& value)
    {
        object_[sfBalance] = value;
        return *this;
    }

    /**
     * Set sfOwnerCount (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setOwnerCount(SF_UINT32::type::value_type const& value)
    {
        object_[sfOwnerCount] = value;
        return *this;
    }

    /**
     * Set sfPreviousTxnID (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setPreviousTxnID(SF_UINT256::type::value_type const& value)
    {
        object_[sfPreviousTxnID] = value;
        return *this;
    }

    /**
     * Set sfPreviousTxnLgrSeq (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setPreviousTxnLgrSeq(SF_UINT32::type::value_type const& value)
    {
        object_[sfPreviousTxnLgrSeq] = value;
        return *this;
    }

    /**
     * Set sfAccountTxnID (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setAccountTxnID(SF_UINT256::type::value_type const& value)
    {
        object_[sfAccountTxnID] = value;
        return *this;
    }

    /**
     * Set sfRegularKey (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setRegularKey(SF_ACCOUNT::type::value_type const& value)
    {
        object_[sfRegularKey] = value;
        return *this;
    }

    /**
     * Set sfEmailHash (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setEmailHash(SF_UINT128::type::value_type const& value)
    {
        object_[sfEmailHash] = value;
        return *this;
    }

    /**
     * Set sfWalletLocator (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setWalletLocator(SF_UINT256::type::value_type const& value)
    {
        object_[sfWalletLocator] = value;
        return *this;
    }

    /**
     * Set sfWalletSize (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setWalletSize(SF_UINT32::type::value_type const& value)
    {
        object_[sfWalletSize] = value;
        return *this;
    }

    /**
     * Set sfMessageKey (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setMessageKey(SF_VL::type::value_type const& value)
    {
        object_[sfMessageKey] = value;
        return *this;
    }

    /**
     * Set sfTransferRate (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setTransferRate(SF_UINT32::type::value_type const& value)
    {
        object_[sfTransferRate] = value;
        return *this;
    }

    /**
     * Set sfDomain (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setDomain(SF_VL::type::value_type const& value)
    {
        object_[sfDomain] = value;
        return *this;
    }

    /**
     * Set sfTickSize (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setTickSize(SF_UINT8::type::value_type const& value)
    {
        object_[sfTickSize] = value;
        return *this;
    }

    /**
     * Set sfTicketCount (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setTicketCount(SF_UINT32::type::value_type const& value)
    {
        object_[sfTicketCount] = value;
        return *this;
    }

    /**
     * Set sfNFTokenMinter (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setNFTokenMinter(SF_ACCOUNT::type::value_type const& value)
    {
        object_[sfNFTokenMinter] = value;
        return *this;
    }

    /**
     * Set sfMintedNFTokens (soeDEFAULT)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setMintedNFTokens(SF_UINT32::type::value_type const& value)
    {
        object_[sfMintedNFTokens] = value;
        return *this;
    }

    /**
     * Set sfBurnedNFTokens (soeDEFAULT)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setBurnedNFTokens(SF_UINT32::type::value_type const& value)
    {
        object_[sfBurnedNFTokens] = value;
        return *this;
    }

    /**
     * Set sfFirstNFTokenSequence (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setFirstNFTokenSequence(SF_UINT32::type::value_type const& value)
    {
        object_[sfFirstNFTokenSequence] = value;
        return *this;
    }

    /**
     * Set sfAMMID (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setAMMID(SF_UINT256::type::value_type const& value)
    {
        object_[sfAMMID] = value;
        return *this;
    }

    /**
     * Set sfVaultID (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setVaultID(SF_UINT256::type::value_type const& value)
    {
        object_[sfVaultID] = value;
        return *this;
    }

    /**
     * Set sfLoanBrokerID (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AccountRootBuilder&
    setLoanBrokerID(SF_UINT256::type::value_type const& value)
    {
        object_[sfLoanBrokerID] = value;
        return *this;
    }

    /**
     * Build and return the completed AccountRoot wrapper.
     * @return The constructed ledger entry wrapper.
     * @throws std::runtime_error if the JSON cannot be parsed into a valid ledger entry.
     */
    AccountRoot
    build(uint256 const& index)
    {
        return AccountRoot{SLE(object_, index)};
    }
};

}  // namespace xrpl::ledger_entries
#pragma once

#include <xrpl/protocol/TransactionBase.h>
#include <xrpl/protocol/TransactionBuilderBase.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>

namespace xrpl::transactions {

// Forward declaration
class AMMBidBuilder;

/**
 * Transaction: AMMBid
 * Type: ttAMM_BID (39)
 * Delegable: Delegation::delegable
 * Amendment: featureAMM
 * Privileges: noPriv
 *
 * Immutable wrapper around STTx providing type-safe field access.
 * Use AMMBidBuilder to construct new transactions.
 */
class AMMBid : public TransactionBase
{
public:
    static constexpr xrpl::TxType txType = ttAMM_BID;

    /**
     * Construct a AMMBid transaction wrapper from an existing STTx object.
     * @throws std::runtime_error if the transaction type doesn't match.
     */
    explicit AMMBid(STTx const& tx)
        : TransactionBase(tx)
    {
        // Verify transaction type
        if (tx.getTxnType() != txType)
        {
            throw std::runtime_error("Invalid transaction type for AMMBid");
        }
    }

    // Transaction-specific field getters

    /**
     * Get sfAsset (soeREQUIRED)
     */
    [[nodiscard]]
    SF_ISSUE::type::value_type
    getAsset() const
    {
        return this->tx_.at(sfAsset);
    }

    /**
     * Get sfAsset2 (soeREQUIRED)
     */
    [[nodiscard]]
    SF_ISSUE::type::value_type
    getAsset2() const
    {
        return this->tx_.at(sfAsset2);
    }

    /**
     * Get sfBidMin (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_AMOUNT::type::value_type>
    getBidMin() const
    {
        if (hasBidMin())
        {
            return this->tx_.at(sfBidMin);
        }
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasBidMin() const
    {
        return this->tx_.isFieldPresent(sfBidMin);
    }

    /**
     * Get sfBidMax (soeOPTIONAL)
     */
    [[nodiscard]]
    std::optional<SF_AMOUNT::type::value_type>
    getBidMax() const
    {
        if (hasBidMax())
        {
            return this->tx_.at(sfBidMax);
        }
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasBidMax() const
    {
        return this->tx_.isFieldPresent(sfBidMax);
    }
    /**
     * Get sfAuthAccounts (soeOPTIONAL)
     * Note: This is an untyped field
     */
    [[nodiscard]]
    std::optional<std::reference_wrapper<STArray const>>
    getAuthAccounts() const
    {
        if (this->tx_.isFieldPresent(sfAuthAccounts))
            return this->tx_.getFieldArray(sfAuthAccounts);
        return std::nullopt;
    }

    [[nodiscard]]
    bool
    hasAuthAccounts() const
    {
        return this->tx_.isFieldPresent(sfAuthAccounts);
    }
};

/**
 * Builder for AMMBid transactions.
 * Provides a fluent interface for constructing transactions with method chaining.
 * Uses Json::Value internally for flexible transaction construction.
 * Inherits common field setters from TransactionBuilderBase.
 */
class AMMBidBuilder : public TransactionBuilderBase<AMMBidBuilder>
{
public:
    AMMBidBuilder()
    {
        // Initialize with transaction type
        object_[sfTransactionType]  = ttAMM_BID;
    }

    AMMBidBuilder(STTx const& tx)
    {
        if (tx.getTxnType() != ttAMM_BID)
        {
            throw std::runtime_error("Invalid transaction type for AMMBidBuilder");
        }
        object_ = tx;
    }

    // Transaction-specific field setters

    /**
     * Set sfAsset (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AMMBidBuilder&
    setAsset(SF_ISSUE::type::value_type const& value)
    {
        object_[sfAsset] = STIssue(sfAsset, value);
        return *this;
    }

    /**
     * Set sfAsset2 (soeREQUIRED)
     * @return Reference to this builder for method chaining.
     */
    AMMBidBuilder&
    setAsset2(SF_ISSUE::type::value_type const& value)
    {
        object_[sfAsset2] = STIssue(sfAsset2, value);
        return *this;
    }

    /**
     * Set sfBidMin (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AMMBidBuilder&
    setBidMin(SF_AMOUNT::type::value_type const& value)
    {
        object_[sfBidMin] = value;
        return *this;
    }

    /**
     * Set sfBidMax (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AMMBidBuilder&
    setBidMax(SF_AMOUNT::type::value_type const& value)
    {
        object_[sfBidMax] = value;
        return *this;
    }

    /**
     * Set sfAuthAccounts (soeOPTIONAL)
     * @return Reference to this builder for method chaining.
     */
    AMMBidBuilder&
    setAuthAccounts(STArray const& value)
    {
        object_.setFieldArray(sfAuthAccounts, value);
        return *this;
    }

    /**
     * Build and return the completed AMMBid wrapper.
     * @return The constructed transaction wrapper.
     * @throws std::runtime_error if the JSON cannot be parsed into a valid transaction.
     */
    AMMBid
    build()
    {
        return AMMBid(STTx(std::move(object_)));
    }
};

}  // namespace xrpl::transactions

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Performance (increase or change in throughput and/or latency)
  • Tests (you added tests for code that already exists, or your new feature included in this PR)
  • Documentation update
  • Chore (no impact to binary, e.g. .gitignore, formatting, dropping support for older tooling)
  • Release

API Impact

  • Public API: New feature (new methods and/or new fields)
  • Public API: Breaking change (in general, breaking changes should only impact the next api_version)
  • libxrpl change (any change that may affect libxrpl or dependents of libxrpl)
  • Peer protocol change (must be backward compatible or bump the peer protocol version)

Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
@a1q123456 a1q123456 changed the title feat: Add code generator feat: Add code generator for transactions and ledger entries Feb 27, 2026
value = args_list[1]
name = args_list[2]
rpc_name = args_list[3]
fields_str = args_list[4]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might be able to make this a little bit more future-proof by setting the fields_str to the last item rather than a specific index. The way the existing macros are written, the fields will always have to be last, so any new fields will be inserted before them. At least until the possible future where the macros are all replaced by python parsers.

set(VENV_PYTHON "${VENV_DIR}/Scripts/python.exe")
set(VENV_PIP "${VENV_DIR}/Scripts/pip.exe")
else ()
set(VENV_PYTHON "${VENV_DIR}/bin/python")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if it builds if there's no network connection

message(STATUS "Using Python3 for code generation: ${Python3_EXECUTABLE}")

# Set up Python virtual environment for code generation
set(VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/codegen_venv")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to have: may be worth making it a build option

/.cache

# Auto-generated protocol wrapper classes (generated at CMake configure time)
/include/xrpl/protocol_autogen/transactions/
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be a good idea to check those files in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants