diff --git a/.changeset/silver-suns-deny.md b/.changeset/silver-suns-deny.md new file mode 100644 index 00000000..3e2fde0b --- /dev/null +++ b/.changeset/silver-suns-deny.md @@ -0,0 +1,5 @@ +--- +'@rosen-bridge/watcher': minor +--- + +Integrate Handshake watcher diff --git a/config/default.yaml b/config/default.yaml index 540d78b6..e81cc65f 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -87,6 +87,16 @@ firo: timeout: 10 # rpc request timeout (in seconds) # username: '' # rpc username for authentication required instances # password: '' # rpc password for authentication required instances +handshake: + type: 'rpc' # options: rpc + initial: + height: -1 # initial height of scanning + interval: 180 # scanning interval (in seconds) + rpc: + url: '' # rpc url + timeout: 10 # rpc request timeout (in seconds) + # username: '' # rpc username for authentication required instances + # password: '' # rpc password for authentication required instances ergo: network: 'Mainnet' # ergo network type. testnet or mainnet type: 'node' # ergo scanner type. options: node, explorer diff --git a/docker/custom-environment-variables.yaml b/docker/custom-environment-variables.yaml index 2847b00b..9c2283ca 100644 --- a/docker/custom-environment-variables.yaml +++ b/docker/custom-environment-variables.yaml @@ -34,4 +34,8 @@ firo: rpc: username: 'FIRO_RPC_USERNAME' password: 'FIRO_RPC_PASSWORD' +handshake: + rpc: + username: 'HANDSHAKE_RPC_USERNAME' + password: 'HANDSHAKE_RPC_PASSWORD' overrideLokiBasicAuth: 'OVERRIDE_LOKI_BASIC_AUTH' diff --git a/package-lock.json b/package-lock.json index f2d58611..fcc124c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,8 @@ "@rosen-bridge/extended-typeorm": "1.1.0", "@rosen-bridge/firo-observation-extractor": "^1.0.1", "@rosen-bridge/firo-scanner": "^0.1.2", + "@rosen-bridge/handshake-observation-extractor": "^1.0.1", + "@rosen-bridge/handshake-scanner": "^0.1.2", "@rosen-bridge/health-check": "^8.0.0", "@rosen-bridge/json-bigint": "^1.1.0", "@rosen-bridge/log-level-check": "^4.0.0", @@ -3977,6 +3979,40 @@ "npm": "11.6.2" } }, + "node_modules/@rosen-bridge/handshake-observation-extractor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rosen-bridge/handshake-observation-extractor/-/handshake-observation-extractor-1.0.1.tgz", + "integrity": "sha512-WyizMBnHfwDwuscTffnxm1be0X77+ZV4zT9LQOs/uLOHnG8z2y35fUppODW1Mi6o0zUCpCq6MRhLvH5atkSyqw==", + "license": "MIT", + "dependencies": { + "@rosen-bridge/abstract-logger": "^4.0.0", + "@rosen-bridge/abstract-observation-extractor": "^1.0.6", + "@rosen-bridge/extended-typeorm": "^1.1.0", + "@rosen-bridge/handshake-scanner": "^0.1.2", + "@rosen-bridge/rosen-extractor": "^12.0.2", + "@rosen-bridge/scanner-interfaces": "^0.2.2", + "@rosen-bridge/tokens": "^6.0.1" + }, + "engines": { + "node": ">=22.18.0", + "npm": "11.6.2" + } + }, + "node_modules/@rosen-bridge/handshake-scanner": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/handshake-scanner/-/handshake-scanner-0.1.2.tgz", + "integrity": "sha512-2qoOrrhgVYX4aPG6kuvHeNU3ow+3q6YP7BAfV7hjUaEQFqzB6/IboFuuPX47Zvzlr99k3zdVFIc/nzL177lDvQ==", + "license": "MIT", + "dependencies": { + "@rosen-bridge/abstract-scanner": "^1.0.4", + "@rosen-bridge/scanner-interfaces": "^0.2.2", + "@rosen-clients/rate-limited-axios": "^2.0.0" + }, + "engines": { + "node": ">=22.18.0", + "npm": "11.6.2" + } + }, "node_modules/@rosen-bridge/health-check": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@rosen-bridge/health-check/-/health-check-8.0.0.tgz", diff --git a/package.json b/package.json index 1ce2ddd7..3fe94819 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,8 @@ "@rosen-bridge/extended-typeorm": "1.1.0", "@rosen-bridge/firo-observation-extractor": "^1.0.1", "@rosen-bridge/firo-scanner": "^0.1.2", + "@rosen-bridge/handshake-observation-extractor": "^1.0.1", + "@rosen-bridge/handshake-scanner": "^0.1.2", "@rosen-bridge/health-check": "^8.0.0", "@rosen-bridge/json-bigint": "^1.1.0", "@rosen-bridge/log-level-check": "^4.0.0", diff --git a/src/config/config.ts b/src/config/config.ts index aab91b34..36781168 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,15 +1,15 @@ +import { ErgoNetworkType } from '@rosen-bridge/scanner-interfaces'; +import { TransportOptions } from '@rosen-bridge/winston-logger'; +import { RateLimitedAxiosConfig } from '@rosen-clients/rate-limited-axios'; +import { generateMnemonic } from 'bip39'; import config from 'config'; import * as wasm from 'ergo-lib-wasm-nodejs'; -import { SecretError } from '../errors/errors'; -import * as Constants from './constants'; -import { RosenConfig } from './rosenConfig'; import { cloneDeep } from 'lodash-es'; +import { SecretError } from '../errors/errors'; import { NetworkType } from '../types'; -import { generateMnemonic } from 'bip39'; import { convertMnemonicToSecretKey } from '../utils/utils'; -import { ErgoNetworkType } from '@rosen-bridge/scanner-interfaces'; -import { TransportOptions } from '@rosen-bridge/winston-logger'; -import { RateLimitedAxiosConfig } from '@rosen-clients/rate-limited-axios'; +import * as Constants from './constants'; +import { RosenConfig } from './rosenConfig'; const supportedNetworks: Array = [ Constants.ERGO_CHAIN_NAME, @@ -19,6 +19,7 @@ const supportedNetworks: Array = [ Constants.DOGE_CHAIN_NAME, Constants.ETHEREUM_CHAIN_NAME, Constants.BINANCE_CHAIN_NAME, + Constants.HANDSHAKE_CHAIN_NAME, Constants.FIRO_CHAIN_NAME, ]; @@ -31,6 +32,7 @@ interface ConfigType { binance: BinanceConfig; firo: FiroConfig; doge: DogeConfig; + handshake: HandshakeConfig; general: Config; rosen: RosenConfig; database: DatabaseConfig; @@ -239,6 +241,7 @@ class Config { [Constants.ETHEREUM_CHAIN_NAME]: Constants.ETHEREUM_BLOCK_TIME, [Constants.DOGE_CHAIN_NAME]: Constants.DOGE_BLOCK_TIME, [Constants.FIRO_CHAIN_NAME]: Constants.FIRO_BLOCK_TIME, + [Constants.HANDSHAKE_CHAIN_NAME]: Constants.HANDSHAKE_BLOCK_TIME, }[this.networkWatcher]; this.observationValidThreshold = Math.floor( getRequiredNumber('observation.validThreshold') / blockTime @@ -639,6 +642,37 @@ class FiroConfig { } } +class HandshakeConfig { + type: string; + initialHeight: number; + interval: number; + rpc?: { + url: string; + timeout: number; + username?: string; + password?: string; + }; + + constructor(network: string) { + this.type = config.get('handshake.type'); + if (network === Constants.HANDSHAKE_CHAIN_NAME) { + this.initialHeight = getRequiredNumber('handshake.initial.height'); + this.interval = getRequiredNumber('handshake.interval'); + if (this.type == Constants.RPC_TYPE) { + const url = getRequiredString('handshake.rpc.url'); + const timeout = getRequiredNumber('handshake.rpc.timeout'); + const username = getOptionalString('handshake.rpc.username', undefined); + const password = getOptionalString('handshake.rpc.password', undefined); + this.rpc = { url, timeout, username, password }; + } else { + throw new Error( + `Improperly configured. handshake configuration type is invalid available choices are '${Constants.RPC_TYPE}'` + ); + } + } + } +} + class DatabaseConfig { type: string; path = ''; @@ -749,6 +783,7 @@ const getConfig = (): ConfigType => { const doge = new DogeConfig(general.networkWatcher); const ethereum = new EthereumConfig(general.networkWatcher); const binance = new BinanceConfig(general.networkWatcher); + const handshake = new HandshakeConfig(general.networkWatcher); const firo = new FiroConfig(general.networkWatcher); const rosen = new RosenConfig( general.networkWatcher, @@ -764,6 +799,7 @@ const getConfig = (): ConfigType => { doge, ethereum, binance, + handshake, firo, logger, general, @@ -777,14 +813,15 @@ const getConfig = (): ConfigType => { }; export { - getConfig, - Config, - RosenConfig, - CardanoConfig, + BinanceConfig, BitcoinConfig, BitcoinRunesConfig, + CardanoConfig, + Config, + DogeConfig, EthereumConfig, - BinanceConfig, FiroConfig, - DogeConfig, + getConfig, + HandshakeConfig, + RosenConfig, }; diff --git a/src/config/constants.ts b/src/config/constants.ts index 099335de..e32e0e47 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -18,6 +18,7 @@ export const BITCOIN_RUNES_CHAIN_NAME = 'bitcoin-runes'; export const DOGE_CHAIN_NAME = 'doge'; export const ETHEREUM_CHAIN_NAME = 'ethereum'; export const BINANCE_CHAIN_NAME = 'binance'; +export const HANDSHAKE_CHAIN_NAME = 'handshake'; export const FIRO_CHAIN_NAME = 'firo'; export const ERGO_NATIVE_ASSET = 'erg'; export const ERGO_DECIMALS = 9; @@ -34,6 +35,7 @@ export const CARDANO_BLOCK_TIME = 20; export const ERGO_BLOCK_TIME = 120; export const ETHEREUM_BLOCK_TIME = 12; export const DOGE_BLOCK_TIME = 60; +export const HANDSHAKE_BLOCK_TIME = 600; export const FIRO_BLOCK_TIME = 150; export const UNISAT_TYPE = 'unisat'; export const ORDISCAN_TYPE = 'ordiscan'; diff --git a/src/jobs/initScanner.ts b/src/jobs/initScanner.ts index 0f1096d2..c8448420 100644 --- a/src/jobs/initScanner.ts +++ b/src/jobs/initScanner.ts @@ -1,9 +1,9 @@ +import { DefaultLogger } from '@rosen-bridge/abstract-logger'; import { GeneralScanner } from '@rosen-bridge/abstract-scanner'; import { CardanoOgmiosScanner } from '@rosen-bridge/cardano-scanner'; -import * as Constants from '../config/constants'; -import { getConfig } from '../config/config'; -import { DefaultLogger } from '@rosen-bridge/abstract-logger'; import { EvmRpcScanner } from '@rosen-bridge/evm-scanner'; +import { getConfig } from '../config/config'; +import * as Constants from '../config/constants'; import { CreateScanner } from '../utils/scanner'; const allConfig = getConfig(); @@ -15,6 +15,7 @@ const { doge: dogeConfig, ethereum: ethereumConfig, binance: binanceConfig, + handshake: handshakeConfig, firo: firoConfig, } = allConfig; @@ -87,6 +88,12 @@ export const scannerInit = () => { scanner.getObservationScanner() as GeneralScanner ).then(() => null); break; + case Constants.HANDSHAKE_CHAIN_NAME: + scanningJob( + handshakeConfig.interval, + scanner.getObservationScanner() as GeneralScanner + ).then(() => null); + break; case Constants.ERGO_CHAIN_NAME: break; default: diff --git a/src/types/config.ts b/src/types/config.ts index 5efedf7c..f0c94f5e 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -8,6 +8,7 @@ type NetworkType = | typeof Constants.DOGE_CHAIN_NAME | typeof Constants.ETHEREUM_CHAIN_NAME | typeof Constants.BINANCE_CHAIN_NAME - | typeof Constants.FIRO_CHAIN_NAME; + | typeof Constants.FIRO_CHAIN_NAME + | typeof Constants.HANDSHAKE_CHAIN_NAME; export { NetworkType }; diff --git a/src/utils/healthCheck.ts b/src/utils/healthCheck.ts index c9ce9b3a..29856df0 100644 --- a/src/utils/healthCheck.ts +++ b/src/utils/healthCheck.ts @@ -1,25 +1,25 @@ +import { DefaultLogger } from '@rosen-bridge/abstract-logger'; import { ErgoExplorerAssetHealthCheckParam, ErgoNodeAssetHealthCheckParam, } from '@rosen-bridge/asset-check'; +import { CardanoOgmiosScanner } from '@rosen-bridge/cardano-scanner'; +import { DiscordNotification } from '@rosen-bridge/discord-notification'; import { HealthCheck, HealthStatusLevel } from '@rosen-bridge/health-check'; +import { LogLevelHealthCheck } from '@rosen-bridge/log-level-check'; import { AbstractPermitHealthCheckParam, ExplorerPermitHealthCheckParam, NodePermitHealthCheckParam, } from '@rosen-bridge/permit-check'; import { - ScannerSyncHealthCheckParam, CardanoOgmiosScannerHealthCheck, + ScannerSyncHealthCheckParam, } from '@rosen-bridge/scanner-sync-check'; import { ExplorerWidHealthCheckParam, NodeWidHealthCheckParam, } from '@rosen-bridge/wid-check'; -import { DefaultLogger } from '@rosen-bridge/abstract-logger'; -import { CardanoOgmiosScanner } from '@rosen-bridge/cardano-scanner'; -import { DiscordNotification } from '@rosen-bridge/discord-notification'; -import { LogLevelHealthCheck } from '@rosen-bridge/log-level-check'; import { Transaction } from '../api/Transaction'; import { getConfig } from '../config/config'; @@ -33,8 +33,6 @@ import { CARDANO_CHAIN_NAME, DOGE_BLOCK_TIME, DOGE_CHAIN_NAME, - FIRO_BLOCK_TIME, - FIRO_CHAIN_NAME, ERGO_BLOCK_TIME, ERGO_CHAIN_NAME, ERGO_DECIMALS, @@ -42,6 +40,10 @@ import { ETHEREUM_BLOCK_TIME, ETHEREUM_CHAIN_NAME, EXPLORER_TYPE, + FIRO_BLOCK_TIME, + FIRO_CHAIN_NAME, + HANDSHAKE_BLOCK_TIME, + HANDSHAKE_CHAIN_NAME, NODE_TYPE, OGMIOS_TYPE, } from '../config/constants'; @@ -196,70 +198,77 @@ class HealthCheckSingleton { */ registerScannerSyncHealthCheck = () => { const scanner = CreateScanner.getInstance(); + const currentConfig = getConfig(); let scannerSyncCheck: | ScannerSyncHealthCheckParam | CardanoOgmiosScannerHealthCheck; if ( - getConfig().general.networkWatcher === CARDANO_CHAIN_NAME && - getConfig().cardano.type === OGMIOS_TYPE + currentConfig.general.networkWatcher === CARDANO_CHAIN_NAME && + currentConfig.cardano.type === OGMIOS_TYPE ) { scannerSyncCheck = new CardanoOgmiosScannerHealthCheck( this.observingNetworkLastBlock(scanner.getObservationScanner().name()), ( scanner.getObservationScanner() as CardanoOgmiosScanner ).getConnectionStatus, - getConfig().healthCheck.scannerWarnDiff, - getConfig().healthCheck.scannerCriticalDiff, + currentConfig.healthCheck.scannerWarnDiff, + currentConfig.healthCheck.scannerCriticalDiff, // TODO: Fix configuration: local/health-check/-/issues/29 - getConfig().cardano.ogmios!.connectionRetrialInterval * 15 + currentConfig.cardano.ogmios!.connectionRetrialInterval * 15 ); } else { let chainName: string; let chainBlockTime: number; let updateInterval: number; - switch (getConfig().general.networkWatcher) { + + switch (currentConfig.general.networkWatcher) { case CARDANO_CHAIN_NAME: chainName = CARDANO_CHAIN_NAME; chainBlockTime = CARDANO_BLOCK_TIME; - updateInterval = getConfig().cardano.koios!.interval; + updateInterval = currentConfig.cardano.koios!.interval; break; case BITCOIN_CHAIN_NAME: chainName = BITCOIN_CHAIN_NAME; chainBlockTime = BITCOIN_BLOCK_TIME; - updateInterval = getConfig().bitcoin.interval; + updateInterval = currentConfig.bitcoin.interval; break; case BITCOIN_RUNES_CHAIN_NAME: chainName = BITCOIN_RUNES_CHAIN_NAME; chainBlockTime = BITCOIN_BLOCK_TIME; - updateInterval = getConfig().bitcoin.interval; + updateInterval = currentConfig.bitcoin.interval; break; case DOGE_CHAIN_NAME: chainName = DOGE_CHAIN_NAME; chainBlockTime = DOGE_BLOCK_TIME; - updateInterval = getConfig().doge.interval; + updateInterval = currentConfig.doge.interval; break; case ETHEREUM_CHAIN_NAME: chainName = ETHEREUM_CHAIN_NAME; chainBlockTime = ETHEREUM_BLOCK_TIME; - updateInterval = getConfig().ethereum.interval; + updateInterval = currentConfig.ethereum.interval; break; case BINANCE_CHAIN_NAME: chainName = BINANCE_CHAIN_NAME; chainBlockTime = BINANCE_BLOCK_TIME; - updateInterval = getConfig().binance.interval; + updateInterval = currentConfig.binance.interval; break; case FIRO_CHAIN_NAME: chainName = FIRO_CHAIN_NAME; chainBlockTime = FIRO_BLOCK_TIME; - updateInterval = getConfig().firo.interval; + updateInterval = currentConfig.firo.interval; + break; + case HANDSHAKE_CHAIN_NAME: + chainName = HANDSHAKE_CHAIN_NAME; + chainBlockTime = HANDSHAKE_BLOCK_TIME; + updateInterval = currentConfig.handshake.interval; break; } scannerSyncCheck = new ScannerSyncHealthCheckParam( chainName!, this.observingNetworkLastBlock(scanner.getObservationScanner().name()), - getConfig().healthCheck.scannerWarnDiff, - getConfig().healthCheck.scannerCriticalDiff, + currentConfig.healthCheck.scannerWarnDiff, + currentConfig.healthCheck.scannerCriticalDiff, chainBlockTime!, updateInterval! ); diff --git a/src/utils/networkConnectorManagers.ts b/src/utils/networkConnectorManagers.ts index 5d18785b..729d8a0c 100644 --- a/src/utils/networkConnectorManagers.ts +++ b/src/utils/networkConnectorManagers.ts @@ -1,32 +1,36 @@ +import { DefaultLogger } from '@rosen-bridge/abstract-logger'; import { - NetworkConnectorManager, FailoverStrategy, + NetworkConnectorManager, RoundRobinStrategy, } from '@rosen-bridge/abstract-scanner'; import { - ErgoNodeNetwork, - ErgoExplorerNetwork, -} from '@rosen-bridge/ergo-scanner'; -import { - DogeRpcTransaction, - BitcoinRpcTransaction, + BitcoinEsploraTransaction, BitcoinRpcNetwork, + BitcoinRpcTransaction, DogeRpcNetwork, + DogeRpcTransaction, EsploraNetwork, - BitcoinEsploraTransaction, } from '@rosen-bridge/bitcoin-scanner'; -import { FiroRpcNetwork, FiroRpcTransaction } from '@rosen-bridge/firo-scanner'; import { - KoiosNetwork, BlockFrostNetwork, - KoiosTransaction, BlockFrostTransaction, + KoiosNetwork, + KoiosTransaction, } from '@rosen-bridge/cardano-scanner'; +import { + ErgoExplorerNetwork, + ErgoNodeNetwork, +} from '@rosen-bridge/ergo-scanner'; import { EvmRpcNetwork } from '@rosen-bridge/evm-scanner'; -import { getConfig } from '../config/config'; -import { DefaultLogger } from '@rosen-bridge/abstract-logger'; +import { FiroRpcNetwork, FiroRpcTransaction } from '@rosen-bridge/firo-scanner'; +import { + HandshakeRpcNetwork, + HandshakeRpcTransaction, +} from '@rosen-bridge/handshake-scanner'; import { Transaction } from '@rosen-bridge/scanner-interfaces'; import { TransactionResponse } from 'ethers'; +import { getConfig } from '../config/config'; const config = getConfig(); const logger = DefaultLogger.getInstance().child(import.meta.url); @@ -40,6 +44,7 @@ const cardanoKoiosLogger = logger.child('cardanoKoiosConnector'); const cardanoBlockfrostLogger = logger.child('cardanoBlockfrostConnector'); const evmLogger = logger.child('evmConnector'); const firoLogger = logger.child('firoConnector'); +const handshakeLogger = logger.child('handshakeConnector'); /** * Creates and configures a NetworkConnectorManager instance for Ergo node @@ -304,3 +309,35 @@ export const createFiroRpcNetworkConnectorManager = () => { return networkConnectorManager; }; + +/** + * Creates and configures a NetworkConnectorManager instance for Handshake RPC scanner + */ +export const createHandshakeRpcNetworkConnectorManager = () => { + const networkConnectorManager = + new NetworkConnectorManager( + new FailoverStrategy(), + handshakeLogger + ); + + if (config.handshake.rpc) { + networkConnectorManager.addConnector( + new HandshakeRpcNetwork( + config.handshake.rpc.url, + config.handshake.rpc.timeout * 1000, + config.handshake.rpc.username && config.handshake.rpc.password + ? { + username: config.handshake.rpc.username, + password: config.handshake.rpc.password, + } + : undefined + ) + ); + } else { + throw new Error( + 'Rpc configuration must be provided for Handshake Rpc network' + ); + } + + return networkConnectorManager; +}; diff --git a/src/utils/scanner.ts b/src/utils/scanner.ts index a41a64f7..8a96444d 100644 --- a/src/utils/scanner.ts +++ b/src/utils/scanner.ts @@ -1,18 +1,24 @@ +import { DefaultLogger } from '@rosen-bridge/abstract-logger'; import { ErgoUTXOExtractor } from '@rosen-bridge/address-extractor'; -import { - BitcoinEsploraScanner, - DogeEsploraScanner, - BitcoinRpcScanner, - DogeRpcScanner, -} from '@rosen-bridge/bitcoin-scanner'; import { BitcoinEsploraObservationExtractor, BitcoinRpcObservationExtractor, DogeEsploraObservationExtractor, DogeRpcObservationExtractor, } from '@rosen-bridge/bitcoin-observation-extractor'; -import { DefaultLogger } from '@rosen-bridge/abstract-logger'; -import { ErgoObservationExtractor } from '@rosen-bridge/ergo-observation-extractor'; +import { + AbstractRunesProtocolNetwork, + BitcoinRunesEsploraObservationExtractor, + BitcoinRunesRpcObservationExtractor, + OrdiscanRunesProtocolNetwork, + UnisatRunesProtocolNetwork, +} from '@rosen-bridge/bitcoin-runes-observation-extractor'; +import { + BitcoinEsploraScanner, + BitcoinRpcScanner, + DogeEsploraScanner, + DogeRpcScanner, +} from '@rosen-bridge/bitcoin-scanner'; import { CardanoBlockFrostObservationExtractor, CardanoKoiosObservationExtractor, @@ -23,7 +29,10 @@ import { CardanoKoiosScanner, CardanoOgmiosScanner, } from '@rosen-bridge/cardano-scanner'; +import { ErgoObservationExtractor } from '@rosen-bridge/ergo-observation-extractor'; import { ErgoScanner } from '@rosen-bridge/ergo-scanner'; +import { HandshakeRpcObservationExtractor } from '@rosen-bridge/handshake-observation-extractor'; +import { HandshakeRpcScanner } from '@rosen-bridge/handshake-scanner'; import { ErgoNetworkType } from '@rosen-bridge/scanner-interfaces'; import { CollateralExtractor, @@ -31,47 +40,42 @@ import { EventTriggerExtractor, PermitExtractor, } from '@rosen-bridge/watcher-data-extractor'; -import { - BitcoinRunesEsploraObservationExtractor, - BitcoinRunesRpcObservationExtractor, - AbstractRunesProtocolNetwork, - UnisatRunesProtocolNetwork, - OrdiscanRunesProtocolNetwork, -} from '@rosen-bridge/bitcoin-runes-observation-extractor'; import { BinanceRpcObservationExtractor, EthereumRpcObservationExtractor, } from '@rosen-bridge/evm-observation-extractor'; +import { EvmRpcScanner } from '@rosen-bridge/evm-scanner'; import { FiroRpcObservationExtractor } from '@rosen-bridge/firo-observation-extractor'; import { FiroRpcScanner } from '@rosen-bridge/firo-scanner'; -import { EvmRpcScanner } from '@rosen-bridge/evm-scanner'; import { dataSource } from '../../config/dataSource'; import { BinanceConfig, BitcoinConfig, + BitcoinRunesConfig, CardanoConfig, Config, + DogeConfig, EthereumConfig, FiroConfig, getConfig, + HandshakeConfig, RosenConfig, - DogeConfig, - BitcoinRunesConfig, } from '../config/config'; import * as Constants from '../config/constants'; import { TokensConfig } from '../config/tokensConfig'; import { - createCardanoKoiosNetworkConnectorManager, - createCardanoBlockfrostNetworkConnectorManager, createBitcoinEsploraNetworkConnectorManager, createBitcoinRpcNetworkConnectorManager, + createCardanoBlockfrostNetworkConnectorManager, + createCardanoKoiosNetworkConnectorManager, createDogeEsploraNetworkConnectorManager, createDogeRpcNetworkConnectorManager, + createErgoExplorerNetworkConnectorManager, + createErgoNodeNetworkConnectorManager, createEvmNetworkConnectorManager, createFiroRpcNetworkConnectorManager, - createErgoNodeNetworkConnectorManager, - createErgoExplorerNetworkConnectorManager, + createHandshakeRpcNetworkConnectorManager, } from './networkConnectorManagers'; const logger = DefaultLogger.getInstance().child(import.meta.url); @@ -106,7 +110,8 @@ class CreateScanner { | DogeEsploraScanner | DogeRpcScanner | EvmRpcScanner - | FiroRpcScanner; + | FiroRpcScanner + | HandshakeRpcScanner; private constructor() { // do nothing @@ -128,6 +133,7 @@ class CreateScanner { doge: dogeConfig, ethereum: ethereumConfig, binance: binanceConfig, + handshake: handshakeConfig, firo: firoConfig, } = allConfig; @@ -183,6 +189,13 @@ class CreateScanner { config.observationStoreRawData ); break; + case Constants.HANDSHAKE_CHAIN_NAME: + await CreateScanner.instance.createHandshakeScanner( + handshakeConfig, + rosenConfig, + config.observationStoreRawData + ); + break; } if (!CreateScanner.instance.observationScanner) throw Error( @@ -225,7 +238,8 @@ class CreateScanner { | DogeEsploraScanner | DogeRpcScanner | EvmRpcScanner - | FiroRpcScanner => { + | FiroRpcScanner + | HandshakeRpcScanner => { if (!CreateScanner.instance) { throw new Error('Scanner is not initialized'); } @@ -586,6 +600,7 @@ class CreateScanner { } } }; + private createFiroScanner = async ( firoConfig: FiroConfig, rosenConfig: RosenConfig, @@ -611,6 +626,32 @@ class CreateScanner { } } }; + + private createHandshakeScanner = async ( + handshakeConfig: HandshakeConfig, + rosenConfig: RosenConfig, + observationStoreRawData: boolean + ) => { + if (!this.observationScanner) { + if (handshakeConfig.rpc) { + this.observationScanner = new HandshakeRpcScanner({ + dataSource, + initialHeight: handshakeConfig.initialHeight, + network: createHandshakeRpcNetworkConnectorManager(), + logger: loggers.observationScannerLogger, + }); + + const observationExtractor = new HandshakeRpcObservationExtractor( + rosenConfig.lockAddress, + dataSource, + TokensConfig.getInstance().getTokenMap(), + loggers.observationExtractorLogger, + observationStoreRawData + ); + this.observationScanner.registerExtractor(observationExtractor); + } + } + }; } export { CreateScanner };