From 93d4bfb5e690c3170c608aad7c370b93397b4fdb Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Fri, 7 Aug 2020 10:37:57 +0200 Subject: [PATCH] Add and use arrayContentEquals --- CHANGELOG.md | 1 + packages/stargate/src/stargateclient.ts | 5 ++-- packages/utils/src/array.spec.ts | 33 +++++++++++++++++++++++++ packages/utils/src/arrays.ts | 18 ++++++++++++++ packages/utils/src/index.ts | 1 + packages/utils/types/arrays.d.ts | 12 +++++++++ packages/utils/types/index.d.ts | 1 + 7 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 packages/utils/src/array.spec.ts create mode 100644 packages/utils/src/arrays.ts create mode 100644 packages/utils/types/arrays.d.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 59a10c61..01abe683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ `BroadcastTxSuccess` and `BroadcastTxFailure` respectively, as well as helper functions `isBroadcastTxFailure`, `isBroadcastTxSuccess` and `assertIsBroadcastTxSuccess`. +- @cosmjs/utils: Add `arrayContentEquals`. ## 0.22.0 (2020-08-03) diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 4c9094f7..f4e1c946 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -4,7 +4,7 @@ import { Coin } from "@cosmjs/launchpad"; import { Uint64 } from "@cosmjs/math"; import * as proto from "@cosmjs/proto-signing"; import { Client as TendermintClient } from "@cosmjs/tendermint-rpc"; -import { assertDefined } from "@cosmjs/utils"; +import { arrayContentEquals, assertDefined } from "@cosmjs/utils"; import Long from "long"; import { BaseAccount } from "./query/accounts"; @@ -118,8 +118,7 @@ export class StargateClient { throw new Error(`Query failed with (${response.code}): ${response.log}`); } - // TODO: better way to compare? - if (toHex(response.key) !== toHex(key)) { + if (!arrayContentEquals(response.key, key)) { throw new Error(`Response key ${toHex(response.key)} doesn't match query key ${toHex(key)}`); } diff --git a/packages/utils/src/array.spec.ts b/packages/utils/src/array.spec.ts new file mode 100644 index 00000000..d42241bc --- /dev/null +++ b/packages/utils/src/array.spec.ts @@ -0,0 +1,33 @@ +import { arrayContentEquals } from "./arrays"; + +describe("array", () => { + describe("arrayContentEquals", () => { + it("can compare number arrays", () => { + expect(arrayContentEquals([1, 2, 3], [1, 2, 3])).toEqual(true); + expect(arrayContentEquals([1, 2, 3], [1, 2, 3, 4])).toEqual(false); + expect(arrayContentEquals([1, 2, 3], [3, 2, 1])).toEqual(false); + }); + + it("can compare string arrays", () => { + expect(arrayContentEquals(["a", "b"], ["a", "b"])).toEqual(true); + expect(arrayContentEquals(["a", "b"], ["a", "b", "c"])).toEqual(false); + expect(arrayContentEquals(["a", "b"], ["b", "a"])).toEqual(false); + }); + + it("can compare bool arrays", () => { + expect(arrayContentEquals([true, false], [true, false])).toEqual(true); + expect(arrayContentEquals([true, false], [true, false, true])).toEqual(false); + expect(arrayContentEquals([true, false], [false, true])).toEqual(false); + }); + + it("can compare different array types", () => { + expect(arrayContentEquals([1, 2, 3], new Uint8Array([1, 2, 3]))).toEqual(true); + expect(arrayContentEquals([1, 2, 3], new Uint8Array([3, 2, 1]))).toEqual(false); + }); + + it("works for empty arrays", () => { + expect(arrayContentEquals([], [])).toEqual(true); + expect(arrayContentEquals([], new Uint8Array([]))).toEqual(true); + }); + }); +}); diff --git a/packages/utils/src/arrays.ts b/packages/utils/src/arrays.ts new file mode 100644 index 00000000..87f5a442 --- /dev/null +++ b/packages/utils/src/arrays.ts @@ -0,0 +1,18 @@ +/** + * Compares the content of two arrays-like objects for equality. + * + * Equality is defined as having equal length and element values, where element equality means `===` returning `true`. + * + * This allows you to compare the content of a Buffer, Uint8Array or number[], ignoring the specific type. + * As a consequence, this returns different results than Jasmine's `toEqual`, which ensures elements have the same type. + */ +export function arrayContentEquals( + a: ArrayLike, + b: ArrayLike, +): boolean { + if (a.length !== b.length) return false; + for (let i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + return true; +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 8d7c29d4..391b2471 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,3 +1,4 @@ +export { arrayContentEquals } from "./arrays"; export { assert, assertDefined } from "./assert"; export { sleep } from "./sleep"; export { isNonNullObject, isUint8Array } from "./typechecks"; diff --git a/packages/utils/types/arrays.d.ts b/packages/utils/types/arrays.d.ts new file mode 100644 index 00000000..2d30e579 --- /dev/null +++ b/packages/utils/types/arrays.d.ts @@ -0,0 +1,12 @@ +/** + * Compares the content of two arrays-like objects for equality. + * + * Equality is defined as having equal length and element values, where element equality means `===` returning `true`. + * + * This allows you to compare the content of a Buffer, Uint8Array or number[], ignoring the specific type. + * As a consequence, this returns different results than Jasmine's `toEqual`, which ensures elements have the same type. + */ +export declare function arrayContentEquals( + a: ArrayLike, + b: ArrayLike, +): boolean; diff --git a/packages/utils/types/index.d.ts b/packages/utils/types/index.d.ts index 8d7c29d4..391b2471 100644 --- a/packages/utils/types/index.d.ts +++ b/packages/utils/types/index.d.ts @@ -1,3 +1,4 @@ +export { arrayContentEquals } from "./arrays"; export { assert, assertDefined } from "./assert"; export { sleep } from "./sleep"; export { isNonNullObject, isUint8Array } from "./typechecks";