Skip to content

Commit

Permalink
Allow switching on/off of isPedantic checks (#5620)
Browse files Browse the repository at this point in the history
* Allow switching on/off of isPedantic checks

* CHANGELOG

* typos
  • Loading branch information
jacogr authored Apr 28, 2023
1 parent ac46305 commit 1ba4c0c
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
Changes:

- Default to hex-only in `Int/UInt.toJSON` for > 128-bit values
- Allow for disabling of `isPedantic` storage checks in API options
- Adjust usage of `objectSpread`, default to runtime as required
- Adjust compilation output for `__internal__` class fields


Expand Down
15 changes: 9 additions & 6 deletions packages/api/src/base/Decorate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,22 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
this._rx.queryAt = (blockHash: Uint8Array | string, knownVersion?: RuntimeVersion) =>
from(this.at(blockHash, knownVersion)).pipe(map((a) => a.rx.query));
this._rx.registry = this.#registry;
this._decorateMethod = decorateMethod;
this._options = options;
this._type = type;

const thisProvider = options.source
const provider = options.source
? options.source._rpcCore.provider.isClonable
? options.source._rpcCore.provider.clone()
: options.source._rpcCore.provider
: (options.provider || new WsProvider());

this._decorateMethod = decorateMethod;
this._options = options;
this._type = type;

// The RPC interface decorates the known interfaces on init
this._rpcCore = new RpcCore(this.#instanceId, this.#registry, thisProvider, this._options.rpc) as (RpcCore & RpcInterface);
this._rpcCore = new RpcCore(this.#instanceId, this.#registry, {
isPedantic: this._options.isPedantic,
provider,
userRpc: this._options.rpc
}) as (RpcCore & RpcInterface);
this._isConnected = new BehaviorSubject(this._rpcCore.provider.isConnected);
this._rx.hasSubscriptions = this._rpcCore.provider.hasSubscriptions;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/api/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export interface ApiOptions extends RegisteredTypes {
* @description Control the initialization of the wasm libraries. When not specified, it defaults to `true`, initializing the wasm libraries, set to `false` to not initialize wasm. (No sr25519 support)
*/
initWasm?: boolean;
/**
* @description Controls the checking of storage values once they have been contructed. When not specified this defaults to `true`. Set to `false` to forgo any checking on storage results.
*/
isPedantic?: boolean;
/**
* @description pre-bundles is a map of 'genesis hash and runtime spec version' as key to a metadata hex string
* if genesis hash and runtime spec version matches, then use metadata, else fetch it from chain
Expand Down
21 changes: 14 additions & 7 deletions packages/rpc-core/src/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ type MemoizedRpcInterfaceMethod = Memoized<RpcInterfaceMethod> & {
meta: DefinitionRpc;
}

interface Options {
isPedantic?: boolean;
provider: ProviderInterface;
userRpc?: Record<string, Record<string, DefinitionRpc | DefinitionRpcSub>>;
}

const l = logger('rpc-core');

const EMPTY_META = {
Expand Down Expand Up @@ -84,14 +90,14 @@ function isTreatAsHex (key: StorageKey): boolean {
* ```
*/
export class RpcCore {
#instanceId: string;
#registryDefault: Registry;
readonly #instanceId: string;
readonly #isPedantic: boolean;
readonly #registryDefault: Registry;
readonly #storageCache = new Map<string, Codec>();

#getBlockRegistry?: (blockHash: Uint8Array) => Promise<{ registry: Registry }>;
#getBlockHash?: (blockNumber: AnyNumber) => Promise<Uint8Array>;

readonly #storageCache = new Map<string, Codec>();

readonly mapping = new Map<string, DefinitionRpcExt>();
readonly provider: ProviderInterface;
readonly sections: string[] = [];
Expand All @@ -101,13 +107,14 @@ export class RpcCore {
* Default constructor for the core RPC handler
* @param {ProviderInterface} provider An API provider using any of the supported providers (HTTP, SC or WebSocket)
*/
constructor (instanceId: string, registry: Registry, provider: ProviderInterface, userRpc: Record<string, Record<string, DefinitionRpc | DefinitionRpcSub>> = {}) {
constructor (instanceId: string, registry: Registry, { isPedantic = true, provider, userRpc = {} }: Options) {
// eslint-disable-next-line @typescript-eslint/unbound-method
if (!provider || !isFunction(provider.send)) {
throw new Error('Expected Provider to API create');
}

this.#instanceId = instanceId;
this.#isPedantic = isPedantic;
this.#registryDefault = registry;
this.provider = provider;

Expand Down Expand Up @@ -484,9 +491,9 @@ export class RpcCore {
: hexToU8a(meta.fallback.toHex())
: undefined
: meta.modifier.isOptional
? registry.createTypeUnsafe(type, [input], { blockHash, isPedantic: true })
? registry.createTypeUnsafe(type, [input], { blockHash, isPedantic: this.#isPedantic })
: input
], { blockHash, isFallback: isEmpty && !!meta.fallback, isOptional: meta.modifier.isOptional, isPedantic: !meta.modifier.isOptional });
], { blockHash, isFallback: isEmpty && !!meta.fallback, isOptional: meta.modifier.isOptional, isPedantic: this.#isPedantic && !meta.modifier.isOptional });
} catch (error) {
throw new Error(`Unable to decode storage ${key.section || 'unknown'}.${key.method || 'unknown'}:${entryNum}: ${(error as Error).message}`);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/rpc-core/src/cached.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Cached Observables', (): void => {

beforeEach((): void => {
provider = new MockProvider(registry);
rpc = new RpcCore('123', registry, provider) as (RpcCore & RpcInterface);
rpc = new RpcCore('123', registry, { provider }) as (RpcCore & RpcInterface);
});

afterEach(async () => {
Expand Down
17 changes: 10 additions & 7 deletions packages/rpc-core/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ describe('Api', (): void => {

it('requires a provider with a send method', (): void => {
expect(
() => new RpcCore('234', registry, {} as unknown as ProviderInterface)
() => new RpcCore('234', registry, { provider: {} as unknown as ProviderInterface })
).toThrow(/Expected Provider/);
});

it('allows for the definition of user RPCs', async () => {
const provider = new MockProvider(registry);
const rpc = new RpcCore('567', registry, provider, {
testing: {
foo: {
description: 'foo',
params: [{ name: 'bar', type: 'u32' }],
type: 'Balance'
const rpc = new RpcCore('567', registry, {
provider,
userRpc: {
testing: {
foo: {
description: 'foo',
params: [{ name: 'bar', type: 'u32' }],
type: 'Balance'
}
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion packages/rpc-core/src/methodSend.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('methodSend', (): void => {
)
} as unknown as ProviderInterface;

rpc = new RpcCore('987', registry, provider);
rpc = new RpcCore('987', registry, { provider });
});

it('checks for mismatched parameters', async (): Promise<void> => {
Expand Down
2 changes: 1 addition & 1 deletion packages/rpc-core/src/replay.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('replay', (): void => {

beforeEach((): void => {
provider = new MockProvider(registry);
rpc = new RpcCore('653', registry, provider) as (RpcCore & RpcInterface);
rpc = new RpcCore('653', registry, { provider }) as (RpcCore & RpcInterface);
});

afterEach(async () => {
Expand Down

0 comments on commit 1ba4c0c

Please sign in to comment.