From 7c60beaa42e69b60174ffd4e7e693c822fa7c83c Mon Sep 17 00:00:00 2001 From: KtorZ Date: Sat, 21 May 2022 11:17:25 +0200 Subject: [PATCH] Make TxMonitor's methods throw a single error & reduce boilerplate. --- .../client/src/TxMonitor/TxMonitorClient.ts | 52 +++--------- .../client/src/TxMonitor/awaitAcquire.ts | 34 +++++--- .../packages/client/src/TxMonitor/hasTx.ts | 63 +++++++------- .../packages/client/src/TxMonitor/nextTx.ts | 85 ++++++++++++------- .../packages/client/src/TxMonitor/release.ts | 38 ++++----- .../client/src/TxMonitor/sizeAndCapacity.ts | 45 +++++----- .../client/test/TxMonitor/TxMonitor.test.ts | 26 +++--- 7 files changed, 175 insertions(+), 168 deletions(-) diff --git a/clients/TypeScript/packages/client/src/TxMonitor/TxMonitorClient.ts b/clients/TypeScript/packages/client/src/TxMonitor/TxMonitorClient.ts index 045f992481..5e2c02b81c 100644 --- a/clients/TypeScript/packages/client/src/TxMonitor/TxMonitorClient.ts +++ b/clients/TypeScript/packages/client/src/TxMonitor/TxMonitorClient.ts @@ -1,12 +1,12 @@ import { InteractionContext } from '../Connection' import { ensureSocketIsOpen, eventEmitterToGenerator, safeJSON } from '../util' -import { MempoolSizeAndCapacity, Null, Ogmios, TxAlonzo, TxId } from "@cardano-ogmios/schema" +import { Ogmios, MempoolSizeAndCapacity, Slot, TxAlonzo, TxId } from "@cardano-ogmios/schema" import { baseRequest, send } from "../Request" -import { AwaitAcquired, handleAwaitAcquireResponse } from "./awaitAcquire" -import { handleHasTxResponse, isHasTxResult } from "./hasTx" -import { handleNextTxResponse, isNextTxResult } from "./nextTx" -import { handleReleaseResponse, isReleasedResult } from "./release" -import { handleSizeAndCapacityResponse, isMempoolSizeAndCapacity } from "./sizeAndCapacity" +import { handleAwaitAcquireResponse } from "./awaitAcquire" +import { handleHasTxResponse } from "./hasTx" +import { handleNextTxResponse } from "./nextTx" +import { handleReleaseResponse } from "./release" +import { handleSizeAndCapacityResponse } from "./sizeAndCapacity" /** * See also {@link createTxMonitorClient} for creating a client. @@ -15,9 +15,9 @@ import { handleSizeAndCapacityResponse, isMempoolSizeAndCapacity } from "./sizeA **/ export interface TxMonitorClient { context: InteractionContext - awaitAcquire: (args?: {}) => Promise + awaitAcquire: (args?: {}) => Promise hasTx: (id: TxId) => Promise - nextTx: (args?: { fields?: "all" }) => Promise + nextTx: (args?: { fields?: "all" }) => Promise sizeAndCapacity: (args?: {}) => Promise release: (args?: {}) => Promise shutdown: () => Promise @@ -97,7 +97,7 @@ export const createTxMonitorClient = async ( context, awaitAcquire: (args?: {}) => { ensureSocketIsOpen(socket) - return send(async (socket) => { + return send(async (socket) => { socket.send(safeJSON.stringify({ ...baseRequest, methodname: 'AwaitAcquire', @@ -116,31 +116,19 @@ export const createTxMonitorClient = async ( args: { id } } as unknown as Ogmios['HasTx'])) - const response = handleHasTxResponse((await hasTxResponse.next()).value) - - if (isHasTxResult(response)) { - return response - } else { - throw response - } + return handleHasTxResponse((await hasTxResponse.next()).value) }, context) }, nextTx: (args?: {fields?: "all"}) => { ensureSocketIsOpen(socket) - return send(async (socket) => { + return send(async (socket) => { socket.send(safeJSON.stringify({ ...baseRequest, methodname: 'NextTx', args: args } as unknown as Ogmios['NextTx'])) - const response = handleNextTxResponse((await nextTxResponse.next()).value) - - if (isNextTxResult(response)) { - return response - } else { - throw response - } + return handleNextTxResponse((await nextTxResponse.next()).value, args) }, context) }, sizeAndCapacity: (args?: {}) => { @@ -152,13 +140,7 @@ export const createTxMonitorClient = async ( args: args } as unknown as Ogmios['SizeAndCapacity'])) - const response = handleSizeAndCapacityResponse((await sizeAndCapacityResponse.next()).value) - - if (isMempoolSizeAndCapacity(response)) { - return response - } else { - throw response - } + return handleSizeAndCapacityResponse((await sizeAndCapacityResponse.next()).value) }, context) }, release: (args?: {}) => { @@ -170,13 +152,7 @@ export const createTxMonitorClient = async ( args: args } as unknown as Ogmios['ReleaseMempool'])) - const response = handleReleaseResponse((await releaseMempoolResponse.next()).value) - - if (isReleasedResult(response)) { - return - } else { - throw response - } + return handleReleaseResponse((await releaseMempoolResponse.next()).value) }, context) }, shutdown: () => new Promise(resolve => { diff --git a/clients/TypeScript/packages/client/src/TxMonitor/awaitAcquire.ts b/clients/TypeScript/packages/client/src/TxMonitor/awaitAcquire.ts index 3d310f6445..3a48c9af4d 100644 --- a/clients/TypeScript/packages/client/src/TxMonitor/awaitAcquire.ts +++ b/clients/TypeScript/packages/client/src/TxMonitor/awaitAcquire.ts @@ -1,13 +1,7 @@ -import { Ogmios, Slot } from "@cardano-ogmios/schema" +import { Ogmios, AwaitAcquired, Slot } from "@cardano-ogmios/schema" import { UnknownResultError } from "../errors"; import { InteractionContext } from '../Connection' import { Query } from '../StateQuery' -export interface AwaitAcquired { - slot: Slot; -}; - -export const isAwaitAcquiredResult = (result: AwaitAcquired | Error[]): result is AwaitAcquired => - (typeof (result as AwaitAcquired) === 'object' && !Array.isArray(result)) /** * Acquire a mempool snapshot. This is blocking until a new (i.e different) snapshot is available. @@ -18,7 +12,7 @@ export const awaitAcquire = (context: InteractionContext, args?: {}) => Query< Ogmios['AwaitAcquire'], Ogmios['AwaitAcquireResponse'], - AwaitAcquired + Slot >({ methodName: 'AwaitAcquire', args: args @@ -32,10 +26,26 @@ export const awaitAcquire = (context: InteractionContext, args?: {}) => } }, context) -export const handleAwaitAcquireResponse = (response: Ogmios['AwaitAcquireResponse']): AwaitAcquired => { +/** + * @internal + */ +export const isAwaitAcquiredResult = (result: any): result is AwaitAcquired => { + if (typeof result !== 'object' || result === null) { + return false + } + + return ('AwaitAcquired' in (result as AwaitAcquired) && typeof result.AwaitAcquired === 'object') +} + +/** + * @internal + */ +export const handleAwaitAcquireResponse = (response: Ogmios['AwaitAcquireResponse']): Slot => { const { result } = response + if ('AwaitAcquired' in result) { - return result.AwaitAcquired - } + return result.AwaitAcquired.slot + } + throw new UnknownResultError(response) -} \ No newline at end of file +} diff --git a/clients/TypeScript/packages/client/src/TxMonitor/hasTx.ts b/clients/TypeScript/packages/client/src/TxMonitor/hasTx.ts index ac4a6be7bc..305cc12c9f 100644 --- a/clients/TypeScript/packages/client/src/TxMonitor/hasTx.ts +++ b/clients/TypeScript/packages/client/src/TxMonitor/hasTx.ts @@ -3,43 +3,42 @@ import { UnknownResultError } from "../errors"; import { InteractionContext } from '../Connection' import { Query } from '../StateQuery' -export const isHasTxResult = (result: boolean | Error[]): result is boolean => - (typeof result === 'boolean') - - /** * Ask whether a given transaction is present in the acquired mempool snapshot. * * @category TxMonitor */ export const hasTx = (context: InteractionContext, id: TxId) => -Query< - Ogmios['HasTx'], - Ogmios['HasTxResponse'], - Boolean ->({ - methodName: 'HasTx', - args: { id } -}, { - handler: (response, resolve, reject) => { - const result = handleHasTxResponse(response) - if (isHasTxResult(result)) { - return resolve(result as Boolean) - } else { - return reject(result as Error[]) + Query< + Ogmios['HasTx'], + Ogmios['HasTxResponse'], + boolean + >({ + methodName: 'HasTx', + args: { id } + }, { + handler: (response, resolve, reject) => { + try { + resolve(handleHasTxResponse(response)) + } catch (e) { + reject(e) + } } - } -}, context) + }, context) -export const handleHasTxResponse = (response: Ogmios['HasTxResponse']): (boolean | Error[]) => { - try { - const { result } = response - if (result !== undefined) { - return result; - } else { - return [new UnknownResultError(response)] - } - } catch (e) { - return [new UnknownResultError(response)] - } -} \ No newline at end of file +/** + * @internal + */ +export const isHasTxResult = (result: any): result is boolean => + (typeof result === 'boolean') + +/** + * @internal + */ +export const handleHasTxResponse = (response: Ogmios['HasTxResponse']): boolean => { + const { result } = response + if (isHasTxResult(result)) { + return result + } + throw new UnknownResultError(response) +} diff --git a/clients/TypeScript/packages/client/src/TxMonitor/nextTx.ts b/clients/TypeScript/packages/client/src/TxMonitor/nextTx.ts index baf9ae4651..6499a9f97c 100644 --- a/clients/TypeScript/packages/client/src/TxMonitor/nextTx.ts +++ b/clients/TypeScript/packages/client/src/TxMonitor/nextTx.ts @@ -1,44 +1,63 @@ -import { Null, Ogmios, TxAlonzo, TxId } from "@cardano-ogmios/schema" -import { UnknownResultError } from "../errors"; +import { Ogmios, TxAlonzo, TxId } from "@cardano-ogmios/schema" +import { UnknownResultError } from "../errors" import { InteractionContext } from '../Connection' import { Query } from '../StateQuery' -export const isNextTxResult = (result: TxId | TxAlonzo | Null | Error[]): result is TxId | TxAlonzo | Null => - ((typeof (result as TxId) === 'string' || typeof (result as TxAlonzo) === 'object' || typeof (result as Null) === 'object') && !Array.isArray(result)) - /** * Request the next mempool transaction from an acquired snapshot. * * @category TxMonitor */ - export const nextTx = (context: InteractionContext, args?: { fields?: "all"}) => - Query< - Ogmios['NextTx'], - Ogmios['NextTxResponse'], - TxId | TxAlonzo | Null - >({ - methodName: 'NextTx', - args: args - }, { - handler: (response, resolve, reject) => { - const result = handleNextTxResponse(response) - if (isNextTxResult(result)) { - return resolve(result as TxId | TxAlonzo | Null) - } else { - return reject(result as Error[]) +export function nextTx (context: InteractionContext, args?: { fields: "all" }) : Promise +export function nextTx (context: InteractionContext, args?: {}) : Promise +export function nextTx (context: InteractionContext, args?: { fields: "all" }) : Promise { + return Query< + Ogmios['NextTx'], + Ogmios['NextTxResponse'], + TxAlonzo | null + >({ + methodName: 'NextTx', + args: args + }, { + handler: (response, resolve, reject) => { + try { + resolve(handleNextTxResponse(response, args)) + } catch (e) { + reject(e) + } } - } - }, context) + }, context) +} + +/** + * @internal + */ +export const isNextTxResultId = (result: any): result is TxId | null => + ((result as null) === null) || (typeof (result as TxId) === 'string') -export const handleNextTxResponse = (response: Ogmios['NextTxResponse']): (TxId | TxAlonzo | Null | Error[]) => { - try { - const { result } = response - if (result !== undefined) { - return result; - } else { - return [new UnknownResultError(response)] - } - } catch (e) { - return [new UnknownResultError(response)] +/** + * @internal + */ +export const isNextTxResultAll = (result: any): result is TxAlonzo | null => + ((result as null) === null) || (typeof (result as TxAlonzo) === 'object') + +/** + * @internal + */ +export function handleNextTxResponse (response: Ogmios['NextTxResponse'], args?: { fields: "all" }): (TxAlonzo | null) +export function handleNextTxResponse (response: Ogmios['NextTxResponse'], args?: {}): (TxId | null) +export function handleNextTxResponse (response: Ogmios['NextTxResponse'], args?: { fields: "all" }): (TxId | TxAlonzo | null) { + const { result } = response + + if (args.fields === "all") { + if (isNextTxResultAll(result)) { + return result + } + } else { + if (isNextTxResultId(result)) { + return result + } } -} \ No newline at end of file + + throw new UnknownResultError(response) +} diff --git a/clients/TypeScript/packages/client/src/TxMonitor/release.ts b/clients/TypeScript/packages/client/src/TxMonitor/release.ts index 9623aa13e6..7d346d68d9 100644 --- a/clients/TypeScript/packages/client/src/TxMonitor/release.ts +++ b/clients/TypeScript/packages/client/src/TxMonitor/release.ts @@ -3,9 +3,6 @@ import { UnknownResultError } from "../errors"; import { InteractionContext } from '../Connection' import { Query } from '../StateQuery' -export const isReleasedResult = (result: string | Error[]): result is string => - (result === "Released") - /** * Release a previously acquired mempool snapshot. * @@ -21,24 +18,27 @@ export const release = (context: InteractionContext, args?: {}) => args: args }, { handler: (response, resolve, reject) => { - const result = handleReleaseResponse(response) - if (isReleasedResult(result)) { - return resolve() - } else { - return reject(result as Error[]) + try { + resolve(handleReleaseResponse(response)) + } catch (e) { + reject(e) } } }, context) -export const handleReleaseResponse = (response: Ogmios['ReleaseMempoolResponse']): (string | Error[]) => { - try { - const { result } = response - if (result !== undefined) { - return result; - } else { - return [new UnknownResultError(response)] - } - } catch (e) { - return [new UnknownResultError(response)] +/** + * @internal + */ +export const isReleaseResult = (result: any): result is string => + (result === "Released") + +/** + * @internal + */ +export const handleReleaseResponse = (response: Ogmios['ReleaseMempoolResponse']): void => { + const { result } = response + if (isReleaseResult(result)) { + return } -} \ No newline at end of file + throw new UnknownResultError(response) +} diff --git a/clients/TypeScript/packages/client/src/TxMonitor/sizeAndCapacity.ts b/clients/TypeScript/packages/client/src/TxMonitor/sizeAndCapacity.ts index 8b9263b420..ada1cfd0d4 100644 --- a/clients/TypeScript/packages/client/src/TxMonitor/sizeAndCapacity.ts +++ b/clients/TypeScript/packages/client/src/TxMonitor/sizeAndCapacity.ts @@ -3,9 +3,6 @@ import { UnknownResultError } from "../errors"; import { InteractionContext } from '../Connection' import { Query } from '../StateQuery' -export const isMempoolSizeAndCapacity = (result: MempoolSizeAndCapacity | Error[]): result is MempoolSizeAndCapacity => - (typeof (result as MempoolSizeAndCapacity) === 'object' && !Array.isArray(result)) - /** * Get size and capacities of the mempool (acquired snapshot). * @@ -21,24 +18,34 @@ export const sizeAndCapacity = (context: InteractionContext, args?: {}) => args: args }, { handler: (response, resolve, reject) => { - const result = handleSizeAndCapacityResponse(response) - if (isMempoolSizeAndCapacity(result)) { - return resolve(result as MempoolSizeAndCapacity) - } else { - return reject(result as Error[]) + try { + resolve(handleSizeAndCapacityResponse(response)) + } catch (e) { + reject(e) } } }, context) -export const handleSizeAndCapacityResponse = (response: Ogmios['SizeAndCapacityResponse']): (MempoolSizeAndCapacity | Error[]) => { - try { - const { result } = response - if ('capacity' in result && 'currentSize' in result && 'numberOfTxs' in result) { - return result; - } else { - return [new UnknownResultError(response)] - } - } catch (e) { - return [new UnknownResultError(response)] +/** + * @internal + */ +export const isSizeAndCapacityResult = (result: any): result is MempoolSizeAndCapacity => { + if (typeof (result as MempoolSizeAndCapacity) !== 'object' || result === null) { + return false } -} \ No newline at end of file + + return ('capacity' in result && 'currentSize' in result && 'numberOfTxs' in result) +} + +/** + * @internal + */ +export const handleSizeAndCapacityResponse = (response: Ogmios['SizeAndCapacityResponse']): MempoolSizeAndCapacity => { + const { result } = response + + if (isSizeAndCapacityResult(result)) { + return result + } + + throw new UnknownResultError(response) +} diff --git a/clients/TypeScript/packages/client/test/TxMonitor/TxMonitor.test.ts b/clients/TypeScript/packages/client/test/TxMonitor/TxMonitor.test.ts index 5234fa53d4..2584936474 100644 --- a/clients/TypeScript/packages/client/test/TxMonitor/TxMonitor.test.ts +++ b/clients/TypeScript/packages/client/test/TxMonitor/TxMonitor.test.ts @@ -48,7 +48,7 @@ describe('TxMonitor', () => { methods.forEach(awaitAcquire => { it('successfully acquire the first snapshot', async () => { const snapshot = await awaitAcquire() - expect(snapshot.slot).toEqual(expect.any(Number)) + expect(snapshot).toEqual(expect.any(Number)) }) }) }) @@ -79,13 +79,12 @@ describe('TxMonitor', () => { expect(exist).toEqual(false) }) - it('fail to check whether tx is in mempool or not as no snapshot was previously acquired', async () => { + it('fail to check whether tx is in mempool when no snapshot was previously acquired', async () => { await client.release() try { await hasTx(id) - } catch(errors) { - expect(errors).toHaveLength(1) - expect(errors[0]).toBeInstanceOf(UnknownResultError) + } catch(e) { + expect(e).toBeInstanceOf(UnknownResultError) } }) }) @@ -118,9 +117,8 @@ describe('TxMonitor', () => { await client.release() try { await nextTx({ fields: "all" }) - } catch(errors) { - expect(errors).toHaveLength(1) - expect(errors[0]).toBeInstanceOf(UnknownResultError) + } catch(e) { + expect(e).toBeInstanceOf(UnknownResultError) } }) }) @@ -155,9 +153,8 @@ describe('TxMonitor', () => { await client.release() try { await sizeAndCapacity() - } catch(errors) { - expect(errors).toHaveLength(1) - expect(errors[0]).toBeInstanceOf(UnknownResultError) + } catch(e) { + expect(e).toBeInstanceOf(UnknownResultError) } }) @@ -186,13 +183,12 @@ describe('TxMonitor', () => { await expect(release()).resolves.not.toThrow(); }) - it('fail to get mempool size and capacity as no snapshot was previously acquired', async () => { + it('fail to get mempool size and capacity when no snapshot was previously acquired', async () => { await release() try { await release() - } catch(errors) { - expect(errors).toHaveLength(1) - expect(errors[0]).toBeInstanceOf(UnknownResultError) + } catch(e) { + expect(e).toBeInstanceOf(UnknownResultError) } }) })