From 643bf25a8a5449a00ad8c11bce01b5da6db4f6f4 Mon Sep 17 00:00:00 2001 From: MadReza Date: Tue, 12 Dec 2023 00:54:44 +0330 Subject: [PATCH 1/6] feat: update validation of GasPrice.fromString to allow using ibc denoms as gas denom --- packages/stargate/src/fee.spec.ts | 15 ++++++++++----- packages/stargate/src/fee.ts | 15 +-------------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/stargate/src/fee.spec.ts b/packages/stargate/src/fee.spec.ts index 38736f1770..c2457a2c36 100644 --- a/packages/stargate/src/fee.spec.ts +++ b/packages/stargate/src/fee.spec.ts @@ -30,6 +30,11 @@ describe("GasPrice", () => { "0.14ucoin2": { amount: "0.14", denom: "ucoin2" }, // eslint-disable-next-line @typescript-eslint/naming-convention "0.14FOOBAR": { amount: "0.14", denom: "FOOBAR" }, + "0.01ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2": + { + amount: "0.01", + denom: "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2", + }, }; for (const [input, expected] of Object.entries(inputs)) { const gasPrice = GasPrice.fromString(input); @@ -46,16 +51,16 @@ describe("GasPrice", () => { expect(() => GasPrice.fromString("234")).toThrowError(/Invalid gas price string/i); expect(() => GasPrice.fromString("-234tkn")).toThrowError(/Invalid gas price string/i); // Checks details of - expect(() => GasPrice.fromString("234t")).toThrowError(/denom must be between 3 and 128 characters/i); - expect(() => GasPrice.fromString("234tt")).toThrowError(/denom must be between 3 and 128 characters/i); + expect(() => GasPrice.fromString("234t")).toThrowError(/Invalid gas price string/i); + expect(() => GasPrice.fromString("234tt")).toThrowError(/Invalid gas price string/i); expect(() => GasPrice.fromString( "234ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt", ), - ).toThrowError(/denom must be between 3 and 128 characters/i); + ).toThrowError(/Invalid gas price string/i); // Checks details of - expect(() => GasPrice.fromString("3.utkn")).toThrowError(/Fractional part missing/i); - expect(() => GasPrice.fromString("..utkn")).toThrowError(/More than one separator found/i); + expect(() => GasPrice.fromString("3.utkn")).toThrowError(/Invalid gas price string/i); + expect(() => GasPrice.fromString("..utkn")).toThrowError(/Invalid gas price string/i); }); }); diff --git a/packages/stargate/src/fee.ts b/packages/stargate/src/fee.ts index 3f210e9f56..a1332dd9c8 100644 --- a/packages/stargate/src/fee.ts +++ b/packages/stargate/src/fee.ts @@ -2,18 +2,6 @@ import { StdFee } from "@cosmjs/amino"; import { Decimal, Uint53 } from "@cosmjs/math"; import { coins } from "@cosmjs/proto-signing"; -/** - * Denom checker for the Cosmos SDK 0.42 denom pattern - * (https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/types/coin.go#L599-L601). - * - * This is like a regexp but with helpful error messages. - */ -function checkDenom(denom: string): void { - if (denom.length < 3 || denom.length > 128) { - throw new Error("Denom must be between 3 and 128 characters"); - } -} - /** * A gas price, i.e. the price of a single unit of gas. This is typically a fraction of * the smallest fee token unit, such as 0.012utoken. @@ -37,12 +25,11 @@ export class GasPrice { */ public static fromString(gasPrice: string): GasPrice { // Use Decimal.fromUserInput and checkDenom for detailed checks and helpful error messages - const matchResult = gasPrice.match(/^([0-9.]+)([a-z][a-z0-9]*)$/i); + const matchResult = gasPrice.match(/^(\d+(?:\.\d+)?|\.\d+)([a-zA-Z][a-zA-Z0-9/:._-]{2,127})$/i); if (!matchResult) { throw new Error("Invalid gas price string"); } const [_, amount, denom] = matchResult; - checkDenom(denom); const fractionalDigits = 18; const decimalAmount = Decimal.fromUserInput(amount, fractionalDigits); return new GasPrice(decimalAmount, denom); From 43aaed0410bfeb16168c9d061b0362aa0e3cebb8 Mon Sep 17 00:00:00 2001 From: MadReza Date: Tue, 12 Dec 2023 01:05:17 +0330 Subject: [PATCH 2/6] docs: add changelog entry --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ef77990d1..e1fc4320db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ and this project adheres to [#1516]: https://github.com/cosmos/cosmjs/pull/1516 +### Changed + +- @cosmjs/stargate: Update validation of GasPrice.fromString to allow using ibc denoms as gas denom ([#1522]) + +[#1522]: https://github.com/cosmos/cosmjs/pull/1522 + ## [0.32.0] - 2023-11-23 ### Added From 8ca4560b6e3a0703eb1a29098dfd6e5552e7bd34 Mon Sep 17 00:00:00 2001 From: MadReza Date: Mon, 18 Dec 2023 21:54:36 +0330 Subject: [PATCH 3/6] fix: bring back the denom length validation out of regex --- packages/stargate/src/fee.spec.ts | 10 +++++----- packages/stargate/src/fee.ts | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/stargate/src/fee.spec.ts b/packages/stargate/src/fee.spec.ts index c2457a2c36..ec0839f367 100644 --- a/packages/stargate/src/fee.spec.ts +++ b/packages/stargate/src/fee.spec.ts @@ -51,16 +51,16 @@ describe("GasPrice", () => { expect(() => GasPrice.fromString("234")).toThrowError(/Invalid gas price string/i); expect(() => GasPrice.fromString("-234tkn")).toThrowError(/Invalid gas price string/i); // Checks details of - expect(() => GasPrice.fromString("234t")).toThrowError(/Invalid gas price string/i); - expect(() => GasPrice.fromString("234tt")).toThrowError(/Invalid gas price string/i); + expect(() => GasPrice.fromString("234t")).toThrowError(/denom must be between 3 and 128 characters/i); + expect(() => GasPrice.fromString("234tt")).toThrowError(/denom must be between 3 and 128 characters/i); expect(() => GasPrice.fromString( "234ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt", ), - ).toThrowError(/Invalid gas price string/i); + ).toThrowError(/denom must be between 3 and 128 characters/i); // Checks details of - expect(() => GasPrice.fromString("3.utkn")).toThrowError(/Invalid gas price string/i); - expect(() => GasPrice.fromString("..utkn")).toThrowError(/Invalid gas price string/i); + expect(() => GasPrice.fromString("3.utkn")).toThrowError(/Fractional part missing/i); + expect(() => GasPrice.fromString("..utkn")).toThrowError(/More than one separator found/i); }); }); diff --git a/packages/stargate/src/fee.ts b/packages/stargate/src/fee.ts index a1332dd9c8..9ca8682a44 100644 --- a/packages/stargate/src/fee.ts +++ b/packages/stargate/src/fee.ts @@ -2,6 +2,18 @@ import { StdFee } from "@cosmjs/amino"; import { Decimal, Uint53 } from "@cosmjs/math"; import { coins } from "@cosmjs/proto-signing"; +/** + * Denom checker for the Cosmos SDK 0.42 denom pattern + * (https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/types/coin.go#L599-L601). + * + * This is like a regexp but with helpful error messages. + */ +function checkDenom(denom: string): void { + if (denom.length < 3 || denom.length > 128) { + throw new Error("Denom must be between 3 and 128 characters"); + } +} + /** * A gas price, i.e. the price of a single unit of gas. This is typically a fraction of * the smallest fee token unit, such as 0.012utoken. @@ -25,11 +37,12 @@ export class GasPrice { */ public static fromString(gasPrice: string): GasPrice { // Use Decimal.fromUserInput and checkDenom for detailed checks and helpful error messages - const matchResult = gasPrice.match(/^(\d+(?:\.\d+)?|\.\d+)([a-zA-Z][a-zA-Z0-9/:._-]{2,127})$/i); + const matchResult = gasPrice.match(/^([0-9.]+)([a-zA-Z][a-zA-Z0-9/:._-]*)$/i); if (!matchResult) { throw new Error("Invalid gas price string"); } const [_, amount, denom] = matchResult; + checkDenom(denom); const fractionalDigits = 18; const decimalAmount = Decimal.fromUserInput(amount, fractionalDigits); return new GasPrice(decimalAmount, denom); From 075b54cc89556271a2dee34780232bc0b422dbb7 Mon Sep 17 00:00:00 2001 From: MadReza Date: Tue, 19 Dec 2023 14:21:16 +0330 Subject: [PATCH 4/6] fix: make the gas price regex case sensitive --- packages/stargate/src/fee.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stargate/src/fee.ts b/packages/stargate/src/fee.ts index 9ca8682a44..21c3c5c28b 100644 --- a/packages/stargate/src/fee.ts +++ b/packages/stargate/src/fee.ts @@ -37,7 +37,7 @@ export class GasPrice { */ public static fromString(gasPrice: string): GasPrice { // Use Decimal.fromUserInput and checkDenom for detailed checks and helpful error messages - const matchResult = gasPrice.match(/^([0-9.]+)([a-zA-Z][a-zA-Z0-9/:._-]*)$/i); + const matchResult = gasPrice.match(/^([0-9.]+)([a-zA-Z][a-zA-Z0-9/:._-]*)$/); if (!matchResult) { throw new Error("Invalid gas price string"); } From fb20b926646f32d28c6f7d4cc083771f4fa79177 Mon Sep 17 00:00:00 2001 From: MadReza Date: Tue, 19 Dec 2023 14:27:44 +0330 Subject: [PATCH 5/6] docs: update changelog --- CHANGELOG.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1fc4320db..e38886d06f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to ## [Unreleased] +### Changed + +- @cosmjs/stargate: Update validation of GasPrice.fromString to allow using ibc denoms as gas denom ([#1522]) + +[#1522]: https://github.com/cosmos/cosmjs/pull/1522 + ## [0.32.1] - 2023-12-04 ### Fixed @@ -17,12 +23,6 @@ and this project adheres to [#1516]: https://github.com/cosmos/cosmjs/pull/1516 -### Changed - -- @cosmjs/stargate: Update validation of GasPrice.fromString to allow using ibc denoms as gas denom ([#1522]) - -[#1522]: https://github.com/cosmos/cosmjs/pull/1522 - ## [0.32.0] - 2023-11-23 ### Added From a752cd8ac0601b5faa2775fd4598d6c62b8c5970 Mon Sep 17 00:00:00 2001 From: MadReza Date: Tue, 19 Dec 2023 14:51:37 +0330 Subject: [PATCH 6/6] fix: lint --- packages/stargate/src/fee.spec.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/stargate/src/fee.spec.ts b/packages/stargate/src/fee.spec.ts index ec0839f367..a8ca0fc026 100644 --- a/packages/stargate/src/fee.spec.ts +++ b/packages/stargate/src/fee.spec.ts @@ -30,11 +30,10 @@ describe("GasPrice", () => { "0.14ucoin2": { amount: "0.14", denom: "ucoin2" }, // eslint-disable-next-line @typescript-eslint/naming-convention "0.14FOOBAR": { amount: "0.14", denom: "FOOBAR" }, - "0.01ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2": - { - amount: "0.01", - denom: "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2", - }, + "0.01ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2": { + amount: "0.01", + denom: "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2", + }, }; for (const [input, expected] of Object.entries(inputs)) { const gasPrice = GasPrice.fromString(input);