payment_queryFeeDetails - Kusama RPC Method
Get a detailed fee breakdown for an extrinsic on Kusama. Analyze base fee, length fee, and adjusted weight fee components to optimize transaction costs for parachain experimentation, early feature deployment, and production-grade testing with real value.
Returns a detailed breakdown of the inclusion fee for a given extrinsic on Kusama. 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 Kusama? Build on Polkadot's canary network for real-world testing with live economic conditions with 7-day governance cycles (vs 1 month on Polkadot), lower bonding requirements, live KSM token economy, and first-to-market feature testing.
When to Use This Method
payment_queryFeeDetails is essential for experimental dApp developers, parachain teams, and early adopters validating new features:
- Fee Optimization -- Identify which fee component dominates your transaction cost and optimize accordingly on Kusama
- Transaction Cost Analysis -- Build detailed cost breakdowns for parachain experimentation, early feature deployment, and production-grade testing with real value, 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://kusama-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://kusama-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 Kusama. 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 Kusama. Monitor consensus progress, validator voting participation, and finality health across the Polkadot's canary network for real-world testing with live economic conditions network.