Skip to content

add dynamic gasfee pricing as a signing client option - Feemarket/Osmosis#1911

Closed
ertemann wants to merge 10 commits intocosmos:mainfrom
ertemann:add-feemarket-auto
Closed

add dynamic gasfee pricing as a signing client option - Feemarket/Osmosis#1911
ertemann wants to merge 10 commits intocosmos:mainfrom
ertemann:add-feemarket-auto

Conversation

@ertemann
Copy link

@ertemann ertemann commented Nov 18, 2025

Summary

Adds automatic gas price discovery for chains with dynamic feemarket modules (Osmosis EIP-1559 and Skip feemarket). Instead of manually setting static gas prices, CosmJS can now query current prices from the chain, preventing transaction failures from outdated pricing.

Changes

  • New feemarket.ts: Query dynamic gas prices from Osmosis EIP-1559 and Skip feemarket modules
  • Updated clients: SigningStargateClient and SigningCosmWasmClient now support DynamicGasPriceConfig
  • Refactoring: Extracted calculateFeeForTransaction() helper
  • Tests: Some unit tests and an end-to-end validation on Osmosis and Neutron testnets

Usage

const client = await SigningStargateClient.connectWithSigner(rpc, signer, {
  gasPrice: {
    denom: "uosmo",
    multiplier: 1.3,
    minGasPrice: GasPrice.fromString("0.0025uosmo"),
    maxGasPrice: GasPrice.fromString("0.1uosmo"),
  }
});

// Gas price queried automatically per transaction
await client.signAndBroadcast(address, messages, "auto");

Features

Graceful fallback to minGasPrice if feemarket query fails
Min/max constraint enforcement with configurable multiplier
backward compatible - existing code unchanged
Automatic chain detection for Osmosis variants

Inspired by Hermes relayer PR #4004.

@ertemann ertemann changed the title add dynamic gasfee pricing as an option through feemarket and osmosis… add dynamic gasfee pricing as a signing client option - Feemarket/Osmosis Nov 18, 2025
@@ -0,0 +1,278 @@
#!/usr/bin/env node
Copy link
Author

Choose a reason for hiding this comment

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

Just a complete integration test to validate the PR, can be removed once merged

Copy link
Author

Choose a reason for hiding this comment

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

anywhere this should be housed @webmaster128 ?

Copy link
Contributor

Choose a reason for hiding this comment

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

No idea to be honest. We don't have example scripts in here usually. For now it can just be there

@ertemann ertemann marked this pull request as draft November 18, 2025 15:00
@ertemann ertemann marked this pull request as ready for review November 18, 2025 20:10
Copy link
Contributor

@webmaster128 webmaster128 left a comment

Choose a reason for hiding this comment

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

Nice stuff. Some first thoughts here

const product = (BigInt(normalizedValue.atomics) * BigInt(multiplierDecimal.atomics)) / factor;

return Decimal.fromAtomics(product.toString(), fractionalDigits);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This implementation might be correct. But as we do not need decimal math here we can also use float math more or less like this:

const x = value.toFloatApproximation() * multiplier; // the value we want

// now convert x to Decimal

Now exactly as the Decimal API is limited but I think you get the idea

Copy link
Author

Choose a reason for hiding this comment

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

do you prefer float math? current impl works and is precise and testable so kept it for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah that's fine. The reason I brought it up is you have a float -> Decimal conversion in here which is not necessarily safe:

const multiplierDecimal = Decimal.fromUserInput(multiplier.toString(), fractionalDigits);

As there are many number string representatations which are not supported by the Decimal constructor. E.g.

> a = 1/10**15
1e-15
> typeof a
'number'
> a.toString()
'1e-15'

Copy link
Contributor

Choose a reason for hiding this comment

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

I think using https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed gives us better strings in most cases and reduces the likelihood of errors here.

@ertemann
Copy link
Author

Thanks for the comments @webmaster128 will resolve remaining issues tomorrow, didnt have time this week yet.

@ertemann
Copy link
Author

changes made, ready for merge.

@webmaster128
Copy link
Contributor

The commit cab1af0 contains copies of a lot of dependencies. This is not needed and should not be done. Did you setup git-lfs? See also https://github.com/cosmos/cosmjs/blob/main/HACKING.md#checking-out-code. We need to ensure the code changes in here are separate from those things.

@webmaster128
Copy link
Contributor

The last commit (the uncommitted dependency change) is not needed. See #1922

@ertemann
Copy link
Author

The commit cab1af0 contains copies of a lot of dependencies. This is not needed and should not be done. Did you setup git-lfs? See also main/HACKING.md#checking-out-code. We need to ensure the code changes in here are separate from those things.

The commits here are simply the result of a yarn install, if that is not correct then id suggest you do it however you want it but I don't see what there is to fix for me.

I have reset the yarn cache to main, with that state i cannot locally build this change.

@webmaster128
Copy link
Contributor

Looks good overall, thank you. I will take care of linting and stuff to make CI happy tomorrow and then merge it

Copy link
Contributor

@webmaster128 webmaster128 left a comment

Choose a reason for hiding this comment

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

Alsright cool, thanks.

I habe a follow-up PR in #1926 including your work and a bunch of improvements. I could not use the existing PRs because of all of the cache related changed. I tried but rebasing was impossible. This happens when git-lfs is not set up during the work. Then the cache files change from pointers to full git blobs and this creates a bit mess. Super annoying, I know. But using the .diff it was no problem.

}
if (
!(gasPriceConfig instanceof GasPrice) &&
!("amount" in gasPriceConfig && "denom" in gasPriceConfig)
Copy link
Contributor

Choose a reason for hiding this comment

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

An object with {amount: "1234", denom: "blub"} was never a valid input. Maybe it worked though. So I'll just change this to an assertion assert(gasPriceConfig instanceof GasPrice).

const product = (BigInt(normalizedValue.atomics) * BigInt(multiplierDecimal.atomics)) / factor;

return Decimal.fromAtomics(product.toString(), fractionalDigits);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think using https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed gives us better strings in most cases and reduces the likelihood of errors here.

@@ -0,0 +1,278 @@
#!/usr/bin/env node
Copy link
Contributor

Choose a reason for hiding this comment

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

No idea to be honest. We don't have example scripts in here usually. For now it can just be there

@webmaster128 webmaster128 added this to the 0.38 milestone Dec 18, 2025
webmaster128 added a commit that referenced this pull request Dec 18, 2025
@ertemann
Copy link
Author

thanks for taking it over the line, hadnt worked with committing cache before and the issues it creates.

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.

2 participants