Create and use omitDefaults

This commit is contained in:
Simon Warta 2020-08-10 06:14:52 +02:00 committed by willclarktech
parent c7c403ee42
commit 7e4705b703
No known key found for this signature in database
GPG Key ID: 551A86E2E398ADF7
4 changed files with 141 additions and 21 deletions

View File

@ -1,7 +1,7 @@
import { fromHex } from "@cosmjs/encoding";
import { parse } from "protobufjs";
import { omitDefault } from "./adr27";
import { omitDefault, omitDefaults } from "./adr27";
describe("adr27", () => {
describe("omitDefault", () => {
@ -46,6 +46,94 @@ describe("adr27", () => {
expect(omitDefault(Review.values["ACCEPTED"])).toEqual(Review.values["ACCEPTED"]);
expect(omitDefault(Review.values["UNSPECIFIED"])).toEqual(null);
});
});
describe("omitDefaults", () => {
it("works for scalars", () => {
expect(omitDefaults("abc")).toEqual("abc");
expect(omitDefaults("")).toEqual(null);
expect(omitDefaults(fromHex("ab"))).toEqual(fromHex("ab"));
expect(omitDefaults(fromHex(""))).toEqual(null);
expect(omitDefaults(123)).toEqual(123);
expect(omitDefaults(0)).toEqual(null);
expect(omitDefaults(1.234)).toEqual(1.234);
expect(omitDefaults(0.0)).toEqual(null);
});
it("works for repeaded", () => {
expect(omitDefaults(["a", "b", "c"])).toEqual(["a", "b", "c"]);
expect(omitDefaults([])).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(omitDefaults(Review.values["ACCEPTED"])).toEqual(Review.values["ACCEPTED"]);
expect(omitDefaults(Review.values["UNSPECIFIED"])).toEqual(null);
});
it("works for objects", () => {
// empty
expect(omitDefaults({})).toEqual({});
// simple
expect(
omitDefaults({
a: "foo",
b: "",
c: 100,
d: 0,
}),
).toEqual({
a: "foo",
b: null,
c: 100,
d: null,
});
// nested
expect(
omitDefaults({
a: {
x: "foo",
y: "",
},
b: {
x: {
o: 1.2,
p: false,
q: 0,
},
},
}),
).toEqual({
a: {
x: "foo",
y: null,
},
b: {
x: {
o: 1.2,
p: null,
q: null,
},
},
});
});
it("can be used to reproduce ADR 027 test vector", () => {
const proto = `
@ -93,18 +181,20 @@ describe("adr27", () => {
);
const serialization = Uint8Array.from(
Article.encode({
title: omitDefault("The world needs change"),
description: omitDefault(""),
created: omitDefault(1596806111080),
updated: omitDefault(0),
public: omitDefault(true),
promoted: omitDefault(false),
type: omitDefault(Type.values["NEWS"]),
review: omitDefault(Review.values["UNSPECIFIED"]),
comments: omitDefault(["Nice one", "Thank you"]),
backlinks: omitDefault([]),
}).finish(),
Article.encode(
omitDefaults({
title: "The world needs change",
description: "",
created: 1596806111080,
updated: 0,
public: true,
promoted: false,
type: Type.values["NEWS"],
review: Review.values["UNSPECIFIED"],
comments: ["Nice one", "Thank you"],
backlinks: [],
}),
).finish(),
);
expect(serialization).toEqual(expected);
});

View File

@ -17,3 +17,27 @@ export function omitDefault<T>(input: T): T | null {
throw new Error("Input type not supported");
}
/**
* Walks through a potentially nested object and calls omitDefault on each element.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function omitDefaults(input: any): any {
if (
typeof input === "number" ||
typeof input === "boolean" ||
typeof input === "string" ||
Array.isArray(input) ||
isUint8Array(input)
) {
return omitDefault(input);
}
return Object.keys(input).reduce(
(accumulator, key) => ({
...accumulator,
[key]: omitDefaults(input[key]),
}),
{},
);
}

View File

@ -2,7 +2,7 @@
import { Bech32, fromBase64, fromHex, toHex } from "@cosmjs/encoding";
import { Secp256k1Wallet } from "@cosmjs/launchpad";
import { omitDefault } from "./adr27";
import { omitDefaults } from "./adr27";
import { cosmos } from "./generated/codecimpl";
import { defaultRegistry } from "./msgs";
import { Registry, TxBodyValue } from "./registry";
@ -149,13 +149,15 @@ describe("signing demo", () => {
await Promise.all(
testVectors.map(async ({ sequenceNumber, signBytes, signedTxBytes }) => {
const signDoc = SignDoc.create({
bodyBytes: omitDefault(txBodyBytes),
authInfoBytes: omitDefault(authInfoBytes),
chainId: omitDefault(chainId),
accountNumber: omitDefault(accountNumber),
accountSequence: omitDefault(sequenceNumber),
});
const signDoc = SignDoc.create(
omitDefaults({
bodyBytes: txBodyBytes,
authInfoBytes: authInfoBytes,
chainId: chainId,
accountNumber: accountNumber,
accountSequence: sequenceNumber,
}),
);
const signDocBytes = Uint8Array.from(SignDoc.encode(signDoc).finish());
expect(toHex(signDocBytes)).toEqual(signBytes);

View File

@ -5,3 +5,7 @@
* @see https://github.com/cosmos/cosmos-sdk/pull/6979
*/
export declare function omitDefault<T>(input: T): T | null;
/**
* Walks through a potentially nested object and calls omitDefault on each element.
*/
export declare function omitDefaults(input: any): any;