diff --git a/packages/api-derive/src/accounts/idAndIndex.ts b/packages/api-derive/src/accounts/idAndIndex.ts index 9ad37cf91f..b7e72e40e9 100644 --- a/packages/api-derive/src/accounts/idAndIndex.ts +++ b/packages/api-derive/src/accounts/idAndIndex.ts @@ -15,6 +15,19 @@ import { drr } from '../util/drr'; export type AccountIdAndIndex = [AccountId?, AccountIndex?]; +/** + * @name idAndIndex + * @param {(Address | AccountId | AccountIndex | string | null)} address - An accounts address in various formats. + * @description An array containing the [[AccountId]] and [[AccountIndex]] as optional values. + * @example + *
+ * + * ```javascript + * api.derive.accounts.idAndIndex('F7Hs', ([id, ix]) => { + * console.log(`AccountId #${id} with corresponding AccountIndex ${ix}`); + * }); + * ``` + */ export function idAndIndex (api: ApiInterface$Rx) { return (address?: Address | AccountId | AccountIndex | string | null): Observable => { try { diff --git a/packages/api-derive/src/accounts/idToIndex.ts b/packages/api-derive/src/accounts/idToIndex.ts index ee6d6aa918..1fc8018783 100644 --- a/packages/api-derive/src/accounts/idToIndex.ts +++ b/packages/api-derive/src/accounts/idToIndex.ts @@ -10,6 +10,20 @@ import { AccountId, AccountIndex } from '@plugnet/types'; import { indexes, AccountIndexes } from './indexes'; import { drr } from '../util/drr'; +/** + * @name idToIndex + * @param {( AccountId | string )} accountId - An accounts Id in different formats. + * @returns Returns the corresponding AccountIndex. + * @example + *
+ * + * ```javascript + * const ALICE = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; + * api.derive.accounts.idToIndex(ALICE, (accountIndex) => { + * console.log(`The AccountIndex of ${ALICE} is ${accountIndex}`); + * }); + * ``` + */ export function idToIndex (api: ApiInterface$Rx) { return (accountId: AccountId | string): Observable => indexes(api)() diff --git a/packages/api-derive/src/accounts/indexToId.ts b/packages/api-derive/src/accounts/indexToId.ts index 36e0ba1e88..e2c3976ced 100644 --- a/packages/api-derive/src/accounts/indexToId.ts +++ b/packages/api-derive/src/accounts/indexToId.ts @@ -10,6 +10,19 @@ import { AccountId, AccountIndex, Vector } from '@plugnet/types'; import { drr } from '../util/drr'; +/** + * @name indexToId + * @param {( AccountIndex | string )} accountIndex - An accounts index in different formats. + * @returns Returns the corresponding AccountId. + * @example + *
+ * + * ```javascript + * api.derive.accounts.indexToId('F7Hs', (accountId) => { + * console.log(`The AccountId of F7Hs is ${accountId}`); + * }); + * ``` + */ export function indexToId (api: ApiInterface$Rx) { return (_accountIndex: AccountIndex | string): Observable => { const querySection = api.query.indices || api.query.balances; diff --git a/packages/api-derive/src/accounts/indexes.ts b/packages/api-derive/src/accounts/indexes.ts index 42746532b1..b9ee785710 100644 --- a/packages/api-derive/src/accounts/indexes.ts +++ b/packages/api-derive/src/accounts/indexes.ts @@ -15,9 +15,19 @@ export type AccountIndexes = { [index: string]: AccountIndex }; const enumsetSize = ENUMSET_SIZE.toNumber(); /** - * Returns all the indexes on the system - this is an unwieldly query since it loops through + * @name indexes + * @returns Returns all the indexes on the system. + * @description This is an unwieldly query since it loops through * all of the enumsets and returns all of the values found. This could be up to 32k depending * on the number of active accounts in the system + * @example + *
+ * + * ```javascript + * api.derive.accounts.indexes((indexes) => { + * console.log('All existing AccountIndexes', indexes); + * }); + * ``` */ export function indexes (api: ApiInterface$Rx) { return (): Observable => { diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index abda849640..48e8cda7db 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -14,6 +14,22 @@ import { drr } from '../util/drr'; const EMPTY_ACCOUNT = new AccountId(); +/** + * @name all + * @param {( ccountIndex | AccountId | Address | string )} address - An accounts Id in different formats. + * @returns An object containing the combined results of the storage queries for + * all relevant fees as declared in the substrate chain spec. + * @example + *
+ * + * ```javascript + * const ALICE = 'F7Hs'; + * + * api.derive.balances.all(ALICE, ([accountId, lockedBalance]) => { + * console.log(`The account ${accountId} has a locked balance ${lockedBalance} units.`); + * }); + * ``` + */ export function all (api: ApiInterface$Rx) { return (address: AccountIndex | AccountId | Address | string): Observable => { return idAndIndex(api)(address).pipe( diff --git a/packages/api-derive/src/balances/fees.ts b/packages/api-derive/src/balances/fees.ts index 2e466a4c10..f7de1492d4 100644 --- a/packages/api-derive/src/balances/fees.ts +++ b/packages/api-derive/src/balances/fees.ts @@ -10,6 +10,19 @@ import BN from 'bn.js'; import { DerivedFees } from '../types'; import { drr } from '../util/drr'; +/** + * @name fees + * @returns An object containing the combined results of the storage queries for + * all relevant fees as declared in the substrate chain spec. + * @example + *
+ * + * ```javascript + * api.derive.balances.fees(([creationFee, transferFee]) => { + * console.log(`The fee for creating a new account on this chain is ${transferFee} units. The fee required for making a transfer is ${transferFee} units.`); + * }); + * ``` + */ export function fees (api: ApiInterface$Rx) { return (): Observable => { return (api.queryMulti([ diff --git a/packages/api-derive/src/chain/bestNumber.ts b/packages/api-derive/src/chain/bestNumber.ts index 2e2acc18ed..9b1c9a3fde 100644 --- a/packages/api-derive/src/chain/bestNumber.ts +++ b/packages/api-derive/src/chain/bestNumber.ts @@ -10,7 +10,8 @@ import { BlockNumber, Header } from '@plugnet/types'; import { drr } from '../util/drr'; /** - * @description Get the latest block number. + * @name bestNumber + * @returns The latest block number. * @example *
* diff --git a/packages/api-derive/src/chain/bestNumberFinalized.ts b/packages/api-derive/src/chain/bestNumberFinalized.ts index a52a76dcb8..cbd73fa9ad 100644 --- a/packages/api-derive/src/chain/bestNumberFinalized.ts +++ b/packages/api-derive/src/chain/bestNumberFinalized.ts @@ -10,8 +10,10 @@ import { BlockNumber, Header } from '@plugnet/types'; import { drr } from '../util/drr'; /** + * @name bestNumberFinalized + * @returns A BlockNumber * @description Get the latest finalized block number. - * example + * @example *
* * ```javascript diff --git a/packages/api-derive/src/chain/bestNumberLag.ts b/packages/api-derive/src/chain/bestNumberLag.ts index 413c1a7950..3095abf0ea 100644 --- a/packages/api-derive/src/chain/bestNumberLag.ts +++ b/packages/api-derive/src/chain/bestNumberLag.ts @@ -12,6 +12,8 @@ import { bestNumber } from './bestNumber'; import { bestNumberFinalized } from './bestNumberFinalized'; /** + * @name bestNumberLag + * @returns A number of blocks * @description Calculates the lag between finalized head and best head * @example *
diff --git a/packages/api-derive/src/chain/getHeader.ts b/packages/api-derive/src/chain/getHeader.ts index 782d957bd2..fc13bb367a 100644 --- a/packages/api-derive/src/chain/getHeader.ts +++ b/packages/api-derive/src/chain/getHeader.ts @@ -11,8 +11,10 @@ import { drr } from '../util/drr'; import { HeaderAndValidators } from './subscribeNewHead'; /** - * @description Get the a specific block header and extend it with the author - * @param hash: Uint8Array | string + * @name bestNumberFinalized + * @param {( Uint8Array | string )} hash - A block hash as U8 array or string. + * @returns An array containing the block header and the block author + * @description Get a specific block header and extend it with the author * @example *
* diff --git a/packages/api-derive/src/chain/subscribeNewHead.ts b/packages/api-derive/src/chain/subscribeNewHead.ts index 6e5a50b4d7..ea76ea8224 100644 --- a/packages/api-derive/src/chain/subscribeNewHead.ts +++ b/packages/api-derive/src/chain/subscribeNewHead.ts @@ -12,7 +12,9 @@ import { drr } from '../util/drr'; export type HeaderAndValidators = [Header, Array]; /** - * @description Subscribe to block headers and extend it with the author + * @name subscribeNewHead + * @returns An array containing the block header and the block author + * @description An observable of the current block header and it's author * @example *
* diff --git a/packages/api-derive/test/e2e/promise.spec.ts b/packages/api-derive/test/e2e/promise.spec.ts index ad086ceb6b..07e70d18ee 100644 --- a/packages/api-derive/test/e2e/promise.spec.ts +++ b/packages/api-derive/test/e2e/promise.spec.ts @@ -32,7 +32,7 @@ describe.skip('derive e2e', () => { it('subscribes to newHead, retrieving the actual validator', (done) => { return api.derive.chain.subscribeNewHead(({ author }) => { - console.error('author', author.toString()); + console.log('author', author.toString()); if (author) { done(); diff --git a/packages/api-derive/test/e2e/rx.spec.ts b/packages/api-derive/test/e2e/rx.spec.ts index 0c403dc5de..86b6cde827 100644 --- a/packages/api-derive/test/e2e/rx.spec.ts +++ b/packages/api-derive/test/e2e/rx.spec.ts @@ -3,14 +3,19 @@ // of the Apache-2.0 license. See the LICENSE file for details. import BN from 'bn.js'; + import ApiRx from '@plugnet/api/rx/Api'; import { ApiInterface$Rx } from '@plugnet/api/types'; -import { BlockNumber } from '@plugnet/types'; +import { AccountId, AccountIndex, Balance, BlockNumber } from '@plugnet/types'; import { WsProvider } from '@plugnet/rpc-provider'; const WS_LOCAL = 'ws://127.0.0.1:9944/'; // const WS_POC3 = 'wss://poc3-rpc.polkadot.io/'; +// Dev account Alice +const ID = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; +const IX = 'F7Hs'; + describe.skip('derive e2e', () => { let api: ApiInterface$Rx; @@ -23,49 +28,192 @@ describe.skip('derive e2e', () => { done(); }); - it('derive.chain.bestNumber', async (done) => { - api.derive.chain.bestNumber().subscribe((blockNumber) => { - expect(blockNumber instanceof BlockNumber).toBe(true); - expect((blockNumber as BlockNumber).gten(0)).toBe(true); - done(); - }); - }); - - it('derive.session.sessionProgress', async (done) => { - api.derive.session.sessionProgress().subscribe((progress) => { - expect(progress instanceof BN).toBe(true); - done(); - }); - }); - - it('returns the intentions with balances', async (done) => { - api.derive.staking.intentionsBalances().subscribe((balances) => { - expect(Object.keys(balances as object)).not.toHaveLength(0); - done(); - }); - }); - - // these only work on localhost, not the poc-3 URL + // These derive.accounts tests only work on localhost, not the poc-3 URL // (and it is assuming it sent at least 1 tx) - describe('accounts', () => { - const ID = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; - const IX = 'F7Gh'; + describe('derive.accounts', () => { - it('looks up id & index from id', async (done) => { - // @ts-ignore silence warning until we have static types here - api.derive.accounts.idAndIndex(ID).subscribe(([id, ix]) => { - expect(id.toString()).toEqual(ID); - expect(ix.toString()).toEqual(IX); - done(); + describe('idAndIndex', () => { + it('looks up AccountId & AccountIndex from AccountId', async (done) => { + // @ts-ignore silence warning until we have static types here + api.derive.accounts.idAndIndex(ID).subscribe(([accountId, accountIndex]) => { + expect(accountId.toString()).toEqual(ID); + // The first emitted value for ix is undefined when passing the ID + if (accountIndex) { + expect(accountIndex.toString()).toEqual(IX); + } else { + expect(accountIndex).toEqual(undefined); + } + done(); + }); + }); + + it('looks up AccountId & AccountIndex from AccountIndex', async (done) => { + // @ts-ignore silence warning until we have static types here + api.derive.accounts.idAndIndex(IX).subscribe(([accountId, accountIndex]) => { + // The first emitted value for id is undefined when passing the IX + if (accountId) { + expect(accountId.toString()).toEqual(ID); + } else { + expect(accountId).toEqual(undefined); + } + expect(accountIndex.toString()).toEqual(IX); + done(); + }); }); }); - it('looks up id & index from index', async (done) => { - // @ts-ignore silence warning until we have static types here - api.derive.accounts.idAndIndex(IX).subscribe(([id, ix]) => { - expect(id.toString()).toEqual(ID); - expect(ix.toString()).toEqual(IX); - done(); + describe('indexToId', () => { + it('looks up AccountId from AccountIndex', async (done) => { + // @ts-ignore silence warning until we have static types here + api.derive.accounts.indexToId(IX).subscribe((accountId) => { + // The first emitted value for accountId is undefined when passing the IX + if (accountId) { + expect(accountId instanceof AccountId).toBe(true); + expect(accountId.toString()).toEqual(ID); + } else { + expect(accountId).toEqual(undefined); + } + done(); + }); + }); + }); + + describe('idToIndex', () => { + it('looks up AccountIndex from AccountId', async (done) => { + // @ts-ignore silence warning until we have static types here + api.derive.accounts.idToIndex(ID).subscribe((accountIndex) => { + // The first emitted value for AccountIndex is undefined when passing the ID + if (accountIndex) { + expect(accountIndex instanceof AccountIndex).toBe(true); + expect(accountIndex.toString()).toEqual(IX); + } else { + expect(accountIndex).toEqual(undefined); + } + done(); + }); + }); + }); + + describe('indexes', () => { + it('looks up all AccountIndexes', async (done) => { + // @ts-ignore silence warning until we have static types here + api.derive.accounts.indexes().subscribe((accountIndexes) => { + // A local dev chain should have the AccountIndex of Alice + expect(accountIndexes).toHaveProperty( + ID, + new AccountIndex(IX) + ); + done(); + }); + }); + }); + }); + + // these only work on localhost, not the poc-3 URL + // (and it is assuming it sent at least 1 tx) + describe('derive.balances', () => { + describe('all', () => { + it('It returns an object with all relevant balance information of an account', async (done) => { + api.derive.balances.all(ID).subscribe((balances) => { + expect(balances).toEqual(expect.objectContaining({ + accountId: expect.any(AccountId), + availableBalance: expect.any(Balance), + freeBalance: expect.any(Balance), + lockedBalance: expect.any(Balance), + reservedBalance: expect.any(Balance), + vestedBalance: expect.any(Balance), + votingBalance: expect.any(Balance) + })); + done(); + }); + }); + }); + + describe('fees', () => { + it('fees: It returns an object with all relevant fees of type BN', async (done) => { + api.derive.balances.fees().subscribe((fees) => { + expect(fees).toEqual(expect.objectContaining({ + creationFee: expect.any(BN), + existentialDeposit: expect.any(BN), + transactionBaseFee: expect.any(BN), + transactionByteFee: expect.any(BN), + transferFee: expect.any(BN) + })); + done(); + }); + }); + }); + }); + + describe('derive.chain', () => { + describe('bestNumber', () => { + it('Get the latest block number', async (done) => { + api.derive.chain.bestNumber().subscribe((blockNumber) => { + expect(blockNumber instanceof BlockNumber).toBe(true); + expect((blockNumber as BlockNumber).gten(0)).toBe(true); + done(); + }); + }); + }); + + describe('bestNumberFinalized', () => { + it('Get the latest finalised block number', async (done) => { + api.derive.chain.bestNumberFinalized().subscribe((blockNumber) => { + expect(blockNumber instanceof BlockNumber).toBe(true); + expect((blockNumber as BlockNumber).gten(0)).toBe(true); + done(); + }); + }); + }); + + describe('bestNumberLag', () => { + it('lag between finalised head and best head', async (done) => { + api.derive.chain.bestNumberLag().subscribe((numberLag) => { + expect(numberLag instanceof BlockNumber).toBe(true); + expect((numberLag as BlockNumber).gten(0)).toBe(true); + done(); + }); + }); + }); + + describe('getHeader', () => { + it('gets a specific block header and extended with it\`s author', async (done) => { + api.derive.chain.getHeader().subscribe((headerExtended) => { + // WIP + expect(headerExtended).toEqual(expect.arrayContaining([])); + done(); + }); + }); + }); + + describe('subscribeNewHead', () => { + it('gets an observable of the current block header and it\'s author', async (done) => { + api.derive.chain.subscribeNewHead().subscribe((headerExtended) => { + // WIP + done(); + }); + }); + }); + }); + + describe('derive.session', () => { + describe('sessionProgress', () => { + it('derive.session.sessionProgress', async (done) => { + api.derive.session.sessionProgress().subscribe((progress) => { + expect(progress instanceof BN).toBe(true); + done(); + }); + }); + }); + }); + + describe('derive.staking', () => { + describe('intentionsBalances', () => { + it('returns the intentions with balances', async (done) => { + api.derive.staking.intentionsBalances().subscribe((balances) => { + expect(Object.keys(balances as object)).not.toHaveLength(0); + done(); + }); }); }); }); diff --git a/packages/types/README.md b/packages/types/README.md index 0d9ee25abf..74ebb2aad2 100644 --- a/packages/types/README.md +++ b/packages/types/README.md @@ -8,7 +8,7 @@ On the Rust side, the codec types and primitive types are implemented via the [p These are the base types of the codec. They are typically not used directly, but rather inherited from to create specific types. They are the building blocks for declaring custom types: -| Type | Description | +| **Types** | | | --- | --- | | [[AbstractArray]] | Manages codec arrays. It is an extension to Array | | [[Base]] | A type extends the Base class, when it holds a value | @@ -31,7 +31,7 @@ These are the base types of the codec. They are typically not used directly, but These primitive types are available: -| Type | Description | +| **Types** | | | --- | --- | | [[Bool]] | Representation for a boolean value in the system | | [[Bytes]] | A Bytes wrapper for `Vec` | @@ -65,7 +65,7 @@ These primitive types are available: These custom types implement specific types that are found as part of the Substrate core. They're all extensions of one of the codec types: -| Type | Description | +| **Types** | | | --- | --- | | [[AccountId]] | A wrapper around an AccountId/PublicKey representation | | [[AccountIndex]] | A wrapper around an AccountIndex, which is a shortened, variable-length encoding for an Account | @@ -147,7 +147,7 @@ These custom types implement specific types that are found as part of the Substr These types are not used in the runtime, but are rather used in RPC results: -| Type | Description | +| **Types** | | | --- | --- | | [[ChainProperties]] | Wraps the properties retrieved from the chain via the `system.properties` RPC call | | [[ExtrinsicStatus]] | An EnumType that indicates the status of the Extrinsic as been submitted | @@ -160,3 +160,12 @@ These types are not used in the runtime, but are rather used in RPC results: | [[RuntimeVersion]] | A [[Tuple]] that conatins the [[ApiId]] and [[U32]] version | | [[SignedBlock]] | A [[Block]] that has been signed and contains a [[Justification]] | | [[StorageChangeSet]] | A set of storage changes. It contains the [[Block]] hash and a list of the actual changes | + + +## Derive types + +These types are are specific for the Polkadot-JS API, so you won't find a representation of them in the SCALE codec or the Substrate core. They are used in the [api-derive](https://www.npmjs.com/package/@polkadot/api-derive) methods. + +| **Types** | | +| --- | --- | +| [[HeaderExtended]] | A [[Block]] header with an additional `author` field that indicates the block author] |