This repository has been archived by the owner on Jan 13, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 919
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(experimental): add generic
createJsonRpcApi
function for c…
…ustom APIs This PR is a concept for now. It serves to potentially address the discussion raised in #1740. The goal of the collective `@solana/rpc-*` packages has been to allow complete customization, as long as their API adheres to the [official JSON RPC spec](https://www.jsonrpc.org/specification). However, I couldn't find the best way someone would _actually_ go about doing this with our current implementation. Maybe I'm missing something. In the actual `library` package, we're providing what's been dubbed the "default" Solana API. The function `createSolanaRpc(..)` allows you to provide your own transport, but it automatically uses the Solana RPC API, defined by `@solana/rpc-core` for the client API. https://github.com/solana-labs/solana-web3.js/blob/589c379aa0ab495f50dac873f06573f52cdc9f98/packages/library/src/rpc.ts#L19-L24 If one wants to create their own RPC client manually, they can use the following code, comprised of `@solana/rpc-transport` and `@solana/rpc-core`, _not_ the main library. ```typescript const api = createSolanaRpcApi(); // ^ IRpcApi<SolanaRpcMethods> const transport = createHttpTransport({ url: 'http://127.0.0.1:8899' }); const rpc = createJsonRpc<SolanaRpcMethods>({ api, transport }); // ^ RpcMethods<SolanaRpcMethods> ``` You can see you can choose to define your API and provide it as a parameter to `createJsonRpc(..)`, however unless I'm missing something in our code, there's no generic API-creator. This PR attempts to roll that generic API-creator as `createJsonRpcApi(..)`. I envision this function being extremely useful for projects who wish to define their own `rpc-core` type-spec via interfaces, as we have with `SolanaRpcMethods`, and simply create it like so: ```typescript // Define the method's response payload type NftCollectionDetailsApiResponse = Readonly<{ address: string; circulatingSupply: number; description: string; erc721: boolean; erc1155: boolean; genesisBlock: string; genesisTransaction: string; name: string; totalSupply: number; }>; // Set up an interface for the request method interface NftCollectionDetailsApi { // Define the method's name, parameters and response type qn_fetchNFTCollectionDetails(args: { contracts: string[] }): NftCollectionDetailsApiResponse; } // Export the type spec for downstream users export type QuickNodeRpcMethods = NftCollectionDetailsApi; // Create the custom API const api = createJsonRpcApi<QuickNodeRpcMethods>(); // Set up an HTTP transport const transport = createHttpTransport({ url: 'http://127.0.0.1:8899' }); // Create the RPC client const quickNodeRpc = createJsonRpc<QuickNodeRpcMethods>({ api, transport }); // ^ RpcMethods<QuickNodeRpcMethods> ``` Of course you could _also_ combine your type spec with Solana's: ```typescript export type QuickNodeSolanaRpcMethods = SolanaRpcMethods & NftCollectionDetailsApi; ``` Let me know any thoughts.
- Loading branch information
1 parent
9f2b2fd
commit 1e2106f
Showing
7 changed files
with
78 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
packages/rpc-transport/src/apis/__typetests__/methods-api-typetest.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { IRpcApi } from '../../json-rpc-types'; | ||
import { IRpcApiMethods } from '../api-types'; | ||
import { createJsonRpcApi } from '../methods/methods-api'; | ||
|
||
type NftCollectionDetailsApiResponse = Readonly<{ | ||
address: string; | ||
circulatingSupply: number; | ||
description: string; | ||
erc721: boolean; | ||
erc1155: boolean; | ||
genesisBlock: string; | ||
genesisTransaction: string; | ||
name: string; | ||
totalSupply: number; | ||
}>; | ||
|
||
interface NftCollectionDetailsApi extends IRpcApiMethods { | ||
qn_fetchNFTCollectionDetails(args: { contracts: string[] }): NftCollectionDetailsApiResponse; | ||
} | ||
|
||
type QuickNodeRpcMethods = NftCollectionDetailsApi; | ||
|
||
createJsonRpcApi<QuickNodeRpcMethods>() satisfies IRpcApi<QuickNodeRpcMethods>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { IRpcApi, RpcRequest } from '../../json-rpc-types'; | ||
import { IRpcApiMethods, RpcApiConfig } from '../api-types'; | ||
|
||
export function createJsonRpcApi<TRpcMethods extends IRpcApiMethods>(config?: RpcApiConfig): IRpcApi<TRpcMethods> { | ||
return new Proxy({} as IRpcApi<TRpcMethods>, { | ||
defineProperty() { | ||
return false; | ||
}, | ||
deleteProperty() { | ||
return false; | ||
}, | ||
get<TMethodName extends keyof IRpcApi<TRpcMethods>>( | ||
...args: Parameters<NonNullable<ProxyHandler<IRpcApi<TRpcMethods>>['get']>> | ||
) { | ||
const [_, p] = args; | ||
const methodName = p.toString() as keyof TRpcMethods as string; | ||
return function ( | ||
...rawParams: Parameters< | ||
TRpcMethods[TMethodName] extends CallableFunction ? TRpcMethods[TMethodName] : never | ||
> | ||
): RpcRequest<ReturnType<TRpcMethods[TMethodName]>> { | ||
const params = config?.parametersTransformer | ||
? config?.parametersTransformer(rawParams, methodName) | ||
: rawParams; | ||
const responseTransformer = config?.responseTransformer | ||
? config?.responseTransformer<ReturnType<TRpcMethods[TMethodName]>> | ||
: (rawResponse: unknown) => rawResponse as ReturnType<TRpcMethods[TMethodName]>; | ||
return { | ||
methodName, | ||
params, | ||
responseTransformer, | ||
}; | ||
}; | ||
}, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters