@substrate/api-sidecar
Version:
REST service that makes it easy to interact with blockchain nodes built using Substrate's FRAME framework.
133 lines • 5.86 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiPromiseRegistry = void 0;
/* eslint-disable @typescript-eslint/no-var-requires */
const api_1 = require("@polkadot/api");
const rpc_provider_1 = require("@polkadot/rpc-provider");
const Log_1 = require("../logging/Log");
const typesBundle_1 = __importDefault(require("../override-types/typesBundle"));
const SidecarConfig_1 = require("../SidecarConfig");
const MultiKeyBiMap_1 = require("../util/MultiKeyBiMap");
class ApiPromiseRegistry {
static setAssetHubInfo(info) {
this.assetHubInfo.isAssetHub = info.isAssetHub;
this.assetHubInfo.isAssetHubMigrated = info.isAssetHubMigrated;
}
/**
* Get the ApiPromise instance for the given spec name.
* @param specName The spec name to get the ApiPromise instance for.
* @returns The ApiPromise instance for the given spec name.
*/
static async initApi(url, type) {
const { logger } = Log_1.Log;
logger.info(`Initializing API for ${url}`);
// TODO: for now use instance by URL as a staging check to make sure we don't need to recreate an API instance
if (!this._instancesByUrl.has(url)) {
const { config } = SidecarConfig_1.SidecarConfig;
const { TYPES_BUNDLE, TYPES_SPEC, TYPES_CHAIN, TYPES, CACHE_CAPACITY } = config.SUBSTRATE;
// Instantiate new API Promise instance
const api = await api_1.ApiPromise.create({
provider: url.startsWith('http')
? new rpc_provider_1.HttpProvider(url, undefined, CACHE_CAPACITY || 0)
: new rpc_provider_1.WsProvider(url, undefined, undefined, undefined, CACHE_CAPACITY || 0),
// only use extra types if the url is the same as the one in the config
...(config.SUBSTRATE.URL === url
? {
typesBundle: TYPES_BUNDLE
? require(TYPES_BUNDLE)
: typesBundle_1.default,
typesChain: TYPES_CHAIN ? require(TYPES_CHAIN) : undefined,
typesSpec: TYPES_SPEC ? require(TYPES_SPEC) : undefined,
types: TYPES ? require(TYPES) : undefined,
}
: {}),
});
const { specName } = await api.rpc.state.getRuntimeVersion();
if (!this.specNameToTypeMap.getByKey(specName.toString())) {
if (type) {
this.specNameToTypeMap.set(specName.toString(), type);
}
}
// TODO: use a generic store for APis and use a unique Id to reference URLs and specNames
if (this._instancesBySpecName.has(specName.toString())) {
const existingInstances = this._instancesBySpecName.get(specName.toString());
this._instancesBySpecName.set(specName.toString(), [...existingInstances, api]);
}
else {
this._instancesBySpecName.set(specName.toString(), [api]);
}
this._instancesByUrl.set(url, api);
logger.info(`API initialized for ${url} with specName ${specName.toString()}`);
}
else {
const api = this._instancesByUrl.get(url);
// make sure we have stored the type for the SUBSTRATE_URL option
if (api && type) {
const { specName } = await api.rpc.state.getRuntimeVersion();
if (!this.specNameToTypeMap.getByKey(specName.toString())) {
if (type) {
this.specNameToTypeMap.set(specName.toString(), type);
}
}
}
}
return this._instancesByUrl.get(url);
}
static getApi(specName) {
const api = this._instancesBySpecName.get(specName);
if (!api) {
throw new Error(`API not found for specName: ${specName}`);
}
// TODO: create logic to return the correct API instance based on workload/necessity
return api[0];
}
static getApiByUrl(url) {
return this._instancesByUrl.get(url);
}
static getTypeBySpecName(specName) {
return this.specNameToTypeMap.getByKey(specName);
}
static getSpecNameByType(type) {
return this.specNameToTypeMap.getByValue(type);
}
static getApiByType(type) {
const specNames = this.specNameToTypeMap.getByValue(type);
if (!specNames) {
return [];
}
const specNameApis = [];
for (const specName of specNames) {
const api = this.getApi(specName);
if (api) {
specNameApis.push({ specName, api });
}
}
return specNameApis;
}
static getAllAvailableSpecNames() {
return Array.from(this._instancesBySpecName.keys());
}
static clear() {
this._instancesBySpecName.clear();
this._instancesByUrl.clear();
this.specNameToTypeMap = new MultiKeyBiMap_1.MultiKeyBiMap();
const { logger } = Log_1.Log;
logger.info('Cleared API registry');
}
}
exports.ApiPromiseRegistry = ApiPromiseRegistry;
// SpecName to ApiPromise instances
ApiPromiseRegistry._instancesBySpecName = new Map();
// SpecName to Type map
ApiPromiseRegistry.specNameToTypeMap = new MultiKeyBiMap_1.MultiKeyBiMap();
// RPC URL to ApiPromise instance
ApiPromiseRegistry._instancesByUrl = new Map();
// Asset hub info, will default to static unless its connected.
ApiPromiseRegistry.assetHubInfo = {
isAssetHub: false,
isAssetHubMigrated: false,
};
//# sourceMappingURL=index.js.map