Skip to content

Commit

Permalink
Extract isJsonRpcPayload method to rpc-spec
Browse files Browse the repository at this point in the history
  • Loading branch information
lorisleiva committed Sep 10, 2024
1 parent 42cece0 commit 0d92cd7
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-snakes-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solana/rpc-spec': patch
---

Add new `isJsonRpcPayload` helper method
17 changes: 17 additions & 0 deletions packages/rpc-spec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,20 @@ A config object with the following properties:

- `requestTransformer<T>(request: RpcRequest<T>): RpcRequest`: An optional function that transforms the `RpcRequest` before it is sent to the JSON RPC server.
- `responseTransformer<T>(response: RpcResponse, request: RpcRequest): RpcResponse<T>`: An optional function that transforms the `RpcResponse` before it is returned to the caller.

### `isJsonRpcPayload(payload)`

A helper function that returns `true` if the given payload is a JSON RPC v2 payload. This means, the payload is an object such that:

- It has a `jsonrpc` property with a value of `'2.0'`.
- It has a `method` property that is a string.
- It has a `params` property of any type.

```ts
import { isJsonRpcPayload } from '@solana/rpc-spec';

if (isJsonRpcPayload(payload)) {
const payloadMethod: string = payload.method;
const payloadParams: unknown = payload.params;
}
```
29 changes: 29 additions & 0 deletions packages/rpc-spec/src/__tests__/rpc-transport-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { isJsonRpcPayload } from '../rpc-transport';

describe('isJsonRpcPayload', () => {
it('recognizes JSON RPC payloads', () => {
expect(isJsonRpcPayload({ jsonrpc: '2.0', method: 'getFoo', params: [123] })).toBe(true);
});
it('returns false if the payload is not an object', () => {
expect(isJsonRpcPayload(undefined)).toBe(false);
expect(isJsonRpcPayload(null)).toBe(false);
expect(isJsonRpcPayload(true)).toBe(false);
expect(isJsonRpcPayload(false)).toBe(false);
expect(isJsonRpcPayload([])).toBe(false);
expect(isJsonRpcPayload('o hai')).toBe(false);
expect(isJsonRpcPayload(123)).toBe(false);
expect(isJsonRpcPayload(123n)).toBe(false);
});
it('returns false if the payload is an empty object', () => {
expect(isJsonRpcPayload({})).toBe(false);
});
it('returns false if the payload is not a JSON RPC v2', () => {
expect(isJsonRpcPayload({ jsonrpc: '42.0', method: 'getFoo', params: [123] })).toBe(false);
});
it('returns false if the method name is missing', () => {
expect(isJsonRpcPayload({ jsonrpc: '2.0', params: [123] })).toBe(false);
});
it('returns false if the parameters are missing', () => {
expect(isJsonRpcPayload({ jsonrpc: '2.0', method: 'getFoo' })).toBe(false);
});
});
9 changes: 9 additions & 0 deletions packages/rpc-spec/src/__typetests__/rpc-transport-typetest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { isJsonRpcPayload } from '../rpc-transport';

{
// [isJsonRpcPayload]: It narrows the type of the payload to a JSON RPC payload.
const payload = {} as unknown;
if (isJsonRpcPayload(payload)) {
payload satisfies { jsonrpc: '2.0'; method: string; params: unknown };
}
}
17 changes: 17 additions & 0 deletions packages/rpc-spec/src/rpc-transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,20 @@ type RpcTransportRequest = Readonly<{
export type RpcTransport = {
<TResponse>(request: RpcTransportRequest): Promise<RpcResponse<TResponse>>;
};

export function isJsonRpcPayload(payload: unknown): payload is Readonly<{
jsonrpc: '2.0';
method: string;
params: unknown;
}> {
if (payload == null || typeof payload !== 'object' || Array.isArray(payload)) {
return false;
}
return (
'jsonrpc' in payload &&
payload.jsonrpc === '2.0' &&
'method' in payload &&
typeof payload.method === 'string' &&
'params' in payload
);
}
14 changes: 1 addition & 13 deletions packages/rpc/src/rpc-request-deduplication.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import fastStableStringify from '@solana/fast-stable-stringify';

function isJsonRpcPayload(payload: unknown): payload is Readonly<{ method: string; params: unknown }> {
if (payload == null || typeof payload !== 'object' || Array.isArray(payload)) {
return false;
}
return (
'jsonrpc' in payload &&
payload.jsonrpc === '2.0' &&
'method' in payload &&
typeof payload.method === 'string' &&
'params' in payload
);
}
import { isJsonRpcPayload } from '@solana/rpc-spec';

export function getSolanaRpcPayloadDeduplicationKey(payload: unknown): string | undefined {
return isJsonRpcPayload(payload) ? fastStableStringify([payload.method, payload.params]) : undefined;
Expand Down

0 comments on commit 0d92cd7

Please sign in to comment.