PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@polkadot/rpc-core/cjs

Просмотр файла: bundle.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RpcCore = exports.packageInfo = void 0;
const tslib_1 = require("tslib");
const rxjs_1 = require("rxjs");
const rpc_provider_1 = require("@polkadot/rpc-provider");
const types_1 = require("@polkadot/types");
const util_1 = require("@polkadot/util");
const index_js_1 = require("./util/index.js");
var packageInfo_js_1 = require("./packageInfo.js");
Object.defineProperty(exports, "packageInfo", { enumerable: true, get: function () { return packageInfo_js_1.packageInfo; } });
tslib_1.__exportStar(require("./util/index.js"), exports);
const l = (0, util_1.logger)('rpc-core');
const EMPTY_META = {
    fallback: undefined,
    modifier: { isOptional: true },
    type: {
        asMap: { linked: { isTrue: false } },
        isMap: false
    }
};
/** @internal */
function logErrorMessage(method, { noErrorLog, params, type }, error) {
    if (noErrorLog) {
        return;
    }
    l.error(`${method}(${params.map(({ isOptional, name, type }) => `${name}${isOptional ? '?' : ''}: ${type}`).join(', ')}): ${type}:: ${error.message}`);
}
function isTreatAsHex(key) {
    // :code is problematic - it does not have the length attached, which is
    // unlike all other storage entries where it is indeed properly encoded
    return ['0x3a636f6465'].includes(key.toHex());
}
/**
 * @name Rpc
 * @summary The API may use a HTTP or WebSockets provider.
 * @description It allows for querying a Polkadot Client Node.
 * WebSockets provider is recommended since HTTP provider only supports basic querying.
 *
 * ```mermaid
 * graph LR;
 *   A[Api] --> |WebSockets| B[WsProvider];
 *   B --> |endpoint| C[ws://127.0.0.1:9944]
 * ```
 *
 * @example
 * <BR>
 *
 * ```javascript
 * import Rpc from '@polkadot/rpc-core';
 * import { WsProvider } from '@polkadot/rpc-provider/ws';
 *
 * const provider = new WsProvider('ws://127.0.0.1:9944');
 * const rpc = new Rpc(provider);
 * ```
 */
class RpcCore {
    __internal__instanceId;
    __internal__isPedantic;
    __internal__registryDefault;
    __internal__storageCache;
    __internal__storageCacheHits = 0;
    __internal__getBlockRegistry;
    __internal__getBlockHash;
    mapping = new Map();
    provider;
    sections = [];
    /**
     * @constructor
     * 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, registry, { isPedantic = true, provider, userRpc = {} }) {
        if (!provider || !(0, util_1.isFunction)(provider.send)) {
            throw new Error('Expected Provider to API create');
        }
        this.__internal__instanceId = instanceId;
        this.__internal__isPedantic = isPedantic;
        this.__internal__registryDefault = registry;
        this.provider = provider;
        const sectionNames = Object.keys(types_1.rpcDefinitions);
        // these are the base keys (i.e. part of jsonrpc)
        this.sections.push(...sectionNames);
        this.__internal__storageCache = new rpc_provider_1.LRUCache(rpc_provider_1.DEFAULT_CAPACITY);
        // decorate all interfaces, defined and user on this instance
        this.addUserInterfaces(userRpc);
    }
    /**
     * @description Returns the connected status of a provider
     */
    get isConnected() {
        return this.provider.isConnected;
    }
    /**
     * @description Manually connect from the attached provider
     */
    connect() {
        return this.provider.connect();
    }
    /**
     * @description Manually disconnect from the attached provider
     */
    async disconnect() {
        await this.__internal__storageCache.clearInterval();
        return this.provider.disconnect();
    }
    /**
     * @description Returns the underlying core stats, including those from teh provider
     */
    get stats() {
        const stats = this.provider.stats;
        return stats
            ? {
                ...stats,
                core: {
                    cacheHits: this.__internal__storageCacheHits,
                    cacheSize: this.__internal__storageCache.length
                }
            }
            : undefined;
    }
    /**
     * @description Sets a registry swap (typically from Api)
     */
    setRegistrySwap(registrySwap) {
        this.__internal__getBlockRegistry = (0, util_1.memoize)(registrySwap, {
            getInstanceId: () => this.__internal__instanceId
        });
    }
    /**
     * @description Sets a function to resolve block hash from block number
     */
    setResolveBlockHash(resolveBlockHash) {
        this.__internal__getBlockHash = (0, util_1.memoize)(resolveBlockHash, {
            getInstanceId: () => this.__internal__instanceId
        });
    }
    addUserInterfaces(userRpc) {
        // add any extra user-defined sections
        this.sections.push(...Object.keys(userRpc).filter((k) => !this.sections.includes(k)));
        for (let s = 0, scount = this.sections.length; s < scount; s++) {
            const section = this.sections[s];
            const defs = (0, util_1.objectSpread)({}, types_1.rpcDefinitions[section], userRpc[section]);
            const methods = Object.keys(defs);
            for (let m = 0, mcount = methods.length; m < mcount; m++) {
                const method = methods[m];
                const def = defs[method];
                const jsonrpc = def.endpoint || `${section}_${method}`;
                if (!this.mapping.has(jsonrpc)) {
                    const isSubscription = !!def.pubsub;
                    if (!this[section]) {
                        this[section] = {};
                    }
                    this.mapping.set(jsonrpc, (0, util_1.objectSpread)({}, def, { isSubscription, jsonrpc, method, section }));
                    (0, util_1.lazyMethod)(this[section], method, () => isSubscription
                        ? this._createMethodSubscribe(section, method, def)
                        : this._createMethodSend(section, method, def));
                }
            }
        }
    }
    _memomize(creator, def) {
        const memoOpts = { getInstanceId: () => this.__internal__instanceId };
        const memoized = (0, util_1.memoize)(creator(true), memoOpts);
        memoized.raw = (0, util_1.memoize)(creator(false), memoOpts);
        memoized.meta = def;
        return memoized;
    }
    _formatResult(isScale, registry, blockHash, method, def, params, result) {
        return isScale
            ? this._formatOutput(registry, blockHash, method, def, params, result)
            : result;
    }
    _createMethodSend(section, method, def) {
        const rpcName = def.endpoint || `${section}_${method}`;
        const hashIndex = def.params.findIndex(({ isHistoric }) => isHistoric);
        let memoized = null;
        // execute the RPC call, doing a registry swap for historic as applicable
        const callWithRegistry = async (isScale, values) => {
            const blockId = hashIndex === -1
                ? null
                : values[hashIndex];
            const blockHash = blockId && def.params[hashIndex].type === 'BlockNumber'
                ? await this.__internal__getBlockHash?.(blockId)
                : blockId;
            const { registry } = isScale && blockHash && this.__internal__getBlockRegistry
                ? await this.__internal__getBlockRegistry((0, util_1.u8aToU8a)(blockHash))
                : { registry: this.__internal__registryDefault };
            const params = this._formatParams(registry, null, def, values);
            // only cache .at(<blockHash>) queries, e.g. where valid blockHash was supplied
            const result = await this.provider.send(rpcName, params.map((p) => p.toJSON()), !!blockHash);
            return this._formatResult(isScale, registry, blockHash, method, def, params, result);
        };
        const creator = (isScale) => (...values) => {
            const isDelayed = isScale && hashIndex !== -1 && !!values[hashIndex];
            return new rxjs_1.Observable((observer) => {
                callWithRegistry(isScale, values)
                    .then((value) => {
                    observer.next(value);
                    observer.complete();
                })
                    .catch((error) => {
                    logErrorMessage(method, def, error);
                    observer.error(error);
                    observer.complete();
                });
                return () => {
                    // delete old results from cache
                    if (isScale) {
                        memoized?.unmemoize(...values);
                    }
                    else {
                        memoized?.raw.unmemoize(...values);
                    }
                };
            }).pipe(
            // eslint-disable-next-line deprecation/deprecation
            (0, rxjs_1.publishReplay)(1), // create a Replay(1)
            isDelayed
                ? (0, index_js_1.refCountDelay)() // Unsubscribe after delay
                // eslint-disable-next-line deprecation/deprecation
                : (0, rxjs_1.refCount)());
        };
        memoized = this._memomize(creator, def);
        return memoized;
    }
    // create a subscriptor, it subscribes once and resolves with the id as subscribe
    _createSubscriber({ paramsJson, subName, subType, update }, errorHandler) {
        return new Promise((resolve, reject) => {
            this.provider
                .subscribe(subType, subName, paramsJson, update)
                .then(resolve)
                .catch((error) => {
                errorHandler(error);
                reject(error);
            });
        });
    }
    _createMethodSubscribe(section, method, def) {
        const [updateType, subMethod, unsubMethod] = def.pubsub;
        const subName = `${section}_${subMethod}`;
        const unsubName = `${section}_${unsubMethod}`;
        const subType = `${section}_${updateType}`;
        let memoized = null;
        const creator = (isScale) => (...values) => {
            return new rxjs_1.Observable((observer) => {
                // Have at least an empty promise, as used in the unsubscribe
                let subscriptionPromise = Promise.resolve(null);
                const registry = this.__internal__registryDefault;
                const errorHandler = (error) => {
                    logErrorMessage(method, def, error);
                    observer.error(error);
                };
                try {
                    const params = this._formatParams(registry, null, def, values);
                    const update = (error, result) => {
                        if (error) {
                            logErrorMessage(method, def, error);
                            return;
                        }
                        try {
                            observer.next(this._formatResult(isScale, registry, null, method, def, params, result));
                        }
                        catch (error) {
                            observer.error(error);
                        }
                    };
                    subscriptionPromise = this._createSubscriber({ paramsJson: params.map((p) => p.toJSON()), subName, subType, update }, errorHandler);
                }
                catch (error) {
                    errorHandler(error);
                }
                // Teardown logic
                return () => {
                    // Delete from cache, so old results don't hang around
                    if (isScale) {
                        memoized?.unmemoize(...values);
                    }
                    else {
                        memoized?.raw.unmemoize(...values);
                    }
                    // Unsubscribe from provider
                    subscriptionPromise
                        .then((subscriptionId) => (0, util_1.isNull)(subscriptionId)
                        ? Promise.resolve(false)
                        : this.provider.unsubscribe(subType, unsubName, subscriptionId))
                        .catch((error) => logErrorMessage(method, def, error));
                };
            }).pipe((0, index_js_1.drr)());
        };
        memoized = this._memomize(creator, def);
        return memoized;
    }
    _formatParams(registry, blockHash, def, inputs) {
        const count = inputs.length;
        const reqCount = def.params.filter(({ isOptional }) => !isOptional).length;
        if (count < reqCount || count > def.params.length) {
            throw new Error(`Expected ${def.params.length} parameters${reqCount === def.params.length ? '' : ` (${def.params.length - reqCount} optional)`}, ${count} found instead`);
        }
        const params = new Array(count);
        for (let i = 0; i < count; i++) {
            params[i] = registry.createTypeUnsafe(def.params[i].type, [inputs[i]], { blockHash });
        }
        return params;
    }
    _formatOutput(registry, blockHash, method, rpc, params, result) {
        if (rpc.type === 'StorageData') {
            const key = params[0];
            return this._formatStorageData(registry, blockHash, key, result);
        }
        else if (rpc.type === 'StorageChangeSet') {
            const keys = params[0];
            return keys
                ? this._formatStorageSet(registry, result.block, keys, result.changes)
                : registry.createType('StorageChangeSet', result);
        }
        else if (rpc.type === 'Vec<StorageChangeSet>') {
            const jsonSet = result;
            const count = jsonSet.length;
            const mapped = new Array(count);
            for (let i = 0; i < count; i++) {
                const { block, changes } = jsonSet[i];
                mapped[i] = [
                    registry.createType('BlockHash', block),
                    this._formatStorageSet(registry, block, params[0], changes)
                ];
            }
            // we only query at a specific block, not a range - flatten
            return method === 'queryStorageAt'
                ? mapped[0][1]
                : mapped;
        }
        return registry.createTypeUnsafe(rpc.type, [result], { blockHash });
    }
    _formatStorageData(registry, blockHash, key, value) {
        const isEmpty = (0, util_1.isNull)(value);
        // we convert to Uint8Array since it maps to the raw encoding, all
        // data will be correctly encoded (incl. numbers, excl. :code)
        const input = isEmpty
            ? null
            : isTreatAsHex(key)
                ? value
                : (0, util_1.u8aToU8a)(value);
        return this._newType(registry, blockHash, key, input, isEmpty);
    }
    _formatStorageSet(registry, blockHash, keys, changes) {
        // For StorageChangeSet, the changes has the [key, value] mappings
        const count = keys.length;
        const withCache = count !== 1;
        const values = new Array(count);
        // multiple return values (via state.storage subscription), decode the
        // values one at a time, all based on the supplied query types
        for (let i = 0; i < count; i++) {
            values[i] = this._formatStorageSetEntry(registry, blockHash, keys[i], changes, withCache, i);
        }
        return values;
    }
    _formatStorageSetEntry(registry, blockHash, key, changes, withCache, entryIndex) {
        const hexKey = key.toHex();
        const found = changes.find(([key]) => key === hexKey);
        const isNotFound = (0, util_1.isUndefined)(found);
        // if we don't find the value, this is our fallback
        //   - in the case of an array of values, fill the hole from the cache
        //   - if a single result value, don't fill - it is not an update hole
        //   - fallback to an empty option in all cases
        if (isNotFound && withCache) {
            const cached = this.__internal__storageCache.get(hexKey);
            if (cached) {
                this.__internal__storageCacheHits++;
                return cached;
            }
        }
        const value = isNotFound
            ? null
            : found[1];
        const isEmpty = (0, util_1.isNull)(value);
        const input = isEmpty || isTreatAsHex(key)
            ? value
            : (0, util_1.u8aToU8a)(value);
        const codec = this._newType(registry, blockHash, key, input, isEmpty, entryIndex);
        this._setToCache(hexKey, codec);
        return codec;
    }
    _setToCache(key, value) {
        this.__internal__storageCache.set(key, value);
    }
    _newType(registry, blockHash, key, input, isEmpty, entryIndex = -1) {
        // single return value (via state.getStorage), decode the value based on the
        // outputType that we have specified. Fallback to Raw on nothing
        const type = key.outputType || 'Raw';
        const meta = key.meta || EMPTY_META;
        const entryNum = entryIndex === -1
            ? ''
            : ` entry ${entryIndex}:`;
        try {
            return registry.createTypeUnsafe(type, [
                isEmpty
                    ? meta.fallback
                        // For old-style Linkage, we add an empty linkage at the end
                        ? type.includes('Linkage<')
                            ? (0, util_1.u8aConcat)((0, util_1.hexToU8a)(meta.fallback.toHex()), new Uint8Array(2))
                            : (0, util_1.hexToU8a)(meta.fallback.toHex())
                        : undefined
                    : meta.modifier.isOptional
                        ? registry.createTypeUnsafe(type, [input], { blockHash, isPedantic: this.__internal__isPedantic })
                        : input
            ], { blockHash, isFallback: isEmpty && !!meta.fallback, isOptional: meta.modifier.isOptional, isPedantic: this.__internal__isPedantic && !meta.modifier.isOptional });
        }
        catch (error) {
            throw new Error(`Unable to decode storage ${key.section || 'unknown'}.${key.method || 'unknown'}:${entryNum}: ${error.message}`);
        }
    }
}
exports.RpcCore = RpcCore;

Выполнить команду


Для локальной разработки. Не используйте в интернете!