solana-web3.js
solana-web3.js copied to clipboard
[experimental] RPC method typespec contribution guide
The new experimental @solana/web3.js implements every RPC method as a type specification. These typespecs power autocomplete in your editor, and help you verify your program's type safety using Typescript – both in terms of the values you send to the Solana JSON-RPC, and in terms of the responses that you get from it.
You're here because you're interested in contributing a type specification to the project. This is a great way to learn more about how the Solana RPC works, and the best way to add support for the methods you need in the new @solana/web3.js.
How?
In general, the way you add support for an RPC method is by writing a Typescript interface that describes its inputs and outputs. This interface must match the inputs/outputs of the JSON-RPC exactly. Same positional order for the input arguments, same shape for the output return type.
type GetTokenAccountBalanceApiConfig = Readonly<{
committment?: Commitment,
}>;
type GetTokenAccountBalanceApiResponse = Readonly<{
// the raw balance without decimals, a string representation of u64
amount: string,
// number of base 10 digits to the right of the decimal place
decimals: number,
/** @deprecated Use `uiAmountString` instead */
// the balance, using mint-prescribed decimals
uiAmount: number | null,
// the balance as a string, using mint-prescribed decimals
uiAmountString: string,
}>
export interface GetTokenAccountBalanceApi {
getTokenAccountBalance(
// Pubkey of Token account to query, as base-58 encoded string
address: Base58EncodedAddress,
config?: GetTokenAccountBalanceApiConfig,
): Promise<GetTokenAccountBalanceApiResponse>
}
A perfectly-crafted interface is only the beginning; to get a PR accepted, make sure to go through the checklist below to finish it up.
Have an example?
Study this PR; it's a good example of how to go about adding a method to the RPC. It is also a good example of some of the challenges you might bump up against.
Checklist
Before you send your own PR, copy and paste this checklist into your PR description.
- [ ] I read the [JSON-RPC docs](https://docs.solana.com/api/http) for my method and implemented it faithfully as a Typescript interface in [`packages/rpc-core/src/rpc-methods`](https://github.com/solana-labs/solana-web3.js/tree/master/packages/rpc-core/src/rpc-methods)
- [ ] I have commented the inputs and outputs of my Typescript interface using text from the JSON-RPC docs
- [ ] I have read through the Rust source code of my RPC method to make sure that it accepts the inputs that I expect, returns the outputs that I expect, and applies the defaults I expect when an input is not supplied
- [ ] Wherever my method's return value changes based on its inputs, I've implemented that as a [Typescript function overload](https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads) ([example](https://github.com/solana-labs/solana-web3.js/blob/b69daf278045bc96740450e123a322e0dd95f60e/packages/rpc-core/src/rpc-methods/getAccountInfo.ts#L80-L114))
- [ ] I have written a test in [`packages/rpc-core/src/rpc-methods/__tests__`](https://github.com/solana-labs/solana-web3.js/tree/master/packages/rpc-core/src/rpc-methods/__tests__) that exercises as much of my RPC method's functionality as is practical
- [ ] Wherever my test relies on reading account data I have created an account fixture in [`scripts/fixtures`](https://github.com/solana-labs/solana-web3.js/tree/master/scripts/fixtures) that gets loaded into the test validator ([example](https://github.com/solana-labs/solana-web3.js/blob/master/scripts/fixtures/4nTLDQiSTRHbngKZWPMfYnZdWTbKiNeuuPcX7yFUpSAc.json))
- [ ] If my RPC method returns a numeric value _other_ than a `u64` or `usize` (eg. a `u8`) I have encoded an exception for that return value so that it does _not_ get upcast to a `bigint` in the RPC ([example](https://github.com/solana-labs/solana-web3.js/blob/b69daf278045bc96740450e123a322e0dd95f60e/packages/rpc-core/src/response-patcher-allowed-numeric-values.ts#L12))