From c3eae7c28ae7f4b2c4dba77d5472fbd6ace72e39 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 13 Jan 2022 19:01:04 +0100 Subject: [PATCH] Add fromBinary/toBinary --- CHANGELOG.md | 6 ++ .../cosmwasm-stargate/src/encoding.spec.ts | 99 +++++++++++++++++++ packages/cosmwasm-stargate/src/encoding.ts | 21 ++++ packages/cosmwasm-stargate/src/index.ts | 1 + 4 files changed, 127 insertions(+) create mode 100644 packages/cosmwasm-stargate/src/encoding.spec.ts create mode 100644 packages/cosmwasm-stargate/src/encoding.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index b7b18b31ed..b5f1c16539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to ## [Unreleased] +### Added + +- @cosmjs/cosmwasm-stargate: Add `fromBinary`/`toBinary` to convert between + JavaScript objects and the JSON representation of `cosmwasm_std::Binary` + (base64). + ## [0.27.0] - 2022-01-10 ### Added diff --git a/packages/cosmwasm-stargate/src/encoding.spec.ts b/packages/cosmwasm-stargate/src/encoding.spec.ts new file mode 100644 index 0000000000..9633311489 --- /dev/null +++ b/packages/cosmwasm-stargate/src/encoding.spec.ts @@ -0,0 +1,99 @@ +import { fromBinary, toBinary } from "./encoding"; + +describe("encoding", () => { + describe("toBinary", () => { + it("works for objects", () => { + // echo -n "{}" | base64 + expect(toBinary({})).toEqual("e30="); + + // echo -n '{"swap":{"max_spread":"0.25"}}' | base64 + // eslint-disable-next-line @typescript-eslint/naming-convention + expect(toBinary({ swap: { max_spread: "0.25" } })).toEqual("eyJzd2FwIjp7Im1heF9zcHJlYWQiOiIwLjI1In19"); + + // echo -n '{"num":3.45,"null":null,"bool":true,"obj":{"str":"bar"}}' | base64 + expect( + toBinary({ num: 3.45, null: null, bool: true, obj: { str: "bar" }, omitted: undefined }), + ).toEqual("eyJudW0iOjMuNDUsIm51bGwiOm51bGwsImJvb2wiOnRydWUsIm9iaiI6eyJzdHIiOiJiYXIifX0="); + }); + + it("works for strings", () => { + // echo -n '""' | base64 + expect(toBinary("")).toEqual("IiI="); + + // echo -n '"hi"' | base64 + expect(toBinary("hi")).toEqual("ImhpIg=="); + }); + + it("works for arrays", () => { + // echo -n '[]' | base64 + expect(toBinary([])).toEqual("W10="); + + // echo -n '[1,2,3]' | base64 + expect(toBinary([1, 2, 3])).toEqual("WzEsMiwzXQ=="); + }); + + it("works for booleans", () => { + // echo -n 'true' | base64 + expect(toBinary(true)).toEqual("dHJ1ZQ=="); + }); + + it("works for numbers", () => { + // echo -n '12.21' | base64 + expect(toBinary(12.21)).toEqual("MTIuMjE="); + }); + + it("works for null", () => { + // echo -n 'null' | base64 + expect(toBinary(null)).toEqual("bnVsbA=="); + }); + }); + + describe("fromBinary", () => { + it("works for objects", () => { + // echo -n "{}" | base64 + expect(fromBinary("e30=")).toEqual({}); + + // echo -n '{"swap":{"max_spread":"0.25"}}' | base64 + expect(fromBinary("eyJzd2FwIjp7Im1heF9zcHJlYWQiOiIwLjI1In19")).toEqual({ + // eslint-disable-next-line @typescript-eslint/naming-convention + swap: { max_spread: "0.25" }, + }); + + // echo -n '{"num":3.45,"null":null,"bool":true,"obj":{"str":"bar"}}' | base64 + expect( + fromBinary("eyJudW0iOjMuNDUsIm51bGwiOm51bGwsImJvb2wiOnRydWUsIm9iaiI6eyJzdHIiOiJiYXIifX0="), + ).toEqual({ num: 3.45, null: null, bool: true, obj: { str: "bar" } }); + }); + + it("works for strings", () => { + // echo -n '""' | base64 + expect(fromBinary("IiI=")).toEqual(""); + + // echo -n '"hi"' | base64 + expect(fromBinary("ImhpIg==")).toEqual("hi"); + }); + + it("works for arrays", () => { + // echo -n '[]' | base64 + expect(fromBinary("W10=")).toEqual([]); + + // echo -n '[1,2,3]' | base64 + expect(fromBinary("WzEsMiwzXQ==")).toEqual([1, 2, 3]); + }); + + it("works for booleans", () => { + // echo -n 'true' | base64 + expect(fromBinary("dHJ1ZQ==")).toEqual(true); + }); + + it("works for numbers", () => { + // echo -n '12.21' | base64 + expect(fromBinary("MTIuMjE=")).toEqual(12.21); + }); + + it("works for null", () => { + // echo -n 'null' | base64 + expect(fromBinary("bnVsbA==")).toEqual(null); + }); + }); +}); diff --git a/packages/cosmwasm-stargate/src/encoding.ts b/packages/cosmwasm-stargate/src/encoding.ts new file mode 100644 index 0000000000..a8f6cb13f0 --- /dev/null +++ b/packages/cosmwasm-stargate/src/encoding.ts @@ -0,0 +1,21 @@ +import { fromBase64, fromUtf8, toBase64, toUtf8 } from "@cosmjs/encoding"; + +/** + * Takes a value, serializes it to JSON and encodes it as base64. + * + * This can be used for creating values of fields that have the CosmWasm Binary type. + */ +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function toBinary(obj: any): string { + return toBase64(toUtf8(JSON.stringify(obj))); +} + +/** + * Takes a base64 string, decodes it and parses the content from JSON to an object. + * + * This can be used for parsing the values of a CosmWasm Binary field. + */ +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function fromBinary(base64: string): any { + return JSON.parse(fromUtf8(fromBase64(base64))); +} diff --git a/packages/cosmwasm-stargate/src/index.ts b/packages/cosmwasm-stargate/src/index.ts index cdf132d240..efb918379e 100644 --- a/packages/cosmwasm-stargate/src/index.ts +++ b/packages/cosmwasm-stargate/src/index.ts @@ -21,6 +21,7 @@ export { MsgStoreCodeEncodeObject, MsgUpdateAdminEncodeObject, } from "./encodeobjects"; +export { fromBinary, toBinary } from "./encoding"; export { ChangeAdminResult, ExecuteResult,