diff --git a/package-lock.json b/package-lock.json index adec7e1ab..364480fe1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -86,6 +86,7 @@ "eslint": "^7.6.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", + "husky": "^8.0.1", "jasmine-core": "~3.5.0", "jasmine-spec-reporter": "~5.0.0", "karma": "^6.3.2", @@ -94,7 +95,8 @@ "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "ng-packagr": "^11.1.2", - "prettier": "^2.2.1", + "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "protractor": "~7.0.0", "ts-node": "~7.0.0", "typescript": "^4.0.7", @@ -3549,9 +3551,9 @@ } }, "node_modules/@ethersproject/abstract-provider": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz", - "integrity": "sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", "funding": [ { "type": "individual", @@ -3563,19 +3565,19 @@ } ], "dependencies": { - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/networks": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/transactions": "^5.4.0", - "@ethersproject/web": "^5.4.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" } }, "node_modules/@ethersproject/abstract-signer": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz", - "integrity": "sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", "funding": [ { "type": "individual", @@ -3587,17 +3589,17 @@ } ], "dependencies": { - "@ethersproject/abstract-provider": "^5.4.0", - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0" + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" } }, "node_modules/@ethersproject/address": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.4.0.tgz", - "integrity": "sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", "funding": [ { "type": "individual", @@ -3609,17 +3611,17 @@ } ], "dependencies": { - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/keccak256": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/rlp": "^5.4.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" } }, "node_modules/@ethersproject/base64": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.4.0.tgz", - "integrity": "sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", "funding": [ { "type": "individual", @@ -3631,13 +3633,13 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.4.0" + "@ethersproject/bytes": "^5.7.0" } }, "node_modules/@ethersproject/bignumber": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.4.2.tgz", - "integrity": "sha512-oIBDhsKy5bs7j36JlaTzFgNPaZjiNDOXsdSgSpXRucUl+UA6L/1YLlFeI3cPAoodcenzF4nxNPV13pcy7XbWjA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", "funding": [ { "type": "individual", @@ -3649,15 +3651,20 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "bn.js": "^4.11.9" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" } }, + "node_modules/@ethersproject/bignumber/node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, "node_modules/@ethersproject/bytes": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.4.0.tgz", - "integrity": "sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", "funding": [ { "type": "individual", @@ -3669,13 +3676,13 @@ } ], "dependencies": { - "@ethersproject/logger": "^5.4.0" + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/constants": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.4.0.tgz", - "integrity": "sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", "funding": [ { "type": "individual", @@ -3687,13 +3694,13 @@ } ], "dependencies": { - "@ethersproject/bignumber": "^5.4.0" + "@ethersproject/bignumber": "^5.7.0" } }, "node_modules/@ethersproject/hash": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.4.0.tgz", - "integrity": "sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", "funding": [ { "type": "individual", @@ -3705,20 +3712,21 @@ } ], "dependencies": { - "@ethersproject/abstract-signer": "^5.4.0", - "@ethersproject/address": "^5.4.0", - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/keccak256": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/strings": "^5.4.0" + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "node_modules/@ethersproject/keccak256": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.4.0.tgz", - "integrity": "sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", "funding": [ { "type": "individual", @@ -3730,14 +3738,19 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.4.0", - "js-sha3": "0.5.7" + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" } }, + "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "node_modules/@ethersproject/logger": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.4.1.tgz", - "integrity": "sha512-DZ+bRinnYLPw1yAC64oRl0QyVZj43QeHIhVKfD/+YwSz4wsv1pfwb5SOFjz+r710YEWzU6LrhuSjpSO+6PeE4A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", "funding": [ { "type": "individual", @@ -3750,9 +3763,9 @@ ] }, "node_modules/@ethersproject/networks": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.4.2.tgz", - "integrity": "sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.0.tgz", + "integrity": "sha512-MG6oHSQHd4ebvJrleEQQ4HhVu8Ichr0RDYEfHzsVAVjHNM+w36x9wp9r+hf1JstMXtseXDtkiVoARAG6M959AA==", "funding": [ { "type": "individual", @@ -3764,13 +3777,13 @@ } ], "dependencies": { - "@ethersproject/logger": "^5.4.0" + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/properties": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.4.1.tgz", - "integrity": "sha512-cyCGlF8wWlIZyizsj2PpbJ9I7rIlUAfnHYwy/T90pdkSn/NFTa5YWZx2wTJBe9V7dD65dcrrEMisCRUJiq6n3w==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", "funding": [ { "type": "individual", @@ -3782,13 +3795,13 @@ } ], "dependencies": { - "@ethersproject/logger": "^5.4.0" + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/rlp": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.4.0.tgz", - "integrity": "sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", "funding": [ { "type": "individual", @@ -3800,14 +3813,14 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/signing-key": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.4.0.tgz", - "integrity": "sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", "funding": [ { "type": "individual", @@ -3819,18 +3832,23 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "bn.js": "^4.11.9", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", "elliptic": "6.5.4", "hash.js": "1.1.7" } }, + "node_modules/@ethersproject/signing-key/node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, "node_modules/@ethersproject/strings": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.4.0.tgz", - "integrity": "sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", "funding": [ { "type": "individual", @@ -3842,15 +3860,15 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/constants": "^5.4.0", - "@ethersproject/logger": "^5.4.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/transactions": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.4.0.tgz", - "integrity": "sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", "funding": [ { "type": "individual", @@ -3862,21 +3880,21 @@ } ], "dependencies": { - "@ethersproject/address": "^5.4.0", - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/constants": "^5.4.0", - "@ethersproject/keccak256": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/rlp": "^5.4.0", - "@ethersproject/signing-key": "^5.4.0" + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" } }, "node_modules/@ethersproject/web": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.4.0.tgz", - "integrity": "sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.0.tgz", + "integrity": "sha512-ApHcbbj+muRASVDSCl/tgxaH2LBkRMEYfLOLVa0COipx0+nlu0QKet7U2lEg0vdkh8XRSLf2nd1f1Uk9SrVSGA==", "funding": [ { "type": "individual", @@ -3888,11 +3906,11 @@ } ], "dependencies": { - "@ethersproject/base64": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/strings": "^5.4.0" + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "node_modules/@istanbuljs/schema": { @@ -5881,6 +5899,15 @@ "node": ">=0.10.0" } }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -6935,9 +6962,9 @@ } }, "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-indexof": { "version": "1.1.1", @@ -12321,9 +12348,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", - "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "dev": true, "funding": [ { @@ -13293,6 +13320,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -13302,6 +13338,21 @@ "ms": "^2.0.0" } }, + "node_modules/husky": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", + "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -13345,9 +13396,23 @@ } }, "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/iferr": { "version": "0.1.5", @@ -16581,6 +16646,15 @@ "run-queue": "^1.0.3" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -16690,6 +16764,40 @@ "buffer": "^5.5.0" } }, + "node_modules/multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/multimatch/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/multimatch/node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -21678,15 +21786,18 @@ } }, "node_modules/prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/prettier-linter-helpers": { @@ -21770,6 +21881,263 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/pretty-quick": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", + "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", + "dev": true, + "dependencies": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "bin": { + "pretty-quick": "bin/pretty-quick.js" + }, + "engines": { + "node": ">=10.13" + }, + "peerDependencies": { + "prettier": ">=2.0.0" + } + }, + "node_modules/pretty-quick/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-quick/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/pretty-quick/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/pretty-quick/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/pretty-quick/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/pretty-quick/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-quick/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-quick/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/printj": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", @@ -24742,6 +25110,15 @@ "node": ">=0.10.0" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -25756,24 +26133,19 @@ } }, "node_modules/tus-js-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-2.3.0.tgz", - "integrity": "sha512-I4cSwm6N5qxqCmBqenvutwSHe9ntf81lLrtf6BmLpG2v4wTl89atCQKqGgqvkodE6Lx+iKIjMbaXmfvStTg01g==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-2.3.2.tgz", + "integrity": "sha512-5a2rm7gp+G7Z+ZB0AO4PzD/dwczB3n1fZeWO5W8AWLJ12RRk1rY4Aeb2VAYX9oKGE+/rGPrdxoFPA/vDSVKnpg==", "dependencies": { - "buffer-from": "^0.1.1", + "buffer-from": "^1.1.2", "combine-errors": "^3.0.3", "is-stream": "^2.0.0", "js-base64": "^2.6.1", "lodash.throttle": "^4.1.1", "proper-lockfile": "^2.0.1", - "url-parse": "^1.4.3" + "url-parse": "^1.5.7" } }, - "node_modules/tus-js-client/node_modules/buffer-from": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" - }, "node_modules/tus-js-client/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -26116,9 +26488,9 @@ } }, "node_modules/url-parse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", - "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -30573,180 +30945,202 @@ } }, "@ethersproject/abstract-provider": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz", - "integrity": "sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", "requires": { - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/networks": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/transactions": "^5.4.0", - "@ethersproject/web": "^5.4.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" } }, "@ethersproject/abstract-signer": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz", - "integrity": "sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", "requires": { - "@ethersproject/abstract-provider": "^5.4.0", - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0" + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" } }, "@ethersproject/address": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.4.0.tgz", - "integrity": "sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", "requires": { - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/keccak256": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/rlp": "^5.4.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" } }, "@ethersproject/base64": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.4.0.tgz", - "integrity": "sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", "requires": { - "@ethersproject/bytes": "^5.4.0" + "@ethersproject/bytes": "^5.7.0" } }, "@ethersproject/bignumber": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.4.2.tgz", - "integrity": "sha512-oIBDhsKy5bs7j36JlaTzFgNPaZjiNDOXsdSgSpXRucUl+UA6L/1YLlFeI3cPAoodcenzF4nxNPV13pcy7XbWjA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", "requires": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "bn.js": "^4.11.9" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + }, + "dependencies": { + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + } } }, "@ethersproject/bytes": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.4.0.tgz", - "integrity": "sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", "requires": { - "@ethersproject/logger": "^5.4.0" + "@ethersproject/logger": "^5.7.0" } }, "@ethersproject/constants": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.4.0.tgz", - "integrity": "sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", "requires": { - "@ethersproject/bignumber": "^5.4.0" + "@ethersproject/bignumber": "^5.7.0" } }, "@ethersproject/hash": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.4.0.tgz", - "integrity": "sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", "requires": { - "@ethersproject/abstract-signer": "^5.4.0", - "@ethersproject/address": "^5.4.0", - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/keccak256": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/strings": "^5.4.0" + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "@ethersproject/keccak256": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.4.0.tgz", - "integrity": "sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", "requires": { - "@ethersproject/bytes": "^5.4.0", - "js-sha3": "0.5.7" + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + }, + "dependencies": { + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + } } }, "@ethersproject/logger": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.4.1.tgz", - "integrity": "sha512-DZ+bRinnYLPw1yAC64oRl0QyVZj43QeHIhVKfD/+YwSz4wsv1pfwb5SOFjz+r710YEWzU6LrhuSjpSO+6PeE4A==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==" }, "@ethersproject/networks": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.4.2.tgz", - "integrity": "sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.0.tgz", + "integrity": "sha512-MG6oHSQHd4ebvJrleEQQ4HhVu8Ichr0RDYEfHzsVAVjHNM+w36x9wp9r+hf1JstMXtseXDtkiVoARAG6M959AA==", "requires": { - "@ethersproject/logger": "^5.4.0" + "@ethersproject/logger": "^5.7.0" } }, "@ethersproject/properties": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.4.1.tgz", - "integrity": "sha512-cyCGlF8wWlIZyizsj2PpbJ9I7rIlUAfnHYwy/T90pdkSn/NFTa5YWZx2wTJBe9V7dD65dcrrEMisCRUJiq6n3w==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", "requires": { - "@ethersproject/logger": "^5.4.0" + "@ethersproject/logger": "^5.7.0" } }, "@ethersproject/rlp": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.4.0.tgz", - "integrity": "sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", "requires": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" } }, "@ethersproject/signing-key": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.4.0.tgz", - "integrity": "sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", "requires": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "bn.js": "^4.11.9", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", "elliptic": "6.5.4", "hash.js": "1.1.7" + }, + "dependencies": { + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + } } }, "@ethersproject/strings": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.4.0.tgz", - "integrity": "sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", "requires": { - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/constants": "^5.4.0", - "@ethersproject/logger": "^5.4.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" } }, "@ethersproject/transactions": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.4.0.tgz", - "integrity": "sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", "requires": { - "@ethersproject/address": "^5.4.0", - "@ethersproject/bignumber": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/constants": "^5.4.0", - "@ethersproject/keccak256": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/rlp": "^5.4.0", - "@ethersproject/signing-key": "^5.4.0" + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" } }, "@ethersproject/web": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.4.0.tgz", - "integrity": "sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.0.tgz", + "integrity": "sha512-ApHcbbj+muRASVDSCl/tgxaH2LBkRMEYfLOLVa0COipx0+nlu0QKet7U2lEg0vdkh8XRSLf2nd1f1Uk9SrVSGA==", "requires": { - "@ethersproject/base64": "^5.4.0", - "@ethersproject/bytes": "^5.4.0", - "@ethersproject/logger": "^5.4.0", - "@ethersproject/properties": "^5.4.0", - "@ethersproject/strings": "^5.4.0" + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "@istanbuljs/schema": { @@ -32323,6 +32717,12 @@ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -33153,9 +33553,9 @@ } }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "buffer-indexof": { "version": "1.1.1", @@ -37380,9 +37780,9 @@ } }, "follow-redirects": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", - "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "dev": true }, "for-in": { @@ -38176,6 +38576,12 @@ } } }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, "humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -38185,6 +38591,12 @@ "ms": "^2.0.0" } }, + "husky": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", + "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -38216,9 +38628,9 @@ } }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "iferr": { "version": "0.1.5", @@ -40711,6 +41123,12 @@ "run-queue": "^1.0.3" } }, + "mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -40790,6 +41208,33 @@ } } }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + } + } + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -44667,9 +45112,9 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true }, "prettier-linter-helpers": { @@ -44731,6 +45176,187 @@ } } }, + "pretty-quick": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", + "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "printj": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", @@ -47072,6 +47698,12 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -47839,24 +48471,19 @@ } }, "tus-js-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-2.3.0.tgz", - "integrity": "sha512-I4cSwm6N5qxqCmBqenvutwSHe9ntf81lLrtf6BmLpG2v4wTl89atCQKqGgqvkodE6Lx+iKIjMbaXmfvStTg01g==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-2.3.2.tgz", + "integrity": "sha512-5a2rm7gp+G7Z+ZB0AO4PzD/dwczB3n1fZeWO5W8AWLJ12RRk1rY4Aeb2VAYX9oKGE+/rGPrdxoFPA/vDSVKnpg==", "requires": { - "buffer-from": "^0.1.1", + "buffer-from": "^1.1.2", "combine-errors": "^3.0.3", "is-stream": "^2.0.0", "js-base64": "^2.6.1", "lodash.throttle": "^4.1.1", "proper-lockfile": "^2.0.1", - "url-parse": "^1.4.3" + "url-parse": "^1.5.7" }, "dependencies": { - "buffer-from": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" - }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -48127,9 +48754,9 @@ } }, "url-parse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", - "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" diff --git a/package.json b/package.json index 7e2c46ad6..0c85ba409 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "eslint": "^7.6.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", + "husky": "^8.0.1", "jasmine-core": "~3.5.0", "jasmine-spec-reporter": "~5.0.0", "karma": "^6.3.2", @@ -109,13 +110,12 @@ "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "ng-packagr": "^11.1.2", + "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "protractor": "~7.0.0", "ts-node": "~7.0.0", "typescript": "^4.0.7", - "webpack-cli": "^3.3.10", - "husky": "^8.0.1", - "prettier": "^2.7.1", - "pretty-quick": "^3.1.3" + "webpack-cli": "^3.3.10" }, "main": "main.js" } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 80eaf0228..479cda32b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -172,6 +172,9 @@ import { BurnDaoCoinModalComponent } from './dao-coins/burn-dao-coin-modal/burn- import { ThemeModule } from './theme/theme.module'; import { Theme } from './theme/symbols'; import { PostMultiplierComponent } from './feed/feed-post-dropdown/post-multiplier/post-multiplier.component'; +import { + CreateMessagingGroupModalComponent +} from "./messages-page/create-messaging-group-modal/create-messaging-group-modal.component"; const lightTheme: Theme = { key: 'light', name: 'Light Theme' }; const darkTheme: Theme = { key: 'dark', name: 'Dark Theme' }; const icydarkTheme: Theme = { key: 'icydark', name: 'Icy Dark Theme' }; @@ -325,6 +328,7 @@ const greenishTheme: Theme = { key: 'greenish', name: 'Green Theme' }; DaoCoinsPageComponent, TransferDAOCoinModalComponent, BurnDaoCoinModalComponent, + CreateMessagingGroupModalComponent, ], imports: [ BrowserModule, diff --git a/src/app/backend-api.service.ts b/src/app/backend-api.service.ts index 62136da54..aff2a4068 100644 --- a/src/app/backend-api.service.ts +++ b/src/app/backend-api.service.ts @@ -3,14 +3,14 @@ // get the browser to save the cookie in the response. // https://github.com/github/fetch#sending-cookies import { Injectable } from '@angular/core'; -import { interval, Observable, of, throwError, zip } from 'rxjs'; +import { from, interval, Observable, of, throwError, zip } from 'rxjs'; import { - map, - switchMap, catchError, + concatMap, filter, + map, + switchMap, take, - concatMap, } from 'rxjs/operators'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { IdentityService } from './identity.service'; @@ -40,8 +40,11 @@ export class BackendRoutes { static RoutePathIsHodlingPublicKey = '/api/v0/is-hodling-public-key'; static RoutePathSendMessageStateless = '/api/v0/send-message-stateless'; static RoutePathGetMessagesStateless = '/api/v0/get-messages-stateless'; + static RoutePathGetMessagesStatelessV1 = '/api/v1/get-messages-stateless'; + static GetAllMessagingGroupKeys = '/api/v0/get-all-messaging-group-keys'; static RoutePathCheckPartyMessagingKeys = '/api/v0/check-party-messaging-keys'; + static RegisterGroupMessagingKey = '/api/v0/register-messaging-group-key'; static RoutePathMarkContactMessagesRead = '/api/v0/mark-contact-messages-read'; static RoutePathMarkAllMessagesRead = '/api/v0/mark-all-messages-read'; @@ -538,6 +541,72 @@ export enum TransferRestrictionStatusString { PERMANENTLY_UNRESTRICTED = 'permanently_unrestricted', } +export type MessagingGroupMember = { + GroupMemberPublicKeyBase58Check: string; + GroupMemberKeyName: string; + EncryptedKey: string; +}; + +export type MessagingGroupEntryResponse = { + GroupOwnerPublicKeyBase58Check: string; + MessagingPublicKeyBase58Check: string; + MessagingGroupKeyName: string; + MessagingGroupMembers: MessagingGroupMember[]; + EncryptedKey: string; + ExtraData: { [k: string]: string }; +}; + +export type GetAllMessagingGroupKeysResponse = { + MessagingGroupEntries: MessagingGroupEntryResponse[]; +}; + +export type MessagingGroupMemberResponse = { + // GroupMemberPublicKeyBase58Check is the main public key of the group member. + GroupMemberPublicKeyBase58Check: string; + + // GroupMemberKeyName is the key name of the member that we encrypt the group messaging public key to. The group + // messaging public key should not be confused with the GroupMemberPublicKeyBase58Check, the former is the public + // key of the whole group, while the latter is the public key of the group member. + GroupMemberKeyName: string; + + // EncryptedKey is the encrypted private key corresponding to the group messaging public key that's encrypted + // to the member's registered messaging key labeled with GroupMemberKeyName. + EncryptedKey: string; +}; + +export type MessageEntryResponse = { + SenderPublicKeyBase58Check: string; + RecipientPublicKeyBase58Check: string; + EncryptedText: string; + TstampNanos: number; + IsSender: boolean; + V2: boolean; // deprecated + Version: number; + SenderMessagingPublicKey: string; + SenderMessagingGroupKeyName: string; + RecipientMessagingPublicKey: string; + RecipientMessagingGroupKeyName: string; + ExtraData: { [k: string]: string }; + + // After Identity is done doing it's decryption, we have the below fields + DecryptedText: string | undefined; +}; + +export type MessageContactResponse = { + PublicKeyBase58Check: string; // NOTE: this is no good for v3 + Messages: MessageEntryResponse[]; + ProfileEntryResponse: ProfileEntryResponse; // NOTE: this is no good for v3 + NumMessagesRead: number; // NOTE: this isn't supported for v3 yet. + + MessagingGroup: MessagingGroupEntryResponse | undefined; +}; + +export type GetMessagesStatelessResponseV1 = { + PublicKeyToProfileEntry: { [k: string]: ProfileEntryResponse }; + OrderedContactsWithMessages: MessageContactResponse[]; + MessagingGroups: MessagingGroupEntryResponse[]; +}; + @Injectable({ providedIn: 'root', }) @@ -802,8 +871,14 @@ export class BackendApiService { FeeRateSatoshisPerKB: number, Broadcast: boolean ): Observable { + // Check if the user is logged in with a derived key and operating as the owner key. + const DerivedPublicKeyBase58Check = + this.identityService.identityServiceUsers[PublicKeyBase58Check] + ?.derivedPublicKeyBase58Check; + let req = this.post(endpoint, BackendRoutes.ExchangeBitcoinRoute, { PublicKeyBase58Check, + DerivedPublicKeyBase58Check, BurnAmountSatoshis, LatestBitcionAPIResponse, BTCDepositAddress, @@ -829,6 +904,7 @@ export class BackendApiService { switchMap((res) => this.post(endpoint, BackendRoutes.ExchangeBitcoinRoute, { PublicKeyBase58Check, + DerivedPublicKeyBase58Check, BurnAmountSatoshis, LatestBitcionAPIResponse, BTCDepositAddress, @@ -961,6 +1037,87 @@ export class BackendApiService { ); } + SendGroupMessage( + endpoint: string, + SenderPublicKeyBase58Check: string, + MessagingPublicKeyBase58Check: string, + SenderMessagingGroupKeyName: string, + MessagingGroupKeyName: string, + MessageText: string, + GroupOwnerPublicKeyBase58Check: string, + MinFeeRateNanosPerKB: number + ): Observable { + // Once we determine the messaging keys of the parties, we will then encrypt a message based on the keys. + const request = this.identityService + .encrypt({ + ...this.identityService.identityServiceParamsForKey( + SenderPublicKeyBase58Check + ), + recipientPublicKey: MessagingPublicKeyBase58Check, + senderGroupKeyName: SenderMessagingGroupKeyName, + message: MessageText, + }) + .pipe( + switchMap((encrypted) => { + // Now we will use the ciphertext encrypted to user's messaging keys as part of the metadata of the + // sendMessage transaction. + const EncryptedMessageText = encrypted.encryptedMessage; + // Determine whether to use V3 messaging group key names for sender or recipient. + return this.post( + endpoint, + BackendRoutes.RoutePathSendMessageStateless, + { + SenderPublicKeyBase58Check, + RecipientMessagingGroupKeyName: MessagingGroupKeyName, + EncryptedMessageText, + SenderMessagingGroupKeyName, + RecipientPublicKeyBase58Check: GroupOwnerPublicKeyBase58Check, + MinFeeRateNanosPerKB, + } + ).pipe( + map((request) => { + return { ...request }; + }) + ); + }) + ); + return this.signAndSubmitTransaction( + endpoint, + request, + SenderPublicKeyBase58Check + ); + } + + RegisterGroupMessagingKey( + endpoint: string, + OwnerPublicKeyBase58Check: string, + MessagingPublicKeyBase58Check: string, + MessagingGroupKeyName: string, + MessagingKeySignatureHex: string, + MessagingGroupMembers: MessagingGroupMemberResponse[], + ExtraData: { [k: string]: string }, + MinFeeRateNanosPerKB: number + ): Observable { + const request = this.post( + endpoint, + BackendRoutes.RegisterGroupMessagingKey, + { + OwnerPublicKeyBase58Check, + MessagingPublicKeyBase58Check, + MessagingGroupKeyName, + MessagingKeySignatureHex, + MessagingGroupMembers, + ExtraData, + MinFeeRateNanosPerKB, + } + ); + return this.signAndSubmitTransaction( + endpoint, + request, + OwnerPublicKeyBase58Check + ); + } + // User-related functions. GetUsersStateless( endpoint: string, @@ -1782,6 +1939,81 @@ export class BackendApiService { ); } + // TODO: add types + GetMessagesV1( + endpoint: string, + PublicKeyBase58Check: string + ): Observable { + let req = this.post( + endpoint, + BackendRoutes.RoutePathGetMessagesStatelessV1, + { PublicKeyBase58Check } + ); + + // create an array of messages to decrypt + req = req.pipe( + map((res: any) => { + // This array contains encrypted messages with public keys + // Public keys of the other party involved in the correspondence + const encryptedMessages = res.OrderedContactsWithMessages.flatMap( + (thread) => + thread.Messages.flatMap((message) => ({ + EncryptedHex: message.EncryptedText, + PublicKey: message.IsSender + ? message.RecipientPublicKeyBase58Check + : message.SenderPublicKeyBase58Check, + IsSender: message.IsSender, + Legacy: !message.V2 && (!message.Version || message.Version < 2), + Version: message.Version, + SenderMessagingPublicKey: message.SenderMessagingPublicKey, + SenderMessagingGroupKeyName: message.SenderMessagingGroupKeyName, + RecipientMessagingPublicKey: message.RecipientMessagingPublicKey, + RecipientMessagingGroupKeyName: + message.RecipientMessagingGroupKeyName, + })) + ); + return { ...res, encryptedMessages }; + }) + ); + + // decrypt all the messages + req = req.pipe( + switchMap((res) => { + // console.log(res.MessagingGroups); + return this.identityService + .decrypt({ + ...this.identityService.identityServiceParamsForKey( + PublicKeyBase58Check + ), + encryptedMessages: res.encryptedMessages, + messagingGroups: res.MessagingGroups, + }) + .pipe( + map((decrypted) => { + res.OrderedContactsWithMessages.forEach((threads) => { + threads.Messages.forEach( + (message) => + (message.DecryptedText = + decrypted.decryptedHexes[message.EncryptedText]) + ); + threads.MessagingGroup = res.MessagingGroups.find((mg) => { + return ( + mg.MessagingGroupKeyName === + threads.MessagingGroupKey.GroupKeyName && + mg.GroupOwnerPublicKeyBase58Check === + threads.MessagingGroupKey.GroupOwnerPublicKeyBase58Check + ); + }); + }); + return { ...res, ...decrypted }; + }) + ); + }) + ); + + return req.pipe(catchError(this._handleError)); + } + GetMessages( endpoint: string, PublicKeyBase58Check: string, @@ -1792,7 +2024,8 @@ export class BackendApiService { FollowersOnly: boolean = false, FollowingOnly: boolean = false, SortAlgorithm: string = 'time' - ): Observable { + ): Observable { + // return this.GetMessagesV1(endpoint, PublicKeyBase58Check); let req = this.httpClient.post( this._makeRequestURL( endpoint, @@ -1839,12 +2072,14 @@ export class BackendApiService { // decrypt all the messages req = req.pipe( switchMap((res) => { + // console.log(res.MessagingGroups); return this.identityService .decrypt({ ...this.identityService.identityServiceParamsForKey( PublicKeyBase58Check ), encryptedMessages: res.encryptedMessages, + messagingGroups: res.MessagingGroups, }) .pipe( map((decrypted) => { @@ -1864,6 +2099,31 @@ export class BackendApiService { return req.pipe(catchError(this._handleError)); } + GetAllMessagingGroupKeys( + endpoint: string, + OwnerPublicKeyBase58Check: string + ): Observable { + return this.post(endpoint, BackendRoutes.GetAllMessagingGroupKeys, { + OwnerPublicKeyBase58Check, + }); + } + + GetDefaultKey( + endpoint: string, + publicKeyBase58Check: string + ): Observable { + return this.GetAllMessagingGroupKeys(endpoint, publicKeyBase58Check).pipe( + map((res) => { + const defaultKeys = res.MessagingGroupEntries.filter( + (messagingGroup: MessagingGroupEntryResponse) => { + return messagingGroup.MessagingGroupKeyName === 'default-key'; + } + ); + return defaultKeys.length ? defaultKeys[0] : null; + }) + ); + } + CreateLike( endpoint: string, ReaderPublicKeyBase58Check: string, diff --git a/src/app/global-vars.service.ts b/src/app/global-vars.service.ts index 23abde980..312a6fa99 100755 --- a/src/app/global-vars.service.ts +++ b/src/app/global-vars.service.ts @@ -11,7 +11,7 @@ import { import { ActivatedRoute, Router } from '@angular/router'; import { RouteNames } from './app-routing.module'; import ConfettiGenerator from 'confetti-js'; -import { Observable, Observer } from 'rxjs'; +import { Observable, Observer, Subscription } from 'rxjs'; import { LoggedInUserObservableResult } from '../lib/observable-results/logged-in-user-observable-result'; import { FollowChangeObservableResult } from '../lib/observable-results/follow-change-observable-result'; import { SwalHelper } from '../lib/helpers/swal-helper'; @@ -150,7 +150,8 @@ export class GlobalVarsService { // and make everything use sockets. updateEverything: any; - emailRegExp = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/; + emailRegExp = + /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/; latestBitcoinAPIResponse: any; @@ -285,7 +286,7 @@ export class GlobalVarsService { } } - LoadInitialMessages() { + LoadInitialMessages(): Subscription { if (!this.loggedInUser) { return; } @@ -1086,10 +1087,8 @@ export class GlobalVarsService { ); bithuntService.getCommunityProjectsLeaderboard().subscribe((res) => { this.allCommunityProjectsLeaderboard = res; - this.topCommunityProjectsLeaderboard = this.allCommunityProjectsLeaderboard.slice( - 0, - 10 - ); + this.topCommunityProjectsLeaderboard = + this.allCommunityProjectsLeaderboard.slice(0, 10); }); } @@ -1205,8 +1204,7 @@ export class GlobalVarsService { Swal.fire({ target: this.getTargetComponentSelector(), title: 'Congrats!', - html: - "You just got some free money!

Now it's time to learn how to earn even more!", + html: "You just got some free money!

Now it's time to learn how to earn even more!", showConfirmButton: true, // Only show skip option to admins showCancelButton: !!this.loggedInUser?.IsAdmin, diff --git a/src/app/identity.service.ts b/src/app/identity.service.ts index 576b323b4..94da66103 100644 --- a/src/app/identity.service.ts +++ b/src/app/identity.service.ts @@ -2,7 +2,20 @@ import { Injectable } from '@angular/core'; import { Observable, Subject } from 'rxjs'; import { v4 as uuid } from 'uuid'; import { HttpParams } from '@angular/common/http'; -import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; +import { DomSanitizer } from '@angular/platform-browser'; + +export enum MessagingGroupOperation { + DEFAULT_KEY = 'DefaultKey', + CREATE_GROUP = 'CreateGroup', + ADD_MEMBERS = 'AddMembers', +} + +export type IdentityMessagingResponse = { + encryptedToApplicationGroupMessagingPrivateKey: string; + encryptedToMembersGroupMessagingPrivateKey: string[]; + messagingKeySignature: string; + messagingPublicKeyBase58Check: string; +}; @Injectable({ providedIn: 'root', @@ -50,6 +63,13 @@ export class IdentityService { public_key?: string; hideJumio?: boolean; accessLevelRequest?: number; + transactionSpendingLimitResponse?: any; + operation?: MessagingGroupOperation; + applicationMessagingPublicKeyBase58Check?: string; + updatedGroupOwnerPublicKeyBase58Check?: string; + updatedGroupKeyName?: string; + updatedMembersPublicKeysBase58Check?: string[]; + updatedMembersKeyNames?: string[]; } ): Observable { let url = this.identityServiceURL as string; @@ -89,6 +109,49 @@ export class IdentityService { ); } + if (params?.operation) { + httpParams = httpParams.append('operation', params.operation.toString()); + } + if (params?.applicationMessagingPublicKeyBase58Check) { + httpParams = httpParams.append( + 'applicationMessagingPublicKeyBase58Check', + params.applicationMessagingPublicKeyBase58Check + ); + } + if (params?.updatedGroupOwnerPublicKeyBase58Check) { + httpParams = httpParams.append( + 'updatedGroupOwnerPublicKeyBase58Check', + params.updatedGroupOwnerPublicKeyBase58Check + ); + } + if (params?.updatedGroupKeyName) { + httpParams = httpParams.append( + 'updatedGroupKeyName', + params.updatedGroupKeyName + ); + } + if (params?.updatedMembersPublicKeysBase58Check) { + httpParams = httpParams.append( + 'updatedMembersPublicKeysBase58Check', + params.updatedMembersPublicKeysBase58Check.join(',') + ); + } + if (params?.updatedMembersKeyNames) { + httpParams = httpParams.append( + 'updatedMembersKeyNames', + params.updatedMembersKeyNames.join(',') + ); + } + + if (params?.transactionSpendingLimitResponse) { + httpParams = httpParams.append( + 'transactionSpendingLimitResponse', + encodeURIComponent( + JSON.stringify(params.transactionSpendingLimitResponse) + ) + ); + } + const paramsStr = httpParams.toString(); if (paramsStr) { url += `?${paramsStr}`; @@ -110,6 +173,45 @@ export class IdentityService { return this.identityWindowSubject; } + launchDefaultMessagingKey( + publicKeyBase58Check: string + ): Observable { + return this.launch('/messaging-group', { + operation: MessagingGroupOperation.DEFAULT_KEY, + applicationMessagingPublicKeyBase58Check: publicKeyBase58Check, + updatedGroupKeyName: 'default-key', + updatedGroupOwnerPublicKeyBase58Check: publicKeyBase58Check, + }); + } + + launchCreateMessagingGroup( + publicKeyBase58Check: string, + groupKeyName: string + ): Observable { + return this.launch('/messaging-group', { + operation: MessagingGroupOperation.CREATE_GROUP, + applicationMessagingPublicKeyBase58Check: publicKeyBase58Check, + updatedGroupKeyName: groupKeyName, + updatedGroupOwnerPublicKeyBase58Check: publicKeyBase58Check, + }); + } + + launchAddMembersToMessagingGroup( + publicKeyBase58check: string, + groupKeyName: string, + updatedMembersPublicKeysBase58Check: string[], + updatedMembersKeyNames: string[] + ): Observable { + return this.launch('/messaging-group', { + operation: MessagingGroupOperation.ADD_MEMBERS, + updatedGroupKeyName: groupKeyName, + updatedGroupOwnerPublicKeyBase58Check: publicKeyBase58check, + updatedMembersPublicKeysBase58Check, + updatedMembersKeyNames, + applicationMessagingPublicKeyBase58Check: publicKeyBase58check, + }); + } + // Outgoing messages burn(payload: { @@ -155,6 +257,7 @@ export class IdentityService { accessLevelHmac: string; encryptedSeedHex: string; encryptedMessages: any; + messagingGroups?: any[]; // TODO: type me }): Observable { return this.send('decrypt', payload); } @@ -221,6 +324,15 @@ export class IdentityService { this.respond(this.identityWindow, id, {}); } + private handleMessagingGroup(payload: any) { + this.identityWindow.close(); + this.identityWindow = null; + + this.identityWindowSubject.next(payload); + this.identityWindowSubject.complete(); + this.identityWindowSubject = null; + } + // Message handling private handleMessage(event: MessageEvent) { @@ -252,6 +364,8 @@ export class IdentityService { this.handleLogin(payload); } else if (method === 'info') { this.handleInfo(id); + } else if (method === 'messagingGroup') { + this.handleMessagingGroup(payload); } else { console.error('Unhandled identity request'); console.error(event); diff --git a/src/app/messages-page/create-messaging-group-modal/create-messaging-group-modal.component.html b/src/app/messages-page/create-messaging-group-modal/create-messaging-group-modal.component.html new file mode 100644 index 000000000..8d0a0ed85 --- /dev/null +++ b/src/app/messages-page/create-messaging-group-modal/create-messaging-group-modal.component.html @@ -0,0 +1,24 @@ +
+ +
+ + +
+
+ {{ error }} +
+ +
+ +
+
diff --git a/src/app/messages-page/create-messaging-group-modal/create-messaging-group-modal.component.ts b/src/app/messages-page/create-messaging-group-modal/create-messaging-group-modal.component.ts new file mode 100644 index 000000000..96e84f95f --- /dev/null +++ b/src/app/messages-page/create-messaging-group-modal/create-messaging-group-modal.component.ts @@ -0,0 +1,145 @@ +import { Component, Input } from '@angular/core'; +import { + BackendApiService, + MessagingGroupMemberResponse, + ProfileEntryResponse, +} from '../../backend-api.service'; +import { GlobalVarsService } from '../../global-vars.service'; +import { BsModalRef } from 'ngx-bootstrap/modal'; +import { BsModalService } from 'ngx-bootstrap/modal'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { IdentityService } from '../../identity.service'; +import {zip} from "lodash"; + +@Component({ + selector: 'app-create-messaging-group-modal', + templateUrl: './create-messaging-group-modal.component.html', +}) +export class CreateMessagingGroupModalComponent { + messagingGroupMembers: { + MessagingGroupMember: MessagingGroupMemberResponse; + ProfileEntryResponse: ProfileEntryResponse; + }[] = []; + error: string; + groupName = ''; + + constructor( + private globalVars: GlobalVarsService, + private backendApi: BackendApiService, + private modalService: BsModalService, + private router: Router, + private identityService: IdentityService, + public bsModalRef: BsModalRef + ) {} + + _handleCreatorSelectedInSearch(creator: ProfileEntryResponse): void { + this.GetMessagingGroupMemberFromPublicKey( + creator.PublicKeyBase58Check + ).subscribe((messagingGroupMember) => { + if (!messagingGroupMember) { + this.error = `${ + creator.Username || creator.PublicKeyBase58Check + } does not have a default key registered and cannot be added to a group chat`; + return; + } + this.error = ''; + this.messagingGroupMembers.push({ + MessagingGroupMember: messagingGroupMember, + ProfileEntryResponse: creator, + }); + }); + } + + GetMessagingGroupMemberFromPublicKey( + publicKeyBase58Check: string + ): Observable { + return this.backendApi + .GetDefaultKey(this.globalVars.localNode, publicKeyBase58Check) + .pipe( + map((res) => { + return res === null + ? null + : { + GroupMemberPublicKeyBase58Check: publicKeyBase58Check, + GroupMemberKeyName: res.MessagingGroupKeyName, + EncryptedKey: res.EncryptedKey, + }; + }) + ); + } + + CreateGroup(): void { + let messagingPublicKeyBase58Check: string; + this.identityService + .launchCreateMessagingGroup( + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.groupName + ) + .subscribe((res) => { + messagingPublicKeyBase58Check = res.messagingPublicKeyBase58Check; + return this.backendApi + .RegisterGroupMessagingKey( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + messagingPublicKeyBase58Check, + this.groupName, + '', + [], + {}, + this.globalVars.feeRateDeSoPerKB * 1e9 + ) + .subscribe(() => { + this.identityService + .launchAddMembersToMessagingGroup( + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.groupName, + this.messagingGroupMembers.map( + (m) => m.MessagingGroupMember.GroupMemberPublicKeyBase58Check + ), + this.messagingGroupMembers.map( + (m) => m.MessagingGroupMember.GroupMemberKeyName + ) + ) + .subscribe((res) => { + this.backendApi + .RegisterGroupMessagingKey( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + messagingPublicKeyBase58Check, + this.groupName, + '', + this.messagingGroupMembers.map((m, ii) => { + return { + ...m.MessagingGroupMember, + ...{ + EncryptedKey: + res.encryptedToMembersGroupMessagingPrivateKey[ii], + }, + }; + }), + {}, + this.globalVars.feeRateDeSoPerKB * 1e9 + ) + .subscribe((res) => { + this.backendApi + .SendGroupMessage( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + messagingPublicKeyBase58Check, + 'default-key', + this.groupName, + 'my first group message', + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.globalVars.feeRateDeSoPerKB * 1e9 + ) + .subscribe((res) => { + console.log('message sent'); + }); + }); + }); + }); + }); + } +} diff --git a/src/app/messages-page/message/message.component.html b/src/app/messages-page/message/message.component.html index f17f0b84a..79b8dc285 100644 --- a/src/app/messages-page/message/message.component.html +++ b/src/app/messages-page/message/message.component.html @@ -39,14 +39,14 @@ style="white-space: pre-wrap; overflow-wrap: anywhere" >
@@ -56,7 +56,7 @@ class="d-flex justify-content-end align-items-end mt-5px" >
{{ @@ -72,13 +72,13 @@
@@ -94,7 +94,7 @@
{{ globalVars.convertTstampToDateOrTime(message.TstampNanos) }} diff --git a/src/app/messages-page/messages-inbox/messages-inbox.component.html b/src/app/messages-page/messages-inbox/messages-inbox.component.html index da380ffcb..9d4a48f91 100644 --- a/src/app/messages-page/messages-inbox/messages-inbox.component.html +++ b/src/app/messages-page/messages-inbox/messages-inbox.component.html @@ -40,7 +40,6 @@
@@ -52,6 +51,8 @@ class="pb-15px border-bottom border-color-grey" > + +
diff --git a/src/app/messages-page/messages-inbox/messages-inbox.component.ts b/src/app/messages-page/messages-inbox/messages-inbox.component.ts index 2e7593f97..461158f19 100644 --- a/src/app/messages-page/messages-inbox/messages-inbox.component.ts +++ b/src/app/messages-page/messages-inbox/messages-inbox.component.ts @@ -7,9 +7,22 @@ import { OnChanges, } from '@angular/core'; import { GlobalVarsService } from '../../global-vars.service'; -import { BackendApiService, User } from '../../backend-api.service'; +import { + BackendApiService, + MessageContactResponse, + MessagingGroupEntryResponse, + MessagingGroupMemberResponse, + User, +} from '../../backend-api.service'; import { ActivatedRoute, Router } from '@angular/router'; import * as _ from 'lodash'; +import { Observable, Subscription } from 'rxjs'; +import { map, take } from 'rxjs/operators'; +import { IdentityService } from '../../identity.service'; +import { SwalHelper } from '../../../lib/helpers/swal-helper'; +import { MintNftModalComponent } from '../../mint-nft-modal/mint-nft-modal.component'; +import { BsModalService } from 'ngx-bootstrap/modal'; +import { CreateMessagingGroupModalComponent } from '../create-messaging-group-modal/create-messaging-group-modal.component'; @Component({ selector: 'messages-inbox', @@ -30,7 +43,7 @@ export class MessagesInboxComponent implements OnInit, OnChanges { Custom: 'custom', }; - @Input() messageThreads: any; + @Input() messageThreads: MessageContactResponse[]; @Input() profileMap: any; @Input() isMobile = false; @Output() selectedThreadEmitter = new EventEmitter(); @@ -38,6 +51,7 @@ export class MessagesInboxComponent implements OnInit, OnChanges { fetchingMoreMessages: boolean = false; activeTab: string; startingSearchText: string; + defaultKey: MessagingGroupEntryResponse; // The contact to select by default, passed in via query param. Note: if the current user // doesn't have a conversation with the contact, these parameters do nothing. @@ -47,8 +61,10 @@ export class MessagesInboxComponent implements OnInit, OnChanges { constructor( private globalVars: GlobalVarsService, private backendApi: BackendApiService, + private identityService: IdentityService, private route: ActivatedRoute, - private router: Router + private router: Router, + private modalService: BsModalService ) { // Based on the route path set the tab and update filter/sort params this.route.queryParams.subscribe((params) => { @@ -64,8 +80,8 @@ export class MessagesInboxComponent implements OnInit, OnChanges { this.activeTab = 'My Holders'; } - // Handle the tab click if the stored messages are from a different tab - if (this.activeTab !== storedTab) { + // Handle the tab click + if (storedTab !== this.activeTab) { this._handleTabClick(this.activeTab); } if (params.username) { @@ -75,9 +91,61 @@ export class MessagesInboxComponent implements OnInit, OnChanges { } ngOnInit() { + this.globalVars.SetupMessages(); if (!this.isMobile) { this._setSelectedThreadBasedOnDefaultThread(); } + this.backendApi + .GetDefaultKey( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check + ) + .subscribe((res) => { + // + if (!res) { + SwalHelper.fire({ + html: 'In order to use the latest messaging features, we need you to create a default messaging key. DeSo Identity will now launch to generate this key for you.', + showCancelButton: false, + }).then(({ isConfirmed }) => { + if (isConfirmed) { + // Ask user to generate a default key + this.identityService + .launchDefaultMessagingKey( + this.globalVars.loggedInUser.PublicKeyBase58Check + ) + .subscribe((res) => { + if (res) { + this.backendApi + .RegisterGroupMessagingKey( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + res.messagingPublicKeyBase58Check, + 'default-key', + res.messagingKeySignature, + [], + {}, + this.globalVars.feeRateDeSoPerKB * 1e9 + ) + .subscribe((res) => { + if (res) { + this.backendApi + .GetDefaultKey( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check + ) + .subscribe((messagingGroupEntryResponse) => { + this.defaultKey = messagingGroupEntryResponse; + }); + } + }); + } + }); + } + }); + } else { + this.defaultKey = res; + } + }); } ngOnChanges(changes: any) { @@ -90,6 +158,24 @@ export class MessagesInboxComponent implements OnInit, OnChanges { } } + GetMessagingGroupMemberFromPublicKey( + publicKeyBase58Check: string + ): Observable { + return this.backendApi + .GetDefaultKey(this.globalVars.localNode, publicKeyBase58Check) + .pipe( + map((res) => { + return res === null + ? null + : { + GroupMemberPublicKeyBase58Check: publicKeyBase58Check, + GroupMemberKeyName: res.MessagingGroupKeyName, + EncryptedKey: res.EncryptedKey, + }; + }) + ); + } + showMoreButton() { return !( this.globalVars.newMessagesFromPage != null && @@ -102,7 +188,8 @@ export class MessagesInboxComponent implements OnInit, OnChanges { if (this.fetchingMoreMessages) { return; } - + // TODO: add support for loading more messages. + // return; this.fetchingMoreMessages = true; if (!this.globalVars.loggedInUser) { return; @@ -117,10 +204,10 @@ export class MessagesInboxComponent implements OnInit, OnChanges { let fetchAfterPubKey = ''; if (this.globalVars.messageResponse.OrderedContactsWithMessages) { - fetchAfterPubKey = this.globalVars.messageResponse - .OrderedContactsWithMessages[ - this.globalVars.messageResponse.OrderedContactsWithMessages.length - 1 - ].PublicKeyBase58Check; + fetchAfterPubKey = + this.globalVars.messageResponse.OrderedContactsWithMessages[ + this.globalVars.messageResponse.OrderedContactsWithMessages.length - 1 + ].PublicKeyBase58Check; } this.backendApi @@ -152,20 +239,21 @@ export class MessagesInboxComponent implements OnInit, OnChanges { JSON.stringify(res) ) { // Add the new contacts - this.globalVars.messageResponse.OrderedContactsWithMessages = this.globalVars.messageResponse.OrderedContactsWithMessages.concat( - res.OrderedContactsWithMessages - ); + this.globalVars.messageResponse.OrderedContactsWithMessages = + this.globalVars.messageResponse.OrderedContactsWithMessages.concat( + res.OrderedContactsWithMessages + ); // If they're a new contact, add their read/unread status mapping - for (let key in res.UnreadStateByContact) { - this.globalVars.messageResponse.UnreadStateByContact[key] = - res.UnreadStateByContact[key]; - } + // for (let key in res.UnreadStateByContact) { + // this.globalVars.messageResponse.UnreadStateByContact[key] = + // res.UnreadStateByContact[key]; + // } // Update the number of unread threads - this.globalVars.messageResponse.NumberOfUnreadThreads = - this.globalVars.messageResponse.NumberOfUnreadThreads + - res.NumberOfUnreadThreads; + // this.globalVars.messageResponse.NumberOfUnreadThreads = + // this.globalVars.messageResponse.NumberOfUnreadThreads + + // res.NumberOfUnreadThreads; // Update the number of new messages so we know when to stop scrolling this.globalVars.newMessagesFromPage = @@ -218,9 +306,10 @@ export class MessagesInboxComponent implements OnInit, OnChanges { // TODO: refactor silly setInterval let interval = setInterval(() => { // If we don't have the messageResponse yet, return - let orderedContactsWithMessages = this.globalVars.messageResponse - ?.OrderedContactsWithMessages; + let orderedContactsWithMessages = + this.globalVars.messageResponse?.OrderedContactsWithMessages; if (orderedContactsWithMessages == null) { + this.globalVars.LoadInitialMessages(); return; } @@ -243,7 +332,6 @@ export class MessagesInboxComponent implements OnInit, OnChanges { } else if (orderedContactsWithMessages.length > 0) { defaultThread = orderedContactsWithMessages[0]; } - if (!this.selectedThread) { this._handleMessagesThreadClick(defaultThread); } @@ -309,12 +397,14 @@ export class MessagesInboxComponent implements OnInit, OnChanges { return; } + // TODO: better support for new DMs // Add the creator to the inbox as a new thread. - let newThread = { + let newThread: MessageContactResponse = { PublicKeyBase58Check: creator.PublicKeyBase58Check, Messages: [], ProfileEntryResponse: creator, NumMessagesRead: 0, + MessagingGroup: undefined, }; // This gets appeneded to the front of the ordered contacts list in the message inbox. this.messageThreads.unshift(newThread); @@ -322,7 +412,7 @@ export class MessagesInboxComponent implements OnInit, OnChanges { this._handleMessagesThreadClick(newThread); } - _handleMessagesThreadClick(thread: any) { + _handleMessagesThreadClick(thread: MessageContactResponse) { this.selectedThread = thread; this.selectedThreadEmitter.emit(thread); this.updateReadMessagesForSelectedThread(); @@ -333,6 +423,8 @@ export class MessagesInboxComponent implements OnInit, OnChanges { if (!this.selectedThread) { return; } + // TODO: implement marking group threads as read + return; let contactPubKey = this.messageThreads[0]?.PublicKeyBase58Check; if (this.selectedThread && this.selectedThread.PublicKeyBase58Check) { @@ -341,12 +433,13 @@ export class MessagesInboxComponent implements OnInit, OnChanges { // We update the read message state on global vars before sending the request so it is more instant. if (this.globalVars.messageResponse.UnreadStateByContact[contactPubKey]) { - this.globalVars.messageResponse.UnreadStateByContact[ - contactPubKey - ] = false; + this.globalVars.messageResponse.UnreadStateByContact[contactPubKey] = + false; this.globalVars.messageResponse.NumberOfUnreadThreads -= 1; // Send an update back to the server noting that we read this thread. + + // TODO: this won't work anymore. this.backendApi .MarkContactMessagesRead( this.globalVars.localNode, @@ -368,4 +461,10 @@ export class MessagesInboxComponent implements OnInit, OnChanges { ); } } + + _openCreateGroupModal() { + this.modalService.show(CreateMessagingGroupModalComponent, { + class: 'modal-dialog-centered modal-lg', + }); + } } diff --git a/src/app/messages-page/messages-page.component.html b/src/app/messages-page/messages-page.component.html index 15b55658a..548a0eb24 100644 --- a/src/app/messages-page/messages-page.component.html +++ b/src/app/messages-page/messages-page.component.html @@ -24,6 +24,7 @@ : globalVars.messageResponse.OrderedContactsWithMessages[0] : null " + [pubKeyToProfileEntryResponses]="globalVars.messageResponse?.PublicKeyToProfileEntry" >
@@ -146,6 +147,7 @@ : globalVars.messageResponse.OrderedContactsWithMessages[0] : null " + [pubKeyToProfileEntryResponses]="globalVars.messageResponse?.PublicKeyToProfileEntry" >
diff --git a/src/app/messages-page/messages-thread-view/messages-thread-view.component.html b/src/app/messages-page/messages-thread-view/messages-thread-view.component.html index ef2d0951a..c751244dd 100644 --- a/src/app/messages-page/messages-thread-view/messages-thread-view.component.html +++ b/src/app/messages-page/messages-thread-view/messages-thread-view.component.html @@ -5,22 +5,26 @@ class="w-100 global__top-bar__height d-flex align-items-center pl-15px fs-15px font-weight-bold border-bottom border-color-grey" style="min-height: 80px" > - - - + {{ messageThread?.MessagingGroup?.MessagingGroupKeyName }} + + + + + + + queryParamsHandling="merge" + [avatar]="counterPartyPublicKey()" + > - - + + diff --git a/src/app/messages-page/messages-thread-view/messages-thread-view.component.ts b/src/app/messages-page/messages-thread-view/messages-thread-view.component.ts index 276f0a2b7..ec1b01c90 100644 --- a/src/app/messages-page/messages-thread-view/messages-thread-view.component.ts +++ b/src/app/messages-page/messages-thread-view/messages-thread-view.component.ts @@ -1,6 +1,10 @@ -import { Component, OnInit, Input, ViewChild } from '@angular/core'; +import { Component, Input, ViewChild } from '@angular/core'; import { GlobalVarsService } from '../../global-vars.service'; -import { BackendApiService } from '../../backend-api.service'; +import { + BackendApiService, + MessageContactResponse, + ProfileEntryResponse, +} from '../../backend-api.service'; import { AppRoutingModule } from '../../app-routing.module'; @Component({ @@ -9,8 +13,11 @@ import { AppRoutingModule } from '../../app-routing.module'; styleUrls: ['./messages-thread-view.component.scss'], }) export class MessagesThreadViewComponent { - @Input() messageThread: any; + @Input() messageThread: MessageContactResponse; @Input() isMobile = false; + @Input() pubKeyToProfileEntryResponses: { + [k: string]: ProfileEntryResponse; + } = {}; messageText = ''; sendMessageBeingCalled = false; AppRoutingModule = AppRoutingModule; @@ -27,12 +34,28 @@ export class MessagesThreadViewComponent { } } - counterpartyUsername() { - if (!this.messageThread || !this.messageThread.ProfileEntryResponse) { - return null; + getCounterPartyProfileEntryResponse(): ProfileEntryResponse | undefined { + // TODO: fix new DM case + const counterPartyPubKey = this.counterPartyPublicKey(); + return counterPartyPubKey + ? this.pubKeyToProfileEntryResponses[counterPartyPubKey] || + this.messageThread.ProfileEntryResponse + : undefined; + } + + counterPartyPublicKey(): string | undefined { + if (!this.messageThread?.Messages?.length) { + return this.messageThread?.PublicKeyBase58Check; } + const firstMessage = this.messageThread.Messages[0]; + return firstMessage.RecipientPublicKeyBase58Check === + this.globalVars.loggedInUser.PublicKeyBase58Check + ? firstMessage.SenderPublicKeyBase58Check + : firstMessage.RecipientPublicKeyBase58Check; + } - return this.messageThread.ProfileEntryResponse.Username; + counterpartyUsername(): string | undefined { + return this.getCounterPartyProfileEntryResponse()?.Username; } _scrollToMostRecentMessage() { @@ -81,8 +104,8 @@ export class MessagesThreadViewComponent { // Immediately add the message to the list to make it feel instant. const messageObj: any = { - SenderPublicKeyBase58Check: this.globalVars.loggedInUser - .PublicKeyBase58Check, + SenderPublicKeyBase58Check: + this.globalVars.loggedInUser.PublicKeyBase58Check, RecipientPublicKeyBase58Check: this.messageThread.PublicKeyBase58Check, DecryptedText: this.messageText, IsSender: true, @@ -108,18 +131,21 @@ export class MessagesThreadViewComponent { } // Move the threads around inside OrderedContactsWithMessages to put the current thread at the top. - let currentContact = this.globalVars.messageResponse - .OrderedContactsWithMessages[ii]; - let messagesBelow = this.globalVars.messageResponse.OrderedContactsWithMessages.slice( - ii + 1 - ); - let messagesAbove = this.globalVars.messageResponse.OrderedContactsWithMessages.slice( - 0, - ii - ); + let currentContact = + this.globalVars.messageResponse.OrderedContactsWithMessages[ii]; + let messagesBelow = + this.globalVars.messageResponse.OrderedContactsWithMessages.slice( + ii + 1 + ); + let messagesAbove = + this.globalVars.messageResponse.OrderedContactsWithMessages.slice( + 0, + ii + ); let newMessageList = messagesAbove.concat(messagesBelow); newMessageList.unshift(currentContact); - this.globalVars.messageResponse.OrderedContactsWithMessages = newMessageList; + this.globalVars.messageResponse.OrderedContactsWithMessages = + newMessageList; } } @@ -129,14 +155,25 @@ export class MessagesThreadViewComponent { const textToSend = this.messageText; this._resetMessageText(''); - this.backendApi - .SendMessage( - this.globalVars.localNode, - this.globalVars.loggedInUser.PublicKeyBase58Check, - this.messageThread.PublicKeyBase58Check, - textToSend, - this.globalVars.feeRateDeSoPerKB * 1e9 - ) + (this.messageThread.MessagingGroup + ? this.backendApi.SendGroupMessage( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.messageThread.MessagingGroup.MessagingPublicKeyBase58Check, + 'default-key', // TODO: support non-default key + this.messageThread.MessagingGroup.MessagingGroupKeyName, + textToSend, + this.messageThread.MessagingGroup.GroupOwnerPublicKeyBase58Check, + this.globalVars.feeRateDeSoPerKB * 1e9 + ) + : this.backendApi.SendMessage( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.counterPartyPublicKey(), + textToSend, + this.globalVars.feeRateDeSoPerKB * 1e9 + ) + ) .subscribe( (res: any) => { this.globalVars.logEvent('message : send'); diff --git a/src/app/messages-page/messages-thread/messages-thread.component.html b/src/app/messages-page/messages-thread/messages-thread.component.html index a81a6fff9..56e9b604b 100644 --- a/src/app/messages-page/messages-thread/messages-thread.component.html +++ b/src/app/messages-page/messages-thread/messages-thread.component.html @@ -7,94 +7,104 @@ 'background-color-grey': isHovered || isSelected, 'message-thread__unread-light-blue': !isHovered && - globalVars.messageResponse && - globalVars.messageResponse.UnreadStateByContact[ - thread.PublicKeyBase58Check - ] !== undefined && - globalVars.messageResponse.UnreadStateByContact[ - thread.PublicKeyBase58Check - ] === true - }" -> -
- -
-
-
-
- {{ - thread.ProfileEntryResponse && thread.ProfileEntryResponse.Username - ? thread.ProfileEntryResponse.Username - : thread.PublicKeyBase58Check - }} -
- + globalVars.messageResponse + }"> +
+
+ {{ thread.MessagingGroup?.MessagingGroupKeyName }} +
+
+ + + + + + + + + +
+ +
+
+
+
+ + {{ getMostRecentUserName() }} + + + + +
+ -
- {{ - globalVars.nanosToUSD( - globalVars._parseFloat( - thread.ProfileEntryResponse.CoinPriceDeSoNanos - ), - 2 - ) - }} -
-
-
- {{ - globalVars.convertTstampToDateOrTime( - thread.Messages[thread.Messages.length - 1].TstampNanos - ) - }} -
-
-
- -
- {{ - globalVars.messageMeta.decryptedMessgesMap[ - thread.Messages[thread.Messages.length - 1] - .SenderPublicKeyBase58Check + - '' + - thread.Messages[thread.Messages.length - 1].TstampNanos - ] - ? globalVars.messageMeta.decryptedMessgesMap[ - thread.Messages[thread.Messages.length - 1] - .SenderPublicKeyBase58Check + - '' + - thread.Messages[thread.Messages.length - 1].TstampNanos - ].DecryptedText - : thread.Messages[thread.Messages.length - 1].DecryptedText - }} -
- -
- {{ thread.Messages[thread.Messages.length - 1].DecryptedText }} -
-
+
+ {{ + globalVars.nanosToUSD( + globalVars._parseFloat( + getMostRecentProfileEntryResponse()?.CoinPriceDeSoNanos + ), + 2 + ) + }} +
+
+
+ {{ + globalVars.convertTstampToDateOrTime( + thread.Messages[thread.Messages.length - 1].TstampNanos + ) + }} +
+
+
+ +
+ {{ + globalVars.messageMeta.decryptedMessgesMap[ + thread.Messages[thread.Messages.length - 1] + .SenderPublicKeyBase58Check + + '' + + thread.Messages[thread.Messages.length - 1].TstampNanos + ] + ? globalVars.messageMeta.decryptedMessgesMap[ + thread.Messages[thread.Messages.length - 1] + .SenderPublicKeyBase58Check + + '' + + thread.Messages[thread.Messages.length - 1].TstampNanos + ].DecryptedText + : thread.Messages[thread.Messages.length - 1].DecryptedText + }} +
+ +
+ {{ thread.Messages[thread.Messages.length - 1].DecryptedText }} +
+
+
+
diff --git a/src/app/messages-page/messages-thread/messages-thread.component.ts b/src/app/messages-page/messages-thread/messages-thread.component.ts index 399139fa1..0dc91b1e0 100644 --- a/src/app/messages-page/messages-thread/messages-thread.component.ts +++ b/src/app/messages-page/messages-thread/messages-thread.component.ts @@ -1,5 +1,15 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { + Component, + OnInit, + Input, + OnChanges, + SimpleChanges, +} from '@angular/core'; import { GlobalVarsService } from '../../global-vars.service'; +import { + MessageContactResponse, + ProfileEntryResponse, +} from '../../backend-api.service'; @Component({ selector: 'messages-thread', @@ -7,9 +17,50 @@ import { GlobalVarsService } from '../../global-vars.service'; styleUrls: ['./messages-thread.component.scss'], }) export class MessagesThreadComponent { - @Input() thread: any; + @Input() thread: MessageContactResponse; @Input() isSelected: boolean; + @Input() pubKeyToProfileEntryResponses: { + [k: string]: ProfileEntryResponse; + } = {}; isHovered = false; + // TODO: Fix this component to work better for DMs. Currently this + // shows your own avatar and username for DMs. constructor(public globalVars: GlobalVarsService) {} + + getMostRecentMessage(): any { + return this.thread?.Messages[this.thread?.Messages?.length - 1]; + } + + getMostRecentPubKey(): string { + const mostRecentMessage = this.getMostRecentMessage(); + if (!mostRecentMessage) { + return this.thread?.PublicKeyBase58Check; + } + // If Messaging group, use messaging group key name. Ugh, + // Prob gonna be weird if messaging DMs with default key. + if (this.thread.MessagingGroup?.MessagingGroupKeyName) { + return mostRecentMessage.SenderPublicKeyBase58Check; + } + return mostRecentMessage.IsSender + ? mostRecentMessage.RecipientPublicKeyBase58Check + : mostRecentMessage.SenderPublicKeyBase58Check; + } + + getMostRecentProfileEntryResponse(): ProfileEntryResponse | undefined { + return ( + this.pubKeyToProfileEntryResponses[this.getMostRecentPubKey()] || + this.thread?.ProfileEntryResponse + ); + } + + getMostRecentUserName(): string { + const mostRecentPubKey = this.getMostRecentPubKey(); + const profileEntry = + this.pubKeyToProfileEntryResponses[mostRecentPubKey] || + this.thread?.ProfileEntryResponse; + return profileEntry + ? profileEntry.Username || profileEntry.PublicKeyBase58Check + : mostRecentPubKey; + } } diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index 28de73771..024d9998a 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -6,6 +6,7 @@ import { ThemeService } from '../theme/theme.service'; import { environment } from 'src/environments/environment'; import { SwalHelper } from '../../lib/helpers/swal-helper'; import { Router } from '@angular/router'; +import { IdentityService, MessagingGroupOperation } from '../identity.service'; @Component({ selector: 'settings', @@ -26,7 +27,8 @@ export class SettingsComponent implements OnInit { private backendApi: BackendApiService, private titleService: Title, public themeService: ThemeService, - private router: Router + private router: Router, + private identityService: IdentityService ) {} selectChangeHandler(event: any) { @@ -36,6 +38,14 @@ export class SettingsComponent implements OnInit { ngOnInit() { this._getUserMetadata(); + this.identityService.launch('/messaging-group', { + operation: MessagingGroupOperation.DEFAULT_KEY, + applicationMessagingPublicKeyBase58Check: + this.globalVars.loggedInUser.PublicKeyBase58Check, + updatedGroupKeyName: 'default-key', + updatedGroupOwnerPublicKeyBase58Check: + this.globalVars.loggedInUser.PublicKeyBase58Check, + }); this.titleService.setTitle(`Settings - ${environment.node.name}`); } diff --git a/src/environments/environment.ts b/src/environments/environment.ts index d029c8a72..c7a558328 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -4,10 +4,10 @@ export const environment = { production: false, - uploadImageHostname: 'node.deso.org', - verificationEndpointHostname: 'https://node.deso.org', - uploadVideoHostname: 'https://node.deso.org', - identityURL: 'https://identity.deso.org', + uploadImageHostname: 'test.deso.org', + verificationEndpointHostname: 'https://test.deso.org', + uploadVideoHostname: 'https://test.deso.org', + identityURL: 'http://localhost:4201', supportEmail: '', dd: { apiKey: 'DCEB26AC8BF47F1D7B4D87440EDCA6',