Skip to content

Commit

Permalink
Add IBC denom support to parseCoins from @cosmjs/amino
Browse files Browse the repository at this point in the history
  • Loading branch information
webmaster128 committed Feb 10, 2024
1 parent 49053d0 commit 4c9d929
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 204 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ and this project adheres to

## [Unreleased]

### Changed

- @cosmjs/amino: Add IBC denom support to `parseCoins` and use the same
implementation in all those imports:

```ts
import { parseCoins } from "@cosmjs/proto-signing";
// equals
import { parseCoins } from "@cosmjs/stargate";
// equals
import { parseCoins } from "@cosmjs/amino";
```

## [0.32.2] - 2023-12-19

### Fixed
Expand Down
57 changes: 51 additions & 6 deletions packages/amino/src/coins.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,33 @@ describe("coins", () => {
]);
});

it("works for two", () => {
expect(parseCoins("819966000ucosm,700000000ustake")).toEqual([
it("works for various denoms", () => {
// very short (3)
expect(parseCoins("7643bar")).toEqual([
{
amount: "819966000",
denom: "ucosm",
amount: "7643",
denom: "bar",
},
]);

// very long (128)
expect(
parseCoins(
"7643abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh",
),
).toEqual([
{
amount: "700000000",
denom: "ustake",
amount: "7643",
denom:
"abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh",
},
]);

// IBC denom (https://github.com/cosmos/cosmos-sdk/blob/v0.42.7/types/coin_test.go#L512-L519)
expect(parseCoins("7643ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2")).toEqual([
{
amount: "7643",
denom: "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2",
},
]);
});
Expand Down Expand Up @@ -144,6 +162,19 @@ describe("coins", () => {
]);
});

it("works for two", () => {
expect(parseCoins("819966000ucosm,700000000ustake")).toEqual([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
});

it("ignores empty elements", () => {
// start
expect(parseCoins(",819966000ucosm,700000000ustake")).toEqual([
Expand Down Expand Up @@ -186,6 +217,20 @@ describe("coins", () => {

// amount missing
expect(() => parseCoins("ucosm")).toThrowError(/invalid coin string/i);

// denom starting with slash
expect(() => parseCoins("3456/ibc")).toThrowError(/invalid coin string/i);

// denom too short
expect(() => parseCoins("3456a")).toThrowError(/invalid coin string/i);
expect(() => parseCoins("3456aa")).toThrowError(/invalid coin string/i);

// denom too long
expect(() =>
parseCoins(
"3456abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgha",
),
).toThrowError(/invalid coin string/i);
});
});

Expand Down
15 changes: 12 additions & 3 deletions packages/amino/src/coins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,30 @@ export function coins(amount: number | string, denom: string): Coin[] {
/**
* Takes a coins list like "819966000ucosm,700000000ustake" and parses it.
*
* A Stargate-ready variant of this function is available via:
* Starting with CosmJS 0.32.3, the following imports are all synonym and support
* a variety of denom types such as IBC denoms or tokenfactory. If you need to
* restrict the denom to something very minimal, this needs to be implemented
* separately in the caller.
*
* ```
* import { parseCoins } from "@cosmjs/proto-signing";
* // or
* // equals
* import { parseCoins } from "@cosmjs/stargate";
* // equals
* import { parseCoins } from "@cosmjs/amino";
* ```
*
* This function is not made for supporting decimal amounts and does not support
* parsing gas prices.
*/
export function parseCoins(input: string): Coin[] {
return input
.replace(/\s/g, "")
.split(",")
.filter(Boolean)
.map((part) => {
const match = part.match(/^([0-9]+)([a-zA-Z]+)/);
// Denom regex from Stargate (https://github.com/cosmos/cosmos-sdk/blob/v0.42.7/types/coin.go#L599-L601)
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: match[1].replace(/^0+/, "") || "0",
Expand Down
170 changes: 0 additions & 170 deletions packages/proto-signing/src/coins.spec.ts

This file was deleted.

23 changes: 0 additions & 23 deletions packages/proto-signing/src/coins.ts

This file was deleted.

5 changes: 3 additions & 2 deletions packages/proto-signing/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// This type happens to be shared between Amino and Direct sign modes
export { parseCoins } from "./coins";
export { DecodedTxRaw, decodeTxRaw } from "./decode";
export {
DirectSecp256k1HdWallet,
Expand Down Expand Up @@ -31,4 +30,6 @@ export {
} from "./signer";
export { makeAuthInfoBytes, makeSignBytes, makeSignDoc } from "./signing";
export { executeKdf, KdfConfiguration } from "./wallet";
export { Coin, coin, coins } from "@cosmjs/amino";

// re-exports
export { Coin, coin, coins, parseCoins } from "@cosmjs/amino";

0 comments on commit 4c9d929

Please sign in to comment.