Skip to content

docs: add new HIP-1261 simple fees #459

Open
theekrystallee wants to merge 3 commits into
mainfrom
feat/hip-1261-docs
Open

docs: add new HIP-1261 simple fees #459
theekrystallee wants to merge 3 commits into
mainfrom
feat/hip-1261-docs

Conversation

@theekrystallee
Copy link
Copy Markdown
Member

Description:

Related issue(s):

Fixes #381

Notes for reviewer:

Checklist

  • Documented (Code comments, README, etc.)
  • Tested (unit, integration, etc.)

Signed-off-by: krystal <56278409+theekrystallee@users.noreply.github.com>
Signed-off-by: krystal <56278409+theekrystallee@users.noreply.github.com>
@Reccetech
Copy link
Copy Markdown

Looks good!

Signed-off-by: krystal <56278409+theekrystallee@users.noreply.github.com>
Copy link
Copy Markdown

@joshmarinacci joshmarinacci left a comment

Choose a reason for hiding this comment

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

This looks great. Thank you! 👍

@theekrystallee theekrystallee changed the title docs for HIP-1261: simple fees added docs: add HIP-1261: simple fees feature Mar 26, 2026
@theekrystallee theekrystallee changed the title docs: add HIP-1261: simple fees feature docs: add HIP-1261 simple fees feature Mar 26, 2026
@theekrystallee theekrystallee self-assigned this Mar 26, 2026
@theekrystallee theekrystallee changed the title docs: add HIP-1261 simple fees feature docs: add new HIP-1261 simple fees Mar 26, 2026
@Reccetech
Copy link
Copy Markdown

PR #459 Review: Fixes and Additions Needed

PR: [#459 docs: add new HIP-1261 simple fees]

Open Question: Sidebar placement and naming of simple-fees.mdx

The PR places simple-fees.mdx under Core Concepts → Transactions and Queries in the sidebar. Two things are worth discussing before the PR merges.

1. The name simple-fees should just be fees

"Simple Fees" is the name of the HIP, not a concept developers will search for. A top-level page called Fees is clearer, more discoverable, and covers the full fees architecture — not just the HIP-1261 model. Rename the file and title accordingly.

2. Fees should be a top-level Core Concepts section, not nested under Transactions and Queries

Fees are a first-class concern for every Hedera developer. A developer looking for fee documentation may not think to look under "Transactions and Queries". Promoting it to its own section makes it easier to find and gives it room to grow:

Core Concepts
├── Accounts
├── Transactions and Queries
├── Fees                          ← new top-level section
│   └── fees.mdx                  (renamed from simple-fees.mdx)
├── Smart Contracts
└── ...

This also provides a natural home for any future fee-related pages (fee collection account, high-volume pricing) without crowding other sections.

The tradeoff is nav restructuring — renaming and moving the page requires updating docs.json, cross-links in fees.mdx and transactions.mdx, and the Related cards within the page itself.

Question for the team: Can we rename simple-fees.mdxfees.mdx and promote it to its own Core Concepts section before this PR merges?


Corrections

1. FileGetInfo is not a free query — simple-fees.mdx

In the Queries section:

"Some queries are marked as free in the fee schedule (e.g., FileGetInfo, TransactionGetReceipt)"

FileGetInfo costs $0.0001 and is not free. Replace with CryptoGetAccountBalance:

(e.g., `CryptoGetAccountBalance`, `TransactionGetReceipt`)

2. Remove stale "stubbed data" warning — network.mdx

The PR adds this callout:

"This endpoint currently returns stubbed (dummy) data as of mirror node v0.145.1."

The mirror node fee estimation endpoint is fully live and returning real data. This warning is no longer accurate and should be removed.


3. Extras table uses wrong names and is missing entries — simple-fees.mdx

The extras table was written against a draft or earlier version of the fee schedule. Comparing against the authoritative Extra enum in the consensus node (org.hiero.hapi.support.fees.Extra), the table has two categories of problems:

Wrong or non-existent names (the fee schedule uses these extra names; the doc has different ones):

Doc name Actual name Issue
TokenTypes (no such extra) Remove
StandardFungibleTokens FungibleTokens Wrong name
StandardNonFungibleTokens NonFungibleTokens Wrong name
CustomFeeFungibleTokens (no such extra) Remove
CustomFeeNonFungibleTokens (no such extra) Remove
CreatedAutoAssociations (no such extra) Remove
CreatedAccounts (no such extra) Remove
CustomFee (no generic extra; see transaction-specific ones below) Remove
HooksCreated HookUpdates (single value, not three) Wrong — collapse to one row
HooksDeleted (same HookUpdates entry) Remove — duplicate of above
HooksModified HookSlotUpdate Wrong name
HookInvocations HookExecution Wrong name

Extras missing entirely from the table (all are in the enum):

Extra name Description
HookUpdates Number of hook create/delete operations
HookSlotUpdate Number of hook slot modifications
HookExecution Number of hook programs invoked during execution
TokenTransferBase Base cost for token transfers
TokenTransferBaseCustomFees Base cost for token transfers with custom fees
TokenCreateWithCustomFee Token creation with a custom fee schedule defined
TokenMintNft Number of NFT serials minted
ConsensusCreateTopicWithCustomFee Topic creation with a custom fee schedule defined
ConsensusSubmitMessageWithCustomFee Message submission to a topic with custom fees
ScheduleCreateContractCallBase Base cost for scheduling a contract call
TokenAssociate Number of token associations

Additions

4. Create new SDK page for FeeEstimateQueryhedera/sdks-and-apis/sdks/fee-estimation.mdx

SDK implementation content belongs in the SDK docs, not in simple-fees.mdx. The concept page covers the fee model; a dedicated SDK page covers how to use it in code. This follows the same pattern as other SDK docs (tokens, consensus, accounts).

Create hedera/sdks-and-apis/sdks/fee-estimation.mdx containing:

a. FeeEstimateQuery usage (Java, Go, JavaScript) — both the direct query and the transaction.estimateFee() convenience method:

// Freeze the transaction first — the body must be finalized before estimating
var transaction = new AccountCreateTransaction()
    .setKeyWithoutAlias(newKey)
    .setInitialBalance(new Hbar(1))
    .freezeWith(client);

// Option 1: FeeEstimateQuery
FeeEstimateResponse response = new FeeEstimateQuery()
    .setTransaction(transaction)
    .setMode(FeeEstimateMode.INTRINSIC)   // optional — INTRINSIC is the default
    .execute(client);

// Option 2: Convenience method
FeeEstimateResponse response = transaction.estimateFee().execute(client);
const transaction = await new AccountCreateTransaction()
    .setKeyWithoutAlias(newKey)
    .setInitialBalance(new Hbar(1))
    .freezeWith(client);

const response = await new FeeEstimateQuery()
    .setTransaction(transaction)
    .setMode(FeeEstimateMode.INTRINSIC)
    .execute(client);

// or: const response = await transaction.estimateFee().execute(client);
tx, _ := hiero.NewAccountCreateTransaction().
    SetKeyWithoutAlias(newKey.PublicKey()).
    SetInitialBalance(hiero.NewHbar(1)).
    FreezeWith(client)

response, err := hiero.NewFeeEstimateQuery().
    SetTransaction(tx).
    SetMode(hiero.FeeEstimateModeIntrinsic).
    Execute(client)

// or: response, err := tx.EstimateFee().Execute(client)

b. Response structure with the totalling formula:

{
  "high_volume_multiplier": 1,
  "network": { "multiplier": 3, "subtotal": <node_subtotal × multiplier> },
  "node": {
    "base": <tinycents>,
    "extras": [
      { "name": "Signatures", "included": 1, "count": 2, "charged": 1, "fee_per_unit": <tinycents>, "subtotal": <tinycents> }
    ]
  },
  "service": { "base": <tinycents>, "extras": [] },
  "total": <tinycents>
}
node.subtotal    = node.base + sum(node.extras[].subtotal)
network.subtotal = node.subtotal × network.multiplier
total            = node.subtotal + network.subtotal + service.subtotal

Use real response values from a testnet call, not made-up numbers — any example with specific values must satisfy the formula above.

c. End-to-end pattern — estimate, gate on budget, then execute:

var transaction = new AccountCreateTransaction()
    .setKeyWithoutAlias(newKey)
    .setInitialBalance(new Hbar(1))
    .freezeWith(client);

FeeEstimateResponse estimate = transaction.estimateFee().execute(client);

// Gate on budget — $1.50 = 15,000,000,000 tinycents
if (estimate.getTotal() > 15_000_000_000L) {
    throw new RuntimeException("Fee estimate exceeds budget: " + estimate.getTotal());
}

var record = transaction
    .setMaxTransactionFee(new Hbar(10))
    .execute(client)
    .getRecord(client);
const transaction = await new AccountCreateTransaction()
    .setKeyWithoutAlias(newKey)
    .setInitialBalance(new Hbar(1))
    .freezeWith(client);

const estimate = await transaction.estimateFee().execute(client);

if (estimate.total.toBigInt() > 15_000_000_000n) {
    throw new Error(`Fee estimate exceeds budget: ${estimate.total}`);
}

const record = await (await transaction
    .setMaxTransactionFee(new Hbar(10))
    .execute(client))
    .getRecord(client);
tx, _ := hiero.NewAccountCreateTransaction().
    SetKeyWithoutAlias(newKey.PublicKey()).
    SetInitialBalance(hiero.NewHbar(1)).
    FreezeWith(client)

estimate, _ := tx.EstimateFee().Execute(client)

if estimate.Total > 15_000_000_000 {
    panic(fmt.Sprintf("fee estimate exceeds budget: %d", estimate.Total))
}

resp, _ := tx.SetMaxTransactionFee(hiero.NewHbar(10)).Execute(client)
record, _ := resp.GetRecord(client)

d. High-volume pricing simulation via setHighVolumeThrottle() (0–10000 basis points, where 10000 = 100% utilization):

FeeEstimateResponse hvResponse = new FeeEstimateQuery()
    .setTransaction(
        new AccountCreateTransaction()
            .setKeyWithoutAlias(newKey)
            .setHighVolume(true)
            .freezeWith(client)
    )
    .setMode(FeeEstimateMode.STATE)
    .setHighVolumeThrottle(5000)   // simulate 50% utilization
    .execute(client);

// high_volume_multiplier uses 1-based scale: 1 = 1×, 4 = 4×
System.out.printf("Multiplier at 50%% load: %dx%n", hvResponse.getHighVolumeMultiplier());
const hvResponse = await new FeeEstimateQuery()
    .setTransaction(
        await new AccountCreateTransaction()
            .setKeyWithoutAlias(newKey)
            .setHighVolume(true)
            .freezeWith(client)
    )
    .setMode(FeeEstimateMode.STATE)
    .setHighVolumeThrottle(5000)
    .execute(client);

console.log(`Multiplier at 50% load: ${hvResponse.highVolumeMultiplier}x`);
tx, _ := hiero.NewAccountCreateTransaction().
    SetKeyWithoutAlias(newKey.PublicKey()).
    SetHighVolume(true).
    FreezeWith(client)

hvResponse, _ := hiero.NewFeeEstimateQuery().
    SetTransaction(tx).
    SetMode(hiero.FeeEstimateModeState).
    SetHighVolumeThrottle(5000).
    Execute(client)

fmt.Printf("Multiplier at 50%% load: %dx\n", hvResponse.HighVolumeMultiplier)

e. Developer notes:

  • Freeze before estimating. Call freezeWith(client) before FeeEstimateQuery — the transaction body must be finalized for the estimate to reflect your actual transaction.
  • Estimates are in tinycents; execution fees are in tinybars. The response uses tinycents (USD × 10⁻¹⁰). The fee charged on execution is in tinybars (HBAR × 10⁻⁸), converted at the live exchange rate at consensus time.
  • Set maxTransactionFee with headroom. Add 10–20% above the estimate — exchange rates shift between estimation and execution.
  • high_volume_multiplier scale differs from TransactionRecord. The estimate response uses a 1-based scale (1 = 1×, 4 = 4×). TransactionRecord.highVolumePricingMultiplier after execution uses a 1000-based scale (1000 = 1×, 4000 = 4×).

f. SDK version availability:

FeeEstimateQuery is available in Java v2.71.0+, Go v2.79.0+, and JavaScript (@hiero-ledger/sdk) v2.83.0+.


Also update simple-fees.mdx — replace the current Fee Estimation section's closing line with a card linking to the new SDK page:

<Card title="Estimating Fees with the SDK" icon="code" href="/hedera/sdks-and-apis/sdks/fee-estimation">
  FeeEstimateQuery usage, response structure, end-to-end patterns, and developer notes for Java, Go, and JavaScript.
</Card>

Also update hedera/sdks-and-apis/sdks/transactions.mdx — the existing two-line prose update added by this PR should link to the new page rather than just mentioning the mirror node endpoint.

Also update docs.json — add fee-estimation to the SDK docs navigation group.


5. Expand Congestion Pricing section — simple-fees.mdx

The current section is two vague sentences with no reference to HIP-1313. Replace with:

HIP-1313 introduces an optional high-volume lane for entity-creation transactions above the standard throttle. When a transaction opts in with setHighVolume(true), the network may apply a fee multiplier if the high-volume throttle bucket is under load. The multiplier scales with congestion level and is reflected in the high_volume_multiplier field of the fee estimate response.

The high_volume_multiplier field uses a 1-based scale (1 = 1×, 4 = 4×). TransactionRecord.highVolumePricingMultiplier — available after execution — uses a 1000-based scale (1000 = 1×, 4000 = 4×). Both represent the same multiplier.

To simulate the fee at a specific congestion level before committing, use setHighVolumeThrottle() on FeeEstimateQuery. See Estimating Fees with the SDK for code examples.


fees.mdx (separate from simple-fees.mdx)

These are not introduced by this PR but should be addressed alongside it:

6. Cross-link simple-fees.mdx from fees.mdx

fees.mdx is the primary entry point for developers looking up fees — it's the page they find via search and the sidebar. It should prominently link to simple-fees.mdx so readers understand the fee model behind the numbers. The PR adds a one-paragraph intro to fees.mdx referencing Simple Fees, but there is no direct link to simple-fees.mdx from that page.

Add a link in the intro paragraph, for example:

Hedera transaction and query fees follow a base fee + extras model defined by HIP-1261 (Simple Fees).

The intro already contains this text — confirm the simple-fees.mdx path is correctly linked (not just prose) and visible before the fee tables.


7. Remove deprecated operations from fee tables

The following operations are no longer supported by the consensus node and should be removed:

Operation Section
CryptoAddLiveHash Cryptocurrency Service
CryptoDeleteLiveHash Cryptocurrency Service
CryptoGetLiveHash Cryptocurrency Service
CryptoGetStakers Cryptocurrency Service
ContractGetRecords Smart Contract Service
TokenMint (bulk mint 10k NFTs) $200.00 Token Service

8. Typo in intro text

"1,0000-byte sized file"1,000-byte sized file

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.

Add HIP-1261

3 participants