@pezkuwi/rpc-core 16.5.8 → 16.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/packageInfo.js +1 -1
- package/package.json +9 -8
- package/packageInfo.js +1 -1
- package/build/LICENSE +0 -201
- package/build/README.md +0 -3
- package/build/bundle.d.ts +0 -91
- package/build/bundle.js +0 -411
- package/build/cjs/bundle.d.ts +0 -91
- package/build/cjs/bundle.js +0 -417
- package/build/cjs/index.d.ts +0 -2
- package/build/cjs/index.js +0 -5
- package/build/cjs/package.json +0 -3
- package/build/cjs/packageDetect.d.ts +0 -1
- package/build/cjs/packageDetect.js +0 -7
- package/build/cjs/packageInfo.d.ts +0 -6
- package/build/cjs/packageInfo.js +0 -4
- package/build/cjs/types/base.d.ts +0 -22
- package/build/cjs/types/base.js +0 -2
- package/build/cjs/types/index.d.ts +0 -2
- package/build/cjs/types/index.js +0 -5
- package/build/cjs/types/jsonrpc.d.ts +0 -2
- package/build/cjs/types/jsonrpc.js +0 -2
- package/build/cjs/util/drr.d.ts +0 -15
- package/build/cjs/util/drr.js +0 -31
- package/build/cjs/util/index.d.ts +0 -3
- package/build/cjs/util/index.js +0 -6
- package/build/cjs/util/memo.d.ts +0 -6
- package/build/cjs/util/memo.js +0 -18
- package/build/cjs/util/refCountDelay.d.ts +0 -3
- package/build/cjs/util/refCountDelay.js +0 -40
- package/build/index.d.ts +0 -2
- package/build/index.js +0 -2
- package/build/package.json +0 -209
- package/build/packageDetect.d.ts +0 -1
- package/build/packageDetect.js +0 -5
- package/build/packageInfo.d.ts +0 -6
- package/build/packageInfo.js +0 -1
- package/build/types/base.d.ts +0 -22
- package/build/types/base.js +0 -1
- package/build/types/index.d.ts +0 -2
- package/build/types/index.js +0 -2
- package/build/types/jsonrpc.d.ts +0 -2
- package/build/types/jsonrpc.js +0 -1
- package/build/util/drr.d.ts +0 -15
- package/build/util/drr.js +0 -28
- package/build/util/index.d.ts +0 -3
- package/build/util/index.js +0 -3
- package/build/util/memo.d.ts +0 -6
- package/build/util/memo.js +0 -15
- package/build/util/refCountDelay.d.ts +0 -3
- package/build/util/refCountDelay.js +0 -37
- package/build-deno/README.md +0 -3
- package/build-deno/bundle.ts +0 -532
- package/build-deno/checkTypes.manual.ts +0 -2
- package/build-deno/index.ts +0 -4
- package/build-deno/mod.ts +0 -2
- package/build-deno/packageDetect.ts +0 -9
- package/build-deno/packageInfo.ts +0 -3
- package/build-deno/types/base.ts +0 -26
- package/build-deno/types/index.ts +0 -4
- package/build-deno/types/jsonrpc.ts +0 -4
- package/build-deno/util/drr.ts +0 -50
- package/build-deno/util/index.ts +0 -4
- package/build-deno/util/memo.ts +0 -30
- package/build-deno/util/refCountDelay.ts +0 -43
- package/build-tsc/bundle.d.ts +0 -91
- package/build-tsc/index.d.ts +0 -2
- package/build-tsc/packageDetect.d.ts +0 -1
- package/build-tsc/packageInfo.d.ts +0 -6
- package/build-tsc/types/base.d.ts +0 -22
- package/build-tsc/types/index.d.ts +0 -2
- package/build-tsc/types/jsonrpc.d.ts +0 -2
- package/build-tsc/util/drr.d.ts +0 -15
- package/build-tsc/util/index.d.ts +0 -3
- package/build-tsc/util/memo.d.ts +0 -6
- package/build-tsc/util/refCountDelay.d.ts +0 -3
- package/build-tsc-cjs/bundle.js +0 -417
- package/build-tsc-cjs/index.js +0 -5
- package/build-tsc-cjs/packageDetect.js +0 -7
- package/build-tsc-cjs/packageInfo.js +0 -4
- package/build-tsc-cjs/types/base.js +0 -2
- package/build-tsc-cjs/types/index.js +0 -5
- package/build-tsc-cjs/types/jsonrpc.js +0 -2
- package/build-tsc-cjs/util/drr.js +0 -31
- package/build-tsc-cjs/util/index.js +0 -6
- package/build-tsc-cjs/util/memo.js +0 -18
- package/build-tsc-cjs/util/refCountDelay.js +0 -40
- package/build-tsc-esm/bundle.js +0 -411
- package/build-tsc-esm/index.js +0 -2
- package/build-tsc-esm/packageDetect.js +0 -5
- package/build-tsc-esm/packageInfo.js +0 -1
- package/build-tsc-esm/types/base.js +0 -1
- package/build-tsc-esm/types/index.js +0 -2
- package/build-tsc-esm/types/jsonrpc.js +0 -1
- package/build-tsc-esm/util/drr.js +0 -28
- package/build-tsc-esm/util/index.js +0 -3
- package/build-tsc-esm/util/memo.js +0 -15
- package/build-tsc-esm/util/refCountDelay.js +0 -37
- package/src/bundle.ts +0 -535
- package/src/cached.spec.ts +0 -129
- package/src/checkTypes.manual.ts +0 -4
- package/src/index.spec.ts +0 -55
- package/src/index.ts +0 -6
- package/src/methodSend.spec.ts +0 -75
- package/src/mod.ts +0 -4
- package/src/packageDetect.ts +0 -13
- package/src/packageInfo.ts +0 -6
- package/src/replay.spec.ts +0 -73
- package/src/types/base.ts +0 -28
- package/src/types/index.ts +0 -8
- package/src/types/jsonrpc.ts +0 -7
- package/src/util/drr.spec.ts +0 -50
- package/src/util/drr.ts +0 -52
- package/src/util/index.ts +0 -6
- package/src/util/memo.ts +0 -36
- package/src/util/refCountDelay.ts +0 -45
- package/tsconfig.build.json +0 -17
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.spec.json +0 -20
- package/tsconfig.spec.tsbuildinfo +0 -1
package/build-deno/bundle.ts
DELETED
|
@@ -1,532 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Observer } from 'https://esm.sh/rxjs@7.8.1';
|
|
3
|
-
import type { ProviderInterface, ProviderInterfaceCallback } from 'https://deno.land/x/pezkuwi/rpc-provider/types.ts';
|
|
4
|
-
import type { StorageKey, Vec } from 'https://deno.land/x/pezkuwi/types/mod.ts';
|
|
5
|
-
import type { Hash } from 'https://deno.land/x/pezkuwi/types/interfaces/index.ts';
|
|
6
|
-
import type { AnyJson, AnyNumber, Codec, DefinitionRpc, DefinitionRpcExt, DefinitionRpcSub, Registry } from 'https://deno.land/x/pezkuwi/types/types/index.ts';
|
|
7
|
-
import type { Memoized } from 'https://deno.land/x/pezkuwi/util/types.ts';
|
|
8
|
-
import type { RpcCoreStats, RpcInterfaceMethod } from './types/index.ts';
|
|
9
|
-
|
|
10
|
-
import { Observable, publishReplay, refCount } from 'https://esm.sh/rxjs@7.8.1';
|
|
11
|
-
|
|
12
|
-
import { LRUCache } from 'https://deno.land/x/pezkuwi/rpc-provider/mod.ts';
|
|
13
|
-
import { rpcDefinitions } from 'https://deno.land/x/pezkuwi/types/mod.ts';
|
|
14
|
-
import { unwrapStorageSi } from 'https://deno.land/x/pezkuwi/types/util/index.ts';
|
|
15
|
-
import { hexToU8a, isFunction, isNull, isUndefined, lazyMethod, logger, memoize, objectSpread, u8aConcat, u8aToU8a } from 'https://deno.land/x/pezkuwi/util/mod.ts';
|
|
16
|
-
|
|
17
|
-
import { drr, refCountDelay } from './util/index.ts';
|
|
18
|
-
|
|
19
|
-
export { packageInfo } from './packageInfo.ts';
|
|
20
|
-
export * from './util/index.ts';
|
|
21
|
-
|
|
22
|
-
interface StorageChangeSetJSON {
|
|
23
|
-
block: string;
|
|
24
|
-
changes: [string, string | null][];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
type MemoizedRpcInterfaceMethod = Memoized<RpcInterfaceMethod> & {
|
|
28
|
-
raw: Memoized<RpcInterfaceMethod>;
|
|
29
|
-
meta: DefinitionRpc;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface Options {
|
|
33
|
-
isPedantic?: boolean;
|
|
34
|
-
provider: ProviderInterface;
|
|
35
|
-
/**
|
|
36
|
-
* Custom size of the rpc LRUCache capacity. Defaults to `RPC_CORE_DEFAULT_CAPACITY` (1024 * 10 * 10)
|
|
37
|
-
*/
|
|
38
|
-
rpcCacheCapacity?: number;
|
|
39
|
-
ttl?: number | null;
|
|
40
|
-
userRpc?: Record<string, Record<string, DefinitionRpc | DefinitionRpcSub>>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const l = logger('rpc-core');
|
|
44
|
-
|
|
45
|
-
const EMPTY_META = {
|
|
46
|
-
fallback: undefined,
|
|
47
|
-
modifier: { isOptional: true },
|
|
48
|
-
type: {
|
|
49
|
-
asMap: { linked: { isTrue: false } },
|
|
50
|
-
isMap: false
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const RPC_CORE_DEFAULT_CAPACITY = 1024 * 10 * 10;
|
|
55
|
-
|
|
56
|
-
/** @internal */
|
|
57
|
-
function logErrorMessage (method: string, { noErrorLog, params, type }: DefinitionRpc, error: Error): void {
|
|
58
|
-
if (noErrorLog) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
l.error(`${method}(${
|
|
63
|
-
params.map(({ isOptional, name, type }): string =>
|
|
64
|
-
`${name}${isOptional ? '?' : ''}: ${type}`
|
|
65
|
-
).join(', ')
|
|
66
|
-
}): ${type}:: ${error.message}`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function isTreatAsHex (key: StorageKey): boolean {
|
|
70
|
-
// :code is problematic - it does not have the length attached, which is
|
|
71
|
-
// unlike all other storage entries where it is indeed properly encoded
|
|
72
|
-
return ['0x3a636f6465'].includes(key.toHex());
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* @name Rpc
|
|
77
|
-
* @summary The API may use a HTTP or WebSockets provider.
|
|
78
|
-
* @description It allows for querying a Pezkuwi Client Node.
|
|
79
|
-
* WebSockets provider is recommended since HTTP provider only supports basic querying.
|
|
80
|
-
*
|
|
81
|
-
* ```mermaid
|
|
82
|
-
* graph LR;
|
|
83
|
-
* A[Api] --> |WebSockets| B[WsProvider];
|
|
84
|
-
* B --> |endpoint| C[ws://127.0.0.1:9944]
|
|
85
|
-
* ```
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* <BR>
|
|
89
|
-
*
|
|
90
|
-
* ```javascript
|
|
91
|
-
* import Rpc from 'https://deno.land/x/pezkuwi/rpc-core/mod.ts';
|
|
92
|
-
* import { WsProvider } from 'https://deno.land/x/pezkuwi/rpc-provider/ws/index.ts';
|
|
93
|
-
*
|
|
94
|
-
* const provider = new WsProvider('ws://127.0.0.1:9944');
|
|
95
|
-
* const rpc = new Rpc(provider);
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
export class RpcCore {
|
|
99
|
-
readonly #instanceId: string;
|
|
100
|
-
readonly #isPedantic: boolean;
|
|
101
|
-
readonly #registryDefault: Registry;
|
|
102
|
-
readonly #storageCache: LRUCache;
|
|
103
|
-
#storageCacheHits = 0;
|
|
104
|
-
|
|
105
|
-
#getBlockRegistry?: (blockHash: Uint8Array) => Promise<{ registry: Registry }>;
|
|
106
|
-
#getBlockHash?: (blockNumber: AnyNumber) => Promise<Uint8Array>;
|
|
107
|
-
|
|
108
|
-
readonly mapping = new Map<string, DefinitionRpcExt>();
|
|
109
|
-
readonly provider: ProviderInterface;
|
|
110
|
-
readonly sections: string[] = [];
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* @constructor
|
|
114
|
-
* Default constructor for the core RPC handler
|
|
115
|
-
* @param {Registry} registry Type Registry
|
|
116
|
-
* @param {ProviderInterface} options.provider An API provider using any of the supported providers (HTTP, SC or WebSocket)
|
|
117
|
-
* @param {number} [options.rpcCacheCapacity] Custom size of the rpc LRUCache capacity. Defaults to `RPC_CORE_DEFAULT_CAPACITY` (1024 * 10 * 10)
|
|
118
|
-
*/
|
|
119
|
-
constructor (instanceId: string, registry: Registry, { isPedantic = true, provider, rpcCacheCapacity, ttl, userRpc = {} }: Options) {
|
|
120
|
-
if (!provider || !isFunction(provider.send)) {
|
|
121
|
-
throw new Error('Expected Provider to API create');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
this.#instanceId = instanceId;
|
|
125
|
-
this.#isPedantic = isPedantic;
|
|
126
|
-
this.#registryDefault = registry;
|
|
127
|
-
this.provider = provider;
|
|
128
|
-
|
|
129
|
-
const sectionNames = Object.keys(rpcDefinitions);
|
|
130
|
-
|
|
131
|
-
// these are the base keys (i.e. part of jsonrpc)
|
|
132
|
-
this.sections.push(...sectionNames);
|
|
133
|
-
this.#storageCache = new LRUCache(rpcCacheCapacity || RPC_CORE_DEFAULT_CAPACITY, ttl);
|
|
134
|
-
// decorate all interfaces, defined and user on this instance
|
|
135
|
-
this.addUserInterfaces(userRpc);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* @description Returns the connected status of a provider
|
|
140
|
-
*/
|
|
141
|
-
public get isConnected (): boolean {
|
|
142
|
-
return this.provider.isConnected;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* @description Manually connect from the attached provider
|
|
147
|
-
*/
|
|
148
|
-
public connect (): Promise<void> {
|
|
149
|
-
return this.provider.connect();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* @description Manually disconnect from the attached provider
|
|
154
|
-
*/
|
|
155
|
-
public async disconnect (): Promise<void> {
|
|
156
|
-
return this.provider.disconnect();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @description Returns the underlying core stats, including those from teh provider
|
|
161
|
-
*/
|
|
162
|
-
public get stats (): RpcCoreStats | undefined {
|
|
163
|
-
const stats = this.provider.stats;
|
|
164
|
-
|
|
165
|
-
return stats
|
|
166
|
-
? {
|
|
167
|
-
...stats,
|
|
168
|
-
core: {
|
|
169
|
-
cacheHits: this.#storageCacheHits,
|
|
170
|
-
cacheSize: this.#storageCache.length
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
: undefined;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* @description Sets a registry swap (typically from Api)
|
|
178
|
-
*/
|
|
179
|
-
public setRegistrySwap (registrySwap: (blockHash: Uint8Array) => Promise<{ registry: Registry }>): void {
|
|
180
|
-
this.#getBlockRegistry = memoize(registrySwap, {
|
|
181
|
-
getInstanceId: () => this.#instanceId
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* @description Sets a function to resolve block hash from block number
|
|
187
|
-
*/
|
|
188
|
-
public setResolveBlockHash (resolveBlockHash: (blockNumber: AnyNumber) => Promise<Uint8Array>): void {
|
|
189
|
-
this.#getBlockHash = memoize(resolveBlockHash, {
|
|
190
|
-
getInstanceId: () => this.#instanceId
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
public addUserInterfaces (userRpc: Record<string, Record<string, DefinitionRpc | DefinitionRpcSub>>): void {
|
|
195
|
-
// add any extra user-defined sections
|
|
196
|
-
this.sections.push(...Object.keys(userRpc).filter((k) => !this.sections.includes(k)));
|
|
197
|
-
|
|
198
|
-
for (let s = 0, scount = this.sections.length; s < scount; s++) {
|
|
199
|
-
const section = this.sections[s];
|
|
200
|
-
const defs = objectSpread<Record<string, DefinitionRpc | DefinitionRpcSub>>({}, rpcDefinitions[section as 'babe'], userRpc[section]);
|
|
201
|
-
const methods = Object.keys(defs);
|
|
202
|
-
|
|
203
|
-
for (let m = 0, mcount = methods.length; m < mcount; m++) {
|
|
204
|
-
const method = methods[m];
|
|
205
|
-
const def = defs[method];
|
|
206
|
-
const jsonrpc = def.endpoint || `${section}_${method}`;
|
|
207
|
-
|
|
208
|
-
if (!this.mapping.has(jsonrpc)) {
|
|
209
|
-
const isSubscription = !!(def as DefinitionRpcSub).pubsub;
|
|
210
|
-
|
|
211
|
-
if (!(this as Record<string, unknown>)[section]) {
|
|
212
|
-
(this as Record<string, unknown>)[section] = {};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
this.mapping.set(jsonrpc, objectSpread({}, def, { isSubscription, jsonrpc, method, section }));
|
|
216
|
-
|
|
217
|
-
lazyMethod(this[section as 'connect'], method, () =>
|
|
218
|
-
isSubscription
|
|
219
|
-
? this._createMethodSubscribe(section, method, def as DefinitionRpcSub)
|
|
220
|
-
: this._createMethodSend(section, method, def)
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
private _memomize (creator: <T> (isScale: boolean) => (...values: unknown[]) => Observable<T>, def: DefinitionRpc): MemoizedRpcInterfaceMethod {
|
|
228
|
-
const memoOpts = { getInstanceId: () => this.#instanceId };
|
|
229
|
-
const memoized = memoize(creator(true) as RpcInterfaceMethod, memoOpts);
|
|
230
|
-
|
|
231
|
-
memoized.raw = memoize(creator(false), memoOpts);
|
|
232
|
-
memoized.meta = def;
|
|
233
|
-
|
|
234
|
-
return memoized as MemoizedRpcInterfaceMethod;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
private _formatResult <T> (isScale: boolean, registry: Registry, blockHash: string | Uint8Array | null | undefined, method: string, def: DefinitionRpc, params: Codec[], result: unknown): T {
|
|
238
|
-
return isScale
|
|
239
|
-
? this._formatOutput(registry, blockHash, method, def, params, result) as unknown as T
|
|
240
|
-
: result as T;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
private _createMethodSend (section: string, method: string, def: DefinitionRpc): RpcInterfaceMethod {
|
|
244
|
-
const rpcName = def.endpoint || `${section}_${method}`;
|
|
245
|
-
const hashIndex = def.params.findIndex(({ isHistoric }) => isHistoric);
|
|
246
|
-
let memoized: null | MemoizedRpcInterfaceMethod = null;
|
|
247
|
-
|
|
248
|
-
// execute the RPC call, doing a registry swap for historic as applicable
|
|
249
|
-
const callWithRegistry = async <T> (isScale: boolean, values: unknown[]): Promise<T> => {
|
|
250
|
-
const blockId = hashIndex === -1
|
|
251
|
-
? null
|
|
252
|
-
: values[hashIndex];
|
|
253
|
-
|
|
254
|
-
const blockHash = blockId && def.params[hashIndex].type === 'BlockNumber'
|
|
255
|
-
? await this.#getBlockHash?.(blockId as AnyNumber)
|
|
256
|
-
: blockId as (Uint8Array | string | null | undefined);
|
|
257
|
-
|
|
258
|
-
const { registry } = isScale && blockHash && this.#getBlockRegistry
|
|
259
|
-
? await this.#getBlockRegistry(u8aToU8a(blockHash))
|
|
260
|
-
: { registry: this.#registryDefault };
|
|
261
|
-
|
|
262
|
-
const params = this._formatParams(registry, null, def, values);
|
|
263
|
-
|
|
264
|
-
// only cache .at(<blockHash>) queries, e.g. where valid blockHash was supplied
|
|
265
|
-
const result = await this.provider.send<AnyJson>(rpcName, params.map((p) => p.toJSON()), !!blockHash);
|
|
266
|
-
|
|
267
|
-
return this._formatResult(isScale, registry, blockHash, method, def, params, result);
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
const creator = <T> (isScale: boolean) => (...values: unknown[]): Observable<T> => {
|
|
271
|
-
const isDelayed = isScale && hashIndex !== -1 && !!values[hashIndex];
|
|
272
|
-
|
|
273
|
-
return new Observable((observer: Observer<T>): () => void => {
|
|
274
|
-
callWithRegistry<T>(isScale, values)
|
|
275
|
-
.then((value): void => {
|
|
276
|
-
observer.next(value);
|
|
277
|
-
observer.complete();
|
|
278
|
-
})
|
|
279
|
-
.catch((error: Error): void => {
|
|
280
|
-
logErrorMessage(method, def, error);
|
|
281
|
-
|
|
282
|
-
observer.error(error);
|
|
283
|
-
observer.complete();
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
return (): void => {
|
|
287
|
-
// delete old results from cache
|
|
288
|
-
if (isScale) {
|
|
289
|
-
memoized?.unmemoize(...values);
|
|
290
|
-
} else {
|
|
291
|
-
memoized?.raw.unmemoize(...values);
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
}).pipe(
|
|
295
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
296
|
-
publishReplay(1), // create a Replay(1)
|
|
297
|
-
isDelayed
|
|
298
|
-
? refCountDelay() // Unsubscribe after delay
|
|
299
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
300
|
-
: refCount()
|
|
301
|
-
);
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
memoized = this._memomize(creator, def);
|
|
305
|
-
|
|
306
|
-
return memoized;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// create a subscriptor, it subscribes once and resolves with the id as subscribe
|
|
310
|
-
private _createSubscriber ({ paramsJson, subName, subType, update }: { subType: string; subName: string; paramsJson: AnyJson[]; update: ProviderInterfaceCallback }, errorHandler: (error: Error) => void): Promise<number | string> {
|
|
311
|
-
return new Promise((resolve, reject): void => {
|
|
312
|
-
this.provider
|
|
313
|
-
.subscribe(subType, subName, paramsJson, update)
|
|
314
|
-
.then(resolve)
|
|
315
|
-
.catch((error: Error): void => {
|
|
316
|
-
errorHandler(error);
|
|
317
|
-
reject(error);
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
private _createMethodSubscribe (section: string, method: string, def: DefinitionRpcSub): RpcInterfaceMethod {
|
|
323
|
-
const [updateType, subMethod, unsubMethod] = def.pubsub;
|
|
324
|
-
const subName = `${section}_${subMethod}`;
|
|
325
|
-
const unsubName = `${section}_${unsubMethod}`;
|
|
326
|
-
const subType = `${section}_${updateType}`;
|
|
327
|
-
let memoized: null | MemoizedRpcInterfaceMethod = null;
|
|
328
|
-
|
|
329
|
-
const creator = <T> (isScale: boolean) => (...values: unknown[]): Observable<T> => {
|
|
330
|
-
return new Observable((observer: Observer<T>): () => void => {
|
|
331
|
-
// Have at least an empty promise, as used in the unsubscribe
|
|
332
|
-
let subscriptionPromise: Promise<number | string | null> = Promise.resolve(null);
|
|
333
|
-
const registry = this.#registryDefault;
|
|
334
|
-
|
|
335
|
-
const errorHandler = (error: Error): void => {
|
|
336
|
-
logErrorMessage(method, def, error);
|
|
337
|
-
|
|
338
|
-
observer.error(error);
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
try {
|
|
342
|
-
const params = this._formatParams(registry, null, def, values);
|
|
343
|
-
|
|
344
|
-
const update = (error?: Error | null, result?: unknown): void => {
|
|
345
|
-
if (error) {
|
|
346
|
-
logErrorMessage(method, def, error);
|
|
347
|
-
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
try {
|
|
352
|
-
observer.next(this._formatResult(isScale, registry, null, method, def, params, result));
|
|
353
|
-
} catch (error) {
|
|
354
|
-
observer.error(error);
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
subscriptionPromise = this._createSubscriber({ paramsJson: params.map((p) => p.toJSON()), subName, subType, update }, errorHandler);
|
|
359
|
-
} catch (error) {
|
|
360
|
-
errorHandler(error as Error);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// Teardown logic
|
|
364
|
-
return (): void => {
|
|
365
|
-
// Delete from cache, so old results don't hang around
|
|
366
|
-
if (isScale) {
|
|
367
|
-
memoized?.unmemoize(...values);
|
|
368
|
-
} else {
|
|
369
|
-
memoized?.raw.unmemoize(...values);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Unsubscribe from provider
|
|
373
|
-
subscriptionPromise
|
|
374
|
-
.then((subscriptionId): Promise<boolean> =>
|
|
375
|
-
isNull(subscriptionId)
|
|
376
|
-
? Promise.resolve(false)
|
|
377
|
-
: this.provider.unsubscribe(subType, unsubName, subscriptionId)
|
|
378
|
-
)
|
|
379
|
-
.catch((error: Error) => logErrorMessage(method, def, error));
|
|
380
|
-
};
|
|
381
|
-
}).pipe(drr());
|
|
382
|
-
};
|
|
383
|
-
|
|
384
|
-
memoized = this._memomize(creator, def);
|
|
385
|
-
|
|
386
|
-
return memoized;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
private _formatParams (registry: Registry, blockHash: Uint8Array | string | null | undefined, def: DefinitionRpc, inputs: unknown[]): Codec[] {
|
|
390
|
-
const count = inputs.length;
|
|
391
|
-
const reqCount = def.params.filter(({ isOptional }) => !isOptional).length;
|
|
392
|
-
|
|
393
|
-
if (count < reqCount || count > def.params.length) {
|
|
394
|
-
throw new Error(`Expected ${def.params.length} parameters${reqCount === def.params.length ? '' : ` (${def.params.length - reqCount} optional)`}, ${count} found instead`);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
const params = new Array<Codec>(count);
|
|
398
|
-
|
|
399
|
-
for (let i = 0; i < count; i++) {
|
|
400
|
-
params[i] = registry.createTypeUnsafe(def.params[i].type, [inputs[i]], { blockHash });
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
return params;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
private _formatOutput (registry: Registry, blockHash: Uint8Array | string | null | undefined, method: string, rpc: DefinitionRpc, params: Codec[], result?: unknown): Codec | Codec[] {
|
|
407
|
-
if (rpc.type === 'StorageData') {
|
|
408
|
-
const key = params[0] as StorageKey;
|
|
409
|
-
|
|
410
|
-
return this._formatStorageData(registry, blockHash, key, result as string);
|
|
411
|
-
} else if (rpc.type === 'StorageChangeSet') {
|
|
412
|
-
const keys = params[0] as Vec<StorageKey>;
|
|
413
|
-
|
|
414
|
-
return keys
|
|
415
|
-
? this._formatStorageSet(registry, (result as StorageChangeSetJSON).block, keys, (result as StorageChangeSetJSON).changes)
|
|
416
|
-
: registry.createType('StorageChangeSet', result);
|
|
417
|
-
} else if (rpc.type === 'Vec<StorageChangeSet>') {
|
|
418
|
-
const jsonSet = (result as StorageChangeSetJSON[]);
|
|
419
|
-
const count = jsonSet.length;
|
|
420
|
-
const mapped = new Array<[Hash, Codec[]]>(count);
|
|
421
|
-
|
|
422
|
-
for (let i = 0; i < count; i++) {
|
|
423
|
-
const { block, changes } = jsonSet[i];
|
|
424
|
-
|
|
425
|
-
mapped[i] = [
|
|
426
|
-
registry.createType('BlockHash', block),
|
|
427
|
-
this._formatStorageSet(registry, block, params[0] as Vec<StorageKey>, changes)
|
|
428
|
-
];
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// we only query at a specific block, not a range - flatten
|
|
432
|
-
return method === 'queryStorageAt'
|
|
433
|
-
? mapped[0][1]
|
|
434
|
-
: mapped as unknown as Codec[];
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return registry.createTypeUnsafe(rpc.type, [result], { blockHash });
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
private _formatStorageData (registry: Registry, blockHash: Uint8Array | string | null | undefined, key: StorageKey, value: string | null): Codec {
|
|
441
|
-
const isEmpty = isNull(value);
|
|
442
|
-
|
|
443
|
-
// we convert to Uint8Array since it maps to the raw encoding, all
|
|
444
|
-
// data will be correctly encoded (incl. numbers, excl. :code)
|
|
445
|
-
const input = isEmpty
|
|
446
|
-
? null
|
|
447
|
-
: isTreatAsHex(key)
|
|
448
|
-
? value
|
|
449
|
-
: u8aToU8a(value);
|
|
450
|
-
|
|
451
|
-
return this._newType(registry, blockHash, key, input, isEmpty);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
private _formatStorageSet (registry: Registry, blockHash: string, keys: Vec<StorageKey>, changes: [string, string | null][]): Codec[] {
|
|
455
|
-
// For StorageChangeSet, the changes has the [key, value] mappings
|
|
456
|
-
const count = keys.length;
|
|
457
|
-
const withCache = count !== 1;
|
|
458
|
-
const values = new Array<Codec>(count);
|
|
459
|
-
|
|
460
|
-
// multiple return values (via state.storage subscription), decode the
|
|
461
|
-
// values one at a time, all based on the supplied query types
|
|
462
|
-
for (let i = 0; i < count; i++) {
|
|
463
|
-
values[i] = this._formatStorageSetEntry(registry, blockHash, keys[i], changes, withCache, i);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
return values;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
private _formatStorageSetEntry (registry: Registry, blockHash: string, key: StorageKey, changes: [string, string | null][], withCache: boolean, entryIndex: number): Codec {
|
|
470
|
-
const hexKey = key.toHex();
|
|
471
|
-
const found = changes.find(([key]) => key === hexKey);
|
|
472
|
-
const isNotFound = isUndefined(found);
|
|
473
|
-
|
|
474
|
-
// if we don't find the value, this is our fallback
|
|
475
|
-
// - in the case of an array of values, fill the hole from the cache
|
|
476
|
-
// - if a single result value, don't fill - it is not an update hole
|
|
477
|
-
// - fallback to an empty option in all cases
|
|
478
|
-
if (isNotFound && withCache) {
|
|
479
|
-
const cached = this.#storageCache.get(hexKey) as Codec | undefined;
|
|
480
|
-
|
|
481
|
-
if (cached) {
|
|
482
|
-
this.#storageCacheHits++;
|
|
483
|
-
|
|
484
|
-
return cached;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
const value = isNotFound
|
|
489
|
-
? null
|
|
490
|
-
: found[1];
|
|
491
|
-
const isEmpty = isNull(value);
|
|
492
|
-
const input = isEmpty || isTreatAsHex(key)
|
|
493
|
-
? value
|
|
494
|
-
: u8aToU8a(value);
|
|
495
|
-
const codec = this._newType(registry, blockHash, key, input, isEmpty, entryIndex);
|
|
496
|
-
|
|
497
|
-
this._setToCache(hexKey, codec);
|
|
498
|
-
|
|
499
|
-
return codec;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
private _setToCache (key: string, value: Codec): void {
|
|
503
|
-
this.#storageCache.set(key, value);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
private _newType (registry: Registry, blockHash: Uint8Array | string | null | undefined, key: StorageKey, input: string | Uint8Array | null, isEmpty: boolean, entryIndex = -1): Codec {
|
|
507
|
-
// single return value (via state.getStorage), decode the value based on the
|
|
508
|
-
// outputType that we have specified. Fallback to Raw on nothing
|
|
509
|
-
const type = key.meta ? registry.createLookupType(unwrapStorageSi(key.meta.type)) : (key.outputType || 'Raw');
|
|
510
|
-
const meta = key.meta || EMPTY_META;
|
|
511
|
-
const entryNum = entryIndex === -1
|
|
512
|
-
? ''
|
|
513
|
-
: ` entry ${entryIndex}:`;
|
|
514
|
-
|
|
515
|
-
try {
|
|
516
|
-
return registry.createTypeUnsafe(type, [
|
|
517
|
-
isEmpty
|
|
518
|
-
? meta.fallback
|
|
519
|
-
// For old-style Linkage, we add an empty linkage at the end
|
|
520
|
-
? type.includes('Linkage<')
|
|
521
|
-
? u8aConcat(hexToU8a(meta.fallback.toHex()), new Uint8Array(2))
|
|
522
|
-
: hexToU8a(meta.fallback.toHex())
|
|
523
|
-
: undefined
|
|
524
|
-
: meta.modifier.isOptional
|
|
525
|
-
? registry.createTypeUnsafe(type, [input], { blockHash, isPedantic: this.#isPedantic })
|
|
526
|
-
: input
|
|
527
|
-
], { blockHash, isFallback: isEmpty && !!meta.fallback, isOptional: meta.modifier.isOptional, isPedantic: this.#isPedantic && !meta.modifier.isOptional });
|
|
528
|
-
} catch (error) {
|
|
529
|
-
throw new Error(`Unable to decode storage ${key.section || 'unknown'}.${key.method || 'unknown'}:${entryNum}: ${(error as Error).message}`);
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
package/build-deno/index.ts
DELETED
package/build-deno/mod.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { packageInfo as providerInfo } from 'https://deno.land/x/pezkuwi/rpc-provider/packageInfo.ts';
|
|
4
|
-
import { packageInfo as typesInfo } from 'https://deno.land/x/pezkuwi/types/packageInfo.ts';
|
|
5
|
-
import { detectPackage } from 'https://deno.land/x/pezkuwi/util/mod.ts';
|
|
6
|
-
|
|
7
|
-
import { packageInfo } from './packageInfo.ts';
|
|
8
|
-
|
|
9
|
-
detectPackage(packageInfo, null, [providerInfo, typesInfo]);
|
package/build-deno/types/base.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Observable } from 'https://esm.sh/rxjs@7.8.1';
|
|
3
|
-
import type { ProviderInterface } from 'https://deno.land/x/pezkuwi/rpc-provider/types.ts';
|
|
4
|
-
import type { AnyFunction, Codec, DefinitionRpc } from 'https://deno.land/x/pezkuwi/types/types/index.ts';
|
|
5
|
-
|
|
6
|
-
export interface RpcInterfaceMethod {
|
|
7
|
-
<T extends Codec> (...params: unknown[]): Observable<T>;
|
|
8
|
-
raw (...params: unknown[]): Observable<unknown>;
|
|
9
|
-
meta: DefinitionRpc;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type AugmentedRpc<F extends AnyFunction> = F & {
|
|
13
|
-
raw: <T> (...params: Parameters<F>) => Observable<T>;
|
|
14
|
-
meta: DefinitionRpc;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/** Stats from the rpc-core layer, including the provider stats */
|
|
18
|
-
export interface RpcCoreStats extends NonNullable<ProviderInterface['stats']> {
|
|
19
|
-
/** Internal stats for the rpc-core layer */
|
|
20
|
-
core: {
|
|
21
|
-
/** The number of values retrieved from the core cache */
|
|
22
|
-
cacheHits: number;
|
|
23
|
-
/** The number of entries in the core cache */
|
|
24
|
-
cacheSize: number;
|
|
25
|
-
}
|
|
26
|
-
}
|
package/build-deno/util/drr.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Observable } from 'https://esm.sh/rxjs@7.8.1';
|
|
3
|
-
|
|
4
|
-
import { catchError, distinctUntilChanged, publishReplay, refCount, tap } from 'https://esm.sh/rxjs@7.8.1';
|
|
5
|
-
|
|
6
|
-
import { stringify } from 'https://deno.land/x/pezkuwi/util/mod.ts';
|
|
7
|
-
|
|
8
|
-
import { refCountDelay } from './refCountDelay.ts';
|
|
9
|
-
|
|
10
|
-
export type DrrResult = <T> (source$: Observable<T>) => Observable<T>;
|
|
11
|
-
|
|
12
|
-
interface Options {
|
|
13
|
-
delay?: number;
|
|
14
|
-
skipChange?: boolean;
|
|
15
|
-
skipTimeout?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function CMP (a: unknown, b: unknown): boolean {
|
|
19
|
-
return stringify({ t: a }) === stringify({ t: b });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function ERR (error: Error): Observable<never> {
|
|
23
|
-
throw error;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function NOOP (): void {
|
|
27
|
-
// empty
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Shorthand for distinctUntilChanged(), publishReplay(1) and refCount().
|
|
32
|
-
*
|
|
33
|
-
* @ignore
|
|
34
|
-
* @internal
|
|
35
|
-
*/
|
|
36
|
-
export function drr ({ delay, skipChange = false, skipTimeout = false }: Options = {}): DrrResult {
|
|
37
|
-
return <T> (source$: Observable<T>): Observable<T> =>
|
|
38
|
-
source$.pipe(
|
|
39
|
-
catchError(ERR),
|
|
40
|
-
skipChange
|
|
41
|
-
? tap(NOOP)
|
|
42
|
-
: distinctUntilChanged<T>(CMP),
|
|
43
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
44
|
-
publishReplay(1),
|
|
45
|
-
skipTimeout
|
|
46
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
47
|
-
? refCount()
|
|
48
|
-
: refCountDelay(delay)
|
|
49
|
-
);
|
|
50
|
-
}
|
package/build-deno/util/index.ts
DELETED
package/build-deno/util/memo.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Observer, TeardownLogic } from 'https://esm.sh/rxjs@7.8.1';
|
|
3
|
-
import type { Memoized } from 'https://deno.land/x/pezkuwi/util/types.ts';
|
|
4
|
-
|
|
5
|
-
import { Observable } from 'https://esm.sh/rxjs@7.8.1';
|
|
6
|
-
|
|
7
|
-
import { memoize } from 'https://deno.land/x/pezkuwi/util/mod.ts';
|
|
8
|
-
|
|
9
|
-
import { drr } from './drr.ts';
|
|
10
|
-
|
|
11
|
-
type ObsFn <T> = (...params: unknown[]) => Observable<T>;
|
|
12
|
-
|
|
13
|
-
/** @internal */
|
|
14
|
-
export function memo <T> (instanceId: string, inner: Function): Memoized<ObsFn<T>> {
|
|
15
|
-
const options = { getInstanceId: () => instanceId };
|
|
16
|
-
const cached = memoize(
|
|
17
|
-
(...params: unknown[]): Observable<T> =>
|
|
18
|
-
new Observable((observer: Observer<T>): TeardownLogic => {
|
|
19
|
-
const subscription = (inner as ObsFn<T>)(...params).subscribe(observer);
|
|
20
|
-
|
|
21
|
-
return (): void => {
|
|
22
|
-
cached.unmemoize(...params);
|
|
23
|
-
subscription.unsubscribe();
|
|
24
|
-
};
|
|
25
|
-
}).pipe(drr()),
|
|
26
|
-
options
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
return cached;
|
|
30
|
-
}
|