diff --git a/web3.js/module.d.ts b/web3.js/module.d.ts index b86805c175..7d4d6bb854 100644 --- a/web3.js/module.d.ts +++ b/web3.js/module.d.ts @@ -173,6 +173,13 @@ declare module '@solana/web3.js' { firstNormalSlot: number; }; + export type Supply = { + total: number; + circulating: number; + nonCirculating: number; + nonCirculatingAccounts: Array; + }; + export type VoteAccountStatus = { current: Array; delinquent: Array; @@ -200,6 +207,7 @@ declare module '@solana/web3.js' { getBalance(publicKey: PublicKey, commitment?: Commitment): Promise; getBlockTime(slot: number): Promise; getMinimumLedgerSlot(): Promise; + getSupply(commitment?: Commitment): Promise>; getClusterNodes(): Promise>; getConfirmedBlock(slot: number): Promise; getConfirmedTransaction( diff --git a/web3.js/module.flow.js b/web3.js/module.flow.js index 7c55d59eac..9efe8726be 100644 --- a/web3.js/module.flow.js +++ b/web3.js/module.flow.js @@ -186,6 +186,13 @@ declare module '@solana/web3.js' { absoluteSlot: number, }; + declare export type Supply = { + total: number, + circulating: number, + nonCirculating: number, + nonCirculatingAccounts: Array, + }; + declare export type VoteAccountStatus = { current: Array, delinquent: Array, @@ -213,6 +220,7 @@ declare module '@solana/web3.js' { getBalance(publicKey: PublicKey, commitment: ?Commitment): Promise; getBlockTime(slot: number): Promise; getMinimumLedgerSlot(): Promise; + getSupply(commitment: ?Commitment): Promise>; getClusterNodes(): Promise>; getConfirmedBlock(slot: number): Promise; getConfirmedTransaction( diff --git a/web3.js/src/connection.js b/web3.js/src/connection.js index c3bf18f87b..d0019e760b 100644 --- a/web3.js/src/connection.js +++ b/web3.js/src/connection.js @@ -403,6 +403,34 @@ const MinimumLedgerSlotRpcResult = struct({ result: 'number', }); +/** + * Supply + * + * @typedef {Object} Supply + * @property {number} total Total supply in lamports + * @property {number} circulating Circulating supply in lamports + * @property {number} nonCirculating Non-circulating supply in lamports + * @property {Array} nonCirculatingAccounts List of non-circulating account addresses + */ +type Supply = { + total: number, + circulating: number, + nonCirculating: number, + nonCirculatingAccounts: Array, +}; + +/** + * Expected JSON RPC response for the "getSupply" message + */ +const GetSupplyRpcResult = jsonRpcResultAndContext( + struct({ + total: 'number', + circulating: 'number', + nonCirculating: 'number', + nonCirculatingAccounts: struct.array(['string']), + }), +); + /** * Expected JSON RPC response for the "getVersion" message */ @@ -1016,6 +1044,25 @@ export class Connection { return res.result; } + /** + * Fetch information about the current supply + */ + async getSupply( + commitment: ?Commitment, + ): Promise> { + const args = this._argsWithCommitment([], commitment); + const unsafeRes = await this._rpcRequest('getSupply', args); + const res = GetSupplyRpcResult(unsafeRes); + if (res.error) { + throw new Error('failed to get supply: ' + res.error.message); + } + assert(typeof res.result !== 'undefined'); + res.result.value.nonCirculatingAccounts = res.result.value.nonCirculatingAccounts.map( + account => new PublicKey(account), + ); + return res.result; + } + /** * Fetch all the account info for the specified public key, return with context */ diff --git a/web3.js/test/connection.test.js b/web3.js/test/connection.test.js index 303bd40d4f..55e8abd291 100644 --- a/web3.js/test/connection.test.js +++ b/web3.js/test/connection.test.js @@ -1109,6 +1109,38 @@ test('get minimum ledger slot', async () => { expect(minimumLedgerSlot).toBeGreaterThanOrEqual(0); }); +test('get supply', async () => { + const connection = new Connection(url); + + mockRpc.push([ + url, + { + method: 'getSupply', + params: [], + }, + { + error: null, + result: { + context: { + slot: 1, + }, + value: { + total: 1000, + circulating: 100, + nonCirculating: 900, + nonCirculatingAccounts: [new Account().publicKey.toBase58()], + }, + }, + }, + ]); + + const supply = (await connection.getSupply()).value; + expect(supply.total).toBeGreaterThan(0); + expect(supply.circulating).toBeGreaterThan(0); + expect(supply.nonCirculating).toBeGreaterThan(0); + expect(supply.nonCirculatingAccounts.length).toBeGreaterThan(0); +}); + test('getVersion', async () => { const connection = new Connection(url);