diff --git a/.changeset/heavy-bottles-cheat.md b/.changeset/hungry-eyes-grin.md similarity index 100% rename from .changeset/heavy-bottles-cheat.md rename to .changeset/hungry-eyes-grin.md diff --git a/.changeset/rich-queens-greet.md b/.changeset/rich-queens-greet.md new file mode 100644 index 0000000..a845151 --- /dev/null +++ b/.changeset/rich-queens-greet.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/CHANGELOG.md b/CHANGELOG.md index 932dfe3..7fc219f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # @rosen-bridge/watcher +## 4.1.0 + +### Minor Changes + +- Integrate binance + +### Patch Changes + +- Add environment variables for bitcoin rpc connection +- Use @rosen-bridge/extended-typeorm to prevent db transaction conflicts +- Fix commitment redeem job bug +- Fix required commitment count to match with the smart contract computations + ## 4.0.3 ### Patch Changes diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/README.md b/README.md index 5e07bea..442c070 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,7 @@ - [Run in production mode](#run-in-production-mode) - [Config](#config) - [How to Be a Watcher](#how-to-be-a-watcher) -- [Contributing](#contributing) -- [License](#license) +- [License](./LICENSE) ## Description @@ -47,12 +46,4 @@ You can find the project configs here. In this config, you should set what netwo ## How to Be a Watcher -TBD - -## Contributing - -TBD - -## License - -TBD +Check our operation documentation [here](https://github.com/rosen-bridge/operation/blob/dev/docs/watcher/deploy-docker.md#watcher-deployment). diff --git a/config/dataSource.ts b/config/dataSource.ts index 2894d8d..7247fef 100644 --- a/config/dataSource.ts +++ b/config/dataSource.ts @@ -18,7 +18,7 @@ import { PermitEntity, CollateralEntity, } from '@rosen-bridge/watcher-data-extractor'; -import { DataSource } from 'typeorm'; +import { DataSource } from '@rosen-bridge/extended-typeorm'; import { getConfig } from '../src/config/config'; import { ObservationStatusEntity } from '../src/database/entities/observationStatusEntity'; diff --git a/config/default.yaml b/config/default.yaml index 41048ca..a64ab69 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -15,6 +15,8 @@ bitcoin: interval: 180 # rpc scanning interval (in seconds) timeout: 10 # rpc request timeout (in seconds) url: '' # rpc url + # username: '' # rpc username for authentication required instances + # password: '' # rpc password for authentication required instances cardano: type: '' # options: koios, ogmios, blockfrost initial: @@ -25,6 +27,7 @@ cardano: interval: 20 # koios scanning interval (in seconds) timeout: 10 # koios request timeout (in seconds) url: 'https://api.koios.rest/api/v1' # koios url + # authToken: # rpc auth token ogmios: host: '' # ogmios node host address port: 1337 # ogmios port @@ -43,6 +46,16 @@ ethereum: url: '' # rpc url interval: 20 # rpc scanning interval (in seconds) timeout: 10 # rpc request timeout (in seconds) + # authToken: # rpc auth token +binance: + type: '' # options: rpc + initial: + height: -1 # initial height of scanning + rpc: + url: '' # rpc url + interval: 20 # rpc scanning interval (in seconds) + timeout: 10 # rpc request timeout (in seconds) + # authToken: # rpc auth token ergo: network: 'Mainnet' # ergo network type. testnet or mainnet type: 'node' # ergo scanner type. options: node, explorer @@ -117,6 +130,9 @@ healthCheck: ethereumScanner: warnDifference: 40 # warning difference between existing and scanned blocks height criticalDifference: 160 # critical difference between existing and scanned blocks height + binanceScanner: + warnDifference: 160 # warning difference between existing and scanned blocks height + criticalDifference: 640 # critical difference between existing and scanned blocks height permit: warnCommitmentCount: 4 # warning remaining permits for creating commitment criticalCommitmentCount: 0 # critical remaining permits for creating commitment @@ -124,7 +140,6 @@ healthCheck: duration: 600 # log duration time check (in seconds) maxAllowedErrorCount: 1 # maximum allowed error log lines maxAllowedWarnCount: 10 # maximum allowed warn log lines -redeemSwapEnabled: true # if set true when no permit left, system automatically redeem new commitments and commit again for old observations rewardCollection: threshold: 100000 # RSN threshold for reward collection interval: 600 # reward collection interval in seconds diff --git a/docker/custom-environment-variables.yaml b/docker/custom-environment-variables.yaml index 980bb15..9618979 100644 --- a/docker/custom-environment-variables.yaml +++ b/docker/custom-environment-variables.yaml @@ -10,6 +10,10 @@ database: name: 'POSTGRES_DB' ergo: mnemonic: 'MNEMONIC' +bitcoin: + rpc: + username: 'BITCOIN_RPC_USERNAME' + password: 'BITCOIN_RPC_PASSWORD' cardano: koios: authToken: 'KOIOS_AUTH_TOKEN' @@ -18,4 +22,7 @@ cardano: ethereum: rpc: authToken: 'ETHEREUM_RPC_AUTH_TOKEN' +binance: + rpc: + authToken: 'BINANCE_RPC_AUTH_TOKEN' overrideLokiBasicAuth: 'OVERRIDE_LOKI_BASIC_AUTH' diff --git a/package-lock.json b/package-lock.json index b16af87..a106391 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,36 +1,37 @@ { "name": "@rosen-bridge/watcher", - "version": "4.0.3", + "version": "4.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@rosen-bridge/watcher", - "version": "4.0.3", + "version": "4.1.0", "hasInstallScript": true, "license": "ISC", "dependencies": { "@emurgo/cip14-js": "^3.0.1", "@rosen-bridge/abstract-logger": "^2.0.1", - "@rosen-bridge/address-extractor": "^5.0.7", - "@rosen-bridge/asset-check": "^1.0.4", - "@rosen-bridge/bitcoin-esplora-scanner": "^0.1.14", - "@rosen-bridge/bitcoin-observation-extractor": "^4.0.7", - "@rosen-bridge/bitcoin-rpc-scanner": "^0.2.8", + "@rosen-bridge/address-extractor": "^5.0.8", + "@rosen-bridge/asset-check": "^2.0.0", + "@rosen-bridge/bitcoin-esplora-scanner": "^1.0.0", + "@rosen-bridge/bitcoin-observation-extractor": "^4.0.10", + "@rosen-bridge/bitcoin-rpc-scanner": "^1.0.0", "@rosen-bridge/discord-notification": "^0.1.3", - "@rosen-bridge/evm-observation-extractor": "^3.0.5", - "@rosen-bridge/evm-rpc-scanner": "^1.0.4", - "@rosen-bridge/health-check": "6.0.3", - "@rosen-bridge/log-level-check": "^1.0.3", + "@rosen-bridge/evm-observation-extractor": "3.1.2", + "@rosen-bridge/evm-rpc-scanner": "^2.0.0", + "@rosen-bridge/extended-typeorm": "^0.0.3", + "@rosen-bridge/health-check": "6.0.4", + "@rosen-bridge/log-level-check": "^1.0.4", "@rosen-bridge/minimum-fee": "^2.2.2", - "@rosen-bridge/node-sync-check": "^1.0.3", - "@rosen-bridge/observation-extractor": "^5.0.7", - "@rosen-bridge/permit-check": "^1.0.3", - "@rosen-bridge/scanner": "^4.1.3", - "@rosen-bridge/scanner-sync-check": "^1.0.3", + "@rosen-bridge/node-sync-check": "^1.0.4", + "@rosen-bridge/observation-extractor": "^5.0.10", + "@rosen-bridge/permit-check": "^1.0.4", + "@rosen-bridge/scanner": "^5.0.0", + "@rosen-bridge/scanner-sync-check": "^2.0.0", "@rosen-bridge/tokens": "^1.2.1", - "@rosen-bridge/watcher-data-extractor": "^8.0.2", - "@rosen-bridge/wid-check": "^1.0.3", + "@rosen-bridge/watcher-data-extractor": "^9.0.0", + "@rosen-bridge/wid-check": "^1.0.4", "@rosen-bridge/winston-logger": "1.0.2", "@rosen-clients/cardano-koios": "^2.0.3", "axios": "^0.26.1", @@ -2006,8 +2007,9 @@ "license": "MIT" }, "node_modules/@rosen-bridge/abstract-extractor": { - "version": "0.3.0", - "license": "GPL-3.0", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@rosen-bridge/abstract-extractor/-/abstract-extractor-0.3.1.tgz", + "integrity": "sha512-C09GpKLmaLog6hAGX63KZ4qw50vu0dV3UHil+dJUI9l6Ei7e5wNcDYR+Y2iLyOKwSG4xleF/nl0r42u+XUn+6A==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", @@ -2038,8 +2040,9 @@ } }, "node_modules/@rosen-bridge/address-codec": { - "version": "0.3.0", - "license": "GPL-3.0", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/address-codec/-/address-codec-0.4.0.tgz", + "integrity": "sha512-YjHEXDytiTw7UAfDhyKbFIvrubKQr295qf5X5PF3CQjqhRC/Po1wE+j/FLc6eRK1IU++5G8AkICH8WDuek35KQ==", "dependencies": { "@emurgo/cardano-serialization-lib-nodejs": "^11.5.0", "bitcoinjs-lib": "^6.1.5", @@ -2051,10 +2054,11 @@ } }, "node_modules/@rosen-bridge/address-extractor": { - "version": "5.0.7", - "license": "GPL-3.0", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@rosen-bridge/address-extractor/-/address-extractor-5.0.8.tgz", + "integrity": "sha512-Eg0nIgd4lzMQSm2LmaoHZr3tqnQnz7Q8VMOQ76F8MpaJRBP4KHyW2sRiGvxmbbuQqZqrOZm9SFp+CxofYBc/NA==", "dependencies": { - "@rosen-bridge/abstract-extractor": "^0.3.0", + "@rosen-bridge/abstract-extractor": "^0.3.1", "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-clients/ergo-explorer": "^1.1.1", "blakejs": "^1.2.1", @@ -2071,13 +2075,13 @@ "integrity": "sha512-hN/cb0HSlhqvaEjqzFPZGIYOa70gdPd+mYrS5C7uNrv1Vw6k2k4lY4US05rwBENjSQpwik1H4gdCBzUkbCcjGA==" }, "node_modules/@rosen-bridge/asset-check": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@rosen-bridge/asset-check/-/asset-check-1.0.4.tgz", - "integrity": "sha512-OLvCMCxfWScILNSRXcv0Iwx/3igXcwSo6nhiM7EgEWC8QDPGvv/61SdEVzCsxcWD7egf6x851j8/Bxx5i8+eaw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/asset-check/-/asset-check-2.0.0.tgz", + "integrity": "sha512-Abs8VQKXILex8/W/TDpaGaW1/2s/e8JqkWiT0tI4faUO/dI15H4MZQNOfOJOP1ZE27tIkky1r75ZelT1x0uRow==", "dependencies": { "@apollo/client": "^3.9.11", "@blockfrost/blockfrost-js": "^5.5.0", - "@rosen-bridge/health-check": "^6.0.3", + "@rosen-bridge/health-check": "^6.0.4", "@rosen-clients/cardano-koios": "^2.0.1", "@rosen-clients/ergo-explorer": "^1.1.1", "@rosen-clients/ergo-node": "^1.1.1", @@ -2124,13 +2128,12 @@ } }, "node_modules/@rosen-bridge/bitcoin-esplora-scanner": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/@rosen-bridge/bitcoin-esplora-scanner/-/bitcoin-esplora-scanner-0.1.14.tgz", - "integrity": "sha512-CV74VNVn7tPph0KPxQq0JiBtbI2RDTHUXbg2dUi98hiafFbRIF1bSw6sNWAEfI00RmNR20q7kgD7a7nO2HOiLw==", - "license": "GPL-3.0", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/bitcoin-esplora-scanner/-/bitcoin-esplora-scanner-1.0.0.tgz", + "integrity": "sha512-rlTGX9XLgEXnDVcMNY0OgtF4eAh1wU8lsnDnQrm4FgY7QR8y5h7F9/R6Vba+F2i2mG/XQpHCrZ8MrIJ6FMhXDg==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/scanner": "^4.1.3", + "@rosen-bridge/scanner": "^5.0.0", "axios": "^1.6.8" }, "engines": { @@ -2152,17 +2155,16 @@ } }, "node_modules/@rosen-bridge/bitcoin-observation-extractor": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@rosen-bridge/bitcoin-observation-extractor/-/bitcoin-observation-extractor-4.0.7.tgz", - "integrity": "sha512-mtQfx5utzCcjLR9spz07kZ+IoFscsTIJnlzEHlS8cVsZHTUejhbH4co4ceDdqsx7RYePty7XJ4TYLNObS6N8lg==", - "license": "GPL-3.0", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@rosen-bridge/bitcoin-observation-extractor/-/bitcoin-observation-extractor-4.0.10.tgz", + "integrity": "sha512-rZXuwzxFazoGbn9Vncr/Qj9Y4ug5tMa93GP2vZWTw2HE2JF+THpTS7Gc45qR8O2r1QbwnwByHj/7JVU+pzFgvQ==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/bitcoin-esplora-scanner": "^0.1.14", - "@rosen-bridge/bitcoin-rpc-scanner": "^0.2.8", - "@rosen-bridge/observation-extractor": "^5.0.7", - "@rosen-bridge/rosen-extractor": "^6.2.0", - "@rosen-bridge/tokens": "^1.2.0", + "@rosen-bridge/bitcoin-esplora-scanner": "^1.0.0", + "@rosen-bridge/bitcoin-rpc-scanner": "^1.0.0", + "@rosen-bridge/observation-extractor": "^5.0.10", + "@rosen-bridge/rosen-extractor": "^6.3.1", + "@rosen-bridge/tokens": "^1.2.1", "typeorm": "^0.3.20" }, "engines": { @@ -2175,13 +2177,12 @@ "integrity": "sha512-hN/cb0HSlhqvaEjqzFPZGIYOa70gdPd+mYrS5C7uNrv1Vw6k2k4lY4US05rwBENjSQpwik1H4gdCBzUkbCcjGA==" }, "node_modules/@rosen-bridge/bitcoin-rpc-scanner": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@rosen-bridge/bitcoin-rpc-scanner/-/bitcoin-rpc-scanner-0.2.8.tgz", - "integrity": "sha512-pOpa6ytcsqOGXkTdqwR6kmWycqAx4QWLaU4UWGpWSozJ2QrKXTXwfwb67uEuSiFL4g2zvqSJ2pSRQwaUdkBx1g==", - "license": "GPL-3.0", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/bitcoin-rpc-scanner/-/bitcoin-rpc-scanner-1.0.0.tgz", + "integrity": "sha512-gpk2fhZ7hIFHmRUTDjUHojLmChajkEajK69+H6mak6Yi0cDYweJMGttUjrNN7rv+BHQ95X2s2ANCNo2HCQ41IA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/scanner": "^4.1.3", + "@rosen-bridge/scanner": "^5.0.0", "axios": "^1.6.8" }, "engines": { @@ -2197,7 +2198,6 @@ "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -2225,15 +2225,15 @@ } }, "node_modules/@rosen-bridge/evm-observation-extractor": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@rosen-bridge/evm-observation-extractor/-/evm-observation-extractor-3.0.5.tgz", - "integrity": "sha512-WJZdAKJHMtWXWXDDgo3Q3hZDZZxFWfSr8SuKDSvmIaOOxuCZ3VbKxHJlnOmz4LtxgncXK3YT0fdNqzQ1sOne9Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@rosen-bridge/evm-observation-extractor/-/evm-observation-extractor-3.1.2.tgz", + "integrity": "sha512-+U76ddZPXrR+OOQoSg5qsHc4z9RGu7CzqEQGQTxZ3N9b0R2GuUZlOjKYrrMDRFT0H82DkB2HqSnxpXt7GXDTtg==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/evm-rpc-scanner": "^1.0.4", - "@rosen-bridge/observation-extractor": "^5.0.7", - "@rosen-bridge/rosen-extractor": "^6.2.0", - "@rosen-bridge/tokens": "^1.2.0", + "@rosen-bridge/evm-rpc-scanner": "^2.0.0", + "@rosen-bridge/observation-extractor": "^5.0.10", + "@rosen-bridge/rosen-extractor": "^6.3.1", + "@rosen-bridge/tokens": "^1.2.1", "blakejs": "^1.2.1", "ethers": "^6.11.0" }, @@ -2247,12 +2247,12 @@ "integrity": "sha512-hN/cb0HSlhqvaEjqzFPZGIYOa70gdPd+mYrS5C7uNrv1Vw6k2k4lY4US05rwBENjSQpwik1H4gdCBzUkbCcjGA==" }, "node_modules/@rosen-bridge/evm-rpc-scanner": { - "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/evm-rpc-scanner/-/evm-rpc-scanner-2.0.0.tgz", + "integrity": "sha512-EPTXRYoI2odeXGwqIJuZ6BPsn+F6Dz/7J+Mo0uX8AfzgHTPkykqav13IYs5g58feESk+SSfFAsgXUpbYoGEgnA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/scanner": "^4.1.3", + "@rosen-bridge/scanner": "^5.0.0", "ethers": "^6.11.0" } }, @@ -2273,9 +2273,9 @@ } }, "node_modules/@rosen-bridge/health-check": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/health-check/-/health-check-6.0.3.tgz", - "integrity": "sha512-ApUVEmra1XL4kP3JGGLF56zz2P50M00t2TNPx2anGYkqPoWbJtwC8UNLGiHHHkW2vzdpteWgFz4egbUjYs9i7A==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@rosen-bridge/health-check/-/health-check-6.0.4.tgz", + "integrity": "sha512-0btvlzG+3t8zFWjs75np2/6+vvS4KruHIgQU8VuOlKFU5Joacm3GekgnkIH5FPrPNO1nl8uZQLdTWVdAy7v/jA==", "dependencies": { "@rosen-bridge/abstract-notification": "^0.2.1" }, @@ -2294,12 +2294,12 @@ } }, "node_modules/@rosen-bridge/log-level-check": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/log-level-check/-/log-level-check-1.0.3.tgz", - "integrity": "sha512-ZbV8Zp4hV1nCDzgZnKZnEAkXEvmv9vpvchEnYHmhZ330JD4Yhf81vbaY8L4NMptA2YdqG59zFRcc/NsisoT30w==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rosen-bridge/log-level-check/-/log-level-check-1.0.4.tgz", + "integrity": "sha512-2Hl2vlcPTy0phFXd3TO+uUl4GOhu4kCJcwg4LsXyDbFJyZHg/cLBaj/6GmrOIEcyPpKj0nabyhhRnKxaZVB0tA==", "dependencies": { "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/health-check": "^6.0.3", + "@rosen-bridge/health-check": "^6.0.4", "lodash-es": "^4.17.21" }, "engines": { @@ -2327,11 +2327,11 @@ } }, "node_modules/@rosen-bridge/node-sync-check": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/node-sync-check/-/node-sync-check-1.0.3.tgz", - "integrity": "sha512-HtEiGvXLoQsgsTi+neM3Nsn0hcw/6Sk0dJGAaoyVr1zjUICXQnAb5FxsO4ydp07uvYMkhjAlDqFTRLc8bvh8rQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rosen-bridge/node-sync-check/-/node-sync-check-1.0.4.tgz", + "integrity": "sha512-Fn54fZtg1V8w4HPBx1FOfOqBDg8obrjgZdfZRJX/03PH1uDyIsDNKM24n07E+fUcpcxSyAUPtw1i0qSSRG0Sfw==", "dependencies": { - "@rosen-bridge/health-check": "^6.0.3", + "@rosen-bridge/health-check": "^6.0.4", "@rosen-clients/ergo-node": "^1.1.1" }, "engines": { @@ -2339,17 +2339,16 @@ } }, "node_modules/@rosen-bridge/observation-extractor": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@rosen-bridge/observation-extractor/-/observation-extractor-5.0.7.tgz", - "integrity": "sha512-CLMwnmfVrgY3YgbW6ZKHM4ySu9DEvbtTQYhq23NWLCTVUNEJmsCEe48Rx1gZjeqSKMP0Mc/gnVj58Vopj2dPYA==", - "license": "GPL-3.0", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@rosen-bridge/observation-extractor/-/observation-extractor-5.0.10.tgz", + "integrity": "sha512-rr88s9tDuzY4+Mb69NAHB4H3J3iBdLkh/gyx1jaUg08nN0l4nBoqX5icZUwSnKUQkjDb/jjDAcwjhPPKaG42eg==", "dependencies": { "@cardano-ogmios/schema": "^6.6.1", - "@rosen-bridge/abstract-extractor": "^0.3.0", + "@rosen-bridge/abstract-extractor": "^0.3.1", "@rosen-bridge/abstract-logger": "^1.0.0", - "@rosen-bridge/rosen-extractor": "^6.2.0", - "@rosen-bridge/scanner": "^4.1.3", - "@rosen-bridge/tokens": "^1.2.0", + "@rosen-bridge/rosen-extractor": "^6.3.1", + "@rosen-bridge/scanner": "^5.0.0", + "@rosen-bridge/tokens": "^1.2.1", "blakejs": "^1.2.1", "ergo-lib-wasm-nodejs": "^0.24.1", "lodash-es": "^4.17.21", @@ -2364,11 +2363,11 @@ "integrity": "sha512-hN/cb0HSlhqvaEjqzFPZGIYOa70gdPd+mYrS5C7uNrv1Vw6k2k4lY4US05rwBENjSQpwik1H4gdCBzUkbCcjGA==" }, "node_modules/@rosen-bridge/permit-check": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/permit-check/-/permit-check-1.0.3.tgz", - "integrity": "sha512-3K6b6j5W9hSTAQ/vNsjavg2lRhmVZzrcRcuJ5em6r9oE2jHKGCS8e4UBaQexTEWQBjCz4QqwCBNN+x/9/Lq2RQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rosen-bridge/permit-check/-/permit-check-1.0.4.tgz", + "integrity": "sha512-CQw82SH+C0Pry3vglnyAHCFaLWHC4BK8rPDnge8Nkht0uJXFiWLOTiXhXf5Xm8LgGveYBmmWTVg24MgqXybkhw==", "dependencies": { - "@rosen-bridge/health-check": "^6.0.3", + "@rosen-bridge/health-check": "^6.0.4", "@rosen-clients/ergo-explorer": "^1.1.1", "@rosen-clients/ergo-node": "^1.1.1", "ergo-lib-wasm-nodejs": "^0.24.1" @@ -2404,13 +2403,14 @@ } }, "node_modules/@rosen-bridge/rosen-extractor": { - "version": "6.2.0", - "license": "GPL-3.0", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@rosen-bridge/rosen-extractor/-/rosen-extractor-6.3.1.tgz", + "integrity": "sha512-NBI6I85u4DNHB3bvyNFaEIIYSCMMIY6K2DWp0rxThvcsATmAeAa54o2w9qHOeOqA3iaRiHVRp9TSkiV+bSVEug==", "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.3.0", + "@rosen-bridge/abstract-logger": "^2.0.1", + "@rosen-bridge/address-codec": "^0.4.0", "@rosen-bridge/json-bigint": "^0.1.0", "@rosen-bridge/tokens": "^1.2.1", "bitcoinjs-lib": "^6.1.5", @@ -2420,28 +2420,23 @@ "lodash-es": "^4.17.21" } }, - "node_modules/@rosen-bridge/rosen-extractor/node_modules/@rosen-bridge/abstract-logger": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@rosen-bridge/abstract-logger/-/abstract-logger-1.0.0.tgz", - "integrity": "sha512-hN/cb0HSlhqvaEjqzFPZGIYOa70gdPd+mYrS5C7uNrv1Vw6k2k4lY4US05rwBENjSQpwik1H4gdCBzUkbCcjGA==" - }, "node_modules/@rosen-bridge/scanner": { - "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==", - "license": "GPL-3.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/scanner/-/scanner-5.0.0.tgz", + "integrity": "sha512-v4ayWIBA1yEpitCCN1Y9B/BgyqxMvHj+SnXQ9nAURSgV9fW7Q7y4ijRMiXwsxft/OEe06TVJTIv8mSx/mH4CKg==", "dependencies": { "@apollo/client": "^3.8.7", "@blockfrost/blockfrost-js": "^5.4.0", "@cardano-ogmios/client": "^6.6.1", "@cardano-ogmios/schema": "^6.6.1", - "@rosen-bridge/abstract-extractor": "^0.3.0", + "@rosen-bridge/abstract-extractor": "^0.3.1", "@rosen-bridge/abstract-logger": "^1.0.0", "@rosen-bridge/json-bigint": "^0.1.0", "@rosen-clients/ergo-explorer": "^1.1.1", "@rosen-clients/ergo-node": "^1.1.1", "await-semaphore": "^0.1.3", "axios": "^1.6.8", + "cockatiel": "^3.2.1", "cross-fetch": "^4.0.0", "lodash-es": "^4.17.21", "reflect-metadata": "^0.1.13", @@ -2450,14 +2445,14 @@ } }, "node_modules/@rosen-bridge/scanner-sync-check": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/scanner-sync-check/-/scanner-sync-check-1.0.3.tgz", - "integrity": "sha512-cFt2pMzOSExUdYD0bMZKDafPn3H7rH8AGj7ih5cdvwQZggivoYhVC6AQWffgkZRNxmMuLkO7fmUFr71AInYyIw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/scanner-sync-check/-/scanner-sync-check-2.0.0.tgz", + "integrity": "sha512-oBOY9m3Zcbl00mR0Xe+lgZ34iJEuJX6B+cUYE2tQhj8ZBcuu7IHjC+LSwLA+s887RjxWcjRCxMRj5zn5aXcjcw==", "dependencies": { "@apollo/client": "^3.9.11", "@blockfrost/blockfrost-js": "^5.5.0", "@cardano-ogmios/client": "^6.3.0", - "@rosen-bridge/health-check": "^6.0.3", + "@rosen-bridge/health-check": "^6.0.4", "@rosen-clients/ergo-explorer": "^1.1.1", "@rosen-clients/ergo-node": "^1.1.1", "axios": "^1.6.8", @@ -2546,15 +2541,15 @@ "license": "GPL-3.0" }, "node_modules/@rosen-bridge/watcher-data-extractor": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@rosen-bridge/watcher-data-extractor/-/watcher-data-extractor-8.0.2.tgz", - "integrity": "sha512-pnpSbuqgCVEecCZDZrL6TthMrXPWkgpXOC5pnWFYNyjOyYlymxCrCEhW15L8hahmRPyy2LfH0TMd0LGQNmeRzg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@rosen-bridge/watcher-data-extractor/-/watcher-data-extractor-9.0.0.tgz", + "integrity": "sha512-OrQCtVxd4XaLEYAQZVVQbtf6Vy+U+rwEbbUbb3+AH/m0ekw9/oDVBgrRDgQq9kCkAMqybhpUgpp9OkILtCSZFA==", "dependencies": { - "@rosen-bridge/abstract-extractor": "^0.3.0", + "@rosen-bridge/abstract-extractor": "^0.3.1", "@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.3", + "@rosen-bridge/scanner": "^5.0.0", "@rosen-bridge/tokens": "^1.2.1", "@rosen-clients/ergo-explorer": "^1.1.1", "@types/lodash-es": "^4.17.6", @@ -2601,11 +2596,11 @@ } }, "node_modules/@rosen-bridge/wid-check": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rosen-bridge/wid-check/-/wid-check-1.0.3.tgz", - "integrity": "sha512-lJGxv1GEZ1PKWdxhFdisx031vviLceU9KF7dUO8ucj6GNls2CTHw91Qf7n6A2clbxvNYXf+JrzLX9za1IvKNYw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rosen-bridge/wid-check/-/wid-check-1.0.4.tgz", + "integrity": "sha512-6jcnuD3eBoFySZ/Ia50qhpWqsmyATaAPIEYEjpxzVqWA8qT+E2xl0dAGDzqF22GDD5BAKLZXC5rwT3rwXQMuSw==", "dependencies": { - "@rosen-bridge/health-check": "^6.0.3", + "@rosen-bridge/health-check": "^6.0.4", "@rosen-clients/ergo-explorer": "^1.1.1", "@rosen-clients/ergo-node": "^1.1.1", "ergo-lib-wasm-nodejs": "^0.24.1", @@ -3647,7 +3642,8 @@ }, "node_modules/base-x": { "version": "4.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -3699,7 +3695,8 @@ }, "node_modules/bip174": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz", + "integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==", "engines": { "node": ">=8.0.0" } @@ -3712,8 +3709,9 @@ } }, "node_modules/bitcoinjs-lib": { - "version": "6.1.6", - "license": "MIT", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.7.tgz", + "integrity": "sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg==", "dependencies": { "@noble/hashes": "^1.2.0", "bech32": "^2.0.0", @@ -3792,14 +3790,16 @@ }, "node_modules/bs58": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", "dependencies": { "base-x": "^4.0.0" } }, "node_modules/bs58check": { "version": "3.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", + "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", "dependencies": { "@noble/hashes": "^1.2.0", "bs58": "^5.0.0" @@ -4319,6 +4319,14 @@ "node": ">=4" } }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "engines": { + "node": ">=16" + } + }, "node_modules/color": { "version": "3.2.1", "license": "MIT", @@ -12337,7 +12345,8 @@ }, "node_modules/typeforce": { "version": "1.18.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" }, "node_modules/typeorm": { "version": "0.3.20", @@ -12741,7 +12750,8 @@ }, "node_modules/varuint-bitcoin": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", + "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", "dependencies": { "safe-buffer": "^5.1.1" } diff --git a/package.json b/package.json index de88edf..e1641a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rosen-bridge/watcher", - "version": "4.0.3", + "version": "4.1.0", "description": "Rosen bridge Watcher service", "main": "index.js", "type": "module", @@ -76,25 +76,26 @@ "dependencies": { "@emurgo/cip14-js": "^3.0.1", "@rosen-bridge/abstract-logger": "^2.0.1", - "@rosen-bridge/address-extractor": "^5.0.7", - "@rosen-bridge/asset-check": "^1.0.4", - "@rosen-bridge/bitcoin-esplora-scanner": "^0.1.14", - "@rosen-bridge/bitcoin-observation-extractor": "^4.0.7", - "@rosen-bridge/bitcoin-rpc-scanner": "^0.2.8", + "@rosen-bridge/address-extractor": "^5.0.8", + "@rosen-bridge/asset-check": "^2.0.0", + "@rosen-bridge/bitcoin-esplora-scanner": "^1.0.0", + "@rosen-bridge/bitcoin-observation-extractor": "^4.0.10", + "@rosen-bridge/bitcoin-rpc-scanner": "^1.0.0", "@rosen-bridge/discord-notification": "^0.1.3", - "@rosen-bridge/evm-observation-extractor": "^3.0.5", - "@rosen-bridge/evm-rpc-scanner": "^1.0.4", - "@rosen-bridge/health-check": "6.0.3", - "@rosen-bridge/log-level-check": "^1.0.3", + "@rosen-bridge/evm-observation-extractor": "3.1.2", + "@rosen-bridge/evm-rpc-scanner": "^2.0.0", + "@rosen-bridge/extended-typeorm": "^0.0.3", + "@rosen-bridge/health-check": "6.0.4", + "@rosen-bridge/log-level-check": "^1.0.4", "@rosen-bridge/minimum-fee": "^2.2.2", - "@rosen-bridge/node-sync-check": "^1.0.3", - "@rosen-bridge/observation-extractor": "^5.0.7", - "@rosen-bridge/permit-check": "^1.0.3", - "@rosen-bridge/scanner": "^4.1.3", - "@rosen-bridge/scanner-sync-check": "^1.0.3", + "@rosen-bridge/node-sync-check": "^1.0.4", + "@rosen-bridge/observation-extractor": "^5.0.10", + "@rosen-bridge/permit-check": "^1.0.4", + "@rosen-bridge/scanner": "^5.0.0", + "@rosen-bridge/scanner-sync-check": "^2.0.0", "@rosen-bridge/tokens": "^1.2.1", - "@rosen-bridge/watcher-data-extractor": "^8.0.2", - "@rosen-bridge/wid-check": "^1.0.3", + "@rosen-bridge/watcher-data-extractor": "^9.0.0", + "@rosen-bridge/wid-check": "^1.0.4", "@rosen-bridge/winston-logger": "1.0.2", "@rosen-clients/cardano-koios": "^2.0.3", "axios": "^0.26.1", diff --git a/src/config/config.ts b/src/config/config.ts index 008cb8f..7cda738 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -17,6 +17,7 @@ const supportedNetworks: Array = [ Constants.CARDANO_CHAIN_NAME, Constants.BITCOIN_CHAIN_NAME, Constants.ETHEREUM_CHAIN_NAME, + Constants.BINANCE_CHAIN_NAME, ]; interface ConfigType { @@ -24,6 +25,7 @@ interface ConfigType { cardano: CardanoConfig; bitcoin: BitcoinConfig; ethereum: EthereumConfig; + binance: BinanceConfig; general: Config; rosen: RosenConfig; token: TokensConfig; @@ -107,7 +109,6 @@ class Config { minimumFeeUpdateInterval: number; observationConfirmation: number; observationValidThreshold: number; - redeemSwapEnabled: boolean; rosenConfigPath: string; rosenTokensPath: string; apiPort: number; @@ -218,7 +219,6 @@ class Config { this.observationValidThreshold = getRequiredNumber( 'observation.validThreshold' ); - this.redeemSwapEnabled = config.get('redeemSwapEnabled'); this.tokenNameInterval = getRequiredNumber('ergo.interval.tokenName'); this.revenueInterval = getRequiredNumber('ergo.interval.revenue'); if (this.ergoInterval <= this.revenueInterval) { @@ -452,6 +452,35 @@ class EthereumConfig { } } +class BinanceConfig { + type: string; + initialHeight: number; + rpc?: { + url: string; + timeout: number; + interval: number; + authToken?: string; + }; + + constructor(network: string) { + this.type = config.get('binance.type'); + if (network === Constants.BINANCE_CHAIN_NAME) { + this.initialHeight = getRequiredNumber('binance.initial.height'); + if (this.type == Constants.EVM_RPC_TYPE) { + const url = getRequiredString('binance.rpc.url'); + const timeout = getRequiredNumber('binance.rpc.timeout'); + const interval = getRequiredNumber('binance.rpc.interval'); + const authToken = getOptionalString('binance.rpc.authToken', undefined); + this.rpc = { url, timeout, interval, authToken }; + } else { + throw new Error( + `Improperly configured. binance configuration type is invalid available choices are '${Constants.EVM_RPC_TYPE}'` + ); + } + } + } +} + class DatabaseConfig { type: string; path = ''; @@ -518,6 +547,8 @@ class HealthCheckConfig { bitcoinScannerCriticalDiff: number; ethereumScannerWarnDiff: number; ethereumScannerCriticalDiff: number; + binanceScannerWarnDiff: number; + binanceScannerCriticalDiff: number; ergoNodeMaxHeightDiff: number; ergoNodeMaxBlockTime: number; ergoNodeMinPeerCount: number; @@ -573,6 +604,12 @@ class HealthCheckConfig { this.ethereumScannerCriticalDiff = getRequiredNumber( 'healthCheck.ethereumScanner.criticalDifference' ); + this.binanceScannerWarnDiff = getRequiredNumber( + 'healthCheck.binanceScanner.warnDifference' + ); + this.binanceScannerCriticalDiff = getRequiredNumber( + 'healthCheck.binanceScanner.criticalDifference' + ); this.permitWarnCommitmentCount = getRequiredNumber( 'healthCheck.permit.warnCommitmentCount' ); @@ -599,6 +636,7 @@ const getConfig = (): ConfigType => { const cardano = new CardanoConfig(general.networkWatcher); const bitcoin = new BitcoinConfig(general.networkWatcher); const ethereum = new EthereumConfig(general.networkWatcher); + const binance = new BinanceConfig(general.networkWatcher); const rosen = new RosenConfig( general.networkWatcher, general.networkType, @@ -612,6 +650,7 @@ const getConfig = (): ConfigType => { cardano, bitcoin, ethereum, + binance, logger, general, rosen, diff --git a/src/config/constants.ts b/src/config/constants.ts index 31654f3..c3a552e 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -15,6 +15,7 @@ export const ERGO_CHAIN_NAME = 'ergo'; export const CARDANO_CHAIN_NAME = 'cardano'; export const BITCOIN_CHAIN_NAME = 'bitcoin'; export const ETHEREUM_CHAIN_NAME = 'ethereum'; +export const BINANCE_CHAIN_NAME = 'binance'; export const ERGO_NATIVE_ASSET = 'erg'; export const ERGO_DECIMALS = 9; export const DEFAULT_API_LIMIT = 20; diff --git a/src/ergo/transaction/queue.ts b/src/ergo/transaction/queue.ts index b1c67ac..b884bcf 100644 --- a/src/ergo/transaction/queue.ts +++ b/src/ergo/transaction/queue.ts @@ -207,9 +207,14 @@ export class Queue { try { await this.processTx(tx, currentHeight); } catch (e) { - logger.warn( - `An error occurred while processing tx [${tx.txId}] with type ${tx.type}: ${e.message} - ${e.stack}` - ); + if (e instanceof Error) + logger.warn( + `An error occurred while processing tx [${tx.txId}] with type ${tx.type}: ${e.message} - ${e.stack}` + ); + else + logger.warn( + `An unknown problem occurred while processing tx [${tx.txId}] with type ${tx.type}: ${e}` + ); } } logger.info('Transactions check job is done', { count: txs.length }); diff --git a/src/ergo/utils.ts b/src/ergo/utils.ts index 630ce20..4a6607c 100644 --- a/src/ergo/utils.ts +++ b/src/ergo/utils.ts @@ -335,9 +335,8 @@ export class ErgoUtils { const min = BigInt(configs[2]); const percentage = parseInt(configs[1]); const watcherCount = Number(R5.to_i64().to_str()); - const formula = - min + BigInt(Math.ceil((percentage * (watcherCount - 1)) / 100)); - return max < formula ? max : formula; + const formula = min + BigInt(Math.floor((percentage * watcherCount) / 100)); + return (max < formula ? max : formula) + 1n; }; /** diff --git a/src/jobs/commitmentRedeem.ts b/src/jobs/commitmentRedeem.ts index 16b42fd..0fe53c2 100644 --- a/src/jobs/commitmentRedeem.ts +++ b/src/jobs/commitmentRedeem.ts @@ -16,9 +16,6 @@ const redeemJob = async () => { await HealthCheckSingleton.getInstance().getErgoScannerSyncHealth(); if (scannerSyncStatus !== HealthStatusLevel.BROKEN) { await commitmentRedeemObj.job(); - if (getConfig().general.redeemSwapEnabled) { - await commitmentRedeemObj.deadlockJob(); - } } else { logger.info( 'Scanner is not synced with network, skipping commitment redeem job' diff --git a/src/jobs/initScanner.ts b/src/jobs/initScanner.ts index 364de3b..d10aa0d 100644 --- a/src/jobs/initScanner.ts +++ b/src/jobs/initScanner.ts @@ -11,6 +11,7 @@ const { cardano: cardanoConfig, bitcoin: bitcoinConfig, ethereum: ethereumConfig, + binance: binanceConfig, } = allConfig; const logger = DefaultLoggerFactory.getInstance().getLogger(import.meta.url); @@ -59,6 +60,12 @@ export const scannerInit = () => { scanner.observationScanner as EvmRpcScanner ).then(() => null); break; + case Constants.BINANCE_CHAIN_NAME: + scanningJob( + binanceConfig.rpc!.interval, + scanner.observationScanner as EvmRpcScanner + ).then(() => null); + break; case Constants.ERGO_CHAIN_NAME: break; default: diff --git a/src/transactions/commitmentRedeem.ts b/src/transactions/commitmentRedeem.ts index 8f1a9ab..8264180 100644 --- a/src/transactions/commitmentRedeem.ts +++ b/src/transactions/commitmentRedeem.ts @@ -9,7 +9,6 @@ import { TxType } from '../database/entities/txEntity'; import { TransactionUtils, WatcherUtils } from '../utils/watcherUtils'; import { getConfig } from '../config/config'; import { DefaultLoggerFactory } from '@rosen-bridge/abstract-logger'; -import { ERGO_CHAIN_NAME } from '../config/constants'; const logger = DefaultLoggerFactory.getInstance().getLogger(import.meta.url); @@ -184,81 +183,4 @@ export class CommitmentRedeem { count: commitments.length, }); }; - - /** - * Redeem the last unspent commitment if there is a missed uncommitted observation - */ - deadlockJob = async () => { - const activeTx = - await this.watcherUtils.dataBase.getActiveTransactionsByType([ - TxType.REDEEM, - TxType.COMMITMENT, - ]); - if (activeTx.length > 0) { - logger.debug('Has unconfirmed commitment or redeem transactions'); - return; - } - const tokenMap = getConfig().token.tokenMap; - const rwtPerCommitment = tokenMap.unwrapAmount( - getConfig().rosen.RWTId, - await Transaction.getInstance().getRequiredPermitsCountPerEvent(), - ERGO_CHAIN_NAME - ).amount; - const availablePermits = - ((await ErgoUtils.getPermitCount(getConfig().rosen.RWTId)) - 1n) / - rwtPerCommitment; - if (availablePermits >= 1) { - logger.debug( - `Still have [${availablePermits}] available permits, aborting last commit redeem job` - ); - return; - } - if (!Transaction.watcherWID) { - logger.warn('Watcher WID is not set. Cannot run commitment redeem job.'); - return; - } - try { - if (!(await this.watcherUtils.hasMissedObservation())) { - logger.debug('There is no missed observations'); - return; - } - const commitment = await this.watcherUtils.lastCommitment(); - logger.info(`Redeeming last commitment with boxId [${commitment.boxId}]`); - const WID = Transaction.watcherWID; - const WIDBox = (await this.boxes.getWIDBox(WID))[0]; - logger.info(`Using WID Box [${WIDBox.box_id().to_str()}]`); - const requiredValue = - BigInt(getConfig().general.fee) + - BigInt(getConfig().general.minBoxValue) * 2n; - const feeBoxes: wasm.ErgoBox[] = []; - const widBoxValue = BigInt(WIDBox.value().as_i64().to_str()); - if (widBoxValue < requiredValue) { - logger.debug( - `Require more than WID box Ergs. Total: [${widBoxValue}], Required: [${requiredValue}]` - ); - feeBoxes.push( - ...(await this.boxes.getUserPaymentBox(requiredValue, [ - WIDBox.box_id().to_str(), - ])) - ); - logger.debug( - `Using extra fee boxes in commitment redeem tx: [${feeBoxes.map( - (box) => box.box_id().to_str() - )}] with extra erg [${ErgoUtils.getBoxValuesSum(feeBoxes)}]` - ); - } - await this.redeemCommitmentTx( - WID, - WIDBox, - decodeSerializedBox(commitment.boxSerialized), - feeBoxes, - requiredValue - ); - } catch (e) { - logger.warn( - `Skipping the last commitment redeem due to occurred error: ${e.message} - ${e.stack}` - ); - } - logger.info(`Resolve deadlock job is done`); - }; } diff --git a/src/transactions/commitmentReveal.ts b/src/transactions/commitmentReveal.ts index 3408012..2c29cac 100644 --- a/src/transactions/commitmentReveal.ts +++ b/src/transactions/commitmentReveal.ts @@ -140,11 +140,9 @@ export class CommitmentReveal { repoConfigBox ); logger.info( - `Valid commitments: [${validCommitments.length}/${ - requiredCommitments + 1n - }]` + `Valid commitments: [${validCommitments.length}/${requiredCommitments}]` ); - if (BigInt(validCommitments.length) > requiredCommitments) { + if (BigInt(validCommitments.length) >= requiredCommitments) { const commitmentBoxes = await Promise.all( validCommitments.map(async (commitment) => { return await ErgoNetwork.unspentErgoBoxById(commitment.boxId); diff --git a/src/types/config.ts b/src/types/config.ts index b72dcef..3753fc4 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -4,6 +4,7 @@ type NetworkType = | typeof Constants.CARDANO_CHAIN_NAME | typeof Constants.ERGO_CHAIN_NAME | typeof Constants.BITCOIN_CHAIN_NAME - | typeof Constants.ETHEREUM_CHAIN_NAME; + | typeof Constants.ETHEREUM_CHAIN_NAME + | typeof Constants.BINANCE_CHAIN_NAME; export { NetworkType }; diff --git a/src/utils/healthCheck.ts b/src/utils/healthCheck.ts index 8c538ac..54f81e2 100644 --- a/src/utils/healthCheck.ts +++ b/src/utils/healthCheck.ts @@ -17,7 +17,7 @@ import { ErgoNodeScannerHealthCheck, BitcoinEsploraScannerHealthCheck, BitcoinRPCScannerHealthCheck, - EthereumRPCScannerHealthCheck, + EvmRPCScannerHealthCheck, } from '@rosen-bridge/scanner-sync-check'; import { ExplorerWidHealthCheckParam, @@ -30,6 +30,7 @@ import { DiscordNotification } from '@rosen-bridge/discord-notification'; import { Transaction } from '../api/Transaction'; import { getConfig } from '../config/config'; import { + BINANCE_CHAIN_NAME, BITCOIN_CHAIN_NAME, CARDANO_CHAIN_NAME, ERGO_DECIMALS, @@ -81,10 +82,6 @@ class HealthCheckSingleton { windowDuration: getConfig().notification.hasBeenUnknownForAWhileWindowDuration, }, - isStillUnhealthy: { - windowDuration: - getConfig().notification.isStillUnhealthyWindowDuration, - }, }, }; } @@ -112,6 +109,9 @@ class HealthCheckSingleton { if (getConfig().general.networkWatcher === ETHEREUM_CHAIN_NAME) { this.registerEthereumHealthCheckParams(); } + if (getConfig().general.networkWatcher === BINANCE_CHAIN_NAME) { + this.registerBinanceHealthCheckParams(); + } } private observingNetworkLastBlock = (scanner: string) => { @@ -249,7 +249,8 @@ class HealthCheckSingleton { * Registers all ethereum check params */ registerEthereumHealthCheckParams = () => { - const ethereumRpcScannerSyncCheck = new EthereumRPCScannerHealthCheck( + const ethereumRpcScannerSyncCheck = new EvmRPCScannerHealthCheck( + ETHEREUM_CHAIN_NAME, this.observingNetworkLastBlock(scanner.observationScanner.name()), scanner.observationScanner.name(), getConfig().healthCheck.ethereumScannerWarnDiff, @@ -261,6 +262,23 @@ class HealthCheckSingleton { this.healthCheck.register(ethereumRpcScannerSyncCheck); }; + /** + * Registers all binance check params + */ + registerBinanceHealthCheckParams = () => { + const binanceRpcScannerSyncCheck = new EvmRPCScannerHealthCheck( + BINANCE_CHAIN_NAME, + this.observingNetworkLastBlock(scanner.observationScanner.name()), + scanner.observationScanner.name(), + getConfig().healthCheck.binanceScannerWarnDiff, + getConfig().healthCheck.binanceScannerCriticalDiff, + getConfig().binance.rpc!.url, + getConfig().binance.rpc!.authToken, + getConfig().binance.rpc!.timeout + ); + this.healthCheck.register(binanceRpcScannerSyncCheck); + }; + /** * Registers permit check if watcher wid exists */ diff --git a/src/utils/scanner.ts b/src/utils/scanner.ts index 18058d5..3dea9cd 100644 --- a/src/utils/scanner.ts +++ b/src/utils/scanner.ts @@ -30,7 +30,10 @@ import { getConfig } from '../config/config'; import { dataSource } from '../../config/dataSource'; import * as Constants from '../config/constants'; import { EvmRpcScanner } from '@rosen-bridge/evm-rpc-scanner'; -import { EthereumRpcObservationExtractor } from '@rosen-bridge/evm-observation-extractor'; +import { + EthereumRpcObservationExtractor, + BinanceRpcObservationExtractor, +} from '@rosen-bridge/evm-observation-extractor'; const allConfig = getConfig(); const { @@ -40,6 +43,7 @@ const { cardano: cardanoConfig, bitcoin: bitcoinConfig, ethereum: ethereumConfig, + binance: binanceConfig, } = allConfig; /** @@ -92,6 +96,9 @@ class CreateScanner { case Constants.ETHEREUM_CHAIN_NAME: this.createEthereumScanner(); break; + case Constants.BINANCE_CHAIN_NAME: + this.createBinanceScanner(); + break; } if (!this.observationScanner) throw Error( @@ -154,6 +161,8 @@ class CreateScanner { const eventTriggerExtractor = new EventTriggerExtractor( Constants.TRIGGER_EXTRACTOR_NAME, dataSource, + config.scannerType, + networkUrl, rosenConfig.eventTriggerAddress, rosenConfig.RWTId, rosenConfig.watcherPermitAddress, @@ -196,8 +205,6 @@ class CreateScanner { dataSource: dataSource, initialHash: cardanoConfig.ogmios.initialHash, initialSlot: cardanoConfig.ogmios.initialSlot, - connectionRetrialInterval: - cardanoConfig.ogmios.connectionRetrialInterval * 1000, }, loggers.scannerLogger ); @@ -313,6 +320,32 @@ class CreateScanner { } } }; + + private createBinanceScanner = () => { + if (!this.observationScanner) { + if (binanceConfig.rpc) { + this.observationScanner = new EvmRpcScanner( + Constants.BINANCE_CHAIN_NAME, + { + RpcUrl: binanceConfig.rpc.url, + timeout: binanceConfig.rpc.timeout * 1000, + initialHeight: binanceConfig.initialHeight, + dataSource: dataSource, + }, + loggers.scannerLogger, + binanceConfig.rpc.authToken + ); + + const observationExtractor = new BinanceRpcObservationExtractor( + rosenConfig.lockAddress, + dataSource, + tokensConfig.tokens, + loggers.observationExtractorLogger + ); + this.observationScanner.registerExtractor(observationExtractor); + } + } + }; } const scanner = new CreateScanner();