From 186cdb171865fa4a3ee25258a4536d99798ec7f4 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 15 Sep 2022 09:34:59 +0200 Subject: [PATCH] Remove uint64 range limit from parseCoins --- CHANGELOG.md | 3 +++ packages/amino/src/coins.spec.ts | 23 +++++++++++++++++++++++ packages/amino/src/coins.ts | 5 +++-- packages/proto-signing/src/coins.spec.ts | 23 +++++++++++++++++++++++ packages/proto-signing/src/coins.ts | 3 +-- 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9324f8..b2ce9142 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,11 +55,14 @@ and this project adheres to - @cosmjs/tendermint-rpc: Fix `key` and `value` type in `RpcAbciQueryResponse` to also include the `null` option. - @cosmjs/tendermint-rpc: Fix decoding events without attributes ([#1198]). +- @cosmjs/amino, @cosmjs/proto-signing: Support amounts larger than the uint64 + range in `parseCoins` ([#1268]). [#1170]: https://github.com/cosmos/cosmjs/issues/1170 [#1177]: https://github.com/cosmos/cosmjs/issues/1177 [#1188]: https://github.com/cosmos/cosmjs/pull/1188 [#1198]: https://github.com/cosmos/cosmjs/pull/1198 +[#1268]: https://github.com/cosmos/cosmjs/issues/1268 ### Changed diff --git a/packages/amino/src/coins.spec.ts b/packages/amino/src/coins.spec.ts index 24c8927b..4e36dce7 100644 --- a/packages/amino/src/coins.spec.ts +++ b/packages/amino/src/coins.spec.ts @@ -121,6 +121,29 @@ describe("coins", () => { ]); }); + it("works for large numbers", () => { + expect(parseCoins(`${Number.MAX_SAFE_INTEGER}ureef`)).toEqual([ + { + amount: "9007199254740991", + denom: "ureef", + }, + ]); + // 2**64-1 + expect(parseCoins("18446744073709551615ureef")).toEqual([ + { + amount: "18446744073709551615", + denom: "ureef", + }, + ]); + // 2**128-1 + expect(parseCoins("340282366920938463463374607431768211455ureef")).toEqual([ + { + amount: "340282366920938463463374607431768211455", + denom: "ureef", + }, + ]); + }); + it("ignores empty elements", () => { // start expect(parseCoins(",819966000ucosm,700000000ustake")).toEqual([ diff --git a/packages/amino/src/coins.ts b/packages/amino/src/coins.ts index 23a6ae22..a8faa098 100644 --- a/packages/amino/src/coins.ts +++ b/packages/amino/src/coins.ts @@ -1,4 +1,5 @@ -import { Decimal, Uint53, Uint64 } from "@cosmjs/math"; +import { Decimal, Uint53 } from "@cosmjs/math"; + export interface Coin { readonly denom: string; readonly amount: string; @@ -62,7 +63,7 @@ export function parseCoins(input: string): Coin[] { const match = part.match(/^([0-9]+)([a-zA-Z]+)/); if (!match) throw new Error("Got an invalid coin string"); return { - amount: Uint64.fromString(match[1]).toString(), + amount: match[1].replace(/^0+/, "") || "0", denom: match[2], }; }); diff --git a/packages/proto-signing/src/coins.spec.ts b/packages/proto-signing/src/coins.spec.ts index e2de707b..b8ef7a41 100644 --- a/packages/proto-signing/src/coins.spec.ts +++ b/packages/proto-signing/src/coins.spec.ts @@ -73,6 +73,29 @@ describe("coins", () => { ]); }); + it("works for large numbers", () => { + expect(parseCoins(`${Number.MAX_SAFE_INTEGER}ureef`)).toEqual([ + { + amount: "9007199254740991", + denom: "ureef", + }, + ]); + // 2**64-1 + expect(parseCoins("18446744073709551615ureef")).toEqual([ + { + amount: "18446744073709551615", + denom: "ureef", + }, + ]); + // 2**128-1 + expect(parseCoins("340282366920938463463374607431768211455ureef")).toEqual([ + { + amount: "340282366920938463463374607431768211455", + denom: "ureef", + }, + ]); + }); + it("works for two", () => { expect(parseCoins("819966000ucosm,700000000ustake")).toEqual([ { diff --git a/packages/proto-signing/src/coins.ts b/packages/proto-signing/src/coins.ts index 0a8a7bac..0c85c6ac 100644 --- a/packages/proto-signing/src/coins.ts +++ b/packages/proto-signing/src/coins.ts @@ -1,5 +1,4 @@ import { Coin } from "@cosmjs/amino"; -import { Uint64 } from "@cosmjs/math"; /** * Takes a coins list like "819966000ucosm,700000000ustake" and parses it. @@ -17,7 +16,7 @@ export function parseCoins(input: string): Coin[] { const match = part.match(/^([0-9]+)([a-zA-Z][a-zA-Z0-9/]{2,127})$/); if (!match) throw new Error("Got an invalid coin string"); return { - amount: Uint64.fromString(match[1]).toString(), + amount: match[1].replace(/^0+/, "") || "0", denom: match[2], }; });