diff --git a/.changeset/breezy-hornets-fail.md b/.changeset/breezy-hornets-fail.md new file mode 100644 index 00000000..a5ca4874 --- /dev/null +++ b/.changeset/breezy-hornets-fail.md @@ -0,0 +1,5 @@ +--- +'guard-service': patch +--- + +change ergo scanner sync health-check thresholds diff --git a/.changeset/dull-numbers-look.md b/.changeset/dull-numbers-look.md new file mode 100644 index 00000000..338ee729 --- /dev/null +++ b/.changeset/dull-numbers-look.md @@ -0,0 +1,5 @@ +--- +'guard-service': minor +--- + +update health-check APIs regarding to latest changes diff --git a/.changeset/four-mirrors-poke.md b/.changeset/four-mirrors-poke.md new file mode 100644 index 00000000..c55311b2 --- /dev/null +++ b/.changeset/four-mirrors-poke.md @@ -0,0 +1,5 @@ +--- +'guard-service': minor +--- + +add notification to health-check diff --git a/.changeset/healthy-flies-tap.md b/.changeset/healthy-flies-tap.md new file mode 100644 index 00000000..ab657f12 --- /dev/null +++ b/.changeset/healthy-flies-tap.md @@ -0,0 +1,5 @@ +--- +'guard-service': minor +--- + +add ethereum scanner sync and asset health-check parameters diff --git a/.changeset/neat-rings-search.md b/.changeset/neat-rings-search.md new file mode 100644 index 00000000..d5f83426 --- /dev/null +++ b/.changeset/neat-rings-search.md @@ -0,0 +1,5 @@ +--- +'guard-service': patch +--- + +change default requeue waiting events interval to 6 hours diff --git a/.changeset/polite-masks-move.md b/.changeset/polite-masks-move.md new file mode 100644 index 00000000..7c99de66 --- /dev/null +++ b/.changeset/polite-masks-move.md @@ -0,0 +1,5 @@ +--- +'guard-service': minor +--- + +add tx progress health-check parameter diff --git a/.changeset/two-foxes-rule.md b/.changeset/two-foxes-rule.md new file mode 100644 index 00000000..31fdf7af --- /dev/null +++ b/.changeset/two-foxes-rule.md @@ -0,0 +1,5 @@ +--- +'guard-service': patch +--- + +change default tx processor interval to 1 minute diff --git a/config/default.yaml b/config/default.yaml index bbe9d7b4..1adb9392 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -139,13 +139,12 @@ coldStorage: startHour: 17 # start of cold storage transaction generation period endHour: 19 # end of cold storage transaction generation period intervals: - txProcessorInterval: 180 + txProcessorInterval: 60 timeoutProcessorInterval: 3600 # interval to check if events got timeout - requeueWaitingEventsInterval: 43200 # interval for requeue events which are timeout + requeueWaitingEventsInterval: 21600 # interval for requeue events which are timeout minimumFeeUpdateInterval: 300 tokensPath: './config/rosen/tokens.json' # path to supported tokens of bridge thresholdsPath: './config/thresholds.json' # path to thresholds of lock address tokens -discordWebHookUrl: '' # Discord webhook url for sending notifications database: type: 'sqlite' # options: postgres, sqlite path: './sqlite/guard.sqlite' # database path (for sqlite) @@ -169,9 +168,15 @@ healthCheck: btc: warnThreshold: 5000000 # minimum recommended btc balance criticalThreshold: 1000000 # minimum required btc balance + eth: + warnThreshold: '20000000000000000' # minimum recommended eth balance + criticalThreshold: '4000000000000000' # minimum required eth balance ergoScanner: - warnDifference: 2 # warning difference between existing and scanned blocks height - criticalDifference: 100 # critical difference between existing and scanned blocks height + warnDifference: 5 # warning difference between existing and scanned blocks height + criticalDifference: 20 # critical difference between existing and scanned blocks height + ethereumScanner: + warnDifference: 50 # warning difference between existing and scanned blocks height + criticalDifference: 200 # critical difference between existing and scanned blocks height ergoNode: maxHeightDifference: 2 # maximum difference between header height and full height maxBlockTime: 1800 # maximum time to see a new block @@ -182,5 +187,15 @@ healthCheck: duration: 100 # error log duration time check p2p: defectConfirmationTimeWindow: 120 # Time to wait after any peer disconnection + txSignFailed: + warnThreshold: 3 + criticalThreshold: 7 revenue: interval: 120 # revenue update interval +discordWebHookUrl: '' # Discord webhook url for sending notifications +notification: + historyCleanupThreshold: 90000 # 1 day and 1 hour + windowDurations: + hasBeenUnstableForAWhile: 900 + hasBeenUnknownForAWhile: 900 + isStillUnhealthy: 900 diff --git a/package-lock.json b/package-lock.json index 5b7eb719..0805726e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,33 +27,34 @@ "@libp2p/websockets": "^5.0.2", "@multiformats/multiaddr": "^11.0.3", "@rosen-bridge/abstract-notification": "^0.2.1", - "@rosen-bridge/asset-check": "^0.2.1", - "@rosen-bridge/discord-notification": "^0.1.2", - "@rosen-bridge/evm-address-tx-extractor": "^1.0.3", - "@rosen-bridge/evm-rpc-scanner": "^1.0.3", - "@rosen-bridge/health-check": "^5.0.0", - "@rosen-bridge/log-level-check": "^0.1.1", - "@rosen-bridge/minimum-fee": "^2.1.0", - "@rosen-bridge/node-sync-check": "^0.1.1", - "@rosen-bridge/p2p-network-check": "^0.1.1", - "@rosen-bridge/scanner": "^4.1.2", - "@rosen-bridge/scanner-sync-check": "^0.3.0", + "@rosen-bridge/asset-check": "^1.0.3", + "@rosen-bridge/discord-notification": "^0.1.3", + "@rosen-bridge/evm-address-tx-extractor": "^1.0.4", + "@rosen-bridge/evm-rpc-scanner": "^1.0.4", + "@rosen-bridge/health-check": "^6.0.2", + "@rosen-bridge/log-level-check": "^1.0.2", + "@rosen-bridge/minimum-fee": "^2.2.0", + "@rosen-bridge/node-sync-check": "^1.0.2", + "@rosen-bridge/p2p-network-check": "^1.0.2", + "@rosen-bridge/scanner": "^4.1.3", + "@rosen-bridge/scanner-sync-check": "^1.0.2", "@rosen-bridge/tokens": "^1.2.1", "@rosen-bridge/tss": "^3.0.1", - "@rosen-bridge/watcher-data-extractor": "^8.0.1", + "@rosen-bridge/tx-progress-check": "^1.0.0", + "@rosen-bridge/watcher-data-extractor": "^8.0.2", "@rosen-bridge/winston-logger": "0.2.1", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/bitcoin": "^5.0.1", - "@rosen-chains/bitcoin-esplora": "^4.0.1", - "@rosen-chains/cardano": "^9.0.1", - "@rosen-chains/cardano-blockfrost-network": "^7.0.1", - "@rosen-chains/cardano-koios-network": "^10.0.1", - "@rosen-chains/ergo": "^9.0.1", - "@rosen-chains/ergo-explorer-network": "^9.0.1", - "@rosen-chains/ergo-node-network": "^9.0.1", - "@rosen-chains/ethereum": "^0.1.5", - "@rosen-chains/evm": "^4.0.1", - "@rosen-chains/evm-rpc": "^2.1.2", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/bitcoin": "^5.0.2", + "@rosen-chains/bitcoin-esplora": "^4.0.2", + "@rosen-chains/cardano": "^9.0.2", + "@rosen-chains/cardano-blockfrost-network": "^7.0.2", + "@rosen-chains/cardano-koios-network": "^10.0.2", + "@rosen-chains/ergo": "^9.0.2", + "@rosen-chains/ergo-explorer-network": "^9.0.2", + "@rosen-chains/ergo-node-network": "^9.0.2", + "@rosen-chains/ethereum": "^0.1.6", + "@rosen-chains/evm": "^4.0.2", + "@rosen-chains/evm-rpc": "^2.1.3", "@sinclair/typebox": "^0.30.4", "await-semaphore": "^0.1.3", "axios": "^1.6.8", @@ -695,11 +696,11 @@ } }, "node_modules/@cardano-ogmios/client": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@cardano-ogmios/client/-/client-6.3.0.tgz", - "integrity": "sha512-nWaZ76n/R+p8nxBfRCetOuoDH8o5QToL5zWhRUu9EwHDJqM/0rzvYEk9JYCikAcVlC1qt6+3CcG4nCpG0dsptw==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@cardano-ogmios/client/-/client-6.6.2.tgz", + "integrity": "sha512-d8zsdlYl5nfQXVfpXEGHmc3t7M6vv+59drOH82t1nVMc9d/YnTJeFTHqQ2TN8C2GvMfZ7QvwNPw1iK6JMOKAeg==", "dependencies": { - "@cardano-ogmios/schema": "6.3.0", + "@cardano-ogmios/schema": "6.6.2", "@cardanosolutions/json-bigint": "^1.0.1", "@types/json-bigint": "^1.0.1", "bech32": "^2.0.0", @@ -708,7 +709,7 @@ "isomorphic-ws": "^4.0.1", "nanoid": "^3.1.31", "ts-custom-error": "^3.2.0", - "ws": "^7.4.6" + "ws": "^7.5.10" }, "engines": { "node": ">=14" @@ -723,9 +724,9 @@ } }, "node_modules/@cardano-ogmios/schema": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@cardano-ogmios/schema/-/schema-6.3.0.tgz", - "integrity": "sha512-reM7NDYV4cgMAdFCzypoIuCVgSUfR9ztRMlk6p7k0cTeqUkbMfA83ps1FVkTDxzXxFjgM4EkhqoJyRjKIKRPQA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@cardano-ogmios/schema/-/schema-6.6.2.tgz", + "integrity": "sha512-F3WqeeQ9AnemRgvTv5SCsQXYe+m6paFqMY6IvX2JcpwSQ/ineIymRUvlBC9vTc3/BkxeKqGERpzE1fUIS852gw==", "engines": { "node": ">=14" } @@ -3993,31 +3994,34 @@ } }, "node_modules/@rosen-bridge/address-codec": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@rosen-bridge/address-codec/-/address-codec-0.2.1.tgz", - "integrity": "sha512-W7d7W0rmciMJMuq4KYh+6EeiB9dCE9RBTzu5xeFd3BLHjMnYpt1/J6vdZeXpFFySNRfxclFZwU94B5q3l6CV8Q==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/address-codec/-/address-codec-0.3.0.tgz", + "integrity": "sha512-qH8kOKuAStVbXoeAWmMuGD9CQTYGCE4nFAAS1NEi11eZV1nK97/mXQgjIpPHNGKJxkuPpmsGVoZxbaZakSCE5g==", "dependencies": { "@emurgo/cardano-serialization-lib-nodejs": "^11.5.0", "bitcoinjs-lib": "^6.1.5", - "ergo-lib-wasm-nodejs": "^0.24.1" + "ergo-lib-wasm-nodejs": "^0.24.1", + "ethers": "^6.13.2" }, "engines": { "node": ">=20.11.0" } }, "node_modules/@rosen-bridge/asset-check": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@rosen-bridge/asset-check/-/asset-check-0.2.1.tgz", - "integrity": "sha512-DUvNB6Ys6xN0QWPZTvzam5vIr1wFubZSmvBa6zGpimtTBetrOWRt6VEOZ93th6IO2vXHrputFRAr5AcPQ7x4Pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rosen-bridge/asset-check/-/asset-check-1.0.3.tgz", + "integrity": "sha512-qqckGOvSq8KRxH1v4HaMiNeDawLomtViLGWmjKCPHha5A7Ruw7t4pd/u6Rukdw5tIX1Jpl5OZV2MhsTHMOHBQw==", + "license": "GPL-3.0", "dependencies": { "@apollo/client": "^3.9.11", "@blockfrost/blockfrost-js": "^5.5.0", - "@rosen-bridge/health-check": "^5.0.0", + "@rosen-bridge/health-check": "^6.0.2", "@rosen-clients/cardano-koios": "^2.0.1", "@rosen-clients/ergo-explorer": "^1.1.1", "@rosen-clients/ergo-node": "^1.1.1", "axios": "^1.6.8", - "cross-fetch": "^4.0.0" + "cross-fetch": "^4.0.0", + "ethers": "^6.13.2" }, "engines": { "node": ">=20.11.0" @@ -4044,9 +4048,9 @@ } }, "node_modules/@rosen-bridge/discord-notification": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@rosen-bridge/discord-notification/-/discord-notification-0.1.2.tgz", - "integrity": "sha512-J1U98dx0+4GYKipObandwHGIUPWR5SzG3yxpZbRKDgSWpdYoGAlbDMNTTwrVu4fRZdA6SXqztKv/4fkgwKZhIA==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@rosen-bridge/discord-notification/-/discord-notification-0.1.3.tgz", + "integrity": "sha512-ygIRnK1AY8/XrelMzQc6991e8nMyLVRd9nwO/hgMXh7SrumiYLoWRU5elSj9zw+3LT/tgkaqeYeWhMXCskTHtg==", "dependencies": { "@rosen-bridge/abstract-notification": "^0.2.1", "discord.js": "^14.15.3" @@ -4056,13 +4060,13 @@ } }, "node_modules/@rosen-bridge/evm-address-tx-extractor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/evm-address-tx-extractor/-/evm-address-tx-extractor-1.0.3.tgz", - "integrity": "sha512-TJ477VN7Xt3HMVaXbzHZH/tZ7IXr+v9KF2fkTqnarEpcI7Imb3GPT8DsxvB75w+2TNJv0wUqjKkebRaMvf+xCg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rosen-bridge/evm-address-tx-extractor/-/evm-address-tx-extractor-1.0.4.tgz", + "integrity": "sha512-0vnEtkVaxCuyuG8agAEXC2RhcpgV7w7NKlEcCnZX7Yc8HXLsRZXpnbJQM1qeubt3vTcBoCNs8rAvQXTW/xRPjA==", "dependencies": { "@rosen-bridge/abstract-extractor": "^0.3.0", "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/scanner": "^4.1.2", + "@rosen-bridge/scanner": "^4.1.3", "ethers": "^6.11.0", "typeorm": "^0.3.20" }, @@ -4071,12 +4075,12 @@ } }, "node_modules/@rosen-bridge/evm-rpc-scanner": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/evm-rpc-scanner/-/evm-rpc-scanner-1.0.3.tgz", - "integrity": "sha512-eNks7KjQIoD+Hjkrs1JipLVzKyGmQceyd3xoVp12maLwBbaCPfHiAY45E2AFXSSDdSX0Sv9eIySt6TA1bi7y9w==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rosen-bridge/evm-rpc-scanner/-/evm-rpc-scanner-1.0.4.tgz", + "integrity": "sha512-IrMrpK51SJkgUT7QY/nfjb/1U4t9yh1C/x+eZeFe2vRlLN+kX9NUtYHwGCY3Qfnfd+zpFrbRQQ0ooG7C70H5FA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/scanner": "^4.1.2", + "@rosen-bridge/scanner": "^4.1.3", "ethers": "^6.11.0" } }, @@ -4093,9 +4097,12 @@ } }, "node_modules/@rosen-bridge/health-check": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@rosen-bridge/health-check/-/health-check-5.0.0.tgz", - "integrity": "sha512-Tbk6SAOf1e6bpJychQZCEVlwdF7XnY9S6Zapw3vmliv1oa4yY7LXHvfVXVRKT4y8ZJocCzQ1YMi+satLaojrGQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/health-check/-/health-check-6.0.2.tgz", + "integrity": "sha512-g5fy/xMxYz0DLU6faR09jzDM/vql8wXNGLHXmU1G1D+sh33gX7kaIp28SacC7SnBph+13ouiKGEMKB5NJNAySA==", + "dependencies": { + "@rosen-bridge/abstract-notification": "^0.2.1" + }, "engines": { "node": ">=20.11.0" } @@ -4112,12 +4119,13 @@ } }, "node_modules/@rosen-bridge/log-level-check": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@rosen-bridge/log-level-check/-/log-level-check-0.1.1.tgz", - "integrity": "sha512-FcxqK3OnrPwHEgmX8oA4Xq4JGcS7m5NAVxf8YhAyxCNL+NRsROrs7EwWXyj9AVcSjK4+liWRVBTENcOy+nj+rA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/log-level-check/-/log-level-check-1.0.2.tgz", + "integrity": "sha512-HAFWSfPgYfCYh3jrvD1vFg4b9BoAM8IBaaJOypOBjeVd/f0f2rUmAxPJa7gpX4emXC0r/WGqK4Ze9m0mtM7kQA==", + "license": "GPL-3.0", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/health-check": "^5.0.0", + "@rosen-bridge/health-check": "^6.0.2", "lodash-es": "^4.17.21" }, "engines": { @@ -4125,9 +4133,9 @@ } }, "node_modules/@rosen-bridge/minimum-fee": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@rosen-bridge/minimum-fee/-/minimum-fee-2.1.0.tgz", - "integrity": "sha512-vd7+f4I//u4PaN5PRkwMtSfWCk4X7GoAwfD+qxwiVtpDvvE655eqxGY2z6VGWjuKlIqC8EUNRumy23t/tnhQ2w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/minimum-fee/-/minimum-fee-2.2.0.tgz", + "integrity": "sha512-nlh2a2A7a2PYWOMIT/upWLWqG1iJZQbfwFvFD0n2vWOOTdvGXT0WpKvwZYTNb1kwv5YA57fkold7H2l4IGupag==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", @@ -4140,11 +4148,12 @@ } }, "node_modules/@rosen-bridge/node-sync-check": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@rosen-bridge/node-sync-check/-/node-sync-check-0.1.1.tgz", - "integrity": "sha512-up+CJ1K96s34G+7dsz1mwSesILi1QpRNslY9ZThd3yA3sl2rc1nVihhfgP7dd7xIiTYyhgO2m3bv+FtuTKUiEQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/node-sync-check/-/node-sync-check-1.0.2.tgz", + "integrity": "sha512-jKi3Sh4hoMBglkt1lyWZjkOtEejOpoJ/TyHEqpjBohyakcEEhX2B8tWAOw/lpyMXd0YMKFovPawS0U04SvPhdw==", + "license": "GPL-3.0", "dependencies": { - "@rosen-bridge/health-check": "^5.0.0", + "@rosen-bridge/health-check": "^6.0.2", "@rosen-clients/ergo-node": "^1.1.1" }, "engines": { @@ -4152,25 +4161,26 @@ } }, "node_modules/@rosen-bridge/p2p-network-check": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@rosen-bridge/p2p-network-check/-/p2p-network-check-0.1.1.tgz", - "integrity": "sha512-2xrxNCThLiqClNKJ2+l6lQ4U7Hr3zqrHABcVyYcXMohSzHE0HUceuBWusylSQj373FNV2aUfV0G+Kev3zc0gxg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/p2p-network-check/-/p2p-network-check-1.0.2.tgz", + "integrity": "sha512-3ESJb4NniB/Wk2KujGp+G2D+hKFedjXBkNc8H900DVbE6nSgvv8GsTC6Wzcks3PX8nfG0K40hvvCWx4o0fXoaA==", + "license": "GPL-3.0", "dependencies": { - "@rosen-bridge/health-check": "^5.0.0" + "@rosen-bridge/health-check": "^6.0.2" }, "engines": { "node": ">=20.11.0" } }, "node_modules/@rosen-bridge/rosen-extractor": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@rosen-bridge/rosen-extractor/-/rosen-extractor-6.1.1.tgz", - "integrity": "sha512-hhyYd+TRABb9ajsDjnF6ISAU1r4bBOyYnl4hBIOndrdOldKCVzSSTM1/dVJ1UZCBkA3/sJa186fu+LsBX7SytA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/rosen-extractor/-/rosen-extractor-6.2.0.tgz", + "integrity": "sha512-cKQaJn3QuhrhEqTaosN9aKgBAuepwyFuehvH+br8lmdmtn1IiCsBFzzCJpXW5lm+Uluq0/yijvkelTNVEuVbfQ==", "dependencies": { "@blockfrost/blockfrost-js": "^5.4.0", "@cardano-ogmios/schema": "^6.0.3", "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/address-codec": "^0.2.1", + "@rosen-bridge/address-codec": "^0.3.0", "@rosen-bridge/json-bigint": "^0.1.0", "@rosen-bridge/tokens": "^1.2.1", "bitcoinjs-lib": "^6.1.5", @@ -4181,14 +4191,14 @@ } }, "node_modules/@rosen-bridge/scanner": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@rosen-bridge/scanner/-/scanner-4.1.2.tgz", - "integrity": "sha512-DX0x1jeNjWVnnu8Z2pku6IGN35JTUYxJkFJn5UERGOaXFiwtNmQCeg4v1qp4uFmQ4MP/NaFqCiIcVHXUXXqLJg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@rosen-bridge/scanner/-/scanner-4.1.3.tgz", + "integrity": "sha512-21o0zu54XtGpXuvApgXlAb/9AV3XBt/kb5nJT1c5pLG1MlrMbjcpPXW6kEsdI/M+XP+Hpr7//y9TRotipKh1Ug==", "dependencies": { "@apollo/client": "^3.8.7", "@blockfrost/blockfrost-js": "^5.4.0", - "@cardano-ogmios/client": "^6.3.0", - "@cardano-ogmios/schema": "^6.3.0", + "@cardano-ogmios/client": "^6.6.1", + "@cardano-ogmios/schema": "^6.6.1", "@rosen-bridge/abstract-extractor": "^0.3.0", "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", @@ -4204,20 +4214,20 @@ } }, "node_modules/@rosen-bridge/scanner-sync-check": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@rosen-bridge/scanner-sync-check/-/scanner-sync-check-0.3.0.tgz", - "integrity": "sha512-263Aauf0e4VjFEOy9pzC3+HPFSGf8vYpUP5CV9FnZSVmPfr8Q4R7Xic+uifqUZv24vXdCP0EwsqmGlSo2hBVvw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/scanner-sync-check/-/scanner-sync-check-1.0.2.tgz", + "integrity": "sha512-OdjOIhnxjdKoPeAWytxSXiaBZYvUd2ySN1Nnu/GK+RNBSQEdkFAMz/8AEbCZljTOWYqhYgiW5YONrEM1yLKb1w==", + "license": "GPL-3.0", "dependencies": { "@apollo/client": "^3.9.11", "@blockfrost/blockfrost-js": "^5.5.0", "@cardano-ogmios/client": "^6.3.0", - "@rosen-bridge/health-check": "^5.0.0", - "@rosen-bridge/scanner": "^4.0.0", + "@rosen-bridge/health-check": "^6.0.2", "@rosen-clients/ergo-explorer": "^1.1.1", "@rosen-clients/ergo-node": "^1.1.1", "axios": "^1.6.8", "cross-fetch": "^4.0.0", - "typeorm": "^0.3.20" + "ether": "^0.0.9" }, "engines": { "node": ">=20.11.0" @@ -4253,16 +4263,29 @@ } ] }, + "node_modules/@rosen-bridge/tx-progress-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/tx-progress-check/-/tx-progress-check-1.0.0.tgz", + "integrity": "sha512-Na2BEFlJRWCIXvR9aezSisu85avrctRJx2kyoFjE/5QH2qpXB3YQtamPMcsBKPFb+KEfRG9jBtl7tY8YR2TamA==", + "dependencies": { + "@rosen-bridge/health-check": "^6.0.2", + "@types/lodash-es": "^4.17.12", + "lodash-es": "^4.17.21" + }, + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/@rosen-bridge/watcher-data-extractor": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@rosen-bridge/watcher-data-extractor/-/watcher-data-extractor-8.0.1.tgz", - "integrity": "sha512-aLbJXPagnMIh1LnNgRkouErphIHts8MRS65wx+kDhm02SESWga3b+GzzAVAMNR2/0IqoEK8/sPWiWepMWz7nsA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/watcher-data-extractor/-/watcher-data-extractor-8.0.2.tgz", + "integrity": "sha512-pnpSbuqgCVEecCZDZrL6TthMrXPWkgpXOC5pnWFYNyjOyYlymxCrCEhW15L8hahmRPyy2LfH0TMd0LGQNmeRzg==", "dependencies": { "@rosen-bridge/abstract-extractor": "^0.3.0", "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/extended-typeorm": "^0.0.3", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-bridge/scanner": "^4.1.2", + "@rosen-bridge/scanner": "^4.1.3", "@rosen-bridge/tokens": "^1.2.1", "@rosen-clients/ergo-explorer": "^1.1.1", "@types/lodash-es": "^4.17.6", @@ -4292,29 +4315,29 @@ } }, "node_modules/@rosen-chains/abstract-chain": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/abstract-chain/-/abstract-chain-9.0.1.tgz", - "integrity": "sha512-HjlVJhMbN1RPOA0lVMP9fSj4/mAmghqEKz/YHbDD3igxZc38y2Wt/XfqGT5Fdx8mihQv9dRUQtZIZXPhEiENMg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/abstract-chain/-/abstract-chain-9.0.2.tgz", + "integrity": "sha512-exH4kCHcFl1FcnPPrCdAfj6fxisE8IJsGsAj8VmY4gfZcAyBS3qnIZsWWgSrGwNcMrNVWNbT1vvm7MhgVTKynA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-bridge/minimum-fee": "^2.1.0", - "@rosen-bridge/rosen-extractor": "^6.1.1", + "@rosen-bridge/minimum-fee": "^2.2.0", + "@rosen-bridge/rosen-extractor": "^6.2.0", "@rosen-bridge/tokens": "^1.2.1", "blakejs": "^1.2.1" } }, "node_modules/@rosen-chains/bitcoin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/bitcoin/-/bitcoin-5.0.1.tgz", - "integrity": "sha512-1LqQxUoKUrY8Y3V2Qaqgbm2/NSLLrBSowwjepcC50Si/1STeigWRADzLp/c+SrHLDXOXNTCtLAGLZondqdBnjw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/bitcoin/-/bitcoin-5.0.2.tgz", + "integrity": "sha512-TeXeF6p0yB6m9Q8g8kbO2/03tAgNNU3VIRvPUyJ5LR11TufkaugI2HnzB20ZtChZLC2Lc5fQGiHf17fgds/hRQ==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/bitcoin-utxo-selection": "^0.2.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-bridge/rosen-extractor": "^6.1.1", + "@rosen-bridge/rosen-extractor": "^6.2.0", "@rosen-bridge/tokens": "^1.2.1", - "@rosen-chains/abstract-chain": "^9.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", "bitcoinjs-lib": "^6.1.5" }, "engines": { @@ -4322,14 +4345,14 @@ } }, "node_modules/@rosen-chains/bitcoin-esplora": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/bitcoin-esplora/-/bitcoin-esplora-4.0.1.tgz", - "integrity": "sha512-L+8QXxfacBKkbW8oFcfgA6Vov8JzW6uad+z8mcGx1grZos/tISSd89+vNTMiJ/lDvNlTw2fHPmBRXTj3TmtcPQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/bitcoin-esplora/-/bitcoin-esplora-4.0.2.tgz", + "integrity": "sha512-FQzKm5f7YSIoeLFMjlNfTyN/KySAY2UVMqeiPg61K+l/jcOQNOoZFBipY2SWMPby1Ambaj1AQNGmdTcUH3ZqZg==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/bitcoin": "^5.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/bitcoin": "^5.0.2", "axios": "^1.6.7", "bitcoinjs-lib": "^6.1.5" }, @@ -4338,69 +4361,69 @@ } }, "node_modules/@rosen-chains/cardano": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/cardano/-/cardano-9.0.1.tgz", - "integrity": "sha512-1EfsHaqsBDwYUutl/Hklo2kZvCW9C1G9gUBz7bkOF+zLZryF3FxZg4HywnSRkdST4EE0Agyyay03OXgrM2GdOQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/cardano/-/cardano-9.0.2.tgz", + "integrity": "sha512-yzmTrR6kBDo2Lre+A/sJskTkE0OINFpjo+socBzhHMraMVpYXLX6mRu9jYwhQ3lFJcK09PeeYSOKxkj4sU8tzQ==", "dependencies": { "@emurgo/cardano-serialization-lib-nodejs": "^11.3.1", "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-bridge/rosen-extractor": "^6.1.1", + "@rosen-bridge/rosen-extractor": "^6.2.0", "@rosen-bridge/tokens": "^1.2.1", - "@rosen-chains/abstract-chain": "^9.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", "bech32": "^2.0.0" } }, "node_modules/@rosen-chains/cardano-blockfrost-network": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/cardano-blockfrost-network/-/cardano-blockfrost-network-7.0.1.tgz", - "integrity": "sha512-CHWS1feB33XXpW7eZAFc/AWbPQWTqfTVunPsXxONa90ZCrIMgCbQvFVuCNN05QOZSfmSVx7EdgefUf1mQvJcSQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/cardano-blockfrost-network/-/cardano-blockfrost-network-7.0.2.tgz", + "integrity": "sha512-yqWKd8WFHiKGNvgPKYxvRGm74WhPPKRhzOW0Qk+fnfdhJ07aM9kdE9g3NfdIy3bYQR7/NaQsMS8FW16x7xLJLA==", "dependencies": { "@blockfrost/blockfrost-js": "^5.4.0", "@emurgo/cardano-serialization-lib-nodejs": "^11.3.1", "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/cardano": "^9.0.1" + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/cardano": "^9.0.2" }, "engines": { "node": ">=18.12.0" } }, "node_modules/@rosen-chains/cardano-koios-network": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/cardano-koios-network/-/cardano-koios-network-10.0.1.tgz", - "integrity": "sha512-i/QBKmMXQezkAj79t8wnxfgI8XWRfx0N7oGL/Gjirr8tmARTd0nqOUsclegPtgz9sdQ7/iVuHxTupDfV/fajiw==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/cardano-koios-network/-/cardano-koios-network-10.0.2.tgz", + "integrity": "sha512-VyS7EsrwfQVAtXYl12i1vfKTJ9FWkv1rTA2Md0j9Ej7dyUgfnuKp6K2/BO5ZTx9iiixwUhEfjdTJsoN0yt9baA==", "dependencies": { "@emurgo/cardano-serialization-lib-nodejs": "^11.3.1", "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/cardano": "^9.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/cardano": "^9.0.2", "@rosen-clients/cardano-koios": "^2.0.3" } }, "node_modules/@rosen-chains/ergo": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/ergo/-/ergo-9.0.1.tgz", - "integrity": "sha512-S15GHw8HXHkLnguih47uLj0e42bSnAO4cXJa7QCEygrgYEBB4pZnE+QV3QCefBh44YPuH92MGFrFHngay9uUow==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/ergo/-/ergo-9.0.2.tgz", + "integrity": "sha512-ivKUzL11Jl2HIqzDplkuFT3G1Kp461SbxYk5pWmP4PcgGYORTDaHj7wa81XcYJCJorwXossj47AAzYFf7mHKSg==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-bridge/rosen-extractor": "^6.1.1", + "@rosen-bridge/rosen-extractor": "^6.2.0", "@rosen-bridge/tokens": "^1.2.1", - "@rosen-chains/abstract-chain": "^9.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", "ergo-lib-wasm-nodejs": "^0.24.1" } }, "node_modules/@rosen-chains/ergo-explorer-network": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/ergo-explorer-network/-/ergo-explorer-network-9.0.1.tgz", - "integrity": "sha512-FvZlc7mAMzC64kbybtDKHaPBIXwIaGa6p1y4DEOQ43CUy7q0LozJazqnwsjCBocSmV6DctD+VOcyf9EWgESl+w==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/ergo-explorer-network/-/ergo-explorer-network-9.0.2.tgz", + "integrity": "sha512-uBHKpzSJFW3Ssy7CfQD4N2HUqIKWNd/f/QFJILot2eBtCNtpU97uN8W5Wf7j7a7Hz2xmxATuOzyCsWev6f3otA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/ergo": "^9.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/ergo": "^9.0.2", "@rosen-clients/ergo-explorer": "^1.1.1", "ergo-lib-wasm-nodejs": "^0.24.1", "it-all": "^3.0.1" @@ -4416,14 +4439,14 @@ } }, "node_modules/@rosen-chains/ergo-node-network": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/ergo-node-network/-/ergo-node-network-9.0.1.tgz", - "integrity": "sha512-/BRzwaAxjRXvr+ggVfr17MAVbwqMaSLGDG/g772V8ZD2TrB6PDeh5bxcxjtWjF1sYL4Nz5AbdabtCxWsfRRlKg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/ergo-node-network/-/ergo-node-network-9.0.2.tgz", + "integrity": "sha512-/lJtb2nxXxQc0j+YsWzqHSu6z+6VpWhOrQJk6AcoG4tfCaARq4osaWN4XuHSBZ3u6wJHyyeY5muDJUy7sfHBsw==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/ergo": "^9.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/ergo": "^9.0.2", "@rosen-clients/ergo-node": "^1.1.1", "ergo-lib-wasm-nodejs": "^0.24.1", "it-all": "^3.0.1" @@ -4439,29 +4462,29 @@ } }, "node_modules/@rosen-chains/ethereum": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@rosen-chains/ethereum/-/ethereum-0.1.5.tgz", - "integrity": "sha512-vKCC4NyNK3tqogk6MLz/LupLd6039OMFy1JbeQ917JHgK3lS+Cn5tINdoGsTM41bc6vkRv0dIWxD1DgP6zFtxw==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@rosen-chains/ethereum/-/ethereum-0.1.6.tgz", + "integrity": "sha512-qgtPZITlCi/uUIvs33awmM8Khm9DEJ3qbL3CefVNCgkkMbLuVbKj0yQgougGR37YSgge6pFRouBvL6xpQ0ozZA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/tokens": "^1.2.1", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/evm": "^4.0.1" + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/evm": "^4.0.2" }, "engines": { "node": ">=20.11.0" } }, "node_modules/@rosen-chains/evm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@rosen-chains/evm/-/evm-4.0.1.tgz", - "integrity": "sha512-BxowIspVfwm4Kd1DTQt3+1lg3wVcLjx6nWDM2HarY3TUYz08h+pUfMg3nOF3V2L4uxw/3a2MskzBsU5oFpoNMQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@rosen-chains/evm/-/evm-4.0.2.tgz", + "integrity": "sha512-Lp43Br0praB+z8vok6/JWsGjz6ME5cEVixUHyKsj7zmG3cJpmMaiUMb5eOxZQGZfNpg7/F54aLkAO8Hrawk4nA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", - "@rosen-bridge/rosen-extractor": "^6.1.1", + "@rosen-bridge/rosen-extractor": "^6.2.0", "@rosen-bridge/tokens": "^1.2.1", - "@rosen-chains/abstract-chain": "^9.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", "ethers": "^6.11.1" }, "engines": { @@ -4469,14 +4492,14 @@ } }, "node_modules/@rosen-chains/evm-rpc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@rosen-chains/evm-rpc/-/evm-rpc-2.1.2.tgz", - "integrity": "sha512-RbSEhZo1Yb0E/HX4ix3QxN0R8jtj1cbiKx+fVjMDlvz3PEq0SOwMHmRPGG4ezPrzTlAk6fWcgyTUMTHJaOhwxA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@rosen-chains/evm-rpc/-/evm-rpc-2.1.3.tgz", + "integrity": "sha512-YDKtt5hZyAnv7YshBv1azDIXvb8HHr+eDdEHmH7L906S21641LS9wLIT80ga1bSH+ljE85AbeP72skVUxremsg==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/evm-address-tx-extractor": "^1.0.3", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/evm": "^4.0.1", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/evm": "^4.0.2", "typeorm": "^0.3.20" }, "engines": { @@ -5026,9 +5049,9 @@ "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" }, "node_modules/@types/lodash-es": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.6.tgz", - "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "dependencies": { "@types/lodash": "*" } @@ -5844,6 +5867,11 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, "node_modules/async-exit-hook": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", @@ -6492,6 +6520,18 @@ "node": ">=6" } }, + "node_modules/cli-color": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.2.3.tgz", + "integrity": "sha512-f4DFHXdoe2rGMwuVO+DTBM6CkSt4m9R4a0vjnq5CJkSCKaXbrHbslCmyjG6cz/o50HP2wkjO3G1mXvc7G3V1LQ==", + "dependencies": { + "es5-ext": "~0.9.2", + "memoizee": "~0.2.5" + }, + "engines": { + "node": ">=0.1.103" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -6790,6 +6830,14 @@ "node": ">= 0.6" } }, + "node_modules/cookiejar": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-1.3.0.tgz", + "integrity": "sha512-U+NgxxtwHIokuL04FqKEkqsaWBDtnCQo+wvYjUCtBA56Lcg8vpV3SGtBx+RAmw92SV3VT8PwsYcCFK/cC3Dw+A==", + "engines": { + "node": "*" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -7476,6 +7524,11 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/emitter-component": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.0.0.tgz", + "integrity": "sha512-GZrLdp4Z7OERecoYQYElVVqf6/gcbGUs8nvaE+nmu2dGy453lLgGyPLNX9DdSyojdMqI86fCT9XQqsWJymciEw==" + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -7691,6 +7744,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es5-ext": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.9.2.tgz", + "integrity": "sha512-wP3OSxZ0L/qK76t6qxPR8gWr2o5F4SzNF9qS5F/mOfVY3Ezcg07v6hSkETDmoekXIzn8xhQbHpp+tVlOE+qOAg==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/esbuild": { "version": "0.17.14", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.14.tgz", @@ -8484,6 +8545,30 @@ "node": ">=0.10.0" } }, + "node_modules/ether": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ether/-/ether-0.0.9.tgz", + "integrity": "sha512-KYive1RzWSVsOTnGM0GHCUkeAz/TtNA9XRzd+WS0GndvXlmpKyNQ9n69SF46lJmNeuMtvgcG+LIDXZYhk2/kDQ==", + "dependencies": { + "commander": "~2.1.0", + "inquirer": "~0.4.0", + "memoizee": "~0.2.6", + "micro-engine": "0.0.1", + "sudo-block": "~0.3.0", + "superagent": "~0.16.0" + }, + "bin": { + "ether": "bin/index.js" + } + }, + "node_modules/ether/node_modules/commander": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", + "integrity": "sha512-J2wnb6TKniXNOtoHS8TSrG9IOQluPrsmyAJ8oCUJOBmv+uLBCyPYAZkD2jFvw2DCzIXNnISIM01NIvr35TkBMQ==", + "engines": { + "node": ">= 0.6.x" + } + }, "node_modules/ethers": { "version": "6.13.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", @@ -8541,6 +8626,17 @@ } } }, + "node_modules/event-emitter": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.2.2.tgz", + "integrity": "sha512-kdjfxF6jYJ5m/OEe3ZNNJzbCEcagF4lNJeuhgrBSRnlitpdxICDKzCel+Z5Wbl7K9UhBN/7k2MzXBvCvSwfzzg==", + "dependencies": { + "es5-ext": "~0.9.2" + }, + "engines": { + "node": ">=0.4" + } + }, "node_modules/event-iterator": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", @@ -8993,6 +9089,15 @@ "node": ">= 6" } }, + "node_modules/formidable": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz", + "integrity": "sha512-aOskFHEfYwkSKSzGui5jhQ+uyLo2NTwpzhndggz2YZHlv0HkAi+zG5ZEBCL3GTvqLyr/FzX9Mvx9DueCmu2HzQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -9411,6 +9516,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha512-kaNz5OTAYYmt646Hkqw50/qyxP2vFnTVu5AQ1Zmk22Kk5+4Qx6BpO8+u7IKsML5fOsFk0ZT0AcCJNYwcvaLBvw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -9754,6 +9867,28 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/inquirer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.4.1.tgz", + "integrity": "sha512-q+Im4T6ukccagPS1iGpVoVXA3aqYYOQGEDfGPkvGCsKPxy/WDiXX2BCJMxQqyz5AJp/sGYcnaM6YfwP2s3uxbQ==", + "dependencies": { + "async": "~0.2.8", + "cli-color": "~0.2.2", + "lodash": "~2.4.1", + "mute-stream": "0.0.4", + "readline2": "~0.1.0", + "through": "~2.3.4" + } + }, + "node_modules/inquirer/node_modules/lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha512-Kak1hi6/hYHGVPmdyiZijoQyz5x2iGVzs6w9GYB/HiXEtylY7tIoYEROMjvM1d9nXJqPOrG2MNPMn01bJ+S0Rw==", + "engines": [ + "node", + "rhino" + ] + }, "node_modules/interface-datastore": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-7.0.1.tgz", @@ -11655,6 +11790,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/memoizee": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.2.6.tgz", + "integrity": "sha512-0VZI0btwyGk6FSDnJGuJtso4M/eSxhVb5ID5AZNWMFFgT2LexCV18hHI764V4ELKlyfnQ5KMQ+q5H3uvFN3MLw==", + "dependencies": { + "es5-ext": "~0.9.2", + "event-emitter": "~0.2.2", + "next-tick": "0.1.x" + }, + "engines": { + "node": ">=0.4" + } + }, "node_modules/meow": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", @@ -11730,6 +11878,19 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/methods/-/methods-0.0.1.tgz", + "integrity": "sha512-pB8oFfci/xcfUgM6DTxc7lbTKifPPgs3mZUOsEgaH+1TTWpmcmv3sHl+5sUHIj2X2W8aPYa2+nJealRHK+Lo6A==" + }, + "node_modules/micro-engine": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/micro-engine/-/micro-engine-0.0.1.tgz", + "integrity": "sha512-HdhhNwLLq3Kk5pwKo3x8sS8x6MZDnMq48kMkWzK10/hCJLptUWMVGAFqk3q4qFcdCW4A/qFDw6om7Vaw6FdSEQ==", + "dependencies": { + "should": "~2.1.1" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -12062,6 +12223,11 @@ "npm": ">=7.0.0" } }, + "node_modules/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-amvrY4m/7oZamehMoFi1tbwU/kXbVvRTGM2S7F+PZi3n51Jx+9AcSQ3EQsag3tR+hS2higfgOP/Kl8kri/X52A==" + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -12137,6 +12303,14 @@ "node": ">= 0.4.0" } }, + "node_modules/next-tick": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.1.0.tgz", + "integrity": "sha512-I44QWeGCHJTx2D3buhnljvSjmPgJua3zdPGtlCQEvA45t9kS/CaHnlVqidTzHwq8LGXhD2SMezjk4hQgP+32Lg==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -13842,6 +14016,14 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz", + "integrity": "sha512-n7wA/f30O3SsOw2BVkGUDzjWMw7kXvQJWKtDdgfq5HJvDoad+Jbc6osN1AQ0Iain5plo9e7Cs5fE+xR+DVkPTw==", + "engines": { + "node": "*" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -14081,6 +14263,37 @@ "node": ">=8.10.0" } }, + "node_modules/readline2": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "integrity": "sha512-qs8GGG+hLGMaDOGjd+mDglDoYcHDkjIY7z5RU0/ApsGT0qypyrWskNeemUqD+UxIXiZoMYT5aLwGp4ehoyZhIg==", + "dependencies": { + "mute-stream": "0.0.4", + "strip-ansi": "^2.0.1" + } + }, + "node_modules/readline2/node_modules/ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha512-q5i8bFLg2wDfsuR56c1NzlJFPzVD+9mxhDrhqOGigEFa87OZHlF+9dWeGWzVTP/0ECiA/JUGzfzRr2t3eYORRw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readline2/node_modules/strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha512-2h8q2CP3EeOhDJ+jd932PRMpa3/pOJFGoF22J1U/DNbEK2gSW2DqeF46VjCXsSQXhC+k/l8/gaaRBQKL6hUPfQ==", + "dependencies": { + "ansi-regex": "^1.0.0" + }, + "bin": { + "strip-ansi": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -14110,6 +14323,11 @@ "node": ">=8" } }, + "node_modules/reduce-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz", + "integrity": "sha512-y0wyCcdQul3hI3xHfIs0vg/jSbboQc/YTOAqaxjFG7At+XSexduuOqBVL9SmOLSwa/ldkbzVzdwuk9s2EKTAZg==" + }, "node_modules/reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", @@ -14614,6 +14832,14 @@ "node": ">=8" } }, + "node_modules/should": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/should/-/should-2.1.1.tgz", + "integrity": "sha512-w9EBOxgQMNmWxqPgjaCOz21FcuYepdNjTGxw0EyIvibY1CdB4UqHjBqEvN5xj5B+tzwrndTaNFwp79yX2E1cFw==", + "engines": { + "node": ">= 0.2.0" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -15449,6 +15675,72 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/sudo-block": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/sudo-block/-/sudo-block-0.3.0.tgz", + "integrity": "sha512-Jv0WZsbu61SeFqeIVF6hSLnXELZafaxWLESVKt1XUW4UPMVccmE3n2ojL39OkbgjRnaYe7qHP7APJobeDxvMDw==", + "dependencies": { + "chalk": "~0.3.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sudo-block/node_modules/ansi-styles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-0.2.0.tgz", + "integrity": "sha512-YyQBeLj0juxUC9uUXRpQ1ZAzPT1dnsn5vVeJLHYFq4Ct1p0rymUSyvckKCXCH9I0bh3jWDIETA5nXIaZVKlDyA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sudo-block/node_modules/chalk": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.3.0.tgz", + "integrity": "sha512-OcfgS16PHpCu2Q4TNMtk0aZNx8PyeNiiB+6AgGH91fhT9hJ3v6pIIJ3lxlaOEDHlTm8t3wDe6bDGamvtIokQTg==", + "dependencies": { + "ansi-styles": "~0.2.0", + "has-color": "~0.1.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/superagent": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-0.16.0.tgz", + "integrity": "sha512-/CJzCPSwbwEK1DJOllhcUHy7/4yuKiWOI5gvvyS38Dz8ZortROdYSrxJSB0f+1kPsOLentwnB61obWpRsro5+A==", + "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", + "dependencies": { + "cookiejar": "1.3.0", + "debug": "~0.7.2", + "emitter-component": "1.0.0", + "formidable": "1.0.14", + "methods": "0.0.1", + "mime": "1.2.5", + "qs": "0.6.5", + "reduce-component": "1.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha512-EohAb3+DSHSGx8carOSKJe8G0ayV5/i609OD0J2orCkuyae7SyZSz2aoLmQF2s0Pj5gITDebwPH7GFBlqOUQ1Q==", + "engines": { + "node": "*" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.5.tgz", + "integrity": "sha512-QfwTOA+zRHSZXxl9Y7ue5ifKDhU1prnh0dO67Vgcl7Lcx0+79vL9A1ln0qtVur8CFSdYq5Zhnw9DDZQgwDh8Ng==", + "engines": { + "node": "*" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -15708,8 +16000,7 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "node_modules/timeout-abort-controller": { "version": "3.0.0", @@ -17520,9 +17811,9 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "engines": { "node": ">=8.3.0" }, diff --git a/package.json b/package.json index 4601cea6..63ff357f 100644 --- a/package.json +++ b/package.json @@ -41,33 +41,34 @@ "@libp2p/websockets": "^5.0.2", "@multiformats/multiaddr": "^11.0.3", "@rosen-bridge/abstract-notification": "^0.2.1", - "@rosen-bridge/asset-check": "^0.2.1", - "@rosen-bridge/discord-notification": "^0.1.2", - "@rosen-bridge/evm-address-tx-extractor": "^1.0.3", - "@rosen-bridge/evm-rpc-scanner": "^1.0.3", - "@rosen-bridge/health-check": "^5.0.0", - "@rosen-bridge/log-level-check": "^0.1.1", - "@rosen-bridge/minimum-fee": "^2.1.0", - "@rosen-bridge/node-sync-check": "^0.1.1", - "@rosen-bridge/p2p-network-check": "^0.1.1", - "@rosen-bridge/scanner": "^4.1.2", - "@rosen-bridge/scanner-sync-check": "^0.3.0", + "@rosen-bridge/asset-check": "^1.0.3", + "@rosen-bridge/discord-notification": "^0.1.3", + "@rosen-bridge/evm-address-tx-extractor": "^1.0.4", + "@rosen-bridge/evm-rpc-scanner": "^1.0.4", + "@rosen-bridge/health-check": "^6.0.2", + "@rosen-bridge/log-level-check": "^1.0.2", + "@rosen-bridge/minimum-fee": "^2.2.0", + "@rosen-bridge/node-sync-check": "^1.0.2", + "@rosen-bridge/p2p-network-check": "^1.0.2", + "@rosen-bridge/scanner": "^4.1.3", + "@rosen-bridge/scanner-sync-check": "^1.0.2", "@rosen-bridge/tokens": "^1.2.1", "@rosen-bridge/tss": "^3.0.1", - "@rosen-bridge/watcher-data-extractor": "^8.0.1", + "@rosen-bridge/tx-progress-check": "^1.0.0", + "@rosen-bridge/watcher-data-extractor": "^8.0.2", "@rosen-bridge/winston-logger": "0.2.1", - "@rosen-chains/abstract-chain": "^9.0.1", - "@rosen-chains/bitcoin": "^5.0.1", - "@rosen-chains/bitcoin-esplora": "^4.0.1", - "@rosen-chains/cardano": "^9.0.1", - "@rosen-chains/cardano-blockfrost-network": "^7.0.1", - "@rosen-chains/cardano-koios-network": "^10.0.1", - "@rosen-chains/ergo": "^9.0.1", - "@rosen-chains/ergo-explorer-network": "^9.0.1", - "@rosen-chains/ergo-node-network": "^9.0.1", - "@rosen-chains/ethereum": "^0.1.5", - "@rosen-chains/evm": "^4.0.1", - "@rosen-chains/evm-rpc": "^2.1.2", + "@rosen-chains/abstract-chain": "^9.0.2", + "@rosen-chains/bitcoin": "^5.0.2", + "@rosen-chains/bitcoin-esplora": "^4.0.2", + "@rosen-chains/cardano": "^9.0.2", + "@rosen-chains/cardano-blockfrost-network": "^7.0.2", + "@rosen-chains/cardano-koios-network": "^10.0.2", + "@rosen-chains/ergo": "^9.0.2", + "@rosen-chains/ergo-explorer-network": "^9.0.2", + "@rosen-chains/ergo-node-network": "^9.0.2", + "@rosen-chains/ethereum": "^0.1.6", + "@rosen-chains/evm": "^4.0.2", + "@rosen-chains/evm-rpc": "^2.1.3", "@sinclair/typebox": "^0.30.4", "await-semaphore": "^0.1.3", "axios": "^1.6.8", diff --git a/src/api/generalInfo.ts b/src/api/generalInfo.ts index 331795c8..c44c3202 100644 --- a/src/api/generalInfo.ts +++ b/src/api/generalInfo.ts @@ -79,13 +79,18 @@ const infoRoute = (server: FastifySeverInstance) => { }, }); } + const healthCheck = await getHealthCheck(); + const healthStatus = await healthCheck.getOverallHealthStatus(); + const trialErrors = await healthCheck.getTrialErrors(); reply.status(200).send({ // TODO: Update dependencies like typescript and vitest // local:ergo/rosen-bridge/guard-service#364 version: Utils.readJsonFile('./package.json').version, - health: (await (await getHealthCheck()).getOverallHealthStatus()) - .status, + health: { + status: healthStatus, + trialErrors: trialErrors, + }, rsnTokenId: rosenConfig.RSN, emissionTokenId: GuardsErgoConfigs.emissionTokenId, balances: balances, diff --git a/src/api/healthCheck.ts b/src/api/healthCheck.ts index ad1efed0..9c2d713f 100644 --- a/src/api/healthCheck.ts +++ b/src/api/healthCheck.ts @@ -22,11 +22,11 @@ const healthStatusRoute = (server: FastifySeverInstance) => { }, }, async (request, reply) => { - const result = await ( - await (await getHealthCheck()).getHealthStatus() - ).map((status) => ({ + const health = await getHealthCheck(); + const result = (await health.getHealthStatus()).map((status) => ({ ...status, lastCheck: status.lastCheck?.toISOString(), + lastTrialErrorTime: status.lastTrialErrorTime?.toISOString(), })); reply.status(200).send(result); } @@ -51,14 +51,18 @@ const healthStatusForParameterRoute = (server: FastifySeverInstance) => { }, async (request, reply) => { const health = await getHealthCheck(); - const status = await health.getHealthStatusFor(request.params.paramId); + const status = await health.getHealthStatusWithParamId( + request.params.paramId + ); if (!status) throw new Error( `Health parameter with id '${request.params.paramId}' is not registered.` ); - reply - .status(200) - .send({ ...status, lastCheck: status.lastCheck!.toISOString() }); + reply.status(200).send({ + ...status, + lastCheck: status.lastCheck?.toISOString(), + lastTrialErrorTime: status.lastTrialErrorTime?.toISOString(), + }); } ); }; @@ -83,14 +87,18 @@ const updateHealthStatusForParameterRoute = (server: FastifySeverInstance) => { async (request, reply) => { const health = await getHealthCheck(); await health.updateParam(request.params.paramId); - const status = await health.getHealthStatusFor(request.params.paramId); + const status = await health.getHealthStatusWithParamId( + request.params.paramId + ); if (!status) throw new Error( `Health parameter with id '${request.params.paramId}' is not registered.` ); - reply - .status(200) - .send({ ...status, lastCheck: status.lastCheck!.toISOString() }); + reply.status(200).send({ + ...status, + lastCheck: status.lastCheck?.toISOString(), + lastTrialErrorTime: status.lastTrialErrorTime?.toISOString(), + }); } ); }; diff --git a/src/api/schemas.ts b/src/api/schemas.ts index babb8f4d..f1dd7dc1 100644 --- a/src/api/schemas.ts +++ b/src/api/schemas.ts @@ -53,7 +53,10 @@ export const OutputItemsSchema = ( export const InfoResponseSchema = Type.Object({ version: Type.String(), - health: Type.String(), + health: Type.Object({ + status: Type.String(), + trialErrors: Type.Array(Type.String()), + }), rsnTokenId: Type.String(), emissionTokenId: Type.String(), balances: LockBalanceSchema, @@ -61,9 +64,13 @@ export const InfoResponseSchema = Type.Object({ export const HealthStatusTypeSchema = Type.Object({ id: Type.String(), + title: Type.String(), + description: Type.String(), status: Type.Enum(HealthStatusLevel), - description: Type.Optional(Type.String()), lastCheck: Type.Optional(Type.String()), + lastTrialErrorMessage: Type.Optional(Type.String()), + lastTrialErrorTime: Type.Optional(Type.String()), + details: Type.Optional(Type.String()), }); export const RevenueHistoryQuerySchema = Type.Object({ diff --git a/src/configs/Configs.ts b/src/configs/Configs.ts index c8026d42..82ca812c 100644 --- a/src/configs/Configs.ts +++ b/src/configs/Configs.ts @@ -236,8 +236,6 @@ class Configs { this.logs = clonedLogs; } - static discordWebHookUrl = config.get('discordWebHookUrl'); - // Database Configs static dbType = getOptionalConfig('database.type', ''); static dbPath = getOptionalConfig('database.path', ''); @@ -276,13 +274,27 @@ class Configs { static btcCriticalThreshold = BigInt( config.get('healthCheck.asset.btc.criticalThreshold') ); + static ethWarnThreshold = BigInt( + config.get('healthCheck.asset.eth.warnThreshold') + ); + static ethCriticalThreshold = BigInt( + config.get('healthCheck.asset.eth.criticalThreshold') + ); static ergoScannerWarnDiff = getConfigIntKeyOrDefault( 'healthCheck.ergoScanner.warnDifference', - 2 + 5 ); static ergoScannerCriticalDiff = getConfigIntKeyOrDefault( 'healthCheck.ergoScanner.criticalDifference', - 100 + 20 + ); + static ethereumScannerWarnDiff = getConfigIntKeyOrDefault( + 'healthCheck.ethereumScanner.warnDifference', + 5 + ); + static ethereumScannerCriticalDiff = getConfigIntKeyOrDefault( + 'healthCheck.ethereumScanner.criticalDifference', + 20 ); static ergoNodeMaxHeightDiff = getConfigIntKeyOrDefault( 'healthCheck.ergoNode.maxHeightDifference', @@ -312,12 +324,35 @@ class Configs { ); static p2pBrokenTimeAllowed = getConfigIntKeyOrDefault('p2p.brokenTimeAllowed', 1200) * 1000; + static txSignFailedWarnThreshold = getConfigIntKeyOrDefault( + 'healthCheck.txSignFailed.warnThreshold', + 3 + ); + static txSignFailedCriticalThreshold = getConfigIntKeyOrDefault( + 'healthCheck.txSignFailed.criticalThreshold', + 7 + ); // Revenue Config static revenueUpdateInterval = getConfigIntKeyOrDefault( 'revenue.interval', 120 ); + + // Notification Configs + static discordWebHookUrl = config.get('discordWebHookUrl'); + static historyCleanupThreshold = config.get( + 'notification.historyCleanupThreshold' + ); + static hasBeenUnstableForAWhileWindowDuration = config.get( + 'notification.windowDurations.hasBeenUnstableForAWhile' + ); + static hasBeenUnknownForAWhileWindowDuration = config.get( + 'notification.windowDurations.hasBeenUnknownForAWhile' + ); + static isStillUnhealthyWindowDuration = config.get( + 'notification.windowDurations.isStillUnhealthy' + ); } export default Configs; diff --git a/src/db/DatabaseAction.ts b/src/db/DatabaseAction.ts index 64ce4964..878a99ec 100644 --- a/src/db/DatabaseAction.ts +++ b/src/db/DatabaseAction.ts @@ -27,17 +27,20 @@ import { RevenueView } from './entities/revenueView'; import { RevenueChartView } from './entities/revenueChartView'; import { ImpossibleBehavior, + NotFoundError, PaymentTransaction, TransactionType, } from '@rosen-chains/abstract-chain'; import WinstonLogger from '@rosen-bridge/winston-logger'; import { EventView } from './entities/EventView'; +import { BlockEntity, PROCEED } from '@rosen-bridge/scanner'; const logger = WinstonLogger.getInstance().getLogger(import.meta.url); class DatabaseAction { private static instance: DatabaseAction; dataSource: DataSource; + BlockRepository: Repository; CommitmentRepository: Repository; EventRepository: Repository; ConfirmedEventRepository: Repository; @@ -51,6 +54,7 @@ class DatabaseAction { protected constructor(dataSource: DataSource) { this.dataSource = dataSource; + this.BlockRepository = this.dataSource.getRepository(BlockEntity); this.CommitmentRepository = this.dataSource.getRepository(CommitmentEntity); this.EventRepository = this.dataSource.getRepository(EventTriggerEntity); this.ConfirmedEventRepository = @@ -792,6 +796,22 @@ class DatabaseAction { .orderBy('commitment."spendIndex"', 'ASC') .getMany(); }; + + /** + * @param scannerName + * @return the last block height of the given scanner + */ + getLastSavedBlockForScanner = async ( + scannerName: string + ): Promise => { + const lastBlock = await this.BlockRepository.find({ + where: { status: PROCEED, scanner: scannerName }, + order: { height: 'DESC' }, + take: 1, + }); + if (lastBlock.length !== 0) return lastBlock[0].height; + throw new NotFoundError(`No block found in database`); + }; } export { DatabaseAction }; diff --git a/src/guard/HealthCheck.ts b/src/guard/HealthCheck.ts index 94a61fc3..0d4469f8 100644 --- a/src/guard/HealthCheck.ts +++ b/src/guard/HealthCheck.ts @@ -4,6 +4,7 @@ import { CardanoKoiosAssetHealthCheckParam, ErgoExplorerAssetHealthCheckParam, ErgoNodeAssetHealthCheckParam, + EthereumRpcAssetHealthCheckParam, } from '@rosen-bridge/asset-check'; import { HealthCheck, HealthStatusLevel } from '@rosen-bridge/health-check'; import { LogLevelHealthCheck } from '@rosen-bridge/log-level-check'; @@ -12,6 +13,7 @@ import { P2PNetworkHealthCheck } from '@rosen-bridge/p2p-network-check'; import { ErgoExplorerScannerHealthCheck, ErgoNodeScannerHealthCheck, + EthereumRPCScannerHealthCheck, } from '@rosen-bridge/scanner-sync-check'; import WinstonLogger from '@rosen-bridge/winston-logger'; @@ -26,11 +28,19 @@ import Configs from '../configs/Configs'; import GuardsCardanoConfigs from '../configs/GuardsCardanoConfigs'; import GuardsErgoConfigs from '../configs/GuardsErgoConfigs'; import { rosenConfig } from '../configs/RosenConfig'; -import { dataSource } from '../db/dataSource'; import GuardPkHandler from '../handlers/GuardPkHandler'; import { ADA_DECIMALS, ERG_DECIMALS } from '../utils/constants'; import GuardsBitcoinConfigs from '../configs/GuardsBitcoinConfigs'; -import { BITCOIN_CHAIN } from '@rosen-chains/bitcoin'; +import { BITCOIN_CHAIN, BTC } from '@rosen-chains/bitcoin'; +import { DatabaseAction } from '../db/DatabaseAction'; +import { NotFoundError } from '@rosen-chains/abstract-chain'; +import { NotificationHandler } from '../handlers/NotificationHandler'; +import { + TxInfo, + TxProgressHealthCheckParam, +} from '@rosen-bridge/tx-progress-check'; +import GuardsEthereumConfigs from '../configs/GuardsEthereumConfigs'; +import { ETH, ETHEREUM_CHAIN } from '@rosen-chains/ethereum'; const logger = WinstonLogger.getInstance().getLogger(import.meta.url); let healthCheck: HealthCheck | undefined; @@ -41,8 +51,30 @@ let healthCheck: HealthCheck | undefined; */ const getHealthCheck = async () => { if (!healthCheck) { - healthCheck = new HealthCheck(); + // initialize HealthCheck + const notificationHandler = NotificationHandler.getInstance(); + const notificationConfig = { + historyConfig: { + cleanupThreshold: Configs.historyCleanupThreshold, + }, + notificationCheckConfig: { + hasBeenUnstableForAWhile: { + windowDuration: Configs.hasBeenUnstableForAWhileWindowDuration, + }, + hasBeenUnknownForAWhile: { + windowDuration: Configs.hasBeenUnknownForAWhileWindowDuration, + }, + isStillUnhealthy: { + windowDuration: Configs.isStillUnhealthyWindowDuration, + }, + }, + }; + healthCheck = new HealthCheck( + notificationHandler.notify, + notificationConfig + ); + // add LogLevel param const errorLogHealthCheck = new LogLevelHealthCheck( logger, HealthStatusLevel.UNSTABLE, @@ -51,8 +83,9 @@ const getHealthCheck = async () => { 'error' ); healthCheck.register(errorLogHealthCheck); - const dialer = await Dialer.getInstance(); + // add P2PNetwork param + const dialer = await Dialer.getInstance(); const p2pHealthCheck = new P2PNetworkHealthCheck({ defectConfirmationTimeWindow: Configs.p2pDefectConfirmationTimeWindow, connectedGuardsHealthyThreshold: @@ -67,9 +100,46 @@ const getHealthCheck = async () => { }); healthCheck.register(p2pHealthCheck); + // add TxProgress param + const getActiveTransactions = async (): Promise => { + return (await DatabaseAction.getInstance().getActiveTransactions()).map( + (txEntity) => ({ + txId: txEntity.txId, + txType: txEntity.type, + signFailedCount: txEntity.signFailedCount, + chain: txEntity.chain, + eventId: txEntity.event.id, + }) + ); + }; + const txProgressHealthCheck = new TxProgressHealthCheckParam( + getActiveTransactions, + Configs.txSignFailedWarnThreshold, + Configs.txSignFailedCriticalThreshold + ); + healthCheck.register(txProgressHealthCheck); + const ergoContracts = rosenConfig.contractReader(ERGO_CHAIN); const cardanoContracts = rosenConfig.contractReader(CARDANO_CHAIN); const bitcoinContracts = rosenConfig.contractReader(BITCOIN_CHAIN); + const ethereumContracts = rosenConfig.contractReader(ETHEREUM_CHAIN); + + const generateLastBlockFetcher = (scannerName: string) => { + return async () => { + try { + return await DatabaseAction.getInstance().getLastSavedBlockForScanner( + scannerName + ); + } catch (e) { + if (e instanceof NotFoundError) { + logger.info( + `No block found in database. Passing 0 as last height to HealthCheck` + ); + return 0; + } else throw e; + } + }; + }; if (GuardsErgoConfigs.chainNetworkName === NODE_NETWORK) { const ergAssetHealthCheck = new ErgoNodeAssetHealthCheckParam( @@ -94,9 +164,10 @@ const getHealthCheck = async () => { ); healthCheck.register(emissionTokenAssetHealthCheck); + const scannerName = 'ergo-node'; const ergoScannerSyncCheck = new ErgoNodeScannerHealthCheck( - dataSource, - 'ergo-node', + generateLastBlockFetcher(scannerName), + scannerName, Configs.ergoScannerWarnDiff, Configs.ergoScannerCriticalDiff, GuardsErgoConfigs.node.url @@ -135,9 +206,10 @@ const getHealthCheck = async () => { ); healthCheck.register(emissionTokenAssetHealthCheck); + const scannerName = 'ergo-explorer'; const ergoScannerSyncCheck = new ErgoExplorerScannerHealthCheck( - dataSource, - 'ergo-explorer', + generateLastBlockFetcher(scannerName), + scannerName, Configs.ergoScannerWarnDiff, Configs.ergoScannerCriticalDiff, GuardsErgoConfigs.explorer.url @@ -177,7 +249,7 @@ const getHealthCheck = async () => { } if (GuardsBitcoinConfigs.chainNetworkName === 'esplora') { const btcAssetHealthCheck = new BitcoinEsploraAssetHealthCheckParam( - 'BTC', + BTC, bitcoinContracts.lockAddress, Configs.btcWarnThreshold, Configs.btcCriticalThreshold, @@ -186,6 +258,30 @@ const getHealthCheck = async () => { ); healthCheck.register(btcAssetHealthCheck); } + if (GuardsEthereumConfigs.chainNetworkName === 'rpc') { + const ethAssetHealthCheck = new EthereumRpcAssetHealthCheckParam( + ETH, + ETH, + ethereumContracts.lockAddress, + Configs.ethWarnThreshold, + Configs.ethCriticalThreshold, + GuardsEthereumConfigs.rpc.url, + 8 + ); + healthCheck.register(ethAssetHealthCheck); + + const scannerName = 'ethereum-evm-rpc'; + const ethereumScannerSyncCheck = new EthereumRPCScannerHealthCheck( + generateLastBlockFetcher(scannerName), + scannerName, + Configs.ethereumScannerWarnDiff, + Configs.ethereumScannerCriticalDiff, + GuardsEthereumConfigs.rpc.url, + GuardsEthereumConfigs.rpc.authToken, + GuardsEthereumConfigs.rpc.timeout + ); + healthCheck.register(ethereumScannerSyncCheck); + } } return healthCheck; diff --git a/src/jobs/healthCheck.ts b/src/jobs/healthCheck.ts index d3664664..ec7ca775 100644 --- a/src/jobs/healthCheck.ts +++ b/src/jobs/healthCheck.ts @@ -13,7 +13,9 @@ const healthCheckUpdateJob = async (healthCheck: HealthCheck) => { // TODO: remove this part after fixing p2p problem // local:ergo/rosen-bridge/p2p#11 if (Configs.p2pBrokenTimeAllowed !== 0) { - const status = await healthCheck.getHealthStatusFor('P2P Network'); + const status = await healthCheck.getHealthStatusWithParamId( + 'P2P Network' + ); if (status?.status === HealthStatusLevel.BROKEN) { const diff = Date.now() - lastP2pUp; if (diff > Configs.p2pBrokenTimeAllowed) { diff --git a/tests/api/generalInfo.spec.ts b/tests/api/generalInfo.spec.ts index 68ffeed2..78bb8fdf 100644 --- a/tests/api/generalInfo.spec.ts +++ b/tests/api/generalInfo.spec.ts @@ -1,3 +1,4 @@ +import { HealthStatusLevel } from '@rosen-bridge/health-check'; import { AssetBalance } from '@rosen-chains/abstract-chain'; import { BITCOIN_CHAIN } from '@rosen-chains/bitcoin'; import { CARDANO_CHAIN } from '@rosen-chains/cardano'; @@ -39,11 +40,13 @@ describe('generalInfo', () => { * @target fastifyServer[GET /info] should return general info of the guard correctly * @dependencies * - ChainHandler + * - HealthCheck * @scenario * - mock ChainHandler * - mock Ergo functions * - mock Cardano functions * - mock Bitcoin functions + * - mock healthCheck * - send a request to the server * - check the result * @expected @@ -126,6 +129,18 @@ describe('generalInfo', () => { GuardsBitcoinConfigs.chainConfigs ); + // mock healthCheck + vi.mock('../../src/guard/HealthCheck', () => { + return { + getHealthCheck: vi.fn().mockResolvedValue({ + getOverallHealthStatus: vi + .fn() + .mockResolvedValue(HealthStatusLevel.HEALTHY), + getTrialErrors: vi.fn().mockResolvedValue([]), + }), + }; + }); + // send a request to the server const result = await mockedServer.inject({ method: 'GET', diff --git a/tests/api/testData.ts b/tests/api/testData.ts index 01bad33d..427799f2 100644 --- a/tests/api/testData.ts +++ b/tests/api/testData.ts @@ -9,7 +9,10 @@ import { BITCOIN_CHAIN } from '@rosen-chains/bitcoin'; export const guardInfo = { version: expect.any(String), - health: HealthStatusLevel.HEALTHY, + health: { + status: HealthStatusLevel.HEALTHY, + trialErrors: [], + }, balances: { hot: [ {