Added derive e2e tests and documentation (#898)
* export IExtrinsic * Switch to localhos & enable tests in promise.spec * Derive.accounts docs (copy from my other branch) + code examples * Fixed existing accounts tests and added tests for all accounts.derive methods * e2e tests and docs/ examples for balances.all and balances.fees * Removed emty lines below jsdoc info * tests & documentation dor derive.chain * Addressed comments from former PR https://github.com/polkadot-js/api/pull/869 * Removed unused import * obseralbe -> observable * undo keith' commit * use correct jsdocs syntax * Re-enable skip
This commit is contained in:
committed by
Jaco Greeff
parent
4da52c8d76
commit
c30d3a80e8
@@ -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
|
||||
* <BR>
|
||||
*
|
||||
* ```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<AccountIdAndIndex> => {
|
||||
try {
|
||||
|
||||
@@ -10,6 +10,20 @@ import { AccountId, AccountIndex } from '@polkadot/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
|
||||
* <BR>
|
||||
*
|
||||
* ```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<AccountIndex | undefined> =>
|
||||
indexes(api)()
|
||||
|
||||
@@ -10,6 +10,19 @@ import { AccountId, AccountIndex, Vector } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
/**
|
||||
* @name indexToId
|
||||
* @param {( AccountIndex | string )} accountIndex - An accounts index in different formats.
|
||||
* @returns Returns the corresponding AccountId.
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```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<AccountId> => {
|
||||
const querySection = api.query.indices || api.query.balances;
|
||||
|
||||
@@ -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
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.accounts.indexes((indexes) => {
|
||||
* console.log('All existing AccountIndexes', indexes);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function indexes (api: ApiInterface$Rx) {
|
||||
return (): Observable<AccountIndexes> => {
|
||||
|
||||
@@ -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
|
||||
* <BR>
|
||||
*
|
||||
* ```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<DerivedBalances> => {
|
||||
return idAndIndex(api)(address).pipe(
|
||||
|
||||
@@ -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
|
||||
* <BR>
|
||||
*
|
||||
* ```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<DerivedFees> => {
|
||||
return (api.queryMulti([
|
||||
|
||||
@@ -10,7 +10,8 @@ import { BlockNumber, Header } from '@polkadot/types';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
/**
|
||||
* @description Get the latest block number.
|
||||
* @name bestNumber
|
||||
* @returns The latest block number.
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
|
||||
@@ -10,8 +10,10 @@ import { BlockNumber, Header } from '@polkadot/types';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
/**
|
||||
* @name bestNumberFinalized
|
||||
* @returns A BlockNumber
|
||||
* @description Get the latest finalized block number.
|
||||
* example
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
|
||||
@@ -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
|
||||
* <BR>
|
||||
|
||||
@@ -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
|
||||
* <BR>
|
||||
*
|
||||
|
||||
@@ -12,7 +12,9 @@ import { drr } from '../util/drr';
|
||||
export type HeaderAndValidators = [Header, Array<AccountId>];
|
||||
|
||||
/**
|
||||
* @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
|
||||
* <BR>
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -3,14 +3,19 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import ApiRx from '@polkadot/api/rx/Api';
|
||||
import { ApiInterface$Rx } from '@polkadot/api/types';
|
||||
import { BlockNumber } from '@polkadot/types';
|
||||
import { AccountId, AccountIndex, Balance, BlockNumber } from '@polkadot/types';
|
||||
import { WsProvider } from '@polkadot/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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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<u8>` |
|
||||
@@ -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] |
|
||||
|
||||
Reference in New Issue
Block a user