docs: add new HIP-1261 simple fees #459
Conversation
Signed-off-by: krystal <56278409+theekrystallee@users.noreply.github.com>
Signed-off-by: krystal <56278409+theekrystallee@users.noreply.github.com>
|
Looks good! |
Signed-off-by: krystal <56278409+theekrystallee@users.noreply.github.com>
joshmarinacci
left a comment
There was a problem hiding this comment.
This looks great. Thank you! 👍
PR #459 Review: Fixes and Additions NeededPR: [#459 docs: add new HIP-1261 simple fees] Open Question: Sidebar placement and naming of
|
| 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 FeeEstimateQuery — hedera/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)beforeFeeEstimateQuery— 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
maxTransactionFeewith headroom. Add 10–20% above the estimate — exchange rates shift between estimation and execution. high_volume_multiplierscale differs fromTransactionRecord. The estimate response uses a 1-based scale (1 = 1×, 4 = 4×).TransactionRecord.highVolumePricingMultiplierafter 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 thehigh_volume_multiplierfield of the fee estimate response.The
high_volume_multiplierfield 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()onFeeEstimateQuery. 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
Description:
Related issue(s):
Fixes #381
Notes for reviewer:
Checklist