Skip to content

[Advanced]: Implement HIP-1261 Fee Estimate Query Support #1029

@gsstoykov

Description

@gsstoykov

🧠 Advanced

This issue is well-suited for contributors who are very familiar with the Hiero C++ SDK and enjoy working with its core abstractions and design patterns.

Advanced Issues often involve:

  • Exploring and shaping SDK architecture
  • Reasoning about trade-offs and long-term impact
  • Working across multiple modules or systems
  • Updating tests, examples, and documentation alongside code

The goal is to support thoughtful, high-impact contributions in a clear and collaborative way.


🐞 Problem Description

The Hiero C++ SDK doesn't currently support fee estimate queries as defined in HIP-1261: Simple Fees. This makes it harder for developers to programmatically estimate transaction fees before execution.

Background

HIP-1261 introduces a simplified fee model with three components:

  • Node fee: Paid to the submitting node (based on bytes and signatures)
  • Network fee: Covers gossip, consensus, signature verification, and storage
  • Service fee: Covers execution costs and state persistence

The fee estimation API allows users to predict transaction costs before submission, supporting two modes:

  • STATE mode (default): Estimates using the mirror node's latest known state
  • INTRINSIC mode: Estimates from the payload alone, ignoring state-dependent costs

💡 Proposed / Expected Outcome

Implement full SDK support for HIP-1261 fee estimation following the design document provided:

Design Document: https://github.com/hiero-ledger/sdk-collaboration-hub/blob/main/proposals/hips/hip-1261.md

Important

The implementation MUST follow the API design, class structure, and behavior defined in the design document above. This ensures consistency across all Hiero SDK implementations.

The design document specifies the following components to implement:

New Data Types

enum class FeeEstimateMode {
    STATE,      // Default: uses latest known state
    INTRINSIC   // Ignores state-dependent factors
};

class FeeExtra {
    std::string name;           // Extra fee name (e.g., "Signatures", "Bytes")
    uint32_t included;          // Count included for free
    uint32_t count;             // Actual count received
    uint32_t charged;           // max(0, count - included)
    uint64_t feePerUnit;        // Fee per unit in tinycents
    uint64_t subtotal;          // charged * feePerUnit
};

class FeeEstimate {
    uint64_t base;              // Base fee in tinycents
    std::vector<FeeExtra> extras;
};

class NetworkFee {
    uint32_t multiplier;        // Multiplied by node fee
    uint64_t subtotal;          // node.subtotal * multiplier
};

class FeeEstimateResponse {
    FeeEstimateMode mode;
    NetworkFee networkFee;
    FeeEstimate nodeFee;
    FeeEstimate serviceFee;
    std::vector<std::string> notes;
    uint64_t total;             // Sum of all subtotals
};

New Query Class

class FeeEstimateQuery : public Query<FeeEstimateResponse> {
    FeeEstimateQuery& setMode(FeeEstimateMode mode);
    FeeEstimateMode getMode() const;
    
    FeeEstimateQuery& setTransaction(const Transaction& transaction);
    // Transaction is automatically frozen if not already frozen
};

Transaction Extension

class Transaction {
    // New method to create a fee estimate query
    FeeEstimateQuery estimateFee() const;
};

🧠 Implementation & Design Notes

Design Document (Authoritative Source)

Important

All implementation details, API signatures, class names, and behaviors are defined in the design document. The design document is the authoritative source for this implementation.

Design Document: https://github.com/hiero-ledger/sdk-collaboration-hub/blob/main/proposals/hips/hip-1261.md

The design document includes:

  • Complete API specifications for all new types
  • Method signatures and expected behavior
  • Test plan with specific test cases
  • Code examples demonstrating usage

Contributors should implement the C++ equivalent of the APIs defined in the design document, following existing SDK patterns and conventions.

Key Implementation Areas (per Design Document)

  1. Data model classes (FeeExtra, FeeEstimate, NetworkFee, FeeEstimateResponse)

    • Immutable value types with appropriate getters
    • Serialization/deserialization from Mirror Node response
  2. FeeEstimateMode enum

    • Two modes: STATE and INTRINSIC
    • Default to STATE when not specified
  3. FeeEstimateQuery class

    • Extends existing Query base class patterns
    • Integrates with Mirror Node gRPC NetworkService.getFeeEstimate
    • Auto-freezes transaction if not already frozen
    • Implements retry policy (retry on UNAVAILABLE, DEADLINE_EXCEEDED; no retry on INVALID_ARGUMENT)
  4. Chunked transaction handling

    • For FileAppendTransaction and TopicMessageSubmitTransaction
    • Aggregate fees across all chunks into single response
    • total = sum of all chunk fees
  5. Transaction.estimateFee() method

    • Convenience method to create FeeEstimateQuery from any transaction

Fee Calculation Logic

From HIP-1261:

nodeFee = node.baseFee + sum(extras)
networkFee = nodeFee * network.multiplier
serviceFee = service.baseFee + sum(service.extras)
total = nodeFee + networkFee + serviceFee

Mirror Node Integration

The query communicates with the Mirror Node REST API:

POST /api/v1/network/fees?mode=STATE
Content-Type: application/protobuf
<Transaction protobuf binary>

Files to Create/Modify

New files (suggested structure):

  • src/sdk/main/include/FeeEstimateMode.h
  • src/sdk/main/include/FeeExtra.h
  • src/sdk/main/include/FeeEstimate.h
  • src/sdk/main/include/NetworkFee.h
  • src/sdk/main/include/FeeEstimateResponse.h
  • src/sdk/main/include/FeeEstimateQuery.h
  • src/sdk/main/src/FeeEstimateQuery.cc

Modified files:

  • Transaction base class (add estimateFee() method)
  • Potentially chunked transaction classes for fee aggregation

Test Plan

The design document includes a comprehensive test plan:

  1. Basic functionality: STATE mode, INTRINSIC mode, default mode behavior
  2. Transaction type coverage: TokenCreate, TokenMint, TopicCreate, ContractCreate, FileCreate
  3. Fee component validation: Verify network.subtotal = node.subtotal * multiplier, verify total calculation
  4. Error handling: Malformed transactions, service unavailable, timeouts
  5. Chunked transactions: FileAppendTransaction, TopicMessageSubmitTransaction aggregation

✅ Acceptance Criteria

A pull request for this issue should:

  • Follow the design document: Implementation matches the API design, class structure, and behavior specified in the design document
  • Implement all new data types as specified (FeeEstimateMode, FeeExtra, FeeEstimate, NetworkFee, FeeEstimateResponse)
  • Implement FeeEstimateQuery class as specified in the design document
  • Add estimateFee() method to Transaction base class
  • Handle chunked transaction fee aggregation per design document
  • Implement retry policy as specified (retry on UNAVAILABLE/DEADLINE_EXCEEDED, no retry on INVALID_ARGUMENT)
  • Auto-freeze transactions that aren't already frozen
  • Pass all test cases: Implement tests covering the test plan defined in the design document
  • Maintain backwards compatibility
  • Follow existing architectural and C++ conventions
  • Provide usage examples
  • Update relevant documentation
  • Pass all CI checks

📚 Additional Context, Links, or Prior Art

References

Document Purpose
SDK Design Document Authoritative source for implementation - defines APIs, behavior, and test plan
HIP-1261 (Simple Fees) Background context - explains the fee model and Mirror Node API

Fee Schedule Details

Fees are defined in tinycents (10^8 tinycents = 1 cent USD). The fee schedule is stored in system file 0.0.113.

Common extras:

Extra Description
Signatures Number of signatures on the transaction
Bytes Size of the transaction in protobuf bytes
Keys Number of keys being defined
Gas Gas cost for smart contract operations
TokenTypes Number of token types referenced
NFTSerials Number of distinct NFT serials

Cross-SDK Alignment

The design document ensures consistency across all Hiero SDK implementations. By following the design document, this C++ implementation will align with the Java, JavaScript, Go, and other SDK implementations.

Metadata

Metadata

Assignees

Labels

priority: highImportant issue that should be prioritized in the current sprint/releasescope: apiRelated to the public SDK API surfacescope: grpcRelated to gRPC/protobuf/network layerskill: advancedRequires deep understanding of the SDK architecture and may span multiple modulesstatus: blockedWork is stalled due to external dependency or required decision

Projects

Status

👷 In Progress

Status

In Progress

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions