diff --git a/packages/api-derive/src/bundle.ts b/packages/api-derive/src/bundle.ts index 9975e90960..84fed9de9e 100644 --- a/packages/api-derive/src/bundle.ts +++ b/packages/api-derive/src/bundle.ts @@ -39,12 +39,12 @@ export { lazyDeriveSection }; export const derive = { accounts, balances, bounties, chain, contracts, council, crowdloan, democracy, elections, imOnline, membership, parachains, session, society, staking, technicalCommittee, treasury, tx }; type DeriveSection
= { - [Method in keyof Section]: Section[Method] extends AnyFunction - ? ReturnType // ReturnType will be the inner function, i.e. without (api) argument + [M in keyof Section]: Section[M] extends AnyFunction + ? ReturnType // ReturnType will be the inner function, i.e. without (api) argument : never; }; type DeriveAllSections = { - [Section in keyof AllSections]: DeriveSection + [S in keyof AllSections]: DeriveSection }; type DeriveCreator = (instanceId: string, api: ApiInterfaceRx) => (...args: unknown[]) => Observable; diff --git a/packages/api-derive/src/staking/cache.ts b/packages/api-derive/src/staking/cache.ts new file mode 100644 index 0000000000..fb3afc2045 --- /dev/null +++ b/packages/api-derive/src/staking/cache.ts @@ -0,0 +1,27 @@ +// Copyright 2017-2021 @polkadot/api-derive authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { EraIndex } from '@polkadot/types/interfaces'; + +import { deriveCache } from '../util'; + +export function getEraCache (CACHE_KEY: string, era: EraIndex, withActive?: boolean): [string, T | undefined] { + const cacheKey = `${CACHE_KEY}-${era.toString()}`; + + return [ + cacheKey, + withActive + ? undefined + : deriveCache.get(cacheKey) + ]; +} + +export function getEraMultiCache (CACHE_KEY: string, eras: EraIndex[], withActive?: boolean): T[] { + const cached: T[] = withActive + ? [] + : eras + .map((e) => deriveCache.get(`${CACHE_KEY}-${e.toString()}`)) + .filter((v): v is T => !!v); + + return cached; +} diff --git a/packages/api-derive/src/staking/erasExposure.ts b/packages/api-derive/src/staking/erasExposure.ts index 21638ce218..fcd71d2705 100644 --- a/packages/api-derive/src/staking/erasExposure.ts +++ b/packages/api-derive/src/staking/erasExposure.ts @@ -8,9 +8,11 @@ import type { AccountId, EraIndex } from '@polkadot/types/interfaces'; import type { PalletStakingExposure } from '@polkadot/types/lookup'; import type { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types'; -import { combineLatest, map, of, switchMap } from 'rxjs'; +import { combineLatest, map, of } from 'rxjs'; import { deriveCache, memo } from '../util'; +import { getEraCache } from './cache'; +import { erasHistoricApply } from './util'; type KeysAndExposures = [StorageKey<[EraIndex, AccountId]>, PalletStakingExposure][]; @@ -38,10 +40,7 @@ function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposur export function _eraExposure (instanceId: string, api: ApiInterfaceRx): (era: EraIndex, withActive: boolean) => Observable { return memo(instanceId, (era: EraIndex, withActive: boolean): Observable => { - const cacheKey = `${CACHE_KEY}-${era.toString()}`; - const cached = withActive - ? undefined - : deriveCache.get(cacheKey); + const [cacheKey, cached] = getEraCache(CACHE_KEY, era, withActive); return cached ? of(cached) @@ -71,10 +70,4 @@ export function _erasExposure (instanceId: string, api: ApiInterfaceRx): (eras: ); } -export function erasExposure (instanceId: string, api: ApiInterfaceRx): (withActive?: boolean) => Observable { - return memo(instanceId, (withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._erasExposure(eras, withActive)) - ) - ); -} +export const erasExposure = erasHistoricApply('_erasExposure'); diff --git a/packages/api-derive/src/staking/erasPoints.ts b/packages/api-derive/src/staking/erasPoints.ts index c2949937eb..5d09c457e3 100644 --- a/packages/api-derive/src/staking/erasPoints.ts +++ b/packages/api-derive/src/staking/erasPoints.ts @@ -7,12 +7,13 @@ import type { EraIndex } from '@polkadot/types/interfaces'; import type { PalletStakingEraRewardPoints } from '@polkadot/types/lookup'; import type { DeriveEraPoints, DeriveEraValPoints } from '../types'; -import { map, of, switchMap } from 'rxjs'; +import { map, of } from 'rxjs'; import { BN_ZERO } from '@polkadot/util'; import { deriveCache, memo } from '../util'; -import { filterEras } from './util'; +import { getEraMultiCache } from './cache'; +import { erasHistoricApply, filterEras } from './util'; const CACHE_KEY = 'eraPoints'; @@ -40,11 +41,7 @@ export function _erasPoints (instanceId: string, api: ApiInterfaceRx): (eras: Er return of([]); } - const cached: DeriveEraPoints[] = withActive - ? [] - : eras - .map((era) => deriveCache.get(`${CACHE_KEY}-${era.toString()}`)) - .filter((value): value is DeriveEraPoints => !!value); + const cached = getEraMultiCache(CACHE_KEY, eras, withActive); const remaining = filterEras(eras, cached); return !remaining.length @@ -64,10 +61,4 @@ export function _erasPoints (instanceId: string, api: ApiInterfaceRx): (eras: Er }); } -export function erasPoints (instanceId: string, api: ApiInterfaceRx): (withActive?: boolean) => Observable { - return memo(instanceId, (withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._erasPoints(eras, withActive)) - ) - ); -} +export const erasPoints = erasHistoricApply('_erasPoints'); diff --git a/packages/api-derive/src/staking/erasPrefs.ts b/packages/api-derive/src/staking/erasPrefs.ts index 6ebcfc129a..a329de47b7 100644 --- a/packages/api-derive/src/staking/erasPrefs.ts +++ b/packages/api-derive/src/staking/erasPrefs.ts @@ -8,9 +8,11 @@ import type { EraIndex } from '@polkadot/types/interfaces'; import type { PalletStakingValidatorPrefs } from '@polkadot/types/lookup'; import type { DeriveEraPrefs, DeriveEraValPrefs } from '../types'; -import { combineLatest, map, of, switchMap } from 'rxjs'; +import { combineLatest, map, of } from 'rxjs'; import { deriveCache, memo } from '../util'; +import { getEraCache } from './cache'; +import { erasHistoricApply } from './util'; const CACHE_KEY = 'eraPrefs'; @@ -26,10 +28,7 @@ function mapPrefs (era: EraIndex, all: [StorageKey, PalletStakingValidatorPrefs] export function _eraPrefs (instanceId: string, api: ApiInterfaceRx): (era: EraIndex, withActive: boolean) => Observable { return memo(instanceId, (era: EraIndex, withActive: boolean): Observable => { - const cacheKey = `${CACHE_KEY}-${era.toString()}`; - const cached = withActive - ? undefined - : deriveCache.get(cacheKey); + const [cacheKey, cached] = getEraCache(CACHE_KEY, era, withActive); return cached ? of(cached) @@ -59,10 +58,4 @@ export function _erasPrefs (instanceId: string, api: ApiInterfaceRx): (eras: Era ); } -export function erasPrefs (instanceId: string, api: ApiInterfaceRx): (withActive?: boolean) => Observable { - return memo(instanceId, (withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._erasPrefs(eras, withActive)) - ) - ); -} +export const erasPrefs = erasHistoricApply('_erasPrefs'); diff --git a/packages/api-derive/src/staking/erasRewards.ts b/packages/api-derive/src/staking/erasRewards.ts index 22572fe471..7eaabf35b1 100644 --- a/packages/api-derive/src/staking/erasRewards.ts +++ b/packages/api-derive/src/staking/erasRewards.ts @@ -7,10 +7,11 @@ import type { Option } from '@polkadot/types'; import type { Balance, EraIndex } from '@polkadot/types/interfaces'; import type { DeriveEraRewards } from '../types'; -import { map, of, switchMap } from 'rxjs'; +import { map, of } from 'rxjs'; import { deriveCache, memo } from '../util'; -import { filterEras } from './util'; +import { getEraMultiCache } from './cache'; +import { erasHistoricApply, filterEras } from './util'; const CACHE_KEY = 'eraRewards'; @@ -27,11 +28,7 @@ export function _erasRewards (instanceId: string, api: ApiInterfaceRx): (eras: E return of([]); } - const cached: DeriveEraRewards[] = withActive - ? [] - : eras - .map((era) => deriveCache.get(`${CACHE_KEY}-${era.toString()}`)) - .filter((value): value is DeriveEraRewards => !!value); + const cached = getEraMultiCache(CACHE_KEY, eras, withActive); const remaining = filterEras(eras, cached); if (!remaining.length) { @@ -53,10 +50,4 @@ export function _erasRewards (instanceId: string, api: ApiInterfaceRx): (eras: E }); } -export function erasRewards (instanceId: string, api: ApiInterfaceRx): (withActive?: boolean) => Observable { - return memo(instanceId, (withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._erasRewards(eras, withActive)) - ) - ); -} +export const erasRewards = erasHistoricApply('_erasRewards'); diff --git a/packages/api-derive/src/staking/erasSlashes.ts b/packages/api-derive/src/staking/erasSlashes.ts index a74e4b0822..2de58f9ece 100644 --- a/packages/api-derive/src/staking/erasSlashes.ts +++ b/packages/api-derive/src/staking/erasSlashes.ts @@ -8,9 +8,11 @@ import type { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces'; import type { ITuple } from '@polkadot/types/types'; import type { DeriveEraSlashes, DeriveEraValSlash } from '../types'; -import { combineLatest, map, of, switchMap } from 'rxjs'; +import { combineLatest, map, of } from 'rxjs'; import { deriveCache, memo } from '../util'; +import { getEraCache } from './cache'; +import { erasHistoricApply } from './util'; const CACHE_KEY = 'eraSlashes'; @@ -31,10 +33,7 @@ function mapSlashes (era: EraIndex, noms: [StorageKey, Option][], val export function _eraSlashes (instanceId: string, api: ApiInterfaceRx): (era: EraIndex, withActive: boolean) => Observable { return memo(instanceId, (era: EraIndex, withActive: boolean): Observable => { - const cacheKey = `${CACHE_KEY}-${era.toString()}`; - const cached = withActive - ? undefined - : deriveCache.get(cacheKey); + const [cacheKey, cached] = getEraCache(CACHE_KEY, era, withActive); return cached ? of(cached) @@ -69,10 +68,4 @@ export function _erasSlashes (instanceId: string, api: ApiInterfaceRx): (eras: E ); } -export function erasSlashes (instanceId: string, api: ApiInterfaceRx): (withActive?: boolean) => Observable { - return memo(instanceId, (withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._erasSlashes(eras, withActive)) - ) - ); -} +export const erasSlashes = erasHistoricApply('_erasSlashes'); diff --git a/packages/api-derive/src/staking/ownExposure.ts b/packages/api-derive/src/staking/ownExposure.ts index 70261342e4..6c54fbd63f 100644 --- a/packages/api-derive/src/staking/ownExposure.ts +++ b/packages/api-derive/src/staking/ownExposure.ts @@ -7,9 +7,10 @@ import type { EraIndex } from '@polkadot/types/interfaces'; import type { PalletStakingExposure } from '@polkadot/types/lookup'; import type { DeriveOwnExposure } from '../types'; -import { map, of, switchMap } from 'rxjs'; +import { map, of } from 'rxjs'; import { memo } from '../util'; +import { erasHistoricApplyAccount } from './util'; export function _ownExposures (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -35,12 +36,4 @@ export function ownExposure (instanceId: string, api: ApiInterfaceRx): (accountI ); } -export function ownExposures (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable { - return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable => { - return api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => - api.derive.staking._ownExposures(accountId, eras, withActive) - ) - ); - }); -} +export const ownExposures = erasHistoricApplyAccount('_ownExposures'); diff --git a/packages/api-derive/src/staking/ownSlashes.ts b/packages/api-derive/src/staking/ownSlashes.ts index 9812151c86..c2b894ae5b 100644 --- a/packages/api-derive/src/staking/ownSlashes.ts +++ b/packages/api-derive/src/staking/ownSlashes.ts @@ -8,9 +8,10 @@ import type { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces'; import type { ITuple } from '@polkadot/types/types'; import type { DeriveStakerSlashes } from '../types'; -import { map, of, switchMap } from 'rxjs'; +import { map, of } from 'rxjs'; import { memo } from '../util'; +import { erasHistoricApplyAccount } from './util'; export function _ownSlashes (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -41,12 +42,4 @@ export function ownSlash (instanceId: string, api: ApiInterfaceRx): (accountId: ); } -export function ownSlashes (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable { - return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable => { - return api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => - api.derive.staking._ownSlashes(accountId, eras, withActive) - ) - ); - }); -} +export const ownSlashes = erasHistoricApplyAccount('_ownSlashes'); diff --git a/packages/api-derive/src/staking/stakerPoints.ts b/packages/api-derive/src/staking/stakerPoints.ts index b559407aa0..24444cfc0c 100644 --- a/packages/api-derive/src/staking/stakerPoints.ts +++ b/packages/api-derive/src/staking/stakerPoints.ts @@ -6,9 +6,10 @@ import type { ApiInterfaceRx } from '@polkadot/api/types'; import type { EraIndex } from '@polkadot/types/interfaces'; import type { DeriveStakerPoints } from '../types'; -import { map, switchMap } from 'rxjs'; +import { map } from 'rxjs'; import { memo } from '../util'; +import { erasHistoricApplyAccount } from './util'; export function _stakerPoints (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable { return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean): Observable => { @@ -26,10 +27,4 @@ export function _stakerPoints (instanceId: string, api: ApiInterfaceRx): (accoun }); } -export function stakerPoints (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable { - return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._stakerPoints(accountId, eras, withActive)) - ) - ); -} +export const stakerPoints = erasHistoricApplyAccount('_stakerPoints'); diff --git a/packages/api-derive/src/staking/stakerPrefs.ts b/packages/api-derive/src/staking/stakerPrefs.ts index 842172db28..19e94a7022 100644 --- a/packages/api-derive/src/staking/stakerPrefs.ts +++ b/packages/api-derive/src/staking/stakerPrefs.ts @@ -6,9 +6,10 @@ import type { ApiInterfaceRx } from '@polkadot/api/types'; import type { EraIndex } from '@polkadot/types/interfaces'; import type { DeriveStakerPrefs } from '../types'; -import { map, switchMap } from 'rxjs'; +import { map } from 'rxjs'; import { memo } from '../util'; +import { erasHistoricApplyAccount } from './util'; export function _stakerPrefs (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -24,10 +25,4 @@ export function _stakerPrefs (instanceId: string, api: ApiInterfaceRx): (account ); } -export function stakerPrefs (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable { - return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._stakerPrefs(accountId, eras, withActive)) - ) - ); -} +export const stakerPrefs = erasHistoricApplyAccount('_stakerPrefs'); diff --git a/packages/api-derive/src/staking/stakerSlashes.ts b/packages/api-derive/src/staking/stakerSlashes.ts index 0a7fd2ca8e..4731a5a918 100644 --- a/packages/api-derive/src/staking/stakerSlashes.ts +++ b/packages/api-derive/src/staking/stakerSlashes.ts @@ -6,9 +6,10 @@ import type { ApiInterfaceRx } from '@polkadot/api/types'; import type { EraIndex } from '@polkadot/types/interfaces'; import type { DeriveStakerSlashes } from '../types'; -import { map, switchMap } from 'rxjs'; +import { map } from 'rxjs'; import { memo } from '../util'; +import { erasHistoricApplyAccount } from './util'; export function _stakerSlashes (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable { return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean): Observable => { @@ -25,10 +26,4 @@ export function _stakerSlashes (instanceId: string, api: ApiInterfaceRx): (accou }); } -export function stakerSlashes (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable { - return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable => - api.derive.staking.erasHistoric(withActive).pipe( - switchMap((eras) => api.derive.staking._stakerSlashes(accountId, eras, withActive)) - ) - ); -} +export const stakerSlashes = erasHistoricApplyAccount('_stakerSlashes'); diff --git a/packages/api-derive/src/staking/util.ts b/packages/api-derive/src/staking/util.ts index cc344b682c..9dcd69fccd 100644 --- a/packages/api-derive/src/staking/util.ts +++ b/packages/api-derive/src/staking/util.ts @@ -1,8 +1,38 @@ // Copyright 2017-2021 @polkadot/api-derive authors & contributors // SPDX-License-Identifier: Apache-2.0 +import type { ApiInterfaceRx } from '@polkadot/api/types'; import type { EraIndex } from '@polkadot/types/interfaces'; +import type { ExactDerive } from '../bundle'; + +import { switchMap } from 'rxjs'; + +import { memo } from '../util'; + +type ApplyReturn = ReturnType; export function filterEras (eras: EraIndex[], list: T[]): EraIndex[] { return eras.filter((era) => !list.some((entry) => era.eq(entry.era))); } + +export function erasHistoricApply (fn: F): (instanceId: string, api: ApiInterfaceRx) => (withActive?: boolean) => ApplyReturn { + return (instanceId: string, api: ApiInterfaceRx) => + // Cannot quite get the typing right, but it is right in the code + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + memo(instanceId, (withActive = false) => + api.derive.staking.erasHistoric(withActive).pipe( + switchMap((e) => api.derive.staking[fn](e, withActive)) + ) + ) as any; +} + +export function erasHistoricApplyAccount (fn: F): (instanceId: string, api: ApiInterfaceRx) => (accountId: string | Uint8Array, withActive?: boolean) => ApplyReturn { + return (instanceId: string, api: ApiInterfaceRx) => + // Cannot quite get the typing right, but it is right in the code + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + memo(instanceId, (accountId: string | Uint8Array, withActive = false) => + api.derive.staking.erasHistoric(withActive).pipe( + switchMap((e) => api.derive.staking[fn](accountId, e, withActive)) + ) + ) as any; +}