From 31971b5d2c69911b02ebf9322be9ddbe5a01fea6 Mon Sep 17 00:00:00 2001 From: Jaco Date: Sun, 12 Jun 2022 09:36:41 +0200 Subject: [PATCH] Correct handling for storage Option> (#4927) * Correct handling for storage Option> * Adjust --- CHANGELOG.md | 1 + packages/types-codec/src/base/Option.spec.ts | 18 +++++++++++++++ packages/types-codec/src/base/Option.ts | 23 +++++++++++++------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03998d2e26..6c20f37167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Contributed: Changes: +- Ensure storage `Option>` are correctly handled - Cater for named event fields (expose on event data as available) - Expose (partial) `runtimeVersion` on `api.at` interfaces - Add aliases for `DispatchError{U8, U8a}` (default to new `U8a` variant) diff --git a/packages/types-codec/src/base/Option.spec.ts b/packages/types-codec/src/base/Option.spec.ts index 7453d88bdd..9de96f5b4a 100644 --- a/packages/types-codec/src/base/Option.spec.ts +++ b/packages/types-codec/src/base/Option.spec.ts @@ -43,6 +43,24 @@ describe('Option', (): void => { }); }); + it('can decode a nested Option', (): void => { + expect( + new Option( + registry, + Option.with(Option.with(Text)), + new Option( + registry, + Option.with(Text), + new Option( + registry, + Text, + new Uint8Array([1, 3 << 2, 66, 67, 68]) + ) + ) + ).toU8a() + ).toEqual(new Uint8Array([1, 1, 1, 3 << 2, 66, 67, 68])); + }); + it('can convert between different Some/None', (): void => { const def = '{ "foo":"Text", "zar":"Text" }'; const none = new Option(registry, def, null); diff --git a/packages/types-codec/src/base/Option.ts b/packages/types-codec/src/base/Option.ts index dda66fb976..45f6da8b9e 100644 --- a/packages/types-codec/src/base/Option.ts +++ b/packages/types-codec/src/base/Option.ts @@ -29,16 +29,23 @@ class None extends Null { /** @internal */ function decodeOption (registry: Registry, Type: CodecClass, value?: unknown): Codec { - // In the case of an option, unwrap the inner - if (value instanceof Option) { - value = value.value; - } - - if (isNull(value) || isUndefined(value) || value === '0x' || value instanceof None) { - return new None(registry); - } else if (value instanceof Type) { + if (value instanceof Type) { // don't re-create, use as it (which also caters for derived types) return value; + } else if (value instanceof Option) { + if (value.value instanceof Type) { + // same instance, return it + return value.value; + } else if (value.isNone) { + // internal is None, we are also none + return new None(registry); + } + + // convert the actual value into known + return new Type(registry, value.value); + } else if (isNull(value) || isUndefined(value) || value === '0x' || value instanceof None) { + // anyhting empty we pass as-is + return new None(registry); } else if (isU8a(value)) { // the isU8a check happens last in the if-tree - since the wrapped value // may be an instance of it, so Type and Option checks go in first