From 1c25dd4069a3a8f5599285c9b0eaeb71a2f897d1 Mon Sep 17 00:00:00 2001 From: Loris Leiva Date: Sun, 1 Sep 2024 19:07:12 +0100 Subject: [PATCH] Rename `RpcResponse` to `RpcResponseData` (#3145) The purpose of this PR stack is to refactor both the RPC and RPC Subscriptions packages such that they have better interfaces with their respective transports. In this first batch of PRs, we will start by focusing on the RPC packages whilst ensuring minimum changes on the RPC Subscriptions packages. The end goal of this first part is to have the following interfaces for the RPC packages: ### RPC Shared Layer ```ts type RpcRequest = { readonly methodName: string; readonly params: TParams; } type RpcResponse = { readonly json: () => Promise; readonly text: () => Promise; } type RpcRequestTransformer = { (request: RpcRequest): RpcRequest; }; type RpcResponseTransformer = { (response: RpcResponse, request: RpcRequest): RpcResponse; }; type RpcResponseTransformerFor = { (response: RpcResponse, request: RpcRequest): RpcResponse; }; ``` ### RPC Transport Layer ```ts type RpcTransportRequest = { readonly payload: unknown; readonly signal?: AbortSignal; } type RpcTransport = { ( request: RpcTransportRequest ): Promise>; } ``` ### RPC API Layer ```ts type RpcApi = { ... } type RpcApiConfig = { readonly requestTransformer?: RpcRequestTransformer; readonly responseTransformer?: RpcResponseTransformer; } type PendingRpcApiRequest = RpcRequest & { responseTransformer?: RpcResponseTransformerFor; }; ``` ### RPC Layer ```ts type PendingRpcRequest = { // Nothing changes here but the final send function returns the result of `response.json()`. send(options?: RpcSendOptions): Promise; }; ``` --- In the first two PRs of the stack, we start by cleaning up the type namespace to allow these new types to exist. First, we rename `RpcResponse` to `RpcResponseData`, since `RpcResponse` will be used to define a proper response interface that aligns all the RPC layers. --- .changeset/gorgeous-foxes-type.md | 8 ++++++++ .../src/__tests__/get-stake-minimum-delegation-test.ts | 2 +- packages/rpc-api/src/__tests__/is-blockhash-valid-test.ts | 2 +- packages/rpc-spec-types/src/rpc-response.ts | 5 +++-- packages/rpc-spec/src/rpc.ts | 4 ++-- packages/rpc-subscriptions-spec/src/rpc-subscriptions.ts | 6 +++--- 6 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 .changeset/gorgeous-foxes-type.md diff --git a/.changeset/gorgeous-foxes-type.md b/.changeset/gorgeous-foxes-type.md new file mode 100644 index 000000000000..e50915adfd5c --- /dev/null +++ b/.changeset/gorgeous-foxes-type.md @@ -0,0 +1,8 @@ +--- +'@solana/rpc-subscriptions-spec': patch +'@solana/rpc-spec-types': patch +'@solana/rpc-spec': patch +'@solana/rpc-api': patch +--- + +Rename `RpcResponse` type to `RpcResponseData` to make room for a new `RpcResponse` type diff --git a/packages/rpc-api/src/__tests__/get-stake-minimum-delegation-test.ts b/packages/rpc-api/src/__tests__/get-stake-minimum-delegation-test.ts index f41b05de1782..5d2fd27f28f8 100644 --- a/packages/rpc-api/src/__tests__/get-stake-minimum-delegation-test.ts +++ b/packages/rpc-api/src/__tests__/get-stake-minimum-delegation-test.ts @@ -11,7 +11,7 @@ describe('getStakeMinimumDelegation', () => { }); (['confirmed', 'finalized', 'processed'] as Commitment[]).forEach(commitment => { describe(`when called with \`${commitment}\` commitment`, () => { - it('returns the result as a bigint wrapped in an RpcResponse', async () => { + it('returns the result as a bigint wrapped in an RpcResponseData', async () => { expect.assertions(1); const result = await rpc.getStakeMinimumDelegation({ commitment }).send(); expect(result.value).toEqual(expect.any(BigInt)); diff --git a/packages/rpc-api/src/__tests__/is-blockhash-valid-test.ts b/packages/rpc-api/src/__tests__/is-blockhash-valid-test.ts index 90e8510b0918..a007953ebb1c 100644 --- a/packages/rpc-api/src/__tests__/is-blockhash-valid-test.ts +++ b/packages/rpc-api/src/__tests__/is-blockhash-valid-test.ts @@ -11,7 +11,7 @@ describe('isBlockhashValid', () => { }); (['confirmed', 'finalized', 'processed'] as Commitment[]).forEach(commitment => { describe(`when called with \`${commitment}\` commitment`, () => { - it('returns the result as a bool wrapped in an RpcResponse', async () => { + it('returns the result as a bool wrapped in an RpcResponseData', async () => { expect.assertions(1); const blockhash = '9PCVWkKP3bq1sT5eLFurUysMvVs4PxJsTfza5QSBB4d1' as Blockhash; const result = await rpc.isBlockhashValid(blockhash, { commitment }).send(); diff --git a/packages/rpc-spec-types/src/rpc-response.ts b/packages/rpc-spec-types/src/rpc-response.ts index 9b391507e5ef..485323271f71 100644 --- a/packages/rpc-spec-types/src/rpc-response.ts +++ b/packages/rpc-spec-types/src/rpc-response.ts @@ -2,10 +2,11 @@ interface IHasIdentifier { readonly id: number; } -type RpcErrorResponse = Readonly<{ +type RpcErrorResponsePayload = Readonly<{ code: number; data?: unknown; message: string; }>; -export type RpcResponse = IHasIdentifier & Readonly<{ error: RpcErrorResponse } | { result: TResponse }>; +export type RpcResponseData = IHasIdentifier & + Readonly<{ error: RpcErrorResponsePayload } | { result: TResponse }>; diff --git a/packages/rpc-spec/src/rpc.ts b/packages/rpc-spec/src/rpc.ts index dec275b7f66d..c94667009b1b 100644 --- a/packages/rpc-spec/src/rpc.ts +++ b/packages/rpc-spec/src/rpc.ts @@ -3,7 +3,7 @@ import { createRpcMessage, Flatten, OverloadImplementations, - RpcResponse, + RpcResponseData, UnionToIntersection, } from '@solana/rpc-spec-types'; @@ -69,7 +69,7 @@ function createPendingRpcRequest { const { methodName, params, responseTransformer } = pendingRequest; const payload = createRpcMessage(methodName, params); - const response = await rpcConfig.transport>({ + const response = await rpcConfig.transport>({ payload, signal: options?.abortSignal, }); diff --git a/packages/rpc-subscriptions-spec/src/rpc-subscriptions.ts b/packages/rpc-subscriptions-spec/src/rpc-subscriptions.ts index 694fe0df9396..4c956e658383 100644 --- a/packages/rpc-subscriptions-spec/src/rpc-subscriptions.ts +++ b/packages/rpc-subscriptions-spec/src/rpc-subscriptions.ts @@ -9,7 +9,7 @@ import { createRpcMessage, Flatten, OverloadImplementations, - RpcResponse, + RpcResponseData, UnionToIntersection, } from '@solana/rpc-spec-types'; @@ -155,7 +155,7 @@ function createPendingRpcSubscription< * STEP 2: Wait for the acknowledgement from the server with the subscription id. */ for await (const message of connection as AsyncIterable< - RpcNotification | RpcResponse + RpcNotification | RpcResponseData >) { if ('id' in message && message.id === subscribeMessage.id) { if ('error' in message) { @@ -175,7 +175,7 @@ function createPendingRpcSubscription< return { async *[Symbol.asyncIterator]() { for await (const message of connection as AsyncIterable< - RpcNotification | RpcResponse + RpcNotification | RpcResponseData >) { if (!('params' in message) || message.params.subscription !== subscriptionId) { continue;