diff --git a/packages/tendermint-rpc/src/adaptors/v0-33/hasher.spec.ts b/packages/tendermint-rpc/src/adaptors/v0-33/hasher.spec.ts index cc3081b2..a9f0c4c5 100644 --- a/packages/tendermint-rpc/src/adaptors/v0-33/hasher.spec.ts +++ b/packages/tendermint-rpc/src/adaptors/v0-33/hasher.spec.ts @@ -1,7 +1,7 @@ import { fromBase64, fromHex } from "@cosmjs/encoding"; import { ReadonlyDate } from "readonly-date"; -import { ReadonlyDateWithNanoseconds } from "../../types"; +import { ReadonlyDateWithNanoseconds } from "../../dates"; import { hashBlock, hashTx } from "./hasher"; describe("Hasher", () => { diff --git a/packages/tendermint-rpc/src/adaptors/v0-33/responses.ts b/packages/tendermint-rpc/src/adaptors/v0-33/responses.ts index 93d17ec8..7c4cdb22 100644 --- a/packages/tendermint-rpc/src/adaptors/v0-33/responses.ts +++ b/packages/tendermint-rpc/src/adaptors/v0-33/responses.ts @@ -3,6 +3,7 @@ import { fromBase64, fromHex } from "@cosmjs/encoding"; import { JsonRpcSuccessResponse } from "@cosmjs/json-rpc"; import { assert } from "@cosmjs/utils"; +import { DateTime } from "../../dates"; import { assertArray, assertBoolean, @@ -11,7 +12,6 @@ import { assertObject, assertSet, assertString, - DateTime, dictionaryToStringMap, Integer, may, diff --git a/packages/tendermint-rpc/src/dates.spec.ts b/packages/tendermint-rpc/src/dates.spec.ts new file mode 100644 index 00000000..9b80b851 --- /dev/null +++ b/packages/tendermint-rpc/src/dates.spec.ts @@ -0,0 +1,41 @@ +import { ReadonlyDate } from "readonly-date"; + +import { DateTime } from "./dates"; + +describe("dates", () => { + describe("DateTime", () => { + it("decodes a string", () => { + expect(DateTime.decode("2020-12-15T10:57:26.778Z").nanoseconds).toEqual(0); + expect(DateTime.decode("2020-12-15T10:57:26.7789Z").nanoseconds).toEqual(900000); + expect(DateTime.decode("2020-12-15T10:57:26.77809Z").nanoseconds).toEqual(90000); + expect(DateTime.decode("2020-12-15T10:57:26.778009Z").nanoseconds).toEqual(9000); + expect(DateTime.decode("2020-12-15T10:57:26.7780009Z").nanoseconds).toEqual(900); + expect(DateTime.decode("2020-12-15T10:57:26.77800009Z").nanoseconds).toEqual(90); + expect(DateTime.decode("2020-12-15T10:57:26.778000009Z").nanoseconds).toEqual(9); + }); + + it("encodes a string", () => { + const date1 = new ReadonlyDate("2020-12-15T10:57:26.778Z"); + (date1 as any).nanoseconds = 0; + expect(DateTime.encode(date1)).toEqual("2020-12-15T10:57:26.778000000Z"); + const date2 = new ReadonlyDate("2020-12-15T10:57:26.778Z"); + (date2 as any).nanoseconds = 900000; + expect(DateTime.encode(date2)).toEqual("2020-12-15T10:57:26.778900000Z"); + const date3 = new ReadonlyDate("2020-12-15T10:57:26.778Z"); + (date3 as any).nanoseconds = 90000; + expect(DateTime.encode(date3)).toEqual("2020-12-15T10:57:26.778090000Z"); + const date4 = new ReadonlyDate("2020-12-15T10:57:26.778Z"); + (date4 as any).nanoseconds = 9000; + expect(DateTime.encode(date4)).toEqual("2020-12-15T10:57:26.778009000Z"); + const date5 = new ReadonlyDate("2020-12-15T10:57:26.778Z"); + (date5 as any).nanoseconds = 900; + expect(DateTime.encode(date5)).toEqual("2020-12-15T10:57:26.778000900Z"); + const date6 = new ReadonlyDate("2020-12-15T10:57:26.778Z"); + (date6 as any).nanoseconds = 90; + expect(DateTime.encode(date6)).toEqual("2020-12-15T10:57:26.778000090Z"); + const date7 = new ReadonlyDate("2020-12-15T10:57:26.778Z"); + (date7 as any).nanoseconds = 9; + expect(DateTime.encode(date7)).toEqual("2020-12-15T10:57:26.778000009Z"); + }); + }); +}); diff --git a/packages/tendermint-rpc/src/dates.ts b/packages/tendermint-rpc/src/dates.ts new file mode 100644 index 00000000..fe32dc51 --- /dev/null +++ b/packages/tendermint-rpc/src/dates.ts @@ -0,0 +1,23 @@ +import { fromRfc3339 } from "@cosmjs/encoding"; +import { ReadonlyDate } from "readonly-date"; + +export interface ReadonlyDateWithNanoseconds extends ReadonlyDate { + /* Nanoseconds after the time stored in a vanilla ReadonlyDate (millisecond granularity) */ + readonly nanoseconds?: number; +} + +export class DateTime { + public static decode(dateTimeString: string): ReadonlyDateWithNanoseconds { + const readonlyDate = fromRfc3339(dateTimeString); + const nanosecondsMatch = dateTimeString.match(/\.(\d+)Z$/); + const nanoseconds = nanosecondsMatch ? nanosecondsMatch[1].slice(3) : ""; + (readonlyDate as any).nanoseconds = parseInt(nanoseconds.padEnd(6, "0"), 10); + return readonlyDate as ReadonlyDateWithNanoseconds; + } + + public static encode(dateTime: ReadonlyDateWithNanoseconds): string { + const millisecondIso = dateTime.toISOString(); + const nanoseconds = dateTime.nanoseconds?.toString() ?? ""; + return `${millisecondIso.slice(0, -1)}${nanoseconds.padStart(6, "0")}Z`; + } +} diff --git a/packages/tendermint-rpc/src/encodings.spec.ts b/packages/tendermint-rpc/src/encodings.spec.ts index 88750e68..afea0600 100644 --- a/packages/tendermint-rpc/src/encodings.spec.ts +++ b/packages/tendermint-rpc/src/encodings.spec.ts @@ -1,53 +1,8 @@ import { ReadonlyDate } from "readonly-date"; -import { - DateTime, - encodeBlockId, - encodeBytes, - encodeInt, - encodeString, - encodeTime, - encodeVersion, -} from "./encodings"; -import { ReadonlyDateWithNanoseconds } from "./types"; +import { encodeBlockId, encodeBytes, encodeInt, encodeString, encodeTime, encodeVersion } from "./encodings"; describe("encodings", () => { - describe("DateTime", () => { - it("decodes a string", () => { - expect(DateTime.decode("2020-12-15T10:57:26.778Z").nanoseconds).toEqual(0); - expect(DateTime.decode("2020-12-15T10:57:26.7789Z").nanoseconds).toEqual(900000); - expect(DateTime.decode("2020-12-15T10:57:26.77809Z").nanoseconds).toEqual(90000); - expect(DateTime.decode("2020-12-15T10:57:26.778009Z").nanoseconds).toEqual(9000); - expect(DateTime.decode("2020-12-15T10:57:26.7780009Z").nanoseconds).toEqual(900); - expect(DateTime.decode("2020-12-15T10:57:26.77800009Z").nanoseconds).toEqual(90); - expect(DateTime.decode("2020-12-15T10:57:26.778000009Z").nanoseconds).toEqual(9); - }); - - it("encodes a string", () => { - const date1 = new ReadonlyDate("2020-12-15T10:57:26.778Z") as ReadonlyDateWithNanoseconds; - (date1 as any).nanoseconds = 0; - expect(DateTime.encode(date1)).toEqual("2020-12-15T10:57:26.778000000Z"); - const date2 = new ReadonlyDate("2020-12-15T10:57:26.778Z") as ReadonlyDateWithNanoseconds; - (date2 as any).nanoseconds = 900000; - expect(DateTime.encode(date2)).toEqual("2020-12-15T10:57:26.778900000Z"); - const date3 = new ReadonlyDate("2020-12-15T10:57:26.778Z") as ReadonlyDateWithNanoseconds; - (date3 as any).nanoseconds = 90000; - expect(DateTime.encode(date3)).toEqual("2020-12-15T10:57:26.778090000Z"); - const date4 = new ReadonlyDate("2020-12-15T10:57:26.778Z") as ReadonlyDateWithNanoseconds; - (date4 as any).nanoseconds = 9000; - expect(DateTime.encode(date4)).toEqual("2020-12-15T10:57:26.778009000Z"); - const date5 = new ReadonlyDate("2020-12-15T10:57:26.778Z") as ReadonlyDateWithNanoseconds; - (date5 as any).nanoseconds = 900; - expect(DateTime.encode(date5)).toEqual("2020-12-15T10:57:26.778000900Z"); - const date6 = new ReadonlyDate("2020-12-15T10:57:26.778Z") as ReadonlyDateWithNanoseconds; - (date6 as any).nanoseconds = 90; - expect(DateTime.encode(date6)).toEqual("2020-12-15T10:57:26.778000090Z"); - const date7 = new ReadonlyDate("2020-12-15T10:57:26.778Z") as ReadonlyDateWithNanoseconds; - (date7 as any).nanoseconds = 9; - expect(DateTime.encode(date7)).toEqual("2020-12-15T10:57:26.778000009Z"); - }); - }); - describe("encodeString", () => { it("works", () => { expect(encodeString("")).toEqual(Uint8Array.from([0])); diff --git a/packages/tendermint-rpc/src/encodings.ts b/packages/tendermint-rpc/src/encodings.ts index 59f6e042..ef7727ee 100644 --- a/packages/tendermint-rpc/src/encodings.ts +++ b/packages/tendermint-rpc/src/encodings.ts @@ -1,8 +1,8 @@ -import { fromRfc3339, toUtf8 } from "@cosmjs/encoding"; +import { toUtf8 } from "@cosmjs/encoding"; import { Int53 } from "@cosmjs/math"; +import { ReadonlyDateWithNanoseconds } from "./dates"; import { BlockId, Version } from "./responses"; -import { ReadonlyDateWithNanoseconds } from "./types"; /** * A runtime checker that ensures a given value is set (i.e. not undefined or null) @@ -156,22 +156,6 @@ export class Integer { } } -export class DateTime { - public static decode(dateTimeString: string): ReadonlyDateWithNanoseconds { - const readonlyDate = fromRfc3339(dateTimeString); - const nanosecondsMatch = dateTimeString.match(/\.(\d+)Z$/); - const nanoseconds = nanosecondsMatch ? nanosecondsMatch[1].slice(3) : ""; - (readonlyDate as any).nanoseconds = parseInt(nanoseconds.padEnd(6, "0"), 10); - return readonlyDate as ReadonlyDateWithNanoseconds; - } - - public static encode(dateTime: ReadonlyDateWithNanoseconds): string { - const millisecondIso = dateTime.toISOString(); - const nanoseconds = dateTime.nanoseconds?.toString() ?? ""; - return `${millisecondIso.slice(0, -1)}${nanoseconds.padStart(6, "0")}Z`; - } -} - // Encodings needed for hashing block headers // Several of these functions are inspired by https://github.com/nomic-io/js-tendermint/blob/tendermint-0.30/src/ diff --git a/packages/tendermint-rpc/src/index.ts b/packages/tendermint-rpc/src/index.ts index df736fb1..a099ee1f 100644 --- a/packages/tendermint-rpc/src/index.ts +++ b/packages/tendermint-rpc/src/index.ts @@ -1,7 +1,7 @@ export { Adaptor } from "./adaptor"; export { adaptor33, adaptor34 } from "./adaptors"; export { Client } from "./client"; -export { DateTime } from "./encodings"; +export { DateTime, ReadonlyDateWithNanoseconds } from "./dates"; export { AbciInfoRequest, AbciQueryParams, @@ -72,10 +72,4 @@ export { VoteType, } from "./responses"; export { HttpClient, WebsocketClient } from "./rpcclients"; // TODO: Why do we export those outside of this package? -export { - BlockIdFlag, - CommitSignature, - ReadonlyDateWithNanoseconds, - ValidatorEd25519Pubkey, - ValidatorPubkey, -} from "./types"; +export { BlockIdFlag, CommitSignature, ValidatorEd25519Pubkey, ValidatorPubkey } from "./types"; diff --git a/packages/tendermint-rpc/src/responses.ts b/packages/tendermint-rpc/src/responses.ts index 83e7ab65..5706726a 100644 --- a/packages/tendermint-rpc/src/responses.ts +++ b/packages/tendermint-rpc/src/responses.ts @@ -1,6 +1,7 @@ import { ReadonlyDate } from "readonly-date"; -import { CommitSignature, ReadonlyDateWithNanoseconds, ValidatorPubkey } from "./types"; +import { ReadonlyDateWithNanoseconds } from "./dates"; +import { CommitSignature, ValidatorPubkey } from "./types"; export type Response = | AbciInfoResponse diff --git a/packages/tendermint-rpc/src/types.ts b/packages/tendermint-rpc/src/types.ts index c71a10f7..1c62851c 100644 --- a/packages/tendermint-rpc/src/types.ts +++ b/packages/tendermint-rpc/src/types.ts @@ -1,11 +1,7 @@ // Types in this file are exported outside of the @cosmjs/tendermint-rpc package, // e.g. as part of a request or response -import { ReadonlyDate } from "readonly-date"; -export interface ReadonlyDateWithNanoseconds extends ReadonlyDate { - /* Nanoseconds after the time stored in a vanilla ReadonlyDate (millisecond granularity) */ - readonly nanoseconds?: number; -} +import { ReadonlyDateWithNanoseconds } from "./dates"; export interface ValidatorEd25519Pubkey { readonly algorithm: "ed25519";