UNPKG

@swingby-protocol/sdk

Version:

An implementation of the Swingby standard development kit for NodeJS and JavaScript.

111 lines (97 loc) 3.37 kB
import type { PartialDeep } from 'type-fest'; import { SkybridgeBridge, SKYBRIDGE_BRIDGES } from '../bridges'; import { SkybridgePeer } from '../common-params'; import { FIXED_NODE_ENDPOINT } from '../endpoints'; import { fetcher } from '../fetch'; import type { SkybridgeMode } from '../modes'; import { getNetworkDetails } from './getNetworkDetails'; import type { SkybridgeContext } from './SkybridgeContext'; const randomInt = (min: number, max: number) => Math.round(Math.random() * (max - min)) + min; export const buildContext = async <M extends SkybridgeMode>({ mode, servers, affiliateApi, }: { mode: M; } & PartialDeep<Omit<SkybridgeContext<M>, 'mode'>>): Promise<SkybridgeContext<M>> => { const results = await Promise.all( SKYBRIDGE_BRIDGES.map((bridge) => getNetworkDetails({ mode, bridge })), ); const getRandomIndexer = async ({ bridge }: { bridge: SkybridgeBridge }) => { const index = SKYBRIDGE_BRIDGES.findIndex((it) => it === bridge); if (results[index].indexerNodes.length <= 1) { return results[index].indexerNodes[0] ?? null; } for (const indexer of results[index].indexerNodes) { try { const result = await fetcher<{ blockbook: { inSync: boolean } }>(`${indexer}/api/v2`); if (result.blockbook.inSync) { return indexer; } } catch (e) {} } return null; }; const getRandomSwapNode = async ({ bridge, mode, }: { bridge: SkybridgeBridge; mode: SkybridgeMode; }) => { const fallbackEndpoint = FIXED_NODE_ENDPOINT[bridge][mode][0]; // Memo: Currently Ropsten endpoint is available for node-1 only if (mode === 'test') { const nodes = FIXED_NODE_ENDPOINT[bridge][mode]; const node = nodes[randomInt(0, nodes.length - 1)]; return node; } const index = SKYBRIDGE_BRIDGES.findIndex((it) => it === bridge); try { const swapNodes = (() => { const sorted = [...results[index].swapNodes].filter((it) => { try { return ( typeof it.restUri === 'string' && new URL(it.restUri).protocol === 'https:' && it.restUri !== 'https://' ); } catch (e) { return false; } }); return sorted; })(); const endpoint = (swapNodes[randomInt(0, swapNodes.length - 1)] || null)?.restUri; try { const url = `${endpoint}/api/v1/peers`; const result = await fetcher<SkybridgePeer[]>(url); if (result.length > 0) { return endpoint; } else { return fallbackEndpoint; } } catch (error) { return fallbackEndpoint; } } catch (e) { return fallbackEndpoint; } }; return { mode, affiliateApi: affiliateApi ?? 'https://affiliate.swingby.network', servers: { swapNode: { btc_erc: servers?.swapNode?.btc_erc ?? (await getRandomSwapNode({ bridge: 'btc_erc', mode })), btc_bep20: servers?.swapNode?.btc_bep20 ?? (await getRandomSwapNode({ bridge: 'btc_bep20', mode })), }, indexer: { btc_erc: servers?.indexer?.btc_erc ?? (await getRandomIndexer({ bridge: 'btc_erc' })), btc_bep20: servers?.indexer?.btc_bep20 ?? (await getRandomIndexer({ bridge: 'btc_bep20' })), }, }, }; };