Merge pull request #845 from cosmos/parseCoins-Stargate

Add Stargate-ready parseCoins
This commit is contained in:
Simon Warta 2021-07-22 09:34:44 +02:00 committed by GitHub
commit f2f2b3555c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 156 additions and 1 deletions

View File

@ -15,6 +15,8 @@ and this project adheres to
for Tendermint v0.33. for Tendermint v0.33.
- @cosmjs/tendermint-rpc: Exports relating to `Tendermint33Client` are now - @cosmjs/tendermint-rpc: Exports relating to `Tendermint33Client` are now
available under `tendermint33`. available under `tendermint33`.
- @cosmjs/proto-signing and @cosmjs/stargate: Create a Stargate-ready
`parseCoins` that replaces the `parseCoins` re-export from `@cosmjs/amino`.
### Changed ### Changed

View File

@ -21,6 +21,14 @@ export function coins(amount: number, denom: string): Coin[] {
/** /**
* Takes a coins list like "819966000ucosm,700000000ustake" and parses it. * Takes a coins list like "819966000ucosm,700000000ustake" and parses it.
*
* A Stargate-ready variant of this function is available via:
*
* ```
* import { parseCoins } from "@cosmjs/proto-signing";
* // or
* import { parseCoins } from "@cosmjs/stargate";
* ```
*/ */
export function parseCoins(input: string): Coin[] { export function parseCoins(input: string): Coin[] {
return input return input

View File

@ -0,0 +1,120 @@
import { parseCoins } from "./coins";
describe("coins", () => {
describe("parseCoins", () => {
it("works for empty", () => {
expect(parseCoins("")).toEqual([]);
});
it("works for one element", () => {
expect(parseCoins("7643ureef")).toEqual([
{
amount: "7643",
denom: "ureef",
},
]);
});
it("works for various denoms", () => {
// very short (3)
expect(parseCoins("7643bar")).toEqual([
{
amount: "7643",
denom: "bar",
},
]);
// very long (128)
expect(
parseCoins(
"7643abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh",
),
).toEqual([
{
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",
},
]);
});
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([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
// middle
expect(parseCoins("819966000ucosm,,700000000ustake")).toEqual([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
// end
expect(parseCoins("819966000ucosm,700000000ustake,")).toEqual([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
});
it("throws for invalid inputs", () => {
// denom missing
expect(() => parseCoins("3456")).toThrowError(/invalid coin string/i);
// 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);
});
});
});

View File

@ -0,0 +1,24 @@
import { Coin } from "@cosmjs/amino";
import { Uint64 } from "@cosmjs/math";
/**
* Takes a coins list like "819966000ucosm,700000000ustake" and parses it.
*
* This is a Stargate ready version of parseCoins from @cosmjs/amino and @cosmjs/launchpad.
* It supports more denoms.
*/
export function parseCoins(input: string): Coin[] {
return input
.replace(/\s/g, "")
.split(",")
.filter(Boolean)
.map((part) => {
// 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: Uint64.fromString(match[1]).toString(),
denom: match[2],
};
});
}

View File

@ -1,6 +1,7 @@
// This type happens to be shared between Amino and Direct sign modes // This type happens to be shared between Amino and Direct sign modes
export { Coin, coin, coins, parseCoins } from "@cosmjs/amino"; export { Coin, coin, coins } from "@cosmjs/amino";
export { parseCoins } from "./coins";
export { decodeTxRaw, DecodedTxRaw } from "./decode"; export { decodeTxRaw, DecodedTxRaw } from "./decode";
export { export {
DecodeObject, DecodeObject,