Skip to content

Commit

Permalink
fixup! refactor(experimental): add getBlockProduction API
Browse files Browse the repository at this point in the history
  • Loading branch information
mcintyre94 committed Apr 21, 2023
1 parent 18f642a commit 0322ad5
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { createJsonRpcTransport } from '@solana/rpc-transport';
import type { SolanaJsonRpcErrorCode } from '@solana/rpc-transport/dist/types/json-rpc-transport/json-rpc-errors';
import type { Transport } from '@solana/rpc-transport/dist/types/json-rpc-transport/json-rpc-transport-types';
import { createHttpTransport, createJsonRpc } from '@solana/rpc-transport';
import type { SolanaJsonRpcErrorCode } from '@solana/rpc-transport/dist/types/json-rpc-errors';
import type { Rpc } from '@solana/rpc-transport/dist/types/json-rpc-types';
import fetchMock from 'jest-fetch-mock-fork';
import { createSolanaRpcApi, SolanaRpcMethods } from '../../index';
import { Commitment } from '../common';
import { Base58EncodedAddress } from '@solana/keys';

describe('getBalance', () => {
let transport: Transport<SolanaRpcMethods>;
describe('getBlockProduction', () => {
let rpc: Rpc<SolanaRpcMethods>;
beforeEach(() => {
fetchMock.resetMocks();
fetchMock.dontMock();
transport = createJsonRpcTransport({
rpc = createJsonRpc<SolanaRpcMethods>({
api: createSolanaRpcApi(),
url: 'http://127.0.0.1:8899',
transport: createHttpTransport({ url: 'http://127.0.0.1:8899' }),
});
});

(['confirmed', 'finalized', 'processed'] as Commitment[]).forEach(commitment => {
describe(`when called with \`${commitment}\` commitment`, () => {
it('returns block production data', async () => {
expect.assertions(1);
const blockProductionPromise = transport.getBlockProduction({ commitment }).send();
const blockProductionPromise = rpc.getBlockProduction({ commitment }).send();
await expect(blockProductionPromise).resolves.toMatchObject({
value: expect.objectContaining({
byIdentity: expect.toBeObject(),
Expand All @@ -35,10 +35,8 @@ describe('getBalance', () => {

it('has the latest context slot as the last slot', async () => {
expect.assertions(1);
const blockProductionPromise = transport.getBlockProduction({ commitment }).send();
await expect(blockProductionPromise).resolves.toSatisfy(
rpcResponse => rpcResponse.context.slot === rpcResponse.value.range.lastSlot
);
const blockProduction = await rpc.getBlockProduction({ commitment }).send();
expect(blockProduction.value.range.lastSlot).toBe(blockProduction.context.slot);
});
});
});
Expand All @@ -51,7 +49,7 @@ describe('getBalance', () => {
expect.assertions(1);
// Randomly generated address, assumed not to be a block producer
const identity = '9NmqDDZa7mH1DBM4zeq9cm7VcRn2un1i2TwuMvjBoVhU' as Base58EncodedAddress;
const blockProductionPromise = transport.getBlockProduction({ identity }).send();
const blockProductionPromise = rpc.getBlockProduction({ identity }).send();
await expect(blockProductionPromise).resolves.toMatchObject({
value: expect.objectContaining({
byIdentity: expect.toBeEmptyObject(),
Expand All @@ -63,7 +61,7 @@ describe('getBalance', () => {
describe('when called with a `lastSlot` higher than the highest slot available', () => {
it('throws an error', async () => {
expect.assertions(1);
const blockProductionPromise = transport
const blockProductionPromise = rpc
.getBlockProduction({
range: {
firstSlot: 0n,
Expand All @@ -72,7 +70,7 @@ describe('getBalance', () => {
})
.send();
await expect(blockProductionPromise).rejects.toMatchObject({
code: -32602 satisfies (typeof SolanaJsonRpcErrorCode)['JSON_RPC_SERVER_ERROR_LAST_SLOT_TOO_LARGE'],
code: -32602 satisfies (typeof SolanaJsonRpcErrorCode)['JSON_RPC_INVALID_PARAMS'],
message: expect.any(String),
name: 'SolanaJsonRpcError',
});
Expand Down
37 changes: 27 additions & 10 deletions packages/rpc-core/src/rpc-methods/getBlockProduction.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
import { Base58EncodedAddress } from '@solana/keys';
import { Commitment, RpcResponse, U64UnsafeBeyond2Pow53Minus1 } from './common';

type NumberOfLeaderSlots = number;
type NumberOfBlocksProduced = number;
type NumberOfLeaderSlots = U64UnsafeBeyond2Pow53Minus1;
type NumberOfBlocksProduced = U64UnsafeBeyond2Pow53Minus1;

type Range = Readonly<{
type SlotRange = Readonly<{
firstSlot: U64UnsafeBeyond2Pow53Minus1;
lastSlot: U64UnsafeBeyond2Pow53Minus1;
}>;

type GetBlockProductionApiResponse = RpcResponse<{
byIdentity: Readonly<{
[address: string]: [NumberOfLeaderSlots, NumberOfBlocksProduced];
type GetBlockProductionApiResponseBase = RpcResponse<{
range: SlotRange;
}>;

type GetBlockProductionApiResponseWithAllIdentities = Readonly<{
value: Readonly<{
byIdentity: Record<Base58EncodedAddress, [NumberOfLeaderSlots, NumberOfBlocksProduced]>;
}>;
}>;

type GetBlockProductionApiResponseWithSingleIdentity<TIdentity extends string> = Readonly<{
value: Readonly<{
byIdentity: { [TAddress in TIdentity]?: [NumberOfLeaderSlots, NumberOfBlocksProduced] };
}>;
range: Range;
}>;

export interface GetBlockProductionApi {
/**
* Returns recent block production information from the current or previous epoch.
*/
getBlockProduction(
config: Readonly<{
commitment?: Commitment;
identity: Base58EncodedAddress;
range?: SlotRange;
}>
): GetBlockProductionApiResponseBase & GetBlockProductionApiResponseWithSingleIdentity<typeof config.identity>;

getBlockProduction(
config?: Readonly<{
commitment?: Commitment;
identity?: Base58EncodedAddress;
range?: Range;
identity: undefined;
range?: SlotRange;
}>
): GetBlockProductionApiResponse;
): GetBlockProductionApiResponseBase & GetBlockProductionApiResponseWithAllIdentities;
}
2 changes: 1 addition & 1 deletion packages/rpc-transport/src/json-rpc-errors.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Keep in sync with https://github.com/solana-labs/solana/blob/master/rpc-client-api/src/custom_error.rs
// Typescript `enums` thwart tree-shaking. See https://bargsten.org/jsts/enums/
export const SolanaJsonRpcErrorCode = {
JSON_RPC_INVALID_PARAMS: -32602,
JSON_RPC_SCAN_ERROR: -32012,
JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP: -32001,
JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: -32004,
JSON_RPC_SERVER_ERROR_BLOCK_STATUS_NOT_AVAILABLE_YET: -32014,
JSON_RPC_SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX: -32010,
JSON_RPC_SERVER_ERROR_LAST_SLOT_TOO_LARGE: -32602,
JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED: -32009,
JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED: -32016,
JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY: -32005,
Expand Down
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0322ad5

Please sign in to comment.