From 7a459c537af7c37fc8e28844bc762518ddb5a8b9 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sun, 9 Aug 2020 14:35:26 +0200 Subject: [PATCH] Add omitDefault implementation --- packages/proto-signing/src/adr27.spec.ts | 50 ++++++++++++++++++++++ packages/proto-signing/src/adr27.ts | 19 ++++++++ packages/proto-signing/src/signing.spec.ts | 13 +++--- packages/proto-signing/types/adr27.d.ts | 7 +++ 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 packages/proto-signing/src/adr27.spec.ts create mode 100644 packages/proto-signing/src/adr27.ts create mode 100644 packages/proto-signing/types/adr27.d.ts diff --git a/packages/proto-signing/src/adr27.spec.ts b/packages/proto-signing/src/adr27.spec.ts new file mode 100644 index 00000000..785cb43c --- /dev/null +++ b/packages/proto-signing/src/adr27.spec.ts @@ -0,0 +1,50 @@ +import { fromHex } from "@cosmjs/encoding"; +import { parse } from "protobufjs"; + +import { omitDefault } from "./adr27"; + +describe("adr27", () => { + describe("omitDefault", () => { + it("works for strings", () => { + expect(omitDefault("abc")).toEqual("abc"); + expect(omitDefault("")).toEqual(null); + }); + + it("works for bytes", () => { + expect(omitDefault(fromHex("ab"))).toEqual(fromHex("ab")); + expect(omitDefault(fromHex(""))).toEqual(null); + }); + + it("works for integers", () => { + expect(omitDefault(123)).toEqual(123); + expect(omitDefault(0)).toEqual(null); + }); + + it("works for floats", () => { + expect(omitDefault(1.234)).toEqual(1.234); + expect(omitDefault(0.0)).toEqual(null); + }); + + it("works for repeaded", () => { + expect(omitDefault(["a", "b", "c"])).toEqual(["a", "b", "c"]); + expect(omitDefault([])).toEqual(null); + }); + + it("works for enums", () => { + const proto = ` + package blog; + syntax = "proto3"; + + enum Review { + UNSPECIFIED = 0; + ACCEPTED = 1; + REJECTED = 2; + }; + `; + // eslint-disable-next-line @typescript-eslint/naming-convention + const Review = parse(proto).root.lookupEnum("blog.Review"); + expect(omitDefault(Review.values["ACCEPTED"])).toEqual(Review.values["ACCEPTED"]); + expect(omitDefault(Review.values["UNSPECIFIED"])).toEqual(null); + }); + }); +}); diff --git a/packages/proto-signing/src/adr27.ts b/packages/proto-signing/src/adr27.ts new file mode 100644 index 00000000..22a57df9 --- /dev/null +++ b/packages/proto-signing/src/adr27.ts @@ -0,0 +1,19 @@ +import { isUint8Array } from "@cosmjs/utils"; + +/** + * Converts default values to null in order to tell protobuf.js + * to not serialize them. + * + * @see https://github.com/cosmos/cosmos-sdk/pull/6979 + */ +export function omitDefault(input: T): T | null { + if (typeof input === "number" || typeof input === "boolean" || typeof input === "string") { + return input || null; + } + + if (Array.isArray(input) || isUint8Array(input)) { + return input.length ? input : null; + } + + throw new Error("Input type not supported"); +} diff --git a/packages/proto-signing/src/signing.spec.ts b/packages/proto-signing/src/signing.spec.ts index 31659d82..fd3f2493 100644 --- a/packages/proto-signing/src/signing.spec.ts +++ b/packages/proto-signing/src/signing.spec.ts @@ -2,6 +2,7 @@ import { Bech32, fromBase64, fromHex, toHex } from "@cosmjs/encoding"; import { Secp256k1Wallet } from "@cosmjs/launchpad"; +import { omitDefault } from "./adr27"; import { cosmos } from "./generated/codecimpl"; import { defaultRegistry } from "./msgs"; import { Registry, TxBodyValue } from "./registry"; @@ -29,7 +30,7 @@ const faucet = { // simd tx bank send --sign-mode direct --chain-id simd-testing testgen cosmos1qypqxpq9qcrsszg2pvxq6rs0zqg3yyc5lzv7xu 1234567ucosm -b block const testVectors = [ { - sequenceNumber: undefined, // Go doesn’t encode 0 + sequenceNumber: 0, signedTxBytes: "0a580a560a142f636f736d6f732e62616e6b2e4d736753656e64123e0a140d82b1e7c96dbfa42462fe612932e6bff111d51b12140102030405060708090a0b0c0d0e0f10111213141a100a0575636f736d12073132333435363712330a2b0a230a21034f04181eeba35391b858633a765c4a0c189697b40d216354d50890d350c7029012040a020801120410c09a0c1a40692d88f681d5d69924a53668e8ecec535ca0ca170d1febfb1dd87de9959b07340427d6bba22526d6c30cc622f27dc5eb1ce04cfc0ff98716154066ec69db62e5", signBytes: @@ -149,11 +150,11 @@ describe("signing demo", () => { await Promise.all( testVectors.map(async ({ sequenceNumber, signBytes, signedTxBytes }) => { const signDoc = SignDoc.create({ - bodyBytes: txBodyBytes, - authInfoBytes: authInfoBytes, - chainId: chainId, - accountNumber: accountNumber, - accountSequence: sequenceNumber, + bodyBytes: omitDefault(txBodyBytes), + authInfoBytes: omitDefault(authInfoBytes), + chainId: omitDefault(chainId), + accountNumber: omitDefault(accountNumber), + accountSequence: omitDefault(sequenceNumber), }); const signDocBytes = Uint8Array.from(SignDoc.encode(signDoc).finish()); expect(toHex(signDocBytes)).toEqual(signBytes); diff --git a/packages/proto-signing/types/adr27.d.ts b/packages/proto-signing/types/adr27.d.ts new file mode 100644 index 00000000..dba1b48b --- /dev/null +++ b/packages/proto-signing/types/adr27.d.ts @@ -0,0 +1,7 @@ +/** + * Converts default values to null in order to tell protobuf.js + * to not serialize them. + * + * @see https://github.com/cosmos/cosmos-sdk/pull/6979 + */ +export declare function omitDefault(input: T): T | null;