diff --git a/packages/api/test/e2e/promise-alex.spec.js b/packages/api/test/e2e/promise-alex.spec.js index d2ebf11688..b2a2cbcb10 100644 --- a/packages/api/test/e2e/promise-alex.spec.js +++ b/packages/api/test/e2e/promise-alex.spec.js @@ -8,48 +8,97 @@ import WsProvider from '../../../rpc-provider/src/ws'; describe.skip('alex queries', () => { let api; - beforeAll(async () => { - api = await Api.create({ - provider: new WsProvider('wss://poc3-rpc.polkadot.io/') - }); - - return api; - }); - beforeEach(() => { jest.setTimeout(3000000); }); - it('retrieves the list of validators', (done) => { - api.query.staking.validators((res) => { - console.log('api.query.staking.validators():', res.toJSON()); + describe.skip('Remote RPC queries', () => { + beforeAll(async () => { + api = await Api.create({ + provider: new WsProvider('wss://poc3-rpc.polkadot.io/') + }); - done(); + return api; + }); + + it('retrieves the list of validators', (done) => { + api.query.staking.validators((res) => { + console.log('api.query.staking.validators():', res.toJSON()); + + done(); + }); + }); + + it('retrieves a single value', (done) => { + api.query.staking.validators('5EF7wdkP9XZq38fu2ioAvxoEhHUJUc1E2KbuSQSMGofRKhCL', (res) => { + console.log('api.query.staking.validators(id):', res.toJSON()); + + done(); + }); + }); + + it('derives a list of the controllers', (done) => { + api.derive.staking.controllers((res) => { + console.log('api.derive.staking.controllers:', JSON.stringify(res)); + + done(); + }); + }); + + it.skip('retrieves the list of nominators', (done) => { + let count = 0; + api.query.staking.nominators((res) => { + console.log(`[${++count}]:: nominators(${res[0].length}):`, res.toJSON()); + + // done(); + }); }); }); - it('retrieves a single value', (done) => { - api.query.staking.validators('5EF7wdkP9XZq38fu2ioAvxoEhHUJUc1E2KbuSQSMGofRKhCL', (res) => { - console.log('api.query.staking.validators(id):', res.toJSON()); + describe.skip('Local archive queries (for debug)', () => { + beforeAll(async () => { + api = await Api.create(); + + return api; + }); + + // https://github.com/polkadot-js/api/issues/845 + it('retrieves block with no issues', async () => { + const metadata = await api.rpc.state.getMetadata('0x6f6f9bba0eed8e3ae9446c37eee763f93118b52a315a7b46090453ba6288da1f'); + + console.error(JSON.stringify(metadata, null, 2)); + + const block = await api.rpc.chain.getBlock('0x6f6f9bba0eed8e3ae9446c37eee763f93118b52a315a7b46090453ba6288da1f') + + console.error(block); + + expect(block).toBeDefined(); + + return true; + }); + + // https://github.com/polkadot-js/api/issues/846 + it('handles toJSON with no issues', async (done) => { + const signedBlock = await api.rpc.chain.getBlock('0x85c62b581f38cb81c3e443d34392672beb1fb877017fd7237cc87704113259dc'); + const failed = signedBlock.block.extrinsics.filter((extrinsic) => { + try { + const json = extrinsic.method.toJSON(); + + console.error(json); + + return false; + } catch (error) { + console.log(extrinsic.method); + console.log(extrinsic.method.keys()); + console.error(error); + + return true; + } + }); + + expect(failed).toHaveLength(0); done(); }); }); - - it('derives a list of the controllers', (done) => { - api.derive.staking.controllers((res) => { - console.log('api.derive.staking.controllers:', JSON.stringify(res)); - - done(); - }); - }); - - it.skip('retrieves the list of nominators', (done) => { - let count = 0; - api.query.staking.nominators((res) => { - console.log(`[${++count}]:: nominators(${res[0].length}):`, res.toJSON()); - - // done(); - }); - }); }); diff --git a/packages/types/src/codec/Struct.ts b/packages/types/src/codec/Struct.ts index 15164e6c30..d05e6e2213 100644 --- a/packages/types/src/codec/Struct.ts +++ b/packages/types/src/codec/Struct.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { hexToU8a, isHex, isObject, isU8a, u8aConcat, u8aToHex } from '@plugnet/util'; +import { hexToU8a, isHex, isObject, isU8a, isUndefined, u8aConcat, u8aToHex } from '@plugnet/util'; import { Codec, Constructor, ConstructorDef } from '../types'; import { compareMap, decodeU8a } from './utils'; @@ -79,6 +79,7 @@ export default class Struct< return Object.keys(Types).reduce((raw: T, key: keyof S, index) => { // TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'. (raw as any)[key] = values[index]; + return raw; }, {} as T); } else if (!value) { @@ -99,23 +100,29 @@ export default class Struct< // Types, result or any other maps, it's camelCase const jsonKey = (jsonMap.get(key as any) && !value[key]) ? jsonMap.get(key as any) : key; - if (Array.isArray(value)) { - raw[key] = value[index] instanceof Types[key] - ? value[index] - : new Types[key](value[index]); - } else if (value instanceof Map) { - const mapped = value.get(jsonKey); + try { + if (Array.isArray(value)) { + raw[key] = value[index] instanceof Types[key] + ? value[index] + : new Types[key](value[index]); + } else if (value instanceof Map) { + const mapped = value.get(jsonKey); - // TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'. - (raw as any)[key] = mapped instanceof Types[key] - ? mapped - : new Types[key](mapped); - } else if (isObject(value)) { - raw[key] = value[jsonKey as string] instanceof Types[key] - ? value[jsonKey as string] - : new Types[key](value[jsonKey as string]); - } else { - throw new Error(`Struct: cannot decode type ${Types[key].name} with value ${JSON.stringify(value)}`); + // TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'. + (raw as any)[key] = mapped instanceof Types[key] + ? mapped + : new Types[key](mapped); + } else if (isObject(value)) { + raw[key] = value[jsonKey as string] instanceof Types[key] + ? value[jsonKey as string] + : new Types[key](value[jsonKey as string]); + } else { + throw new Error(`Struct: cannot decode type ${Types[key].name} with value ${JSON.stringify(value)}`); + } + } catch (error) { + console.error(`Unable to decode Struct on key '${jsonKey}': ${error.message}`); + + throw error; } return raw; @@ -130,6 +137,11 @@ export default class Struct< super(Types, value, jsonMap); (Object.keys(Types) as Array).forEach((key) => { + // do not clobber existing properties on the object + if (!isUndefined((this as any)[key])) { + return; + } + Object.defineProperty(this, key, { enumerable: true, get: () => this.get(key) @@ -212,8 +224,8 @@ export default class Struct< toJSON (): any { return [...this.keys()].reduce((json, key) => { const jsonKey = this._jsonMap.get(key) || key; - const value = this.get(key); + json[jsonKey] = value && value.toJSON(); return json; diff --git a/packages/types/src/codec/Tuple.ts b/packages/types/src/codec/Tuple.ts index b2af140e30..f7e880da42 100644 --- a/packages/types/src/codec/Tuple.ts +++ b/packages/types/src/codec/Tuple.ts @@ -41,7 +41,13 @@ export default class Tuple extends AbstractArray { : Object.values(_Types); return Types.map((Type, index) => { - return new Type(value && value[index]); + try { + return new Type(value && value[index]); + } catch (error) { + console.error(`Unable to decode Tuple on index ${index}`, error.message); + + throw error; + } }); } diff --git a/packages/types/src/codec/Vector.ts b/packages/types/src/codec/Vector.ts index 4629fb587e..6c341bde4f 100644 --- a/packages/types/src/codec/Vector.ts +++ b/packages/types/src/codec/Vector.ts @@ -29,11 +29,17 @@ export default class Vector extends AbstractArray { static decodeVector (Type: Constructor, value: Vector | Uint8Array | string | Array): Array { if (Array.isArray(value)) { - return value.map((entry) => - entry instanceof Type - ? entry - : new Type(entry) - ); + return value.map((entry, index) => { + try { + return entry instanceof Type + ? entry + : new Type(entry); + } catch (error) { + console.error(`Unable to decode Vector on index ${index}`, error.message); + + throw error; + } + }); } const u8a = u8aToU8a(value); diff --git a/packages/types/src/codec/utils/decodeU8a.ts b/packages/types/src/codec/utils/decodeU8a.ts index 50e8629f87..bcb978f598 100644 --- a/packages/types/src/codec/utils/decodeU8a.ts +++ b/packages/types/src/codec/utils/decodeU8a.ts @@ -21,7 +21,14 @@ export default function decodeU8a (u8a: Uint8Array, _types: Constructor[] | { [i } const Type = types[0]; - const value = new Type(u8a); - return [value].concat(decodeU8a(u8a.subarray(value.encodedLength), types.slice(1))); + try { + const value = new Type(u8a); + + return [value].concat(decodeU8a(u8a.subarray(value.encodedLength), types.slice(1))); + } catch (error) { + console.error(`Unable to decode Uint8Array for type '${Type.name}': ${error.message}`); + + throw error; + } }