diff --git a/packages/api-derive/src/staking/info.ts b/packages/api-derive/src/staking/info.ts index c53f780fd2..30b16d2d42 100644 --- a/packages/api-derive/src/staking/info.ts +++ b/packages/api-derive/src/staking/info.ts @@ -22,6 +22,10 @@ import { eraLength } from '../session/eraLength'; import { recentlyOffline } from './recentlyOffline'; import { drr } from '../util/drr'; +const EMPTY_KEYS = { + toU8a: (): Uint8Array => new Uint8Array() +}; + type MultiResult = [Option, [ Option | Vec<[AccountId, Keys] & Codec>, Option, [AccountId[]], RewardDestination, Exposure, [ValidatorPrefs] ]]; @@ -84,13 +88,27 @@ function redeemableSum (stakingLedger: StakingLedger | undefined, eraLength: BN, ); } +function keysToAccountIds (keys: Uint8Array): AccountId[] { + const result: AccountId[] = []; + let offset = 0; + + while (offset < keys.length) { + result.push(createType('AccountId', keys.subarray(offset, offset + 32))); + offset += 32; + } + + return result; +} + function unwrapSessionIds (stashId: AccountId, queuedKeys: Option | Vec<[AccountId, Keys] & Codec>, nextKeys: Option): { nextSessionIds: AccountId[]; nextSessionId?: AccountId; sessionIds: AccountId[]; sessionId?: AccountId } { // for 2.x we have a Vec<(ValidatorId,Keys)> of the keys if (Array.isArray(queuedKeys)) { - const sessionIds = (queuedKeys.find(([currentId]): boolean => currentId.eq(stashId)) || [undefined, { toArray: (): AccountId[] => [] }])[1].toArray() as AccountId[]; - const nextSessionIds = nextKeys.isSome - ? nextKeys.unwrap().toArray() as AccountId[] - : []; + const sessionIds = keysToAccountIds( + (queuedKeys.find(([currentId]): boolean => + currentId.eq(stashId) + ) || [undefined, EMPTY_KEYS])[1].toU8a(true) + ); + const nextSessionIds = keysToAccountIds(nextKeys.unwrapOr(EMPTY_KEYS).toU8a(true)); return { nextSessionId: nextSessionIds[0], diff --git a/packages/rpc-core/src/jsonrpc.types.ts b/packages/rpc-core/src/jsonrpc.types.ts index f8ce0a3989..683bd8f50f 100644 --- a/packages/rpc-core/src/jsonrpc.types.ts +++ b/packages/rpc-core/src/jsonrpc.types.ts @@ -9,7 +9,9 @@ import { Codec, IExtrinsic } from '@polkadot/types/types'; export interface RpcInterface { author: { + insertKey(keyType: Text | string, suri: Text | string, maybePublic?: Bytes | Uint8Array | string): Observable; removeExtrinsic(bytesOrHash: (ExtrinsicOrHash)[]): Observable>; + rotateKeys(): Observable; pendingExtrinsics(): Observable>; submitExtrinsic(extrinsic: IExtrinsic): Observable; submitAndWatchExtrinsic(extrinsic: IExtrinsic): Observable; diff --git a/packages/type-jsonrpc/src/author.ts b/packages/type-jsonrpc/src/author.ts index f83386d04d..7de6535a80 100644 --- a/packages/type-jsonrpc/src/author.ts +++ b/packages/type-jsonrpc/src/author.ts @@ -15,6 +15,22 @@ const removeExtrinsic: RpcMethodOpt = { type: 'Vec' }; +const insertKey: RpcMethodOpt = { + description: 'Insert a key into the keystore.', + params: [ + createParam('keyType', 'Text'), + createParam('suri', 'Text'), + createParam('maybePublic', 'Bytes', { isOptional: true }) + ], + type: 'Bytes' +}; + +const rotateKeys: RpcMethodOpt = { + description: 'Generate new session keys and returns the corresponding public keys', + params: [], + type: 'Bytes' +}; + const pendingExtrinsics: RpcMethodOpt = { description: 'Returns all pending extrinsics, potentially grouped by sender', params: [], @@ -55,7 +71,9 @@ export default { description: 'Authoring of network items', section, methods: { + insertKey: createMethod(section, 'insertKey', insertKey), removeExtrinsic: createMethod(section, 'removeExtrinsic', removeExtrinsic), + rotateKeys: createMethod(section, 'rotateKeys', rotateKeys), pendingExtrinsics: createMethod(section, 'pendingExtrinsics', pendingExtrinsics), submitExtrinsic: createMethod(section, 'submitExtrinsic', submitExtrinsic), submitAndWatchExtrinsic: createMethod(section, 'submitAndWatchExtrinsic', submitAndWatchExtrinsic)