Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/api-derive/src/session/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function createDerivedV1 ([bestNumber, { currentIndex, validatorCount }, [_lastL
function createDerivedLatest ([[hasBabe, epochDuration, sessionsPerEra], { currentIndex, currentEra, validatorCount }, [currentSlot, epochIndex, epochOrGenesisStartSlot, currentEraStartSessionIndex]]: Result): DerivedSessionInfo {
const epochStartSlot = epochIndex.mul(epochDuration).add(epochOrGenesisStartSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
const eraProgress = currentIndex.sub(currentEraStartSessionIndex).add(sessionProgress);
const eraProgress = currentIndex.sub(currentEraStartSessionIndex).mul(epochDuration).add(sessionProgress);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugfix. Not sure where this went, without it the era progress era calcs are completely wrong.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not seen this before since Kusama is running on forcing new eras - however visible on local substrate 2.x dev node (1.x is fine)


return {
currentEra,
Expand Down
56 changes: 27 additions & 29 deletions packages/api-derive/src/staking/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.

import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Balance, BlockNumber, Exposure, Keys, RewardDestination, StakingLedger, UnlockChunk, ValidatorPrefs } from '@polkadot/types/interfaces';
import { AccountId, Balance, BlockNumber, Exposure, Keys, Nominations, RewardDestination, StakingLedger, UnlockChunk, ValidatorPrefs } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DerivedRecentlyOffline, DerivedSessionInfo, DerivedStaking, DerivedUnlocking } from '../types';

Expand Down Expand Up @@ -152,62 +152,60 @@ function retrieveInfoV1 (api: ApiInterfaceRx, accountId: AccountId, stashId: Acc
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId]
]) as Observable<MultiResultV1>
]).pipe(map(([
sessionInfo, recentlyOffline,
[nextKeyFor, stakingLedger, [nominators], rewardDestination, stakers, [validatorPrefs]]
]: [DerivedSessionInfo, DerivedRecentlyOffline, MultiResultV1]): DerivedStaking =>
]).pipe(map(([sessionInfo, recentlyOffline, [nextKeyFor, stakingLedger, [nominators], rewardDestination, stakers, [validatorPrefs]]]: [DerivedSessionInfo, DerivedRecentlyOffline, MultiResultV1]): DerivedStaking =>
parseResult({
accountId, controllerId, stashId, sessionInfo, recentlyOffline, nextKeyFor, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs
})
));
}

type MultiResultV2 = [Option<StakingLedger>, [Vec<AccountId>], RewardDestination, Exposure, [ValidatorPrefs], Option<Keys>];
type MultiResultV2 = [[Vec<AccountId>] | Option<ITuple<[Nominations]>>, RewardDestination, Exposure, [ValidatorPrefs], Option<Keys>, Option<StakingLedger>];

function retrieveInfoV2 (api: ApiInterfaceRx, accountId: AccountId, stashId: AccountId, controllerId: AccountId): Observable<DerivedStaking> {
return combineLatest([
api.derive.session.info(),
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
api.queryMulti([
[api.query.staking.ledger, controllerId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId],
[api.query.session.nextKeys, [api.consts.session.dedupKeyPrefix, stashId]]
[api.query.session.nextKeys, [api.consts.session.dedupKeyPrefix, stashId]],
[api.query.staking.ledger, controllerId]
]) as Observable<MultiResultV2>
]).pipe(map(([
sessionInfo, queuedKeys,
[stakingLedger, [nominators], rewardDestination, stakers, [validatorPrefs], nextKeys]
]: [DerivedSessionInfo, [AccountId, Keys][], MultiResultV2]): DerivedStaking =>
parseResult({
]).pipe(map(([sessionInfo, queuedKeys, [_nominators, rewardDestination, stakers, [validatorPrefs], nextKeys, stakingLedger]]: [DerivedSessionInfo, [AccountId, Keys][], MultiResultV2]): DerivedStaking => {
// if we have staking.storageVersion it indicates the new structure, unwrap as needed
// FIXME We really want to be pulling all the new (valuable) info along
const nominators: AccountId[] = api.query.staking.storageVersion
? (_nominators as Option<ITuple<[Nominations]>>).isSome
? (_nominators as Option<ITuple<[Nominations]>>).unwrap()[0].targets
: []
: (_nominators as [Vec<AccountId>])[0];

return parseResult({
accountId, controllerId, stashId, sessionInfo, queuedKeys, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs, nextKeys
})
));
});
}));
}

function retrieveV1 (api: ApiInterfaceRx, controllerId: AccountId): Observable<DerivedStaking> {
return api.query.staking
.ledger<Option<StakingLedger>>(controllerId)
.pipe(
switchMap((stakingLedger): Observable<DerivedStaking> =>
stakingLedger.isSome
? retrieveInfoV1(api, controllerId, stakingLedger.unwrap().stash, controllerId)
: of({ accountId: controllerId, nextSessionIds: [], sessionIds: [] })
)
);
.pipe(switchMap((stakingLedger): Observable<DerivedStaking> =>
stakingLedger.isSome
? retrieveInfoV1(api, controllerId, stakingLedger.unwrap().stash, controllerId)
: of({ accountId: controllerId, nextSessionIds: [], sessionIds: [] })
));
}

function retrieveV2 (api: ApiInterfaceRx, stashId: AccountId): Observable<DerivedStaking> {
return api.query.staking
.bonded<Option<AccountId>>(stashId)
.pipe(
switchMap((controllerId): Observable<DerivedStaking> =>
controllerId.isSome
? retrieveInfoV2(api, stashId, stashId, controllerId.unwrap())
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] })
)
);
.pipe(switchMap((controllerId): Observable<DerivedStaking> =>
controllerId.isSome
? retrieveInfoV2(api, stashId, stashId, controllerId.unwrap())
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] })
));
}

/**
Expand Down
10 changes: 6 additions & 4 deletions packages/types/src/codec/create/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ const mappings: Mapper[] = [
_alias('Lookup::Source', 'Address'),
// alias Lookup::Target to AccountId (always the case)
_alias('Lookup::Target', 'AccountId'),
// alias for grandpa, as used in polkadot
_alias('grandpa::AuthorityId', 'AuthorityId'),
// specific for SessionIndex (could make this session::, but be conservative)
_alias('session::SessionIndex', 'SessionIndex'),
// alias for grandpa internal, as used in polkadot
_alias('grandpa::', ''),
// specific for session internal
_alias('session::', ''),
// specific for staking/slashing.rs internal
_alias('slashing::', ''),
// HACK duplication between contracts & primitives, however contracts prefixed with exec
_alias('exec::StorageKey', 'ContractStorageKey'),
// Phantom
Expand Down
21 changes: 20 additions & 1 deletion packages/types/src/interfaceRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { AuthorityIndex, AuthorityList, AuthorityWeight, NextAuthority, PendingP
import { AuthIndex, AuthoritySignature, Heartbeat, OpaqueMultiaddr, OpaqueNetworkState, OpaquePeerId } from '@polkadot/types/interfaces/imOnline';
import { Kind, OffenceDetails, Offender, OpaqueTimeSlot, ReportIdOf, Reporter } from '@polkadot/types/interfaces/offences';
import { FullIdentification, IdentificationTuple, Keys, SessionIndex, SessionKeys3, SessionKeys4, SessionKeys5, SessionKeysPolkadot, SessionKeysSubstrate } from '@polkadot/types/interfaces/session';
import { EraIndex, EraPoints, EraRewards, Exposure, Forcing, IndividualExposure, MomentOf, Points, RewardDestination, SlashJournalEntry, StakingLedger, UnlockChunk, ValidatorPrefs, ValidatorPrefs0to145 } from '@polkadot/types/interfaces/staking';
import { EraIndex, EraPoints, EraRewards, Exposure, Forcing, IndividualExposure, MomentOf, Nominations, Points, RewardDestination, SlashJournalEntry, SlashingSpans, SpanIndex, SpanRecord, StakingLedger, UnappliedSlash, UnappliedSlashOther, UnlockChunk, ValidatorPrefs, ValidatorPrefs0to145 } from '@polkadot/types/interfaces/staking';
import { DigestOf, DispatchError, Event, EventId, EventIndex, EventRecord, EventRecord0to76, Key, Phase } from '@polkadot/types/interfaces/system';
import { TreasuryProposal } from '@polkadot/types/interfaces/treasury';
import { Multiplier } from '@polkadot/types/interfaces/txpayment';
Expand Down Expand Up @@ -618,6 +618,9 @@ export interface InterfaceRegistry {
MomentOf: MomentOf;
'Option<MomentOf>': Option<MomentOf>;
'Vec<MomentOf>': Vec<MomentOf>;
Nominations: Nominations;
'Option<Nominations>': Option<Nominations>;
'Vec<Nominations>': Vec<Nominations>;
Points: Points;
'Compact<Points>': Compact<Points>;
'Option<Points>': Option<Points>;
Expand All @@ -628,9 +631,25 @@ export interface InterfaceRegistry {
SlashJournalEntry: SlashJournalEntry;
'Option<SlashJournalEntry>': Option<SlashJournalEntry>;
'Vec<SlashJournalEntry>': Vec<SlashJournalEntry>;
SlashingSpans: SlashingSpans;
'Option<SlashingSpans>': Option<SlashingSpans>;
'Vec<SlashingSpans>': Vec<SlashingSpans>;
SpanIndex: SpanIndex;
'Compact<SpanIndex>': Compact<SpanIndex>;
'Option<SpanIndex>': Option<SpanIndex>;
'Vec<SpanIndex>': Vec<SpanIndex>;
SpanRecord: SpanRecord;
'Option<SpanRecord>': Option<SpanRecord>;
'Vec<SpanRecord>': Vec<SpanRecord>;
StakingLedger: StakingLedger;
'Option<StakingLedger>': Option<StakingLedger>;
'Vec<StakingLedger>': Vec<StakingLedger>;
UnappliedSlashOther: UnappliedSlashOther;
'Option<UnappliedSlashOther>': Option<UnappliedSlashOther>;
'Vec<UnappliedSlashOther>': Vec<UnappliedSlashOther>;
UnappliedSlash: UnappliedSlash;
'Option<UnappliedSlash>': Option<UnappliedSlash>;
'Vec<UnappliedSlash>': Vec<UnappliedSlash>;
UnlockChunk: UnlockChunk;
'Option<UnlockChunk>': Option<UnlockChunk>;
'Vec<UnlockChunk>': Vec<UnlockChunk>;
Expand Down
23 changes: 23 additions & 0 deletions packages/types/src/interfaces/staking/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export default {
value: 'Compact<Balance>'
},
MomentOf: 'Moment',
Nominations: {
targets: 'Vec<AccountId>',
submittedIn: 'EraIndex',
suppressed: 'bool'
},
Points: 'u32',
RewardDestination: {
_enum: [
Expand All @@ -44,12 +49,30 @@ export default {
amount: 'Balance',
ownSlash: 'Balance'
},
SlashingSpans: {
spanIndex: 'SpanIndex',
lastStart: 'EraIndex',
prior: 'Vec<EraIndex>'
},
SpanIndex: 'u32',
SpanRecord: {
slashed: 'Balance',
paidOut: 'Balance'
},
StakingLedger: {
stash: 'AccountId',
total: 'Compact<Balance>',
active: 'Compact<Balance>',
unlocking: 'Vec<UnlockChunk>'
},
UnappliedSlashOther: '(AccountId, Balance)',
UnappliedSlash: {
validator: 'AccountId',
own: 'Balance',
others: 'Vec<UnappliedSlashOther>',
reporters: 'Vec<AccountId>',
payout: 'Balance'
},
UnlockChunk: {
value: 'Compact<Balance>',
era: 'Compact<BlockNumber>'
Expand Down
51 changes: 50 additions & 1 deletion packages/types/src/interfaces/staking/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Auto-generated via `yarn build:interfaces`, do not edit
/* eslint-disable @typescript-eslint/no-empty-interface */

import { ITuple } from '@polkadot/types/types';
import { Compact, Enum, Struct, Vec } from '@polkadot/types/codec';
import { u32 } from '@polkadot/types/primitive';
import { bool, u32 } from '@polkadot/types/primitive';
import { AccountId, Balance, BlockNumber, Moment } from '@polkadot/types/interfaces/runtime';

/** u32 */
Expand Down Expand Up @@ -57,6 +58,16 @@ export interface IndividualExposure extends Struct {
/** Moment */
export interface MomentOf extends Moment {}

/** Struct */
export interface Nominations extends Struct {
/** Vec<AccountId> */
readonly targets: Vec<AccountId>;
/** EraIndex */
readonly submittedIn: EraIndex;
/** bool */
readonly suppressed: bool;
}

/** u32 */
export interface Points extends u32 {}

Expand All @@ -70,6 +81,16 @@ export interface RewardDestination extends Enum {
readonly isController: boolean;
}

/** Struct */
export interface SlashingSpans extends Struct {
/** SpanIndex */
readonly spanIndex: SpanIndex;
/** EraIndex */
readonly lastStart: EraIndex;
/** Vec<EraIndex> */
readonly prior: Vec<EraIndex>;
}

/** Struct */
export interface SlashJournalEntry extends Struct {
/** AccountId */
Expand All @@ -80,6 +101,17 @@ export interface SlashJournalEntry extends Struct {
readonly ownSlash: Balance;
}

/** u32 */
export interface SpanIndex extends u32 {}

/** Struct */
export interface SpanRecord extends Struct {
/** Balance */
readonly slashed: Balance;
/** Balance */
readonly paidOut: Balance;
}

/** Struct */
export interface StakingLedger extends Struct {
/** AccountId */
Expand All @@ -92,6 +124,23 @@ export interface StakingLedger extends Struct {
readonly unlocking: Vec<UnlockChunk>;
}

/** Struct */
export interface UnappliedSlash extends Struct {
/** AccountId */
readonly validator: AccountId;
/** Balance */
readonly own: Balance;
/** Vec<UnappliedSlashOther> */
readonly others: Vec<UnappliedSlashOther>;
/** Vec<AccountId> */
readonly reporters: Vec<AccountId>;
/** Balance */
readonly payout: Balance;
}

/** ITuple<[AccountId, Balance]> */
export interface UnappliedSlashOther extends ITuple<[AccountId, Balance]> {}

/** Struct */
export interface UnlockChunk extends Struct {
/** Compact<Balance> */
Expand Down