diff --git a/packages/api-observable/src/Combined.ts b/packages/api-observable/src/Combined.ts index 6cb269d086..b0a7c590df 100644 --- a/packages/api-observable/src/Combined.ts +++ b/packages/api-observable/src/Combined.ts @@ -135,11 +135,12 @@ export default class ApiCombined extends ApiCalls { this.sessionsPerEra(), this.eraLastLengthChange() ], - ([sessionBlockProgress, sessionLength, sessionCurrentIndex, sessionsPerEra, eraLastLengthChange = new BlockNumber(0)]: [BlockNumber | undefined, BlockNumber | undefined, BlockNumber | undefined, BlockNumber | undefined, BlockNumber | undefined]): BlockNumber | undefined => - sessionsPerEra && sessionCurrentIndex && sessionLength && sessionBlockProgress && eraLastLengthChange + ([sessionBlockProgress, sessionLength, sessionCurrentIndex, sessionsPerEra, eraLastLengthChange]: [BlockNumber | undefined, BlockNumber | undefined, BlockNumber | undefined, BlockNumber | undefined, BlockNumber | undefined]): BlockNumber | undefined => + sessionsPerEra && sessionCurrentIndex && sessionLength && sessionBlockProgress ? new BlockNumber( sessionCurrentIndex - .sub(eraLastLengthChange) + // last era can be null (i.e. new chain, valid key, no value set yet) + .sub(eraLastLengthChange || new BlockNumber(0)) .mod(sessionsPerEra.toBn()) .mul(sessionLength.toBn()) .add(sessionBlockProgress.toBn()) @@ -171,10 +172,11 @@ export default class ApiCombined extends ApiCalls { this.sessionLastLengthChange() ], ([bestNumber, sessionLength, lastSessionLengthChange]: [BlockNumber | undefined, BlockNumber | undefined, BlockNumber | undefined]): BlockNumber | undefined => - bestNumber && sessionLength && lastSessionLengthChange + bestNumber && sessionLength ? new BlockNumber( bestNumber - .sub(lastSessionLengthChange) + // last change can be null (i.e. new chain, valid key, no value set yet) + .sub(lastSessionLengthChange || new BlockNumber(0)) .add(sessionLength.toBn()) .mod(sessionLength.toBn()) ) diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 812bf04dfa..66e0ea0a68 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -169,7 +169,7 @@ export default class Api implements ApiInterface { ); } - private formatOutput (method: RpcMethod, params: Array, result?: any): Base | Array { + private formatOutput (method: RpcMethod, params: Array, result?: any): Base | Array { const base = createType(method.type as string).fromJSON(result); if (method.type === 'StorageData') { @@ -182,7 +182,10 @@ export default class Api implements ApiInterface { } } else if (method.type === 'StorageChangeSet') { // multiple return values (via state.storage subscription), decode the values - // one at a time, all based on the query types + // one at a time, all based on the query types. Three values can be returned - + // - Base - There is a valid value, non-empty + // - null - The storage key is empty (but in the resultset) + // - undefined - The storage value is not in the resultset return (params[0] as Vector).reduce((result, _key: StorageKey) => { const type = _key.outputType; @@ -199,13 +202,17 @@ export default class Api implements ApiInterface { // if we don't have a value, do not fill in the entry, it will be up to the // caller to sort this out, either ignoring or having a cache for older values result.push( - item && !item.value.isEmpty - ? createType(type, item.value.value) - : undefined + !item + ? undefined + : ( + item.value.isEmpty + ? null + : createType(type, item.value.value) + ) ); return result; - }, [] as Array); + }, [] as Array); } return base;