Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions packages/extension-polkagate/src/util/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,21 +167,8 @@ export function extractBaseUrl (url: string | undefined) {
export async function fastestConnection (endpoints: DropdownOption[]): Promise<FastestConnectionType> {
try {
const urls = endpoints.map(({ value }) => ({ value: value as string }));
const { api, connections } = await fastestEndpoint(urls);

// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const selectedEndpoint = api.registry.knownTypes.provider.endpoint as string;
const connectionsToDisconnect = connections.filter(({ wsProvider }) => wsProvider.endpoint !== selectedEndpoint);

connectionsToDisconnect.forEach(({ wsProvider }) => {
wsProvider.disconnect().catch(console.error);
});

return {
api,
selectedEndpoint
};
return await fastestEndpoint(urls);
} catch (error) {
console.error('Unable to make an API connection!', error);

Expand Down Expand Up @@ -219,4 +206,4 @@ export const removeZeroBalanceRecords = (toBeSavedAssets: SavedAssets): SavedAss
});

return _toBeSavedAssets;
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { FETCHING_ASSETS_FUNCTION_NAMES } from '../../constants';
import { closeWebsockets, fastestEndpoint, getChainEndpoints, metadataFromApi, toGetNativeToken } from '../utils';
import { fastestEndpoint, getChainEndpoints, metadataFromApi, toGetNativeToken } from '../utils';
import { getAssets } from './getAssets.js';

/**
Expand All @@ -15,7 +15,7 @@ import { getAssets } from './getAssets.js';
*/
export async function getAssetOnAssetHub (addresses, assetsToBeFetched, chainName, userAddedEndpoints, port) {
const endpoints = getChainEndpoints(chainName, userAddedEndpoints);
const { api, connections } = await fastestEndpoint(endpoints);
const { api, provider } = await fastestEndpoint(endpoints);

const { metadata } = metadataFromApi(api);

Expand All @@ -42,5 +42,6 @@ export async function getAssetOnAssetHub (addresses, assetsToBeFetched, chainNam

console.info(chainName, ': account assets fetched.');
port.postMessage(JSON.stringify({ functionName: FETCHING_ASSETS_FUNCTION_NAMES.ASSET_HUB, results }));
closeWebsockets(connections);

provider.disconnect().catch(console.error);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getSubstrateAddress } from '../../address';
import { FETCHING_ASSETS_FUNCTION_NAMES } from '../../constants';
import { toTitleCase } from '../../string';
// eslint-disable-next-line import/extensions
import { balancifyAsset, closeWebsockets, fastestEndpoint, getChainEndpoints, metadataFromApi, toGetNativeToken } from '../utils';
import { balancifyAsset, fastestEndpoint, getChainEndpoints, metadataFromApi, toGetNativeToken } from '../utils';

/**
*
Expand All @@ -20,7 +20,7 @@ import { balancifyAsset, closeWebsockets, fastestEndpoint, getChainEndpoints, me
*/
export async function getAssetOnMultiAssetChain (assetsToBeFetched, addresses, chainName, userAddedEndpoints, port) {
const endpoints = getChainEndpoints(chainName, userAddedEndpoints);
const { api, connections } = await fastestEndpoint(endpoints);
const { api, provider } = await fastestEndpoint(endpoints);

const { metadata } = metadataFromApi(api);

Expand All @@ -37,7 +37,6 @@ export async function getAssetOnMultiAssetChain (assetsToBeFetched, addresses, c
return;
}

// @ts-ignore
const [formatted, assetIdRaw] = entry[0].toHuman() ?? [];

let assetId;
Expand All @@ -51,7 +50,6 @@ export async function getAssetOnMultiAssetChain (assetsToBeFetched, addresses, c

const storageKey = entry[0].toString();

// @ts-ignore
let maybeAssetInfo = assetsToBeFetched.find((_asset) => {
const currencyId = _asset?.extras?.['currencyIdScale'].replace('0x', '');

Expand Down Expand Up @@ -79,7 +77,6 @@ export async function getAssetOnMultiAssetChain (assetsToBeFetched, addresses, c
}

if (maybeAssetInfo) {
// @ts-ignore
const totalBalance = balance.free.add(balance.reserved);

const asset = {
Expand All @@ -97,7 +94,6 @@ export async function getAssetOnMultiAssetChain (assetsToBeFetched, addresses, c

const address = getSubstrateAddress(formatted);

// @ts-ignore
results[address]?.push(asset) ?? (results[address] = [asset]);
} else {
console.info(`NOTE: There is an asset on ${chainName} for ${formatted} which is not whitelisted. assetInfo`, storageKey, balance?.toHuman());
Expand All @@ -106,5 +102,6 @@ export async function getAssetOnMultiAssetChain (assetsToBeFetched, addresses, c

console.info(chainName, ': account assets fetched.');
port.postMessage(JSON.stringify({ functionName: FETCHING_ASSETS_FUNCTION_NAMES.MULTI_ASSET, results }));
closeWebsockets(connections);

provider.disconnect().catch(console.error);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { FETCHING_ASSETS_FUNCTION_NAMES, NATIVE_TOKEN_ASSET_ID, TEST_NETS } from '../../constants';
import { getPriceIdByChainName } from '../../misc';
import { balancify, closeWebsockets } from '../utils';
import { balancify } from '../utils';
import { getBalances } from './getBalances.js';

/**
Expand All @@ -16,9 +16,9 @@ export async function getAssetOnRelayChain (addresses, chainName, userAddedEndpo
const results = {};

try {
const { api, balanceInfo, connectionsToBeClosed } = await getBalances(chainName, addresses, userAddedEndpoints, port) ?? {};
const { api, balanceInfo, connectionToBeClosed } = await getBalances(chainName, addresses, userAddedEndpoints, port) ?? {};

if (!api || !balanceInfo || !connectionsToBeClosed) {
if (!api || !balanceInfo || !connectionToBeClosed) {
return;
}

Expand Down Expand Up @@ -46,7 +46,7 @@ export async function getAssetOnRelayChain (addresses, chainName, userAddedEndpo
}];
});

closeWebsockets(connectionsToBeClosed);
connectionToBeClosed.disconnect().catch(console.error);
} catch (error) {
console.error(`getAssetOnRelayChain: Error fetching balances for ${chainName}:`, error);
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { getStakingBalances } from './getStakingBalances';
*/
export async function getBalances (chainName, addresses, userAddedEndpoints, port) {
const chainEndpoints = getChainEndpoints(chainName, userAddedEndpoints);
const { api, connections } = await fastestEndpoint(chainEndpoints);
const { api, provider } = await fastestEndpoint(chainEndpoints);

if (api.isConnected && api.derive.balances) {
const { metadata } = metadataFromApi(api);
Expand Down Expand Up @@ -49,7 +49,7 @@ export async function getBalances (chainName, addresses, userAddedEndpoints, por
};
});

return { api, balanceInfo: await Promise.all(requests), connectionsToBeClosed: connections };
return { api, balanceInfo: await Promise.all(requests), connectionToBeClosed: provider };
}

return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { SUPPORTED_NFT_CHAINS } from '../../../fullscreen/nft/utils/constants';
import { getFormattedAddress } from '../../address';
import { closeWebsockets, fastestEndpoint, getChainEndpoints } from '../utils';
import { fastestEndpoint, getChainEndpoints } from '../utils';

const NFT_FUNCTION_NAME = 'getNFTs';

Expand Down Expand Up @@ -191,9 +191,9 @@ async function getNFTs (addresses) {
const formattedAddresses = addresses.map((address) => getFormattedAddress(address, undefined, prefix));
const endpoints = getChainEndpoints(name, undefined);

const { api, connections } = await fastestEndpoint(endpoints);
const { api, provider } = await fastestEndpoint(endpoints);

return ({ api, chainName, connections, formattedAddresses, originalAddresses: addresses });
return ({ api, chainName, formattedAddresses, originalAddresses: addresses, provider });
});

const apis = await Promise.all(apiPromises);
Expand Down Expand Up @@ -224,7 +224,9 @@ async function getNFTs (addresses) {
return itemsByAddress;
} finally {
// Ensure all websocket connections are closed
apis.forEach(({ connections }) => closeWebsockets(connections));
apis.forEach(({ provider }) => {
provider.disconnect().catch(console.error);
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { BN, BN_ZERO, bnMax, hexToString } from '@polkadot/util';

import getChainName from '../../getChainName';
import getPoolAccounts from '../../getPoolAccounts';
import { closeWebsockets, fastestEndpoint, getChainEndpoints } from '../utils';
import { fastestEndpoint, getChainEndpoints } from '../utils';

/**
* Get all information regarding a pool
Expand All @@ -31,7 +31,7 @@ export async function getPool (genesisHash, stakerAddress, id, port) {
const chainName = getChainName(genesisHash);
const endpoints = getChainEndpoints(chainName ?? '');

const { api, connections } = await fastestEndpoint(endpoints);
const { api, provider } = await fastestEndpoint(endpoints);

console.log(`getPool is called for ${stakerAddress} on chain ${chainName}`);
id && console.log('getPool is called to fetch the pool with poolId:', id);
Expand Down Expand Up @@ -133,5 +133,5 @@ export async function getPool (genesisHash, stakerAddress, id, port) {

port.postMessage(JSON.stringify({ functionName: 'getPool', results: JSON.stringify(poolInfo) }));

closeWebsockets(connections);
provider.disconnect().catch(console.error);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { hexToString } from '@polkadot/util';

import { KUSAMA_GENESIS_HASH, POLKADOT_GENESIS_HASH } from '../../constants';
import getChainName from '../../getChainName';
import { closeWebsockets, fastestEndpoint, getChainEndpoints } from '../utils';
import { fastestEndpoint, getChainEndpoints } from '../utils';

const BATCH_SIZE = 50;

Expand Down Expand Up @@ -72,7 +72,7 @@ export default async function getValidatorsInformation (genesisHash, port) {
const endpoints = getChainEndpoints(chainName);

try {
const { api, connections } = await fastestEndpoint(endpoints);
const { api, provider } = await fastestEndpoint(endpoints);

console.log('getting validators information on ' + chainName);

Expand All @@ -84,14 +84,14 @@ export default async function getValidatorsInformation (genesisHash, port) {

console.log('electedInfo, waitingInfo, currentEra fetched successfully');

// Close the initial connections to the relay chain
closeWebsockets(connections);
// Close the initial connection to the relay chain
provider.disconnect().catch(console.error);

// Start connect to the People chain endpoints in order to fetch identities
console.log('Connecting to People chain endpoints...');
const peopleChainName = getPeopleChainName(genesisHash);
const peopleEndpoints = getChainEndpoints(peopleChainName);
const { api: peopleApi, connections: peopleConnections } = await fastestEndpoint(peopleEndpoints);
const { api: peopleApi, provider: peopleWebSocket } = await fastestEndpoint(peopleEndpoints);

// Keep elected and waiting validators separate
const electedValidatorsInfo = electedInfo.info;
Expand Down Expand Up @@ -136,7 +136,7 @@ export default async function getValidatorsInformation (genesisHash, port) {
await processSubIdentities(peopleApi, waitingMayHaveSubId, waitingValidatorsInformation, waitingAccountSubInfo);
await processParentIdentities(peopleApi, waitingAccountSubInfo, waitingValidatorsInformation);

closeWebsockets(peopleConnections);
peopleWebSocket.disconnect().catch(console.error);

const results = {
eraIndex: Number(currentEra?.toString() || '0'),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,5 @@ export async function fastestApi (genesisHash) {
const chainName = getChainName(genesisHash);
const endpoints = getChainEndpoints(chainName ?? '');

const { api, connections } = await fastestEndpoint(endpoints);

return {
api,
connections
};
return await fastestEndpoint(endpoints);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,50 @@
import { ApiPromise, WsProvider } from '@polkadot/api';

/**
* @param {{ value: string; }[]} endpoints
* Connects to multiple endpoints and returns the fastest one.
* Automatically disconnects all other providers.
*
* @param {{ value: string }[]} endpoints
*/
export async function fastestEndpoint (endpoints) {
let connection;

const connections = endpoints.map(({ value }) => {
// Check if e.value matches the pattern 'wss://<any_number>'
// ignore due to its rate limits
if (/^wss:\/\/\d+$/.test(value) || (value).includes('onfinality') || value.startsWith('light')) {
return undefined;
}

const wsProvider = new WsProvider(value);

connection = ApiPromise.create({ provider: wsProvider });

return {
connection,
connectionEndpoint: value,
wsProvider
};
}).filter((i) => !!i);

const api = await Promise.any(connections.map(({ connection }) => connection));

// Find the matching connection that created this API
// @ts-ignore
const notConnectedEndpoint = connections.filter(({ connectionEndpoint }) => connectionEndpoint !== api?._options?.provider?.endpoint);
// @ts-ignore
const connectedEndpoint = connections.find(({ connectionEndpoint }) => connectionEndpoint === api?._options?.provider?.endpoint);

notConnectedEndpoint.forEach(({ wsProvider }) => {
wsProvider.disconnect().catch(() => null);
});

return {
api,
connections: connectedEndpoint ? [connectedEndpoint] : []
};
// Filter invalid endpoints
const validEndpoints = endpoints
.map(({ value }) => value)
.filter(
(value) =>
!/^wss:\/\/\d+$/.test(value) &&
!value.includes('onfinality') &&
!value.startsWith('light')
);

if (!validEndpoints.length) {
throw new Error('No valid endpoints provided');
}

// Create all providers
const providers = validEndpoints.map((value) => new WsProvider(value));

// Wrap each ApiPromise creation in an object, so we keep the link between api and provider
const apiPromises = providers.map((provider) =>
ApiPromise.create({ provider })
.then((api) => ({ api, provider })) // attach provider reference
.catch((error) => {
provider.disconnect().catch(() => null);
throw error;
})
);

// Get the fastest connection
const { api, provider } = await Promise.any(apiPromises);

// Disconnect all other providers (non-blocking)
Promise.all(
providers.map((p) =>
p === provider
? Promise.resolve()
: p.disconnect().catch(() => null)
)
).catch(() => null);

return { api, provider, selectedEndpoint: provider.endpoint };
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

export * from './balancify.js';
export * from './closeWebsockets.js';
export * from './fastestApi.js';
export * from './fastestEndpoint.js';
export * from './getChainEndpoints.js';
Expand Down
Loading