From 1393c8c5cfce34764c90a437b5078206bd7f4677 Mon Sep 17 00:00:00 2001 From: Stefanie Doll Date: Wed, 10 Jul 2019 16:56:11 +0200 Subject: [PATCH] Include api.consts in api.derive methods (#1084) * Bring back derive changes * Fix fees tests * contract fees for v1.0 * Contract fees v1.0 test * Bring back console.logs * Uase api.consts instead * linter fixes * more linter nits * Fixed staking & session * .skip() * Formatting nits --- packages/api-derive/src/balances/all.ts | 9 +- packages/api-derive/src/balances/fees.ts | 22 ++-- packages/api-derive/src/contracts/fees.ts | 118 +++++++++++++++++----- packages/api-derive/src/session/info.ts | 21 ++-- packages/api-derive/src/types.ts | 2 +- packages/api-derive/test/consts.ts | 0 packages/api-derive/test/e2e/rx.spec.ts | 86 +++++++++++++--- 7 files changed, 195 insertions(+), 63 deletions(-) create mode 100644 packages/api-derive/test/consts.ts diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index 611674bc3c..2e3009afef 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -2,6 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import BN from 'bn.js'; import { combineLatest, of, Observable } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; import { ApiInterface$Rx } from '@polkadot/api/types'; @@ -32,8 +33,8 @@ function calcBalances ([accountId = EMPTY_ACCOUNT, bestNumber = ZERO, [freeBalan // offset = balance locked at genesis, perBlock is the unlock amount const { offset, perBlock } = vesting.unwrapOr(new VestingSchedule()); - const vestedNow = perBlock.mul(bestNumber); - const vestedBalance = vestedNow.gt(offset) + const vestedNow: BN = perBlock.mul(bestNumber); + const vestedBalance: BN = vestedNow.gt(offset) ? freeBalance : freeBalance.sub(offset).add(vestedNow); @@ -42,7 +43,7 @@ function calcBalances ([accountId = EMPTY_ACCOUNT, bestNumber = ZERO, [freeBalan // The locked is > the vested and ended up with the locked > free, // i.e. related to https://github.com/paritytech/polkadot/issues/225 // (most probably due to movements from stash -> controller -> free) - const availableBalance = bnMax(ZERO, vestedBalance.sub(lockedBalance)); + const availableBalance: BN = bnMax(ZERO, vestedBalance.sub(lockedBalance)); return { accountId, @@ -58,7 +59,7 @@ function calcBalances ([accountId = EMPTY_ACCOUNT, bestNumber = ZERO, [freeBalan /** * @name all - * @param {( ccountIndex | AccountId | Address | string )} address - An accounts Id in different formats. + * @param {( AccountIndex | 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 diff --git a/packages/api-derive/src/balances/fees.ts b/packages/api-derive/src/balances/fees.ts index bd9a24e3d2..afbdf56848 100644 --- a/packages/api-derive/src/balances/fees.ts +++ b/packages/api-derive/src/balances/fees.ts @@ -11,8 +11,6 @@ import { map } from 'rxjs/operators'; import { drr } from '../util/drr'; -const ZERO = new BN(0); - /** * @name fees * @returns An object containing the combined results of the storage queries for @@ -29,19 +27,25 @@ const ZERO = new BN(0); export function fees (api: ApiInterface$Rx) { return (): Observable => { return ( - // HACK This is a very quick fix to actually get the types in to continue with - // other work - so as of now, the fees are completely broken - api.query.balances.creationFee - ? api.queryMulti([ + api.consts.balances + ? of([ + // get values from api.const for substrate versions post spec_version: 101 + // https://github.com/paritytech/substrate/pull/2883/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R131 + api.consts.balances.creationFee, + api.consts.balances.existentialDeposit, + api.consts.balances.transactionBaseFee, + api.consts.balances.transactionByteFee, + api.consts.balances.transferFee + ]) as any as Observable<[BN, BN, BN, BN, BN]> + : api.queryMulti([ + // Support older versions and get values from storage api.query.balances.creationFee, api.query.balances.existentialDeposit, api.query.balances.transactionBaseFee, api.query.balances.transactionByteFee, api.query.balances.transferFee ]) as any as Observable<[BN, BN, BN, BN, BN]> - : of([ZERO, ZERO, ZERO, ZERO, ZERO]) - ).pipe( - map(([creationFee, existentialDeposit, transactionBaseFee, transactionByteFee, transferFee]) => ({ + ).pipe(map(([creationFee, existentialDeposit, transactionBaseFee, transactionByteFee, transferFee]) => ({ creationFee, existentialDeposit, transactionBaseFee, diff --git a/packages/api-derive/src/contracts/fees.ts b/packages/api-derive/src/contracts/fees.ts index d85409e82f..46bab5ac66 100644 --- a/packages/api-derive/src/contracts/fees.ts +++ b/packages/api-derive/src/contracts/fees.ts @@ -6,43 +6,107 @@ import { ApiInterface$Rx } from '@polkadot/api/types'; import { DerivedContractFees } from '../types'; import BN from 'bn.js'; -import { Observable } from 'rxjs'; +import { combineLatest, Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { drr } from '../util/drr'; +const ZERO = new BN(0); + /** - * Retrieves all the contract fees + * @name fees + * @returns An object containing the combined results of the queries for + * all relevant contract fees as declared in the substrate chain spec. + * @example + *
+ * + * ```javascript + * api.derive.contracts.fees(([creationFee, transferFee]) => { + * console.log(`The fee for creating a new contract on this chain is ${creationFee} units. The fee required to call this contract is ${transferFee} units.`); + * }); + * ``` */ export function fees (api: ApiInterface$Rx) { return (): Observable => { const queryBase = api.query.contracts || api.query.contract; - // FIXME A numnber of these are being moved https://github.com/paritytech/substrate/pull/2883 - return (api.queryMulti([ - queryBase.callBaseFee, - queryBase.contractFee, - queryBase.createBaseFee, - queryBase.creationFee, - queryBase.rentByteFee, - queryBase.rentDepositOffset, - queryBase.transactionBaseFee, - queryBase.transactionByteFee, - queryBase.transferFee, - queryBase.tombstoneDeposit - ]) as any as Observable>).pipe( - map(([callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, transactionBaseFee, transactionByteFee, transferFee, tombstoneDeposit]) => ({ - callBaseFee, - contractFee, - createBaseFee, - creationFee, - rentByteFee, - rentDepositOffset, - transactionBaseFee, - transactionByteFee, - transferFee, - tombstoneDeposit - } as DerivedContractFees)), + if (api.query.contract && !api.query.contract.rentByteFee) { + // Only for 1.0 support. rentByteFee, rentDepositOffset, tombstoneDeposit are not available in substrate 1.0. + // @TODO remove this once 1.0 support is dropped + return (combineLatest([ + of([ZERO, ZERO, ZERO]), + api.queryMulti([ + queryBase.callBaseFee, + queryBase.contractFee, + queryBase.createBaseFee, + queryBase.creationFee, + queryBase.transactionBaseFee, + queryBase.transactionByteFee, + queryBase.transferFee + ]) + ]) as any as Observable>>).pipe( + map(([ + [rentByteFee, rentDepositOffset, tombstoneDeposit], + [callBaseFee, contractFee, createBaseFee, creationFee, transactionBaseFee, transactionByteFee, transferFee] + ]) => ({ + callBaseFee, + contractFee, + createBaseFee, + creationFee, + rentByteFee, + rentDepositOffset, + tombstoneDeposit, + transactionBaseFee, + transactionByteFee, + transferFee + } as DerivedContractFees)), + drr() + ); + } + + return ( + api.consts.contracts + // get values from api.const for substrate versions post spec_version: 101 + // https://github.com/paritytech/substrate/pull/2883/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R131 + ? of([ + api.consts.contracts.callBaseFee, + api.consts.contracts.contractFee, + api.consts.contracts.createBaseFee, + api.consts.contracts.creationFee, + api.consts.contracts.rentByteFee, + api.consts.contracts.rentDepositOffset, + api.consts.contracts.tombstoneDeposit, + api.consts.contracts.transactionBaseFee, + api.consts.contracts.transactionByteFee, + api.consts.contracts.transferFee + ]) as any as Observable> + // Support versions pre spec_version 101 and get values from storage + : api.queryMulti([ + queryBase.callBaseFee, + queryBase.contractFee, + queryBase.createBaseFee, + queryBase.creationFee, + queryBase.rentByteFee, + queryBase.rentDepositOffset, + queryBase.tombstoneDeposit, + queryBase.transactionBaseFee, + queryBase.transactionByteFee, + queryBase.transferFee + ]) as any as Observable> + ).pipe(map( + ([callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee, transferFee]) => ({ + callBaseFee, + contractFee, + createBaseFee, + creationFee, + rentByteFee, + rentDepositOffset, + tombstoneDeposit, + transactionBaseFee, + transactionByteFee, + transferFee + } as DerivedContractFees) + ), drr() ); }; diff --git a/packages/api-derive/src/session/info.ts b/packages/api-derive/src/session/info.ts index 4e900fb526..faf1fce7a6 100644 --- a/packages/api-derive/src/session/info.ts +++ b/packages/api-derive/src/session/info.ts @@ -13,13 +13,13 @@ import { BlockNumber, Option } from '@polkadot/types'; import { drr } from '../util/drr'; import { bestNumber } from '../chain'; -type Result0_94 = [BN, [BN, Option, BN, BN, BN]]; +type Result_pre_94 = [BN, [BN, Option, BN, BN, BN]]; type Result = [BN, [BN, BN]]; const ZERO = new BN(0); // internal helper to just split the logic - take all inputs, do the calculations and combine -function createDerived0_94 ([bestNumber, [currentIndex, _lastLengthChange, sessionLength, lastEraLengthChange, sessionsPerEra]]: Result0_94): DerivedSessionInfo { +function createDerived_pre_94 ([bestNumber, [currentIndex, _lastLengthChange, sessionLength, lastEraLengthChange, sessionsPerEra]]: Result_pre_94): DerivedSessionInfo { const eraLength = sessionLength.mul(sessionsPerEra); const lastLengthChange = _lastLengthChange ? _lastLengthChange.unwrapOr(ZERO) @@ -65,12 +65,13 @@ function createDerived ([sessionsPerEra, [currentIndex, currentEra]]: Result): D } /** - * @description Retrieves all the session and era info and calculates specific valus on it sunh as the length of the session and eras + * @description Retrieves all the session and era info and calculates specific values on it as the length of the session and eras */ export function info (api: ApiInterface$Rx) { return (): Observable => { - // with 94, the era and session has been explicitly exposed, pre-94 - // we had more info and needed to calculate (handle old/Alex first) + // With substrate `spec_version 94`, the era and session has been explicitly exposed as `parameter_types`. + // pre-94 we had more info and needed to calculate (handle old/Alex first) + // https://github.com/paritytech/substrate/commit/dbf322620948935d2bbae214504e6c668c3073ed#diff-c29f42d6b931fa93ba038dbbbfec3055 return api.query.session.lastLengthChange ? (combineLatest([ bestNumber(api)(), @@ -81,13 +82,15 @@ export function info (api: ApiInterface$Rx) { api.query.staking.lastEraLengthChange, api.query.staking.sessionsPerEra ]) - ]) as any as Observable).pipe( - map(createDerived0_94), + ]) as any as Observable).pipe( + map(createDerived_pre_94), drr() ) : (combineLatest([ - // sessionsPerEra, hardcoded, due to https://github.com/paritytech/substrate/pull/2802/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R156 - of(new BN(6)), + // sessionsPerEra: + // substrate spec_version >= 94 : get from parameter_types exposed as api.consts + // https://github.com/paritytech/substrate/pull/2802/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R156 + of(api.consts.staking.sessionsPerEra), api.queryMulti([ api.query.session.currentIndex, api.query.staking.currentEra diff --git a/packages/api-derive/src/types.ts b/packages/api-derive/src/types.ts index 0eebd7d6dc..22630ebe41 100644 --- a/packages/api-derive/src/types.ts +++ b/packages/api-derive/src/types.ts @@ -27,10 +27,10 @@ export interface DerivedContractFees { creationFee: BN; rentByteFee: BN; rentDepositOffset: BN; + tombstoneDeposit: BN; transactionBaseFee: BN; transactionByteFee: BN; transferFee: BN; - tombstoneDeposit: BN; } export interface DerivedFees { diff --git a/packages/api-derive/test/consts.ts b/packages/api-derive/test/consts.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/api-derive/test/e2e/rx.spec.ts b/packages/api-derive/test/e2e/rx.spec.ts index 2e47cec8bc..74be10210e 100644 --- a/packages/api-derive/test/e2e/rx.spec.ts +++ b/packages/api-derive/test/e2e/rx.spec.ts @@ -5,20 +5,21 @@ import BN from 'bn.js'; import ApiRx from '@polkadot/api/rx/Api'; -import { AccountId, AccountIndex, Balance, BlockNumber, Index } from '@polkadot/types'; +import { AccountId, AccountIndex, BlockNumber, Index } from '@polkadot/types'; import { WsProvider } from '@polkadot/rpc-provider'; import { HeaderExtended } from '../../src/type'; -import { DerivedBalances, DerivedFees } from '../../src/types'; +import { DerivedBalances, DerivedContractFees, DerivedFees, DerivedSessionInfo } from '../../src/types'; -const WS_LOCAL = 'ws://127.0.0.1:9944/'; -// const WS_POC3 = 'wss://poc3-rpc.polkadot.io/'; +const WS = 'ws://127.0.0.1:9944/'; +// const WS = 'wss://poc3-rpc.polkadot.io/'; +// const WS = 'wss://substrate-rpc.parity.io/'; // Dev account Alice const ID = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; const IX = 'F7Hs'; -describe.skip('derive e2e', () => { +describe.skip('Api-RX derive e2e', () => { let api: ApiRx; beforeAll(() => { @@ -26,7 +27,7 @@ describe.skip('derive e2e', () => { }); beforeEach(async (done) => { - api = await ApiRx.create(new WsProvider(WS_LOCAL)).toPromise(); + api = await ApiRx.create(new WsProvider(WS)).toPromise(); done(); }); @@ -119,12 +120,12 @@ describe.skip('derive e2e', () => { expect(balances).toEqual(expect.objectContaining({ accountId: expect.any(AccountId), accountNonce: expect.any(Index), - availableBalance: expect.any(Balance), - freeBalance: expect.any(Balance), - lockedBalance: expect.any(Balance), - reservedBalance: expect.any(Balance), - vestedBalance: expect.any(Balance), - votingBalance: expect.any(Balance) + availableBalance: expect.any(BN), + freeBalance: expect.any(BN), + lockedBalance: expect.any(BN), + reservedBalance: expect.any(BN), + vestedBalance: expect.any(BN), + votingBalance: expect.any(BN) })); done(); }); @@ -199,6 +200,28 @@ describe.skip('derive e2e', () => { }); }); + describe('derive.contracts', () => { + describe('fees', () => { + it('fees: It returns an object with all relevant constract fees of type Balance', async (done) => { + api.derive.contracts.fees().subscribe((fees: DerivedContractFees) => { + expect(fees).toEqual(expect.objectContaining({ + callBaseFee: expect.any(BN), + contractFee: expect.any(BN), + createBaseFee: expect.any(BN), + creationFee: expect.any(BN), + rentByteFee: expect.any(BN), + rentDepositOffset: expect.any(BN), + tombstoneDeposit: expect.any(BN), + transactionBaseFee: expect.any(BN), + transactionByteFee: expect.any(BN), + transferFee: expect.any(BN) + })); + done(); + }); + }); + }); + }); + describe('derive.session', () => { describe('sessionProgress', () => { it('derive.session.sessionProgress', async (done) => { @@ -208,6 +231,43 @@ describe.skip('derive e2e', () => { }); }); }); + + describe('session.info', () => { + it('retrieves all session info', async (done) => { + api.derive.session.info().subscribe((info: DerivedSessionInfo) => { + expect(info).toEqual(expect.objectContaining({ + currentEra: expect.anything(), + currentIndex: expect.anything(), + eraLength: expect.anything(), + eraProgress: expect.anything(), + lastEraLengthChange: expect.anything(), + lastLengthChange: expect.anything(), + sessionLength: expect.anything(), + sessionsPerEra: expect.anything(), + sessionProgress: expect.anything() + })); + done(); + }); + }); + }); + + describe('session.eraLength', () => { + it('derive.session.eraLength', async (done) => { + api.derive.session.eraLength().subscribe((length: BN) => { + expect(length instanceof BN).toBe(true); + done(); + }); + }); + }); + + describe('session.eraProgress', () => { + it('derive.session.eraProgress', async (done) => { + api.derive.session.eraProgress().subscribe((progress: BN) => { + expect(progress instanceof BN).toBe(true); + done(); + }); + }); + }); }); describe('derive.staking', () => { @@ -217,6 +277,6 @@ describe.skip('derive e2e', () => { }); afterAll(() => { - jest.setTimeout(5000); + jest.setTimeout(10000); }); });