payment_queryFeeDetails - Asset Hub RPC Method
Get a detailed fee breakdown for an extrinsic on Asset Hub. Analyze base fee, length fee, and adjusted weight fee components to optimize transaction costs for native stablecoin transfers (USDC, USDT), DOT staking and governance, and cross-chain asset management via XCM.
Returns a detailed breakdown of the inclusion fee for a given extrinsic on Asset Hub. While payment_queryInfo returns the total fee as a single value, this method separates it into three components: the fixed base fee, the length-proportional fee, and the weight-based adjusted fee. This granularity is essential for understanding and optimizing transaction costs.
If you provide blockHash, it must be a real chain block hash. Placeholder hashes and stale examples return an unknown Block style error.
Why Asset Hub? Build on Polkadot's system parachain managing $4.5B+ in DOT tokens, native USDC/USDT, and NFTs with 50-90% lower fees than Relay Chain, fee payment in any supported asset, 1.5M+ accounts migrated, and trustless Ethereum bridge access.
When to Use This Method
payment_queryFeeDetails is essential for asset issuers, stablecoin integrators, and teams requiring low-cost token management on Polkadot:
- Fee Optimization -- Identify which fee component dominates your transaction cost and optimize accordingly on Asset Hub
- Transaction Cost Analysis -- Build detailed cost breakdowns for native stablecoin transfers (USDC, USDT), DOT staking and governance, and cross-chain asset management via XCM, showing users exactly where their fees go
- Fee Model Comparison -- Compare fee structures across different extrinsic types or between runtime upgrades that change fee parameters
- Batching Decisions -- Determine whether batching calls saves fees by amortizing the base fee across multiple operations
Code Examples
# Query fee details for an encoded extrinsic
curl -X POST https://asset-hub-polkadot-rpc.n.dwellir.com \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "payment_queryFeeDetails",
"params": ["0x2d028400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01..."],
"id": 1
}'
# Query fee details at a specific block
# Replace 0xYOUR_RECENT_BLOCK_HASH with a recent finalized hash from chain_getFinalizedHead
curl -X POST https://asset-hub-polkadot-rpc.n.dwellir.com \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "payment_queryFeeDetails",
"params": [
"0x2d028400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01...",
"0xYOUR_RECENT_BLOCK_HASH"
],
"id": 1
}'Common Use Cases
1. Fee Component Analysis for Optimization
Analyze which fee component dominates to guide optimization strategies:
import { ApiPromise, WsProvider } from '@polkadot/api';
async function analyzeFeeComponents(api, tx) {
const feeDetails = await api.rpc.payment.queryFeeDetails(tx.toHex());
if (feeDetails.inclusionFee.isNone) {
return { feeless: true };
}
const fee = feeDetails.inclusionFee.unwrap();
const base = BigInt(fee.baseFee.toString());
const len = BigInt(fee.lenFee.toString());
const weight = BigInt(fee.adjustedWeightFee.toString());
const total = base + len + weight;
const analysis = {
baseFee: { value: base, percentage: Number((base * 10000n) / total) / 100 },
lenFee: { value: len, percentage: Number((len * 10000n) / total) / 100 },
weightFee: { value: weight, percentage: Number((weight * 10000n) / total) / 100 },
total
};
// Suggest optimization based on dominant component
if (analysis.lenFee.percentage > 50) {
analysis.suggestion = 'Length fee dominates -- reduce call data size or batch smaller calls';
} else if (analysis.weightFee.percentage > 50) {
analysis.suggestion = 'Weight fee dominates -- choose lighter runtime operations';
} else {
analysis.suggestion = 'Fees are balanced -- batch calls to amortize base fee';
}
return analysis;
}2. Batch vs. Individual Fee Comparison
Compare the cost of batching calls versus submitting them individually:
async function compareBatchVsIndividual(api, calls) {
// Individual fee total
let individualTotal = 0n;
for (const call of calls) {
const tx = api.tx(call);
const details = await api.rpc.payment.queryFeeDetails(tx.toHex());
if (details.inclusionFee.isSome) {
const fee = details.inclusionFee.unwrap();
individualTotal += BigInt(fee.baseFee.toString())
+ BigInt(fee.lenFee.toString())
+ BigInt(fee.adjustedWeightFee.toString());
}
}
// Batched fee
const batchTx = api.tx.utility.batchAll(calls);
const batchDetails = await api.rpc.payment.queryFeeDetails(batchTx.toHex());
let batchTotal = 0n;
if (batchDetails.inclusionFee.isSome) {
const fee = batchDetails.inclusionFee.unwrap();
batchTotal = BigInt(fee.baseFee.toString())
+ BigInt(fee.lenFee.toString())
+ BigInt(fee.adjustedWeightFee.toString());
}
const savings = individualTotal - batchTotal;
console.log(`Individual total: ${individualTotal} planck`);
console.log(`Batch total: ${batchTotal} planck`);
console.log(`Savings: ${savings} planck (${Number((savings * 10000n) / individualTotal) / 100}%)`);
return { individualTotal, batchTotal, savings };
}3. Fee Tracking Across Runtime Upgrades
Monitor how fee components change after runtime upgrades to detect regressions:
async function compareFeesBetweenBlocks(api, extrinsicHex, blockHashBefore, blockHashAfter) {
const [before, after] = await Promise.all([
api.rpc.payment.queryFeeDetails(extrinsicHex, blockHashBefore),
api.rpc.payment.queryFeeDetails(extrinsicHex, blockHashAfter)
]);
function extractFees(details) {
if (details.inclusionFee.isNone) return null;
const fee = details.inclusionFee.unwrap();
return {
base: BigInt(fee.baseFee.toString()),
len: BigInt(fee.lenFee.toString()),
weight: BigInt(fee.adjustedWeightFee.toString())
};
}
const feesBefore = extractFees(before);
const feesAfter = extractFees(after);
if (feesBefore && feesAfter) {
console.log('Fee comparison:');
console.log(` Base fee: ${feesBefore.base} -> ${feesAfter.base}`);
console.log(` Length fee: ${feesBefore.len} -> ${feesAfter.len}`);
console.log(` Weight fee: ${feesBefore.weight} -> ${feesAfter.weight}`);
}
}Fee Components Explained
| Component | Source | How It's Calculated | Optimization Strategy |
|---|---|---|---|
| baseFee | ExtrinsicBaseWeight | Fixed cost per extrinsic defined by the runtime | Batch multiple calls into a single extrinsic to pay only one base fee |
| lenFee | TransactionByteFee | encodedLength × lengthToFee coefficient | Minimize encoded extrinsic size by using compact encodings and avoiding large payloads |
| adjustedWeightFee | WeightToFee | Execution weight multiplied by the fee multiplier, which adjusts based on block fullness | Choose lighter operations, submit during low-traffic periods when the multiplier is lower |
Tip multiplier: The adjustedWeightFee is sensitive to network congestion. When blocks are consistently more than half full, the fee multiplier increases, raising the weight fee. During low-traffic periods, the multiplier decreases toward its minimum.
Error Handling
Common errors and solutions:
| Error Code | Description | Solution |
|---|---|---|
| -32602 | Invalid params | Ensure the extrinsic hex string is properly SCALE-encoded with the 0x prefix |
| -32603 | Internal error | The runtime could not compute fees -- verify the extrinsic is valid for the target block |
| -32005 | Rate limit exceeded | Reduce request frequency or implement client-side rate limiting |
| Null inclusionFee | Feeless extrinsic | Inherent extrinsics and some unsigned extrinsics do not pay fees -- this is expected behavior |
Related Methods
payment_queryInfo-- Get the total fee and execution weight for an extrinsic as a single valuestate_call-- CallTransactionPaymentApi_query_fee_detailsdirectly for more controlsystem_properties-- Get token decimals and symbol for human-readable fee displayauthor_submitExtrinsic-- Submit the extrinsic after confirming acceptable feesauthor_submitAndWatchExtrinsic-- Submit and track the extrinsic through finalization
payment_queryInfo
Estimate transaction fees on Asset Hub. Get the weight, dispatch class, and partial fee for an extrinsic before submitting it to the network.
grandpa_roundState
Get the current GRANDPA finality round state on Asset Hub. Monitor consensus progress, validator voting participation, and finality health across the Polkadot's system parachain managing $4.5B+ in DOT tokens, native USDC/USDT, and NFTs network.