Skip to content

Commit

Permalink
Rename RpcResponse to RpcResponseData (#3145)
Browse files Browse the repository at this point in the history
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<TParams = unknown> = {
  readonly methodName: string;
  readonly params: TParams;
}

type RpcResponse<TResponse = unknown> = {
  readonly json: () => Promise<TResponse>;
  readonly text: () => Promise<string>;
}


type RpcRequestTransformer = {
    <TParams>(request: RpcRequest<unknown>): RpcRequest<TParams>;
};

type RpcResponseTransformer = {
    <TResponse>(response: RpcResponse<unknown>, request: RpcRequest<unknown>): RpcResponse<TResponse>;
};

type RpcResponseTransformerFor<TResponse> = {
    (response: RpcResponse<unknown>, request: RpcRequest<unknown>): RpcResponse<TResponse>;
};
```

### RPC Transport Layer

```ts
type RpcTransportRequest = {
  readonly payload: unknown;
  readonly signal?: AbortSignal;
}


type RpcTransport = {
  <TResponse>(
    request: RpcTransportRequest
  ): Promise<RpcResponse<TResponse>>;
}
```

### RPC API Layer

```ts
type RpcApi<TRpcMethods> = { ... }

type RpcApiConfig = {
  readonly requestTransformer?: RpcRequestTransformer;
  readonly responseTransformer?: RpcResponseTransformer;
}

type PendingRpcApiRequest<TResponse> = RpcRequest & {
    responseTransformer?: RpcResponseTransformerFor<TResponse>;
};
```

### RPC Layer

```ts
type PendingRpcRequest<TResponse> = {
  // Nothing changes here but the final send function returns the result of `response.json()`.
  send(options?: RpcSendOptions): Promise<TResponse>;
};
```

---

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.
  • Loading branch information
lorisleiva authored Sep 1, 2024
1 parent 1193f5f commit 1c25dd4
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 9 deletions.
8 changes: 8 additions & 0 deletions .changeset/gorgeous-foxes-type.md
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion packages/rpc-api/src/__tests__/is-blockhash-valid-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 3 additions & 2 deletions packages/rpc-spec-types/src/rpc-response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ interface IHasIdentifier {
readonly id: number;
}

type RpcErrorResponse = Readonly<{
type RpcErrorResponsePayload = Readonly<{
code: number;
data?: unknown;
message: string;
}>;

export type RpcResponse<TResponse> = IHasIdentifier & Readonly<{ error: RpcErrorResponse } | { result: TResponse }>;
export type RpcResponseData<TResponse> = IHasIdentifier &
Readonly<{ error: RpcErrorResponsePayload } | { result: TResponse }>;
4 changes: 2 additions & 2 deletions packages/rpc-spec/src/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
createRpcMessage,
Flatten,
OverloadImplementations,
RpcResponse,
RpcResponseData,
UnionToIntersection,
} from '@solana/rpc-spec-types';

Expand Down Expand Up @@ -69,7 +69,7 @@ function createPendingRpcRequest<TRpcMethods, TRpcTransport extends RpcTransport
async send(options?: RpcSendOptions): Promise<TResponse> {
const { methodName, params, responseTransformer } = pendingRequest;
const payload = createRpcMessage(methodName, params);
const response = await rpcConfig.transport<RpcResponse<unknown>>({
const response = await rpcConfig.transport<RpcResponseData<unknown>>({
payload,
signal: options?.abortSignal,
});
Expand Down
6 changes: 3 additions & 3 deletions packages/rpc-subscriptions-spec/src/rpc-subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
createRpcMessage,
Flatten,
OverloadImplementations,
RpcResponse,
RpcResponseData,
UnionToIntersection,
} from '@solana/rpc-spec-types';

Expand Down Expand Up @@ -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<unknown> | RpcResponse<RpcSubscriptionId>
RpcNotification<unknown> | RpcResponseData<RpcSubscriptionId>
>) {
if ('id' in message && message.id === subscribeMessage.id) {
if ('error' in message) {
Expand All @@ -175,7 +175,7 @@ function createPendingRpcSubscription<
return {
async *[Symbol.asyncIterator]() {
for await (const message of connection as AsyncIterable<
RpcNotification<unknown> | RpcResponse<RpcSubscriptionId>
RpcNotification<unknown> | RpcResponseData<RpcSubscriptionId>
>) {
if (!('params' in message) || message.params.subscription !== subscriptionId) {
continue;
Expand Down

0 comments on commit 1c25dd4

Please sign in to comment.