diff --git a/web3.js/module.flow.js b/web3.js/module.flow.js index 25e198a764..03c41b0fe4 100644 --- a/web3.js/module.flow.js +++ b/web3.js/module.flow.js @@ -86,6 +86,23 @@ declare module '@solana/web3.js' { Err: Object, |}; + declare export type Inflation = { + foundation: number, + foundation_term: number, + initial: number, + storage: number, + taper: number, + terminal: number, + }; + + declare export type EpochSchedule = { + slots_per_epoch: number, + leader_schedule_slot_offset: number, + warmup: boolean, + first_normal_epoch: number, + first_normal_slot: number, + }; + declare export class Connection { constructor(endpoint: string): Connection; getAccountInfo(publicKey: PublicKey): Promise; @@ -103,6 +120,8 @@ declare module '@solana/web3.js' { ): Promise; getTransactionCount(): Promise; getTotalSupply(): Promise; + getInflation(): Promise; + getEpochSchedule(): Promise; getRecentBlockhash(): Promise<[Blockhash, FeeCalculator]>; requestAirdrop( to: PublicKey, diff --git a/web3.js/src/connection.js b/web3.js/src/connection.js index 702c405201..e118ab00ed 100644 --- a/web3.js/src/connection.js +++ b/web3.js/src/connection.js @@ -68,16 +68,15 @@ type VoteAccountStatus = { /** * Network Inflation parameters + * (see https://docs.solana.com/book/v/master/implemented-proposals/ed_overview) * - * @typedef {Object} Inflation TODO - link to book terminology? - * @property {number} foundation TODO - link to book terminology? - * @property {number} foundation_term TODO - link to book terminology? - * @property {number} grant TODO - link to book terminology? - * @property {number} grant_term TODO - link to book terminology? - * @property {number} initial TODO - link to book terminology? - * @property {number} storage TODO - link to book terminology? - * @property {number} taper TODO - link to book terminology? - * @property {number} terminal TODO - link to book terminology? + * @typedef {Object} Inflation + * @property {number} foundation + * @property {number} foundation_term + * @property {number} initial + * @property {number} storage + * @property {number} taper + * @property {number} terminal */ const GetInflationResult = struct({ foundation: 'number', @@ -88,6 +87,25 @@ const GetInflationResult = struct({ terminal: 'number', }); +/** + * EpochSchedule parameters + * (see https://docs.solana.com/book/v/master/terminology#epoch) + * + * @typedef {Object} EpochSchedule + * @property {number} slots_per_epoch + * @property {number} leader_schedule_slot_offset + * @property {boolean} warmup + * @property {number} first_normal_epoch + * @property {number} first_normal_slot + */ +const GetEpochScheduleResult = struct({ + slots_per_epoch: 'number', + leader_schedule_slot_offset: 'number', + warmup: 'boolean', + first_normal_epoch: 'number', + first_normal_slot: 'number', +}); + function createRpcRequest(url): RpcRequest { const server = jayson(async (request, callback) => { const options = { @@ -130,6 +148,16 @@ const GetInflationRpcResult = struct({ result: GetInflationResult, }); +/** + * Expected JSON RPC response for the "getEpochSchedule" message + */ +const GetEpochScheduleRpcResult = struct({ + jsonrpc: struct.literal('2.0'), + id: 'string', + error: 'any?', + result: GetEpochScheduleResult, +}); + /** * Expected JSON RPC response for the "getBalance" message */ @@ -678,7 +706,7 @@ export class Connection { } /** - * Fetch the cluster Inflation parameters (TODO - book link/terminology?) + * Fetch the cluster Inflation parameters */ async getInflation(): Promise { const unsafeRes = await this._rpcRequest('getInflation', []); @@ -690,6 +718,19 @@ export class Connection { return GetInflationResult(res.result); } + /** + * Fetch the Epoch Schedule parameters + */ + async getEpochSchedule(): Promise { + const unsafeRes = await this._rpcRequest('getEpochSchedule', []); + const res = GetEpochScheduleRpcResult(unsafeRes); + if (res.error) { + throw new Error(res.error.message); + } + assert(typeof res.result !== 'undefined'); + return GetEpochScheduleResult(res.result); + } + /** * Fetch the minimum balance needed to exempt an account of `dataLength` * size from rent diff --git a/web3.js/test/connection.test.js b/web3.js/test/connection.test.js index 0880cf68dc..ae34f7124f 100644 --- a/web3.js/test/connection.test.js +++ b/web3.js/test/connection.test.js @@ -170,6 +170,43 @@ test('get inflation', async () => { } }); +test('get epoch schedule', async () => { + const connection = new Connection(url); + + mockRpc.push([ + url, + { + method: 'getEpochSchedule', + params: [], + }, + { + error: null, + result: { + first_normal_epoch: 8, + first_normal_slot: 8160, + leader_schedule_slot_offset: 8192, + slots_per_epoch: 8192, + warmup: true, + }, + }, + ]); + + const epochSchedule = await connection.getEpochSchedule(); + + for (const key of [ + 'first_normal_epoch', + 'first_normal_slot', + 'leader_schedule_slot_offset', + 'slots_per_epoch', + ]) { + expect(epochSchedule).toHaveProperty(key); + expect(epochSchedule[key]).toBeGreaterThan(0); + } + + expect(epochSchedule).toHaveProperty('warmup'); + expect(epochSchedule.warmup).toBeTruthy(); +}); + test('get slot', async () => { const connection = new Connection(url);